This commit was manufactured by cvs2svn to create branch
[external/binutils.git] / binutils / stabs.c
index 48161d0..7af10ef 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, 2002, 2003, 2004
+   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"
-
-/* Meaningless definition needs by aout64.h.  FIXME.  */
-#define BYTES_IN_WORD 4
-
+#include "filenames.h"
 #include "aout/aout64.h"
 #include "aout/stab_gnu.h"
 
 
 struct stab_handle
 {
-  /* 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 BFD.  */
+  bfd *abfd;
+  /* TRUE if this is stabs in sections.  */
+  bfd_boolean sections;
+  /* 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;
@@ -64,13 +70,19 @@ struct stab_handle
   int gcc_compiled;
   /* Whether an N_OPT symbol was seen that was not generated by gcc,
      so that we can detect the SunPRO compiler.  */
-  boolean n_opt_found;
+  bfd_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;
+  bfd_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.  */
@@ -83,6 +95,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.  */
+  bfd_boolean self_crossref;
 };
 
 /* A list of these structures is used to hold pending variable
@@ -132,64 +147,70 @@ struct stab_tag
   debug_type type;
 };
 
-static char *savestring PARAMS ((const char *, int));
-static bfd_vma parse_number PARAMS ((const char **, boolean *));
-static void bad_stab PARAMS ((const char *));
-static void warn_stab PARAMS ((const char *, const char *));
-static boolean parse_stab_string
-  PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *));
+static char *savestring (const char *, int);
+static bfd_vma parse_number (const char **, bfd_boolean *);
+static void bad_stab (const char *);
+static void warn_stab (const char *, const char *);
+static bfd_boolean parse_stab_string
+  (void *, struct stab_handle *, int, int, bfd_vma, const char *);
 static debug_type parse_stab_type
-  PARAMS ((PTR, struct stab_handle *, const char *, const char **,
-          debug_type **));
-static boolean parse_stab_type_number
-  PARAMS ((const char **, int *));
+  (void *, struct stab_handle *, const char *, const char **, debug_type **);
+static bfd_boolean parse_stab_type_number (const char **, int *);
 static debug_type parse_stab_range_type
-  PARAMS ((PTR, struct stab_handle *, const char *, const char **,
-          const int *));
-static debug_type parse_stab_sun_builtin_type PARAMS ((PTR, const char **));
-static debug_type parse_stab_sun_floating_type
-  PARAMS ((PTR, const char **));
-static debug_type parse_stab_enum_type PARAMS ((PTR, const char **));
+  (void *, struct stab_handle *, const char *, const char **, const int *);
+static debug_type parse_stab_sun_builtin_type (void *, const char **);
+static debug_type parse_stab_sun_floating_type (void *, const char **);
+static debug_type parse_stab_enum_type (void *, const char **);
 static debug_type parse_stab_struct_type
-  PARAMS ((PTR, struct stab_handle *, const char **, boolean, const int *));
-static boolean parse_stab_baseclasses
-  PARAMS ((PTR, struct stab_handle *, const char **, debug_baseclass **));
-static boolean parse_stab_struct_fields
-  PARAMS ((PTR, struct stab_handle *, const char **, debug_field **,
-          boolean *));
-static boolean parse_stab_cpp_abbrev
-  PARAMS ((PTR, struct stab_handle *, const char **, debug_field *));
-static boolean parse_stab_one_struct_field
-  PARAMS ((PTR, struct stab_handle *, const char **, const char *,
-          debug_field *, boolean *));
-static boolean parse_stab_members
-  PARAMS ((PTR, struct stab_handle *, const char **, debug_method **));
-static boolean parse_stab_tilde_field
-  PARAMS ((PTR, struct stab_handle *, const char **, const int *,
-          debug_type *, boolean *));
+  (void *, struct stab_handle *, const char *, const char **,
+   bfd_boolean, const int *);
+static bfd_boolean parse_stab_baseclasses
+  (void *, struct stab_handle *, const char **, debug_baseclass **);
+static bfd_boolean parse_stab_struct_fields
+  (void *, struct stab_handle *, const char **, debug_field **, bfd_boolean *);
+static bfd_boolean parse_stab_cpp_abbrev
+  (void *, struct stab_handle *, const char **, debug_field *);
+static bfd_boolean parse_stab_one_struct_field
+  (void *, struct stab_handle *, const char **, const char *,
+   debug_field *, bfd_boolean *);
+static bfd_boolean parse_stab_members
+  (void *, struct stab_handle *, const char *, const char **, const int *,
+   debug_method **);
+static debug_type parse_stab_argtypes
+  (void *, struct stab_handle *, debug_type, const char *, const char *,
+   debug_type, const char *, bfd_boolean, bfd_boolean, const char **);
+static bfd_boolean parse_stab_tilde_field
+  (void *, struct stab_handle *, const char **, const int *, debug_type *,
+   bfd_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 const char *pop_bincl PARAMS ((struct stab_handle *));
-static boolean stab_record_variable
-  PARAMS ((PTR, struct stab_handle *, const char *, debug_type,
-          enum debug_var_kind, bfd_vma));
-static boolean stab_emit_pending_vars PARAMS ((PTR, struct stab_handle *));
-static debug_type *stab_find_slot
-  PARAMS ((struct stab_handle *, const int *));
-static debug_type stab_find_type
-  PARAMS ((PTR, struct stab_handle *, const int *));
-static boolean stab_record_type
-  PARAMS ((PTR, struct stab_handle *, const int *, debug_type));
+  (void *, struct stab_handle *, const char **, bfd_boolean);
+static void push_bincl (struct stab_handle *, const char *, bfd_vma);
+static const char *pop_bincl (struct stab_handle *);
+static bfd_boolean find_excl (struct stab_handle *, const char *, bfd_vma);
+static bfd_boolean stab_record_variable
+  (void *, struct stab_handle *, const char *, debug_type,
+   enum debug_var_kind, bfd_vma);
+static bfd_boolean stab_emit_pending_vars (void *, struct stab_handle *);
+static debug_type *stab_find_slot (struct stab_handle *, const int *);
+static debug_type stab_find_type (void *, struct stab_handle *, const int *);
+static bfd_boolean stab_record_type
+  (void *, struct stab_handle *, const int *, debug_type);
 static debug_type stab_xcoff_builtin_type
-  PARAMS ((PTR, struct stab_handle *, int));
+  (void *, struct stab_handle *, int);
+static debug_type stab_find_tagged_type
+  (void *, struct stab_handle *, const char *, int, enum debug_type_kind);
+static debug_type *stab_demangle_argtypes
+  (void *, struct stab_handle *, const char *, bfd_boolean *, unsigned int);
+static debug_type *stab_demangle_v3_argtypes
+  (void *, struct stab_handle *, const char *, bfd_boolean *);
+static debug_type stab_demangle_v3_arg
+  (void *, struct stab_handle *, struct demangle_component *, debug_type,
+   bfd_boolean *);
 
 /* Save a string in memory.  */
 
 static char *
-savestring (start, len)
-     const char *start;
-     int len;
+savestring (const char *start, int len)
 {
   char *ret;
 
@@ -202,45 +223,48 @@ savestring (start, len)
 /* Read a number from a string.  */
 
 static bfd_vma
-parse_number (pp, poverflow)
-     const char **pp;
-     boolean *poverflow;
+parse_number (const char **pp, bfd_boolean *poverflow)
 {
   unsigned long ul;
   const char *orig;
 
   if (poverflow != NULL)
-    *poverflow = false;
+    *poverflow = FALSE;
 
   orig = *pp;
 
   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.  */
-
   if (sizeof (bfd_vma) > sizeof (unsigned long))
     {
       const char *p;
-      boolean neg;
+      bfd_boolean neg;
       int base;
       bfd_vma over, lastdig;
-      boolean overflow;
+      bfd_boolean overflow;
       bfd_vma v;
 
       /* Our own version of strtoul, for a bfd_vma.  */
-
       p = orig;
 
-      neg = false;
+      neg = FALSE;
       if (*p == '+')
        ++p;
       else if (*p == '-')
        {
-         neg = true;
+         neg = TRUE;
          ++p;
        }
 
@@ -262,18 +286,18 @@ parse_number (pp, poverflow)
       over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base;
       lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base;
 
-      overflow = false;
+      overflow = FALSE;
       v = 0;
       while (1)
        {
          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;
@@ -283,7 +307,7 @@ parse_number (pp, poverflow)
 
          if (v > over || (v == over && (bfd_vma) d > lastdig))
            {
-             overflow = true;
+             overflow = TRUE;
              break;
            }
        }
@@ -298,11 +322,10 @@ parse_number (pp, poverflow)
 
   /* If we get here, the number is too large to represent in a
      bfd_vma.  */
-
   if (poverflow != NULL)
-    *poverflow = true;
+    *poverflow = TRUE;
   else
-    warn_stab (orig, "numeric overflow");
+    warn_stab (orig, _("numeric overflow"));
 
   return 0;
 }
@@ -310,83 +333,113 @@ parse_number (pp, poverflow)
 /* Give an error for a bad stab string.  */
 
 static void
-bad_stab (p)
-     const char *p;
+bad_stab (const char *p)
 {
-  fprintf (stderr, "Bad stab: %s\n", p);
+  fprintf (stderr, _("Bad stab: %s\n"), p);
 }
 
 /* Warn about something in a stab string.  */
 
 static void
-warn_stab (p, err)
-     const char *p;
-     const char *err;
+warn_stab (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;
-     boolean sections;
+void *
+start_stab (void *dhandle ATTRIBUTE_UNUSED, bfd *abfd, bfd_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;
-  return (PTR) ret;
+  ret->function_end = (bfd_vma) -1;
+  return (void *) ret;
 }
 
 /* When we have processed all the stabs information, we need to go
    through and fill in all the undefined tags.  */
 
-boolean
-finish_stab (dhandle, handle)
-     PTR dhandle;
-     PTR handle;
+bfd_boolean
+finish_stab (void *dhandle, void *handle)
 {
   struct stab_handle *info = (struct stab_handle *) handle;
   struct stab_tag *st;
 
   if (info->within_function)
     {
-      if (! debug_end_function (dhandle, (bfd_vma) -1))
-       return false;
-      info->within_function = false;
+      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)
     {
-      st->slot = debug_make_undefined_tagged_type (dhandle, st->name,
-                                                  st->kind);
+      enum debug_type_kind kind;
+
+      kind = st->kind;
+      if (kind == DEBUG_KIND_ILLEGAL)
+       kind = DEBUG_KIND_STRUCT;
+      st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
       if (st->slot == DEBUG_TYPE_NULL)
-       return false;
+       return FALSE;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Handle a single stabs symbol.  */
 
-boolean
-parse_stab (dhandle, handle, type, desc, value, string)
-     PTR dhandle;
-     PTR handle;
-     int type;
-     int desc;
-     bfd_vma value;
-     const char *string;
+bfd_boolean
+parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
+           const char *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:
@@ -400,8 +453,8 @@ parse_stab (dhandle, handle, type, desc, value, string)
 
       if (! info->within_function)
        {
-         fprintf (stderr, "N_LBRAC not within function\n");
-         return false;
+         fprintf (stderr, _("N_LBRAC not within function\n"));
+         return FALSE;
        }
 
       /* Start an inner lexical block.  */
@@ -409,11 +462,11 @@ parse_stab (dhandle, handle, type, desc, value, string)
                               (value
                                + info->file_start_offset
                                + info->function_start_offset)))
-       return false;
+       return FALSE;
 
       /* Emit any pending variable definitions.  */
       if (! stab_emit_pending_vars (dhandle, info))
-       return false;
+       return FALSE;
 
       ++info->block_depth;
       break;
@@ -427,132 +480,147 @@ parse_stab (dhandle, handle, type, desc, value, string)
          if we do, we probably need to emit them before closing the
          block.  */
       if (! stab_emit_pending_vars (dhandle, info))
-       return false;
+       return FALSE;
 
       /* End an inner lexical block.  */
       if (! debug_end_block (dhandle,
                             (value
                              + info->file_start_offset
                              + info->function_start_offset)))
-       return false;
+       return FALSE;
 
       --info->block_depth;
-      if (info->block_depth == 0)
+      if (info->block_depth < 0)
        {
-         info->within_function = false;
-         if (! debug_end_function (dhandle,
-                                   (value
-                                    + info->file_start_offset
-                                    + info->function_start_offset)))
-           return false;
+         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, (bfd_vma) -1))
-               return false;
-             info->within_function = false;
-           }
-         return true;
+         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;
+         info->within_function = FALSE;
+         info->function_end = (bfd_vma) -1;
        }
-      info->gcc_compiled = 0;
-      info->n_opt_found = false;
-      if (info->last_type == N_SO)
-       {
-         char *o;
 
-         if (! debug_append_filename (dhandle, string))
-           return false;
-         o = info->main_filename;
-         info->main_filename = concat (o, string, (const char *) NULL);
-         free (o);
-       }
+      /* 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, (bfd_vma) -1))
-               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);
+         char *f;
 
-         /* 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;
+         f = info->so_string;
 
-         /* 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;
+         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:
       /* Start an include file.  */
       if (! debug_start_source (dhandle, string))
-       return false;
+       return FALSE;
       break;
 
     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;
+       return FALSE;
       break;
 
     case N_EINCL:
       /* End an N_BINCL include.  */
       if (! debug_start_source (dhandle, pop_bincl (info)))
-       return false;
+       return FALSE;
       break;
 
     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:
       if (! debug_record_line (dhandle, desc,
-                              value + info->function_start_offset))
-       return false;
+                              value + (info->within_function
+                                       ? info->function_start_offset : 0)))
+       return FALSE;
       break;
 
     case N_BCOMM:
       if (! debug_start_common_block (dhandle, string))
-       return false;
+       return FALSE;
       break;
 
     case N_ECOMM:
       if (! debug_end_common_block (dhandle, string))
-       return false;
+       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;
@@ -563,18 +631,26 @@ parse_stab (dhandle, handle, type, desc, value, string)
          {
            if (info->within_function)
              {
-               if (! debug_end_function (dhandle, (bfd_vma) -1))
-                 return false;
+               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.  */
            if (info->sections)
              info->function_start_offset = value;
-           info->within_function = true;
+           info->within_function = TRUE;
          }
 
        if (! parse_stab_string (dhandle, info, type, desc, value, string))
-         return false;
+         return FALSE;
       }
       break;
 
@@ -584,42 +660,37 @@ parse_stab (dhandle, handle, type, desc, value, string)
       else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
        info->gcc_compiled = 1;
       else
