gnats-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Changes to gnats/libiberty/cplus-dem.c


From: Milan Zamazal
Subject: Changes to gnats/libiberty/cplus-dem.c
Date: Mon, 10 Dec 2001 18:04:19 -0500

Index: gnats/libiberty/cplus-dem.c
diff -c gnats/libiberty/cplus-dem.c:1.2 gnats/libiberty/cplus-dem.c:1.3
*** gnats/libiberty/cplus-dem.c:1.2     Tue Oct 26 03:10:16 1999
--- gnats/libiberty/cplus-dem.c Mon Dec 10 18:03:26 2001
***************
*** 1,5 ****
  /* Demangler for GNU C++
!    Copyright 1989, 91, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
     Written by James Clark (address@hidden)
     Rewritten by Fred Fish (address@hidden) for ARM and Lucid demangling
     Modified by Satish Pai (address@hidden) for HP demangling
--- 1,6 ----
  /* Demangler for GNU C++
!    Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
!    2000, 2001 Free Software Foundation, Inc.
     Written by James Clark (address@hidden)
     Rewritten by Fred Fish (address@hidden) for ARM and Lucid demangling
     Modified by Satish Pai (address@hidden) for HP demangling
***************
*** 33,39 ****
  #include "config.h"
  #endif
  
! #include <ctype.h>
  #include <sys/types.h>
  #include <string.h>
  #include <stdio.h>
--- 34,41 ----
  #include "config.h"
  #endif
  
! #include "safe-ctype.h"
! 
  #include <sys/types.h>
  #include <string.h>
  #include <stdio.h>
***************
*** 51,58 ****
--- 53,68 ----
  
  #include "libiberty.h"
  
+ static char *ada_demangle  PARAMS ((const char *, int));
+ 
  #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
  
+ /* A value at least one greater than the maximum number of characters
+    that will be output when using the `%d' format with `printf'.  */
+ #define INTBUF_SIZE 32
+ 
+ extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
+ 
  static const char *mystrstr PARAMS ((const char *, const char *));
  
  static const char *
***************
*** 92,98 ****
  #define CPLUS_MARKER '$'
  #endif
  
! enum demangling_styles current_demangling_style = gnu_demangling;
  
  static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
  
--- 102,108 ----
  #define CPLUS_MARKER '$'
  #endif
  
! enum demangling_styles current_demangling_style = auto_demangling;
  
  static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
  
***************
*** 246,251 ****
--- 256,322 ----
    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_V3_DEMANGLING_STYLE_STRING,
