]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Merge from mainline.
authorPhil Blundell <philb@gnu.org>
Mon, 23 Oct 2000 09:43:14 +0000 (09:43 +0000)
committerPhil Blundell <philb@gnu.org>
Mon, 23 Oct 2000 09:43:14 +0000 (09:43 +0000)
include/ChangeLog
include/demangle.h
libiberty/ChangeLog
libiberty/Makefile.in
libiberty/cp-demangle.c
libiberty/cplus-dem.c
libiberty/dyn-string.c
libiberty/testsuite/demangle-expected
libiberty/testsuite/regress-demangle

index 4408899df90a37d42b20e9ea1943198b772b42e5..a41d5b1793c7a05ec77934419f8f995fc98c78ba 100644 (file)
@@ -1,3 +1,7 @@
+2000-10-23  Philip Blundell  <pb@futuretv.com>
+
+       * demangle.h, dyn-string.h: Update from trunk version.
+
 2000-05-26  Eli Zaretskii  <eliz@is.elta.co.il>
 
        * filenames.h: New file.
index 63fe5e2adf4f0f39279a29d62aac98e42829f42e..61dd23071a451e8b27766f3ce5042cb0a3ad5552 100644 (file)
 
 /* Options passed to cplus_demangle (in 2nd parameter). */
 
-#define DMGL_NO_OPTS   0               /* For readability... */
-#define DMGL_PARAMS    (1 << 0)        /* Include function args */
-#define DMGL_ANSI      (1 << 1)        /* Include const, volatile, etc */
-#define DMGL_JAVA      (1 << 2)        /* Demangle as Java rather than C++. */
-
-#define DMGL_AUTO      (1 << 8)
-#define DMGL_GNU       (1 << 9)
-#define DMGL_LUCID     (1 << 10)
-#define DMGL_ARM       (1 << 11)
-#define DMGL_HP        (1 << 12)       /* For the HP aCC compiler; same as ARM
-                                           except for template arguments, etc. */
-#define DMGL_EDG       (1 << 13)
+#define DMGL_NO_OPTS    0              /* For readability... */
+#define DMGL_PARAMS     (1 << 0)       /* Include function args */
+#define DMGL_ANSI       (1 << 1)       /* Include const, volatile, etc */
+#define DMGL_JAVA       (1 << 2)       /* Demangle as Java rather than C++. */
+
+#define DMGL_AUTO       (1 << 8)
+#define DMGL_GNU        (1 << 9)
+#define DMGL_LUCID      (1 << 10)
+#define DMGL_ARM        (1 << 11)
+#define DMGL_HP         (1 << 12)       /* For the HP aCC compiler;
+                                            same as ARM except for
+                                            template arguments, etc. */
+#define DMGL_EDG        (1 << 13)
+#define DMGL_GNU_NEW_ABI (1 << 14)
 
 /* If none of these are set, use 'current_demangling_style' as the default. */
-#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG)
+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_NEW_ABI)
 
 /* Enumeration of possible demangling styles.
 
@@ -56,17 +58,19 @@ extern enum demangling_styles
   lucid_demangling = DMGL_LUCID,
   arm_demangling = DMGL_ARM,
   hp_demangling = DMGL_HP,
-  edg_demangling = DMGL_EDG
+  edg_demangling = DMGL_EDG,
+  gnu_new_abi_demangling = DMGL_GNU_NEW_ABI
 } current_demangling_style;
 
 /* Define string names for the various demangling styles. */
 
-#define AUTO_DEMANGLING_STYLE_STRING   "auto"
-#define GNU_DEMANGLING_STYLE_STRING    "gnu"
-#define LUCID_DEMANGLING_STYLE_STRING  "lucid"
-#define ARM_DEMANGLING_STYLE_STRING    "arm"
-#define HP_DEMANGLING_STYLE_STRING     "hp"
-#define EDG_DEMANGLING_STYLE_STRING    "edg"
+#define AUTO_DEMANGLING_STYLE_STRING         "auto"
+#define GNU_DEMANGLING_STYLE_STRING                  "gnu"
+#define LUCID_DEMANGLING_STYLE_STRING        "lucid"
+#define ARM_DEMANGLING_STYLE_STRING          "arm"
+#define HP_DEMANGLING_STYLE_STRING           "hp"
+#define EDG_DEMANGLING_STYLE_STRING          "edg"
+#define GNU_NEW_ABI_DEMANGLING_STYLE_STRING   "gnu-new-abi"
 
 /* Some macros to test what demangling style is active. */
 
@@ -77,6 +81,17 @@ extern enum demangling_styles
 #define ARM_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_ARM)
 #define HP_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_HP)
 #define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG)
+#define GNU_NEW_ABI_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_NEW_ABI)
+
+/* Provide information about the available demangle styles. This code is
+   pulled from gdb into libiberty because it is useful to binutils also.  */
+
+extern struct demangler_engine
+{
+  const char *demangling_style_name;
+  enum demangling_styles demangling_style;
+  const char *demangling_style_doc;
+} libiberty_demanglers[];
 
 extern char *
 cplus_demangle PARAMS ((const char *mangled, int options));
@@ -92,4 +107,14 @@ cplus_mangle_opname PARAMS ((const char *opname, int options));
 extern void
 set_cplus_marker_for_demangling PARAMS ((int ch));
 
+extern enum demangling_styles 
+cplus_demangle_set_style PARAMS ((enum demangling_styles style));
+
+extern enum demangling_styles 
+cplus_demangle_name_to_style PARAMS ((const char *name));
+
+/* New-ABI demangling entry point, defined in cp-demangle.c.  */
+extern char*
+cplus_demangle_new_abi PARAMS ((const char* mangled));
+
 #endif /* DEMANGLE_H */
index c858409d301e51de9e05d34cbf8f3c0b50038ddd..dbd616b1a2065e12ee209f2f6c6c89c797996db1 100644 (file)
@@ -1,3 +1,16 @@
+2000-10-17  Philip Blundell  <pb@futuretv.com>
+
+       * cp-demangle.c, dyn-string.c, cplus-dem.c: Update from trunk
+       version.
+       * testsuite/demangle-expected, testsuite/regress-demangle:
+       Likewise.
+       
+       From 2000-06-04  Alex Samuel  <samuel@codesourcery.com>
+       * Makefile.in (CFILES): Add cp-demangle.c and dyn-string.c.
+       (REQUIRED_OFILES): Add cp-demangle.o and dyn-string.o.
+       (cp-demangle.o): New dependency.
+       (dyn-string.o): Likewise.
+
 Thu Mar 16 01:33:58 2000  Jeffrey A Law  (law@cygnus.com)
 
        * Makefile.in (partition.o): Depend on config.h
index 9aa57f06d4bf141ba386a64f4a4a31a86d2f66fc..5858a5072c0a30e5ae54c3b440a68c6f352525a8 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Makefile
-#   Copyright (C) 1990, 91 - 99, 2000
+#   Copyright (C) 1990, 91, 00 - 99, 2000
 #   Free Software Foundation
 #
 # This file is part of the libiberty library.
@@ -124,7 +124,8 @@ HFILES = alloca-conf.h
 # (alphabetical), and add them to REQUIRED_OFILES or funcs in
 # configure.in.
 CFILES = asprintf.c alloca.c argv.c atexit.c basename.c bcmp.c bcopy.c       \
-       bzero.c calloc.c choose-temp.c clock.c concat.c cplus-dem.c fdmatch.c \
+       bzero.c calloc.c choose-temp.c clock.c concat.c cplus-dem.c           \
+       cp-demangle.c dyn-string.c fdmatch.c \
        fnmatch.c getcwd.c getpwd.c getopt.c getopt1.c getpagesize.c          \
        getruntime.c floatformat.c hashtab.c hex.c index.c insque.c memchr.c  \
        memcmp.c memcpy.c memmove.c memset.c mkstemps.c objalloc.c obstack.c  \
@@ -136,10 +137,10 @@ CFILES = asprintf.c alloca.c argv.c atexit.c basename.c bcmp.c bcopy.c          \
        xatexit.c xexit.c xmalloc.c xmemdup.c xstrdup.c xstrerror.c
 
 # These are always included in the library.
-REQUIRED_OFILES = argv.o choose-temp.o concat.o cplus-dem.o \
-  fdmatch.o fnmatch.o getopt.o getopt1.o getpwd.o getruntime.o hashtab.o \
-  hex.o floatformat.o objalloc.o obstack.o partition.o pexecute.o spaces.o \
-  splay-tree.o strerror.o strsignal.o xatexit.o xexit.o xmalloc.o \
+REQUIRED_OFILES = argv.o choose-temp.o concat.o cplus-dem.o cp-demangle.o \
+  dyn-string.o fdmatch.o fnmatch.o getopt.o getopt1.o getpwd.o getruntime.o \
+  hashtab.o hex.o floatformat.o objalloc.o obstack.o partition.o pexecute.o \
+  spaces.o splay-tree.o strerror.o strsignal.o xatexit.o xexit.o xmalloc.o \
   xmemdup.o xstrdup.o xstrerror.o
 
 $(TARGETLIB): $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS) $(ALLOCA)
@@ -259,6 +260,8 @@ choose-temp.o: config.h
 clock.o: config.h
 concat.o: $(INCDIR)/libiberty.h
 cplus-dem.o: config.h $(INCDIR)/demangle.h
+cp-demangle.o: config.h $(INCDIR)/dyn-string.h $(INCDIR)/demangle.h
+dyn-string.o: config.h $(INCDIR)/dyn-string.h
 fdmatch.o: $(INCDIR)/libiberty.h
 fnmatch.o: config.h $(INCDIR)/fnmatch.h
 getcwd.o: config.h
index e543edfd7666c728f5bb82a14f1ad9869555395f..1eb24027e513a8da06cc45466adf01d052abddf2 100644 (file)
@@ -1,9 +1,7 @@
 /* Demangler for IA64 / g++ standard C++ ABI.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000 CodeSourcery LLC.
    Written by Alex Samuel <samuel@codesourcery.com>. 
 
-   This file is part of GNU CC.
-
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
@@ -23,8 +21,7 @@
    the IA64 / g++ standard C++ ABI.  Use the cp_demangle function to
    demangle a mangled name, or compile with the preprocessor macro
    STANDALONE_DEMANGLER defined to create a demangling filter
-   executable (functionally similar to c++filt, but includes this
-   demangler only).  */
+   executable.  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
   (((CHAR) >= 'a' && (CHAR) <= 'z')                                     \
    || ((CHAR) >= 'A' && (CHAR) <= 'Z'))
 
-/* The prefix prepended by GCC to an identifier represnting the
-   anonymous namespace.  */
-#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
-
 /* If flag_verbose is zero, some simplifications will be made to the
    output to make it easier to read and supress details that are
    generally not of interest to the average C++ programmer.
@@ -98,10 +91,17 @@ struct substitution_def
   /* The demangled text of the substitution.  */
   dyn_string_t text;
 
+  /* The template parameter that this represents, indexed from zero.
+     If this is not a template paramter number, the value is
+     NOT_TEMPLATE_PARM.  */
+  int template_parm_number;
+
   /* Whether this substitution represents a template item.  */
   int template_p : 1;
 };
 
+#define NOT_TEMPLATE_PARM (-1)
+
 /* Data structure representing a template argument list.  */
 
 struct template_arg_list_def
@@ -172,7 +172,7 @@ typedef const char *status_t;
 #define STATUS_INTERNAL_ERROR           "Internal error."
 
 /* This status code indicates a failure in malloc or realloc.  */
-static const char *const status_allocation_failed = "Allocation failed.";
+static const charconst status_allocation_failed = "Allocation failed.";
 #define STATUS_ALLOCATION_FAILED        status_allocation_failed
 
 /* Non-zero if STATUS indicates that no error has occurred.  */
@@ -196,8 +196,8 @@ static string_list_t string_list_new
   PARAMS ((int));
 static void string_list_delete
   PARAMS ((string_list_t));
-static status_t result_add_separated_char
-  PARAMS ((demangling_t, int));
+static status_t result_close_template_list 
+  PARAMS ((demangling_t));
 static status_t result_push
   PARAMS ((demangling_t));
 static string_list_t result_pop
@@ -205,7 +205,7 @@ static string_list_t result_pop
 static int substitution_start
   PARAMS ((demangling_t));
 static status_t substitution_add
-  PARAMS ((demangling_t, int, int));
+  PARAMS ((demangling_t, int, int, int));
 static dyn_string_t substitution_get
   PARAMS ((demangling_t, int, int *));
 #ifdef CP_DEMANGLE_DEBUG
