Tidy up formatting of --help output.
[deliverable/binutils-gdb.git] / binutils / stabs.c
index 76b221b0f4acb85c4883795d06b17d2e2172d4ab..bbc06320e747d327a3437d01357ba41bb68ced5d 100644 (file)
@@ -1,5 +1,6 @@
 /* stabs.c -- Parse stabs debugging information
-   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>.
 
    This file is part of GNU Binutils.
    trying to identify the correct address for anything.  */
 
 #include <stdio.h>
-#include <ctype.h>
 
 #include "bfd.h"
 #include "bucomm.h"
 #include "libiberty.h"
+#include "safe-ctype.h"
 #include "demangle.h"
 #include "debug.h"
 #include "budbg.h"
+#include "filenames.h"
 
 /* Meaningless definition needs by aout64.h.  FIXME.  */
 #define BYTES_IN_WORD 4
 
 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 +77,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 +99,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 +193,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));
@@ -193,7 +213,7 @@ static debug_type stab_find_tagged_type
   PARAMS ((PTR, struct stab_handle *, const char *, int,
           enum debug_type_kind));
 static debug_type *stab_demangle_argtypes
-  PARAMS ((PTR, struct stab_handle *, const char *));
+  PARAMS ((PTR, struct stab_handle *, const char *, boolean *));
 
 /* Save a string in memory.  */
 
@@ -228,7 +248,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.  */
@@ -280,11 +307,11 @@ parse_number (pp, poverflow)
          int d;
 
          d = *p++;
-         if (isdigit ((unsigned char) d))
+         if (ISDIGIT (d))
            d -= '0';
-         else if (isupper ((unsigned char) d))
+         else if (ISUPPER (d))
            d -= 'A';
-         else if (islower ((unsigned char) d))
+         else if (ISLOWER (d))
            d -= 'a';
          else
            break;
@@ -313,7 +340,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 +351,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 +361,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)
-     PTR dhandle;
+start_stab (dhandle, abfd, sections, syms, symcount)
+     PTR dhandle ATTRIBUTE_UNUSED;
+     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 +403,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 +422,6 @@ finish_stab (dhandle, handle)
        return false;
     }
 
-  if (info->pending)
-    fprintf (stderr, "Left over pending variables in stabs debugging\n");
-
   return true;
 }
 
@@ -405,6 +438,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 +483,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 +522,56 @@ 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')
+      /* This always ends a function.  */
+      if (info->within_function)
        {
-         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)
-       {
-         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 (IS_ABSOLUTE_PATH (string))
+           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 +582,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 +596,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 +616,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 +660,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.  */
@@ -604,11 +695,10 @@ parse_stab (dhandle, handle, type, desc, value, string)
     case N_OBJ:
     case N_ENDM:
     case N_MAIN:
+    case N_WARNING:
       break;
     }
 
-  info->last_type = type;
-
   return true;
 }
 
@@ -628,6 +718,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 +767,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;
        }
     }
@@ -690,7 +781,7 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
     }
 
   ++p;
-  if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+  if (ISDIGIT (*p) || *p == '(' || *p == '-')
     type = 'l';
   else
     type = *p++;
@@ -788,15 +879,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
@@ -827,9 +937,13 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
          dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
                                   (debug_type **) NULL);
          if (dtype != DEBUG_TYPE_NULL)
-           dtype = debug_make_pointer_type (dhandle,
-                                            debug_make_function_type (dhandle,
-                                                                      dtype));
+           {
+             debug_type ftype;
+
+             ftype = debug_make_function_type (dhandle, dtype,
+                                               (debug_type *) NULL, false);
+             dtype = debug_make_pointer_type (dhandle, ftype);
+           }
        }
       if (dtype == DEBUG_TYPE_NULL)
        return false;
