* m10300-dis.c: Do not emit a comma before a PLUS (autoincrement)
[deliverable/binutils-gdb.git] / binutils / stabs.c
index be9fce0a6f21cdfd42f0a61100e22aab7858c5d1..d4833dbed8664e6acf212250da18723f9f5c4336 100644 (file)
@@ -1,5 +1,5 @@
 /* stabs.c -- Parse stabs debugging information
-   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>.
 
    This file is part of GNU Binutils.
 #include "aout/aout64.h"
 #include "aout/stab_gnu.h"
 
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
 /* The number of predefined XCOFF types.  */
 
 #define XCOFF_TYPE_COUNT 34
 
 struct stab_handle
 {
+  /* The BFD.  */
+  bfd *abfd;
   /* True if this is stabs in sections.  */
   boolean sections;
-  /* The type of the last stab symbol, so that we can detect N_SO
-     pairs.  */
-  int last_type;
+  /* The symbol table.  */
+  asymbol **syms;
+  /* The number of symbols.  */
+  long symcount;
+  /* The accumulated file name string.  */
+  char *so_string;
+  /* The value of the last N_SO symbol.  */
+  bfd_vma so_value;
   /* The value of the start of the file, so that we can handle file
      relative N_LBRAC and N_RBRAC symbols.  */
   bfd_vma file_start_offset;
@@ -68,10 +79,16 @@ struct stab_handle
   boolean n_opt_found;
   /* The main file name.  */
   char *main_filename;
-  /* A stack of N_BINCL files.  */
+  /* A stack of unfinished N_BINCL files.  */
   struct bincl_file *bincl_stack;
+  /* A list of finished N_BINCL files.  */
+  struct bincl_file *bincl_list;
   /* Whether we are inside a function or not.  */
   boolean within_function;
+  /* The address of the end of the function, used if we have seen an
+     N_FUN symbol while in a function.  This is -1 if we have not seen
+     an N_FUN (the normal case).  */
+  bfd_vma function_end;
   /* The depth of block nesting.  */
   int block_depth;
   /* List of pending variable definitions.  */
@@ -84,6 +101,9 @@ struct stab_handle
   debug_type xcoff_types[XCOFF_TYPE_COUNT];
   /* Undefined tags.  */
   struct stab_tag *tags;
+  /* Set by parse_stab_type if it sees a structure defined as a cross
+     reference to itself.  Reset by parse_stab_type otherwise.  */
+  boolean self_crossref;
 };
 
 /* A list of these structures is used to hold pending variable
@@ -175,8 +195,10 @@ static boolean parse_stab_tilde_field
           debug_type *, boolean *));
 static debug_type parse_stab_array_type
   PARAMS ((PTR, struct stab_handle *, const char **, boolean));
-static void push_bincl PARAMS ((struct stab_handle *, const char *));
+static void push_bincl PARAMS ((struct stab_handle *, const char *, bfd_vma));
 static const char *pop_bincl PARAMS ((struct stab_handle *));
+static boolean find_excl
+  PARAMS ((struct stab_handle *, const char *, bfd_vma));
 static boolean stab_record_variable
   PARAMS ((PTR, struct stab_handle *, const char *, debug_type,
           enum debug_var_kind, bfd_vma));
@@ -228,7 +250,14 @@ parse_number (pp, poverflow)
   errno = 0;
   ul = strtoul (*pp, (char **) pp, 0);
   if (ul + 1 != 0 || errno == 0)
-    return (bfd_vma) ul;
+    {
+      /* If bfd_vma is larger than unsigned long, and the number is
+         meant to be negative, we have to make sure that we sign
+         extend properly.  */
+      if (*orig == '-')
+       return (bfd_vma) (bfd_signed_vma) (long) ul;
+      return (bfd_vma) ul;
+    }
 
   /* Note that even though strtoul overflowed, it should have set *pp
      to the end of the number, which is where we want it.  */
@@ -313,7 +342,7 @@ parse_number (pp, poverflow)
   if (poverflow != NULL)
     *poverflow = true;
   else
-    warn_stab (orig, "numeric overflow");
+    warn_stab (orig, _("numeric overflow"));
 
   return 0;
 }
@@ -324,7 +353,7 @@ static void
 bad_stab (p)
      const char *p;
 {
-  fprintf (stderr, "Bad stab: %s\n", p);
+  fprintf (stderr, _("Bad stab: %s\n"), p);
 }
 
 /* Warn about something in a stab string.  */
@@ -334,25 +363,32 @@ warn_stab (p, err)
      const char *p;
      const char *err;
 {
-  fprintf (stderr, "Warning: %s: %s\n", err, p);
+  fprintf (stderr, _("Warning: %s: %s\n"), err, p);
 }
 
 /* Create a handle to parse stabs symbols with.  */
 
 /*ARGSUSED*/
 PTR