-       info->n_opt_found = true;
+       info->n_opt_found = TRUE;
       break;
 
     case N_OBJ:
     case N_ENDM:
     case N_MAIN:
+    case N_WARNING:
       break;
     }
 
-  info->last_type = type;
-
-  return true;
+  return TRUE;
 }
 
 /* Parse the stabs string.  */
 
-static boolean
-parse_stab_string (dhandle, info, stabtype, desc, value, string)
-     PTR dhandle;
-     struct stab_handle *info;
-     int stabtype;
-     int desc;
-     bfd_vma value;
-     const char *string;
+static bfd_boolean
+parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
+                  int desc, bfd_vma value, const char *string)
 {
   const char *p;
   char *name;
   int type;
   debug_type dtype;
-  boolean synonym;
+  bfd_boolean synonym;
+  bfd_boolean self_crossref;
   unsigned int lineno;
   debug_type *slot;
 
   p = strchr (string, ':');
   if (p == NULL)
-    return true;
+    return TRUE;
 
   while (p[1] == ':')
     {
@@ -628,7 +699,7 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
       if (p == NULL)
        {
          bad_stab (string);
-         return false;
+         return FALSE;
        }
     }
 
@@ -662,7 +733,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;
        }
     }
@@ -676,7 +747,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++;
@@ -693,7 +764,7 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
       if (*p != '=')
        {
          bad_stab (string);
-         return false;
+         return FALSE;
        }
       ++p;
       switch (*p++)
@@ -701,7 +772,7 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
        case 'r':
          /* Floating point constant.  */
          if (! debug_record_float_const (dhandle, name, atof (p)))
-           return false;
+           return FALSE;
          break;
        case 'i':
          /* Integer constant.  */
@@ -712,7 +783,7 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
             other languages probably should have at least unsigned as
             well as signed constants.  */
          if (! debug_record_int_const (dhandle, name, atoi (p)))
-           return false;
+           return FALSE;
          break;
        case 'e':
          /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
@@ -722,18 +793,18 @@ 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)
-           return false;
+           return FALSE;
          if (*p != ',')
            {
              bad_stab (string);
-             return false;
+             return FALSE;
            }
          if (! debug_record_typed_const (dhandle, name, dtype, atoi (p)))
-           return false;
+           return FALSE;
          break;
        default:
          bad_stab (string);
-         return false;
+         return FALSE;
        }
 
       break;
@@ -743,9 +814,9 @@ 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)
-       return false;
+       return FALSE;
       if (! debug_record_label (dhandle, name, dtype, value))
-       return false;
+       return FALSE;
       break;
 
     case 'f':
@@ -754,9 +825,9 @@ 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)
-       return false;
+       return FALSE;
       if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
-       return false;
+       return FALSE;
 
       /* Sun acc puts declared types of arguments here.  We don't care
         about their actual types (FIXME -- we should remember the whole
@@ -768,21 +839,40 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
          if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
                               (debug_type **) NULL)
              == DEBUG_TYPE_NULL)
-           return false;
+           return FALSE;
        }
 
       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
@@ -793,10 +883,10 @@ 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)
-       return false;
+       return FALSE;
       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
                                  value))
-       return false;
+       return FALSE;
       break;
 
     case 'p':
@@ -813,21 +903,24 @@ 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;
+       return FALSE;
       if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK,
                                    value))
-       return false;
+       return FALSE;
 
       /* FIXME: At this point gdb considers rearranging the parameter
         address on a big endian machine if it is smaller than an int.
         We have no way to do that, since we don't really know much
         about the target.  */
-
       break;
 
     case 'P':
@@ -840,7 +933,7 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
              if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
                                   (debug_type **) NULL)
                  == DEBUG_TYPE_NULL)
-               return false;
+               return FALSE;
            }
          break;
        }
@@ -850,10 +943,10 @@ 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)
-       return false;
+       return FALSE;
       if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
                                    value))
-       return false;
+       return FALSE;
       break;
 
     case 'r':
@@ -861,41 +954,40 @@ 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)
-       return false;
+       return FALSE;
       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
                                  value))
-       return false;
+       return FALSE;
 
       /* FIXME: At this point gdb checks to combine pairs of 'p' and
         'r' stabs into a single 'P' stab.  */
-
       break;
 
     case 'S':
-      /* Static symbol at top level of file */
+      /* Static symbol at top level of file */
       dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
                               (debug_type **) NULL);
       if (dtype == DEBUG_TYPE_NULL)
-       return false;
+       return FALSE;
       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
                                  value))
-       return false;
+       return FALSE;
       break;
 
     case 't':
       /* A typedef.  */
       dtype = parse_stab_type (dhandle, info, name, &p, &slot);
       if (dtype == DEBUG_TYPE_NULL)
-       return false;
+       return FALSE;
       if (name == NULL)
        {
          /* A nameless type.  Nothing to do.  */
-         return true;
+         return TRUE;
        }
 
       dtype = debug_name_type (dhandle, name, dtype);
       if (dtype == DEBUG_TYPE_NULL)
-       return false;
+       return FALSE;
 
       if (slot != NULL)
        *slot = dtype;
@@ -907,50 +999,57 @@ parse_stab_string (dhandle, info, stabtype, desc, value, string)
         by 't' which means we are typedef'ing it as well.  */
       if (*p != 't')
        {
-         synonym = false;
-         /* FIXME: gdb sets synonym to true if the current language
+         synonym = FALSE;
+         /* FIXME: gdb sets synonym to TRUE if the current language
              is C++.  */
        }
       else
        {
-         synonym = true;
+         synonym = TRUE;
          ++p;
        }
 
-      dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p, &slot);
+      dtype = parse_stab_type (dhandle, info, name, &p, &slot);
       if (dtype == DEBUG_TYPE_NULL)
-       return false;
+       return FALSE;
       if (name == NULL)
-       return true;
+       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;
+       return FALSE;
       if (slot != NULL)
        *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)
        {
          dtype = debug_name_type (dhandle, name, dtype);
          if (dtype == DEBUG_TYPE_NULL)
-           return false;
+           return FALSE;
 
          if (slot != NULL)
            *slot = dtype;
@@ -963,11 +1062,11 @@ 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)
-       return false;
+       return FALSE;
       /* FIXME: gdb checks os9k_stabs here.  */
       if (! stab_record_variable (dhandle, info, name, dtype,
                                  DEBUG_LOCAL_STATIC, value))
-       return false;
+       return FALSE;
       break;
 
     case 'v':
@@ -975,10 +1074,10 @@ 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)
-       return false;
+       return FALSE;
       if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
                                    value))
-       return false;
+       return FALSE;
       break;
 
     case 'a':
@@ -986,10 +1085,10 @@ 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)
-       return false;
+       return FALSE;
       if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
                                    value))
-       return false;
+       return FALSE;
       break;
 
     case 'X':
@@ -1000,40 +1099,35 @@ 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)
-       return false;
+       return FALSE;
       if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
                                  value))
-       return false;
+       return FALSE;
       break;
 
     default:
       bad_stab (string);
-      return false;
+      return FALSE;
     }
 
   /* FIXME: gdb converts structure values to structure pointers in a
      couple of cases, depending upon the target.  */
 
-  return true;
+  return TRUE;
 }
 
 /* Parse a stabs type.  The typename argument is non-NULL if this is a
-   typedef.  The pp argument points to the stab string, and is
-   updated.  The slotp argument points to a place to store the slot
-   used if the type is being defined.  */
+   typedef or a tag definition.  The pp argument points to the stab
+   string, and is updated.  The slotp argument points to a place to
+   store the slot used if the type is being defined.  */
 
 static debug_type
-parse_stab_type (dhandle, info, typename, pp, slotp)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char *typename;
-     const char **pp;
-     debug_type **slotp;
+parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename, const char **pp, debug_type **slotp)
 {
   const char *orig;
   int typenums[2];
   int size;
-  boolean stringp;
+  bfd_boolean stringp;
   int descriptor;
   debug_type dtype;
 
@@ -1043,12 +1137,14 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
   orig = *pp;
 
   size = -1;
-  stringp = false;
+  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.  */
@@ -1060,11 +1156,9 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
        return DEBUG_TYPE_NULL;
 
       if (**pp != '=')
-       {
-         /* Type is not being defined here.  Either it already
-            exists, or this is a forward reference to it.  */
-         return stab_find_type (dhandle, info, typenums);
-       }
+       /* Type is not being defined here.  Either it already
+          exists, or this is a forward reference to it.  */
+       return stab_find_type (dhandle, info, typenums);
 
       /* Only set the slot if the type is being defined.  This means
          that the mapping from type numbers to types will only record
@@ -1091,11 +1185,9 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
          const char *p = *pp + 1;
          const char *attr;
 
-         if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
-           {
-             /* Member type.  */
-             break;
-           }
+         if (ISDIGIT (*p) || *p == '(' || *p == '-')
+           /* Member type.  */
+           break;
 
          /* Type attributes.  */
          attr = p;
@@ -1114,12 +1206,13 @@ 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;
 
            case 'S':
-             stringp = true;
+             stringp = TRUE;
              break;
 
            default:
@@ -1139,11 +1232,8 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
       {
        enum debug_type_kind code;
        const char *q1, *q2, *p;
-       char *name;
-       struct stab_tag *st;
 
        /* A cross reference to another type.  */
-
        switch (**pp)
          {
          case 's':
@@ -1158,7 +1248,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;
          }
@@ -1171,66 +1261,39 @@ 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;
              }
          }
 
-       name = savestring (*pp, p - *pp);
-
-       *pp = p + 1;
-
-       /* We pass DEBUG_KIND_VOID because we want all tags in the
-           same namespace.  This is right for C, and I don't know how
-           to handle other languages.  FIXME.  */
-       dtype = debug_find_tagged_type (dhandle, name, DEBUG_KIND_VOID);
-       if (dtype != DEBUG_TYPE_NULL)
-         {
-           free (name);
-           if (typenums[0] != -1)
-             {
-               if (! stab_record_type (dhandle, info, typenums, dtype))
-                 return DEBUG_TYPE_NULL;
-             }
-           return dtype;
-         }
+       /* 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;
 
-       /* We need to allocate an entry on the undefined tag list.  */
-       for (st = info->tags; st != NULL; st = st->next)
-         {
-           if (st->name[0] == name[0]
-               && strcmp (st->name, name) == 0)
-             break;
-         }
-       if (st == NULL)
-         {
-           st = (struct stab_tag *) xmalloc (sizeof *st);
-           memset (st, 0, sizeof *st);
-
-           st->next = info->tags;
-           st->name = name;
-           st->kind = code;
-           st->slot = DEBUG_TYPE_NULL;
-           st->type = debug_make_indirect_type (dhandle, &st->slot, name);
-           info->tags = st;
-         }
+       dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
 
-       dtype = st->type;
-       if (typenums[0] != -1)
-         {
-           if (! stab_record_type (dhandle, info, typenums, dtype))
-             return DEBUG_TYPE_NULL;
-         }
-       return dtype;
+       *pp = p + 1;
       }
       break;
 
@@ -1251,7 +1314,6 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
        int xtypenums[2];
 
        /* This type is defined as another type.  */
-
        (*pp)--;
        hold = *pp;
 
@@ -1309,7 +1371,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':
@@ -1379,7 +1442,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
        {
@@ -1388,6 +1452,7 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
          debug_type *args;
          unsigned int n;
          unsigned int alloc;
+         bfd_boolean varargs;
 
          domain = parse_stab_type (dhandle, info, (const char *) NULL,
                                    pp, (debug_type **) NULL);
@@ -1422,7 +1487,7 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
                {
                  alloc += 10;
                  args = ((debug_type *)
-                         xrealloc ((PTR) args, alloc * sizeof *args));
+                         xrealloc (args, alloc * sizeof *args));
                }
 
              args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
@@ -1433,9 +1498,22 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
            }
          ++*pp;
 
+         /* 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
+           {
+             --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;
 
@@ -1463,7 +1541,7 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
     case 's':
     case 'u':
       /* Struct or union type.  */
-      dtype = parse_stab_struct_type (dhandle, info, pp,
+      dtype = parse_stab_struct_type (dhandle, info, typename, pp,
                                      descriptor == 's', typenums);
       break;
 
@@ -1505,7 +1583,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;
@@ -1516,10 +1594,8 @@ parse_stab_type (dhandle, info, typename, pp, slotp)
    single number N is equivalent to (0,N).  Return the two numbers by
    storing them in the vector TYPENUMS.  */
 
-static boolean
-parse_stab_type_number (pp, typenums)
-     const char **pp;
-     int *typenums;
+static bfd_boolean
+parse_stab_type_number (const char **pp, int *typenums)
 {
   const char *orig;
 
@@ -1528,47 +1604,42 @@ parse_stab_type_number (pp, typenums)
   if (**pp != '(')
     {
       typenums[0] = 0;
-      typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+      typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
     }
   else
     {
       ++*pp;
-      typenums[0] = (int) parse_number (pp, (boolean *) NULL);
+      typenums[0] = (int) parse_number (pp, (bfd_boolean *) NULL);
       if (**pp != ',')
        {
          bad_stab (orig);
-         return false;
+         return FALSE;
        }
       ++*pp;
-      typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+      typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
       if (**pp != ')')
        {
          bad_stab (orig);
-         return false;
+         return FALSE;
        }
       ++*pp;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Parse a range type.  */
 
 static debug_type
-parse_stab_range_type (dhandle, info, typename, pp, typenums)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char *typename;
-     const char **pp;
-     const int *typenums;
+parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *typename, const char **pp, const int *typenums)
 {
   const char *orig;
   int rangenums[2];
-  boolean self_subrange;
+  bfd_boolean self_subrange;
   debug_type index_type;
   const char *s2, *s3;
   bfd_signed_vma n2, n3;
-  boolean ov2, ov3;
+  bfd_boolean ov2, ov3;
 
   orig = *pp;
 
@@ -1618,21 +1689,21 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
     {
       /* gcc will emit range stabs for long long types.  Handle this
          as a special case.  FIXME: This needs to be more general.  */
-#define LLLOW  "01000000000000000000000;"
-#define LLHIGH "0777777777777777777777;"
+#define LLLOW   "01000000000000000000000;"
+#define LLHIGH   "0777777777777777777777;"
 #define ULLHIGH "01777777777777777777777;"
       if (index_type == DEBUG_TYPE_NULL)
        {
          if (strncmp (s2, LLLOW, sizeof LLLOW - 1) == 0
              && strncmp (s3, LLHIGH, sizeof LLHIGH - 1) == 0)
-           return debug_make_int_type (dhandle, 8, false);
+           return debug_make_int_type (dhandle, 8, FALSE);
          if (! ov2
              && n2 == 0
              && strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0)
-           return debug_make_int_type (dhandle, 8, true);
+           return debug_make_int_type (dhandle, 8, TRUE);
        }
 
-      warn_stab (orig, "numeric overflow");
+      warn_stab (orig, _("numeric overflow"));
     }
 
   if (index_type == DEBUG_TYPE_NULL)
@@ -1642,6 +1713,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)
@@ -1657,44 +1733,51 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
          if (typename != NULL)
            {
              if (strcmp (typename, "long long int") == 0)
-               return debug_make_int_type (dhandle, 8, false);
+               return debug_make_int_type (dhandle, 8, FALSE);
              else if (strcmp (typename, "long long unsigned int") == 0)
-               return debug_make_int_type (dhandle, 8, true);
+               return debug_make_int_type (dhandle, 8, TRUE);
            }
          /* FIXME: The size here really depends upon the target.  */
-         return debug_make_int_type (dhandle, 4, true);
+         return debug_make_int_type (dhandle, 4, TRUE);
        }
 
       /* A range of 0 to 127 is char.  */
       if (self_subrange && n2 == 0 && n3 == 127)
-       return debug_make_int_type (dhandle, 1, false);
+       return debug_make_int_type (dhandle, 1, FALSE);
 
       /* FIXME: gdb checks for the language CHILL here.  */
 
       if (n2 == 0)
        {
          if (n3 < 0)
-           return debug_make_int_type (dhandle, - n3, true);
+           return debug_make_int_type (dhandle, - n3, TRUE);
          else if (n3 == 0xff)
-           return debug_make_int_type (dhandle, 1, true);
+           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.  */
+           return debug_make_int_type (dhandle, 2, TRUE);
+         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)
+       return debug_make_int_type (dhandle, - n2, TRUE);
+      else if (n2 == - n3 - 1 || n2 == n3 + 1)
        {
          if (n3 == 0x7f)
-           return debug_make_int_type (dhandle, 1, false);
+           return debug_make_int_type (dhandle, 1, FALSE);
          else if (n3 == 0x7fff)
-           return debug_make_int_type (dhandle, 2, false);
+           return debug_make_int_type (dhandle, 2, FALSE);
          else if (n3 == 0x7fffffff)
-           return debug_make_int_type (dhandle, 4, false);
+           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
        }
     }
 