@@ -287,22 +287,6 @@ static void demangling_delete
   (dyn_string_append_char (&(DM)->result->string, (CHAR))               \
    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
 
-/* Inserts a dyn_string_t to the demangled result at position POS.  */
-#define result_insert_string(DM, POS, STRING)                           \
-  (dyn_string_insert (&(DM)->result->string, (POS), (STRING))           \
-   ? STATUS_OK : STATUS_ALLOCATION_FAILED)
-
-/* Inserts NUL-terminated string CSTR to the demangled result at
-   position POS.  */
-#define result_insert(DM, POS, CSTR)                                    \
-  (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR))        \
-   ? STATUS_OK : STATUS_ALLOCATION_FAILED)
-
-/* Inserts character CHAR to the demangled result at position POS.  */
-#define result_insert_char(DM, POS, CHAR)                               \
-  (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR))        \
-   ? STATUS_OK : STATUS_ALLOCATION_FAILED)
-
 /* The length of the current demangled result.  */
 #define result_length(DM)                                               \
   dyn_string_length (&(DM)->result->string)
@@ -313,13 +297,6 @@ static void demangling_delete
   (dyn_string_append_space (&(DM)->result->string)                      \
    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
 
-/* Appends a (less-than, greater-than) character to the result in DM
-   to (open, close) a template argument or parameter list.  Appends a
-   space first if necessary to prevent spurious elision of angle
-   brackets with the previous character.  */
-#define result_open_template_list(DM) result_add_separated_char(DM, '<')
-#define result_close_template_list(DM) result_add_separated_char(DM, '>')
-
 /* Appends a base 10 representation of VALUE to DS.  STATUS_OK on
    success.  On failure, deletes DS and returns an error code.  */
 
@@ -401,27 +378,28 @@ string_list_delete (node)
     }
 }
 
-/* Appends CHARACTER to the demangled result.  If the current trailing
-   character of the result is CHARACTER, a space is inserted first.  */
+/* Appends a greater-than character to the demangled result.  If the
+   last character is a greater-than character, a space is inserted
+   first, so that the two greater-than characters don't look like a
+   right shift token.  */
 
 static status_t
-result_add_separated_char (dm, character)
+result_close_template_list (dm)
      demangling_t dm;
-     int character;
 {
   dyn_string_t s = &dm->result->string;
 
   /* Add a space if the last character is already a closing angle
      bracket, so that a nested template arg list doesn't look like
      it's closed with a right-shift operator.  */
-  if (dyn_string_last_char (s) == character)
+  if (dyn_string_last_char (s) == '>')
     {
       if (!dyn_string_append_char (s, ' '))
        return STATUS_ALLOCATION_FAILED;
     }
 
   /* Add closing angle brackets.  */
-  if (!dyn_string_append_char (s, character))
+  if (!dyn_string_append_char (s, '>'))
     return STATUS_ALLOCATION_FAILED;
 
   return STATUS_OK;
@@ -473,13 +451,19 @@ substitution_start (dm)
 
 /* Adds the suffix of the current demangled result of DM starting at
    START_POSITION as a potential substitution.  If TEMPLATE_P is
-   non-zero, this potential substitution is a template-id.  */
+   non-zero, this potential substitution is a template-id.  
+
+   If TEMPLATE_PARM_NUMBER is not NOT_TEMPLATE_PARM, the substitution
+   is for that particular <template-param>, and is distinct from other
+   otherwise-identical types and other <template-param>s with
+   different indices.  */
 
 static status_t
-substitution_add (dm, start_position, template_p)
+substitution_add (dm, start_position, template_p, template_parm_number)
      demangling_t dm;
      int start_position;
      int template_p;
+     int template_parm_number;
 {
   dyn_string_t result = result_string (dm);
   dyn_string_t substitution = dyn_string_new (0);
@@ -497,14 +481,23 @@ substitution_add (dm, start_position, template_p)
       return STATUS_ALLOCATION_FAILED;
     }
 
+  /* Check whether SUBSTITUTION already occurs.  */
+  for (i = 0; i < dm->num_substitutions; ++i)
+    if (dyn_string_eq (dm->substitutions[i].text, substitution)
+       && dm->substitutions[i].template_parm_number == template_parm_number)
+      /* Found SUBSTITUTION already present.  */
+      {
+       /* Callers expect this function to take ownership of
+          SUBSTITUTION, so delete it.  */
+       dyn_string_delete (substitution);
+       return STATUS_OK;
+      }
+
   /* If there's no room for the new entry, grow the array.  */
   if (dm->substitutions_allocated == dm->num_substitutions)
     {
       size_t new_array_size;
-      if (dm->substitutions_allocated > 0)
-       dm->substitutions_allocated *= 2;
-      else
-       dm->substitutions_allocated = 2;
+      dm->substitutions_allocated *= 2;
       new_array_size = 
        sizeof (struct substitution_def) * dm->substitutions_allocated;
 
@@ -519,9 +512,10 @@ substitution_add (dm, start_position, template_p)
     }
 
   /* Add the substitution to the array.  */
-  i = dm->num_substitutions++;
   dm->substitutions[i].text = substitution;
   dm->substitutions[i].template_p = template_p;
+  dm->substitutions[i].template_parm_number = template_parm_number;
+  ++dm->num_substitutions;
 
 #ifdef CP_DEMANGLE_DEBUG
   substitutions_print (dm, stderr);
@@ -807,7 +801,7 @@ static status_t demangle_nested_name
 static status_t demangle_prefix
   PARAMS ((demangling_t, int *));
 static status_t demangle_unqualified_name
-  PARAMS ((demangling_t, int *));
+  PARAMS ((demangling_t));
 static status_t demangle_source_name
   PARAMS ((demangling_t));
 static status_t demangle_number
@@ -818,18 +812,12 @@ static status_t demangle_identifier
   PARAMS ((demangling_t, int, dyn_string_t));
 static status_t demangle_operator_name
   PARAMS ((demangling_t, int, int *));
-static status_t demangle_nv_offset
-  PARAMS ((demangling_t));
-static status_t demangle_v_offset
-  PARAMS ((demangling_t));
-static status_t demangle_call_offset
-  PARAMS ((demangling_t));
 static status_t demangle_special_name
   PARAMS ((demangling_t));
 static status_t demangle_ctor_dtor_name
   PARAMS ((demangling_t));
 static status_t demangle_type_ptr
-  PARAMS ((demangling_t, int *, int));
+  PARAMS ((demangling_t));
 static status_t demangle_type
   PARAMS ((demangling_t));
 static status_t demangle_CV_qualifiers
@@ -837,15 +825,15 @@ static status_t demangle_CV_qualifiers
 static status_t demangle_builtin_type
   PARAMS ((demangling_t));
 static status_t demangle_function_type
-  PARAMS ((demangling_t, int *));
+  PARAMS ((demangling_t, int));
 static status_t demangle_bare_function_type
-  PARAMS ((demangling_t, int *));
+  PARAMS ((demangling_t, int));
 static status_t demangle_class_enum_type
   PARAMS ((demangling_t, int *));
 static status_t demangle_array_type
   PARAMS ((demangling_t));
 static status_t demangle_template_param
-  PARAMS ((demangling_t));
+  PARAMS ((demangling_t, int *));
 static status_t demangle_template_args
   PARAMS ((demangling_t));
 static status_t demangle_literal
@@ -859,21 +847,19 @@ static status_t demangle_scope_expression
 static status_t demangle_expr_primary
   PARAMS ((demangling_t));
 static status_t demangle_substitution
-  PARAMS ((demangling_t, int *));
+  PARAMS ((demangling_t, int *, int *));
 static status_t demangle_local_name
   PARAMS ((demangling_t));
 static status_t demangle_discriminator 
   PARAMS ((demangling_t, int));
 static status_t cp_demangle
   PARAMS ((const char *, dyn_string_t));
-#ifdef IN_LIBGCC2
 static status_t cp_demangle_type
   PARAMS ((const char*, dyn_string_t));
-#endif
 
 /* When passed to demangle_bare_function_type, indicates that the
    function's return type is not encoded before its parameter types.  */
-#define BFT_NO_RETURN_TYPE    NULL
+#define BFT_NO_RETURN_TYPE    -1
 
 /* Check that the next character is C.  If so, consume it.  If not,
    return an error.  */
@@ -924,7 +910,7 @@ static status_t
 demangle_encoding (dm)
      demangling_t dm;
 {
-  int encode_return_type;
+  int template_p;
   int start_position;
   template_arg_list_t old_arg_list = current_template_arg_list (dm);
   char peek = peek_char (dm);
@@ -940,18 +926,18 @@ demangle_encoding (dm)
   else
     {
       /* Now demangle the name.  */
-      RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));
+      RETURN_IF_ERROR (demangle_name (dm, &template_p));
 
       /* If there's anything left, the name was a function name, with
         maybe its return type, and its parameters types, following.  */
       if (!end_of_name_p (dm) 
          && peek_char (dm) != 'E')
        {
-         if (encode_return_type)
+         if (template_p)
            /* Template functions have their return type encoded.  The
               return type should be inserted at start_position.  */
            RETURN_IF_ERROR 
-             (demangle_bare_function_type (dm, &start_position));
+             (demangle_bare_function_type (dm, start_position));
          else
            /* Non-template functions don't have their return type
               encoded.  */
@@ -982,32 +968,24 @@ demangle_encoding (dm)
                         ::= <substitution>  */
 
 static status_t
-demangle_name (dm, encode_return_type)
+demangle_name (dm, template_p)
      demangling_t dm;
-     int *encode_return_type;
+     int *template_p;
 {
+  int special_std_substitution;
   int start = substitution_start (dm);
-  char peek = peek_char (dm);
-  int is_std_substitution = 0;
-
-  /* Generally, the return type is encoded if the function is a
-     template-id, and suppressed otherwise.  There are a few cases,
-     though, in which the return type is not encoded even for a
-     templated function.  In these cases, this flag is set.  */
-  int suppress_return_type = 0;
 
   DEMANGLE_TRACE ("name", dm);
 
-  switch (peek)
+  switch (peek_char (dm))
     {
     case 'N':
       /* This is a <nested-name>.  */
-      RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));
+      RETURN_IF_ERROR (demangle_nested_name (dm, template_p));
       break;
 
     case 'Z':
       RETURN_IF_ERROR (demangle_local_name (dm));
-      *encode_return_type = 0;
       break;
 
     case 'S':
@@ -1018,45 +996,48 @@ demangle_name (dm, encode_return_type)
          (void) next_char (dm);
          (void) next_char (dm);
          RETURN_IF_ERROR (result_append (dm, "std::"));
-         RETURN_IF_ERROR 
-           (demangle_unqualified_name (dm, &suppress_return_type));
-         is_std_substitution = 1;
+         RETURN_IF_ERROR (demangle_unqualified_name (dm));
        }
       else
-       RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
+       {
+         RETURN_IF_ERROR (demangle_substitution (dm, template_p,
+                                                 &special_std_substitution));
+         if (special_std_substitution)
+           {
+             /* This was the magic `std::' substitution.  We can have
+                a <nested-name> or one of the unscoped names
+                following.  */
+             RETURN_IF_ERROR (result_append (dm, "::"));
+             RETURN_IF_ERROR (demangle_name (dm, template_p));
+           }
+       }
       /* Check if a template argument list immediately follows.
         If so, then we just demangled an <unqualified-template-name>.  */
       if (peek_char (dm) == 'I') 
        {
-         /* A template name of the form std::<unqualified-name> is a
-             substitution candidate.  */
-         if (is_std_substitution)
-           RETURN_IF_ERROR (substitution_add (dm, start, 0));
-         /* Demangle the <template-args> here.  */
+         RETURN_IF_ERROR (substitution_add (dm, start, 0, 
+                                            NOT_TEMPLATE_PARM));
          RETURN_IF_ERROR (demangle_template_args (dm));
-         *encode_return_type = !suppress_return_type;
        }
-      else
-       *encode_return_type = 0;
-
       break;
 
     default:
       /* This is an <unscoped-name> or <unscoped-template-name>.  */
-      RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));
+      RETURN_IF_ERROR (demangle_unqualified_name (dm));
 
       /* If the <unqualified-name> is followed by template args, this
         is an <unscoped-template-name>.  */
       if (peek_char (dm) == 'I')
        {
          /* Add a substitution for the unqualified template name.  */
-         RETURN_IF_ERROR (substitution_add (dm, start, 0));
+         RETURN_IF_ERROR (substitution_add (dm, start, 0, 
+                                            NOT_TEMPLATE_PARM));
 
          RETURN_IF_ERROR (demangle_template_args (dm));
-         *encode_return_type = !suppress_return_type;
+         *template_p = 1;
        }
       else