-start_stab (dhandle, sections)
+start_stab (dhandle, abfd, sections, syms, symcount)
      PTR dhandle;
+     bfd *abfd;
      boolean sections;
+     asymbol **syms;
+     long symcount;
 {
   struct stab_handle *ret;
 
   ret = (struct stab_handle *) xmalloc (sizeof *ret);
   memset (ret, 0, sizeof *ret);
+  ret->abfd = abfd;
   ret->sections = sections;
+  ret->syms = syms;
+  ret->symcount = symcount;
   ret->files = 1;
   ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
   ret->file_types[0] = NULL;
+  ret->function_end = (bfd_vma) -1;
   return (PTR) ret;
 }
 
@@ -369,9 +405,11 @@ finish_stab (dhandle, handle)
 
   if (info->within_function)
     {
-      if (! debug_end_function (dhandle, (bfd_vma) -1))
+      if (! stab_emit_pending_vars (dhandle, info)
+         || ! debug_end_function (dhandle, info->function_end))
        return false;
       info->within_function = false;
+      info->function_end = (bfd_vma) -1;
     }
 
   for (st = info->tags; st != NULL; st = st->next)
@@ -386,9 +424,6 @@ finish_stab (dhandle, handle)
        return false;
     }
 
-  if (info->pending)
-    fprintf (stderr, "Left over pending variables in stabs debugging\n");
-
   return true;
 }
 
