]> granicus.if.org Git - yasm/commitdiff
Allow both signed and unsigned interpretations for get_int and check_size.
authorPeter Johnson <peter@tortall.net>
Mon, 15 Oct 2001 04:32:16 +0000 (04:32 -0000)
committerPeter Johnson <peter@tortall.net>
Mon, 15 Oct 2001 04:32:16 +0000 (04:32 -0000)
Change argument order on get_int and check_size to better match other
functions (intnum * first arg).

svn path=/trunk/yasm/; revision=280

libyasm/intnum.c
libyasm/intnum.h
src/intnum.c
src/intnum.h

index 05f5303eb8d70b0865d3ac48a0277f7bb24335a0..0826a7aebb738bc6251857f82cc76f3e052c2509 100644 (file)
@@ -457,21 +457,49 @@ intnum_is_neg1(intnum *intn)
            (intn->type == INTNUM_BV && BitVector_is_full(intn->val.bv)));
 }
 
-void
-intnum_get_int(unsigned long *ret_val, const intnum *intn)
+unsigned long
+intnum_get_uint(const intnum *intn)
 {
     switch (intn->type) {
        case INTNUM_UL:
-           *ret_val = intn->val.ul;
-           break;
+           return intn->val.ul;
        case INTNUM_BV:
-           *ret_val = BitVector_Chunk_Read(intn->val.bv, 32, 0);
-           break;
+           return BitVector_Chunk_Read(intn->val.bv, 32, 0);
+       default:
+           InternalError(__LINE__, __FILE__, _("unknown intnum type"));
+           return 0;
+    }
+}
+
+long
+intnum_get_int(const intnum *intn)
+{
+    switch (intn->type) {
+       case INTNUM_UL:
+           return (long)intn->val.ul;
+       case INTNUM_BV:
+           if (BitVector_msb(intn->val.bv)) {
+               /* it's negative: negate the bitvector to get a positive
+                * number, then negate the positive number.
+                */
+               intptr abs_bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE);
+               long retval;
+
+               BitVector_Negate(abs_bv, intn->val.bv);
+               retval = -((long)BitVector_Chunk_Read(abs_bv, 32, 0));
+
+               BitVector_Destroy(abs_bv);
+               return retval;
+           } else
+               return BitVector_Chunk_Read(intn->val.bv, 32, 0);
+       default:
+           InternalError(__LINE__, __FILE__, _("unknown intnum type"));
+           return 0;
     }
 }
 
 void
-intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size)
+intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size)
 {
     unsigned long ul;
     unsigned char *buf;
@@ -499,27 +527,68 @@ intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size)
 
 /* Return 1 if okay size, 0 if not */
 int
-intnum_check_size(const intnum *intn, size_t size)
+intnum_check_size(const intnum *intn, size_t size, int is_signed)
 {
-    switch (intn->type) {
-       case INTNUM_UL:
-           if (size >= 4)
-               return 1;
-           switch (size) {
-               case 3:
-                   return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul);
-               case 2:
-                   return ((intn->val.ul & 0x0000FFFF) == intn->val.ul);
-               case 1:
-                   return ((intn->val.ul & 0x000000FF) == intn->val.ul);
-           }
-           break;
-       case INTNUM_BV:
-           if (size >= 10)
-               return 1;
-           else
-               return (Set_Max(intn->val.bv) < size*8);
-           break;
+    if (is_signed) {
+       long absl;
+
+       switch (intn->type) {
+           case INTNUM_UL:
+               if (size >= 4)
+                   return 1;
+               /* absl = absolute value of (long)intn->val.ul */
+               absl = (long)intn->val.ul;
+               if (absl < 0)
+                   absl = -absl;
+
+               switch (size) {
+                   case 3:
+                       return ((absl & 0x00FFFFFF) == absl);
+                   case 2:
+                       return ((absl & 0x0000FFFF) == absl);
+                   case 1:
+                       return ((absl & 0x000000FF) == absl);
+               }
+               break;
+           case INTNUM_BV:
+               if (size >= 10)
+                   return 1;
+               if (BitVector_msb(intn->val.bv)) {
+                   /* it's negative */
+                   intptr abs_bv = BitVector_Create(BITVECT_ALLOC_SIZE,
+                                                    FALSE);
+                   int retval;
+
+                   BitVector_Negate(abs_bv, intn->val.bv);
+                   retval = Set_Max(abs_bv) < size*8;
+
+                   BitVector_Destroy(abs_bv);
+                   return retval;
+               } else
+                   return (Set_Max(intn->val.bv) < size*8);
+               break;
+       }
+    } else {
+       switch (intn->type) {
+           case INTNUM_UL:
+               if (size >= 4)
+                   return 1;
+               switch (size) {
+                   case 3:
+                       return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul);
+                   case 2:
+                       return ((intn->val.ul & 0x0000FFFF) == intn->val.ul);
+                   case 1:
+                       return ((intn->val.ul & 0x000000FF) == intn->val.ul);
+               }
+               break;
+           case INTNUM_BV:
+               if (size >= 10)
+                   return 1;
+               else
+                   return (Set_Max(intn->val.bv) < size*8);
+               break;
+       }
     }
     return 0;
 }
