* stabsread.c (read_huge_number): Add support for reading octal
authorJerome Guitton <guitton@adacore.com>
Mon, 13 Dec 2004 15:56:47 +0000 (15:56 +0000)
committerJerome Guitton <guitton@adacore.com>
Mon, 13 Dec 2004 15:56:47 +0000 (15:56 +0000)
signed number in twos complement, based on the size of this
number.
(read_range_type): Add support for reading octal signed bounds
in twos complements, based on the size of the type.
(read_type_number, read_cpp_abbrev, read_member_functions,
read_cpp_abbrev, read_one_struct_field, read_baseclasses,
read_struct_type, read_array_type, read_enum_type,
read_sun_builtin_type, read_sun_floating_type): Update calls to
read_huge_number.
(read_type): Update call to read_range_type.

gdb/ChangeLog
gdb/stabsread.c

index 2b3c3629e8451846e87abc82f32a905a2dee52c5..f47019e6ff1bc2cc8669e8f1bbfaa6c1e7ebb340 100644 (file)
@@ -1,3 +1,17 @@
+2004-12-13  Jerome Guitton  <guitton@gnat.com>
+
+       * stabsread.c (read_huge_number): Add support for reading octal
+       signed number in twos complement, based on the size of this
+       number.
+       (read_range_type): Add support for reading octal signed bounds
+       in twos complements, based on the size of the type.
+       (read_type_number, read_cpp_abbrev, read_member_functions,
+       read_cpp_abbrev, read_one_struct_field, read_baseclasses,
+       read_struct_type, read_array_type, read_enum_type,
+       read_sun_builtin_type, read_sun_floating_type): Update calls to
+       read_huge_number.
+       (read_type): Update call to read_range_type.
+
 2004-12-13  Randolph Chung  <tausq@debian.org>
 
        * hppa-hpux-tdep.c (internalize_hp_cxx_exception_support): Call