@@ -405,6 +440,38 @@ parse_stab (dhandle, handle, type, desc, value, string)
 {
   struct stab_handle *info = (struct stab_handle *) handle;
 
+  /* gcc will emit two N_SO strings per compilation unit, one for the
+     directory name and one for the file name.  We just collect N_SO
+     strings as we see them, and start the new compilation unit when
+     we see a non N_SO symbol.  */
+  if (info->so_string != NULL
+      && (type != N_SO || *string == '\0' || value != info->so_value))
+    {
+      if (! debug_set_filename (dhandle, info->so_string))
+       return false;
+      info->main_filename = info->so_string;
+
+      info->gcc_compiled = 0;
+      info->n_opt_found = false;
+
+      /* Generally, for stabs in the symbol table, the N_LBRAC and
+        N_RBRAC symbols are relative to the N_SO symbol value.  */
+      if (! info->sections)
+       info->file_start_offset = info->so_value;
+
+      /* We need to reset the mapping from type numbers to types.  We
+        can't free the old mapping, because of the use of
+        debug_make_indirect_type.  */
+      info->files = 1;
+      info->file_types = ((struct stab_types **)
+                         xmalloc (sizeof *info->file_types));
+      info->file_types[0] = NULL;
+
+      info->so_string = NULL;
+
+      /* Now process whatever type we just got.  */
+    }
+
   switch (type)
     {
     case N_FN:
@@ -418,7 +485,7 @@ parse_stab (dhandle, handle, type, desc, value, string)
 
       if (! info->within_function)
        {
-         fprintf (stderr, "N_LBRAC not within function\n");
+         fprintf (stderr, _("N_LBRAC not within function\n"));
          return false;
        }
 
@@ -457,64 +524,61 @@ parse_stab (dhandle, handle, type, desc, value, string)
       --info->block_depth;
       if (info->block_depth < 0)
        {
-         fprintf (stderr, "Too many N_RBRACs\n");
+         fprintf (stderr, _("Too many N_RBRACs\n"));
          return false;
        }
       break;
 
     case N_SO:
-      /* Start a file.  If we get two in a row, the first is the
-         directory name.  An empty string is emitted by gcc at the end
-         of a compilation unit.  */
-      if (*string == '\0')
-       {
-         if (info->within_function)
-           {
-             if (! debug_end_function (dhandle, value))
-               return false;
-             info->within_function = false;
-           }
-         return true;
-       }
-      info->gcc_compiled = 0;
-      info->n_opt_found = false;
-      if (info->last_type == N_SO)
+      /* This always ends a function.  */
+      if (info->within_function)
        {
-         char *o;
-
-         if (! debug_append_filename (dhandle, string))
+         bfd_vma endval;
+
+         endval = value;
+         if (*string != '\0'
+             && info->function_end != (bfd_vma) -1
+             && info->function_end < endval)
+           endval = info->function_end;
+         if (! stab_emit_pending_vars (dhandle, info)
+             || ! debug_end_function (dhandle, endval))
            return false;
-         o = info->main_filename;
-         info->main_filename = concat (o, string, (const char *) NULL);
-         free (o);
+         info->within_function = false;
+         info->function_end = (bfd_vma) -1;
        }
+
+      /* An empty string is emitted by gcc at the end of a compilation
+         unit.  */
+      if (*string == '\0')
+       return true;
+
+      /* Just accumulate strings until we see a non N_SO symbol.  If
+         the string starts with a directory separator or some other
+        form of absolute path specification, we discard the previously
+         accumulated strings.  */
+      if (info->so_string == NULL)
+       info->so_string = xstrdup (string);
       else
        {
-         if (info->within_function)
-           {
-             if (! debug_end_function (dhandle, value))
-               return false;
-             info->within_function = false;
-           }
-         if (! debug_set_filename (dhandle, string))
-           return false;
-         if (info->main_filename != NULL)
-           free (info->main_filename);
-         info->main_filename = xstrdup (string);
-
-         /* Generally, for stabs in the symbol table, the N_LBRAC and
-             N_RBRAC symbols are relative to the N_SO symbol value.  */
-         if (! info->sections)
-           info->file_start_offset = value;
-
-         /* We need to reset the mapping from type numbers to types.
-             We can't free the old mapping, because of the use of
-             debug_make_indirect_type.  */
-         info->files = 1;
-         info->file_types = ((struct stab_types **)
-                             xmalloc (sizeof *info->file_types));
-         info->file_types[0] = NULL;
+         char *f;
+
+         f = info->so_string;
+
+         if (   (string[0] == '/')
+             || (string[0] == DIR_SEPARATOR)
+             || (   (DIR_SEPARATOR == '\\')
+                 && (string[1] == ':')
+                 && (   (string[2] == DIR_SEPARATOR)
+                     || (string[2] == '/'))))
+           info->so_string = xstrdup (string);
+         else
+           info->so_string = concat (info->so_string, string,
+                                     (const char *) NULL);
+         free (f);
        }
+
+      info->so_value = value;
+
       break;
 
     case N_SOL:
@@ -525,7 +589,7 @@ parse_stab (dhandle, handle, type, desc, value, string)
 
     case N_BINCL:
       /* Start an include file which may be replaced.  */
-      push_bincl (info, string);
+      push_bincl (info, string, value);
       if (! debug_start_source (dhandle, string))
        return false;
       break;
@@ -539,12 +603,8 @@ parse_stab (dhandle, handle, type, desc, value, string)
     case N_EXCL:
       /* This is a duplicate of a header file named by N_BINCL which
          was eliminated by the linker.  */
-      ++info->files;
-      info->file_types = ((struct stab_types **)
-                         xrealloc ((PTR) info->file_types,
-                                   (info->files
-                                    * sizeof *info->file_types)));
-      info->file_types[info->files - 1] = NULL;
+      if (! find_excl (info, string, value))
+       return false;
       break;
 
     case N_SLINE:
@@ -563,10 +623,40 @@ parse_stab (dhandle, handle, type, desc, value, string)
        return false;
       break;
 
+    case N_FUN:
+      if (*string == '\0')
+       {
+         if (info->within_function)
+           {
+             /* This always marks the end of a function; we don't
+                 need to worry about info->function_end.  */
+             if (info->sections)
+               value += info->function_start_offset;
+             if (! stab_emit_pending_vars (dhandle, info)
+                 || ! debug_end_function (dhandle, value))
+               return false;
+             info->within_function = false;
+             info->function_end = (bfd_vma) -1;
+           }
+         break;
+       }
+
+      /* A const static symbol in the .text section will have an N_FUN
+         entry.  We need to use these to mark the end of the function,
+         in case we are looking at gcc output before it was changed to
+         always emit an empty N_FUN.  We can't call debug_end_function
+         here, because it might be a local static symbol.  */
+      if (info->within_function
+         && (info->function_end == (bfd_vma) -1
+             || value < info->function_end))
+       info->function_end = value;
+
+      /* Fall through.  */
       /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
          symbols, and if it does not start with :S, gdb relocates the
          value to the start of the section.  gcc always seems to use
          :S, so we don't worry about this.  */
+      /* Fall through.  */
     default:
       {
        const char *colon;
@@ -577,8 +667,16 @@ parse_stab (dhandle, handle, type, desc, value, string)
          {
            if (info->within_function)
              {
-               if (! debug_end_function (dhandle, value))
+               bfd_vma endval;
+
+               endval = value;
+               if (info->function_end != (bfd_vma) -1
+                   && info->function_end < endval)
+                 endval = info->function_end;
+               if (! stab_emit_pending_vars (dhandle, info)
+                   || ! debug_end_function (dhandle, endval))
                  return false;
+               info->function_end = (bfd_vma) -1;
              }
            /* For stabs in sections, line numbers and block addresses
                are offsets from the start of the function.  */
@@ -607,8 +705,6 @@ parse_stab (dhandle, handle, type, desc, value, string)
       break;
     }
 
-  info->last_type = type;
-
   return true;
 }
 
@@ -628,6 +724,7 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
   int type;
   debug_type dtype;
   boolean synonym;
+  boolean self_crossref;
   unsigned int lineno;
   debug_type *slot;
 
@@ -676,7 +773,7 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
          /* SunPRO (3.0 at least) static variable encoding.  */
          break;
        default:
-         warn_stab (string, "unknown C++ encoded name");
+         warn_stab (string, _("unknown C++ encoded name"));
          break;
        }
     }