@@ -1712,8 +1795,8 @@ 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");
-      index_type = debug_make_int_type (dhandle, 4, false);
+      warn_stab (orig, _("missing index type"));
+      index_type = debug_make_int_type (dhandle, 4, FALSE);
     }
 
   return debug_make_range_type (dhandle, index_type, n2, n3);
@@ -1732,12 +1815,10 @@ parse_stab_range_type (dhandle, info, typename, pp, typenums)
    FIXME.  */
 
 static debug_type
-parse_stab_sun_builtin_type (dhandle, pp)
-     PTR dhandle;
-     const char **pp;
+parse_stab_sun_builtin_type (void *dhandle, const char **pp)
 {
   const char *orig;
-  boolean unsignedp;
+  bfd_boolean unsignedp;
   bfd_vma bits;
 
   orig = *pp;
@@ -1745,10 +1826,10 @@ parse_stab_sun_builtin_type (dhandle, pp)
   switch (**pp)
     {
     case 's':
-      unsignedp = false;
+      unsignedp = FALSE;
       break;
     case 'u':
-      unsignedp = true;
+      unsignedp = TRUE;
       break;
     default:
       bad_stab (orig);
@@ -1767,7 +1848,7 @@ parse_stab_sun_builtin_type (dhandle, pp)
      by this type, except that unsigned short is 4 instead of 2.
      Since this information is redundant with the third number,
      we will ignore it.  */
-  (void) parse_number (pp, (boolean *) NULL);
+  (void) parse_number (pp, (bfd_boolean *) NULL);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1775,8 +1856,8 @@ parse_stab_sun_builtin_type (dhandle, pp)
     }
   ++*pp;
 
-  /* The second number is always 0, so ignore it too. */
-  (void) parse_number (pp, (boolean *) NULL);
+  /* The second number is always 0, so ignore it too.  */
+  (void) parse_number (pp, (bfd_boolean *) NULL);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1784,8 +1865,8 @@ parse_stab_sun_builtin_type (dhandle, pp)
     }
   ++*pp;
 
-  /* The third number is the number of bits for this type. */
-  bits = parse_number (pp, (boolean *) NULL);
+  /* The third number is the number of bits for this type.  */
+  bits = parse_number (pp, (bfd_boolean *) NULL);
 
   /* The type *should* end with a semicolon.  If it are embedded
      in a larger type the semicolon may be the only way to know where
@@ -1805,9 +1886,7 @@ parse_stab_sun_builtin_type (dhandle, pp)
 /* Parse a builtin floating type generated by the Sun compiler.  */
 
 static debug_type
-parse_stab_sun_floating_type (dhandle, pp)
-     PTR dhandle;
-     const char **pp;
+parse_stab_sun_floating_type (void *dhandle, const char **pp)
 {
   const char *orig;
   bfd_vma details;
@@ -1817,7 +1896,7 @@ parse_stab_sun_floating_type (dhandle, pp)
 
   /* The first number has more details about the type, for example
      FN_COMPLEX.  */
-  details = parse_number (pp, (boolean *) NULL);
+  details = parse_number (pp, (bfd_boolean *) NULL);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1825,7 +1904,7 @@ parse_stab_sun_floating_type (dhandle, pp)
     }
 
   /* The second number is the number of bytes occupied by this type */
-  bytes = parse_number (pp, (boolean *) NULL);
+  bytes = parse_number (pp, (bfd_boolean *) NULL);
   if (**pp != ';')
     {
       bad_stab (orig);
@@ -1837,15 +1916,13 @@ parse_stab_sun_floating_type (dhandle, pp)
       || details == NF_COMPLEX32)
     return debug_make_complex_type (dhandle, bytes);
 
-  return debug_make_float_type (dhandle, bytes);      
+  return debug_make_float_type (dhandle, bytes);
 }
 
 /* Handle an enum type.  */
 
 static debug_type
-parse_stab_enum_type (dhandle, pp)
-     PTR dhandle;
-     const char **pp;
+parse_stab_enum_type (void *dhandle, const char **pp)
 {
   const char *orig;
   const char **names;
@@ -1886,7 +1963,7 @@ parse_stab_enum_type (dhandle, pp)
       name = savestring (*pp, p - *pp);
 
       *pp = p + 1;
-      val = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+      val = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
       if (**pp != ',')
        {
          bad_stab (orig);
@@ -1898,9 +1975,9 @@ parse_stab_enum_type (dhandle, pp)
        {
          alloc += 10;
          names = ((const char **)
-                  xrealloc ((PTR) names, alloc * sizeof *names));
+                  xrealloc (names, alloc * sizeof *names));
          values = ((bfd_signed_vma *)
-                   xrealloc ((PTR) values, alloc * sizeof *values));
+                   xrealloc (values, alloc * sizeof *values));
        }
 
       names[n] = name;
@@ -1921,35 +1998,32 @@ parse_stab_enum_type (dhandle, pp)
    describing the type.
 
    PP points to a character pointer that points to the next unconsumed token
-   in the the stabs string.  For example, given stabs "A:T4=s4a:1,0,32;;",
+   in the stabs string.  For example, given stabs "A:T4=s4a:1,0,32;;",
    *PP will point to "4a:1,0,32;;".  */
 
 static debug_type
-parse_stab_struct_type (dhandle, info, pp, structp, typenums)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char **pp;
-     boolean structp;
-     const int *typenums;
+parse_stab_struct_type (void *dhandle, struct stab_handle *info,
+                       const char *tagname, const char **pp,
+                       bfd_boolean structp, const int *typenums)
 {
   const char *orig;
   bfd_vma size;
   debug_baseclass *baseclasses;
   debug_field *fields;
-  boolean statics;
+  bfd_boolean statics;
   debug_method *methods;
   debug_type vptrbase;
-  boolean ownvptr;
+  bfd_boolean ownvptr;
 
   orig = *pp;
 
   /* Get the size.  */
-  size = parse_number (pp, (boolean *) NULL);
+  size = parse_number (pp, (bfd_boolean *) NULL);
 
   /* Get the other information.  */
   if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
       || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics)
-      || ! parse_stab_members (dhandle, info, pp, &methods)
+      || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
       || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
                                   &ownvptr))
     return DEBUG_TYPE_NULL;
@@ -1977,7 +2051,7 @@ parse_stab_struct_type (dhandle, info, pp, structp, typenums)
    the type for the base class, and a terminating semicolon.
 
    A typical example, with two base classes, would be "!2,020,19;0264,21;".
-                                                      ^^ ^ ^ ^  ^ ^  ^
+                                                      ^^ ^ ^ ^  ^ ^  ^
        Baseclass information marker __________________|| | | |  | |  |
        Number of baseclasses __________________________| | | |  | |  |
        Visibility specifiers (2) ________________________| | |  | |  |
@@ -1987,14 +2061,11 @@ parse_stab_struct_type (dhandle, info, pp, structp, typenums)
        Offset in bits from start of class ________________________|  |
        Type number of base class ____________________________________|
 
-  Return true for success, false for failure.  */
+  Return TRUE for success, FALSE for failure.  */
 
-static boolean
-parse_stab_baseclasses (dhandle, info, pp, retp)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char **pp;
-     debug_baseclass **retp;
+static bfd_boolean
+parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
+                       const char **pp, debug_baseclass **retp)
 {
   const char *orig;
   unsigned int c, i;
@@ -2007,16 +2078,16 @@ parse_stab_baseclasses (dhandle, info, pp, retp)
   if (**pp != '!')
     {
       /* No base classes.  */
-      return true;
+      return TRUE;
     }
   ++*pp;
 
-  c = (unsigned int) parse_number (pp, (boolean *) NULL);
+  c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL);
 
   if (**pp != ',')
     {
       bad_stab (orig);
-      return false;
+      return FALSE;
     }
   ++*pp;
 
@@ -2024,7 +2095,7 @@ parse_stab_baseclasses (dhandle, info, pp, retp)
 
   for (i = 0; i < c; i++)
     {
-      boolean virtual;
+      bfd_boolean virtual;
       enum debug_visibility visibility;
       bfd_vma bitpos;
       debug_type type;
@@ -2032,14 +2103,14 @@ parse_stab_baseclasses (dhandle, info, pp, retp)
       switch (**pp)
        {
        case '0':
-         virtual = false;
+         virtual = FALSE;
          break;
        case '1':
-         virtual = true;
+         virtual = TRUE;
          break;
        default:
-         warn_stab (orig, "unknown virtual character for baseclass");
-         virtual = false;
+         warn_stab (orig, _("unknown virtual character for baseclass"));
+         virtual = FALSE;
          break;
        }
       ++*pp;
@@ -2056,7 +2127,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;
        }
@@ -2065,26 +2136,26 @@ parse_stab_baseclasses (dhandle, info, pp, retp)
       /* The remaining value is the bit offset of the portion of the
         object corresponding to this baseclass.  Always zero in the
         absence of multiple inheritance.  */
-      bitpos = parse_number (pp, (boolean *) NULL);
+      bitpos = parse_number (pp, (bfd_boolean *) NULL);
       if (**pp != ',')
        {
          bad_stab (orig);
-         return false;
+         return FALSE;
        }
       ++*pp;
 
       type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
                              (debug_type **) NULL);
       if (type == DEBUG_TYPE_NULL)
-       return false;
+       return FALSE;
 
       classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual,
                                         visibility);
       if (classes[i] == DEBUG_BASECLASS_NULL)
-       return false;
+       return FALSE;
 
       if (**pp != ';')
-       return false;
+       return FALSE;
       ++*pp;
     }
 
@@ -2092,12 +2163,12 @@ parse_stab_baseclasses (dhandle, info, pp, retp)
 
   *retp = classes;
 
-  return true;
+  return TRUE;
 }
 
 /* Read struct or class data fields.  They have the form:
 
-       NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
+       NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
 
    At the end, we see a semicolon instead of a field.
 
@@ -2106,7 +2177,7 @@ parse_stab_baseclasses (dhandle, info, pp, retp)
 
    The optional VISIBILITY is one of:
 
-       '/0'    (VISIBILITY_PRIVATE)
+       '/0'    (VISIBILITY_PRIVATE)
        '/1'    (VISIBILITY_PROTECTED)
        '/2'    (VISIBILITY_PUBLIC)
        '/9'    (VISIBILITY_IGNORE)
@@ -2115,13 +2186,10 @@ parse_stab_baseclasses (dhandle, info, pp, retp)
 
    Returns 1 for success, 0 for failure.  */
 
-static boolean
-parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char **pp;
-     debug_field **retp;
-     boolean *staticsp;
+static bfd_boolean
+parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
+                         const char **pp, debug_field **retp,
+                         bfd_boolean *staticsp)
 {
   const char *orig;
   const char *p;
@@ -2130,7 +2198,7 @@ parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
   unsigned int alloc;
 
   *retp = NULL;
-  *staticsp = false;
+  *staticsp = FALSE;
 
   orig = *pp;
 
@@ -2148,7 +2216,7 @@ parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
        {
          alloc += 10;
          fields = ((debug_field *)
-                   xrealloc ((PTR) fields, alloc * sizeof *fields));
+                   xrealloc (fields, alloc * sizeof *fields));
        }
 
       /* If it starts with CPLUS_MARKER it is a special abbreviation,
@@ -2162,7 +2230,7 @@ parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
        {
          ++*pp;
          if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
-           return false;
+           return FALSE;
          ++c;
          continue;
        }
@@ -2170,13 +2238,13 @@ parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
       /* Look for the ':' that separates the field name from the field
         values.  Data members are delimited by a single ':', while member
         functions are delimited by a pair of ':'s.  When we hit the member
-        functions (if any), terminate scan loop and return. */
+        functions (if any), terminate scan loop and return.  */
 
       p = strchr (p, ':');
       if (p == NULL)
        {
          bad_stab (orig);
-         return false;
+         return FALSE;
        }
 
       if (p[1] == ':')
@@ -2184,7 +2252,7 @@ parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
 
       if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
                                         staticsp))
-       return false;
+       return FALSE;
 
       ++c;
     }
@@ -2193,17 +2261,14 @@ parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
 
   *retp = fields;
 