-       *encode_return_type = 0;
+       *template_p = 0;
 
       break;
     }
@@ -1066,12 +1047,12 @@ demangle_name (dm, encode_return_type)
 
 /* Demangles and emits a <nested-name>. 
 
-    <nested-name>     ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E  */
+    <nested-name>       ::= N [<CV-qualifiers>] <prefix> <component> E  */
 
 static status_t
-demangle_nested_name (dm, encode_return_type)
+demangle_nested_name (dm, template_p)
      demangling_t dm;
-     int *encode_return_type;
+     int *template_p;
 {
   char peek;
 
@@ -1096,9 +1077,9 @@ demangle_nested_name (dm, encode_return_type)
       RETURN_IF_ERROR (result_append_space (dm));
     }
   
-  RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
-  /* No need to demangle the final <unqualified-name>; demangle_prefix
-     will handle it.  */
+  RETURN_IF_ERROR (demangle_prefix (dm, template_p));
+  /* No need to demangle the final <component>; demangle_prefix will
+     handle it.  */
   RETURN_IF_ERROR (demangle_char (dm, 'E'));
 
   return STATUS_OK;
@@ -1106,52 +1087,41 @@ demangle_nested_name (dm, encode_return_type)
 
 /* Demangles and emits a <prefix>.
 
-    <prefix>            ::= <prefix> <unqualified-name>
+    <prefix>            ::= <prefix> <component>
                         ::= <template-prefix> <template-args>
                        ::= # empty
                        ::= <substitution>
 
     <template-prefix>   ::= <prefix>
-                        ::= <substitution>  */
+                        ::= <substitution>
+
+    <component>         ::= <unqualified-name>
+                        ::= <local-name>  */
 
 static status_t
-demangle_prefix (dm, encode_return_type)
+demangle_prefix (dm, template_p)
      demangling_t dm;
-     int *encode_return_type;
+     int *template_p;
 {
   int start = substitution_start (dm);
   int nested = 0;
 
-  /* ENCODE_RETURN_TYPE is updated as we decend the nesting chain.
-     After <template-args>, it is set to non-zero; after everything
-     else it is set to zero.  */
-
-  /* Generally, the return type is encoded if the function is a
-     template-id, and suppressed otherwise.  There are a few cases,
-     though, in which the return type is not encoded even for a
-     templated function.  In these cases, this flag is set.  */
-  int suppress_return_type = 0;
+  /* TEMPLATE_P is updated as we decend the nesting chain.  After
+     <template-args>, it is set to non-zero; after everything else it
+     is set to zero.  */
 
   DEMANGLE_TRACE ("prefix", dm);
 
   while (1)
     {
       char peek;
+      int unused;
 
       if (end_of_name_p (dm))
        return "Unexpected end of name in <compound-name>.";
 
       peek = peek_char (dm);
       
-      /* We'll initialize suppress_return_type to false, and set it to true
-        if we end up demangling a constructor name.  However, make
-        sure we're not actually about to demangle template arguments
-        -- if so, this is the <template-args> following a
-        <template-prefix>, so we'll want the previous flag value
-        around.  */
-      if (peek != 'I')
-       suppress_return_type = 0;
-
       if (IS_DIGIT ((unsigned char) peek)
          || (peek >= 'a' && peek <= 'z')
          || peek == 'C' || peek == 'D'
@@ -1165,30 +1135,25 @@ demangle_prefix (dm, encode_return_type)
 
          if (peek == 'S')
            /* The substitution determines whether this is a
-              template-id.  */
-           RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
+              template-id.   */
+           RETURN_IF_ERROR (demangle_substitution (dm, template_p, 
+                                                   &unused));
          else
            {
-             /* It's just a name.  */
-             RETURN_IF_ERROR 
-               (demangle_unqualified_name (dm, &suppress_return_type));
-             *encode_return_type = 0;
+             RETURN_IF_ERROR (demangle_unqualified_name (dm));
+             *template_p = 0;
            }
        }
       else if (peek == 'Z')
        RETURN_IF_ERROR (demangle_local_name (dm));
       else if (peek == 'I')
        {
+         if (*template_p)
+           return STATUS_INTERNAL_ERROR;
+         /* The template name is a substitution candidate.  */
+         RETURN_IF_ERROR (substitution_add (dm, start, 0, NOT_TEMPLATE_PARM));
          RETURN_IF_ERROR (demangle_template_args (dm));
-
-         /* Now we want to indicate to the caller that we've
-            demangled template arguments, thus the prefix was a
-            <template-prefix>.  That's so that the caller knows to
-            demangle the function's return type, if this turns out to
-            be a function name.  But, if it's a member template
-            constructor or a templated conversion operator, report it
-            as untemplated.  Those never get encoded return types.  */
-         *encode_return_type = !suppress_return_type;
+         *template_p = 1;
        }
       else if (peek == 'E')
        /* All done.  */
@@ -1196,56 +1161,38 @@ demangle_prefix (dm, encode_return_type)
       else
        return "Unexpected character in <compound-name>.";
 
-      if (peek != 'S'
-         && peek_char (dm) != 'E')
-       /* Add a new substitution for the prefix thus far.  */
-       RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));
+      /* Add a new substitution for the prefix thus far.  */
+      RETURN_IF_ERROR (substitution_add (dm, start, *template_p, 
+                                        NOT_TEMPLATE_PARM));
     }
 }
 
-/* Demangles and emits an <unqualified-name>.  If this
-   <unqualified-name> is for a special function type that should never
-   have its return type encoded (particularly, a constructor or
-   conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise,
-   it is set to zero.
+/* Demangles and emits an <unqualified-name>.  If the
+   <unqualified-name> is a function and the first element in the
+   argument list should be taken to be its return type,
+   ENCODE_RETURN_TYPE is non-zero.
 
     <unqualified-name>  ::= <operator-name>
                        ::= <special-name>  
                        ::= <source-name>  */
 
 static status_t
-demangle_unqualified_name (dm, suppress_return_type)
+demangle_unqualified_name (dm)
      demangling_t dm;
-     int *suppress_return_type;
 {
   char peek = peek_char (dm);
 
   DEMANGLE_TRACE ("unqualified-name", dm);
 
-  /* By default, don't force suppression of the return type (though
-     non-template functions still don't get a return type encoded).  */ 
-  *suppress_return_type = 0;
-
   if (IS_DIGIT ((unsigned char) peek))
     RETURN_IF_ERROR (demangle_source_name (dm));
   else if (peek >= 'a' && peek <= 'z')
     {
       int num_args;
-
-      /* Conversion operators never have a return type encoded.  */
-      if (peek == 'c' && peek_char_next (dm) == 'v')
-       *suppress_return_type = 1;
-
       RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args));
     }
   else if (peek == 'C' || peek == 'D')
-    {
-      /* Constructors never have a return type encoded.  */
-      if (peek == 'C')
-       *suppress_return_type = 1;
-
-      RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
-    }
+    RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
   else
     return "Unexpected character in <unqualified-name>.";
 
@@ -1383,29 +1330,6 @@ demangle_identifier (dm, length, identifier)
        return STATUS_ALLOCATION_FAILED;
     }
 
-  /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'
-     followed by the source file name and some random characters.
-     Unless we're in strict mode, decipher these names appropriately.  */
-  if (!flag_strict)
-    {
-      char *name = dyn_string_buf (identifier);
-      int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
-
-      /* Compare the first, fixed part.  */
-      if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
-        {
-         name += prefix_length;
-         /* The next character might be a period, an underscore, or
-            dollar sign, depending on the target architecture's
-            assembler's capabilities.  After that comes an `N'.  */
-         if ((*name == '.' || *name == '_' || *name == '$')
-             && *(name + 1) == 'N')
-           /* This looks like the anonymous namespace identifier.
-              Replace it with something comprehensible.  */
-           dyn_string_copy_cstr (identifier, "(anonymous namespace)");
-       }
-    }
-
   return STATUS_OK;
 }
 
@@ -1464,7 +1388,7 @@ demangle_identifier (dm, length, identifier)
                   ::= qu        # ?
                   ::= sz        # sizeof 
                   ::= cv <type> # cast        
-                 ::= v [0-9] <source-name>  # vendor extended operator  */
+                  ::= vx <source-name>  # vendor extended operator  */
 
 static status_t
 demangle_operator_name (dm, short_name, num_args)
@@ -1525,7 +1449,6 @@ demangle_operator_name (dm, short_name, num_args)
     { "pm", "->*"      , 2 },
     { "pp", "++"       , 1 },
     { "ps", "+"        , 1 },
-    { "pt", "->"       , 2 },
     { "qu", "?"        , 3 },
     { "rM", "%="       , 2 },
     { "rS", ">>="      , 2 },
@@ -1544,10 +1467,10 @@ demangle_operator_name (dm, short_name, num_args)
 
   DEMANGLE_TRACE ("operator-name", dm);
 
-  /* Is this a vendor-extended operator?  */
-  if (c0 == 'v' && IS_DIGIT (c1))
+  /* Is this a vendor extended operator?  */
+  if (c0 == 'v' && c1 == 'x')
     {
-      RETURN_IF_ERROR (result_append (dm, "operator "));
+      RETURN_IF_ERROR (result_append (dm, "operator"));
       RETURN_IF_ERROR (demangle_source_name (dm));
       *num_args = 0;
       return STATUS_OK;
@@ -1593,157 +1516,22 @@ demangle_operator_name (dm, short_name, num_args)
     }
 }
 
-/* Demangles and omits an <nv-offset>.
-
-    <nv-offset> ::= <offset number>   # non-virtual base override  */
-
-static status_t
-demangle_nv_offset (dm)
-     demangling_t dm;
-{
-  dyn_string_t number;
-  status_t status = STATUS_OK;
-
-  DEMANGLE_TRACE ("h-offset", dm);
-
-  /* Demangle the offset.  */
-  number = dyn_string_new (4);
-  if (number == NULL)
-    return STATUS_ALLOCATION_FAILED;
-  demangle_number_literally (dm, number, 10, 1);
-
-  /* Don't display the offset unless in verbose mode.  */
-  if (flag_verbose)
-    {
-      status = result_append (dm, " [nv:");
-      if (STATUS_NO_ERROR (status))
-       status = result_append_string (dm, number);
-      if (STATUS_NO_ERROR (status))
-       status = result_append_char (dm, ']');
-    }
-
-  /* Clean up.  */
-  dyn_string_delete (number);
-  RETURN_IF_ERROR (status);
-  return STATUS_OK;
-}
-
-/* Demangles and emits a <v-offset>. 
-
-    <v-offset>  ::= <offset number> _ <virtual offset number>
-                       # virtual base override, with vcall offset  */
-
-static status_t
-demangle_v_offset (dm)
-     demangling_t dm;
-{
-  dyn_string_t number;
-  status_t status = STATUS_OK;
-
-  DEMANGLE_TRACE ("v-offset", dm);
-
-  /* Demangle the offset.  */
-  number = dyn_string_new (4);
-  if (number == NULL)
-    return STATUS_ALLOCATION_FAILED;
-  demangle_number_literally (dm, number, 10, 1);
-
-  /* Don't display the offset unless in verbose mode.  */
-  if (flag_verbose)
-    {
-      status = result_append (dm, " [v:");
-      if (STATUS_NO_ERROR (status))
-       status = result_append_string (dm, number);
-      if (STATUS_NO_ERROR (status))
-       result_append_char (dm, ',');
-    }
-  dyn_string_delete (number);
-  RETURN_IF_ERROR (status);
-
-  /* Demangle the separator.  */
-  RETURN_IF_ERROR (demangle_char (dm, '_'));
-
-  /* Demangle the vcall offset.  */
-  number = dyn_string_new (4);
-  if (number == NULL)
-    return STATUS_ALLOCATION_FAILED;
-  demangle_number_literally (dm, number, 10, 1);
-
-  /* Don't display the vcall offset unless in verbose mode.  */
-  if (flag_verbose)
-    {
-      status = result_append_string (dm, number);
-      if (STATUS_NO_ERROR (status))
-       status = result_append_char (dm, ']');
-    }
-  dyn_string_delete (number);
-  RETURN_IF_ERROR (status);
-
-  return STATUS_OK;
-}
-
-/* Demangles and emits a <call-offset>.
-
-    <call-offset> ::= h <nv-offset> _
-                 ::= v <v-offset> _  */
-
-static status_t
-demangle_call_offset (dm)
-     demangling_t dm;
-{
-  DEMANGLE_TRACE ("call-offset", dm);
-
-  switch (peek_char (dm))
-    {
-    case 'h':
-      advance_char (dm);
-      /* Demangle the offset.  */
-      RETURN_IF_ERROR (demangle_nv_offset (dm));
-      /* Demangle the separator.  */
-      RETURN_IF_ERROR (demangle_char (dm, '_'));
-      break;
-
-    case 'v':
-      advance_char (dm);
-      /* Demangle the offset.  */
-      RETURN_IF_ERROR (demangle_v_offset (dm));
-      /* Demangle the separator.  */
-      RETURN_IF_ERROR (demangle_char (dm, '_'));
-      break;
-
-    default:
-      return "Unrecognized <call-offset>.";
-    }
-
-  return STATUS_OK;
-}
-
 /* Demangles and emits a <special-name>.  
 
     <special-name> ::= GV <object name>   # Guard variable
+                   ::= Th[n] <offset number> _ <base name> <base encoding>
+                                          # non-virtual base override thunk
+                   ::= Tv[n] <offset number> _ <vcall offset number> 
+                         _ <base encoding>
+                                          # virtual base override thunk
                    ::= TV <type>          # virtual table
                    ::= TT <type>          # VTT
                    ::= TI <type>          # typeinfo structure
                   ::= TS <type>          # typeinfo name  
 
-   Other relevant productions include thunks:
-
-    <special-name> ::= T <call-offset> <base encoding>
-                        # base is the nominal target function of thunk
-
-    <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
-                        # base is the nominal target function of thunk
-                        # first call-offset is 'this' adjustment
-                        # second call-offset is result adjustment
-
-   where
-
-    <call-offset>  ::= h <nv-offset> _
-                  ::= v <v-offset> _
-
    Also demangles the special g++ manglings,
 
-    <special-name> ::= TC <type> <offset number> _ <base type>
+    <special-name> ::= CT <type> <offset number> _ <base type>
                                           # construction vtable
                   ::= TF <type>          # typeinfo function (old ABI only)
                   ::= TJ <type>          # java Class structure  */