@@ -788,15 +885,34 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
       break;
 
     case 'G':
-      /* A global symbol.  The value must be extracted from the symbol
-         table.  */
-      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
-                              (debug_type **) NULL);
-      if (dtype == DEBUG_TYPE_NULL)
-       return false;
-      if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
-                                 (bfd_vma) -1))
-       return false;
+      {
+       char leading;
+       long c;
+       asymbol **ps;
+
+       /* A global symbol.  The value must be extracted from the
+          symbol table.  */
+       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+                                (debug_type **) NULL);
+       if (dtype == DEBUG_TYPE_NULL)
+         return false;
+       leading = bfd_get_symbol_leading_char (info->abfd);
+       for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
+         {
+           const char *n;
+
+           n = bfd_asymbol_name (*ps);
+           if (leading != '\0' && *n == leading)
+             ++n;
+           if (*n == *name && strcmp (n, name) == 0)
+             break;
+         }
+       if (c > 0)
+         value = bfd_asymbol_value (*ps);
+       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
+                                   value))
+         return false;
+      }
       break;
 
       /* This case is faked by a conditional above, when there is no
@@ -941,6 +1057,11 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
       if (name == NULL)
        return true;
 
+      /* INFO->SELF_CROSSREF is set by parse_stab_type if this type is
+         a cross reference to itself.  These are generated by some
+         versions of g++.  */
+      self_crossref = info->self_crossref;
+
       dtype = debug_tag_type (dhandle, name, dtype);
       if (dtype == DEBUG_TYPE_NULL)
        return false;
@@ -948,21 +1069,23 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
        *slot = dtype;
 
       /* See if we have a cross reference to this tag which we can now
-         fill in.  */
-      {
-       register struct stab_tag **pst;
+         fill in.  Avoid filling in a cross reference to ourselves,
+         because that would lead to circular debugging information.  */
+      if (! self_crossref)
+       {
+         register struct stab_tag **pst;
 
-       for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)
-         {
-           if ((*pst)->name[0] == name[0]
-               && strcmp ((*pst)->name, name) == 0)
-             {
-               (*pst)->slot = dtype;
-               *pst = (*pst)->next;
-               break;
-             }
-         }
-      }
+         for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)
+           {
+             if ((*pst)->name[0] == name[0]
+                 && strcmp ((*pst)->name, name) == 0)
+               {
+                 (*pst)->slot = dtype;
+                 *pst = (*pst)->next;
+                 break;
+               }
+           }
+       }
 
       if (synonym)
        {
@@ -1063,6 +1186,8 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
   size = -1;
   stringp = false;
 
+  info->self_crossref = false;
+
   /* Read type number if present.  The type number may be omitted.
      for instance in a two-dimensional array declared with type
      "ar1;1;10;ar1;1;10;4".  */
@@ -1174,7 +1299,7 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
          default:
            /* Complain and keep going, so compilers can invent new
               cross-reference types.  */
-           warn_stab (orig, "unrecognized cross reference type");
+           warn_stab (orig, _("unrecognized cross reference type"));
            code = DEBUG_KIND_STRUCT;
            break;
          }
@@ -1201,6 +1326,15 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
              }
          }
 
+       /* Some versions of g++ can emit stabs like
+              fleep:T20=xsfleep:
+          which define structures in terms of themselves.  We need to
+          tell the caller to avoid building a circular structure.  */
+       if (typename != NULL
+           && strncmp (typename, *pp, p - *pp) == 0
+           && typename[p - *pp] == '\0')
+         info->self_crossref = true;
+
        dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
 
        *pp = p + 1;
@@ -1621,7 +1755,7 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
            return debug_make_int_type (dhandle, 8, true);
        }
 
-      warn_stab (orig, "numeric overflow");
+      warn_stab (orig, _("numeric overflow"));
     }
 
   if (index_type == DEBUG_TYPE_NULL)