-  return true;
+  return TRUE;
 }
 
 /* Special GNU C++ name.  */
 
-static boolean
-parse_stab_cpp_abbrev (dhandle, info, pp, retp)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char **pp;
-     debug_field *retp;
+static bfd_boolean
+parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
+                      const char **pp, debug_field *retp)
 {
   const char *orig;
   int cpp_abbrev;
@@ -2220,7 +2285,7 @@ parse_stab_cpp_abbrev (dhandle, info, pp, retp)
   if (**pp != 'v')
     {
       bad_stab (*pp);
-      return false;
+      return FALSE;
     }
   ++*pp;
 
@@ -2235,7 +2300,7 @@ parse_stab_cpp_abbrev (dhandle, info, pp, retp)
   context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
                             (debug_type **) NULL);
   if (context == DEBUG_TYPE_NULL)
-    return false;
+    return FALSE;
 
   switch (cpp_abbrev)
     {
@@ -2248,13 +2313,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;
     }
@@ -2262,7 +2327,7 @@ parse_stab_cpp_abbrev (dhandle, info, pp, retp)
   if (**pp != ':')
     {
       bad_stab (orig);
-      return false;
+      return FALSE;
     }
   ++*pp;
 
@@ -2271,36 +2336,32 @@ parse_stab_cpp_abbrev (dhandle, info, pp, retp)
   if (**pp != ',')
     {
       bad_stab (orig);
-      return false;
+      return FALSE;
     }
   ++*pp;
 
-  bitpos = parse_number (pp, (boolean *) NULL);
+  bitpos = parse_number (pp, (bfd_boolean *) NULL);
   if (**pp != ';')
     {
       bad_stab (orig);
-      return false;
+      return FALSE;
     }
   ++*pp;
 
   *retp = debug_make_field (dhandle, name, type, bitpos, 0,
                            DEBUG_VISIBILITY_PRIVATE);
   if (*retp == DEBUG_FIELD_NULL)
-    return false;
+    return FALSE;
 
-  return true;
+  return TRUE;
 }
 
 /* Parse a single field in a struct or union.  */
 
-static boolean
-parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char **pp;
-     const char *p;
-     debug_field *retp;
-     boolean *staticsp;
+static bfd_boolean
+parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
+                            const char **pp, const char *p,
+                            debug_field *retp, bfd_boolean *staticsp)
 {
   const char *orig;
   char *name;
@@ -2334,7 +2395,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;
        }
@@ -2344,7 +2405,7 @@ parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
   type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
                          (debug_type **) NULL);
   if (type == DEBUG_TYPE_NULL)
-    return false;
+    return FALSE;
 
   if (**pp == ':')
     {
@@ -2356,7 +2417,7 @@ parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
       if (p == NULL)
        {
          bad_stab (orig);
-         return false;
+         return FALSE;
        }
 
       varname = savestring (*pp, p - *pp);
@@ -2365,31 +2426,31 @@ parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
 
       *retp = debug_make_static_member (dhandle, name, type, varname,
                                        visibility);
-      *staticsp = true;
+      *staticsp = TRUE;
 
-      return true;
+      return TRUE;
     }
 
   if (**pp != ',')
     {
       bad_stab (orig);
-      return false;
+      return FALSE;
     }
   ++*pp;
 
-  bitpos = parse_number (pp, (boolean *) NULL);
+  bitpos = parse_number (pp, (bfd_boolean *) NULL);
   if (**pp != ',')
     {
       bad_stab (orig);
-      return false;
+      return FALSE;
     }
   ++*pp;
 
-  bitsize = parse_number (pp, (boolean *) NULL);
+  bitsize = parse_number (pp, (bfd_boolean *) NULL);
   if (**pp != ';')
     {
       bad_stab (orig);
-      return false;
+      return FALSE;
     }
   ++*pp;
 
@@ -2415,7 +2476,7 @@ parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
 
   *retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility);
 
-  return true;
+  return TRUE;
 }
 
 /* Read member function stabs info for C++ classes.  The form of each member
@@ -2431,12 +2492,10 @@ parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
    $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
    name (such as `+=') and `.' marks the end of the operator name.  */
 
-static boolean
-parse_stab_members (dhandle, info, pp, retp)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char **pp;
-     debug_method **retp;
+static bfd_boolean
+parse_stab_members (void *dhandle, struct stab_handle *info,
+                   const char *tagname, const char **pp,
+                   const int *typenums, debug_method **retp)
 {
   const char *orig;
   debug_method *methods;
@@ -2472,7 +2531,7 @@ parse_stab_members (dhandle, info, pp, retp)
        }
       else
        {
-         /* This is a completely wierd case.  In order to stuff in the
+         /* This is a completely weird case.  In order to stuff in the
             names that might contain colons (the usual name delimiter),
             Mike Tiemann defined a different name format which is
             signalled if the identifier is "op$".  In that case, the
@@ -2484,7 +2543,7 @@ parse_stab_members (dhandle, info, pp, retp)
          if (*p != '.')
            {
              bad_stab (orig);
-             return false;
+             return FALSE;
            }
          name = savestring (*pp, p - *pp);
          *pp = p + 1;
@@ -2500,11 +2559,14 @@ parse_stab_members (dhandle, info, pp, retp)
       do
        {
          debug_type type;
+         bfd_boolean stub;
          char *argtypes;
          enum debug_visibility visibility;
-         boolean constp, volatilep, staticp;
+         bfd_boolean constp, volatilep, staticp;
          bfd_vma voffset;
          debug_type context;
+         const char *physname;
+         bfd_boolean varargs;
 
          if (look_ahead_type != DEBUG_TYPE_NULL)
            {
@@ -2517,11 +2579,11 @@ parse_stab_members (dhandle, info, pp, retp)
              type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
                                      (debug_type **) NULL);
              if (type == DEBUG_TYPE_NULL)
-               return false;
+               return FALSE;
              if (**pp != ':')
                {
                  bad_stab (orig);
-                 return false;
+                 return FALSE;
                }
            }
 
@@ -2530,10 +2592,13 @@ parse_stab_members (dhandle, info, pp, retp)
          if (p == NULL)
            {
              bad_stab (orig);
-             return false;
+             return FALSE;
            }
 
-         /* FIXME: gdb sets is_stub here.  */
+         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;
@@ -2552,8 +2617,8 @@ parse_stab_members (dhandle, info, pp, retp)
            }
          ++*pp;
 
-         constp = false;
-         volatilep = false;
+         constp = FALSE;
+         volatilep = FALSE;
          switch (**pp)
            {
            case 'A':
@@ -2562,18 +2627,18 @@ parse_stab_members (dhandle, info, pp, retp)
              break;
            case 'B':
              /* const member function.  */
-             constp = true;
+             constp = TRUE;
              ++*pp;
              break;
            case 'C':
              /* volatile member function.  */
-             volatilep = true;
+             volatilep = TRUE;
              ++*pp;
              break;
            case 'D':
              /* const volatile member function.  */
-             constp = true;
-             volatilep = true;
+             constp = TRUE;
+             volatilep = TRUE;
              ++*pp;
              break;
            case '*':
@@ -2582,31 +2647,26 @@ parse_stab_members (dhandle, info, pp, 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;
            }
 
-         staticp = false;
+         staticp = FALSE;
          switch (**pp)
            {
            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);
+             voffset = parse_number (pp, (bfd_boolean *) NULL);
              if (**pp != ';')
                {
                  bad_stab (orig);
-                 return false;
+                 return FALSE;
                }
              ++*pp;
              voffset &= 0x7fffffff;
-             voffset += 2;
 
              if (**pp == ';' || *pp == '\0')
                {
@@ -2618,35 +2678,37 @@ parse_stab_members (dhandle, info, pp, retp)
                  /* Figure out from whence this virtual function
                     came.  It may belong to virtual function table of
                     one of its baseclasses.  */
-                   look_ahead_type = parse_stab_type (dhandle, info,
-                                                      (const char *) NULL,
-                                                      pp,
-                                                      (debug_type **) NULL);
-                   if (**pp == ':')
-                     {
-                       /* g++ version 1 overloaded methods.  */
-                     }
-                   else
-                     {
-                       context = look_ahead_type;
-                       look_ahead_type = DEBUG_TYPE_NULL;
-                       if (**pp != ';')
-                         {
-                           bad_stab (orig);
-                           return false;
-                         }
-                       ++*pp;
-                     }
-                 }
+                 look_ahead_type = parse_stab_type (dhandle, info,
+                                                    (const char *) NULL,
+                                                    pp,
+                                                    (debug_type **) NULL);
+                 if (**pp == ':')
+                   {
+                     /* g++ version 1 overloaded methods.  */
+                     context = DEBUG_TYPE_NULL;
+                   }
+                 else
+                   {
+                     context = look_ahead_type;
+                     look_ahead_type = DEBUG_TYPE_NULL;
+                     if (**pp != ';')
+                       {
+                         bad_stab (orig);
+                         return FALSE;
+                       }
+                     ++*pp;
+                   }
+               }
              break;
 
            case '?':
              /* static member function.  */
              ++*pp;
-             staticp = true;
+             staticp = TRUE;
              voffset = 0;
-             /* FIXME: gdb sets is_stub here.  */
              context = DEBUG_TYPE_NULL;
+             if (strncmp (argtypes, name, strlen (name)) != 0)
+               stub = TRUE;
              break;
 
            default:
@@ -2662,28 +2724,55 @@ parse_stab_members (dhandle, info, pp, retp)
              break;
            }
 
+         /* 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
+           {
+             debug_type class_type, return_type;
+
+             class_type = stab_find_type (dhandle, info, typenums);
+             if (class_type == DEBUG_TYPE_NULL)
+               return FALSE;
+             return_type = debug_get_return_type (dhandle, type);
+             if (return_type == DEBUG_TYPE_NULL)
+               {
+                 bad_stab (orig);
+                 return FALSE;
+               }
+             type = parse_stab_argtypes (dhandle, info, class_type, name,
+                                         tagname, return_type, argtypes,
+                                         constp, volatilep, &physname);
+             if (type == DEBUG_TYPE_NULL)
+               return FALSE;
+           }
+
          if (cvars + 1 >= allocvars)
            {
              allocvars += 10;
              variants = ((debug_method_variant *)
-                         xrealloc ((PTR) variants,
+                         xrealloc (variants,
                                    allocvars * sizeof *variants));
            }
 
          if (! staticp)
-           variants[cvars] = debug_make_method_variant (dhandle, argtypes,
+           variants[cvars] = debug_make_method_variant (dhandle, physname,
                                                         type, visibility,
                                                         constp, volatilep,
                                                         voffset, context);
          else
            variants[cvars] = debug_make_static_method_variant (dhandle,
-                                                               argtypes,
+                                                               physname,
                                                                type,
                                                                visibility,
                                                                constp,
                                                                volatilep);
          if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL)
-           return false;
+           return FALSE;
 
          ++cvars;
        }
@@ -2698,7 +2787,7 @@ parse_stab_members (dhandle, info, pp, retp)
        {
          alloc += 10;
          methods = ((debug_method *)
-                    xrealloc ((PTR) methods, alloc * sizeof *methods));
+                    xrealloc (methods, alloc * sizeof *methods));
        }
 
       methods[c] = debug_make_method (dhandle, name, variants);
@@ -2711,7 +2800,129 @@ parse_stab_members (dhandle, info, pp, retp)
 
   *retp = methods;
 
-  return true;
+  return TRUE;
+}
+
+/* Parse a string representing argument types for a method.  Stabs
+   tries to save space by packing argument types into a mangled
+   string.  This string should give us enough information to extract
+   both argument types and the physical name of the function, given
+   the tag name.  */
+
+static debug_type
+parse_stab_argtypes (void *dhandle, struct stab_handle *info,
+                    debug_type class_type, const char *fieldname,
+                    const char *tagname, debug_type return_type,
+                    const char *argtypes, bfd_boolean constp,
+                    bfd_boolean volatilep, const char **pphysname)
+{
+  bfd_boolean is_full_physname_constructor;
+  bfd_boolean is_constructor;
+  bfd_boolean is_destructor;
+  bfd_boolean is_v3;
+  debug_type *args;
+  bfd_boolean varargs;
+  unsigned int physname_len = 0;
+
+  /* Constructors are sometimes handled specially.  */
+  is_full_physname_constructor = ((argtypes[0] == '_'
+                                  && argtypes[1] == '_'
+                                  && (ISDIGIT (argtypes[2])
+                                      || argtypes[2] == 'Q'
+                                      || argtypes[2] == 't'))
+                                 || strncmp (argtypes, "__ct", 4) == 0);
+
+  is_constructor = (is_full_physname_constructor
+                   || (tagname != NULL
+                       && strcmp (fieldname, tagname) == 0));
+  is_destructor = ((argtypes[0] == '_'
+                   && (argtypes[1] == '$' || argtypes[1] == '.')
+                   && argtypes[2] == '_')
+                  || strncmp (argtypes, "__dt", 4) == 0);
+  is_v3 = argtypes[0] == '_' && argtypes[1] == 'Z';
+
+  if (is_destructor || is_full_physname_constructor || is_v3)
+    *pphysname = argtypes;
+  else
+    {
+      unsigned int len;
+      const char *const_prefix;
+      const char *volatile_prefix;
+      char buf[20];
+      unsigned int mangled_name_len;
+      char *physname;
+
+      len = tagname == NULL ? 0 : strlen (tagname);
+      const_prefix = constp ? "C" : "";
+      volatile_prefix = volatilep ? "V" : "";
+
+      if (len == 0)
+       sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+      else if (tagname != NULL && strchr (tagname, '<') != NULL)
+       {
+         /* Template methods are fully mangled.  */
+         sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+         tagname = NULL;
+         len = 0;
+       }
+      else
+       sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+
+      mangled_name_len = ((is_constructor ? 0 : strlen (fieldname))
+                         + strlen (buf)
+                         + len
+                         + strlen (argtypes)
+                         + 1);
+
+      if (fieldname[0] == 'o'
+         && fieldname[1] == 'p'
+         && (fieldname[2] == '$' || fieldname[2] == '.'))
+       {
+         const char *opname;
+
+         opname = cplus_mangle_opname (fieldname + 3, 0);
+         if (opname == NULL)
+           {
+             fprintf (stderr, _("No mangling for \"%s\"\n"), fieldname);
+             return DEBUG_TYPE_NULL;
+           }
+         mangled_name_len += strlen (opname);
+         physname = (char *) xmalloc (mangled_name_len);
+         strncpy (physname, fieldname, 3);
+         strcpy (physname + 3, opname);
+       }
+      else
+       {
+         physname = (char *) xmalloc (mangled_name_len);
+         if (is_constructor)
+           physname[0] = '\0';
+         else
+           strcpy (physname, fieldname);
+       }
+
+      physname_len = strlen (physname);
+      strcat (physname, buf);
+      if (tagname != NULL)
+       strcat (physname, tagname);
+      strcat (physname, argtypes);
+
+      *pphysname = physname;
+    }
+
+  if (*argtypes == '\0' || is_destructor)
+    {
+      args = (debug_type *) xmalloc (sizeof *args);
+      *args = NULL;
+      return debug_make_method_type (dhandle, return_type, class_type, args,
+                                    FALSE);
+    }
+
+  args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs, physname_len);
+  if (args == NULL)
+    return DEBUG_TYPE_NULL;
+
+  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
@@ -2722,42 +2933,38 @@ parse_stab_members (dhandle, info, pp, retp)
    This function is called when we have parsed all the method declarations,
    so we can look for the vptr base class info.  */
 