@@ -937,6 +1051,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;
@@ -944,21 +1063,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)
        {
@@ -1059,10 +1180,12 @@ 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".  */
-  if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-')
+  if (! ISDIGIT (**pp) && **pp != '(' && **pp != '-')
     {
       /* 'typenums=' not present, type is anonymous.  Read and return
         the definition, but don't put it in the type vector.  */
@@ -1105,7 +1228,7 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
          const char *p = *pp + 1;
          const char *attr;
 
-         if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+         if (ISDIGIT (*p) || *p == '(' || *p == '-')
            {
              /* Member type.  */
              break;
@@ -1128,6 +1251,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;
@@ -1170,7 +1294,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;
          }
@@ -1183,20 +1307,36 @@ 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;
              }
          }
 
+       /* 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;
@@ -1278,7 +1418,8 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
       dtype = (debug_make_function_type
               (dhandle,
                parse_stab_type (dhandle, info, (const char *) NULL, pp,
-                                (debug_type **) NULL)));
+                                (debug_type **) NULL),
+               (debug_type *) NULL, false));
       break;
 
     case 'k':
@@ -1348,7 +1489,8 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
            }
          ++*pp;
          dtype = debug_make_method_type (dhandle, return_type,
-                                         DEBUG_TYPE_NULL, NULL);
+                                         DEBUG_TYPE_NULL,
+                                         (debug_type *) NULL, false);
        }
       else
        {
@@ -1357,6 +1499,7 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
          debug_type *args;
          unsigned int n;
          unsigned int alloc;
+         boolean varargs;
 
          domain = parse_stab_type (dhandle, info, (const char *) NULL,
                                    pp, (debug_type **) NULL);
@@ -1402,30 +1545,22 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
            }
          ++*pp;
 
-         /* If the last type is void, then this function does not
-            take a variable number of arguments.  If the last is not
-            void, then it does.  */
-         if (n > 0
-             && debug_get_type_kind (dhandle, args[n - 1]) == DEBUG_KIND_VOID)
-           --n;
+         /* If the last type is not void, then this function takes a
+            variable number of arguments.  Otherwise, we must strip
+            the void type.  */
+         if (n == 0
+             || debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID)
+           varargs = true;
          else
            {
-             if (n + 1 >= alloc)
-               {
-                 alloc += 10;
-                 args = ((debug_type *)
-                         xrealloc ((PTR) args, alloc * sizeof *args));
-               }
-
-             args[n] = debug_make_ellipsis_type (dhandle);
-             if (args[n] == DEBUG_TYPE_NULL)
-               return DEBUG_TYPE_NULL;
-             ++n;
+             --n;
+             varargs = false;
            }
 
          args[n] = DEBUG_TYPE_NULL;
 
-         dtype = debug_make_method_type (dhandle, return_type, domain, args);
+         dtype = debug_make_method_type (dhandle, return_type, domain, args,
+                                         varargs);
        }
       break;
 
@@ -1495,7 +1630,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;
@@ -1622,7 +1757,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)
@@ -1632,6 +1767,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)
@@ -1669,15 +1809,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 == (bfd_signed_vma) 0xffffffff)
+           return debug_make_int_type (dhandle, 4, true);
+#ifdef BFD64
+         else if (n3 == ((((bfd_signed_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);
@@ -1685,6 +1828,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
        }
     }
 
@@ -1702,7 +1849,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);
     }
 
@@ -2029,7 +2176,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;
        }
@@ -2047,7 +2194,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;
        }
@@ -2239,13 +2386,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;
     }
@@ -2325,7 +2472,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;
        }
@@ -2493,12 +2640,14 @@ 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;
          bfd_vma voffset;
          debug_type context;
          const char *physname;
+         boolean varargs;
 
          if (look_ahead_type != DEBUG_TYPE_NULL)
            {
@@ -2527,6 +2676,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 +2728,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 +2737,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 +2748,6 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
                }
              ++*pp;
              voffset &= 0x7fffffff;