@@ -1631,6 +1765,11 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
       if (self_subrange && n2 == 0 && n3 == 0)
        return debug_make_void_type (dhandle);
 
+      /* A type defined as a subrange of itself, with n2 positive and
+        n3 zero, is a complex type, and n2 is the number of bytes.  */
+      if (self_subrange && n3 == 0 && n2 > 0)
+       return debug_make_complex_type (dhandle, n2);
+
       /* If n3 is zero and n2 is positive, this is a floating point
          type, and n2 is the number of bytes.  */
       if (n3 == 0 && n2 > 0)
@@ -1668,15 +1807,18 @@ 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);
-         /* -1 is used for the upper bound of (4 byte) "unsigned int"
-            and "unsigned long", and we already checked for that, so
-            don't need to test for it here.  */
+         else if (n3 == 0xffffffff)
+           return debug_make_int_type (dhandle, 4, true);
+#ifdef BFD64
+         else if (n3 == (((bfd_vma) 0xffffffff) << 32) | 0xffffffff)
+           return debug_make_int_type (dhandle, 8, true);
+#endif
        }
       else if (n3 == 0
               && n2 < 0
               && (self_subrange || n2 == -8))
        return debug_make_int_type (dhandle, - n2, true);
-      else if (n2 == - n3 - 1)
+      else if (n2 == - n3 - 1 || n2 == n3 + 1)
        {
          if (n3 == 0x7f)
            return debug_make_int_type (dhandle, 1, false);
@@ -1684,6 +1826,10 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
            return debug_make_int_type (dhandle, 2, false);
          else if (n3 == 0x7fffffff)
            return debug_make_int_type (dhandle, 4, false);
+#ifdef BFD64
+         else if (n3 == (((bfd_vma) 0x7fffffff) << 32) | 0xffffffff)
+           return debug_make_int_type (dhandle, 8, false);
+#endif
        }
     }
 
@@ -1701,7 +1847,7 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
     {
       /* Does this actually ever happen?  Is that why we are worrying
          about dealing with it rather than just calling error_type?  */
-      warn_stab (orig, "missing index type");
+      warn_stab (orig, _("missing index type"));
       index_type = debug_make_int_type (dhandle, 4, false);
     }
 
@@ -2028,7 +2174,7 @@ parse_stab_baseclasses (dhandle, info, pp, retp)
          virtual = true;
          break;
        default:
-         warn_stab (orig, "unknown virtual character for baseclass");
+         warn_stab (orig, _("unknown virtual character for baseclass"));
          virtual = false;
          break;
        }
@@ -2046,7 +2192,7 @@ parse_stab_baseclasses (dhandle, info, pp, retp)
          visibility = DEBUG_VISIBILITY_PUBLIC;
          break;
        default:
-         warn_stab (orig, "unknown visibility character for baseclass");
+         warn_stab (orig, _("unknown visibility character for baseclass"));
          visibility = DEBUG_VISIBILITY_PUBLIC;
          break;
        }
@@ -2238,13 +2384,13 @@ parse_stab_cpp_abbrev (dhandle, info, pp, retp)
       typename = debug_get_type_name (dhandle, context);
       if (typename == NULL)
        {
-         warn_stab (orig, "unnamed $vb type");
+         warn_stab (orig, _("unnamed $vb type"));
          typename = "FOO";
        }
       name = concat ("_vb$", typename, (const char *) NULL);
       break;
     default:
-      warn_stab (orig, "unrecognized C++ abbreviation");
+      warn_stab (orig, _("unrecognized C++ abbreviation"));
       name = "INVALID_CPLUSPLUS_ABBREV";
       break;
     }
@@ -2324,7 +2470,7 @@ parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
          visibility = DEBUG_VISIBILITY_PUBLIC;
          break;
        default:
-         warn_stab (orig, "unknown visibility character for field");
+         warn_stab (orig, _("unknown visibility character for field"));
          visibility = DEBUG_VISIBILITY_PUBLIC;
          break;
        }
@@ -2492,6 +2638,7 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
       do
        {
          debug_type type;
+         boolean stub;
          char *argtypes;
          enum debug_visibility visibility;
          boolean constp, volatilep, staticp;
@@ -2527,6 +2674,11 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
              return false;
            }
 
+         stub = false;
+         if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
+             && debug_get_parameter_types (dhandle, type, &varargs) == NULL)
+           stub = true;
+
          argtypes = savestring (*pp, p - *pp);
          *pp = p + 1;
 
@@ -2574,7 +2726,7 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
              /* File compiled with g++ version 1; no information.  */
              break;
            default:
-             warn_stab (orig, "const/volatile indicator missing");
+             warn_stab (orig, _("const/volatile indicator missing"));
              break;
            }
 
