From bbf23a557d45f52c38cc585142b0cfd9e69019c7 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 15 Apr 2006 09:59:17 +0000 Subject: [PATCH] * intnum.c (yasm_intnum_create_sized): New, reverse function of yasm_intnum_get_sized(). * intnum.h (yasm_intnum_create_sized): Prototype. * yasm.pyx: Bring in _PyLong_From/AsByteArray functions. * intnum.pyx: Use yasm_intnum_create_sized(), etc to implement full 128-bit number handling. * intnum.c (yasm_intnum_get_str): Return strings in hex rather than in decimal. svn path=/trunk/yasm/; revision=1488 --- libyasm/intnum.c | 65 ++++++++++++++++++++++++++++++++---- libyasm/intnum.h | 14 +++++++- tools/python-yasm/intnum.pxi | 27 ++++++++------- tools/python-yasm/yasm.pyx | 22 ++++++++++++ 4 files changed, 108 insertions(+), 20 deletions(-) diff --git a/libyasm/intnum.c b/libyasm/intnum.c index c39343e0..572327fd 100644 --- a/libyasm/intnum.c +++ b/libyasm/intnum.c @@ -296,6 +296,44 @@ yasm_intnum_create_leb128(const unsigned char *ptr, int sign, return intn; } +yasm_intnum * +yasm_intnum_create_sized(unsigned char *ptr, int sign, size_t srcsize, + int bigendian, unsigned long line) +{ + yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum)); + unsigned long i = 0; + + intn->origsize = 0; + + if (srcsize*8 > BITVECT_NATIVE_SIZE) + yasm__warning(YASM_WARN_GENERAL, line, + N_("Numeric constant too large for internal format")); + + /* Read the buffer into a bitvect */ + BitVector_Empty(conv_bv); + if (bigendian) { + /* TODO */ + yasm_internal_error(N_("big endian not implemented")); + } else { + for (i = 0; i < srcsize; i++) + BitVector_Chunk_Store(conv_bv, 8, i*8, ptr[i]); + } + + /* Sign extend if needed */ + if (srcsize*8 < BITVECT_NATIVE_SIZE && sign && (ptr[i] & 0x80) == 0x80) + BitVector_Interval_Fill(conv_bv, i*8, BITVECT_NATIVE_SIZE-1); + + if (Set_Max(conv_bv) < 32) { + intn->type = INTNUM_UL; + intn->val.ul = BitVector_Chunk_Read(conv_bv, 32, 0); + } else { + intn->type = INTNUM_BV; + intn->val.bv = BitVector_Clone(conv_bv); + } + + return intn; +} + yasm_intnum * yasm_intnum_copy(const yasm_intnum *intn) { @@ -881,17 +919,30 @@ yasm_size_uleb128(unsigned long v) char * yasm_intnum_get_str(const yasm_intnum *intn) { - unsigned char *s; + char *s, *s2; switch (intn->type) { case INTNUM_UL: - s = yasm_xmalloc(16); - sprintf((char *)s, "%lu", intn->val.ul); - return (char *)s; - break; + s = yasm_xmalloc(20); + sprintf(s, "0x%lx", intn->val.ul); + return s; case INTNUM_BV: - return (char *)BitVector_to_Dec(intn->val.bv); - break; + if (BitVector_msb_(intn->val.bv)) { + /* it's negative: negate the bitvector to get positive */ + BitVector_Negate(conv_bv, intn->val.bv); + s2 = (char *)BitVector_to_Hex(conv_bv); + s = yasm_xmalloc(strlen(s2)+4); + strcpy(s, "-0x"); + strcat(s, s2); + yasm_xfree(s2); + } else { + s2 = (char *)BitVector_to_Hex(intn->val.bv); + s = yasm_xmalloc(strlen(s2)+3); + strcpy(s, "0x"); + strcat(s, s2); + yasm_xfree(s2); + } + return s; } /*@notreached@*/ return NULL; diff --git a/libyasm/intnum.h b/libyasm/intnum.h index 3a8dcf7b..b3e0e7f7 100644 --- a/libyasm/intnum.h +++ b/libyasm/intnum.h @@ -92,7 +92,7 @@ void yasm_intnum_cleanup(void); /** Create a new intnum from LEB128-encoded form. * \param ptr pointer to start of LEB128 encoded form - * \param sign signed (1) or unsiged (0) LEB128 format + * \param sign signed (1) or unsigned (0) LEB128 format * \param size number of bytes read from ptr (output) * \param line virtual line (where the number came from) * \return Newly allocated intnum. Number of bytes read returned into @@ -102,6 +102,18 @@ void yasm_intnum_cleanup(void); (const unsigned char *ptr, int sign, /*@out@*/ unsigned long *size, unsigned long line); +/** Create a new intnum from a little-endian or big-endian buffer. + * In little endian, the LSB is in ptr[0]. + * \param ptr pointer to start of buffer + * \param sign signed (1) or unsigned (0) source + * \param srcsize source buffer size (in bytes) + * \param bigendian endianness (nonzero=big, zero=little) + * \param line virtual line; may be 0 if warn is 0 + */ +/*@only@*/ yasm_intnum *yasm_intnum_create_sized + (unsigned char *ptr, int sign, size_t srcsize, int bigendian, + unsigned long line); + /** Duplicate an intnum. * \param intn intnum * \return Newly allocated intnum with the same value as intn. diff --git a/tools/python-yasm/intnum.pxi b/tools/python-yasm/intnum.pxi index 5a8433d7..ef68a2ad 100644 --- a/tools/python-yasm/intnum.pxi +++ b/tools/python-yasm/intnum.pxi @@ -36,6 +36,8 @@ cdef extern from "libyasm/intnum.h": cdef yasm_intnum *yasm_intnum_create_int(long i) cdef yasm_intnum *yasm_intnum_create_leb128(unsigned char *ptr, int sign, unsigned long *size, unsigned long line) + cdef yasm_intnum *yasm_intnum_create_sized(unsigned char *ptr, int sign, + size_t srcsize, int bigendian, unsigned long line) cdef yasm_intnum *yasm_intnum_copy(yasm_intnum *intn) cdef void yasm_intnum_destroy(yasm_intnum *intn) cdef void yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, @@ -63,11 +65,12 @@ cdef extern from "libyasm/intnum.h": cdef unsigned long yasm_size_uleb128(unsigned long v) cdef void yasm_intnum_print(yasm_intnum *intn, FILE *f) -# TODO: rework __new__ / __int__ / __long__ to support > int values 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): @@ -79,29 +82,29 @@ cdef class IntNum: val = None if isinstance(value, str): - val = int(value, base) + val = long(value, base) elif isinstance(value, (int, long)): - val = value + val = long(value) if val is None: raise ValueError - if val < 0: - self.intn = yasm_intnum_create_int(val) - else: - self.intn = yasm_intnum_create_uint(val) + _PyLong_AsByteArray(val, buf, 16, 1, 1) + self.intn = yasm_intnum_create_sized(buf, 1, 16, 0, 0) 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, 0) + return _PyLong_FromByteArray(buf, 16, 1, 1) + def __int__(self): - if yasm_intnum_sign(self.intn) < 0: - return yasm_intnum_get_int(self.intn) - else: - return yasm_intnum_get_uint(self.intn) + return int(self.__long__()) def __repr__(self): - return str(int(self)) + return "IntNum(%s)" % str(int(self)) def __op(self, op, o=None): lhs = IntNum(self) diff --git a/tools/python-yasm/yasm.pyx b/tools/python-yasm/yasm.pyx index a92e980c..e6d91e3d 100644 --- a/tools/python-yasm/yasm.pyx +++ b/tools/python-yasm/yasm.pyx @@ -22,6 +22,23 @@ # 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. +"""Interface to the Yasm library. + +The Yasm library (aka libyasm) provides the core functionality of the Yasm +assembler. Classes in this library provide for manipulation of machine +instructions and object file constructs such as symbol tables and sections. + +Expression objects encapsulate complex expressions containing registers, +symbols, and operations such as SEG. + +Bytecode objects encapsulate data or code objects such as data, reserve, +align, or instructions. + +Section objects encapsulate an object file section, including the section +name, any Bytecode objects contained within that section, and other +information. + +""" cdef extern from "Python.h": cdef object PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *)) @@ -31,6 +48,11 @@ cdef extern from "Python.h": cdef void *PyCObject_AsVoidPtr(object) cdef void *PyCObject_GetDesc(object) + cdef object _PyLong_FromByteArray(unsigned char *bytes, unsigned int n, + int little_endian, int is_signed) + cdef int _PyLong_AsByteArray(object v, unsigned char *bytes, unsigned int n, + int little_endian, int is_signed) except -1 + cdef extern from "libyasm/compat-queue.h": pass -- 2.40.0