-             voffset += 2;
 
              if (**pp == ';' || *pp == '\0')
                {
@@ -2617,6 +2766,7 @@ parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
                    if (**pp == ':')
                      {
                        /* g++ version 1 overloaded methods.  */
+                       context = DEBUG_TYPE_NULL;
                      }
                    else
                      {
@@ -2638,6 +2788,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 +2805,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) != 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
            {
@@ -2759,11 +2908,12 @@ parse_stab_argtypes (dhandle, info, class_type, fieldname, tagname,
   boolean is_constructor;
   boolean is_destructor;
   debug_type *args;
+  boolean varargs;
 
   /* Constructors are sometimes handled specially.  */
   is_full_physname_constructor = ((argtypes[0] == '_'
                                   && argtypes[1] == '_'
-                                  && (isdigit ((unsigned char) argtypes[2])
+                                  && (ISDIGIT (argtypes[2])
                                       || argtypes[2] == 'Q'
                                       || argtypes[2] == 't'))
                                  || strncmp (argtypes, "__ct", 4) == 0);
@@ -2818,7 +2968,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);
@@ -2843,18 +2993,20 @@ 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;
-      return debug_make_method_type (dhandle, return_type, class_type, args);
+      return debug_make_method_type (dhandle, return_type, class_type, args,
+                                    false);
     }
 
-  args = stab_demangle_argtypes (dhandle, info, *pphysname);
+  args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs);
   if (args == NULL)
     return DEBUG_TYPE_NULL;
 
-  return debug_make_method_type (dhandle, return_type, class_type, args);
+  return debug_make_method_type (dhandle, return_type, class_type, args,
+                                varargs);
 }
 
 /* The tail end of stabs for C++ classes that contain a virtual function
@@ -2949,6 +3101,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;
@@ -2965,8 +3119,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 DEBUG_TYPE_NULL;
+  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 DEBUG_TYPE_NULL;
+       }
+      *pp = p;
+    }
+  else
+    {
+      index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+                                   (debug_type **) NULL);
+    }
+
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -2976,7 +3149,7 @@ parse_stab_array_type (dhandle, info, pp, stringp)
 
   adjustable = false;
 
-  if (! isdigit ((unsigned char) **pp) && **pp != '-')
+  if (! ISDIGIT (**pp) && **pp != '-')
     {
       ++*pp;
       adjustable = true;
@@ -2986,11 +3159,11 @@ parse_stab_array_type (dhandle, info, pp, stringp)
   if (**pp != ';')
     {
       bad_stab (orig);
-      return false;
+      return DEBUG_TYPE_NULL;
     }
   ++*pp;
 
-  if (! isdigit ((unsigned char) **pp) && **pp != '-')
+  if (! ISDIGIT (**pp) && **pp != '-')
     {
       ++*pp;
       adjustable = true;
@@ -3000,14 +3173,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)
     {
@@ -3019,26 +3192,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;
@@ -3046,7 +3236,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
@@ -3061,13 +3251,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
@@ -3146,12 +3369,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;
     }
 
@@ -3207,7 +3430,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;
@@ -3238,7 +3461,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)
@@ -3492,6 +3715,8 @@ struct stab_demangle_info
   struct stab_handle *info;
   /* The array of arguments we are building.  */
   debug_type *args;
+  /* Whether the method takes a variable number of arguments.  */
+  boolean varargs;
   /* The array of types we have remembered.  */
   struct stab_demangle_typestring *typestrings;
   /* The number of typestrings.  */
@@ -3513,11 +3738,12 @@ 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
-  PARAMS ((struct stab_demangle_info *, const char **, debug_type **));
+  PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
+          boolean *));
 static boolean stab_demangle_arg
   PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
           unsigned int *, unsigned int *));
@@ -3534,7 +3760,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.  */
@@ -3546,7 +3772,7 @@ stab_demangle_count (pp)
   unsigned int count;
 
   count = 0;