index 62fe9e27595fb8c276e909d1a41f23077b38291c..38f3248e2aff129e8c164ec26de3886c5bdee90e 100644 (file)
@@ -78,18 +78,23 @@ int intnum_is_neg1(intnum *acc);
  * for overflow.  Use intnum_check_size() to check for overflow.
  */
 
-/* Return a 32-bit value in "standard" C format (eg, of unknown endian). */
-void intnum_get_int(unsigned long *ret_val, const intnum *intn);
+/* Return a 32-bit value in "standard" C format (eg, of unknown endian).
+ * intnum_get_uint() treats intn as an unsigned integer (and returns as such).
+ * intnum_get_int() treats intn as a signed integer (and returns as such).
+ */
+unsigned long intnum_get_uint(const intnum *intn);
+long intnum_get_int(const intnum *intn);
 
 /* ptr will point to the Intel-format little-endian byte string after
  * call (eg, [0] should be the first byte output to the file).
  */
-void intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size);
+void intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size);
 
 /* Check to see if intn will fit without overflow in size bytes.
+ * If is_signed is 1, intn is treated as a signed number.
  * Returns 1 if it will, 0 if not.
  */
-int intnum_check_size(const intnum *intn, size_t size);
+int intnum_check_size(const intnum *intn, size_t size, int is_signed);
 
 void intnum_print(const intnum *intn);
 
index 05f5303eb8d70b0865d3ac48a0277f7bb24335a0..0826a7aebb738bc6251857f82cc76f3e052c2509 100644 (file)
@@ -457,21 +457,49 @@ intnum_is_neg1(intnum *intn)
            (intn->type == INTNUM_BV && BitVector_is_full(intn->val.bv)));
 }
 
-void
-intnum_get_int(unsigned long *ret_val, const intnum *intn)
+unsigned long
+intnum_get_uint(const intnum *intn)
 {
     switch (intn->type) {
        case INTNUM_UL:
-           *ret_val = intn->val.ul;
-           break;
+           return intn->val.ul;
        case INTNUM_BV:
-           *ret_val = BitVector_Chunk_Read(intn->val.bv, 32, 0);
-           break;
+           return BitVector_Chunk_Read(intn->val.bv, 32, 0);
+       default:
+           InternalError(__LINE__, __FILE__, _("unknown intnum type"));
+           return 0;
+    }
+}
+
+long
+intnum_get_int(const intnum *intn)
+{
+    switch (intn->type) {
+       case INTNUM_UL:
+           return (long)intn->val.ul;
+       case INTNUM_BV:
+           if (BitVector_msb(intn->val.bv)) {
+               /* it's negative: negate the bitvector to get a positive
+                * number, then negate the positive number.
+                */
+               intptr abs_bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE);
+               long retval;
+
+               BitVector_Negate(abs_bv, intn->val.bv);
+               retval = -((long)BitVector_Chunk_Read(abs_bv, 32, 0));
+
+               BitVector_Destroy(abs_bv);
+               return retval;
+           } else
+               return BitVector_Chunk_Read(intn->val.bv, 32, 0);
+       default:
+           InternalError(__LINE__, __FILE__, _("unknown intnum type"));
+           return 0;
     }
 }
 
 void
-intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size)
+intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size)
 {
     unsigned long ul;
     unsigned char *buf;
@@ -499,27 +527,68 @@ intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size)
 
 /* Return 1 if okay size, 0 if not */
 int
-intnum_check_size(const intnum *intn, size_t size)
+intnum_check_size(const intnum *intn, size_t size, int is_signed)
 {
-    switch (intn->type) {
-       case INTNUM_UL:
-           if (size >= 4)
-               return 1;
-           switch (size) {
-               case 3:
-                   return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul);
-               case 2:
-                   return ((intn->val.ul & 0x0000FFFF) == intn->val.ul);
-               case 1:
-                   return ((intn->val.ul & 0x000000FF) == intn->val.ul);
-           }
-           break;
-       case INTNUM_BV:
-           if (size >= 10)
-               return 1;
-           else
-               return (Set_Max(intn->val.bv) < size*8);
-           break;
+    if (is_signed) {
+       long absl;
+
+       switch (intn->type) {
+           case INTNUM_UL:
+               if (size >= 4)
+                   return 1;
+               /* absl = absolute value of (long)intn->val.ul */
+               absl = (long)intn->val.ul;
+               if (absl < 0)
+                   absl = -absl;
+
+               switch (size) {
+                   case 3:
+                       return ((absl & 0x00FFFFFF) == absl);
+                   case 2:
+                       return ((absl & 0x0000FFFF) == absl);
+                   case 1:
+                       return ((absl & 0x000000FF) == absl);
+               }
+               break;
+           case INTNUM_BV:
+               if (size >= 10)
+                   return 1;
+               if (BitVector_msb(intn->val.bv)) {
+                   /* it's negative */
+                   intptr abs_bv = BitVector_Create(BITVECT_ALLOC_SIZE,
+                                                    FALSE);
+                   int retval;
+
+                   BitVector_Negate(abs_bv, intn->val.bv);
+                   retval = Set_Max(abs_bv) < size*8;
+
+                   BitVector_Destroy(abs_bv);
+                   return retval;
+               } else
+                   return (Set_Max(intn->val.bv) < size*8);
+               break;
+       }
+    } else {
+       switch (intn->type) {
+           case INTNUM_UL:
+               if (size >= 4)
+                   return 1;
+               switch (size) {
+                   case 3:
+                       return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul);
+                   case 2:
+                       return ((intn->val.ul & 0x0000FFFF) == intn->val.ul);
+                   case 1:
+                       return ((intn->val.ul & 0x000000FF) == intn->val.ul);
+               }
+               break;
+           case INTNUM_BV:
+               if (size >= 10)
+                   return 1;
+               else
+                   return (Set_Max(intn->val.bv) < size*8);
+               break;
+       }
     }
     return 0;
 }
index 62fe9e27595fb8c276e909d1a41f23077b38291c..38f3248e2aff129e8c164ec26de3886c5bdee90e 100644 (file)
@@ -78,18 +78,23 @@ int intnum_is_neg1(intnum *acc);
  * for overflow.  Use intnum_check_size() to check for overflow.
  */
 
-/* Return a 32-bit value in "standard" C format (eg, of unknown endian). */
-void intnum_get_int(unsigned long *ret_val, const intnum *intn);
+/* Return a 32-bit value in "standard" C format (eg, of unknown endian).
+ * intnum_get_uint() treats intn as an unsigned integer (and returns as such).
+ * intnum_get_int() treats intn as a signed integer (and returns as such).
+ */
+unsigned long intnum_get_uint(const intnum *intn);
+long intnum_get_int(const intnum *intn);
 
 /* ptr will point to the Intel-format little-endian byte string after
  * call (eg, [0] should be the first byte output to the file).
  */
-void intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size);
+void intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size);
 
 /* Check to see if intn will fit without overflow in size bytes.
+ * If is_signed is 1, intn is treated as a signed number.
  * Returns 1 if it will, 0 if not.
  */
-int intnum_check_size(const intnum *intn, size_t size);
+int intnum_check_size(const intnum *intn, size_t size, int is_signed);
 
 void intnum_print(const intnum *intn);