index e91a98090521ef30f0ea70d73158ef76b388f841..c0f0ae3bc3134901b1ef7ee7ef4f75343e11b043 100644 (file)
@@ -92,7 +92,7 @@ read_one_struct_field (struct field_info *, char **, char *,
 
 static struct type *dbx_alloc_type (int[2], struct objfile *);
 
-static long read_huge_number (char **, int, int *);
+static long read_huge_number (char **, int, int *, int);
 
 static struct type *error_type (char **, struct objfile *);
 
@@ -106,7 +106,7 @@ static int read_type_number (char **, int *);
 
 static struct type *read_type (char **, struct objfile *);
 
-static struct type *read_range_type (char **, int[2], struct objfile *);
+static struct type *read_range_type (char **, int[2], int, struct objfile *);
 
 static struct type *read_sun_builtin_type (char **, int[2], struct objfile *);
 
@@ -435,17 +435,17 @@ read_type_number (char **pp, int *typenums)
   if (**pp == '(')
     {
       (*pp)++;
-      typenums[0] = read_huge_number (pp, ',', &nbits);
+      typenums[0] = read_huge_number (pp, ',', &nbits, 0);
       if (nbits != 0)
        return -1;
-      typenums[1] = read_huge_number (pp, ')', &nbits);
+      typenums[1] = read_huge_number (pp, ')', &nbits, 0);
       if (nbits != 0)
        return -1;
     }
   else
     {
       typenums[0] = 0;
-      typenums[1] = read_huge_number (pp, 0, &nbits);
+      typenums[1] = read_huge_number (pp, 0, &nbits, 0);
       if (nbits != 0)
        return -1;
     }
@@ -1811,7 +1811,7 @@ again:
       break;
 
     case 'r':                  /* Range type */
-      type = read_range_type (pp, typenums, objfile);
+      type = read_range_type (pp, typenums, type_size, objfile);
       if (typenums[0] != -1)
        *dbx_lookup_type (typenums) = type;
       break;
@@ -2291,7 +2291,7 @@ read_member_functions (struct field_info *fip, char **pp, struct type *type,
                   the sign bit out, and usable as a valid index into
                   the array.  Remove the sign bit here.  */
                new_sublist->fn_field.voffset =
-                 (0x7fffffff & read_huge_number (pp, ';', &nbits)) + 2;
+                 (0x7fffffff & read_huge_number (pp, ';', &nbits, 0)) + 2;
                if (nbits != 0)
                  return 0;
 
@@ -2656,7 +2656,8 @@ read_cpp_abbrev (struct field_info *fip, char **pp, struct type *type,
 
       {
        int nbits;
-       FIELD_BITPOS (fip->list->field) = read_huge_number (pp, ';', &nbits);
+       FIELD_BITPOS (fip->list->field) = read_huge_number (pp, ';', &nbits,
+                                                            0);
        if (nbits != 0)
          return 0;
       }
@@ -2729,13 +2730,13 @@ read_one_struct_field (struct field_info *fip, char **pp, char *p,
 
   {
     int nbits;
-    FIELD_BITPOS (fip->list->field) = read_huge_number (pp, ',', &nbits);
+    FIELD_BITPOS (fip->list->field) = read_huge_number (pp, ',', &nbits, 0);
     if (nbits != 0)
       {
        stabs_general_complaint ("bad structure-type format");
        return;
       }
-    FIELD_BITSIZE (fip->list->field) = read_huge_number (pp, ';', &nbits);
+    FIELD_BITSIZE (fip->list->field) = read_huge_number (pp, ';', &nbits, 0);
     if (nbits != 0)
       {
        stabs_general_complaint ("bad structure-type format");
@@ -2931,7 +2932,7 @@ read_baseclasses (struct field_info *fip, char **pp, struct type *type,
   ALLOCATE_CPLUS_STRUCT_TYPE (type);
   {
     int nbits;
-    TYPE_N_BASECLASSES (type) = read_huge_number (pp, ',', &nbits);
+    TYPE_N_BASECLASSES (type) = read_huge_number (pp, ',', &nbits, 0);
     if (nbits != 0)
       return 0;
   }
@@ -3005,7 +3006,7 @@ read_baseclasses (struct field_info *fip, char **pp, struct type *type,
           corresponding to this baseclass.  Always zero in the absence of
           multiple inheritance.  */
 
-       FIELD_BITPOS (new->field) = read_huge_number (pp, ',', &nbits);
+       FIELD_BITPOS (new->field) = read_huge_number (pp, ',', &nbits, 0);
        if (nbits != 0)
          return 0;
       }
@@ -3310,7 +3311,7 @@ read_struct_type (char **pp, struct type *type, enum type_code type_code,
 
   {
     int nbits;
-    TYPE_LENGTH (type) = read_huge_number (pp, 0, &nbits);
+    TYPE_LENGTH (type) = read_huge_number (pp, 0, &nbits, 0);
     if (nbits != 0)
       return error_type (pp, objfile);
   }
@@ -3368,7 +3369,7 @@ read_array_type (char **pp, struct type *type,
       (*pp)++;
       adjustable = 1;
     }
-  lower = read_huge_number (pp, ';', &nbits);
+  lower = read_huge_number (pp, ';', &nbits, 0);
 
   if (nbits != 0)
     return error_type (pp, objfile);
@@ -3378,7 +3379,7 @@ read_array_type (char **pp, struct type *type,
       (*pp)++;
       adjustable = 1;
     }
-  upper = read_huge_number (pp, ';', &nbits);
+  upper = read_huge_number (pp, ';', &nbits, 0);
   if (nbits != 0)
     return error_type (pp, objfile);
 
@@ -3452,7 +3453,7 @@ read_enum_type (char **pp, struct type *type,
        p++;
       name = obsavestring (*pp, p - *pp, &objfile->objfile_obstack);
       *pp = p + 1;
-      n = read_huge_number (pp, ',', &nbits);
+      n = read_huge_number (pp, ',', &nbits, 0);
       if (nbits != 0)
        return error_type (pp, objfile);
 
@@ -3564,17 +3565,17 @@ read_sun_builtin_type (char **pp, int typenums[2], struct objfile *objfile)
      by this type, except that unsigned short is 4 instead of 2.
      Since this information is redundant with the third number,
      we will ignore it.  */
-  read_huge_number (pp, ';', &nbits);
+  read_huge_number (pp, ';', &nbits, 0);
   if (nbits != 0)
     return error_type (pp, objfile);
 
   /* The second number is always 0, so ignore it too. */
-  read_huge_number (pp, ';', &nbits);
+  read_huge_number (pp, ';', &nbits, 0);
   if (nbits != 0)
     return error_type (pp, objfile);
 
   /* The third number is the number of bits for this type. */
-  type_bits = read_huge_number (pp, 0, &nbits);
+  type_bits = read_huge_number (pp, 0, &nbits, 0);
   if (nbits != 0)
     return error_type (pp, objfile);
   /* The type *should* end with a semicolon.  If it are embedded
@@ -3607,12 +3608,12 @@ read_sun_floating_type (char **pp, int typenums[2], struct objfile *objfile)
 
   /* The first number has more details about the type, for example
      FN_COMPLEX.  */
-  details = read_huge_number (pp, ';', &nbits);
+  details = read_huge_number (pp, ';', &nbits, 0);
   if (nbits != 0)
     return error_type (pp, objfile);
 
   /* The second number is the number of bytes occupied by this type */
-  nbytes = read_huge_number (pp, ';', &nbits);
+  nbytes = read_huge_number (pp, ';', &nbits, 0);
   if (nbits != 0)
     return error_type (pp, objfile);
 
@@ -3635,22 +3636,30 @@ read_sun_floating_type (char **pp, int typenums[2], struct objfile *objfile)
    and that character is skipped if it does match.
    If END is zero, *PP is left pointing to that character.
 
+   If TWOS_COMPLEMENT_BITS is set to a strictly positive value and if
+   the number is represented in an octal representation, assume that
+   it is represented in a 2's complement representation with a size of
+   TWOS_COMPLEMENT_BITS.
+
    If the number fits in a long, set *BITS to 0 and return the value.
    If not, set *BITS to be the number of bits in the number and return 0.
 
    If encounter garbage, set *BITS to -1 and return 0.  */
 
 static long
-read_huge_number (char **pp, int end, int *bits)
+read_huge_number (char **pp, int end, int *bits, int twos_complement_bits)
 {
   char *p = *pp;
   int sign = 1;
+  int sign_bit;
   long n = 0;
+  long sn = 0;
   int radix = 10;
   char overflow = 0;
   int nbits = 0;
   int c;
   long upper_limit;
+  int twos_complement_representation = radix == 8 && twos_complement_bits > 0;
 
   if (*p == '-')
     {
@@ -3671,12 +3680,36 @@ read_huge_number (char **pp, int end, int *bits)
   while ((c = *p++) >= '0' && c < ('0' + radix))
     {
       if (n <= upper_limit)
-       {
-         n *= radix;
-         n += c - '0';         /* FIXME this overflows anyway */
-       }
+        {
+          if (twos_complement_representation)
+            {
+              /* Octal, signed, twos complement representation. In this case,
+                 sn is the signed value, n is the corresponding absolute
+                 value. signed_bit is the position of the sign bit in the
+                 first three bits.  */
+              if (sn == 0)
+                {
+                  sign_bit = (twos_complement_bits % 3 + 2) % 3;
+                  sn = c - '0' - ((2 * (c - '0')) | (2 << sign_bit));
+                }
+              else
+                {
+                  sn *= radix;
+                  sn += c - '0';
+                }
+
+              if (sn < 0)
+                n = -sn;
+            }
+          else
+            {
+              /* unsigned representation */
+              n *= radix;
+              n += c - '0';            /* FIXME this overflows anyway */
+            }
+        }
       else
-       overflow = 1;
+        overflow = 1;
 
       /* This depends on large values being output in octal, which is
          what GCC does. */
@@ -3733,14 +3766,18 @@ read_huge_number (char **pp, int end, int *bits)
     {
       if (bits)
        *bits = 0;
-      return n * sign;
+      if (twos_complement_representation)
+        return sn;
+      else
+        return n * sign;
     }
   /* It's *BITS which has the interesting information.  */
   return 0;
 }
 
 static struct type *
-read_range_type (char **pp, int typenums[2], struct objfile *objfile)
+read_range_type (char **pp, int typenums[2], int type_size,
+                 struct objfile *objfile)
 {
   char *orig_pp = *pp;
   int rangenums[2];
@@ -3769,8 +3806,8 @@ read_range_type (char **pp, int typenums[2], struct objfile *objfile)
 
   /* The remaining two operands are usually lower and upper bounds
      of the range.  But in some special cases they mean something else.  */
-  n2 = read_huge_number (pp, ';', &n2bits);
-  n3 = read_huge_number (pp, ';', &n3bits);
+  n2 = read_huge_number (pp, ';', &n2bits, type_size);
+  n3 = read_huge_number (pp, ';', &n3bits, type_size);
 
   if (n2bits == -1 || n3bits == -1)
     return error_type (pp, objfile);
@@ -3786,8 +3823,19 @@ read_range_type (char **pp, int typenums[2], struct objfile *objfile)
       /* Number of bits in the type.  */
       int nbits = 0;
 
+      /* If a type size attribute has been specified, the bounds of
+         the range should fit in this size. If the lower bounds needs
+         more bits than the upper bound, then the type is signed.  */
+      if (n2bits <= type_size && n3bits <= type_size)
+        {
+          if (n2bits == type_size && n2bits > n3bits)
+            got_signed = 1;
+          else
+            got_unsigned = 1;
+          nbits = type_size;
+        }
       /* Range from 0 to <large number> is an unsigned large integral type.  */
-      if ((n2bits == 0 && n2 == 0) && n3bits != 0)
+      else if ((n2bits == 0 && n2 == 0) && n3bits != 0)
        {
          got_unsigned = 1;
          nbits = n3bits;