@@ -1821,7 +1609,20 @@ demangle_special_name (dm)
          /* Non-virtual thunk.  */
          advance_char (dm);
          RETURN_IF_ERROR (result_append (dm, "non-virtual thunk"));
-         RETURN_IF_ERROR (demangle_nv_offset (dm));
+         /* Demangle and emit the offset.  */
+         number = dyn_string_new (4);
+         if (number == NULL)
+           return STATUS_ALLOCATION_FAILED;
+         demangle_number_literally (dm, number, 10, 1);
+         /* Don't display the offset unless in verbose mode.  */
+         if (flag_verbose)
+           {
+             status = result_append_char (dm, ' ');
+             if (STATUS_NO_ERROR (status))
+               status = result_append_string (dm, number);
+           }
+         dyn_string_delete (number);
+         RETURN_IF_ERROR (status);
          /* Demangle the separator.  */
          RETURN_IF_ERROR (demangle_char (dm, '_'));
          /* Demangle and emit the target name and function type.  */
@@ -1832,23 +1633,41 @@ demangle_special_name (dm)
        case 'v':
          /* Virtual thunk.  */
          advance_char (dm);
-         RETURN_IF_ERROR (result_append (dm, "virtual thunk"));
-         RETURN_IF_ERROR (demangle_v_offset (dm));
+         RETURN_IF_ERROR (result_append (dm, "virtual thunk "));
+         /* Demangle and emit the offset.  */
+         number = dyn_string_new (4);
+         if (number == NULL)
+           return STATUS_ALLOCATION_FAILED;
+         demangle_number_literally (dm, number, 10, 1);
+         /* Don't display the offset unless in verbose mode.  */
+         if (flag_verbose)
+           {
+             status = result_append_string (dm, number);
+             if (STATUS_NO_ERROR (status))
+               result_append_char (dm, ' ');
+           }
+         dyn_string_delete (number);
+         RETURN_IF_ERROR (status);
+         /* Demangle the separator.  */
+         RETURN_IF_ERROR (demangle_char (dm, '_'));
+         /* Demangle and emit the vcall offset.  */
+         number = dyn_string_new (4);
+         if (number == NULL)
+           return STATUS_ALLOCATION_FAILED;
+         demangle_number_literally (dm, number, 10, 1);
+         /* Don't display the vcall offset unless in verbose mode.  */
+         if (flag_verbose)
+           {
+             status = result_append_string (dm, number);
+             if (STATUS_NO_ERROR (status))
+               status = result_append_char (dm, ' ');
+           }
+         dyn_string_delete (number);
+         RETURN_IF_ERROR (status);
          /* Demangle the separator.  */
          RETURN_IF_ERROR (demangle_char (dm, '_'));
          /* Demangle and emit the target function.  */
-         RETURN_IF_ERROR (result_append (dm, " to "));
-         RETURN_IF_ERROR (demangle_encoding (dm));
-         break;
-
-       case 'c':
-         /* Covariant return thunk.  */
-         advance_char (dm);
-         RETURN_IF_ERROR (result_append (dm, "covariant return thunk"));
-         RETURN_IF_ERROR (demangle_call_offset (dm));
-         RETURN_IF_ERROR (demangle_call_offset (dm));
-         /* Demangle and emit the target function.  */
-         RETURN_IF_ERROR (result_append (dm, " to "));
+         RETURN_IF_ERROR (result_append (dm, "to "));
          RETURN_IF_ERROR (demangle_encoding (dm));
          break;
 
@@ -1917,6 +1736,7 @@ demangle_special_name (dm)
                    ::= C1  # complete object (in-charge) ctor
                    ::= C2  # base object (not-in-charge) ctor
                    ::= C3  # complete object (in-charge) allocating ctor
+                   ::= C4  # base object (not-in-charge) allocating ctor
                    ::= D0  # deleting (in-charge) dtor
                    ::= D1  # complete object (in-charge) dtor
                    ::= D2  # base object (not-in-charge) dtor  */
@@ -1929,7 +1749,8 @@ demangle_ctor_dtor_name (dm)
   {
     "in-charge",
     "not-in-charge",
-    "allocating"
+    "in-charge allocating",
+    "not-in-charge allocating"
   };
   static const char *const dtor_flavors[] = 
   {
@@ -1947,7 +1768,7 @@ demangle_ctor_dtor_name (dm)
     {
       /* A constructor name.  Consume the C.  */
       advance_char (dm);
-      if (peek_char (dm) < '1' || peek_char (dm) > '3')
+      if (peek_char (dm) < '1' || peek_char (dm) > '4')
        return "Unrecognized constructor.";
       RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
       /* Print the flavor of the constructor if in verbose mode.  */
@@ -1989,19 +1810,6 @@ demangle_ctor_dtor_name (dm)
    a pointer to data or pointer to function to construct the right
    output syntax.  C++'s pointer syntax is hairy.  
 
-   This function adds substitution candidates for every nested
-   pointer/reference type it processes, including the outermost, final
-   type, assuming the substitution starts at SUBSTITUTION_START in the
-   demangling result.  For example, if this function demangles
-   `PP3Foo', it will add a substitution for `Foo', `Foo*', and
-   `Foo**', in that order.
-
-   *INSERT_POS is a quantity used internally, when this function calls
-   itself recursively, to figure out where to insert pointer
-   punctuation on the way up.  On entry to this function, INSERT_POS
-   should point to a temporary value, but that value need not be
-   initialized.
-
      <type> ::= P <type>
             ::= R <type>
             ::= <pointer-to-member-type>
@@ -2009,137 +1817,105 @@ demangle_ctor_dtor_name (dm)
      <pointer-to-member-type> ::= M </class/ type> </member/ type>  */
 
 static status_t
-demangle_type_ptr (dm, insert_pos, substitution_start)
+demangle_type_ptr (dm)
      demangling_t dm;
-     int *insert_pos;
-     int substitution_start;
 {
   char next;
   status_t status;
-  int is_substitution_candidate = 1;
+
+  /* Collect pointer symbols into this string.  */
+  dyn_string_t symbols = dyn_string_new (10);
 
   DEMANGLE_TRACE ("type*", dm);
 
+  if (symbols == NULL)
+    return STATUS_ALLOCATION_FAILED;
+
   /* Scan forward, collecting pointers and references into symbols,
      until we hit something else.  Then emit the type.  */
-  next = peek_char (dm);
-  if (next == 'P')
-    {
-      /* A pointer.  Snarf the `P'.  */
-      advance_char (dm);
-      /* Demangle the underlying type.  */
-      RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos, 
-                                         substitution_start));
-      /* Insert an asterisk where we're told to; it doesn't
-        necessarily go at the end.  */
-      RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
-      /* The next (outermost) pointer or reference character should go
-        after this one.  */
-      ++(*insert_pos);
-    }
-  else if (next == 'R')
-    {
-      /* A reference.  Snarf the `R'.  */
-      advance_char (dm);
-      /* Demangle the underlying type.  */
-      RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos, 
-                                         substitution_start));
-      /* Insert an ampersand where we're told to; it doesn't
-        necessarily go at the end.  */
-      RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
-      /* The next (outermost) pointer or reference character should go
-        after this one.  */
-      ++(*insert_pos);
-    }
-  else if (next == 'M')
+  while (1)
     {
-      /* A pointer-to-member.  */
-      dyn_string_t class_type;
-      
-      /* Eat the 'M'.  */
-      advance_char (dm);
-      
-      /* Capture the type of which this is a pointer-to-member.  */
-      RETURN_IF_ERROR (result_push (dm));
-      RETURN_IF_ERROR (demangle_type (dm));
-      class_type = (dyn_string_t) result_pop (dm);
-      
-      if (peek_char (dm) == 'F')
-       /* A pointer-to-member function.  We want output along the
-          lines of `void (C::*) (int, int)'.  Demangle the function
-          type, which would in this case give `void () (int, int)'
-          and set *insert_pos to the spot between the first
-          parentheses.  */
-       status = demangle_type_ptr (dm, insert_pos, substitution_start);
-      else
-        {
-         /* A pointer-to-member variable.  Demangle the type of the
-             pointed-to member.  */
+      next = peek_char (dm);
+      if (next == 'P')
+       {
+         if (!dyn_string_append_char (symbols, '*'))
+           return STATUS_ALLOCATION_FAILED;
+         advance_char (dm);
+       }
+      else if (next == 'R')
+       {
+         if (!dyn_string_append_char (symbols, '&'))
+           return STATUS_ALLOCATION_FAILED;
+         advance_char (dm);
+       }
+      else if (next == 'M')
+       {
+         /* Pointer-to-member.  */
+         dyn_string_t class_type;
+
+         /* Eat the 'M'.  */
+         advance_char (dm);
+
+         /* Capture the type of which this is a pointer-to-member.  */
+         RETURN_IF_ERROR (result_push (dm));
+         RETURN_IF_ERROR (demangle_type (dm));
+         class_type = (dyn_string_t) result_pop (dm);
+
+         /* Build the pointer-to-member notation.  It comes before
+            other pointer and reference qualifiers -- */
+         if (!dyn_string_prepend_cstr (symbols, "::*"))
+           return STATUS_ALLOCATION_FAILED;
+         if (!dyn_string_prepend (symbols, class_type))
+           return STATUS_ALLOCATION_FAILED;
+         dyn_string_delete (class_type);
+
+         if (peek_char (dm) == 'F')
+           continue;
+
+         /* Demangle the type of the pointed-to member.  */
          status = demangle_type (dm);
          /* Make it pretty.  */
          if (STATUS_NO_ERROR (status))
            status = result_append_space (dm);
-         /* The pointer-to-member notation (e.g. `C::*') follows the
-             member's type.  */
-         *insert_pos = result_length (dm);
+         /* Add the pointer-to-member syntax, and other pointer and
+            reference symbols.  */
+         if (STATUS_NO_ERROR (status))
+           status = result_append_string (dm, symbols);
+         /* Clean up.  */
+         dyn_string_delete (symbols);
+
+         RETURN_IF_ERROR (status);
+         return STATUS_OK;
        }
+      else if (next == 'F')
+       {
+         /* Ooh, tricky, a pointer-to-function.  */
+         int position = result_length (dm);
+         status = result_append_char (dm, '(');
+         if (STATUS_NO_ERROR (status))
+           status = result_append_string (dm, symbols);
+         if (STATUS_NO_ERROR (status))
+           status = result_append_char (dm, ')');
+         dyn_string_delete (symbols);
+         RETURN_IF_ERROR (status);
 
-      /* Build the pointer-to-member notation.  */
-      if (STATUS_NO_ERROR (status))
-       status = result_insert (dm, *insert_pos, "::*");
-      if (STATUS_NO_ERROR (status))
-       status = result_insert_string (dm, *insert_pos, class_type);
-      /* There may be additional levels of (pointer or reference)
-        indirection in this type.  If so, the `*' and `&' should be
-        added after the pointer-to-member notation (e.g. `C::*&' for
-        a reference to a pointer-to-member of class C).  */
-      *insert_pos += dyn_string_length (class_type) + 3;
+         RETURN_IF_ERROR (demangle_function_type (dm, position));
+         return STATUS_OK;
+       }
+      else
+       {
+         /* No more pointe or reference tokens.  Finish up.  */
+         status = demangle_type (dm);
 
-      /* Clean up. */
-      dyn_string_delete (class_type);
+         if (STATUS_NO_ERROR (status))
+           status = result_append_string (dm, symbols);
+         dyn_string_delete (symbols);
+         RETURN_IF_ERROR (status);
 
-      RETURN_IF_ERROR (status);
-    }
-  else if (next == 'F')
-    {
-      /* Ooh, tricky, a pointer-to-function.  When we demangle the
-        function type, the return type should go at the very
-        beginning.  */
-      *insert_pos = result_length (dm);
-      /* The parentheses indicate this is a function pointer or
-        reference type.  */
-      RETURN_IF_ERROR (result_append (dm, "()"));
-      /* Now demangle the function type.  The return type will be
-        inserted before the `()', and the argument list will go after
-        it.  */
-      RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
-      /* We should now have something along the lines of 
-        `void () (int, int)'.  The pointer or reference characters
-        have to inside the first set of parentheses.  *insert_pos has
-        already been updated to point past the end of the return
-        type.  Move it one character over so it points inside the
-        `()'.  */
-      ++(*insert_pos);
-    }
-  else
-    {
-      /* No more pointer or reference tokens; this is therefore a
-        pointer to data.  Finish up by demangling the underlying
-        type.  */
-      RETURN_IF_ERROR (demangle_type (dm));
-      /* The pointer or reference characters follow the underlying
-        type, as in `int*&'.  */
-      *insert_pos = result_length (dm);
-      /* Because of the production <type> ::= <substitution>,
-        demangle_type will already have added the underlying type as
-        a substitution candidate.  Don't do it again.  */
-      is_substitution_candidate = 0;
+         RETURN_IF_ERROR (status);
+         return STATUS_OK;
+       }
     }
-  
-  if (is_substitution_candidate)
-    RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
-  
-  return STATUS_OK;
 }
 
 /* Demangles and emits a <type>.  
@@ -2150,7 +1926,6 @@ demangle_type_ptr (dm, insert_pos, substitution_start)
           ::= <array-type>
           ::= <pointer-to-member-type>
           ::= <template-param>
-          ::= <template-template-param> <template-args>
            ::= <CV-qualifiers> <type>
           ::= P <type>   # pointer-to
           ::= R <type>   # reference-to
@@ -2166,28 +1941,22 @@ demangle_type (dm)
   int start = substitution_start (dm);
   char peek = peek_char (dm);
   char peek_next;
-  int encode_return_type = 0;
+  int template_p = 0;
+  int special_std_substitution;
+  int is_builtin_type = 0;
   template_arg_list_t old_arg_list = current_template_arg_list (dm);
-  int insert_pos;
-
-  /* A <type> can be a <substitution>; therefore, this <type> is a
-     substitution candidate unless a special condition holds (see
-     below).  */
-  int is_substitution_candidate = 1;
+  int template_parm = NOT_TEMPLATE_PARM;
 
   DEMANGLE_TRACE ("type", dm);
 
   /* A <class-enum-type> can start with a digit (a <source-name>), an
      N (a <nested-name>), or a Z (a <local-name>).  */
   if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
