1# Python bindings for Yasm: Pyrex input file for intnum.h 2# 3# Copyright (C) 2006 Michael Urman, Peter Johnson 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' 15# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE 18# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24# POSSIBILITY OF SUCH DAMAGE. 25 26cdef class IntNum 27 28cdef object __intnum_op_ex(object x, yasm_expr_op op, object y): 29 value = __intnum_op(x, op, y) 30 __error_check() 31 return value 32 33cdef object __intnum_op(object x, yasm_expr_op op, object y): 34 if isinstance(x, IntNum): 35 result = IntNum(x) 36 if y is None: 37 yasm_intnum_calc((<IntNum>result).intn, op, NULL) 38 else: 39 # Coerce to intnum if not already 40 if isinstance(y, IntNum): 41 rhs = y 42 else: 43 rhs = IntNum(y) 44 yasm_intnum_calc((<IntNum>result).intn, op, (<IntNum>rhs).intn) 45 return result 46 elif isinstance(y, IntNum): 47 # Reversed operation - x OP y still, just y is intnum, x isn't. 48 result = IntNum(x) 49 yasm_intnum_calc((<IntNum>result).intn, op, (<IntNum>y).intn) 50 return result 51 else: 52 raise NotImplementedError 53 54cdef object __make_intnum(yasm_intnum *intn): 55 return IntNum(__pass_voidp(intn, IntNum)) 56 57cdef class IntNum: 58 cdef yasm_intnum *intn 59 60 def __cinit__(self, value, base=None): 61 cdef unsigned char buf[16] 62 63 self.intn = NULL 64 65 if isinstance(value, IntNum): 66 self.intn = yasm_intnum_copy((<IntNum>value).intn) 67 return 68 if PyCObject_Check(value): 69 self.intn = <yasm_intnum *>__get_voidp(value, IntNum) 70 return 71 72 if isinstance(value, str): 73 if base == 2: 74 self.intn = yasm_intnum_create_bin(value) 75 elif base == 8: 76 self.intn = yasm_intnum_create_oct(value) 77 elif base == 10 or base is None: 78 self.intn = yasm_intnum_create_dec(value) 79 elif base == 16: 80 self.intn = yasm_intnum_create_hex(value) 81 elif base == "nasm": 82 self.intn = yasm_intnum_create_charconst_nasm(value) 83 else: 84 raise ValueError("base must be 2, 8, 10, 16, or \"nasm\"") 85 elif isinstance(value, (int, long)): 86 _PyLong_AsByteArray(long(value), buf, 16, 1, 1) 87 self.intn = yasm_intnum_create_sized(buf, 1, 16, 0) 88 else: 89 raise ValueError 90 91 def __dealloc__(self): 92 if self.intn != NULL: yasm_intnum_destroy(self.intn) 93 94 def __long__(self): 95 cdef unsigned char buf[16] 96 yasm_intnum_get_sized(self.intn, buf, 16, 128, 0, 0, 0) 97 return _PyLong_FromByteArray(buf, 16, 1, 1) 98 99 def __repr__(self): 100 return "IntNum(%d)" % self 101 102 def __int__(self): return int(self.__long__()) 103 def __complex__(self): return complex(self.__long__()) 104 def __float__(self): return float(self.__long__()) 105 106 def __oct__(self): return oct(int(self.__long__())) 107 def __hex__(self): return hex(int(self.__long__())) 108 109 def __add__(x, y): return __intnum_op(x, YASM_EXPR_ADD, y) 110 def __sub__(x, y): return __intnum_op(x, YASM_EXPR_SUB, y) 111 def __mul__(x, y): return __intnum_op(x, YASM_EXPR_MUL, y) 112 def __div__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNDIV, y) 113 def __floordiv__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNDIV, y) 114 def __mod__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNMOD, y) 115 def __neg__(self): return __intnum_op(self, YASM_EXPR_NEG, None) 116 def __pos__(self): return self 117 def __abs__(self): 118 if yasm_intnum_sign(self.intn) >= 0: return IntNum(self) 119 else: return __intnum_op(self, YASM_EXPR_NEG, None) 120 def __nonzero__(self): return not yasm_intnum_is_zero(self.intn) 121 def __invert__(self): return __intnum_op(self, YASM_EXPR_NOT, None) 122 def __lshift__(x, y): return __intnum_op(x, YASM_EXPR_SHL, y) 123 def __rshift__(x, y): return __intnum_op(x, YASM_EXPR_SHR, y) 124 def __and__(x, y): return __intnum_op(x, YASM_EXPR_AND, y) 125 def __or__(x, y): return __intnum_op(x, YASM_EXPR_OR, y) 126 def __xor__(x, y): return __intnum_op(x, YASM_EXPR_XOR, y) 127 128 cdef object __op(self, yasm_expr_op op, object x): 129 if isinstance(x, IntNum): 130 rhs = x 131 else: 132 rhs = IntNum(x) 133 yasm_intnum_calc(self.intn, op, (<IntNum>rhs).intn) 134 return self 135 136 def __iadd__(self, x): return self.__op(YASM_EXPR_ADD, x) 137 def __isub__(self, x): return self.__op(YASM_EXPR_SUB, x) 138 def __imul__(self, x): return self.__op(YASM_EXPR_MUL, x) 139 def __idiv__(self, x): return self.__op(YASM_EXPR_SIGNDIV, x) 140 def __ifloordiv__(self, x): return self.__op(YASM_EXPR_SIGNDIV, x) 141 def __imod__(self, x): return self.__op(YASM_EXPR_MOD, x) 142 def __ilshift__(self, x): return self.__op(YASM_EXPR_SHL, x) 143 def __irshift__(self, x): return self.__op(YASM_EXPR_SHR, x) 144 def __iand__(self, x): return self.__op(YASM_EXPR_AND, x) 145 def __ior__(self, x): return self.__op(YASM_EXPR_OR, x) 146 def __ixor__(self, x): return self.__op(YASM_EXPR_XOR, x) 147 148 def __cmp__(self, x): 149 cdef yasm_intnum *t 150 t = yasm_intnum_copy(self.intn) 151 if isinstance(x, IntNum): 152 rhs = x 153 else: 154 rhs = IntNum(x) 155 yasm_intnum_calc(t, YASM_EXPR_SUB, (<IntNum>rhs).intn) 156 result = yasm_intnum_sign(t) 157 yasm_intnum_destroy(t) 158 return result 159 160 def __richcmp__(x, y, op): 161 cdef yasm_expr_op aop 162 if op == 0: aop = YASM_EXPR_LT 163 elif op == 1: aop = YASM_EXPR_LE 164 elif op == 2: aop = YASM_EXPR_EQ 165 elif op == 3: aop = YASM_EXPR_NE 166 elif op == 4: aop = YASM_EXPR_GT 167 elif op == 5: aop = YASM_EXPR_GE 168 else: raise NotImplementedError 169 v = __intnum_op(x, aop, y) 170 return bool(not yasm_intnum_is_zero((<IntNum>v).intn)) 171