-static boolean
-parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char **pp;
-     const int *typenums;
-     debug_type *retvptrbase;
-     boolean *retownvptr;
+static bfd_boolean
+parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
+                       const char **pp, const int *typenums,
+                       debug_type *retvptrbase, bfd_boolean *retownvptr)
 {
   const char *orig;
   const char *hold;
   int vtypenums[2];
 
   *retvptrbase = DEBUG_TYPE_NULL;
-  *retownvptr = false;
+  *retownvptr = FALSE;
 
   orig = *pp;
 
-  /* If we are positioned at a ';', then skip it. */
+  /* If we are positioned at a ';', then skip it.  */
   if (**pp == ';')
     ++*pp;
 
   if (**pp != '~')
-    return true;
+    return TRUE;
 
   ++*pp;
 
   if (**pp == '=' || **pp == '+' || **pp == '-')
     {
       /* Obsolete flags that used to indicate the presence of
-        constructors and/or destructors. */
+        constructors and/or destructors.  */
       ++*pp;
     }
 
   if (**pp != '%')
-    return true;
+    return TRUE;
 
   ++*pp;
 
@@ -2766,11 +2973,11 @@ parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr)
   /* The next number is the type number of the base class (possibly
      our own class) which supplies the vtable for this class.  */
   if (! parse_stab_type_number (pp, vtypenums))
-    return false;
+    return FALSE;
 
   if (vtypenums[0] == typenums[0]
       && vtypenums[1] == typenums[1])
-    *retownvptr = true;
+    *retownvptr = TRUE;
   else
     {
       debug_type vtype;
@@ -2785,7 +2992,7 @@ parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr)
       if (*p != ';')
        {
          bad_stab (orig);
-         return false;
+         return FALSE;
        }
 
       *retvptrbase = vtype;
@@ -2793,21 +3000,20 @@ parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr)
       *pp = p + 1;
     }
 
-  return true;    
+  return TRUE;
 }
 
 /* Read a definition of an array type.  */
 
 static debug_type
-parse_stab_array_type (dhandle, info, pp, stringp)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char **pp;
-     boolean stringp;
+parse_stab_array_type (void *dhandle, struct stab_handle *info,
+                      const char **pp, bfd_boolean stringp)
 {
   const char *orig;
+  const char *p;
+  int typenums[2];
   debug_type index_type;
-  boolean adjustable;
+  bfd_boolean adjustable;
   bfd_signed_vma lower, upper;
   debug_type element_type;
 
@@ -2822,8 +3028,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);
@@ -2831,40 +3056,40 @@ parse_stab_array_type (dhandle, info, pp, stringp)
     }
   ++*pp;
 
-  adjustable = false;
+  adjustable = FALSE;
 
-  if (! isdigit ((unsigned char) **pp) && **pp != '-')
+  if (! ISDIGIT (**pp) && **pp != '-')
     {
       ++*pp;
-      adjustable = true;
+      adjustable = TRUE;
     }
 
-  lower = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+  lower = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
   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;
+      adjustable = TRUE;
     }
 