+     gnu_v3_demangling,
+     "GNU (g++) V3 ABI-style demangling"
+   }
+   ,
+   {
+     JAVA_DEMANGLING_STYLE_STRING,
+     java_demangling,
+     "Java style demangling"
+   }
+   ,
+   {
+     GNAT_DEMANGLING_STYLE_STRING,
+     gnat_demangling,
+     "GNAT 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, " ");}
***************
*** 262,273 ****
--- 333,353 ----
  
  /* 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 *));
***************
*** 345,350 ****
--- 425,433 ----
  static void
  string_prependn PARAMS ((string *, const char *, int));
  
+ static void
+ string_append_template_idx PARAMS ((string *, int));
+ 
  static int
  get_count PARAMS ((const char **, int *));
  
***************
*** 370,375 ****
--- 453,462 ----
  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));
  
***************
*** 422,427 ****
--- 509,536 ----
  static const char*
  demangle_qualifier PARAMS ((int));
  
+ static int
+ demangle_expression PARAMS ((struct work_stuff *, const char **, string *, 
+                            type_kind_t));
+ 
+ static int
+ demangle_integral_value PARAMS ((struct work_stuff *, const char **,
+                                string *));
+ 
+ static int
+ demangle_real_value PARAMS ((struct work_stuff *, const char **, string *));
+ 
+ static void
+ demangle_arm_hp_template PARAMS ((struct work_stuff *, const char **, int,
+                                 string *));
+ 
+ static void
+ recursively_demangle PARAMS ((struct work_stuff *, const char **, string *,
+                             int));
+ 
+ static void
+ grow_vect PARAMS ((void **, size_t *, size_t, int));
+ 
  /* Translate count to integer, consuming tokens in the process.
     Conversion terminates on the first non-digit character.
  
***************
*** 436,445 ****
  {
    int count = 0;
  
!   if (! isdigit ((unsigned char)**type))
      return -1;
  
!   while (isdigit ((unsigned char)**type))
      {
        count *= 10;
  
--- 545,554 ----
  {
    int count = 0;
  
!   if (! ISDIGIT ((unsigned char)**type))
      return -1;
  
!   while (ISDIGIT ((unsigned char)**type))
      {
        count *= 10;
  
***************
*** 450,456 ****
         ten.  */
        if ((count % 10) != 0)
        {
!         while (isdigit ((unsigned char) **type))
            (*type)++;
          return -1;
        }
--- 559,565 ----
         ten.  */
        if ((count % 10) != 0)
        {
!         while (ISDIGIT ((unsigned char) **type))
            (*type)++;
          return -1;
        }
***************
*** 476,482 ****
    if (**mangled == '_')
      {
        (*mangled)++;
!       if (!isdigit ((unsigned char)**mangled))
        return -1;
  
        idx = consume_count (mangled);
--- 585,591 ----
    if (**mangled == '_')
      {
        (*mangled)++;
!       if (!ISDIGIT ((unsigned char)**mangled))
        return -1;
  
        idx = consume_count (mangled);
***************
*** 608,621 ****
        }
      }
    else if (opname[0] == '_' && opname[1] == '_'
!          && opname[2] >= 'a' && opname[2] <= 'z'
!          && opname[3] >= 'a' && opname[3] <= 'z')
      {
        if (opname[4] == '\0')
        {
          /* Operator.  */
          size_t i;
!         for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
            {
              if (strlen (optable[i].in) == 2
                  && memcmp (optable[i].in, opname + 2, 2) == 0)
--- 717,730 ----
        }
      }
    else if (opname[0] == '_' && opname[1] == '_'
!          && ISLOWER((unsigned char)opname[2])
!          && ISLOWER((unsigned char)opname[3]))
      {
        if (opname[4] == '\0')
        {
          /* Operator.  */
          size_t i;
!         for (i = 0; i < ARRAY_SIZE (optable); i++)
            {
              if (strlen (optable[i].in) == 2
                  && memcmp (optable[i].in, opname + 2, 2) == 0)
***************
*** 633,639 ****
            {
              /* Assignment.  */
              size_t i;
!             for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
                {
                  if (strlen (optable[i].in) == 3
                      && memcmp (optable[i].in, opname + 2, 3) == 0)
--- 742,748 ----
            {
              /* Assignment.  */
              size_t i;
!             for (i = 0; i < ARRAY_SIZE (optable); i++)
                {
                  if (strlen (optable[i].in) == 3
                      && memcmp (optable[i].in, opname + 2, 3) == 0)
***************
*** 657,663 ****
          && memcmp (opname + 3, "assign_", 7) == 0)
        {
          size_t i;
!         for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
            {
              len1 = len - 10;
              if ((int) strlen (optable[i].in) == len1
--- 766,772 ----
          && memcmp (opname + 3, "assign_", 7) == 0)
        {
          size_t i;
!         for (i = 0; i < ARRAY_SIZE (optable); i++)
            {
              len1 = len - 10;
              if ((int) strlen (optable[i].in) == len1
***************
*** 674,680 ****
        else
        {
          size_t i;
!         for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
            {
              len1 = len - 3;
              if ((int) strlen (optable[i].in) == len1
--- 783,789 ----
        else
        {
          size_t i;
!         for (i = 0; i < ARRAY_SIZE (optable); i++)
            {
              len1 = len - 3;
              if ((int) strlen (optable[i].in) == len1
***************
*** 705,710 ****
--- 814,820 ----
    return ret;
  
  }
+ 
  /* Takes operator name as e.g. "++" and returns mangled
     operator name (e.g. "postincrement_expr"), or NULL if not found.
  
***************
*** 720,726 ****
    int len;
  
    len = strlen (opname);
!   for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
      {
        if ((int) strlen (optable[i].out) == len
          && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
--- 830,836 ----
    int len;
  
    len = strlen (opname);
!   for (i = 0; i < ARRAY_SIZE (optable); i++)
      {
        if ((int) strlen (optable[i].out) == len
          && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
***************
*** 730,735 ****
--- 840,879 ----
    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
***************
*** 766,774 ****
    char *ret;
    struct work_stuff work[1];
    memset ((char *) work, 0, sizeof (work));
!   work -> options = options;
!   if ((work -> options & DMGL_STYLE_MASK) == 0)
!     work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK;
  
    ret = internal_cplus_demangle (work, mangled);
    squangle_mop_up (work);
--- 910,936 ----
    char *ret;
    struct work_stuff work[1];
    memset ((char *) work, 0, sizeof (work));
!   work->options = options;
!   if ((work->options & DMGL_STYLE_MASK) == 0)
!     work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
! 
!   /* The V3 ABI demangling is implemented elsewhere.  */
!   if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
!     {
!       ret = cplus_demangle_v3 (mangled);
!       if (ret || GNU_V3_DEMANGLING)
!       return ret;
!     }
! 
!   if (JAVA_DEMANGLING)
!     {
!       ret = java_demangle_v3 (mangled);
!       if (ret)
!         return ret;
!     }
! 
!   if (GNAT_DEMANGLING)
!     return ada_demangle(mangled,options);
  
    ret = internal_cplus_demangle (work, mangled);
    squangle_mop_up (work);
***************
*** 776,781 ****
--- 938,1076 ----
  }
  
  
+ /* Assuming *OLD_VECT points to an array of *SIZE objects of size
+    ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
+    updating *OLD_VECT and *SIZE as necessary.  */
+ 
+ static void
+ grow_vect (old_vect, size, min_size, element_size)
+      void **old_vect;
+      size_t *size;
+      size_t min_size;
+      int element_size;
+ {
+   if (*size < min_size)
+     {
+       *size *= 2;
+       if (*size < min_size)
+       *size = min_size;
+       *old_vect = xrealloc (*old_vect, *size * element_size);
+     }
+ }
+ 
+ /* Demangle ada names:
+    1. Discard final __{DIGIT}+ or ${DIGIT}+
+    2. Convert other instances of embedded "__" to `.'.
+    3. Discard leading _ada_.
+    4. Remove everything after first ___ if it is followed by 'X'.
+    5. Put symbols that should be suppressed in <...> brackets.
+    The resulting string is valid until the next call of ada_demangle.  */
+ 
+ static char *
+ ada_demangle (mangled, option)
+      const char *mangled;
+      int option ATTRIBUTE_UNUSED;
+ {
+   int i, j;
+   int len0;
+   const char* p;
+   char *demangled = NULL;
+   int at_start_name;
+   int changed;
+   char *demangling_buffer = NULL;
+   size_t demangling_buffer_size = 0;
+   
+   changed = 0;
+ 
+   if (strncmp (mangled, "_ada_", 5) == 0)
+     {
+       mangled += 5;
+       changed = 1;
+     }
+   
+   if (mangled[0] == '_' || mangled[0] == '<')
+     goto Suppress;
+   
+   p = strstr (mangled, "___");
+   if (p == NULL)
+     len0 = strlen (mangled);
+   else
+     {
+       if (p[3] == 'X')
+       {
+         len0 = p - mangled;
+         changed = 1;
+       }
+       else
+       goto Suppress;
+     }
+   
+   /* Make demangled big enough for possible expansion by operator name.  */
+   grow_vect ((void **) &(demangling_buffer),
+            &demangling_buffer_size,  2 * len0 + 1,
+            sizeof (char));
+   demangled = demangling_buffer;
+   
+   if (ISDIGIT ((unsigned char) mangled[len0 - 1])) {
+     for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1)
+       ;
+     if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_')
+       {
+       len0 = i - 1;
+       changed = 1;
+       }
+     else if (mangled[i] == '$')
+       {
+       len0 = i;
+       changed = 1;
+       }
+   }
+   
+   for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
+        i += 1, j += 1)
+     demangled[j] = mangled[i];
+   
+   at_start_name = 1;
+   while (i < len0)
+     {
+       at_start_name = 0;
+       
+       if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_')
+       {
+         demangled[j] = '.';
+         changed = at_start_name = 1;
+         i += 2; j += 1;
+       }
+       else
+       {
+         demangled[j] = mangled[i];
+         i += 1;  j += 1;
+       }
+     }
+   demangled[j] = '\000';
+   
+   for (i = 0; demangled[i] != '\0'; i += 1)
+     if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ')
+       goto Suppress;
+ 
+   if (! changed)
+     return NULL;
+   else
+     return demangled;
+   
+  Suppress:
+   grow_vect ((void **) &(demangling_buffer),
+            &demangling_buffer_size,  strlen (mangled) + 3,
+            sizeof (char));
+   demangled = demangling_buffer;
+   if (mangled[0] == '<')
+      strcpy (demangled, mangled);
+   else
+     sprintf (demangled, "<%s>", mangled);
+ 
+   return demangled;
+ }
+ 
  /* This function performs most of what cplus_demangle use to do, but
     to be able to demangle a name with a B, K or n code, we need to
     have a longer term memory of what types have been seen. The original
***************
*** 791,797 ****
    string decl;
    int success = 0;
    char *demangled = NULL;
!   int s1,s2,s3,s4;
    s1 = work->constructor;
    s2 = work->destructor;
    s3 = work->static_type;
--- 1086,1092 ----
    string decl;
    int success = 0;
    char *demangled = NULL;
!   int s1, s2, s3, s4;
    s1 = work->constructor;
    s2 = work->destructor;
    s3 = work->static_type;
***************
*** 844,850 ****
    work->destructor = s2;
    work->static_type = s3;
    work->type_quals = s4;
!   return (demangled);
  }
  
  
--- 1139,1145 ----
    work->destructor = s2;
    work->static_type = s3;
    work->type_quals = s4;
!   return demangled;
  }
  
  
***************
*** 865,880 ****
      }
  }
  
- /* Clear out any mangled storage */
  
! static char *
! mop_up (work, declp, success)
!      struct work_stuff *work;
!      string *declp;
!      int success;
  {
!   char *demangled = NULL;
  
    /* Discard the remembered types, if any.  */
  
    forget_types (work);
--- 1160,1244 ----
      }
  }
  
  
! /* Copy the work state and storage.  */
! 
! static void
! work_stuff_copy_to_from (to, from)
!      struct work_stuff *to;
!      struct work_stuff *from;
  {
!   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);
***************
*** 901,906 ****
--- 1265,1294 ----
        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.  */
***************
*** 912,918 ****
    else
      {
        string_appendn (declp, "", 1);
!       demangled = declp -> b;
      }
    return (demangled);
  }
--- 1300,1306 ----
    else
      {
        string_appendn (declp, "", 1);
!       demangled = declp->b;
      }
    return (demangled);
  }
***************
*** 1126,1132 ****
          break;
  
        case '_':
!         if (GNU_DEMANGLING && expect_return_type)
            {
              /* Read the return type. */
              string return_type;
--- 1514,1520 ----
          break;
  
        case '_':
!         if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
            {
              /* Read the return type. */
              string return_type;
***************
*** 1152,1158 ****
              if (HP_DEMANGLING)
                {
                  (*mangled)++;
!                 while (**mangled && isdigit ((unsigned char)**mangled))
                    (*mangled)++;
                }
              else
--- 1540,1546 ----
              if (HP_DEMANGLING)
                {
                  (*mangled)++;
!                 while (**mangled && ISDIGIT ((unsigned char)**mangled))
                    (*mangled)++;
                }
              else
***************
*** 1160,1166 ****
          break;
  
        case 'H':
!         if (GNU_DEMANGLING)
            {
              /* A G++ template function.  Read the template arguments. */
              success = demangle_template (work, mangled, declp, 0, 0,
--- 1548,1554 ----
          break;
  
        case 'H':
!         if (AUTO_DEMANGLING || GNU_DEMANGLING)
            {
              /* A G++ template function.  Read the template arguments. */
              success = demangle_template (work, mangled, declp, 0, 0,
***************
*** 1328,1409 ****
  }
  
  static int
! demangle_integral_value (work, mangled, s)
       struct work_stuff *work;
       const char** mangled;
       string* s;
  {
    int success;
  
!   if (**mangled == 'E')
      {
!       int need_operator = 0;
! 
!       success = 1;
!       string_appendn (s, "(", 1);
!       (*mangled)++;
!       while (success && **mangled != 'W' && **mangled != '\0')
        {
!         if (need_operator)
!           {
!             size_t i;
!             size_t len;
  
!             success = 0;
  
!             len = strlen (*mangled);
  
!             for (i = 0;
!                  i < sizeof (optable) / sizeof (optable [0]);
!                  ++i)
!               {
!                 size_t l = strlen (optable[i].in);
  
!                 if (l <= len
!                     && memcmp (optable[i].in, *mangled, l) == 0)
!                   {
!                     string_appendn (s, " ", 1);
!                     string_append (s, optable[i].out);
!                     string_appendn (s, " ", 1);
!                     success = 1;
!                     (*mangled) += l;
!                     break;
!                   }
                }
- 
-             if (!success)
-               break;
            }
-         else
-           need_operator = 1;
  
!         success = demangle_template_value_parm (work, mangled, s,
!                                                 tk_integral);
        }
- 
-       if (**mangled != 'W')
-         success = 0;
        else
!       {
!         string_appendn (s, ")", 1);
!         (*mangled)++;
!       }
      }
    else if (**mangled == 'Q' || **mangled == 'K')
      success = demangle_qualified (work, mangled, s, 0, 1);
    else
      {
        success = 0;
  
        if (**mangled == 'm')
        {
          string_appendn (s, "-", 1);
          (*mangled)++;
        }
!       while (isdigit ((unsigned char)**mangled))
        {
!         string_appendn (s, *mangled, 1);
!         (*mangled)++;
          success = 1;
        }
      }
--- 1716,1855 ----
  }
  
  static int
! demangle_expression (work, mangled, s, tk)
       struct work_stuff *work;
       const char** mangled;
       string* s;
+      type_kind_t tk;
  {
+   int need_operator = 0;
    int success;
  
!   success = 1;
!   string_appendn (s, "(", 1);
!   (*mangled)++;
!   while (success && **mangled != 'W' && **mangled != '\0')
      {
!       if (need_operator)
        {
!         size_t i;
!         size_t len;
  
!         success = 0;
  
!         len = strlen (*mangled);
  
!         for (i = 0; i < ARRAY_SIZE (optable); ++i)
!           {
!             size_t l = strlen (optable[i].in);
  
!             if (l <= len
!                 && memcmp (optable[i].in, *mangled, l) == 0)
!               {
!                 string_appendn (s, " ", 1);
!                 string_append (s, optable[i].out);
!                 string_appendn (s, " ", 1);
!                 success = 1;
!                 (*mangled) += l;
!                 break;
                }
            }
  
!         if (!success)
!           break;
        }
        else
!       need_operator = 1;
! 
!       success = demangle_template_value_parm (work, mangled, s, tk);
      }
+ 
+   if (**mangled != 'W')
+     success = 0;
+   else
+     {
+       string_appendn (s, ")", 1);
+       (*mangled)++;
+     }
+ 
+   return success;
+ }
+ 
+ static int
+ demangle_integral_value (work, mangled, s)
+      struct work_stuff *work;
+      const char** mangled;
+      string* s;
+ {
+   int success;
+ 
+   if (**mangled == 'E')
+     success = demangle_expression (work, mangled, s, tk_integral);
    else if (**mangled == 'Q' || **mangled == 'K')
      success = demangle_qualified (work, mangled, s, 0, 1);
    else
      {
+       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'.  */
        if (**mangled == 'm')
        {
          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);
! 
!       if (value != -1)
!       {
!         char buf[INTBUF_SIZE];
!         sprintf (buf, "%d", value);
!         string_append (s, buf);
! 
!         /* 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.  */
          success = 1;
        }
      }
***************
*** 1411,1416 ****
--- 1857,1907 ----
    return success;
  }
  
+ /* Demangle the real value in MANGLED.  */
+ 
+ static int
+ demangle_real_value (work, mangled, s)
+      struct work_stuff *work;
+      const char **mangled;
+      string* s;
+ {
+   if (**mangled == 'E')
+     return demangle_expression (work, mangled, s, tk_real);
+ 
+   if (**mangled == 'm')
+     {
+       string_appendn (s, "-", 1);
+       (*mangled)++;
+     }
+   while (ISDIGIT ((unsigned char)**mangled))
+     {
+       string_appendn (s, *mangled, 1);
+       (*mangled)++;
+     }
+   if (**mangled == '.') /* fraction */
+     {
+       string_appendn (s, ".", 1);
+       (*mangled)++;
+       while (ISDIGIT ((unsigned char)**mangled))
+       {
+         string_appendn (s, *mangled, 1);
+         (*mangled)++;
+       }
+     }
+   if (**mangled == 'e') /* exponent */
+     {
+       string_appendn (s, "e", 1);
+       (*mangled)++;
+       while (ISDIGIT ((unsigned char)**mangled))
+       {
+         string_appendn (s, *mangled, 1);
+         (*mangled)++;
+       }
+     }
+ 
+   return 1;
+ }
+ 
  static int
  demangle_template_value_parm (work, mangled, s, tk)
       struct work_stuff *work;
***************
*** 1434,1444 ****
        if (work->tmpl_argvec)
        string_append (s, work->tmpl_argvec[idx]);
        else
!       {
!         char buf[10];
!         sprintf(buf, "T%d", idx);
!         string_append (s, buf);
!       }
      }
    else if (tk == tk_integral)
      success = demangle_integral_value (work, mangled, s);
--- 1925,1931 ----
        if (work->tmpl_argvec)
        string_append (s, work->tmpl_argvec[idx]);
        else
!       string_append_template_idx (s, idx);
      }
    else if (tk == tk_integral)
      success = demangle_integral_value (work, mangled, s);
***************
*** 1474,1511 ****
        success = 0;
      }
    else if (tk == tk_real)
!     {
!       if (**mangled == 'm')
!       {
!         string_appendn (s, "-", 1);
!         (*mangled)++;
!       }
!       while (isdigit ((unsigned char)**mangled))
!       {
!         string_appendn (s, *mangled, 1);
!         (*mangled)++;
!       }
!       if (**mangled == '.') /* fraction */
!       {
!         string_appendn (s, ".", 1);
!         (*mangled)++;
!         while (isdigit ((unsigned char)**mangled))
!           {
!             string_appendn (s, *mangled, 1);
!             (*mangled)++;
!           }
!       }
!       if (**mangled == 'e') /* exponent */
!       {
!         string_appendn (s, "e", 1);
!         (*mangled)++;
!         while (isdigit ((unsigned char)**mangled))
!           {
!             string_appendn (s, *mangled, 1);
!             (*mangled)++;
!           }
!       }
!     }
    else if (tk == tk_pointer || tk == tk_reference)
      {
        if (**mangled == 'Q')
--- 1961,1967 ----
        success = 0;
      }
    else if (tk == tk_real)
!     success = demangle_real_value (work, mangled, s);
    else if (tk == tk_pointer || tk == tk_reference)
      {
        if (**mangled == 'Q')
***************
*** 1555,1561 ****
     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
     types.  */
  
  static int
--- 2011,2017 ----
     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 template is remembered in the list of back-referenceable
     types.  */
  
  static int
***************
*** 1603,1613 ****
            }
          else
            {
!             char buf[10];
!             sprintf(buf, "T%d", idx);
!             string_append (tname, buf);
              if (trawname)
!               string_append (trawname, buf);
            }
        }
        else
--- 2059,2067 ----
            }
          else
            {
!             string_append_template_idx (tname, idx);
              if (trawname)
!               string_append_template_idx (trawname, idx);
            }
        }
        else
***************
*** 2089,2094 ****
--- 2543,2628 ----
    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
***************
*** 2104,2109 ****
--- 2638,2645 ----
  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
***************
*** 2207,2226 ****
      }
    else if (work -> static_type)
      {
!       if (!isdigit ((unsigned char)scan[0]) && (scan[0] != 't'))
        {
          success = 0;
        }
      }
    else if ((scan == *mangled)
!          && (isdigit ((unsigned char)scan[2]) || (scan[2] == 'Q')
               || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
      {
        /* The ARM says nothing about the mangling of local variables.
         But cfront mangles local variables by prepending __<nesting_level>
         to them. As an extension to ARM demangling we handle this case.  */
        if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
!         && isdigit ((unsigned char)scan[2]))
        {
          *mangled = scan + 2;
          consume_count (mangled);
--- 2743,2762 ----
      }
    else if (work -> static_type)
      {
!       if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
        {
          success = 0;
        }
      }
    else if ((scan == *mangled)
!          && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
               || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
      {
        /* The ARM says nothing about the mangling of local variables.
         But cfront mangles local variables by prepending __<nesting_level>
         to them. As an extension to ARM demangling we handle this case.  */
        if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
!         && ISDIGIT ((unsigned char)scan[2]))
        {
          *mangled = scan + 2;
          consume_count (mangled);
***************
*** 2257,2263 ****
        /* EDG template? */
        demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
      }
!   else if ((scan == *mangled) && !isdigit ((unsigned char)scan[2])
           && (scan[2] != 't'))
      {
        /* Mangled name starts with "__".  Skip over any leading '_' characters,
--- 2793,2799 ----
        /* EDG template? */
        demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
      }
!   else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
           && (scan[2] != 't'))
      {
        /* Mangled name starts with "__".  Skip over any leading '_' characters,
***************
*** 2277,2305 ****
              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);
!           }
        }
      }
    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);
      }
    else
      {
--- 2813,2828 ----
              success = 0;
            }
          else
!           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.  Iterate over all "__":s until the right
!        one is found.  */
!       return iterate_demangle_function (work, mangled, declp, scan);
      }
    else
      {
***************
*** 2392,2398 ****
                                           1);
              break;
            default:
!             if (isdigit((unsigned char)*mangled[0]))
                {
                  n = consume_count(mangled);
                  /* We may be seeing a too-large size, or else a
--- 2915,2921 ----
                                           1);
              break;
            default:
!             if (ISDIGIT((unsigned char)*mangled[0]))
                {
                  n = consume_count(mangled);
                  /* We may be seeing a too-large size, or else a
***************
*** 2448,2458 ****
          break;
        default:
          n = consume_count (mangled);
!         if (n < 0 || n > strlen (*mangled))
            {
              success = 0;
              break;
            }
          string_appendn (declp, *mangled, n);
          (*mangled) += n;
        }
--- 2971,3000 ----
          break;
        default:
          n = consume_count (mangled);
!         if (n < 0 || n > (long) strlen (*mangled))
            {
              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;
        }
***************
*** 2514,2520 ****
          success = demangle_template (work, mangled, declp, 0, 1, 1);
          break;
        default:
!         success = demangle_fund_type (work, mangled, declp);
          break;
        }
        if (success && **mangled != '\0')
--- 3056,3062 ----
          success = demangle_template (work, mangled, declp, 0, 1, 1);
          break;
        default:
!         success = do_type (work, mangled, declp);
          break;
        }
        if (success && **mangled != '\0')
***************
*** 2615,2621 ****
        {
          n = consume_count (mangled);
            if (n == -1
!             || n > strlen (*mangled))
            return 0;
          string_prependn (declp, *mangled, n);
          (*mangled) += n;
--- 3157,3163 ----
        {
          n = consume_count (mangled);
            if (n == -1
!             || n > (long) strlen (*mangled))
            return 0;
          string_prependn (declp, *mangled, n);
          (*mangled) += n;
***************
*** 2676,2682 ****
  {
    int qualifiers = 0;
    int success = 1;
-   const char *p;
    char num[2];
    string temp;
    string last_name;
--- 3218,3223 ----
***************
*** 2708,2726 ****
        /* GNU mangled name with more than 9 classes.  The count is preceded
         by an underscore (to distinguish it from the <= 9 case) and followed
         by an underscore.  */
!       p = *mangled + 2;
!       qualifiers = atoi (p);
!       if (!isdigit ((unsigned char)*p) || *p == '0')
!       success = 0;
! 
!       /* Skip the digits.  */
!       while (isdigit ((unsigned char)*p))
!       ++p;
! 
!       if (*p != '_')
        success = 0;
- 
-       *mangled = p + 1;
        break;
  
      case '1':
--- 3249,3258 ----
        /* GNU mangled name with more than 9 classes.  The count is preceded
         by an underscore (to distinguish it from the <= 9 case) and followed
         by an underscore.  */
!       (*mangled)++;
!       qualifiers = consume_count_with_underscores (mangled);
!       if (qualifiers == -1)
        success = 0;
        break;
  
      case '1':
***************
*** 2910,2924 ****
    const char *p;
    int n;
  
!   if (!isdigit ((unsigned char)**type))
!     {
!       return (0);
!     }
    else
      {
        *count = **type - '0';
        (*type)++;
!       if (isdigit ((unsigned char)**type))
        {
          p = *type;
          n = *count;
--- 3442,3454 ----
    const char *p;
    int n;
  
!   if (!ISDIGIT ((unsigned char)**type))
!     return (0);
    else
      {
        *count = **type - '0';
        (*type)++;
!       if (ISDIGIT ((unsigned char)**type))
        {
          p = *type;
          n = *count;
***************
*** 2928,2934 ****
              n += *p - '0';
              p++;
            }
!         while (isdigit ((unsigned char)*p));
          if (*p == '_')
            {
              *type = p + 1;
--- 3458,3464 ----
              n += *p - '0';
              p++;
            }
!         while (ISDIGIT ((unsigned char)*p));
          if (*p == '_')
            {
              *type = p + 1;
***************
*** 3052,3059 ****
            (*mangled)++;
  
            string_append (&decl, ")");
!           string_prepend (&decl, SCOPE_STRING (work));
!           if (isdigit ((unsigned char)**mangled))
              {
                n = consume_count (mangled);
                if (n == -1
--- 3582,3594 ----
            (*mangled)++;
  
            string_append (&decl, ")");
! 
!           /* We don't need to prepend `::' for a qualified name;
!              demangle_qualified will do that for us.  */
!           if (**mangled != 'Q')
!             string_prepend (&decl, SCOPE_STRING (work));
! 
!           if (ISDIGIT ((unsigned char)**mangled))
              {
                n = consume_count (mangled);
                if (n == -1
***************
*** 3085,3090 ****
--- 3620,3633 ----
                else
                  break;
              }
+           else if (**mangled == 'Q')
+             {
+               success = demangle_qualified (work, mangled, &decl,
+                                             /*isfuncnam=*/0, 
+                                             /*append=*/0);
+               if (!success)
+                 break;
+             }
            else
              {
                success = 0;
***************
*** 3197,3207 ****
        if (work->tmpl_argvec)
          string_append (result, work->tmpl_argvec[idx]);
        else
!         {
!           char buf[10];
!           sprintf(buf, "T%d", idx);
!           string_append (result, buf);
!         }
  
        success = 1;
        }
--- 3740,3746 ----
        if (work->tmpl_argvec)
          string_append (result, work->tmpl_argvec[idx]);
        else
!         string_append_template_idx (result, idx);
  
        success = 1;
        }
***************
*** 3255,3261 ****
    int done = 0;
    int success = 1;
    char buf[10];
!   int dec = 0;
    string btype;
    type_kind_t tk = tk_integral;
  
--- 3794,3800 ----
    int done = 0;
    int success = 1;
    char buf[10];
!   unsigned int dec = 0;
    string btype;
    type_kind_t tk = tk_integral;
  
***************
*** 3369,3375 ****
        break;
      case 'G':
        (*mangled)++;
!       if (!isdigit ((unsigned char)**mangled))
        {
          success = 0;
          break;
--- 3908,3914 ----
        break;
      case 'G':
        (*mangled)++;
!       if (!ISDIGIT ((unsigned char)**mangled))
        {
          success = 0;
          break;
***************
*** 3381,3387 ****
          int i;
          (*mangled)++;
          for (i = 0;
!              i < sizeof (buf) - 1 && **mangled && **mangled != '_';
               (*mangled)++, i++)
            buf[i] = **mangled;
          if (**mangled != '_')
--- 3920,3926 ----
          int i;
          (*mangled)++;
          for (i = 0;
!              i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
               (*mangled)++, i++)
            buf[i] = **mangled;
          if (**mangled != '_')
***************
*** 3399,3405 ****
          *mangled += min (strlen (*mangled), 2);
        }
        sscanf (buf, "%x", &dec);
!       sprintf (buf, "int%i_t", dec);
        APPEND_BLANK (result);
        string_append (result, buf);
        break;
--- 3938,3944 ----
          *mangled += min (strlen (*mangled), 2);
        }
        sscanf (buf, "%x", &dec);
!       sprintf (buf, "int%u_t", dec);
        APPEND_BLANK (result);
        string_append (result, buf);
        break;
***************
*** 3450,3456 ****
  
  static int
  do_hpacc_template_const_value (work, mangled, result)
!      struct work_stuff *work;
       const char **mangled;
       string *result;
  {
--- 3989,3995 ----
  
  static int
  do_hpacc_template_const_value (work, mangled, result)
!      struct work_stuff *work ATTRIBUTE_UNUSED;
       const char **mangled;
       string *result;
  {
***************
*** 3481,3492 ****
      }
  
    /* We have to be looking at an integer now */
!   if (!(isdigit ((unsigned char)**mangled)))
      return 0;
  
    /* We only deal with integral values for template
       parameters -- so it's OK to look only for digits */
!   while (isdigit ((unsigned char)**mangled))
      {
        char_str[0] = **mangled;
        string_append (result, char_str);
--- 4020,4031 ----
      }
  
    /* We have to be looking at an integer now */
!   if (!(ISDIGIT ((unsigned char)**mangled)))
      return 0;
  
    /* We only deal with integral values for template
       parameters -- so it's OK to look only for digits */
!   while (ISDIGIT ((unsigned char)**mangled))
      {
        char_str[0] = **mangled;
        string_append (result, char_str);
***************
*** 3565,3574 ****
    else if (**args == '+')
      (*args)++;
  
!   if (!isdigit ((unsigned char)**args))
      return 0;
  
!   while (isdigit ((unsigned char)**args))
      {
        char_str[0] = **args;
        string_append (arg, char_str);
--- 4104,4113 ----
    else if (**args == '+')
      (*args)++;
  
!   if (!ISDIGIT ((unsigned char)**args))
      return 0;
  
!   while (ISDIGIT ((unsigned char)**args))
      {
        char_str[0] = **args;
        string_append (arg, char_str);
***************
*** 4074,4080 ****
        if (declp->p - declp->b >= 10 /* op$assign_ */
          && memcmp (declp->b + 3, "assign_", 7) == 0)
        {
!         for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
            {
              int len = declp->p - declp->b - 10;
              if ((int) strlen (optable[i].in) == len
--- 4613,4619 ----
        if (declp->p - declp->b >= 10 /* op$assign_ */
          && memcmp (declp->b + 3, "assign_", 7) == 0)
        {
!         for (i = 0; i < ARRAY_SIZE (optable); i++)
            {
              int len = declp->p - declp->b - 10;
              if ((int) strlen (optable[i].in) == len
***************
*** 4090,4096 ****
        }
        else
        {
!         for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
            {
              int len = declp->p - declp->b - 3;
              if ((int) strlen (optable[i].in) == len
--- 4629,4635 ----
        }
        else
        {
!         for (i = 0; i < ARRAY_SIZE (optable); i++)
            {
              int len = declp->p - declp->b - 3;
              if ((int) strlen (optable[i].in) == len
***************
*** 4132,4144 ****
        }
      }
    else if (declp->b[0] == '_' && declp->b[1] == '_'
!          && declp->b[2] >= 'a' && declp->b[2] <= 'z'
!          && declp->b[3] >= 'a' && declp->b[3] <= 'z')
      {
        if (declp->b[4] == '\0')
        {
          /* Operator.  */
!         for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
            {
              if (strlen (optable[i].in) == 2
                  && memcmp (optable[i].in, declp->b + 2, 2) == 0)
--- 4671,4683 ----
        }
      }
    else if (declp->b[0] == '_' && declp->b[1] == '_'
!          && ISLOWER((unsigned char)declp->b[2])
!          && ISLOWER((unsigned char)declp->b[3]))
      {
        if (declp->b[4] == '\0')
        {
          /* Operator.  */
!         for (i = 0; i < ARRAY_SIZE (optable); i++)
            {
              if (strlen (optable[i].in) == 2
                  && memcmp (optable[i].in, declp->b + 2, 2) == 0)
***************
*** 4155,4161 ****
          if (declp->b[2] == 'a' && declp->b[5] == '\0')
            {
              /* Assignment.  */
!             for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
                {
                  if (strlen (optable[i].in) == 3
                      && memcmp (optable[i].in, declp->b + 2, 3) == 0)
--- 4694,4700 ----
          if (declp->b[2] == 'a' && declp->b[5] == '\0')
            {
              /* Assignment.  */
!             for (i = 0; i < ARRAY_SIZE (optable); i++)
                {
                  if (strlen (optable[i].in) == 3
                      && memcmp (optable[i].in, declp->b + 2, 3) == 0)
***************
*** 4320,4325 ****
--- 4859,4874 ----
      }
  }
  
+ static void
+ string_append_template_idx (s, idx)
+      string *s;
+      int idx;
+ {
+   char buf[INTBUF_SIZE + 1 /* 'T' */];
+   sprintf(buf, "T%d", idx);
+   string_append (s, buf);
+ }
+ 
  /* To generate a standalone demangler program for testing purposes,
     just compile and link this file with -DMAIN and libiberty.a.  When
     run, it demangles each command line arg, or each stdin string, and
***************
*** 4329,4341 ****
  
  #include "getopt.h"
  
! static char *program_name;
! static char *program_version = VERSION;
  static int flags = DMGL_PARAMS | DMGL_ANSI;
  
  static void demangle_it PARAMS ((char *));
! static void usage PARAMS ((FILE *, int));
! static void fatal PARAMS ((char *));
  
  static void
  demangle_it (mangled_name)
--- 4878,4891 ----
  
  #include "getopt.h"
  
! static const char *program_name;
! static const char *program_version = VERSION;
  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)
***************
*** 4355,4370 ****
      }
  }
  
  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",
           program_name);
    exit (status);
  }
  
--- 4905,4947 ----
      }
  }
  
+ 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] [--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);
  }
  
***************
*** 4380,4386 ****
    {"strip-underscores", no_argument, 0, '_'},
    {"format", required_argument, 0, 's'},
    {"help", no_argument, 0, 'h'},
-   {"java", no_argument, 0, 'j'},
    {"no-strip-underscores", no_argument, 0, 'n'},
    {"version", no_argument, 0, 'v'},
    {0, no_argument, 0, 0}
--- 4957,4962 ----
***************
*** 4396,4401 ****
--- 4972,4986 ----
  }
  
  
+ static const char *
+ standard_symbol_characters PARAMS ((void));
+ 
+ static const char *
+ hp_symbol_characters PARAMS ((void));
+ 
+ static const char *
+ gnu_v3_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.  */
***************
*** 4444,4449 ****
--- 5029,5047 ----
  }
  
  
+ /* Return the string of non-alnum characters that may occur 
+    as a valid symbol component in the GNU C++ V3 ABI mangling
+    scheme.  */
+ 
+ static const char *
+ gnu_v3_symbol_characters ()
+ {
+   return "_$.";
+ }
+ 
+ 
+ extern int main PARAMS ((int, char **));
+ 
  int
  main (argc, argv)
       int argc;
***************
*** 4451,4463 ****
  {
    char *result;
    int c;
!   char *valid_symbols;
  
    program_name = argv[0];
  
    strip_underscore = prepends_underscore;
  
!   while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != 
EOF)
      {
        switch (c)
        {
--- 5049,5062 ----
  {
    char *result;
    int c;
!   const char *valid_symbols;
!   enum demangling_styles style = auto_demangling;
  
    program_name = argv[0];
  
    strip_underscore = prepends_underscore;
  
!   while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != 
EOF)
      {
        switch (c)
        {
***************
*** 4471,4510 ****
          break;
        case 'v':
          printf ("GNU %s (C++ demangler), version %s\n", program_name, 
program_version);
!         exit (0);
        case '_':
          strip_underscore = 1;
          break;
-       case 'j':
-         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);
!             exit (1);
!           }
          break;
        }
      }
--- 5070,5091 ----
          break;
        case 'v':
          printf ("GNU %s (C++ demangler), version %s\n", program_name, 
program_version);
!         return (0);
        case '_':
          strip_underscore = 1;
          break;
        case 's':
!         {
!           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;
        }
      }
***************
*** 4523,4534 ****
--- 5104,5121 ----
        case gnu_demangling:
        case lucid_demangling:
        case arm_demangling:
+       case java_demangling:
        case edg_demangling:
+       case gnat_demangling:
+       case auto_demangling:
          valid_symbols = standard_symbol_characters ();
          break;
        case hp_demangling:
          valid_symbols = hp_symbol_characters ();
          break;
+       case gnu_v3_demangling:
+         valid_symbols = gnu_v3_symbol_characters ();
+         break;
        default:
          /* Folks should explicitly indicate the appropriate alphabet for
             each demangling.  Providing a default would allow the
***************
*** 4541,4547 ****
          int i = 0;
          c = getchar ();
          /* Try to read a label.  */
!         while (c != EOF && (isalnum (c) || strchr (valid_symbols, c)))
            {
              if (i >= MBUF_SIZE-1)
                break;
--- 5128,5134 ----
          int i = 0;
          c = getchar ();
          /* Try to read a label.  */
!         while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c)))
            {
              if (i >= MBUF_SIZE-1)
                break;
***************
*** 4561,4567 ****
                skip_first = i;
  
              mbuffer[i] = 0;
! 
              result = cplus_demangle (mbuffer + skip_first, flags);
              if (result)
                {
--- 5148,5154 ----
                skip_first = i;
  
              mbuffer[i] = 0;
!             flags |= (int) style;
              result = cplus_demangle (mbuffer + skip_first, flags);
              if (result)
                {
***************
*** 4578,4592 ****
          if (c == EOF)
            break;
          putchar (c);
        }
      }
  
!   exit (0);
  }
  
  static void
  fatal (str)
!      char *str;
  {
    fprintf (stderr, "%s: %s\n", program_name, str);
    exit (1);
--- 5165,5180 ----
          if (c == EOF)
            break;
          putchar (c);
+         fflush (stdout);
        }
      }
  
!   return (0);
  }
  
  static void
  fatal (str)
!      const char *str;
  {
    fprintf (stderr, "%s: %s\n", program_name, str);
    exit (1);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]