diff options
Diffstat (limited to 'tools/python-yasm/intnum.pxi')
-rw-r--r-- | tools/python-yasm/intnum.pxi | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/tools/python-yasm/intnum.pxi b/tools/python-yasm/intnum.pxi new file mode 100644 index 0000000..320ca1b --- /dev/null +++ b/tools/python-yasm/intnum.pxi @@ -0,0 +1,170 @@ +# Python bindings for Yasm: Pyrex input file for intnum.h +# +# Copyright (C) 2006 Michael Urman, Peter Johnson +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +cdef class IntNum + +cdef object __intnum_op_ex(object x, yasm_expr_op op, object y): + value = __intnum_op(x, op, y) + __error_check() + return value + +cdef object __intnum_op(object x, yasm_expr_op op, object y): + if isinstance(x, IntNum): + result = IntNum(x) + if y is None: + yasm_intnum_calc((<IntNum>result).intn, op, NULL) + else: + # Coerce to intnum if not already + if isinstance(y, IntNum): + rhs = y + else: + rhs = IntNum(y) + yasm_intnum_calc((<IntNum>result).intn, op, (<IntNum>rhs).intn) + return result + elif isinstance(y, IntNum): + # Reversed operation - x OP y still, just y is intnum, x isn't. + result = IntNum(x) + yasm_intnum_calc((<IntNum>result).intn, op, (<IntNum>y).intn) + return result + else: + raise NotImplementedError + +cdef object __make_intnum(yasm_intnum *intn): + return IntNum(__pass_voidp(intn, IntNum)) + +cdef class IntNum: + cdef yasm_intnum *intn + + def __cinit__(self, value, base=None): + cdef unsigned char buf[16] + + self.intn = NULL + + if isinstance(value, IntNum): + self.intn = yasm_intnum_copy((<IntNum>value).intn) + return + if PyCObject_Check(value): + self.intn = <yasm_intnum *>__get_voidp(value, IntNum) + return + + if isinstance(value, str): + if base == 2: + self.intn = yasm_intnum_create_bin(value) + elif base == 8: + self.intn = yasm_intnum_create_oct(value) + elif base == 10 or base is None: + self.intn = yasm_intnum_create_dec(value) + elif base == 16: + self.intn = yasm_intnum_create_hex(value) + elif base == "nasm": + self.intn = yasm_intnum_create_charconst_nasm(value) + else: + raise ValueError("base must be 2, 8, 10, 16, or \"nasm\"") + elif isinstance(value, (int, long)): + _PyLong_AsByteArray(long(value), buf, 16, 1, 1) + self.intn = yasm_intnum_create_sized(buf, 1, 16, 0) + else: + raise ValueError + + def __dealloc__(self): + if self.intn != NULL: yasm_intnum_destroy(self.intn) + + def __long__(self): + cdef unsigned char buf[16] + yasm_intnum_get_sized(self.intn, buf, 16, 128, 0, 0, 0) + return _PyLong_FromByteArray(buf, 16, 1, 1) + + def __repr__(self): + return "IntNum(%d)" % self + + def __int__(self): return int(self.__long__()) + def __complex__(self): return complex(self.__long__()) + def __float__(self): return float(self.__long__()) + + def __oct__(self): return oct(int(self.__long__())) + def __hex__(self): return hex(int(self.__long__())) + + def __add__(x, y): return __intnum_op(x, YASM_EXPR_ADD, y) + def __sub__(x, y): return __intnum_op(x, YASM_EXPR_SUB, y) + def __mul__(x, y): return __intnum_op(x, YASM_EXPR_MUL, y) + def __div__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNDIV, y) + def __floordiv__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNDIV, y) + def __mod__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNMOD, y) + def __neg__(self): return __intnum_op(self, YASM_EXPR_NEG, None) + def __pos__(self): return self + def __abs__(self): + if yasm_intnum_sign(self.intn) >= 0: return IntNum(self) + else: return __intnum_op(self, YASM_EXPR_NEG, None) + def __nonzero__(self): return not yasm_intnum_is_zero(self.intn) + def __invert__(self): return __intnum_op(self, YASM_EXPR_NOT, None) + def __lshift__(x, y): return __intnum_op(x, YASM_EXPR_SHL, y) + def __rshift__(x, y): return __intnum_op(x, YASM_EXPR_SHR, y) + def __and__(x, y): return __intnum_op(x, YASM_EXPR_AND, y) + def __or__(x, y): return __intnum_op(x, YASM_EXPR_OR, y) + def __xor__(x, y): return __intnum_op(x, YASM_EXPR_XOR, y) + + cdef object __op(self, yasm_expr_op op, object x): + if isinstance(x, IntNum): + rhs = x + else: + rhs = IntNum(x) + yasm_intnum_calc(self.intn, op, (<IntNum>rhs).intn) + return self + + def __iadd__(self, x): return self.__op(YASM_EXPR_ADD, x) + def __isub__(self, x): return self.__op(YASM_EXPR_SUB, x) + def __imul__(self, x): return self.__op(YASM_EXPR_MUL, x) + def __idiv__(self, x): return self.__op(YASM_EXPR_SIGNDIV, x) + def __ifloordiv__(self, x): return self.__op(YASM_EXPR_SIGNDIV, x) + def __imod__(self, x): return self.__op(YASM_EXPR_MOD, x) + def __ilshift__(self, x): return self.__op(YASM_EXPR_SHL, x) + def __irshift__(self, x): return self.__op(YASM_EXPR_SHR, x) + def __iand__(self, x): return self.__op(YASM_EXPR_AND, x) + def __ior__(self, x): return self.__op(YASM_EXPR_OR, x) + def __ixor__(self, x): return self.__op(YASM_EXPR_XOR, x) + + def __cmp__(self, x): + cdef yasm_intnum *t + t = yasm_intnum_copy(self.intn) + if isinstance(x, IntNum): + rhs = x + else: + rhs = IntNum(x) + yasm_intnum_calc(t, YASM_EXPR_SUB, (<IntNum>rhs).intn) + result = yasm_intnum_sign(t) + yasm_intnum_destroy(t) + return result + + def __richcmp__(x, y, op): + cdef yasm_expr_op aop + if op == 0: aop = YASM_EXPR_LT + elif op == 1: aop = YASM_EXPR_LE + elif op == 2: aop = YASM_EXPR_EQ + elif op == 3: aop = YASM_EXPR_NE + elif op == 4: aop = YASM_EXPR_GT + elif op == 5: aop = YASM_EXPR_GE + else: raise NotImplementedError + v = __intnum_op(x, aop, y) + return bool(not yasm_intnum_is_zero((<IntNum>v).intn)) |