171 lines
6.8 KiB
Cython
171 lines
6.8 KiB
Cython
# 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 __new__(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 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))
|