-    RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type));
-  /* Lower-case letters begin <builtin-type>s, except for `r', which
-     denotes restrict.  */
-  else if (peek >= 'a' && peek <= 'z' && peek != 'r')
+    RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p));
+  else if (peek >= 'a' && peek <= 'z')
     {
       RETURN_IF_ERROR (demangle_builtin_type (dm));
-      /* Built-in types are not substitution candidates.  */
-      is_substitution_candidate = 0;
+      is_builtin_type = 1;
     }
   else
     switch (peek)
@@ -2195,9 +1964,6 @@ demangle_type (dm)
       case 'r':
       case 'V':
       case 'K':
-       /* CV-qualifiers (including restrict).  We have to demangle
-          them off to the side, since C++ syntax puts them in a funny
-          place for qualified pointer and reference types.  */
        {
          status_t status;
          dyn_string_t cv_qualifiers = dyn_string_new (24);
@@ -2240,28 +2006,7 @@ demangle_type (dm)
        break;
 
       case 'T':
-       /* It's either a <template-param> or a
-          <template-template-param>.  In either case, demangle the
-          `T' token first.  */
-       RETURN_IF_ERROR (demangle_template_param (dm));
-
-       /* Check for a template argument list; if one is found, it's a
-            <template-template-param> ::= <template-param>
-                                       ::= <substitution>  */
-       if (peek_char (dm) == 'I')
-         {
-           /* Add a substitution candidate.  The template parameter
-              `T' token is a substitution candidate by itself,
-              without the template argument list.  */
-           RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
-
-           /* Now demangle the template argument list.  */
-           RETURN_IF_ERROR (demangle_template_args (dm));
-           /* The entire type, including the template template
-              parameter and its argument list, will be added as a
-              substitution candidate below.  */
-         }
-
+       RETURN_IF_ERROR (demangle_template_param (dm, &template_parm));
        break;
 
       case 'S':
@@ -2271,56 +2016,16 @@ demangle_type (dm)
           or underscore.  */
        peek_next = peek_char_next (dm);
        if (IS_DIGIT (peek_next) || peek_next == '_')
-         {
-           RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));
-           
-           /* The substituted name may have been a template name.
-              Check if template arguments follow, and if so, demangle
-              them.  */
-           if (peek_char (dm) == 'I')
-             RETURN_IF_ERROR (demangle_template_args (dm));
-           else
-             /* A substitution token is not itself a substitution
-                candidate.  (However, if the substituted template is
-                instantiated, the resulting type is.)  */
-             is_substitution_candidate = 0;
-         }
+         RETURN_IF_ERROR (demangle_substitution (dm, &template_p,
+                                                 &special_std_substitution));
        else
-         {
-           /* Now some trickiness.  We have a special substitution
-              here.  Often, the special substitution provides the
-              name of a template that's subsequently instantiated,
-              for instance `SaIcE' => std::allocator<char>.  In these
-              cases we need to add a substitution candidate for the
-              entire <class-enum-type> and thus don't want to clear
-              the is_substitution_candidate flag.
-
-              However, it's possible that what we have here is a
-              substitution token representing an entire type, such as
-              `Ss' => std::string.  In this case, we mustn't add a
-              new substitution candidate for this substitution token.
-              To detect this case, remember where the start of the
-              substitution token is.  */
-           const char *next = dm->next;
-           /* Now demangle the <class-enum-type>.  */
-           RETURN_IF_ERROR 
-             (demangle_class_enum_type (dm, &encode_return_type));
-           /* If all that was just demangled is the two-character
-              special substitution token, supress the addition of a
-              new candidate for it.  */
-           if (dm->next == next + 2)
-             is_substitution_candidate = 0;
-         }
-
+         demangle_class_enum_type (dm, &template_p);
        break;
 
       case 'P':
       case 'R':
       case 'M':
-       RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
-       /* demangle_type_ptr adds all applicable substitution
-          candidates.  */
-       is_substitution_candidate = 0;
+       RETURN_IF_ERROR (demangle_type_ptr (dm));
        break;
 
       case 'C':
@@ -2338,7 +2043,7 @@ demangle_type (dm)
        break;
 
       case 'U':
-       /* Vendor-extended type qualifier.  */
+       /* Vendor extended type qualifier.  */
        advance_char (dm);
        RETURN_IF_ERROR (demangle_source_name (dm));
        RETURN_IF_ERROR (result_append_char (dm, ' '));
@@ -2349,12 +2054,13 @@ demangle_type (dm)
        return "Unexpected character in <type>.";
       }
 
-  if (is_substitution_candidate)
+  /* Unqualified builin types are not substitution candidates.  */
+  if (!is_builtin_type)
     /* Add a new substitution for the type. If this type was a
        <template-param>, pass its index since from the point of
-       substitutions; a <template-param> token is a substitution
+       substitutions, a <template-param> token is a substitution
        candidate distinct from the type that is substituted for it.  */
-    RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
+    RETURN_IF_ERROR (substitution_add (dm, start, template_p, template_parm));
 
   /* Pop off template argument lists added during mangling of this
      type.  */
@@ -2493,18 +2199,16 @@ demangle_CV_qualifiers (dm, qualifiers)
     }
 }
 
-/* Demangles and emits a <function-type>.  *FUNCTION_NAME_POS is the
+/* Demangles and emits a <function-type> FUNCTION_NAME_POS is the
    position in the result string of the start of the function
-   identifier, at which the function's return type will be inserted;
-   *FUNCTION_NAME_POS is updated to position past the end of the
-   function's return type.
+   identifier, at which the function's return type will be inserted.  
 
     <function-type> ::= F [Y] <bare-function-type> E  */
 
 static status_t
 demangle_function_type (dm, function_name_pos)
      demangling_t dm;
-     int *function_name_pos;
+     int function_name_pos;
 {
   DEMANGLE_TRACE ("function-type", dm);
   RETURN_IF_ERROR (demangle_char (dm, 'F'));  
@@ -2530,7 +2234,7 @@ demangle_function_type (dm, function_name_pos)
 static status_t
 demangle_bare_function_type (dm, return_type_pos)
      demangling_t dm;
-     int *return_type_pos;
+     int return_type_pos;
 {
   /* Sequence is the index of the current function parameter, counting
      from zero.  The value -1 denotes the return type.  */
@@ -2555,16 +2259,10 @@ demangle_bare_function_type (dm, return_type_pos)
 
          /* Add a space to the end of the type.  Insert the return
              type where we've been asked to. */
-         if (!dyn_string_append_space (return_type))
+         if (!dyn_string_append_space (return_type) 
+             || !dyn_string_insert (result_string (dm), return_type_pos, 
+                                    return_type))
            status = STATUS_ALLOCATION_FAILED;
-         if (STATUS_NO_ERROR (status))
-           {
-             if (!dyn_string_insert (result_string (dm), *return_type_pos, 
-                                     return_type))
-               status = STATUS_ALLOCATION_FAILED;
-             else
-               *return_type_pos += dyn_string_length (return_type);
-           }
 
          dyn_string_delete (return_type);
          RETURN_IF_ERROR (status);
@@ -2575,88 +2273,60 @@ demangle_bare_function_type (dm, return_type_pos)
             the only type in a parameter list; in that case, we want
             to print `foo ()' instead of `foo (void)'.  */
          if (peek_char (dm) == 'v')
-           /* Consume the v.  */
-           advance_char (dm);
-         else
            {
-             /* Separate parameter types by commas.  */
-             if (sequence > 0)
-               RETURN_IF_ERROR (result_append (dm, ", "));
-             /* Demangle the type.  */
-             RETURN_IF_ERROR (demangle_type (dm));
+             /* Consume the v.  */
+             advance_char (dm);
+             continue;
            }
+         /* Separate parameter types by commas.  */
+         if (sequence > 0)
+           RETURN_IF_ERROR (result_append (dm, ", "));
+         /* Demangle the type.  */
+         RETURN_IF_ERROR (demangle_type (dm));
        }
 
       ++sequence;
     }
   RETURN_IF_ERROR (result_append_char (dm, ')'));
 
-  /* We should have demangled at least one parameter type (which would
-     be void, for a function that takes no parameters), plus the
-     return type, if we were supposed to demangle that.  */
-  if (sequence == -1)
-    return "Missing function return type.";
-  else if (sequence == 0)
-    return "Missing function parameter.";
-
   return STATUS_OK;
 }
 
