# 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((result).intn, op, NULL) else: # Coerce to intnum if not already if isinstance(y, IntNum): rhs = y else: rhs = IntNum(y) yasm_intnum_calc((result).intn, op, (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((result).intn, op, (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((value).intn) return if PyCObject_Check(value): self.intn = __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, (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, (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((v).intn))