AAganichev's parse_stab_type size fix.
[binutils-gdb.git] / binutils / stabs.c
index d4833dbed8664e6acf212250da18723f9f5c4336..5f600354257e3b11550f096d8a5db51a6773bea5 100644 (file)
@@ -1,5 +1,5 @@
 /* stabs.c -- Parse stabs debugging information
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>.
 
    This file is part of GNU Binutils.
 #include "aout/stab_gnu.h"
 
 #ifndef DIR_SEPARATOR
+#ifdef _WIN32
+#define DIR_SEPARATOR '\\'
+#else
 #define DIR_SEPARATOR '/'
 #endif
+#endif
 
 /* The number of predefined XCOFF types.  */
 
@@ -371,7 +375,7 @@ warn_stab (p, err)
 /*ARGSUSED*/
 PTR
 start_stab (dhandle, abfd, sections, syms, symcount)
-     PTR dhandle;
+     PTR dhandle ATTRIBUTE_UNUSED;
      bfd *abfd;
      boolean sections;
      asymbol **syms;
@@ -1257,6 +1261,7 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
            {
            case 's':
              size = atoi (attr + 1);
+             size /= 8;  /* Size is in bits.  We store it in bytes.  */
              if (size <= 0)
                size = -1;
              break;
@@ -1312,14 +1317,21 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
            bad_stab (orig);
            return DEBUG_TYPE_NULL;
          }
-       while (q1 != NULL && p > q1 && p[1] == ':')
+       if (q1 != NULL && p > q1 && p[1] == ':')
          {
-           q2 = strchr (q1, '>');
-           if (q2 == NULL || q2 < p)
-             break;
-           p += 2;
-           p = strchr (p, ':');
-           if (p == NULL)
+           int nest = 0;
+
+           for (q2 = q1; *q2 != '\0'; ++q2)
+             {
+               if (*q2 == '<')
+                 ++nest;
+               else if (*q2 == '>')
+                 --nest;
+               else if (*q2 == ':' && nest == 0)
+                 break;
+             }
+           p = q2;
+           if (*p != ':')
              {
                bad_stab (orig);
                return DEBUG_TYPE_NULL;
@@ -1628,7 +1640,7 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
   if (size != -1)
     {
       if (! debug_record_type_size (dhandle, dtype, (unsigned int) size))
-       return false;
+       return DEBUG_TYPE_NULL;
     }
 
   return dtype;
@@ -1807,10 +1819,10 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
            return debug_make_int_type (dhandle, 1, true);
          else if (n3 == 0xffff)
            return debug_make_int_type (dhandle, 2, true);
-         else if (n3 == 0xffffffff)
+         else if (n3 == (bfd_signed_vma) 0xffffffff)
            return debug_make_int_type (dhandle, 4, true);
 #ifdef BFD64
-         else if (n3 == (((bfd_vma) 0xffffffff) << 32) | 0xffffffff)
+         else if (n3 == ((((bfd_vma) 0xffffffff) << 32) | 0xffffffff))
            return debug_make_int_type (dhandle, 8, true);
 #endif
        }
@@ -1827,7 +1839,7 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
          else if (n3 == 0x7fffffff)
            return debug_make_int_type (dhandle, 4, false);
 #ifdef BFD64
-         else if (n3 == (((bfd_vma) 0x7fffffff) << 32) | 0xffffffff)
+         else if (n3 == ((((bfd_vma) 0x7fffffff) << 32) | 0xffffffff))
            return debug_make_int_type (dhandle, 8, false);
 #endif
        }
@@ -3120,7 +3132,7 @@ parse_stab_array_type (dhandle, info, pp, stringp)
   /* If the index type is type 0, we take it as int.  */
   p = *pp;
   if (! parse_stab_type_number (&p, typenums))
-    return false;
+    return DEBUG_TYPE_NULL;
   if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
     {
       index_type = debug_find_named_type (dhandle, "int");
@@ -3128,7 +3140,7 @@ parse_stab_array_type (dhandle, info, pp, stringp)
        {
          index_type = debug_make_int_type (dhandle, 4, false);
          if (index_type == DEBUG_TYPE_NULL)
-           return false;
+           return DEBUG_TYPE_NULL;
        }
       *pp = p;
     }