-/* Demangles and emits a <class-enum-type>.  *ENCODE_RETURN_TYPE is set to
+/* Demangles and emits a <class-enum-type>.  *TEMPLATE_P is set to
    non-zero if the type is a template-id, zero otherwise.  
 
     <class-enum-type> ::= <name>  */
 
 static status_t
-demangle_class_enum_type (dm, encode_return_type)
+demangle_class_enum_type (dm, template_p)
      demangling_t dm;
-     int *encode_return_type;
+     int *template_p;
 {
   DEMANGLE_TRACE ("class-enum-type", dm);
 
-  RETURN_IF_ERROR (demangle_name (dm, encode_return_type));
+  RETURN_IF_ERROR (demangle_name (dm, template_p));
   return STATUS_OK;
 }
 
 /* Demangles and emits an <array-type>.  
 
-    <array-type> ::= A [<dimension number>] _ <element type>  
-                 ::= A <dimension expression> _ <element type>  */
+    <array-type> ::= A [<dimension number>] _ <element type>  */
 
 static status_t
 demangle_array_type (dm)
      demangling_t dm;
 {
-  status_t status = STATUS_OK;
-  dyn_string_t array_size = NULL;
-  char peek;
+  status_t status;
+  dyn_string_t array_size = dyn_string_new (10);
+
+  if (array_size == NULL)
+    return STATUS_ALLOCATION_FAILED;
 
-  RETURN_IF_ERROR (demangle_char (dm, 'A'));
+  status = demangle_char (dm, 'A');
 
   /* Demangle the array size into array_size.  */
-  peek = peek_char (dm);
-  if (peek == '_')
-    /* Array bound is omitted.  This is a C99-style VLA.  */
-    ;
-  else if (IS_DIGIT (peek_char (dm))) 
-    {
-      /* It looks like a constant array bound.  */
-      array_size = dyn_string_new (10);
-      if (array_size == NULL)
-       return STATUS_ALLOCATION_FAILED;
-      status = demangle_number_literally (dm, array_size, 10, 0);
-    }
-  else
-    {
-      /* Anything is must be an expression for a nont-constant array
-        bound.  This happens if the array type occurs in a template
-        and the array bound references a template parameter.  */
-      RETURN_IF_ERROR (result_push (dm));
-      RETURN_IF_ERROR (demangle_expression (dm));
-      array_size = (dyn_string_t) result_pop (dm);
-    }
-  /* array_size may have been allocated by now, so we can't use
-     RETURN_IF_ERROR until it's been deallocated.  */
+  if (STATUS_NO_ERROR (status))
+    status = demangle_number_literally (dm, array_size, 10, 0);
 
   /* Demangle the base type of the array.  */
   if (STATUS_NO_ERROR (status))
@@ -2667,26 +2337,27 @@ demangle_array_type (dm)
   /* Emit the array dimension syntax.  */
   if (STATUS_NO_ERROR (status))
     status = result_append_char (dm, '[');
-  if (STATUS_NO_ERROR (status) && array_size != NULL)
+  if (STATUS_NO_ERROR (status))
     status = result_append_string (dm, array_size);
   if (STATUS_NO_ERROR (status))
     status = result_append_char (dm, ']');
-  if (array_size != NULL)
-    dyn_string_delete (array_size);
+  dyn_string_delete (array_size);
   
   RETURN_IF_ERROR (status);
 
   return STATUS_OK;
 }
 
-/* Demangles and emits a <template-param>.  
+/* Demangles and emits a <template-param>.  The zero-indexed position
+   in the parameter list is placed in *TEMPLATE_PARM_NUMBER.  
 
     <template-param> ::= T_       # first template parameter
                      ::= T <parameter-2 number> _  */
 
 static status_t
-demangle_template_param (dm)
+demangle_template_param (dm, template_parm_number)
      demangling_t dm;
+     int *template_parm_number;
 {
   int parm_number;
   template_arg_list_t current_arg_list = current_template_arg_list (dm);
@@ -2716,6 +2387,10 @@ demangle_template_param (dm)
     return "Template parameter number out of bounds.";
   RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
 
+  if (peek_char (dm) == 'I')
+    RETURN_IF_ERROR (demangle_template_args (dm));
+
+  *template_parm_number = parm_number;
   return STATUS_OK;
 }
 
@@ -2744,7 +2419,7 @@ demangle_template_args (dm)
     return STATUS_ALLOCATION_FAILED;
 
   RETURN_IF_ERROR (demangle_char (dm, 'I'));
-  RETURN_IF_ERROR (result_open_template_list (dm));
+  RETURN_IF_ERROR (result_append_char (dm, '<'));
   do
     {
       string_list_t arg;
@@ -2920,7 +2595,6 @@ demangle_template_arg (dm)
       /* Expression.  */
       advance_char (dm);
       RETURN_IF_ERROR (demangle_expression (dm));
-      RETURN_IF_ERROR (demangle_char (dm, 'E'));
       break;
 
     default:
@@ -3025,11 +2699,12 @@ demangle_expr_primary (dm)
      demangling_t dm;
 {
   char peek = peek_char (dm);
+  int unused;
 
   DEMANGLE_TRACE ("expr-primary", dm);
 
   if (peek == 'T')
-    RETURN_IF_ERROR (demangle_template_param (dm));
+    RETURN_IF_ERROR (demangle_template_param (dm, &unused));
   else if (peek == 'L')
     {
       /* Consume the `L'.  */
@@ -3050,7 +2725,10 @@ demangle_expr_primary (dm)
 }
 
 /* Demangles and emits a <substitution>.  Sets *TEMPLATE_P to non-zero
-   if the substitution is the name of a template, zero otherwise. 
+   if the substitution is the name of a template, zero otherwise.  If
+   the substitution token is St, which corresponds to the `::std::'
+   namespace and can appear in a non-nested name, sets
+   *SPECIAL_STD_SUBSTITUTION to non-zero; zero otherwise.  
 
      <substitution> ::= S <seq-id> _
                     ::= S_
@@ -3066,13 +2744,14 @@ demangle_expr_primary (dm)
                     ::= So   # ::std::basic_ostream<char,  
                                                     std::char_traits<char> >
                     ::= Sd   # ::std::basic_iostream<char, 
-                                                    std::char_traits<char> >
+                                                     std::char_traits<char> >
 */
 
 static status_t
-demangle_substitution (dm, template_p)
+demangle_substitution (dm, template_p, special_std_substitution)
      demangling_t dm;
      int *template_p;
+     int *special_std_substitution;
 {
   int seq_id;
   int peek;
@@ -3081,6 +2760,7 @@ demangle_substitution (dm, template_p)
   DEMANGLE_TRACE ("substitution", dm);
 
   RETURN_IF_ERROR (demangle_char (dm, 'S'));
+  *special_std_substitution = 0;
 
   /* Scan the substitution sequence index.  A missing number denotes
      the first index.  */
@@ -3101,6 +2781,7 @@ demangle_substitution (dm, template_p)
        {
        case 't':
          RETURN_IF_ERROR (result_append (dm, "std"));
+         *special_std_substitution = 1;
          break;
 
        case 'a':
@@ -3216,7 +2897,7 @@ demangle_local_name (dm)
   RETURN_IF_ERROR (demangle_char (dm, 'Z'));
   RETURN_IF_ERROR (demangle_encoding (dm));
   RETURN_IF_ERROR (demangle_char (dm, 'E'));
-  RETURN_IF_ERROR (result_append (dm, "::"));
+  RETURN_IF_ERROR (result_append (dm, "'s "));
 
   if (peek_char (dm) == 's')
     {
@@ -3229,6 +2910,7 @@ demangle_local_name (dm)
   else
     {
       int unused;
+      RETURN_IF_ERROR (result_append (dm, "local "));
       /* Local name for some other entity.  Demangle its name.  */
       RETURN_IF_ERROR (demangle_name (dm, &unused));
       RETURN_IF_ERROR (demangle_discriminator (dm, 1));
@@ -3251,7 +2933,7 @@ demangle_discriminator (dm, suppress_first)
      int suppress_first;
 {
   /* Output for <discriminator>s to the demangled name is completely
-     suppressed if not in verbose mode.  */
+     supressed if not in verbose mode.  */
 
   if (peek_char (dm) == '_')
     {
@@ -3343,7 +3025,6 @@ cp_demangle (name, result)
    dyn_string_t.  On success, returns STATUS_OK.  On failiure, returns
    an error message, and the contents of RESULT are unchanged.  */
 
-#ifdef IN_LIBGCC2
 static status_t
 cp_demangle_type (type_name, result)
      const char* type_name;
@@ -3381,6 +3062,9 @@ cp_demangle_type (type_name, result)
   return status;
 }
 
+
+#ifdef IN_LIBGCC2
+
 extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
 
 /* ABI-mandated entry point in the C++ runtime library for performing
@@ -3537,8 +3221,7 @@ static void print_usage
 
 /* Non-zero if CHAR is a character than can occur in a mangled name.  */
 #define is_mangled_char(CHAR)                                           \
-  (IS_ALPHA (CHAR) || IS_DIGIT (CHAR)                                   \
-   || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
+  (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) || (CHAR) == '_')
 
 /* The name of this program, as invoked.  */
 const char* program_name;
@@ -3551,7 +3234,7 @@ print_usage (fp, exit_value)
      int exit_value;
 {
   fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
-  fprintf (fp, "Options:\n");
+  fprintf (fp, "Options:\n", program_name);
   fprintf (fp, "  -h,--help       Display this message.\n");
   fprintf (fp, "  -s,--strict     Demangle standard names only.\n");
   fprintf (fp, "  -v,--verbose    Produce verbose demanglings.\n");
index 52249d2b580c6d3809b1367ec51f15e089b81f86..8a672c684b1564a67d8a4072807abd709cfdd710 100644 (file)
@@ -252,6 +252,55 @@ typedef enum type_kind_t
   tk_real
 } type_kind_t;
 
+struct demangler_engine libiberty_demanglers[] =
+{
+  {
+    AUTO_DEMANGLING_STYLE_STRING,
+      auto_demangling,
+      "Automatic selection based on executable"
+  }
+  ,
+  {
+    GNU_DEMANGLING_STYLE_STRING,
+      gnu_demangling,
+      "GNU (g++) style demangling"
+  }
+  ,
+  {
+    LUCID_DEMANGLING_STYLE_STRING,
+      lucid_demangling,
+      "Lucid (lcc) style demangling"
+  }
+  ,
+  {
+    ARM_DEMANGLING_STYLE_STRING,
+      arm_demangling,
+      "ARM style demangling"
+  }
+  ,
+  {
+    HP_DEMANGLING_STYLE_STRING,
+      hp_demangling,
+      "HP (aCC) style demangling"
+  }
+  ,
+  {
+    EDG_DEMANGLING_STYLE_STRING,
+      edg_demangling,
+      "EDG style demangling"
+  }
+  ,
+  {
+    GNU_NEW_ABI_DEMANGLING_STYLE_STRING,
+    gnu_new_abi_demangling,
+    "GNU (g++) new-ABI-style demangling"
+  }
+  ,
+  {
+    NULL, unknown_demangling, NULL
+  }
+};
+
 #define STRING_EMPTY(str)      ((str) -> b == (str) -> p)
 #define PREPEND_BLANK(str)     {if (!STRING_EMPTY(str)) \
     string_prepend(str, " ");}
@@ -268,12 +317,21 @@ typedef enum type_kind_t
 
 /* Prototypes for local functions */
 
+static void
+delete_work_stuff PARAMS ((struct work_stuff *));
+
+static void
+delete_non_B_K_work_stuff PARAMS ((struct work_stuff *));
+
 static char *
 mop_up PARAMS ((struct work_stuff *, string *, int));
 
 static void
 squangle_mop_up PARAMS ((struct work_stuff *));
 
+static void
+work_stuff_copy_to_from PARAMS ((struct work_stuff *, struct work_stuff *));
+
 #if 0
 static int
 demangle_method_args PARAMS ((struct work_stuff *, const char **, string *));
@@ -379,6 +437,10 @@ static void
 demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
                                const char *));
 
+static int
+iterate_demangle_function PARAMS ((struct work_stuff *,
+                                  const char **, string *, const char *));
+
 static void
 remember_type PARAMS ((struct work_stuff *, const char *, int));
 
@@ -636,8 +698,8 @@ cplus_demangle_opname (opname, result, options)
        }
     }
   else if (opname[0] == '_' && opname[1] == '_'
-          && opname[2] >= 'a' && opname[2] <= 'z'
-          && opname[3] >= 'a' && opname[3] <= 'z')
+          && islower((unsigned char)opname[2])
+          && islower((unsigned char)opname[3]))
     {
       if (opname[4] == '\0')
        {
@@ -733,6 +795,7 @@ cplus_demangle_opname (opname, result, options)
   return ret;
 
 }
+
 /* Takes operator name as e.g. "++" and returns mangled
    operator name (e.g. "postincrement_expr"), or NULL if not found.
 
@@ -758,6 +821,40 @@ cplus_mangle_opname (opname, options)
   return (0);
 }
 
+/* Add a routine to set the demangling style to be sure it is valid and
+   allow for any demangler initialization that maybe necessary. */
+
+enum demangling_styles
+cplus_demangle_set_style (style)
+     enum demangling_styles style;
+{
+  struct demangler_engine *demangler = libiberty_demanglers; 
+
+  for (; demangler->demangling_style != unknown_demangling; ++demangler)
+    if (style == demangler->demangling_style)
+      {
+       current_demangling_style = style;
+       return current_demangling_style;
+      }
+
+  return unknown_demangling;
+}
+
+/* Do string name to style translation */
+
+enum demangling_styles
+cplus_demangle_name_to_style (name)
+     const char *name;
+{
+  struct demangler_engine *demangler = libiberty_demanglers; 
+
+  for (; demangler->demangling_style != unknown_demangling; ++demangler)
+    if (strcmp (name, demangler->demangling_style_name) == 0)
+      return demangler->demangling_style;
+
+  return unknown_demangling;
+}
+
 /* char *cplus_demangle (const char *mangled, int options)
 
    If MANGLED is a mangled function name produced by GNU C++, then
@@ -798,6 +895,10 @@ cplus_demangle (mangled, options)
   if ((work -> options & DMGL_STYLE_MASK) == 0)
     work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK;
 
+  /* The new-ABI demangling is implemented elsewhere.  */
+  if (GNU_NEW_ABI_DEMANGLING)
+    return cplus_demangle_new_abi (mangled);
+
   ret = internal_cplus_demangle (work, mangled);
   squangle_mop_up (work);
   return (ret);
@@ -893,16 +994,85 @@ squangle_mop_up (work)
     }
 }
 
