]> granicus.if.org Git - yasm/commitdiff
* intnum.c (yasm_intnum_create_sized): New, reverse function of
authorPeter Johnson <peter@tortall.net>
Sat, 15 Apr 2006 09:59:17 +0000 (09:59 -0000)
committerPeter Johnson <peter@tortall.net>
Sat, 15 Apr 2006 09:59:17 +0000 (09:59 -0000)
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
libyasm/intnum.h
tools/python-yasm/intnum.pxi
tools/python-yasm/yasm.pyx

index c39343e060887a0e77490b473ea717d69d00ad0d..572327fda12d8be58bb2fe9664668d2c1d476cc8 100644 (file)
@@ -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;
index 3a8dcf7b103054a9f7ad29dc98e67a64b6f66031..b3e0e7f7c3466939054855ea3ad7143fd9a828ee 100644 (file)
@@ -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.
index 5a8433d7722982c2f3d8b86cf47f3830c369a721..ef68a2ad4f0674fe0e9c7dedbdbe1458387dea4d 100644 (file)
@@ -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)
index a92e980c955a9e22d80d600807221b633544ba81..e6d91e3d1709e38fc6d2056e6a925e03099e0b7e 100644 (file)
 # 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