145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# Python bindings for Yasm: Pyrex input file for intnum.h
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#  Copyright (C) 2006  Michael Urman, Peter Johnson
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# Redistribution and use in source and binary forms, with or without
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# modification, are permitted provided that the following conditions
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# are met:
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# 1. Redistributions of source code must retain the above copyright
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#    notice, this list of conditions and the following disclaimer.
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# 2. Redistributions in binary form must reproduce the above copyright
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#    notice, this list of conditions and the following disclaimer in the
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#    documentation and/or other materials provided with the distribution.
1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#
1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# POSSIBILITY OF SUCH DAMAGE.
2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcdef class IntNum
2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcdef object __intnum_op_ex(object x, yasm_expr_op op, object y):
2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    value = __intnum_op(x, op, y)
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    __error_check()
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return value
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcdef object __intnum_op(object x, yasm_expr_op op, object y):
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    if isinstance(x, IntNum):
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        result = IntNum(x)
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if y is None:
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_calc((<IntNum>result).intn, op, NULL)
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            # Coerce to intnum if not already
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if isinstance(y, IntNum):
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                rhs = y
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else:
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                rhs = IntNum(y)
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            yasm_intnum_calc((<IntNum>result).intn, op, (<IntNum>rhs).intn)
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return result
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    elif isinstance(y, IntNum):
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        # Reversed operation - x OP y still, just y is intnum, x isn't.
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        result = IntNum(x)
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc((<IntNum>result).intn, op, (<IntNum>y).intn)
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return result
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    else:
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        raise NotImplementedError
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcdef object __make_intnum(yasm_intnum *intn):
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return IntNum(__pass_voidp(intn, IntNum))
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgcdef class IntNum:
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    cdef yasm_intnum *intn
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
60a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org    def __cinit__(self, value, base=None):
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        cdef unsigned char buf[16]
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self.intn = NULL
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if isinstance(value, IntNum):
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            self.intn = yasm_intnum_copy((<IntNum>value).intn)
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if PyCObject_Check(value):
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            self.intn = <yasm_intnum *>__get_voidp(value, IntNum)
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if isinstance(value, str):
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if base == 2:
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                self.intn = yasm_intnum_create_bin(value)
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elif base == 8:
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                self.intn = yasm_intnum_create_oct(value)
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elif base == 10 or base is None:
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                self.intn = yasm_intnum_create_dec(value)
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elif base == 16:
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                self.intn = yasm_intnum_create_hex(value)
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elif base == "nasm":
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                self.intn = yasm_intnum_create_charconst_nasm(value)
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else:
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                raise ValueError("base must be 2, 8, 10, 16, or \"nasm\"")
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elif isinstance(value, (int, long)):
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            _PyLong_AsByteArray(long(value), buf, 16, 1, 1)
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            self.intn = yasm_intnum_create_sized(buf, 1, 16, 0)
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            raise ValueError
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __dealloc__(self):
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.intn != NULL: yasm_intnum_destroy(self.intn)
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __long__(self):
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        cdef unsigned char buf[16]
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_get_sized(self.intn, buf, 16, 128, 0, 0, 0)
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return _PyLong_FromByteArray(buf, 16, 1, 1)
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __repr__(self):
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return "IntNum(%d)" % self
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __int__(self): return int(self.__long__())
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __complex__(self): return complex(self.__long__())
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __float__(self): return float(self.__long__())
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __oct__(self): return oct(int(self.__long__()))
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __hex__(self): return hex(int(self.__long__()))
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __add__(x, y): return __intnum_op(x, YASM_EXPR_ADD, y)
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __sub__(x, y): return __intnum_op(x, YASM_EXPR_SUB, y)
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __mul__(x, y): return __intnum_op(x, YASM_EXPR_MUL, y)
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __div__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNDIV, y)
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __floordiv__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNDIV, y)
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __mod__(x, y): return __intnum_op_ex(x, YASM_EXPR_SIGNMOD, y)
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __neg__(self): return __intnum_op(self, YASM_EXPR_NEG, None)
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __pos__(self): return self
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __abs__(self):
118a1b5233e6d340f45f4846131fec9d0b92e203ce4hbono@chromium.org        if yasm_intnum_sign(self.intn) >= 0: return IntNum(self)
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else: return __intnum_op(self, YASM_EXPR_NEG, None)
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __nonzero__(self): return not yasm_intnum_is_zero(self.intn)
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __invert__(self): return __intnum_op(self, YASM_EXPR_NOT, None)
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __lshift__(x, y): return __intnum_op(x, YASM_EXPR_SHL, y)
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __rshift__(x, y): return __intnum_op(x, YASM_EXPR_SHR, y)
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __and__(x, y): return __intnum_op(x, YASM_EXPR_AND, y)
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __or__(x, y): return __intnum_op(x, YASM_EXPR_OR, y)
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __xor__(x, y): return __intnum_op(x, YASM_EXPR_XOR, y)
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    cdef object __op(self, yasm_expr_op op, object x):
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if isinstance(x, IntNum):
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            rhs = x
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            rhs = IntNum(x)
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(self.intn, op, (<IntNum>rhs).intn)
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return self
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __iadd__(self, x): return self.__op(YASM_EXPR_ADD, x)
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __isub__(self, x): return self.__op(YASM_EXPR_SUB, x)
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __imul__(self, x): return self.__op(YASM_EXPR_MUL, x)
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __idiv__(self, x): return self.__op(YASM_EXPR_SIGNDIV, x)
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __ifloordiv__(self, x): return self.__op(YASM_EXPR_SIGNDIV, x)
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __imod__(self, x): return self.__op(YASM_EXPR_MOD, x)
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __ilshift__(self, x): return self.__op(YASM_EXPR_SHL, x)
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __irshift__(self, x): return self.__op(YASM_EXPR_SHR, x)
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __iand__(self, x): return self.__op(YASM_EXPR_AND, x)
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __ior__(self, x): return self.__op(YASM_EXPR_OR, x)
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __ixor__(self, x): return self.__op(YASM_EXPR_XOR, x)
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __cmp__(self, x):
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        cdef yasm_intnum *t
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        t = yasm_intnum_copy(self.intn)
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if isinstance(x, IntNum):
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            rhs = x
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            rhs = IntNum(x)
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_calc(t, YASM_EXPR_SUB, (<IntNum>rhs).intn)
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        result = yasm_intnum_sign(t)
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        yasm_intnum_destroy(t)
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return result
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __richcmp__(x, y, op):
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        cdef yasm_expr_op aop
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if op == 0: aop = YASM_EXPR_LT
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elif op == 1: aop = YASM_EXPR_LE
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elif op == 2: aop = YASM_EXPR_EQ
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elif op == 3: aop = YASM_EXPR_NE
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elif op == 4: aop = YASM_EXPR_GT
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elif op == 5: aop = YASM_EXPR_GE
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else: raise NotImplementedError
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        v = __intnum_op(x, aop, y)
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return bool(not yasm_intnum_is_zero((<IntNum>v).intn))
171