-/* Clear out any mangled storage */
 
-static char *
-mop_up (work, declp, success)
-     struct work_stuff *work;
-     string *declp;
-     int success;
+/* Copy the work state and storage.  */
+
+static void
+work_stuff_copy_to_from (to, from)
+     struct work_stuff *to;
+     struct work_stuff *from;
 {
-  char *demangled = NULL;
+  int i;
+
+  delete_work_stuff (to);
+
+  /* Shallow-copy scalars.  */
+  memcpy (to, from, sizeof (*to));
+
+  /* Deep-copy dynamic storage.  */
+  if (from->typevec_size)
+    to->typevec
+      = (char **) xmalloc (from->typevec_size * sizeof (to->typevec[0]));
+
+  for (i = 0; i < from->ntypes; i++)
+    {
+      int len = strlen (from->typevec[i]) + 1;
+
+      to->typevec[i] = xmalloc (len);
+      memcpy (to->typevec[i], from->typevec[i], len);
+    }
+
+  if (from->ksize)
+    to->ktypevec
+      = (char **) xmalloc (from->ksize * sizeof (to->ktypevec[0]));
+
+  for (i = 0; i < from->numk; i++)
+    {
+      int len = strlen (from->ktypevec[i]) + 1;
+
+      to->ktypevec[i] = xmalloc (len);
+      memcpy (to->ktypevec[i], from->ktypevec[i], len);
+    }
+
+  if (from->bsize)
+    to->btypevec
+      = (char **) xmalloc (from->bsize * sizeof (to->btypevec[0]));
+
+  for (i = 0; i < from->numb; i++)
+    {
+      int len = strlen (from->btypevec[i]) + 1;
+
+      to->btypevec[i] = xmalloc (len);
+      memcpy (to->btypevec[i], from->btypevec[i], len);
+    }
+
+  if (from->ntmpl_args)
+    to->tmpl_argvec
+      = xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0]));
 
+  for (i = 0; i < from->ntmpl_args; i++)
+    {
+      int len = strlen (from->tmpl_argvec[i]) + 1;
+
+      to->tmpl_argvec[i] = xmalloc (len);
+      memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
+    }
+
+  if (from->previous_argument)
+    {
+      to->previous_argument = (string*) xmalloc (sizeof (string));
+      string_init (to->previous_argument);
+      string_appends (to->previous_argument, from->previous_argument);
+    }
+}
+
+
+/* Delete dynamic stuff in work_stuff that is not to be re-used.  */
+
+static void
+delete_non_B_K_work_stuff (work)
+     struct work_stuff *work;
+{
   /* Discard the remembered types, if any.  */
 
   forget_types (work);
@@ -929,6 +1099,30 @@ mop_up (work, declp, success)
       free ((char*) work->previous_argument);
       work->previous_argument = NULL;
     }
+}
+
+
+/* Delete all dynamic storage in work_stuff.  */
+static void
+delete_work_stuff (work)
+     struct work_stuff *work;
+{
+  delete_non_B_K_work_stuff (work);
+  squangle_mop_up (work);
+}
+
+
+/* Clear out any mangled storage */
+
+static char *
+mop_up (work, declp, success)
+     struct work_stuff *work;
+     string *declp;
+     int success;
+{
+  char *demangled = NULL;
+
+  delete_non_B_K_work_stuff (work);
 
   /* If demangling was successful, ensure that the demangled string is null
      terminated and return it.  Otherwise, free the demangling decl.  */
@@ -1154,7 +1348,7 @@ demangle_signature (work, mangled, declp)
          break;
 
        case '_':
-         if (GNU_DEMANGLING && expect_return_type)
+         if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
            {
              /* Read the return type. */
              string return_type;
@@ -1188,7 +1382,7 @@ demangle_signature (work, mangled, declp)
          break;
 
        case 'H':
-         if (GNU_DEMANGLING)
+         if (AUTO_DEMANGLING || GNU_DEMANGLING)
            {
              /* A G++ template function.  Read the template arguments. */
              success = demangle_template (work, mangled, declp, 0, 0,
@@ -1433,6 +1627,11 @@ demangle_integral_value (work, mangled, s)
     {
       int value;
 
+      /* By default, we let the number decide whether we shall consume an
+        underscore.  */
+      int consume_following_underscore = 0;
+      int leave_following_underscore = 0;
+
       success = 0;
 
       /* Negative numbers are indicated with a leading `m'.  */
@@ -1441,17 +1640,49 @@ demangle_integral_value (work, mangled, s)
          string_appendn (s, "-", 1);
          (*mangled)++;
        }
+      else if (mangled[0][0] == '_' && mangled[0][1] == 'm')
+       {
+         /* Since consume_count_with_underscores does not handle the
+            `m'-prefix we must do it here, using consume_count and
+            adjusting underscores: we have to consume the underscore
+            matching the prepended one.  */
+         consume_following_underscore = 1;
+         string_appendn (s, "-", 1);
+         (*mangled) += 2;
+       }
+      else if (**mangled == '_')
+       {
+         /* Do not consume a following underscore;
+            consume_following_underscore will consume what should be
+            consumed.  */
+         leave_following_underscore = 1;
+       }
+
+      /* We must call consume_count if we expect to remove a trailing
+        underscore, since consume_count_with_underscores expects
+        the leading underscore (that we consumed) if it is to handle
+        multi-digit numbers.  */
+      if (consume_following_underscore)
+       value = consume_count (mangled);
+      else
+       value = consume_count_with_underscores (mangled);
 
-      /* Read the rest of the number.  */
-      value = consume_count_with_underscores (mangled);
       if (value != -1)
        {
          char buf[INTBUF_SIZE];
          sprintf (buf, "%d", value);
          string_append (s, buf);
 
-         /* If the next character is an underscore, skip it.  */
-         if (**mangled == '_')
+         /* Numbers not otherwise delimited, might have an underscore
+            appended as a delimeter, which we should skip.
+
+            ??? This used to always remove a following underscore, which
+            is wrong.  If other (arbitrary) cases are followed by an
+            underscore, we need to do something more radical.  */
+
+         if ((value > 9 || consume_following_underscore)
+             && ! leave_following_underscore
+             && **mangled == '_')
            (*mangled)++;
 
          /* All is well.  */
@@ -1616,7 +1847,7 @@ demangle_template_value_parm (work, mangled, s, tk)
    template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
    non-NULL.  If IS_TYPE is nonzero, this template is a type template,
    not a function template.  If both IS_TYPE and REMEMBER are nonzero,
-   the tmeplate is remembered in the list of back-referenceable
+   the template is remembered in the list of back-referenceable
    types.  */
 
 static int
@@ -2148,6 +2379,86 @@ demangle_class (work, mangled, declp)
   return (success);
 }
 
+
+/* Called when there's a "__" in the mangled name, with `scan' pointing to
+   the rightmost guess.
+
+   Find the correct "__"-sequence where the function name ends and the
+   signature starts, which is ambiguous with GNU mangling.
+   Call demangle_signature here, so we can make sure we found the right
+   one; *mangled will be consumed so caller will not make further calls to
+   demangle_signature.  */
+
+static int
+iterate_demangle_function (work, mangled, declp, scan)
+     struct work_stuff *work;
+     const char **mangled;
+     string *declp;
+     const char *scan;
+{
+  const char *mangle_init = *mangled;
+  int success = 0;
+  string decl_init;
+  struct work_stuff work_init;
+
+  if (*(scan + 2) == '\0')
+    return 0;
+
+  /* Do not iterate for some demangling modes, or if there's only one
+     "__"-sequence.  This is the normal case.  */
+  if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
+      || mystrstr (scan + 2, "__") == NULL)
+    {
+      demangle_function_name (work, mangled, declp, scan);
+      return 1;
+    }
+
+  /* Save state so we can restart if the guess at the correct "__" was
+     wrong.  */
+  string_init (&decl_init);
+  string_appends (&decl_init, declp);
+  memset (&work_init, 0, sizeof work_init);
+  work_stuff_copy_to_from (&work_init, work);
+
+  /* Iterate over occurrences of __, allowing names and types to have a
+     "__" sequence in them.  We must start with the first (not the last)
+     occurrence, since "__" most often occur between independent mangled
+     parts, hence starting at the last occurence inside a signature
+     might get us a "successful" demangling of the signature.  */
+
+  while (scan[2])
+    {
+      demangle_function_name (work, mangled, declp, scan);
+      success = demangle_signature (work, mangled, declp);
+      if (success)
+       break;
+
+      /* Reset demangle state for the next round.  */
+      *mangled = mangle_init;
+      string_clear (declp);
+      string_appends (declp, &decl_init);
+      work_stuff_copy_to_from (work, &work_init);
+
+      /* Leave this underscore-sequence.  */
+      scan += 2;
+
+      /* Scan for the next "__" sequence.  */
+      while (*scan && (scan[0] != '_' || scan[1] != '_'))
+       scan++;
+
+      /* Move to last "__" in this sequence.  */
+      while (*scan && *scan == '_')
+       scan++;
+      scan -= 2;
+    }
+
+  /* Delete saved state.  */
+  delete_work_stuff (&work_init);
+  string_delete (&decl_init);
+
+  return success;
+}
+
 /*
 
 LOCAL FUNCTION
@@ -2163,6 +2474,8 @@ SYNOPSIS
 DESCRIPTION
 
        Consume and demangle the prefix of the mangled name.
+       While processing the function name root, arrange to call
+       demangle_signature if the root is ambiguous.
 
        DECLP points to the string buffer into which demangled output is
        placed.  On entry, the buffer is empty.  On exit it contains
@@ -2336,29 +2649,16 @@ demangle_prefix (work, mangled, declp)
              success = 0;
            }
          else
-           {
-             const char *tmp;
-
-              /* Look for the LAST occurrence of __, allowing names to
-                 have the '__' sequence embedded in them. */
-             if (!(ARM_DEMANGLING || HP_DEMANGLING))
-               {
-                 while ((tmp = mystrstr (scan + 2, "__")) != NULL)
-                   scan = tmp;
-               }
-             if (*(scan + 2) == '\0')
-               success = 0;
-              else
-                demangle_function_name (work, mangled, declp, scan);
-           }
+           return iterate_demangle_function (work, mangled, declp, scan);
        }
     }
   else if (*(scan + 2) != '\0')
     {
       /* Mangled name does not start with "__" but does have one somewhere
         in there with non empty stuff after it.  Looks like a global
-        function name.  */
-      demangle_function_name (work, mangled, declp, scan);
+        function name.  Iterate over all "__":s until the right
+        one is found.  */
+      return iterate_demangle_function (work, mangled, declp, scan);
     }
   else
     {
@@ -2512,6 +2812,25 @@ gnu_special (work, mangled, declp)
              success = 0;
              break;
            }