-  while (isdigit ((unsigned char) **pp))
+  while (ISDIGIT (**pp))
     {
       count *= 10;
       count += **pp - '0';
@@ -3563,12 +3789,12 @@ stab_demangle_get_count (pp, pi)
      const char **pp;
      unsigned int *pi;
 {
-  if (! isdigit ((unsigned char) **pp))
+  if (! ISDIGIT (**pp))
     return false;
 
   *pi = **pp - '0';
   ++*pp;
-  if (isdigit ((unsigned char) **pp))
+  if (ISDIGIT (**pp))
     {
       unsigned int count;
       const char *p;
@@ -3581,7 +3807,7 @@ stab_demangle_get_count (pp, pi)
          count += *p - '0';
          ++p;
        }
-      while (isdigit ((unsigned char) *p));
+      while (ISDIGIT (*p));
       if (*p == '_')
        {
          *pp = p + 1;
@@ -3596,16 +3822,18 @@ stab_demangle_get_count (pp, pi)
    terminated array of argument types.  */
 
 static debug_type *
-stab_demangle_argtypes (dhandle, info, physname)
+stab_demangle_argtypes (dhandle, info, physname, pvarargs)
      PTR dhandle;
      struct stab_handle *info;
      const char *physname;
+     boolean *pvarargs;
 {
   struct stab_demangle_info minfo;
 
   minfo.dhandle = dhandle;
   minfo.info = info;
   minfo.args = NULL;
+  minfo.varargs = false;
   minfo.typestring_alloc = 10;
   minfo.typestrings = ((struct stab_demangle_typestring *)
                       xmalloc (minfo.typestring_alloc
@@ -3628,8 +3856,9 @@ stab_demangle_argtypes (dhandle, info, physname)
   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;
 
  error_return:
@@ -3673,7 +3902,7 @@ stab_demangle_prefix (minfo, pp)
     scan += i - 2;
 
   if (scan == *pp
-      && (isdigit ((unsigned char) scan[2])
+      && (ISDIGIT (scan[2])
          || scan[2] == 'Q'
          || scan[2] == 't'))
     {
@@ -3682,7 +3911,7 @@ stab_demangle_prefix (minfo, pp)
       return true;
     }
   else if (scan == *pp
-          && ! isdigit ((unsigned char) scan[2])
+          && ! ISDIGIT (scan[2])
           && scan[2] != 't')
     {
       /* Look for the `__' that separates the prefix from the
@@ -3820,7 +4049,7 @@ stab_demangle_signature (minfo, pp)
          hold = NULL;
          func_done = true;
          ++*pp;
-         if (! stab_demangle_args (minfo, pp, &minfo->args))
+         if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
            return false;
          break;
 
@@ -3828,7 +4057,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;
@@ -3848,7 +4077,7 @@ stab_demangle_signature (minfo, pp)
          /* Assume we have stumbled onto the first outermost function
             argument token, and start processing args.  */
          func_done = true;
-         if (! stab_demangle_args (minfo, pp, &minfo->args))
+         if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
            return false;
          break;
        }
@@ -3856,7 +4085,7 @@ stab_demangle_signature (minfo, pp)
       if (expect_func)
        {
          func_done = true;
-         if (! stab_demangle_args (minfo, pp, &minfo->args))
+         if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
            return false;
        }
     }
@@ -3867,7 +4096,7 @@ stab_demangle_signature (minfo, pp)
         bar__3fooi is 'foo::bar(int)'.  We get here when we find the
         first case, and need to ensure that the '(void)' gets added
         to the current declp.  */
-      if (! stab_demangle_args (minfo, pp, &minfo->args))
+      if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
        return false;
     }
 
@@ -3897,13 +4126,13 @@ stab_demangle_qualified (minfo, pp, ptype)
         preceded by an underscore (to distinguish it from the <= 9
         case) and followed by an underscore.  */
       p = *pp + 2;
-      if (! isdigit ((unsigned char) *p) || *p == '0')
+      if (! ISDIGIT (*p) || *p == '0')
        {
          stab_bad_demangle (orig);
          return false;
        }
       qualifiers = atoi (p);
-      while (isdigit ((unsigned char) *p))
+      while (ISDIGIT (*p))
        ++p;
       if (*p != '_')
        {
@@ -3937,10 +4166,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
        {
@@ -3998,7 +4238,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.  */
 
@@ -4036,12 +4276,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;
@@ -4144,7 +4386,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;
@@ -4155,7 +4397,7 @@ stab_demangle_template (minfo, pp)
            {
              if (**pp == 'm')
                ++*pp;
-             while (isdigit ((unsigned char) **pp))
+             while (ISDIGIT (**pp))
                ++*pp;
            }
          else if (charp)
@@ -4186,18 +4428,18 @@ stab_demangle_template (minfo, pp)
            {
              if (**pp == 'm')
                ++*pp;
-             while (isdigit ((unsigned char) **pp))
+             while (ISDIGIT (**pp))
                ++*pp;
              if (**pp == '.')
                {
                  ++*pp;
-                 while (isdigit ((unsigned char) **pp))
+                 while (ISDIGIT (**pp))
                    ++*pp;
                }
              if (**pp == 'e')
                {
                  ++*pp;
-                 while (isdigit ((unsigned char) **pp))
+                 while (ISDIGIT (**pp))
                    ++*pp;
                }
            }
@@ -4215,6 +4457,46 @@ 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 = NULL;
+      char *from, *to;
+
+      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;
+       }
+
+      /* 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);
+    }
+
   return true;
 }
 
@@ -4222,7 +4504,7 @@ stab_demangle_template (minfo, pp)
 
 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;
 {
@@ -4250,10 +4532,11 @@ stab_demangle_class (minfo, pp, pstart)
    is set to a NULL terminated array holding the arguments.  */
 
 static boolean
-stab_demangle_args (minfo, pp, pargs)
+stab_demangle_args (minfo, pp, pargs, pvarargs)
      struct stab_demangle_info *minfo;
      const char **pp;
      debug_type **pargs;
+     boolean *pvarargs;
 {
   const char *orig;
   unsigned int alloc, count;
@@ -4262,7 +4545,10 @@ stab_demangle_args (minfo, pp, pargs)
 
   alloc = 10;
   if (pargs != NULL)
-    *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
+    {
+      *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
+      *pvarargs = false;
+    }
   count = 0;
 
   while (**pp != '_' && **pp != '\0' && **pp != 'e')
@@ -4313,32 +4599,16 @@ stab_demangle_args (minfo, pp, pargs)
        }
     }
 
+  if (pargs != NULL)
+    (*pargs)[count] = DEBUG_TYPE_NULL;
+
   if (**pp == 'e')
     {
       if (pargs != NULL)
-       {
-         debug_type type;
-
-         type = debug_make_ellipsis_type (minfo->dhandle);
-         if (type == DEBUG_TYPE_NULL)
-           return false;
-
-         if (count + 1 >= alloc)
-           {
-             alloc += 10;
-             *pargs = ((debug_type *)
-                       xrealloc (*pargs, alloc * sizeof **pargs));
-           }
-         (*pargs)[count] = type;
-         ++count;
-       }
-
+       *pvarargs = true;
       ++*pp;
     }
 
-  if (pargs != NULL)
-    (*pargs)[count] = DEBUG_TYPE_NULL;
-
   return true;
 }
 
@@ -4422,7 +4692,7 @@ stab_demangle_type (minfo, pp, ptype)
        high = 0;
        while (**pp != '\0' && **pp != '_')
          {
-           if (! isdigit ((unsigned char) **pp))
+           if (! ISDIGIT (**pp))
              {
                stab_bad_demangle (orig);
                return false;
@@ -4478,30 +4748,44 @@ stab_demangle_type (minfo, pp, ptype)
 
     case 'F':
       /* A function.  */
-      ++*pp;
-      /* FIXME: We should pick up the argument types.  */
-      if (! stab_demangle_args (minfo, pp, (debug_type **) NULL))
-       return false;
-      if (**pp != '_')
-       {
-         /* cplus_demangle will accept a function without a return
-             type, but I don't know when that will happen, or what to
-             do if it does.  */
-         stab_bad_demangle (orig);
+      {
+       debug_type *args;
+       boolean varargs;
+
+       ++*pp;
+       if (! stab_demangle_args (minfo, pp,
+                                 (ptype == NULL
+                                  ? (debug_type **) NULL
+                                  : &args),
+                                 (ptype == NULL
+                                  ? (boolean *) NULL
+                                  : &varargs)))
          return false;
-       }
-      ++*pp;
-      if (! stab_demangle_type (minfo, pp, ptype))
-       return false;
-      if (ptype != NULL)
-       *ptype = debug_make_function_type (minfo->dhandle, *ptype);
+       if (**pp != '_')
+         {
+           /* cplus_demangle will accept a function without a return
+              type, but I don't know when that will happen, or what
+              to do if it does.  */
+           stab_bad_demangle (orig);
+           return false;
+         }
+       ++*pp;
+       if (! stab_demangle_type (minfo, pp, ptype))
+         return false;
+       if (ptype != NULL)
+         *ptype = debug_make_function_type (minfo->dhandle, *ptype, args,
+                                            varargs);
+
+      }
       break;
 
     case 'M':
     case 'O':
       {
        boolean memberp, constp, volatilep;
+       debug_type class_type = DEBUG_TYPE_NULL;
        debug_type *args;
+       boolean varargs;
        unsigned int n;
        const char *name;
 
@@ -4509,21 +4793,43 @@ stab_demangle_type (minfo, pp, ptype)
        constp = false;
        volatilep = false;
        args = NULL;
+       varargs = false;
 
        ++*pp;
-       if (! isdigit ((unsigned char) **pp))
+       if (ISDIGIT (**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;
+             }
+         }
+       else if (**pp == 'Q')
+         {
+           if (! stab_demangle_qualified (minfo, pp,
+                                          (ptype == NULL
+                                           ? (debug_type *) NULL
+                                           : &class_type)))
+             return false;
          }
-       n = stab_demangle_count (pp);
-       if (strlen (*pp) < n)
+       else
          {
            stab_bad_demangle (orig);
            return false;
          }
-       name = *pp;
-       *pp += n;
 
        if (memberp)
          {
@@ -4546,7 +4852,10 @@ stab_demangle_type (minfo, pp, ptype)
            if (! stab_demangle_args (minfo, pp,
                                      (ptype == NULL
                                       ? (debug_type **) NULL
-                                      : &args)))
+                                      : &args),
+                                     (ptype == NULL
+                                      ? (boolean *) NULL
+                                      : &varargs)))
              return false;
          }
 
@@ -4562,14 +4871,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);
@@ -4578,7 +4879,7 @@ stab_demangle_type (minfo, pp, ptype)
                /* FIXME: We have no way to record constp or
                    volatilep.  */
                *ptype = debug_make_method_type (minfo->dhandle, *ptype,
-                                                class_type, args);
+                                                class_type, args, varargs);
              }
          }
       }
@@ -4805,7 +5106,7 @@ stab_demangle_fund_type (minfo, pp, ptype)
 
     case 'G':
       ++*pp;
-      if (! isdigit ((unsigned char) **pp))
+      if (! ISDIGIT (**pp))
        {
          stab_bad_demangle (orig);
          return false;
@@ -4824,6 +5125,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
@@ -4831,16 +5133,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.050311 seconds and 4 git commands to generate.