@@ -2583,12 +2735,8 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
            {
            case '*':
              /* virtual member function, followed by index.  The sign
-                bit is set to distinguish pointers-to-methods from
-                virtual function indicies.  Since the array is in
-                words, the quantity must be shifted left by 1 on 16
-                bit machine, and by 2 on 32 bit machine, forcing the
-                sign bit out, and usable as a valid index into the
-                array.  Remove the sign bit here.  */
+                bit is supposedly set to distinguish
+                pointers-to-methods from virtual function indicies.  */
              ++*pp;
              voffset = parse_number (pp, (boolean *) NULL);
              if (**pp != ';')
@@ -2598,7 +2746,6 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
                }
              ++*pp;
              voffset &= 0x7fffffff;
-             voffset += 2;
 
              if (**pp == ';' || *pp == '\0')
                {
@@ -2617,6 +2764,7 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
                    if (**pp == ':')
                      {
                        /* g++ version 1 overloaded methods.  */
+                       context = DEBUG_TYPE_NULL;
                      }
                    else
                      {
@@ -2638,6 +2786,8 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
              staticp = true;
              voffset = 0;
              context = DEBUG_TYPE_NULL;
+             if (strncmp (argtypes, name, strlen (name)) != 0)
+               stub = true;
              break;
 
            default:
@@ -2653,15 +2803,12 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
              break;
            }
 
-         /* If this is a method type which is not a stub--that is,
-            the argument types are fully specified--then the argtypes
-            string is actually the physical name of the function.
-            Otherwise, the argtypes string is the mangled from of the
-            argument types, and the physical name of the function,
-            and the argument types, must be deduced from it.  */
-
-         if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
-             && debug_get_parameter_types (dhandle, type, &varargs) != NULL)
+         /* If the type is not a stub, then the argtypes string is
+             the physical name of the function.  Otherwise the
+             argtypes string is the mangled form of the argument
+             types, and the full type and the physical name must be
+             extracted from them.  */
+         if (! stub)
            physname = argtypes;
          else
            {
@@ -2819,7 +2966,7 @@ parse_stab_argtypes (dhandle, info, class_type, fieldname, tagname,
          opname = cplus_mangle_opname (fieldname + 3, 0);
          if (opname == NULL)
            {
-             fprintf (stderr, "No mangling for \"%s\"\n", fieldname);
+             fprintf (stderr, _("No mangling for \"%s\"\n"), fieldname);
              return DEBUG_TYPE_NULL;
            }
          mangled_name_len += strlen (opname);
@@ -2844,7 +2991,7 @@ parse_stab_argtypes (dhandle, info, class_type, fieldname, tagname,
       *pphysname = physname;
     }
 
-  if (*argtypes == '\0')
+  if (*argtypes == '\0' || is_destructor)
     {
       args = (debug_type *) xmalloc (sizeof *args);
       *args = NULL;
@@ -2952,6 +3099,8 @@ parse_stab_array_type (dhandle, info, pp, stringp)
      boolean stringp;
 {
   const char *orig;
+  const char *p;
+  int typenums[2];
   debug_type index_type;
   boolean adjustable;
   bfd_signed_vma lower, upper;
@@ -2968,8 +3117,27 @@ parse_stab_array_type (dhandle, info, pp, stringp)
 
   /* FIXME: gdb checks os9k_stabs here.  */
 
-  index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                               (debug_type **) NULL);
+  /* If the index type is type 0, we take it as int.  */
+  p = *pp;
+  if (! parse_stab_type_number (&p, typenums))
+    return false;
+  if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
+    {
+      index_type = debug_find_named_type (dhandle, "int");
+      if (index_type == DEBUG_TYPE_NULL)
+       {
+         index_type = debug_make_int_type (dhandle, 4, false);
+         if (index_type == DEBUG_TYPE_NULL)
+           return false;
+       }
+      *pp = p;
+    }
+  else
+    {
+      index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                   (debug_type **) NULL);
+    }
+
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -3022,26 +3190,43 @@ parse_stab_array_type (dhandle, info, pp, stringp)
                                upper, stringp);
 }
 
-/* Keep a stack of N_BINCL include files.  */
+/* This struct holds information about files we have seen using
+   N_BINCL.  */
 
 struct bincl_file
 {
+  /* The next N_BINCL file.  */
   struct bincl_file *next;
+  /* The next N_BINCL on the stack.  */
+  struct bincl_file *next_stack;
+  /* The file name.  */
   const char *name;
+  /* The hash value.  */
+  bfd_vma hash;
+  /* The file index.  */
+  unsigned int file;
+  /* The list of types defined in this file.  */
+  struct stab_types *file_types;
 };
 
 /* Start a new N_BINCL file, pushing it onto the stack.  */
 
 static void