+
+         if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
+             && (*mangled)[9] == 'N'
+             && (*mangled)[8] == (*mangled)[10]
+             && strchr (cplus_markers, (*mangled)[8]))
+           {
+             /* A member of the anonymous namespace.  There's information
+                about what identifier or filename it was keyed to, but
+                it's just there to make the mangled name unique; we just
+                step over it.  */
+             string_append (declp, "{anonymous}");
+             (*mangled) += n;
+
+             /* Now p points to the marker before the N, so we need to
+                update it to the first marker after what we consumed.  */
+             p = strpbrk (*mangled, cplus_markers);
+             break;
+           }
+
          string_appendn (declp, *mangled, n);
          (*mangled) += n;
        }
@@ -2573,7 +2892,7 @@ gnu_special (work, mangled, declp)
          success = demangle_template (work, mangled, declp, 0, 1, 1);
          break;
        default:
-         success = demangle_fund_type (work, mangled, declp);
+         success = do_type (work, mangled, declp);
          break;
        }
       if (success && **mangled != '\0')
@@ -3311,7 +3630,7 @@ demangle_fund_type (work, mangled, result)
   int done = 0;
   int success = 1;
   char buf[10];
-  int dec = 0;
+  unsigned int dec = 0;
   string btype;
   type_kind_t tk = tk_integral;
 
@@ -3455,7 +3774,7 @@ demangle_fund_type (work, mangled, result)
          *mangled += min (strlen (*mangled), 2);
        }
       sscanf (buf, "%x", &dec);
-      sprintf (buf, "int%i_t", dec);
+      sprintf (buf, "int%u_t", dec);
       APPEND_BLANK (result);
       string_append (result, buf);
       break;
@@ -4188,8 +4507,8 @@ demangle_function_name (work, mangled, declp, scan)
        }
     }
   else if (declp->b[0] == '_' && declp->b[1] == '_'
-          && declp->b[2] >= 'a' && declp->b[2] <= 'z'
-          && declp->b[3] >= 'a' && declp->b[3] <= 'z')
+          && islower((unsigned char)declp->b[2])
+          && islower((unsigned char)declp->b[3]))
     {
       if (declp->b[4] == '\0')
        {
@@ -4402,6 +4721,7 @@ static int flags = DMGL_PARAMS | DMGL_ANSI;
 static void demangle_it PARAMS ((char *));
 static void usage PARAMS ((FILE *, int)) ATTRIBUTE_NORETURN;
 static void fatal PARAMS ((const char *)) ATTRIBUTE_NORETURN;
+static void print_demangler_list PARAMS ((FILE *));
 
 static void
 demangle_it (mangled_name)
@@ -4421,16 +4741,43 @@ demangle_it (mangled_name)
     }
 }
 
+static void 
+print_demangler_list (stream)
+     FILE *stream;
+{
+  struct demangler_engine *demangler; 
+
+  fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name);
+  
+  for (demangler = libiberty_demanglers + 1;
+       demangler->demangling_style != unknown_demangling;
+       ++demangler)
+    fprintf (stream, ",%s", demangler->demangling_style_name);
+
+  fprintf (stream, "}");
+}
+
 static void
 usage (stream, status)
      FILE *stream;
      int status;
 {
   fprintf (stream, "\
-Usage: %s [-_] [-n] [-s {gnu,lucid,arm,hp,edg}] [--strip-underscores]\n\
-       [--no-strip-underscores] [--format={gnu,lucid,arm,hp,edg}]\n\
-      [--help] [--version] [arg...]\n",
+Usage: %s [-_] [-n] [--strip-underscores] [--no-strip-underscores] \n",
           program_name);
+
+  fprintf (stream, "\
+       [-s ");
+  print_demangler_list (stream);
+  fprintf (stream, "]\n");
+
+  fprintf (stream, "\
+       [--format ");
+  print_demangler_list (stream);
+  fprintf (stream, "]\n");
+
+  fprintf (stream, "\
+       [--help] [--version] [arg...]\n");
   exit (status);
 }
 
@@ -4468,6 +4815,9 @@ standard_symbol_characters PARAMS ((void));
 static const char *
 hp_symbol_characters PARAMS ((void));
 
+static const char *
+gnu_new_abi_symbol_characters PARAMS ((void));
+
 /* Return the string of non-alnum characters that may occur 
    as a valid symbol component, in the standard assembler symbol
    syntax.  */
@@ -4516,6 +4866,17 @@ hp_symbol_characters ()
 }
 
 
+/* Return the string of non-alnum characters that may occur 
+   as a valid symbol component in the GNU standard C++ ABI mangling
+   scheme.  */
+
+static const char *
+gnu_new_abi_symbol_characters ()
+{
+  return "_";
+}
+
+
 extern int main PARAMS ((int, char **));
 
 int
@@ -4553,32 +4914,19 @@ main (argc, argv)
          flags |= DMGL_JAVA;
          break;
        case 's':
-         if (strcmp (optarg, "gnu") == 0)
-           {
-             current_demangling_style = gnu_demangling;
-           }
-         else if (strcmp (optarg, "lucid") == 0)
-           {
-             current_demangling_style = lucid_demangling;
-           }
-         else if (strcmp (optarg, "arm") == 0)
-           {
-             current_demangling_style = arm_demangling;
-           }
-         else if (strcmp (optarg, "hp") == 0)
-           {
-             current_demangling_style = hp_demangling;
-           }
-          else if (strcmp (optarg, "edg") == 0)
-            {
-              current_demangling_style = edg_demangling;
-            }
-         else
-           {
-             fprintf (stderr, "%s: unknown demangling style `%s'\n",
-                      program_name, optarg);
-             return (1);
-           }
+         {
+           enum demangling_styles style;
+
+           style = cplus_demangle_name_to_style (optarg);
+           if (style == unknown_demangling)
+             {
+               fprintf (stderr, "%s: unknown demangling style `%s'\n",
+                        program_name, optarg);
+               return (1);
+             }
+           else
+             cplus_demangle_set_style (style);
+         }
          break;
        }
     }
@@ -4603,6 +4951,9 @@ main (argc, argv)
        case hp_demangling:
          valid_symbols = hp_symbol_characters ();
          break;
+       case gnu_new_abi_demangling:
+         valid_symbols = gnu_new_abi_symbol_characters ();
+         break;
        default:
          /* Folks should explicitly indicate the appropriate alphabet for
             each demangling.  Providing a default would allow the
@@ -4652,6 +5003,7 @@ main (argc, argv)
          if (c == EOF)
            break;
          putchar (c);
+         fflush (stdout);
        }
     }
 
index 34f88ade96d31d663bc69802e4c8f5bf4072a313..69897f84c5e61a1f33a04263d9e115d6641addf0 100644 (file)
@@ -305,30 +305,6 @@ dyn_string_insert_cstr (dest, pos, src)
   return 1;
 }
 
-/* Inserts character C into DEST starting at position POS.  DEST is
-   expanded as necessary.  Returns 1 on success.  On failure,
-   RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0.  */
-
-int
-dyn_string_insert_char (dest, pos, c)
-     dyn_string_t dest;
-     int pos;
-     int c;
-{
-  int i;
-
-  if (dyn_string_resize (dest, dest->length + 1) == NULL)
-    return 0;
-  /* Make room for the insertion.  Be sure to copy the NUL.  */
-  for (i = dest->length; i >= pos; --i)
-    dest->s[i + 1] = dest->s[i];
-  /* Add the new character.  */
-  dest->s[pos] = c;
-  /* Compute the new length.  */
-  ++dest->length;
-  return 1;
-}
-     
 /* Append S to DS, resizing DS if necessary.  Returns 1 on success.
    On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
    returns 0.  */
index d3a1fe43890d992690a98bfbdf57dbaf215da055..a5d72fab0fe6b9a01f896f35d3c21f010cbc68e3 100644 (file)
@@ -2486,3 +2486,83 @@ f(Bar<21>, int)
 --format=gnu
 f__FGt3Bar1i24XY_t
 f(Bar<2>, XY_t)
+#
+--format=gnu
+foo__H1Zt2TA2ZRCiZt2NA1Ui9_X01_i
+int foo<TA<int const &, NA<9> > >(TA<int const &, NA<9> >)
+#
+--format=gnu
+foo__H1Zt2TA2ZcZt2NA1Ui_20__X01_i
+int foo<TA<char, NA<20> > >(TA<char, NA<20> >)
+#
+--format=gnu
+foo__H1Zt2TA2ZiZt8N___A___1Ui_99__X01_i
+int foo<TA<int, N___A___<99> > >(TA<int, N___A___<99> >)
+#
+--format=gnu
+foo__H1Zt2TA2ZRCiZt2NA1im1_X01_i
+int foo<TA<int const &, NA<-1> > >(TA<int const &, NA<-1> >)
+#
+--format=gnu
+foo__H1Zt2TA2ZRCiZt2NA1im9_X01_i
+int foo<TA<int const &, NA<-9> > >(TA<int const &, NA<-9> >)
+#
+--format=gnu
+foo__H1Zt2TA2ZcZt2NA1i_m20__X01_i
+int foo<TA<char, NA<-20> > >(TA<char, NA<-20> >)
+#
+--format=gnu
+foo__H1Zt2TA2ZcZt2NA1im1_X01_i
+int foo<TA<char, NA<-1> > >(TA<char, NA<-1> >)
+#
+--format=gnu
+foo__H1Zt2TA2ZiZt4N__A1im9_X01_i
+int foo<TA<int, N__A<-9> > >(TA<int, N__A<-9> >)
+#
+--format=gnu
+foo__H1Zt2TA2ZiZt4N__A1i_m99__X01_i
+int foo<TA<int, N__A<-99> > >(TA<int, N__A<-99> >)
+#
+--format=gnu
+__opi__t2TA2ZiZt4N__A1i9
+TA<int, N__A<9> >::operator int(void)
+#
+--format=gnu
+__opi__t2TA2ZiZt8N___A___1i_m99_
+TA<int, N___A___<-99> >::operator int(void)
+#
+--format=gnu
+foo___bar__baz_____H1Zt2TA2ZiZt8N___A___1i_99__X01_i
+int foo___bar__baz___<TA<int, N___A___<99> > >(TA<int, N___A___<99> >)
+#
+--format=gnu
+foo__bar___foobar_____t2TA2ZiZt8N___A___1i_m99_
+TA<int, N___A___<-99> >::foo__bar___foobar___(void)
+#
+--format=gnu
+foo__bar___foobar_____t2TA2ZiZt4N__A1i9
+TA<int, N__A<9> >::foo__bar___foobar___(void)
+#
+--format=gnu
+__tfP8sockaddr
+sockaddr * type_info function
+#
+--format=gnu
+__tfPQ25libcwt16option_event_tct1Z12burst_app_ct
+libcw::option_event_tct<burst_app_ct> * type_info function
+#
+--format=gnu
+__tiP8sockaddr
+sockaddr * type_info node
+#
+--format=gnu
+__tiPQ25libcwt16option_event_tct1Z12burst_app_ct
+libcw::option_event_tct<burst_app_ct> * type_info node
+#
+--format=gnu
+_27_GLOBAL_.N.__12burst_app_ct.app_instance
+{anonymous}::app_instance
+#
+--format=gnu
+_26_GLOBAL_\$N\$_tmp_n.iilg4Gya\$app_instance
+{anonymous}::app_instance
index bd48ce9013ec39bb2fef238249de33bcd24ad018..1086762dbb261f860a6309342f58e5bc1ec4eb6a 100755 (executable)
@@ -15,6 +15,8 @@ sed -e '/^#/ d' "$1" | (
      if test "x$x" != "x$demangled"; then
        failures=`expr $failures + 1`
        echo "FAIL: $type $mangled"
+       echo "   result: $x"
+       echo " expected: $demangled"
      fi
   done