-  upper = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+  upper = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
   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)
     {
@@ -2876,72 +3101,112 @@ 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)
-     struct stab_handle *info;
-     const char *name;
+push_bincl (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;
   info->file_types = ((struct stab_types **)
-                     xrealloc ((PTR) info->file_types,
+                     xrealloc (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
    stack.  */
 
 static const char *
-pop_bincl (info)
-     struct stab_handle *info;
+pop_bincl (struct stab_handle *info)
 {
   struct bincl_file *o;
 
   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 bfd_boolean
+find_excl (struct stab_handle *info, const char *name, bfd_vma hash)
+{
+  struct bincl_file *l;
+
+  ++info->files;
+  info->file_types = ((struct stab_types **)
+                     xrealloc (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
    N_LBRAC, so we can call debug_record_variable immediately.  */
 
-static boolean
-stab_record_variable (dhandle, info, name, type, kind, val)
-     PTR dhandle;
-     struct stab_handle *info;
-     const char *name;
-     debug_type type;
-     enum debug_var_kind kind;
-     bfd_vma val;
+static bfd_boolean
+stab_record_variable (void *dhandle, struct stab_handle *info,
+                     const char *name, debug_type type,
+                     enum debug_var_kind kind, bfd_vma val)
 {
   struct stab_pending_var *v;
 
-  if (! info->within_function
+  if ((kind == DEBUG_GLOBAL || kind == DEBUG_STATIC)
+      || ! info->within_function
       || (info->gcc_compiled == 0 && info->n_opt_found))
     return debug_record_variable (dhandle, name, type, kind, val);
 
@@ -2955,16 +3220,14 @@ stab_record_variable (dhandle, info, name, type, kind, val)
   v->val = val;
   info->pending = v;
 
-  return true;
+  return TRUE;
 }
 
 /* Emit pending variable definitions.  This is called after we see the
    N_LBRAC that starts the block.  */
 
-static boolean
-stab_emit_pending_vars (dhandle, info)
-     PTR dhandle;
-     struct stab_handle *info;
+static bfd_boolean
+stab_emit_pending_vars (void *dhandle, struct stab_handle *info)
 {
   struct stab_pending_var *v;
 
@@ -2974,7 +3237,7 @@ stab_emit_pending_vars (dhandle, info)
       struct stab_pending_var *next;
 
       if (! debug_record_variable (dhandle, v->name, v->type, v->kind, v->val))
-       return false;
+       return FALSE;
 
       next = v->next;
       free (v);
@@ -2983,15 +3246,13 @@ stab_emit_pending_vars (dhandle, info)
 
   info->pending = NULL;
 
-  return true;
+  return TRUE;
 }
 
 /* Find the slot for a type in the database.  */
 
 static debug_type *
-stab_find_slot (info, typenums)
-     struct stab_handle *info;
-     const int *typenums;
+stab_find_slot (struct stab_handle *info, const int *typenums)
 {
   int filenum;
   int index;
@@ -3002,12 +3263,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;
     }
 
@@ -3036,10 +3297,7 @@ stab_find_slot (info, typenums)
    allocated yet, create an indirect type.  */
 
 static debug_type
-stab_find_type (dhandle, info, typenums)
-     PTR dhandle;
-     struct stab_handle *info;
-     const int *typenums;
+stab_find_type (void *dhandle, struct stab_handle *info, const int *typenums)
 {
   debug_type *slot;
 
@@ -3061,40 +3319,35 @@ stab_find_type (dhandle, info, typenums)
 
 /* Record that a given type number refers to a given type.  */
 
-static boolean
-stab_record_type (dhandle, info, typenums, type)
-     PTR dhandle;
-     struct stab_handle *info;
-     const int *typenums;
-     debug_type type;
+static bfd_boolean
+stab_record_type (void *dhandle ATTRIBUTE_UNUSED, struct stab_handle *info,
+                 const int *typenums, debug_type type)
 {
   debug_type *slot;
 
   slot = stab_find_slot (info, typenums);
   if (slot == NULL)
-    return false;
+    return FALSE;
 
   /* gdb appears to ignore type redefinitions, so we do as well.  */
 
   *slot = type;
 
-  return true;
+  return TRUE;
 }
 
 /* Return an XCOFF builtin type.  */
 
 static debug_type
-stab_xcoff_builtin_type (dhandle, info, typenum)
-     PTR dhandle;
-     struct stab_handle *info;
-     int typenum;
+stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info,
+                        int typenum)
 {
   debug_type rettype;
   const char *name;
 
   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)
@@ -3106,42 +3359,42 @@ stab_xcoff_builtin_type (dhandle, info, typenum)
       /* The size of this and all the other types are fixed, defined
         by the debugging format.  */
       name = "int";
-      rettype = debug_make_int_type (dhandle, 4, false);
+      rettype = debug_make_int_type (dhandle, 4, FALSE);
       break;
     case 2:
       name = "char";
-      rettype = debug_make_int_type (dhandle, 1, false);
+      rettype = debug_make_int_type (dhandle, 1, FALSE);
       break;
     case 3:
       name = "short";
-      rettype = debug_make_int_type (dhandle, 2, false);
+      rettype = debug_make_int_type (dhandle, 2, FALSE);
       break;
     case 4:
       name = "long";
-      rettype = debug_make_int_type (dhandle, 4, false);
+      rettype = debug_make_int_type (dhandle, 4, FALSE);
       break;
     case 5:
       name = "unsigned char";
-      rettype = debug_make_int_type (dhandle, 1, true);
+      rettype = debug_make_int_type (dhandle, 1, TRUE);
       break;
     case 6:
       name = "signed char";
-      rettype = debug_make_int_type (dhandle, 1, false);
+      rettype = debug_make_int_type (dhandle, 1, FALSE);
       break;
     case 7:
       name = "unsigned short";
-      rettype = debug_make_int_type (dhandle, 2, true);
+      rettype = debug_make_int_type (dhandle, 2, TRUE);
       break;
     case 8:
       name = "unsigned int";
-      rettype = debug_make_int_type (dhandle, 4, true);
+      rettype = debug_make_int_type (dhandle, 4, TRUE);
       break;
     case 9:
       name = "unsigned";
-      rettype = debug_make_int_type (dhandle, 4, true);
+      rettype = debug_make_int_type (dhandle, 4, TRUE);
     case 10:
       name = "unsigned long";
-      rettype = debug_make_int_type (dhandle, 4, true);
+      rettype = debug_make_int_type (dhandle, 4, TRUE);
       break;
     case 11:
       name = "void";
@@ -3166,7 +3419,7 @@ stab_xcoff_builtin_type (dhandle, info, typenum)
       break;
     case 15:
       name = "integer";
-      rettype = debug_make_int_type (dhandle, 4, false);
+      rettype = debug_make_int_type (dhandle, 4, FALSE);
       break;
     case 16:
       name = "boolean";
@@ -3188,7 +3441,7 @@ stab_xcoff_builtin_type (dhandle, info, typenum)
     case 20:
       /* FIXME */
       name = "character";
-      rettype = debug_make_int_type (dhandle, 1, true);
+      rettype = debug_make_int_type (dhandle, 1, TRUE);
       break;
     case 21:
       name = "logical*1";
@@ -3218,28 +3471,28 @@ stab_xcoff_builtin_type (dhandle, info, typenum)
       break;
     case 27:
       name = "integer*1";
-      rettype = debug_make_int_type (dhandle, 1, false);
+      rettype = debug_make_int_type (dhandle, 1, FALSE);
       break;
     case 28:
       name = "integer*2";
-      rettype = debug_make_int_type (dhandle, 2, false);
+      rettype = debug_make_int_type (dhandle, 2, FALSE);
       break;
     case 29:
       name = "integer*4";
-      rettype = debug_make_int_type (dhandle, 4, false);
+      rettype = debug_make_int_type (dhandle, 4, FALSE);
       break;
     case 30:
       /* FIXME */
       name = "wchar";
-      rettype = debug_make_int_type (dhandle, 2, false);
+      rettype = debug_make_int_type (dhandle, 2, FALSE);
       break;
     case 31:
       name = "long long";
-      rettype = debug_make_int_type (dhandle, 8, false);
+      rettype = debug_make_int_type (dhandle, 8, FALSE);
       break;
     case 32:
       name = "unsigned long long";
-      rettype = debug_make_int_type (dhandle, 8, true);
+      rettype = debug_make_int_type (dhandle, 8, TRUE);
       break;
     case 33:
       name = "logical*8";
@@ -3247,7 +3500,7 @@ stab_xcoff_builtin_type (dhandle, info, typenum)
       break;
     case 34:
       name = "integer*8";
-      rettype = debug_make_int_type (dhandle, 8, false);
+      rettype = debug_make_int_type (dhandle, 8, FALSE);
       break;
     default:
       abort ();
@@ -3259,3 +3512,1838 @@ stab_xcoff_builtin_type (dhandle, info, typenum)
 
   return rettype;
 }
+
+/* Find or create a tagged type.  */
+
+static debug_type
+stab_find_tagged_type (void *dhandle, struct stab_handle *info,
+                      const char *p, int len, enum debug_type_kind kind)
+{
+  char *name;
+  debug_type dtype;
+  struct stab_tag *st;
+
+  name = savestring (p, len);
+
+  /* We pass DEBUG_KIND_ILLEGAL because we want all tags in the same
+     namespace.  This is right for C, and I don't know how to handle
+     other languages.  FIXME.  */
+  dtype = debug_find_tagged_type (dhandle, name, DEBUG_KIND_ILLEGAL);
+  if (dtype != DEBUG_TYPE_NULL)
+    {
+      free (name);
+      return dtype;
+    }
+
+  /* We need to allocate an entry on the undefined tag list.  */
+  for (st = info->tags; st != NULL; st = st->next)
+    {
+      if (st->name[0] == name[0]
+         && strcmp (st->name, name) == 0)
+       {
+         if (st->kind == DEBUG_KIND_ILLEGAL)
+           st->kind = kind;
+         free (name);
+         break;
+       }
+    }
+  if (st == NULL)
+    {
+      st = (struct stab_tag *) xmalloc (sizeof *st);
+      memset (st, 0, sizeof *st);
+
+      st->next = info->tags;
+      st->name = name;
+      st->kind = kind;
+      st->slot = DEBUG_TYPE_NULL;
+      st->type = debug_make_indirect_type (dhandle, &st->slot, name);
+      info->tags = st;
+    }
+
+  return st->type;
+}
+\f
+/* In order to get the correct argument types for a stubbed method, we
+   need to extract the argument types from a C++ mangled string.
+   Since the argument types can refer back to the return type, this
+   means that we must demangle the entire physical name.  In gdb this
+   is done by calling cplus_demangle and running the results back
+   through the C++ expression parser.  Since we have no expression
+   parser, we must duplicate much of the work of cplus_demangle here.
+
+   We assume that GNU style demangling is used, since this is only
+   done for method stubs, and only g++ should output that form of
+   debugging information.  */
+
+/* This structure is used to hold a pointer to type information which
+   demangling a string.  */
+
+struct stab_demangle_typestring
+{
+  /* The start of the type.  This is not null terminated.  */
+  const char *typestring;
+  /* The length of the type.  */
+  unsigned int len;
+};
+
+/* This structure is used to hold information while demangling a
+   string.  */
+
+struct stab_demangle_info
+{
+  /* The debugging information handle.  */
+  void *dhandle;
+  /* The stab information handle.  */
+  struct stab_handle *info;
+  /* The array of arguments we are building.  */
+  debug_type *args;
+  /* Whether the method takes a variable number of arguments.  */
+  bfd_boolean varargs;
+  /* The array of types we have remembered.  */
+  struct stab_demangle_typestring *typestrings;
+  /* The number of typestrings.  */
+  unsigned int typestring_count;
+  /* The number of typestring slots we have allocated.  */
+  unsigned int typestring_alloc;
+};
+
+static void stab_bad_demangle (const char *);
+static unsigned int stab_demangle_count (const char **);
+static bfd_boolean stab_demangle_get_count (const char **, unsigned int *);
+static bfd_boolean stab_demangle_prefix
+  (struct stab_demangle_info *, const char **, unsigned int);
+static bfd_boolean stab_demangle_function_name
+  (struct stab_demangle_info *, const char **, const char *);
+static bfd_boolean stab_demangle_signature
+  (struct stab_demangle_info *, const char **);
+static bfd_boolean stab_demangle_qualified
+  (struct stab_demangle_info *, const char **, debug_type *);
+static bfd_boolean stab_demangle_template
+  (struct stab_demangle_info *, const char **, char **);
+static bfd_boolean stab_demangle_class
+  (struct stab_demangle_info *, const char **, const char **);
+static bfd_boolean stab_demangle_args
+  (struct stab_demangle_info *, const char **, debug_type **, bfd_boolean *);
+static bfd_boolean stab_demangle_arg
+  (struct stab_demangle_info *, const char **, debug_type **,
+   unsigned int *, unsigned int *);
+static bfd_boolean stab_demangle_type
+  (struct stab_demangle_info *, const char **, debug_type *);
+static bfd_boolean stab_demangle_fund_type
+  (struct stab_demangle_info *, const char **, debug_type *);
+static bfd_boolean stab_demangle_remember_type
+  (struct stab_demangle_info *, const char *, int);
+
+/* Warn about a bad demangling.  */
+
+static void
+stab_bad_demangle (const char *s)
+{
+  fprintf (stderr, _("bad mangled name `%s'\n"), s);
+}
+
+/* Get a count from a stab string.  */
+
+static unsigned int
+stab_demangle_count (const char **pp)
+{
+  unsigned int count;
+
+  count = 0;
+  while (ISDIGIT (**pp))
+    {
+      count *= 10;
+      count += **pp - '0';
+      ++*pp;
+    }
+  return count;
+}
+
+/* Require a count in a string.  The count may be multiple digits, in
+   which case it must end in an underscore.  */
+
+static bfd_boolean
+stab_demangle_get_count (const char **pp, unsigned int *pi)
+{
+  if (! ISDIGIT (**pp))
+    return FALSE;
+
+  *pi = **pp - '0';
+  ++*pp;
+  if (ISDIGIT (**pp))
+    {
+      unsigned int count;
+      const char *p;
+
+      count = *pi;
+      p = *pp;
+      do
+       {
+         count *= 10;
+         count += *p - '0';
+         ++p;
+       }
+      while (ISDIGIT (*p));
+      if (*p == '_')
+       {
+         *pp = p + 1;
+         *pi = count;
+       }
+    }
+
+  return TRUE;
+}
+
+/* This function demangles a physical name, returning a NULL
+   terminated array of argument types.  */
+
+static debug_type *
+stab_demangle_argtypes (void *dhandle, struct stab_handle *info,
+                       const char *physname, bfd_boolean *pvarargs,
+                       unsigned int physname_len)
+{
+  struct stab_demangle_info minfo;
+
+  /* Check for the g++ V3 ABI.  */
+  if (physname[0] == '_' && physname[1] == 'Z')
+    return stab_demangle_v3_argtypes (dhandle, info, physname, pvarargs);
+
+  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
+                               * sizeof *minfo.typestrings));
+  minfo.typestring_count = 0;
+
+  /* cplus_demangle checks for special GNU mangled forms, but we can't
+     see any of them in mangled method argument types.  */
+
+  if (! stab_demangle_prefix (&minfo, &physname, physname_len))
+    goto error_return;
+
+  if (*physname != '\0')
+    {
+      if (! stab_demangle_signature (&minfo, &physname))
+       goto error_return;
+    }
+
+  free (minfo.typestrings);
+  minfo.typestrings = NULL;
+
+  if (minfo.args == NULL)
+    fprintf (stderr, _("no argument types in mangled string\n"));
+
+  *pvarargs = minfo.varargs;
+  return minfo.args;
+
+ error_return:
+  if (minfo.typestrings != NULL)
+    free (minfo.typestrings);
+  return NULL;
+}
+
+/* Demangle the prefix of the mangled name.  */
+
+static bfd_boolean
+stab_demangle_prefix (struct stab_demangle_info *minfo, const char **pp,
+                     unsigned int physname_len)
+{
+  const char *scan;
+  unsigned int i;
+
+  /* cplus_demangle checks for global constructors and destructors,
+     but we can't see them in mangled argument types.  */
+
+  if (physname_len)
+    scan = *pp + physname_len;
+  else
+    {
+      /* Look for `__'.  */
+      scan = *pp;
+      do
+       scan = strchr (scan, '_');
+      while (scan != NULL && *++scan != '_');
+
+      if (scan == NULL)
+       {
+         stab_bad_demangle (*pp);
+         return FALSE;
+       }
+
+      --scan;
+
+      /* We found `__'; move ahead to the last contiguous `__' pair.  */
+      i = strspn (scan, "_");
+      if (i > 2)
+       scan += i - 2;
+    }
+
+  if (scan == *pp
+      && (ISDIGIT (scan[2])
+         || scan[2] == 'Q'
+         || scan[2] == 't'))
+    {
+      /* This is a GNU style constructor name.  */
+      *pp = scan + 2;
+      return TRUE;
+    }
+  else if (scan == *pp
+          && ! ISDIGIT (scan[2])
+          && scan[2] != 't')
+    {
+      /* Look for the `__' that separates the prefix from the
+         signature.  */
+      while (*scan == '_')
+       ++scan;
+      scan = strstr (scan, "__");
+      if (scan == NULL || scan[2] == '\0')
+       {
+         stab_bad_demangle (*pp);
+         return FALSE;
+       }
+
+      return stab_demangle_function_name (minfo, pp, scan);
+    }
+  else if (scan[2] != '\0')
+    {
+      /* The name doesn't start with `__', but it does contain `__'.  */
+      return stab_demangle_function_name (minfo, pp, scan);
+    }
+  else
+    {
+      stab_bad_demangle (*pp);
+      return FALSE;
+    }
+  /*NOTREACHED*/
+}
+
+/* Demangle a function name prefix.  The scan argument points to the
+   double underscore which separates the function name from the
+   signature.  */
+
+static bfd_boolean
+stab_demangle_function_name (struct stab_demangle_info *minfo,
+                            const char **pp, const char *scan)
+{
+  const char *name;
+
+  /* The string from *pp to scan is the name of the function.  We
+     don't care about the name, since we just looking for argument
+     types.  However, for conversion operators, the name may include a
+     type which we must remember in order to handle backreferences.  */
+
+  name = *pp;
+  *pp = scan + 2;
+
+  if (*pp - name >= 5
+          && strncmp (name, "type", 4) == 0
+          && (name[4] == '$' || name[4] == '.'))
+    {
+      const char *tem;
+
+      /* This is a type conversion operator.  */
+      tem = name + 5;
+      if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
+       return FALSE;
+    }
+  else if (name[0] == '_'
+          && name[1] == '_'
+          && name[2] == 'o'
+          && name[3] == 'p')
+    {
+      const char *tem;
+
+      /* This is a type conversion operator.  */
+      tem = name + 4;
+      if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
+       return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Demangle the signature.  This is where the argument types are
+   found.  */
+
+static bfd_boolean
+stab_demangle_signature (struct stab_demangle_info *minfo, const char **pp)
+{
+  const char *orig;
+  bfd_boolean expect_func, func_done;
+  const char *hold;
+
+  orig = *pp;
+
+  expect_func = FALSE;
+  func_done = FALSE;
+  hold = NULL;
+
+  while (**pp != '\0')
+    {
+      switch (**pp)
+       {
+       case 'Q':
+         hold = *pp;
+         if (! stab_demangle_qualified (minfo, pp, (debug_type *) NULL)
+             || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+           return FALSE;
+         expect_func = TRUE;
+         hold = NULL;
+         break;
+
+       case 'S':
+         /* Static member function.  FIXME: Can this happen?  */
+         if (hold == NULL)
+           hold = *pp;
+         ++*pp;
+         break;
+
+       case 'C':
+         /* Const member function.  */
+         if (hold == NULL)
+           hold = *pp;
+         ++*pp;
+         break;
+
+       case '0': case '1': case '2': case '3': case '4':
+       case '5': case '6': case '7': case '8': case '9':
+         if (hold == NULL)
+           hold = *pp;
+         if (! stab_demangle_class (minfo, pp, (const char **) NULL)
+             || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+           return FALSE;
+         expect_func = TRUE;
+         hold = NULL;
+         break;
+
+       case 'F':
+         /* Function.  I don't know if this actually happens with g++
+             output.  */
+         hold = NULL;
+         func_done = TRUE;
+         ++*pp;
+         if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+           return FALSE;
+         break;
+
+       case 't':
+         /* Template.  */
+         if (hold == NULL)
+           hold = *pp;
+         if (! stab_demangle_template (minfo, pp, (char **) NULL)
+             || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
+           return FALSE;
+         hold = NULL;
+         expect_func = TRUE;
+         break;
+
+       case '_':
+         /* At the outermost level, we cannot have a return type
+            specified, so if we run into another '_' at this point we
+            are dealing with a mangled name that is either bogus, or
+            has been mangled by some algorithm we don't know how to
+            deal with.  So just reject the entire demangling.  */
+         stab_bad_demangle (orig);
+         return FALSE;
+
+       default:
+         /* 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, &minfo->varargs))
+           return FALSE;
+         break;
+       }
+
+      if (expect_func)
+       {
+         func_done = TRUE;
+         if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
+           return FALSE;
+       }
+    }
+
+  if (! func_done)
+    {
+      /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
+        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, &minfo->varargs))
+       return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Demangle a qualified name, such as "Q25Outer5Inner" which is the
+   mangled form of "Outer::Inner".  */
+
+static bfd_boolean
+stab_demangle_qualified (struct stab_demangle_info *minfo, const char **pp,
+                        debug_type *ptype)
+{
+  const char *orig;
+  const char *p;
+  unsigned int qualifiers;
+  debug_type context;
+
+  orig = *pp;
+
+  switch ((*pp)[1])
+    {
+    case '_':
+      /* GNU mangled name with more than 9 classes.  The count is
+        preceded by an underscore (to distinguish it from the <= 9
+        case) and followed by an underscore.  */
+      p = *pp + 2;
+      if (! ISDIGIT (*p) || *p == '0')
+       {
+         stab_bad_demangle (orig);
+         return FALSE;
+       }
+      qualifiers = atoi (p);
+      while (ISDIGIT (*p))
+       ++p;
+      if (*p != '_')
+       {
+         stab_bad_demangle (orig);
+         return FALSE;
+       }
+      *pp = p + 1;
+      break;
+
+    case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+      qualifiers = (*pp)[1] - '0';
+      /* Skip an optional underscore after the count.  */
+      if ((*pp)[2] == '_')
+       ++*pp;
+      *pp += 2;
+      break;
+
+    case '0':
+    default:
+      stab_bad_demangle (orig);
+      return FALSE;
+    }
+
+  context = DEBUG_TYPE_NULL;
+
+  /* Pick off the names.  */
+  while (qualifiers-- > 0)
+    {
+      if (**pp == '_')
+       ++*pp;
+      if (**pp == 't')
+       {
+         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
+       {
+         unsigned int len;
+
+         len = stab_demangle_count (pp);
+         if (strlen (*pp) < len)
+           {
+             stab_bad_demangle (orig);
+             return FALSE;
+           }
+
+         if (ptype != NULL)
+           {
+             const debug_field *fields;
+
+             fields = NULL;
+             if (context != DEBUG_TYPE_NULL)
+               fields = debug_get_fields (minfo->dhandle, context);
+
+             context = DEBUG_TYPE_NULL;
+
+             if (fields != NULL)
+               {
+                 char *name;
+
+                 /* Try to find the type by looking through the
+                     fields of context until we find a field with the
+                     same type.  This ought to work for a class
+                     defined within a class, but it won't work for,
+                     e.g., an enum defined within a class.  stabs does
+                     not give us enough information to figure out the
+                     latter case.  */
+
+                 name = savestring (*pp, len);
+
+                 for (; *fields != DEBUG_FIELD_NULL; fields++)
+                   {
+                     debug_type ft;
+                     const char *dn;
+
+                     ft = debug_get_field_type (minfo->dhandle, *fields);
+                     if (ft == NULL)
+                       return FALSE;
+                     dn = debug_get_type_name (minfo->dhandle, ft);
+                     if (dn != NULL && strcmp (dn, name) == 0)
+                       {
+                         context = ft;
+                         break;
+                       }
+                   }
+
+                 free (name);
+               }
+
+             if (context == DEBUG_TYPE_NULL)
+               {
+                 /* 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.  */
+
+                 if (qualifiers == 0)
+                   {
+                     char *name;
+
+                     name = savestring (*pp, len);
+                     context = debug_find_named_type (minfo->dhandle,
+                                                      name);
+                     free (name);
+                   }
+
+                 if (context == DEBUG_TYPE_NULL)
+                   {
+                     context = stab_find_tagged_type (minfo->dhandle,
+                                                      minfo->info,
+                                                      *pp, len,
+                                                      (qualifiers == 0
+                                                       ? DEBUG_KIND_ILLEGAL
+                                                       : DEBUG_KIND_CLASS));
+                     if (context == DEBUG_TYPE_NULL)
+                       return FALSE;
+                   }
+               }
+           }
+
+         *pp += len;
+       }
+    }
+
+  if (ptype != NULL)
+    *ptype = context;
+
+  return TRUE;
+}
+
+/* Demangle a template.  If PNAME is not NULL, this sets *PNAME to a
+   string representation of the template.  */
+
+static bfd_boolean
+stab_demangle_template (struct stab_demangle_info *minfo, const char **pp,
+                       char **pname)
+{
+  const char *orig;
+  unsigned int r, i;
+
+  orig = *pp;
+
+  ++*pp;
+
+  /* Skip the template name.  */
+  r = stab_demangle_count (pp);
+  if (r == 0 || strlen (*pp) < r)
+    {
+      stab_bad_demangle (orig);
+      return FALSE;
+    }
+  *pp += r;
+
+  /* Get the size of the parameter list.  */
+  if (stab_demangle_get_count (pp, &r) == 0)
+    {
+      stab_bad_demangle (orig);
+      return FALSE;
+    }
+
+  for (i = 0; i < r; i++)
+    {
+      if (**pp == 'Z')
+       {
+         /* This is a type parameter.  */
+         ++*pp;
+         if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
+           return FALSE;
+       }
+      else
+       {
+         const char *old_p;
+         bfd_boolean pointerp, realp, integralp, charp, boolp;
+         bfd_boolean done;
+
+         old_p = *pp;
+         pointerp = FALSE;
+         realp = FALSE;
+         integralp = FALSE;
+         charp = FALSE;
+         boolp = FALSE;
+         done = FALSE;
+
+         /* This is a value parameter.  */
+
+         if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
+           return FALSE;
+
+         while (*old_p != '\0' && ! done)
+           {
+             switch (*old_p)
+               {
+               case 'P':
+               case 'p':
+               case 'R':
+                 pointerp = TRUE;
+                 done = TRUE;
+                 break;
+               case 'C':       /* Const.  */
+               case 'S':       /* Signed.  */
+               case 'U':       /* Unsigned.  */
+               case 'V':       /* Volatile.  */
+               case 'F':       /* Function.  */
+               case 'M':       /* Member function.  */
+               case 'O':       /* ??? */
+                 ++old_p;
+                 break;
+               case 'Q':       /* Qualified name.  */
+                 integralp = TRUE;
+                 done = TRUE;
+                 break;
+               case 'T':       /* Remembered type.  */
+                 abort ();
+               case 'v':       /* Void.  */
+                 abort ();
+               case 'x':       /* Long long.  */
+               case 'l':       /* Long.  */
+               case 'i':       /* Int.  */
+               case 's':       /* Short.  */
+               case 'w':       /* Wchar_t.  */
+                 integralp = TRUE;
+                 done = TRUE;
+                 break;
+               case 'b':       /* Bool.  */
+                 boolp = TRUE;
+                 done = TRUE;
+                 break;
+               case 'c':       /* Char.  */
+                 charp = TRUE;
+                 done = TRUE;
+                 break;
+               case 'r':       /* Long double.  */
+               case 'd':       /* Double.  */
+               case 'f':       /* Float.  */
+                 realp = TRUE;
+                 done = TRUE;
+                 break;
+               default:
+                 /* Assume it's a user defined integral type.  */
+                 integralp = TRUE;
+                 done = TRUE;
+                 break;
+               }
+           }
+
+         if (integralp)
+           {
+             if (**pp == 'm')
+               ++*pp;
+             while (ISDIGIT (**pp))
+               ++*pp;
+           }
+         else if (charp)
+           {
+             unsigned int val;
+
+             if (**pp == 'm')
+               ++*pp;
+             val = stab_demangle_count (pp);
+             if (val == 0)
+               {
+                 stab_bad_demangle (orig);
+                 return FALSE;
+               }
+           }
+         else if (boolp)
+           {
+             unsigned int val;
+
+             val = stab_demangle_count (pp);
+             if (val != 0 && val != 1)
+               {
+                 stab_bad_demangle (orig);
+                 return FALSE;
+               }
+           }
+         else if (realp)
+           {
+             if (**pp == 'm')
+               ++*pp;
+             while (ISDIGIT (**pp))
+               ++*pp;
+             if (**pp == '.')
+               {
+                 ++*pp;
+                 while (ISDIGIT (**pp))
+                   ++*pp;
+               }
+             if (**pp == 'e')
+               {
+                 ++*pp;
+                 while (ISDIGIT (**pp))
+                   ++*pp;
+               }
+           }
+         else if (pointerp)
+           {
+             unsigned int len;
+
+             if (! stab_demangle_get_count (pp, &len))
+               {
+                 stab_bad_demangle (orig);
+                 return FALSE;
+               }
+             *pp += len;
+           }
+       }
+    }
+
+  /* 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;
+}
+
+/* Demangle a class name.  */
+
+static bfd_boolean
+stab_demangle_class (struct stab_demangle_info *minfo ATTRIBUTE_UNUSED,
+                    const char **pp, const char **pstart)
+{
+  const char *orig;
+  unsigned int n;
+
+  orig = *pp;
+
+  n = stab_demangle_count (pp);
+  if (strlen (*pp) < n)
+    {
+      stab_bad_demangle (orig);
+      return FALSE;
+    }
+
+  if (pstart != NULL)
+    *pstart = *pp;
+
+  *pp += n;
+
+  return TRUE;
+}
+
+/* Demangle function arguments.  If the pargs argument is not NULL, it
+   is set to a NULL terminated array holding the arguments.  */
+
+static bfd_boolean
+stab_demangle_args (struct stab_demangle_info *minfo, const char **pp,
+                   debug_type **pargs, bfd_boolean *pvarargs)
+{
+  const char *orig;
+  unsigned int alloc, count;
+
+  orig = *pp;
+
+  alloc = 10;
+  if (pargs != NULL)
+    {
+      *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
+      *pvarargs = FALSE;
+    }
+  count = 0;
+
+  while (**pp != '_' && **pp != '\0' && **pp != 'e')
+    {
+      if (**pp == 'N' || **pp == 'T')
+       {
+         char temptype;
+         unsigned int r, t;
+
+         temptype = **pp;
+         ++*pp;
+
+         if (temptype == 'T')
+           r = 1;
+         else
+           {
+             if (! stab_demangle_get_count (pp, &r))
+               {
+                 stab_bad_demangle (orig);
+                 return FALSE;
+               }
+           }
+
+         if (! stab_demangle_get_count (pp, &t))
+           {
+             stab_bad_demangle (orig);
+             return FALSE;
+           }
+
+         if (t >= minfo->typestring_count)
+           {
+             stab_bad_demangle (orig);
+             return FALSE;
+           }
+         while (r-- > 0)
+           {
+             const char *tem;
+
+             tem = minfo->typestrings[t].typestring;
+             if (! stab_demangle_arg (minfo, &tem, pargs, &count, &alloc))
+               return FALSE;
+           }
+       }
+      else
+       {
+         if (! stab_demangle_arg (minfo, pp, pargs, &count, &alloc))
+           return FALSE;
+       }
+    }
+
+  if (pargs != NULL)
+    (*pargs)[count] = DEBUG_TYPE_NULL;
+
+  if (**pp == 'e')
+    {
+      if (pargs != NULL)
+       *pvarargs = TRUE;
+      ++*pp;
+    }
+
+  return TRUE;
+}
+
+/* Demangle a single argument.  */
+
+static bfd_boolean
+stab_demangle_arg (struct stab_demangle_info *minfo, const char **pp,
+                  debug_type **pargs, unsigned int *pcount,
+                  unsigned int *palloc)
+{
+  const char *start;
+  debug_type type;
+
+  start = *pp;
+  if (! stab_demangle_type (minfo, pp,
+                           pargs == NULL ? (debug_type *) NULL : &type)
+      || ! stab_demangle_remember_type (minfo, start, *pp - start))
+    return FALSE;
+
+  if (pargs != NULL)
+    {
+      if (type == DEBUG_TYPE_NULL)
+       return FALSE;
+
+      if (*pcount + 1 >= *palloc)
+       {
+         *palloc += 10;
+         *pargs = ((debug_type *)
+                   xrealloc (*pargs, *palloc * sizeof **pargs));
+       }
+      (*pargs)[*pcount] = type;
+      ++*pcount;
+    }
+
+  return TRUE;
+}
+
+/* Demangle a type.  If the ptype argument is not NULL, *ptype is set
+   to the newly allocated type.  */
+
+static bfd_boolean
+stab_demangle_type (struct stab_demangle_info *minfo, const char **pp,
+                   debug_type *ptype)
+{
+  const char *orig;
+
+  orig = *pp;
+
+  switch (**pp)
+    {
+    case 'P':
+    case 'p':
+      /* A pointer type.  */
+      ++*pp;
+      if (! stab_demangle_type (minfo, pp, ptype))
+       return FALSE;
+      if (ptype != NULL)
+       *ptype = debug_make_pointer_type (minfo->dhandle, *ptype);
+      break;
+
+    case 'R':
+      /* A reference type.  */
+      ++*pp;
+      if (! stab_demangle_type (minfo, pp, ptype))
+       return FALSE;
+      if (ptype != NULL)
+       *ptype = debug_make_reference_type (minfo->dhandle, *ptype);
+      break;
+
+    case 'A':
+      /* An array.  */
+      {
+       unsigned long high;
+
+       ++*pp;
+       high = 0;
+       while (**pp != '\0' && **pp != '_')
+         {
+           if (! ISDIGIT (**pp))
+             {
+               stab_bad_demangle (orig);
+               return FALSE;
+             }
+           high *= 10;
+           high += **pp - '0';
+           ++*pp;
+         }
+       if (**pp != '_')
+         {
+           stab_bad_demangle (orig);
+           return FALSE;
+         }
+       ++*pp;
+
+       if (! stab_demangle_type (minfo, pp, ptype))
+         return FALSE;
+       if (ptype != NULL)
+         {
+           debug_type int_type;
+
+           int_type = debug_find_named_type (minfo->dhandle, "int");
+           if (int_type == NULL)
+             int_type = debug_make_int_type (minfo->dhandle, 4, FALSE);
+           *ptype = debug_make_array_type (minfo->dhandle, *ptype, int_type,
+                                           0, high, FALSE);
+         }
+      }
+      break;
+
+    case 'T':
+      /* A back reference to a remembered type.  */
+      {
+       unsigned int i;
+       const char *p;
+
+       ++*pp;
+       if (! stab_demangle_get_count (pp, &i))
+         {
+           stab_bad_demangle (orig);
+           return FALSE;
+         }
+       if (i >= minfo->typestring_count)
+         {
+           stab_bad_demangle (orig);
+           return FALSE;
+         }
+       p = minfo->typestrings[i].typestring;
+       if (! stab_demangle_type (minfo, &p, ptype))
+         return FALSE;
+      }
+      break;
+
+    case 'F':
+      /* A function.  */
+      {
+       debug_type *args;
+       bfd_boolean varargs;
+
+       ++*pp;
+       if (! stab_demangle_args (minfo, pp,
+                                 (ptype == NULL
+                                  ? (debug_type **) NULL
+                                  : &args),
+                                 (ptype == NULL
+                                  ? (bfd_boolean *) NULL
+                                  : &varargs)))
+         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);
+           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':
+      {
+       bfd_boolean memberp, constp, volatilep;
+       debug_type class_type = DEBUG_TYPE_NULL;
+       debug_type *args;
+       bfd_boolean varargs;
+       unsigned int n;
+       const char *name;
+
+       memberp = **pp == 'M';
+       constp = FALSE;
+       volatilep = FALSE;
+       args = NULL;
+       varargs = FALSE;
+
+       ++*pp;
+       if (ISDIGIT (**pp))
+         {
+           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;
+         }
+       else
+         {
+           stab_bad_demangle (orig);
+           return FALSE;
+         }
+
+       if (memberp)
+         {
+           if (**pp == 'C')
+             {
+               constp = TRUE;
+               ++*pp;
+             }
+           else if (**pp == 'V')
+             {
+               volatilep = TRUE;
+               ++*pp;
+             }
+           if (**pp != 'F')
+             {
+               stab_bad_demangle (orig);
+               return FALSE;
+             }
+           ++*pp;
+           if (! stab_demangle_args (minfo, pp,
+                                     (ptype == NULL
+                                      ? (debug_type **) NULL
+                                      : &args),
+                                     (ptype == NULL
+                                      ? (bfd_boolean *) NULL
+                                      : &varargs)))
+             return FALSE;
+         }
+
+       if (**pp != '_')
+         {
+           stab_bad_demangle (orig);
+           return FALSE;
+         }
+       ++*pp;
+
+       if (! stab_demangle_type (minfo, pp, ptype))
+         return FALSE;
+
+       if (ptype != NULL)
+         {
+           if (! memberp)
+             *ptype = debug_make_offset_type (minfo->dhandle, class_type,
+                                              *ptype);
+           else
+             {
+               /* FIXME: We have no way to record constp or
+                   volatilep.  */
+               *ptype = debug_make_method_type (minfo->dhandle, *ptype,
+                                                class_type, args, varargs);
+             }
+         }
+      }
+      break;
+
+    case 'G':
+      ++*pp;
+      if (! stab_demangle_type (minfo, pp, ptype))
+       return FALSE;
+      break;
+
+    case 'C':
+      ++*pp;
+      if (! stab_demangle_type (minfo, pp, ptype))
+       return FALSE;
+      if (ptype != NULL)
+       *ptype = debug_make_const_type (minfo->dhandle, *ptype);
+      break;
+
+    case 'Q':
+      {
+       const char *hold;
+
+       hold = *pp;
+       if (! stab_demangle_qualified (minfo, pp, ptype))
+         return FALSE;
+      }
+      break;
+
+    default:
+      if (! stab_demangle_fund_type (minfo, pp, ptype))
+       return FALSE;
+      break;
+    }
+
+  return TRUE;
+}
+
+/* Demangle a fundamental type.  If the ptype argument is not NULL,
+   *ptype is set to the newly allocated type.  */
+
+static bfd_boolean
+stab_demangle_fund_type (struct stab_demangle_info *minfo, const char **pp,
+                        debug_type *ptype)
+{
+  const char *orig;
+  bfd_boolean constp, volatilep, unsignedp, signedp;
+  bfd_boolean done;
+
+  orig = *pp;
+
+  constp = FALSE;
+  volatilep = FALSE;
+  unsignedp = FALSE;
+  signedp = FALSE;
+
+  done = FALSE;
+  while (! done)
+    {
+      switch (**pp)
+       {
+       case 'C':
+         constp = TRUE;
+         ++*pp;
+         break;
+
+       case 'U':
+         unsignedp = TRUE;
+         ++*pp;
+         break;
+
+       case 'S':
+         signedp = TRUE;
+         ++*pp;
+         break;
+
+       case 'V':
+         volatilep = TRUE;
+         ++*pp;
+         break;
+
+       default:
+         done = TRUE;
+         break;
+       }
+    }
+
+  switch (**pp)
+    {
+    case '\0':
+    case '_':
+      /* cplus_demangle permits this, but I don't know what it means.  */
+      stab_bad_demangle (orig);
+      break;
+
+    case 'v': /* void */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "void");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_void_type (minfo->dhandle);
+       }
+      ++*pp;
+      break;
+
+    case 'x': /* long long */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "long long unsigned int"
+                                          : "long long int"));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 8, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 'l': /* long */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "long unsigned int"
+                                          : "long int"));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 'i': /* int */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "unsigned int"
+                                          : "int"));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 's': /* short */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "short unsigned int"
+                                          : "short int"));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 2, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 'b': /* bool */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "bool");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_bool_type (minfo->dhandle, 4);
+       }
+      ++*pp;
+      break;
+
+    case 'c': /* char */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle,
+                                         (unsignedp
+                                          ? "unsigned char"
+                                          : (signedp
+                                             ? "signed char"
+                                             : "char")));
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 1, unsignedp);
+       }
+      ++*pp;
+      break;
+
+    case 'w': /* wchar_t */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "__wchar_t");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_int_type (minfo->dhandle, 2, TRUE);
+       }
+      ++*pp;
+      break;
+
+    case 'r': /* long double */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "long double");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_float_type (minfo->dhandle, 8);
+       }
+      ++*pp;
+      break;
+
+    case 'd': /* double */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "double");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_float_type (minfo->dhandle, 8);
+       }
+      ++*pp;
+      break;
+
+    case 'f': /* float */
+      if (ptype != NULL)
+       {
+         *ptype = debug_find_named_type (minfo->dhandle, "float");
+         if (*ptype == DEBUG_TYPE_NULL)
+           *ptype = debug_make_float_type (minfo->dhandle, 4);
+       }
+      ++*pp;
+      break;
+
+    case 'G':
+      ++*pp;
+      if (! ISDIGIT (**pp))
+       {
+         stab_bad_demangle (orig);
+         return FALSE;
+       }
+      /* Fall through.  */
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      {
+       const char *hold;
+
+       if (! stab_demangle_class (minfo, pp, &hold))
+         return FALSE;
+       if (ptype != NULL)
+         {
+           char *name;
+
+           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
+                   undefined types are tagged types.  */
+               *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
+                                               hold, *pp - hold,
+                                               DEBUG_KIND_ILLEGAL);
+               if (*ptype == DEBUG_TYPE_NULL)
+                 return FALSE;
+             }
+         }
+      }
+      break;
+
+    case 't':
+      {
+       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:
+      stab_bad_demangle (orig);
+      return FALSE;
+    }
+
+  if (ptype != NULL)
+    {
+      if (constp)
+       *ptype = debug_make_const_type (minfo->dhandle, *ptype);
+      if (volatilep)
+       *ptype = debug_make_volatile_type (minfo->dhandle, *ptype);
+    }
+
+  return TRUE;
+}
+
+/* Remember a type string in a demangled string.  */
+
+static bfd_boolean
+stab_demangle_remember_type (struct stab_demangle_info *minfo,
+                            const char *p, int len)
+{
+  if (minfo->typestring_count >= minfo->typestring_alloc)
+    {
+      minfo->typestring_alloc += 10;
+      minfo->typestrings = ((struct stab_demangle_typestring *)
+                           xrealloc (minfo->typestrings,
+                                     (minfo->typestring_alloc
+                                      * sizeof *minfo->typestrings)));
+    }
+
+  minfo->typestrings[minfo->typestring_count].typestring = p;
+  minfo->typestrings[minfo->typestring_count].len = (unsigned int) len;
+  ++minfo->typestring_count;
+
+  return TRUE;
+}
+\f
+/* Demangle names encoded using the g++ V3 ABI.  The newer versions of
+   g++ which use this ABI do not encode ordinary method argument types
+   in a mangled name; they simply output the argument types.  However,
+   for a static method, g++ simply outputs the return type and the
+   physical name.  So in that case we need to demangle the name here.
+   Here PHYSNAME is the physical name of the function, and we set the
+   variable pointed at by PVARARGS to indicate whether this function
+   is varargs.  This returns NULL, or a NULL terminated array of
+   argument types.  */
+
+static debug_type *
+stab_demangle_v3_argtypes (void *dhandle, struct stab_handle *info,
+                          const char *physname, bfd_boolean *pvarargs)
+{
+  struct demangle_component *dc;
+  void *mem;
+  unsigned int alloc, count;
+  debug_type *pargs;
+
+  dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | DMGL_ANSI, &mem);
+  if (dc == NULL)
+    {
+      stab_bad_demangle (physname);
+      return NULL;
+    }
+
+  /* We expect to see TYPED_NAME, and the right subtree describes the
+     function type.  */
+  if (dc->type != DEMANGLE_COMPONENT_TYPED_NAME
+      || dc->u.s_binary.right->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
+    {
+      fprintf (stderr, _("Demangled name is not a function\n"));
+      free (mem);
+      return NULL;
+    }
+
+  alloc = 10;
+  pargs = (debug_type *) xmalloc (alloc * sizeof *pargs);
+  *pvarargs = FALSE;
+
+  count = 0;
+
+  for (dc = dc->u.s_binary.right->u.s_binary.right;
+       dc != NULL;
+       dc = dc->u.s_binary.right)
+    {
+      debug_type arg;
+      bfd_boolean varargs;
+
+      if (dc->type != DEMANGLE_COMPONENT_ARGLIST)
+       {
+         fprintf (stderr, _("Unexpected type in demangle tree\n"));
+         free (mem);
+         return NULL;
+       }
+
+      arg = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
+                                 NULL, &varargs);
+      if (arg == NULL)
+       {
+         if (varargs)
+           {
+             *pvarargs = TRUE;
+             continue;
+           }
+         free (mem);
+         return NULL;
+       }
+
+      if (count + 1 >= alloc)
+       {
+         alloc += 10;
+         pargs = (debug_type *) xrealloc (pargs, alloc * sizeof *pargs);
+       }
+
+      pargs[count] = arg;
+      ++count;
+    }
+
+  pargs[count] = DEBUG_TYPE_NULL;
+
+  free (mem);
+
+  return pargs;
+}
+
+/* Convert a struct demangle_component tree describing an argument
+   type into a debug_type.  */
+
+static debug_type
+stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
+                     struct demangle_component *dc, debug_type context,
+                     bfd_boolean *pvarargs)
+{
+  debug_type dt;
+
+  if (pvarargs != NULL)
+    *pvarargs = FALSE;
+
+  switch (dc->type)
+    {
+      /* FIXME: These are demangle component types which we probably
+        need to handle one way or another.  */
+    case DEMANGLE_COMPONENT_LOCAL_NAME:
+    case DEMANGLE_COMPONENT_TYPED_NAME:
+    case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+    case DEMANGLE_COMPONENT_CTOR:
+    case DEMANGLE_COMPONENT_DTOR:
+    case DEMANGLE_COMPONENT_JAVA_CLASS:
+    case DEMANGLE_COMPONENT_RESTRICT_THIS:
+    case DEMANGLE_COMPONENT_VOLATILE_THIS:
+    case DEMANGLE_COMPONENT_CONST_THIS:
+    case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+    case DEMANGLE_COMPONENT_COMPLEX:
+    case DEMANGLE_COMPONENT_IMAGINARY:
+    case DEMANGLE_COMPONENT_VENDOR_TYPE:
+    case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+    case DEMANGLE_COMPONENT_ARRAY_TYPE:
+    case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+    case DEMANGLE_COMPONENT_ARGLIST:
+    default:
+      fprintf (stderr, _("Unrecognized demangle component\n"));
+      return NULL;
+
+    case DEMANGLE_COMPONENT_NAME:
+      if (context != NULL)
+       {
+         const debug_field *fields;
+
+         fields = debug_get_fields (dhandle, context);
+         if (fields != NULL)
+           {
+             /* Try to find this type by looking through the context
+                class.  */
+             for (; *fields != DEBUG_FIELD_NULL; fields++)
+               {
+                 debug_type ft;
+                 const char *dn;
+
+                 ft = debug_get_field_type (dhandle, *fields);
+                 if (ft == NULL)
+                   return NULL;
+                 dn = debug_get_type_name (dhandle, ft);
+                 if (dn != NULL
+                     && (int) strlen (dn) == dc->u.s_name.len
+                     && strncmp (dn, dc->u.s_name.s, dc->u.s_name.len) == 0)
+                   return ft;
+               }
+           }
+       }
+      return stab_find_tagged_type (dhandle, info, dc->u.s_name.s,
+                                   dc->u.s_name.len, DEBUG_KIND_ILLEGAL);
+
+    case DEMANGLE_COMPONENT_QUAL_NAME:
+      context = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
+                                     context, NULL);
+      if (context == NULL)
+       return NULL;
+      return stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.right,
+                                  context, NULL);
+
+    case DEMANGLE_COMPONENT_TEMPLATE:
+      {
+       char *p;
+       size_t alc;
+
+       /* We print this component to get a class name which we can
+          use.  FIXME: This probably won't work if the template uses
+          template parameters which refer to an outer template.  */
+       p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
+       if (p == NULL)
+         {
+           fprintf (stderr, _("Failed to print demangled template\n"));
+           return NULL;
+         }
+       dt = stab_find_tagged_type (dhandle, info, p, strlen (p),
+                                   DEBUG_KIND_CLASS);
+       free (p);
+       return dt;
+      }
+
+    case DEMANGLE_COMPONENT_SUB_STD:
+      return stab_find_tagged_type (dhandle, info, dc->u.s_string.string,
+                                   dc->u.s_string.len, DEBUG_KIND_ILLEGAL);
+
+    case DEMANGLE_COMPONENT_RESTRICT:
+    case DEMANGLE_COMPONENT_VOLATILE:
+    case DEMANGLE_COMPONENT_CONST:
+    case DEMANGLE_COMPONENT_POINTER:
+    case DEMANGLE_COMPONENT_REFERENCE:
+      dt = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, NULL,
+                                NULL);
+      if (dt == NULL)
+       return NULL;
+
+      switch (dc->type)
+       {
+       default:
+         abort ();
+       case DEMANGLE_COMPONENT_RESTRICT:
+         /* FIXME: We have no way to represent restrict.  */
+         return dt;
+       case DEMANGLE_COMPONENT_VOLATILE:
+         return debug_make_volatile_type (dhandle, dt);
+       case DEMANGLE_COMPONENT_CONST:
+         return debug_make_const_type (dhandle, dt);
+       case DEMANGLE_COMPONENT_POINTER:
+         return debug_make_pointer_type (dhandle, dt);
+       case DEMANGLE_COMPONENT_REFERENCE:
+         return debug_make_reference_type (dhandle, dt);
+       }
+
+    case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+      {
+       char *p;
+       size_t alc;
+       debug_type ret;
+
+       /* We print this component in order to find out the type name.
+          FIXME: Should we instead expose the
+          demangle_builtin_type_info structure?  */
+       p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
+       if (p == NULL)
+         {
+           fprintf (stderr, _("Couldn't get demangled builtin type\n"));
+           return NULL;
+         }
+
+       /* The mangling is based on the type, but does not itself
+          indicate what the sizes are.  So we have to guess.  */
+       if (strcmp (p, "signed char") == 0)
+         ret = debug_make_int_type (dhandle, 1, FALSE);
+       else if (strcmp (p, "bool") == 0)
+         ret = debug_make_bool_type (dhandle, 1);
+       else if (strcmp (p, "char") == 0)
+         ret = debug_make_int_type (dhandle, 1, FALSE);
+       else if (strcmp (p, "double") == 0)
+         ret = debug_make_float_type (dhandle, 8);
+       else if (strcmp (p, "long double") == 0)
+         ret = debug_make_float_type (dhandle, 8);
+       else if (strcmp (p, "float") == 0)
+         ret = debug_make_float_type (dhandle, 4);
+       else if (strcmp (p, "__float128") == 0)
+         ret = debug_make_float_type (dhandle, 16);
+       else if (strcmp (p, "unsigned char") == 0)
+         ret = debug_make_int_type (dhandle, 1, TRUE);
+       else if (strcmp (p, "int") == 0)
+         ret = debug_make_int_type (dhandle, 4, FALSE);
+       else if (strcmp (p, "unsigned int") == 0)
+         ret = debug_make_int_type (dhandle, 4, TRUE);
+       else if (strcmp (p, "long") == 0)
+         ret = debug_make_int_type (dhandle, 4, FALSE);
+       else if (strcmp (p, "unsigned long") == 0)
+         ret = debug_make_int_type (dhandle, 4, TRUE);
+       else if (strcmp (p, "__int128") == 0)
+         ret = debug_make_int_type (dhandle, 16, FALSE);
+       else if (strcmp (p, "unsigned __int128") == 0)
+         ret = debug_make_int_type (dhandle, 16, TRUE);
+       else if (strcmp (p, "short") == 0)
+         ret = debug_make_int_type (dhandle, 2, FALSE);
+       else if (strcmp (p, "unsigned short") == 0)
+         ret = debug_make_int_type (dhandle, 2, TRUE);
+       else if (strcmp (p, "void") == 0)
+         ret = debug_make_void_type (dhandle);
+       else if (strcmp (p, "wchar_t") == 0)
+         ret = debug_make_int_type (dhandle, 4, TRUE);
+       else if (strcmp (p, "long long") == 0)
+         ret = debug_make_int_type (dhandle, 8, FALSE);
+       else if (strcmp (p, "unsigned long long") == 0)
+         ret = debug_make_int_type (dhandle, 8, TRUE);
+       else if (strcmp (p, "...") == 0)
+         {
+           if (pvarargs == NULL)
+             fprintf (stderr, _("Unexpected demangled varargs\n"));
+           else
+             *pvarargs = TRUE;
+           ret = NULL;
+         }
+       else
+         {
+           fprintf (stderr, _("Unrecognized demangled builtin type\n"));
+           ret = NULL;
+         }
+
+       free (p);
+
+       return ret;
+      }
+    }
+}