-push_bincl (info, name)
+push_bincl (info, name, hash)
      struct stab_handle *info;
      const char *name;
+     bfd_vma hash;
 {
   struct bincl_file *n;
 
   n = (struct bincl_file *) xmalloc (sizeof *n);
-  n->next = info->bincl_stack;
+  n->next = info->bincl_list;
+  n->next_stack = info->bincl_stack;
   n->name = name;
+  n->hash = hash;
+  n->file = info->files;
+  n->file_types = NULL;
+  info->bincl_list = n;
   info->bincl_stack = n;
 
   ++info->files;
@@ -3049,7 +3234,7 @@ push_bincl (info, name)
                      xrealloc ((PTR) info->file_types,
                                (info->files
                                 * sizeof *info->file_types)));
-  info->file_types[info->files - 1] = NULL;
+  info->file_types[n->file] = NULL;
 }
 
 /* Finish an N_BINCL file, at an N_EINCL, popping the name off the
@@ -3064,13 +3249,46 @@ pop_bincl (info)
   o = info->bincl_stack;
   if (o == NULL)
     return info->main_filename;
-  info->bincl_stack = o->next;
-  free (o);
+  info->bincl_stack = o->next_stack;
+
+  o->file_types = info->file_types[o->file];
+
   if (info->bincl_stack == NULL)
     return info->main_filename;
   return info->bincl_stack->name;
 }
 
+/* Handle an N_EXCL: get the types from the corresponding N_BINCL.  */
+
+static boolean
+find_excl (info, name, hash)
+     struct stab_handle *info;
+     const char *name;
+     bfd_vma hash;
+{
+  struct bincl_file *l;
+
+  ++info->files;
+  info->file_types = ((struct stab_types **)
+                     xrealloc ((PTR) info->file_types,
+                               (info->files
+                                * sizeof *info->file_types)));
+
+  for (l = info->bincl_list; l != NULL; l = l->next)
+    if (l->hash == hash && strcmp (l->name, name) == 0)
+      break;
+  if (l == NULL)
+    {
+      warn_stab (name, _("Undefined N_EXCL"));
+      info->file_types[info->files - 1] = NULL;
+      return true;
+    }
+
+  info->file_types[info->files - 1] = l->file_types;
+
+  return true;
+}
+
 /* Handle a variable definition.  gcc emits variable definitions for a
    block before the N_LBRAC, so we must hold onto them until we see
    it.  The SunPRO compiler emits variable definitions after the
@@ -3149,12 +3367,12 @@ stab_find_slot (info, typenums)
 
   if (filenum < 0 || (unsigned int) filenum >= info->files)
     {
-      fprintf (stderr, "Type file number %d out of range\n", filenum);
+      fprintf (stderr, _("Type file number %d out of range\n"), filenum);
       return NULL;
     }
   if (index < 0)
     {
-      fprintf (stderr, "Type index number %d out of range\n", index);
+      fprintf (stderr, _("Type index number %d out of range\n"), index);
       return NULL;
     }
 
@@ -3241,7 +3459,7 @@ stab_xcoff_builtin_type (dhandle, info, typenum)
 
   if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT)
     {
-      fprintf (stderr, "Unrecognized XCOFF type %d\n", typenum);
+      fprintf (stderr, _("Unrecognized XCOFF type %d\n"), typenum);
       return DEBUG_TYPE_NULL;
     }
   if (info->xcoff_types[-typenum] != NULL)
@@ -3518,7 +3736,7 @@ static boolean stab_demangle_signature
 static boolean stab_demangle_qualified
   PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
 static boolean stab_demangle_template
-  PARAMS ((struct stab_demangle_info *, const char **));
+  PARAMS ((struct stab_demangle_info *, const char **, char **));
 static boolean stab_demangle_class
   PARAMS ((struct stab_demangle_info *, const char **, const char **));
 static boolean stab_demangle_args
@@ -3540,7 +3758,7 @@ static void
 stab_bad_demangle (s)
      const char *s;
 {
-  fprintf (stderr, "bad mangled name `%s'\n", s);
+  fprintf (stderr, _("bad mangled name `%s'\n"), s);
 }
 
 /* Get a count from a stab string.  */
@@ -3636,7 +3854,7 @@ stab_demangle_argtypes (dhandle, info, physname, pvarargs)
   minfo.typestrings = NULL;
 
   if (minfo.args == NULL)
-    fprintf (stderr, "no argument types in mangled string\n");
+    fprintf (stderr, _("no argument types in mangled string\n"));
 
   *pvarargs = minfo.varargs;
   return minfo.args;