@@ -3157,7 +3169,7 @@ parse_stab_array_type (dhandle, info, pp, stringp)
   if (**pp != ';')
     {
       bad_stab (orig);
-      return false;
+      return DEBUG_TYPE_NULL;
     }
   ++*pp;
 
@@ -3171,14 +3183,14 @@ parse_stab_array_type (dhandle, info, pp, stringp)
   if (**pp != ';')
     {
       bad_stab (orig);
-      return false;
+      return DEBUG_TYPE_NULL;
     }
   ++*pp;
 
   element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
                                  (debug_type **) NULL);
   if (element_type == DEBUG_TYPE_NULL)
-    return false;
+    return DEBUG_TYPE_NULL;
 
   if (adjustable)
     {
@@ -3428,7 +3440,7 @@ stab_find_type (dhandle, info, typenums)
 
 static boolean
 stab_record_type (dhandle, info, typenums, type)
-     PTR dhandle;
+     PTR dhandle ATTRIBUTE_UNUSED;
      struct stab_handle *info;
      const int *typenums;
      debug_type type;
@@ -4460,6 +4472,7 @@ stab_demangle_template (minfo, pp, pname)
   if (pname != NULL)
     {
       char *s1, *s2, *s3, *s4;
+      char *from, *to;
 
       s1 = savestring (orig, *pp - orig);
 
@@ -4481,7 +4494,15 @@ stab_demangle_template (minfo, pp, pname)
          return false;
        }
 
-      *pname = savestring (s3, s4 - s3);
+      /* Eliminating all spaces, except those between > characters,
+         makes it more likely that the demangled name will match the
+         name which g++ used as the structure name.  */
+      for (from = to = s3; from != s4; ++from)
+       if (*from != ' '
+           || (from[1] == '>' && from > s3 && from[-1] == '>'))
+         *to++ = *from;
+
+      *pname = savestring (s3, to - s3);
 
       free (s3);
     }
@@ -4493,7 +4514,7 @@ stab_demangle_template (minfo, pp, pname)
 
 static boolean
 stab_demangle_class (minfo, pp, pstart)
-     struct stab_demangle_info *minfo;
+     struct stab_demangle_info *minfo ATTRIBUTE_UNUSED;
      const char **pp;
      const char **pstart;
 {
@@ -4772,6 +4793,7 @@ stab_demangle_type (minfo, pp, ptype)
     case 'O':
       {
        boolean memberp, constp, volatilep;
+       debug_type class_type = DEBUG_TYPE_NULL;
        debug_type *args;
        boolean varargs;
        unsigned int n;
@@ -4784,19 +4806,40 @@ stab_demangle_type (minfo, pp, ptype)
        varargs = false;
 
        ++*pp;
-       if (isdigit ((unsigned char) **pp))
+       if (isdigit ((unsigned char) **pp))
          {
-           stab_bad_demangle (orig);
-           return false;
+           n = stab_demangle_count (pp);
+           if (strlen (*pp) < n)
+             {
+               stab_bad_demangle (orig);
+               return false;
+             }
+           name = *pp;
+           *pp += n;
+
+           if (ptype != NULL)
+             {
+               class_type = stab_find_tagged_type (minfo->dhandle,
+                                                   minfo->info,
+                                                   name, (int) n,
+                                                   DEBUG_KIND_CLASS);
+               if (class_type == DEBUG_TYPE_NULL)
+                 return false;
+             }
          }
-       n = stab_demangle_count (pp);
-       if (strlen (*pp) < n)
+       else if (**pp == 'Q')
+         {
+           if (! stab_demangle_qualified (minfo, pp,
+                                          (ptype == NULL
+                                           ? (debug_type *) NULL
+                                           : &class_type)))
+             return false;
+         }
+       else
          {
            stab_bad_demangle (orig);
            return false;
          }
-       name = *pp;
-       *pp += n;
 
        if (memberp)
          {
@@ -4838,14 +4881,6 @@ stab_demangle_type (minfo, pp, ptype)
 
        if (ptype != NULL)
          {
-           debug_type class_type;
-
-           class_type = stab_find_tagged_type (minfo->dhandle, minfo->info,
-                                               name, (int) n,
-                                               DEBUG_KIND_CLASS);
-           if (class_type == DEBUG_TYPE_NULL)
-             return false;
-
            if (! memberp)
              *ptype = debug_make_offset_type (minfo->dhandle, class_type,
                                               *ptype);