@@ -3837,7 +4055,7 @@ stab_demangle_signature (minfo, pp)
          /* Template.  */
          if (hold == NULL)
            hold = *pp;
-         if (! stab_demangle_template (minfo, pp)
+         if (! stab_demangle_template (minfo, pp, (char **) NULL)
              || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
            return false;
          hold = NULL;
@@ -3946,10 +4164,21 @@ stab_demangle_qualified (minfo, pp, ptype)
        ++*pp;
       if (**pp == 't')
        {
-         /* FIXME: I don't know how to handle the ptype != NULL case
-             here.  */
-         if (! stab_demangle_template (minfo, pp))
+         char *name;
+
+         if (! stab_demangle_template (minfo, pp,
+                                       ptype != NULL ? &name : NULL))
            return false;
+
+         if (ptype != NULL)
+           {
+             context = stab_find_tagged_type (minfo->dhandle, minfo->info,
+                                              name, strlen (name),
+                                              DEBUG_KIND_CLASS);
+             free (name);
+             if (context == DEBUG_TYPE_NULL)
+               return false;
+           }
        }
       else
        {
@@ -4007,7 +4236,7 @@ stab_demangle_qualified (minfo, pp, ptype)
 
              if (context == DEBUG_TYPE_NULL)
                {
-         /* We have to fall back on finding the type by name.
+                 /* We have to fall back on finding the type by name.
                      If there are more types to come, then this must
                      be a class.  Otherwise, it could be anything.  */
 
@@ -4045,12 +4274,14 @@ stab_demangle_qualified (minfo, pp, ptype)
   return true;
 }
 
-/* Demangle a template.  */
+/* Demangle a template.  If PNAME is not NULL, this sets *PNAME to a
+   string representation of the template.  */
 
 static boolean
-stab_demangle_template (minfo, pp)
+stab_demangle_template (minfo, pp, pname)
      struct stab_demangle_info *minfo;
      const char **pp;
+     char **pname;
 {
   const char *orig;
   unsigned int r, i;
@@ -4153,7 +4384,7 @@ stab_demangle_template (minfo, pp)
                  done = true;
                  break;
                default:
-                 /* Assume it's a uder defined integral type.  */
+                 /* Assume it's a user defined integral type.  */
                  integralp = true;
                  done = true;
                  break;
@@ -4224,6 +4455,37 @@ stab_demangle_template (minfo, pp)
        }
     }
 
+  /* We can translate this to a string fairly easily by invoking the
+     regular demangling routine.  */
+  if (pname != NULL)
+    {
+      char *s1, *s2, *s3, *s4;
+
+      s1 = savestring (orig, *pp - orig);
+
+      s2 = concat ("NoSuchStrinG__", s1, (const char *) NULL);
+
+      free (s1);
+
+      s3 = cplus_demangle (s2, DMGL_ANSI);
+
+      free (s2);
+
+      if (s3 != NULL)
+       s4 = strstr (s3, "::NoSuchStrinG");
+      if (s3 == NULL || s4 == NULL)
+       {
+         stab_bad_demangle (orig);
+         if (s3 != NULL)
+           free (s3);
+         return false;
+       }
+
+      *pname = savestring (s3, s4 - s3);
+
+      free (s3);
+    }
+
   return true;
 }
 
@@ -4838,6 +5100,7 @@ stab_demangle_fund_type (minfo, pp, ptype)
 
            name = savestring (hold, *pp - hold);
            *ptype = debug_find_named_type (minfo->dhandle, name);
+           free (name);
            if (*ptype == DEBUG_TYPE_NULL)
              {
                /* FIXME: It is probably incorrect to assume that
@@ -4845,16 +5108,30 @@ stab_demangle_fund_type (minfo, pp, ptype)
                *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
                                                hold, *pp - hold,
                                                DEBUG_KIND_ILLEGAL);
+               if (*ptype == DEBUG_TYPE_NULL)
+                 return false;
              }
-           free (name);
          }
       }
       break;
 
     case 't':
-      if (! stab_demangle_template (minfo, pp))
-       return false;
-      abort ();
+      {
+       char *name;
+
+       if (! stab_demangle_template (minfo, pp,
+                                     ptype != NULL ? &name : NULL))
+         return false;
+       if (ptype != NULL)
+         {
+           *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
+                                           name, strlen (name),
+                                           DEBUG_KIND_CLASS);
+           free (name);
+           if (*ptype == DEBUG_TYPE_NULL)
+             return false;
+         }
+      }
       break;
 
     default:
This page took 0.046948 seconds and 4 git commands to generate.