/[gcl]/gcl/binutils/libiberty/cp-demangle.c
ViewVC logotype

Diff of /gcl/binutils/libiberty/cp-demangle.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.1.1 by camm, Fri Aug 9 05:36:26 2002 UTC revision 1.2 by camm, Fri Sep 9 23:32:57 2005 UTC
# Line 1  Line 1 
1  /* Demangler for IA64 / g++ V3 ABI.  /* Demangler for g++ V3 ABI.
2     Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.     Copyright (C) 2003, 2004 Free Software Foundation, Inc.
3     Written by Alex Samuel <samuel@codesourcery.com>.     Written by Ian Lance Taylor <ian@wasabisystems.com>.
4    
5     This file is part of GNU CC.     This file is part of the libiberty library, which is part of GCC.
6    
7     This program is free software; you can redistribute it and/or modify     This file is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.     (at your option) any later version.
# Line 28  Line 28 
28     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29  */  */
30    
31  /* This file implements demangling of C++ names mangled according to  /* This code implements a demangler for the g++ V3 ABI.  The ABI is
32     the IA64 / g++ V3 ABI.  Use the cp_demangle function to     described on this web page:
33     demangle a mangled name, or compile with the preprocessor macro         http://www.codesourcery.com/cxx-abi/abi.html#mangling
34     STANDALONE_DEMANGLER defined to create a demangling filter  
35     executable (functionally similar to c++filt, but includes this     This code was written while looking at the demangler written by
36     demangler only).  */     Alex Samuel <samuel@codesourcery.com>.
37    
38       This code first pulls the mangled name apart into a list of
39       components, and then walks the list generating the demangled
40       name.
41    
42       This file will normally define the following functions, q.v.:
43          char *cplus_demangle_v3(const char *mangled, int options)
44          char *java_demangle_v3(const char *mangled)
45          enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor (const char *name)
46          enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor (const char *name)
47    
48       Also, the interface to the component list is public, and defined in
49       demangle.h.  The interface consists of these types, which are
50       defined in demangle.h:
51          enum demangle_component_type
52          struct demangle_component
53       and these functions defined in this file:
54          cplus_demangle_fill_name
55          cplus_demangle_fill_extended_operator
56          cplus_demangle_fill_ctor
57          cplus_demangle_fill_dtor
58          cplus_demangle_print
59       and other functions defined in the file cp-demint.c.
60    
61       This file also defines some other functions and variables which are
62       only to be used by the file cp-demint.c.
63    
64       Preprocessor macros you can define while compiling this file:
65    
66       IN_LIBGCC2
67          If defined, this file defines the following function, q.v.:
68             char *__cxa_demangle (const char *mangled, char *buf, size_t *len,
69                                   int *status)
70          instead of cplus_demangle_v3() and java_demangle_v3().
71    
72       IN_GLIBCPP_V3
73          If defined, this file defines only __cxa_demangle(), and no other
74          publically visible functions or variables.
75    
76       STANDALONE_DEMANGLER
77          If defined, this file defines a main() function which demangles
78          any arguments, or, if none, demangles stdin.
79    
80       CP_DEMANGLE_DEBUG
81          If defined, turns on debugging mode, which prints information on
82          stdout about the mangled string.  This is not generally useful.
83    */
84    
85  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
86  #include "config.h"  #include "config.h"
87  #endif  #endif
88    
89  #include <sys/types.h>  #include <stdio.h>
90    
91  #ifdef HAVE_STDLIB_H  #ifdef HAVE_STDLIB_H
92  #include <stdlib.h>  #include <stdlib.h>
93  #endif  #endif
   
 #include <stdio.h>  
   
94  #ifdef HAVE_STRING_H  #ifdef HAVE_STRING_H
95  #include <string.h>  #include <string.h>
96  #endif  #endif
97    
 #include <ctype.h>  
   
98  #include "ansidecl.h"  #include "ansidecl.h"
99  #include "libiberty.h"  #include "libiberty.h"
 #include "dyn-string.h"  
100  #include "demangle.h"  #include "demangle.h"
101    #include "cp-demangle.h"
102    
103  /* If CP_DEMANGLE_DEBUG is defined, a trace of the grammar evaluation,  /* If IN_GLIBCPP_V3 is defined, some functions are made static.  We
104     and other debugging output, will be generated. */     also rename them via #define to avoid compiler errors when the
105  #ifdef CP_DEMANGLE_DEBUG     static definition conflicts with the extern declaration in a header
106  #define DEMANGLE_TRACE(PRODUCTION, DM)                                  \     file.  */
107    fprintf (stderr, " -> %-24s at position %3d\n",                       \  #ifdef IN_GLIBCPP_V3
            (PRODUCTION), current_position (DM));  
 #else  
 #define DEMANGLE_TRACE(PRODUCTION, DM)  
 #endif  
108    
109  /* Don't include <ctype.h>, to prevent additional unresolved symbols  #define CP_STATIC_IF_GLIBCPP_V3 static
110     from being dragged into the C++ runtime library.  */  
111  #define IS_DIGIT(CHAR) ((CHAR) >= '0' && (CHAR) <= '9')  #define cplus_demangle_fill_name d_fill_name
112  #define IS_ALPHA(CHAR)                                                  \  static int
113    (((CHAR) >= 'a' && (CHAR) <= 'z')                                     \  d_fill_name PARAMS ((struct demangle_component *, const char *, int));
114     || ((CHAR) >= 'A' && (CHAR) <= 'Z'))  
115    #define cplus_demangle_fill_extended_operator d_fill_extended_operator
116    static int
117    d_fill_extended_operator PARAMS ((struct demangle_component *, int,
118                                      struct demangle_component *));
119    
120    #define cplus_demangle_fill_ctor d_fill_ctor
121    static int
122    d_fill_ctor PARAMS ((struct demangle_component *, enum gnu_v3_ctor_kinds,
123                         struct demangle_component *));
124    
125    #define cplus_demangle_fill_dtor d_fill_dtor
126    static int
127    d_fill_dtor PARAMS ((struct demangle_component *, enum gnu_v3_dtor_kinds,
128                         struct demangle_component *));
129    
130    #define cplus_demangle_mangled_name d_mangled_name
131    static struct demangle_component *
132    d_mangled_name PARAMS ((struct d_info *, int));
133    
134    #define cplus_demangle_type d_type
135    static struct demangle_component *
136    d_type PARAMS ((struct d_info *));
137    
138    #define cplus_demangle_print d_print
139    static char *
140    d_print PARAMS ((int, const struct demangle_component *, int, size_t *));
141    
142    #define cplus_demangle_init_info d_init_info
143    static void
144    d_init_info PARAMS ((const char *, int, size_t, struct d_info *));
145    
146    #else /* ! defined(IN_GLIBCPP_V3) */
147    #define CP_STATIC_IF_GLIBCPP_V3
148    #endif /* ! defined(IN_GLIBCPP_V3) */
149    
150    /* See if the compiler supports dynamic arrays.  */
151    
152    #ifdef __GNUC__
153    #define CP_DYNAMIC_ARRAYS
154    #else
155    #ifdef __STDC__
156    #ifdef __STDC_VERSION__
157    #if __STDC_VERSION__ >= 199901L
158    #define CP_DYNAMIC_ARRAYS
159    #endif /* __STDC__VERSION >= 199901L */
160    #endif /* defined (__STDC_VERSION__) */
161    #endif /* defined (__STDC__) */
162    #endif /* ! defined (__GNUC__) */
163    
164    /* We avoid pulling in the ctype tables, to prevent pulling in
165       additional unresolved symbols when this code is used in a library.
166       FIXME: Is this really a valid reason?  This comes from the original
167       V3 demangler code.
168    
169       As of this writing this file has the following undefined references
170       when compiled with -DIN_GLIBCPP_V3: malloc, realloc, free, memcpy,
171       strcpy, strcat, strlen.  */
172    
173    #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
174    #define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
175    #define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z')
176    
177  /* The prefix prepended by GCC to an identifier represnting the  /* The prefix prepended by GCC to an identifier represnting the
178     anonymous namespace.  */     anonymous namespace.  */
179  #define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"  #define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
180    #define ANONYMOUS_NAMESPACE_PREFIX_LEN \
181      (sizeof (ANONYMOUS_NAMESPACE_PREFIX) - 1)
182    
183  /* Character(s) to use for namespace separation in demangled output */  /* Information we keep for the standard substitutions.  */
 #define NAMESPACE_SEPARATOR (dm->style == DMGL_JAVA ? "." : "::")  
184    
185  /* If flag_verbose is zero, some simplifications will be made to the  struct d_standard_sub_info
186     output to make it easier to read and supress details that are  {
187     generally not of interest to the average C++ programmer.    /* The code for this substitution.  */
188     Otherwise, the demangled representation will attempt to convey as    char code;
189     much information as the mangled form.  */    /* The simple string it expands to.  */
190  static int flag_verbose;    const char *simple_expansion;
191      /* The length of the simple expansion.  */
192  /* If flag_strict is non-zero, demangle strictly according to the    int simple_len;
193     specification -- don't demangle special g++ manglings.  */    /* The results of a full, verbose, expansion.  This is used when
194  static int flag_strict;       qualifying a constructor/destructor, or when in verbose mode.  */
195      const char *full_expansion;
196  /* String_list_t is an extended form of dyn_string_t which provides a    /* The length of the full expansion.  */
197     link field and a caret position for additions to the string.  A    int full_len;
198     string_list_t may safely be cast to and used as a dyn_string_t.  */    /* What to set the last_name field of d_info to; NULL if we should
199         not set it.  This is only relevant when qualifying a
200  struct string_list_def       constructor/destructor.  */
201  {    const char *set_last_name;
202    /* The dyn_string; must be first.  */    /* The length of set_last_name.  */
203    struct dyn_string string;    int set_last_name_len;
   
   /* The position at which additional text is added to this string  
      (using the result_add* macros).  This value is an offset from the  
      end of the string, not the beginning (and should be  
      non-positive).  */  
   int caret_position;  
   
   /* The next string in the list.  */  
   struct string_list_def *next;  
204  };  };
205    
206  typedef struct string_list_def *string_list_t;  /* Accessors for subtrees of struct demangle_component.  */
207    
208  /* Data structure representing a potential substitution.  */  #define d_left(dc) ((dc)->u.s_binary.left)
209    #define d_right(dc) ((dc)->u.s_binary.right)
210    
211  struct substitution_def  /* A list of templates.  This is used while printing.  */
 {  
   /* The demangled text of the substitution.  */  
   dyn_string_t text;  
212    
213    /* Whether this substitution represents a template item.  */  struct d_print_template
214    int template_p : 1;  {
215      /* Next template on the list.  */
216      struct d_print_template *next;
217      /* This template.  */
218      const struct demangle_component *template;
219  };  };
220    
221  /* Data structure representing a template argument list.  */  /* A list of type modifiers.  This is used while printing.  */
222    
223  struct template_arg_list_def  struct d_print_mod
224  {  {
225    /* The next (lower) template argument list in the stack of currently    /* Next modifier on the list.  These are in the reverse of the order
226       active template arguments.  */       in which they appeared in the mangled string.  */
227    struct template_arg_list_def *next;    struct d_print_mod *next;
228      /* The modifier.  */
229      const struct demangle_component *mod;
230      /* Whether this modifier was printed.  */
231      int printed;
232      /* The list of templates which applies to this modifier.  */
233      struct d_print_template *templates;
234    };
235    
236    /* The first element in the list of template arguments in  /* We use this structure to hold information during printing.  */
      left-to-right order.  */  
   string_list_t first_argument;  
237    
238    /* The last element in the arguments lists.  */  struct d_print_info
239    string_list_t last_argument;  {
240      /* The options passed to the demangler.  */
241      int options;
242      /* Buffer holding the result.  */
243      char *buf;
244      /* Current length of data in buffer.  */
245      size_t len;
246      /* Allocated size of buffer.  */
247      size_t alc;
248      /* The current list of templates, if any.  */
249      struct d_print_template *templates;
250      /* The current list of modifiers (e.g., pointer, reference, etc.),
251         if any.  */
252      struct d_print_mod *modifiers;
253      /* Set to 1 if we had a memory allocation failure.  */
254      int allocation_failure;
255  };  };
256    
257  typedef struct template_arg_list_def *template_arg_list_t;  #define d_print_saw_error(dpi) ((dpi)->buf == NULL)
258    
259  /* Data structure to maintain the state of the current demangling.  */  #define d_append_char(dpi, c) \
260      do \
261        { \
262          if ((dpi)->buf != NULL && (dpi)->len < (dpi)->alc) \
263            (dpi)->buf[(dpi)->len++] = (c); \
264          else \
265            d_print_append_char ((dpi), (c)); \
266        } \
267      while (0)
268    
269  struct demangling_def  #define d_append_buffer(dpi, s, l) \
270  {    do \
271    /* The full mangled name being mangled.  */      { \
272    const char *name;        if ((dpi)->buf != NULL && (dpi)->len + (l) <= (dpi)->alc) \
273            { \
274              memcpy ((dpi)->buf + (dpi)->len, (s), (l)); \
275              (dpi)->len += l; \
276            } \
277          else \
278            d_print_append_buffer ((dpi), (s), (l)); \
279        } \
280      while (0)
281    
282    /* Pointer into name at the current position.  */  #define d_append_string_constant(dpi, s) \
283    const char *next;    d_append_buffer (dpi, (s), sizeof (s) - 1)
284    
285    /* Stack for strings containing demangled result generated so far.  #define d_last_char(dpi) \
286       Text is emitted to the topmost (first) string.  */    ((dpi)->buf == NULL || (dpi)->len == 0 ? '\0' : (dpi)->buf[(dpi)->len - 1])
   string_list_t result;  
287    
288    /* The number of presently available substitutions.  */  #ifdef CP_DEMANGLE_DEBUG
289    int num_substitutions;  static void
290    d_dump PARAMS ((struct demangle_component *, int));
291    #endif
292    
293    /* The allocated size of the substitutions array.  */  static struct demangle_component *
294    int substitutions_allocated;  d_make_empty PARAMS ((struct d_info *));
295    
296    /* An array of available substitutions.  The number of elements in  static struct demangle_component *
297       the array is given by num_substitions, and the allocated array  d_make_comp PARAMS ((struct d_info *, enum demangle_component_type,
298       size in substitutions_size.                         struct demangle_component *,
299                         struct demangle_component *));
300    
301    static struct demangle_component *
302    d_make_name PARAMS ((struct d_info *, const char *, int));
303    
304    static struct demangle_component *
305    d_make_builtin_type PARAMS ((struct d_info *,
306                                 const struct demangle_builtin_type_info *));
307    
308    static struct demangle_component *
309    d_make_operator PARAMS ((struct d_info *,
310                             const struct demangle_operator_info *));
311    
312    static struct demangle_component *
313    d_make_extended_operator PARAMS ((struct d_info *, int,
314                                      struct demangle_component *));
315    
316    static struct demangle_component *
317    d_make_ctor PARAMS ((struct d_info *, enum gnu_v3_ctor_kinds,
318                         struct demangle_component *));
319    
320    static struct demangle_component *
321    d_make_dtor PARAMS ((struct d_info *, enum gnu_v3_dtor_kinds,
322                         struct demangle_component *));
323    
324       The most recent substition is at the end, so  static struct demangle_component *
325    d_make_template_param PARAMS ((struct d_info *, long));
326    
327         - `S_'  corresponds to substititutions[num_substitutions - 1]  static struct demangle_component *
328         - `S0_' corresponds to substititutions[num_substitutions - 2]  d_make_sub PARAMS ((struct d_info *, const char *, int));
329    
330       etc. */  static int
331    struct substitution_def *substitutions;  has_return_type PARAMS ((struct demangle_component *));
332    
333    /* The stack of template argument lists.  */  static int
334    template_arg_list_t template_arg_lists;  is_ctor_dtor_or_conversion PARAMS ((struct demangle_component *));
335    
336    /* The most recently demangled source-name.  */  static struct demangle_component *
337    dyn_string_t last_source_name;  d_encoding PARAMS ((struct d_info *, int));
     
   /* Language style to use for demangled output. */  
   int style;  
338    
339    /* Set to non-zero iff this name is a constructor.  The actual value  static struct demangle_component *
340       indicates what sort of constructor this is; see demangle.h.  */  d_name PARAMS ((struct d_info *));
   enum gnu_v3_ctor_kinds is_constructor;  
341    
342    /* Set to non-zero iff this name is a destructor.  The actual value  static struct demangle_component *
343       indicates what sort of destructor this is; see demangle.h.  */  d_nested_name PARAMS ((struct d_info *));
   enum gnu_v3_dtor_kinds is_destructor;  
344    
345  };  static struct demangle_component *
346    d_prefix PARAMS ((struct d_info *));
347    
348  typedef struct demangling_def *demangling_t;  static struct demangle_component *
349    d_unqualified_name PARAMS ((struct d_info *));
350    
351  /* This type is the standard return code from most functions.  Values  static struct demangle_component *
352     other than STATUS_OK contain descriptive messages.  */  d_source_name PARAMS ((struct d_info *));
 typedef const char *status_t;  
   
 /* Special values that can be used as a status_t.  */  
 #define STATUS_OK                       NULL  
 #define STATUS_ERROR                    "Error."  
 #define STATUS_UNIMPLEMENTED            "Unimplemented."  
 #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.";  
 #define STATUS_ALLOCATION_FAILED        status_allocation_failed  
   
 /* Non-zero if STATUS indicates that no error has occurred.  */  
 #define STATUS_NO_ERROR(STATUS)         ((STATUS) == STATUS_OK)  
   
 /* Evaluate EXPR, which must produce a status_t.  If the status code  
    indicates an error, return from the current function with that  
    status code.  */  
 #define RETURN_IF_ERROR(EXPR)                                           \  
   do                                                                    \  
     {                                                                   \  
       status_t s = EXPR;                                                \  
       if (!STATUS_NO_ERROR (s))                                         \  
         return s;                                                       \  
     }                                                                   \  
   while (0)  
353    
354  static status_t int_to_dyn_string  static long
355    PARAMS ((int, dyn_string_t));  d_number PARAMS ((struct d_info *));
 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_push  
   PARAMS ((demangling_t));  
 static string_list_t result_pop  
   PARAMS ((demangling_t));  
 static int substitution_start  
   PARAMS ((demangling_t));  
 static status_t substitution_add  
   PARAMS ((demangling_t, int, int));  
 static dyn_string_t substitution_get  
   PARAMS ((demangling_t, int, int *));  
 #ifdef CP_DEMANGLE_DEBUG  
 static void substitutions_print  
   PARAMS ((demangling_t, FILE *));  
 #endif  
 static template_arg_list_t template_arg_list_new  
   PARAMS ((void));  
 static void template_arg_list_delete  
   PARAMS ((template_arg_list_t));  
 static void template_arg_list_add_arg  
   PARAMS ((template_arg_list_t, string_list_t));  
 static string_list_t template_arg_list_get_arg  
   PARAMS ((template_arg_list_t, int));  
 static void push_template_arg_list  
   PARAMS ((demangling_t, template_arg_list_t));  
 static void pop_to_template_arg_list  
   PARAMS ((demangling_t, template_arg_list_t));  
 #ifdef CP_DEMANGLE_DEBUG  
 static void template_arg_list_print  
   PARAMS ((template_arg_list_t, FILE *));  
 #endif  
 static template_arg_list_t current_template_arg_list  
   PARAMS ((demangling_t));  
 static demangling_t demangling_new  
   PARAMS ((const char *, int));  
 static void demangling_delete  
   PARAMS ((demangling_t));  
   
 /* The last character of DS.  Warning: DS is evaluated twice.  */  
 #define dyn_string_last_char(DS)                                        \  
   (dyn_string_buf (DS)[dyn_string_length (DS) - 1])  
   
 /* Append a space character (` ') to DS if it does not already end  
    with one.  Evaluates to 1 on success, or 0 on allocation failure.  */  
 #define dyn_string_append_space(DS)                                     \  
       ((dyn_string_length (DS) > 0                                      \  
         && dyn_string_last_char (DS) != ' ')                            \  
        ? dyn_string_append_char ((DS), ' ')                             \  
        : 1)  
   
 /* Returns the index of the current position in the mangled name.  */  
 #define current_position(DM)    ((DM)->next - (DM)->name)  
   
 /* Returns the character at the current position of the mangled name.  */  
 #define peek_char(DM)           (*((DM)->next))  
   
 /* Returns the character one past the current position of the mangled  
    name.  */  
 #define peek_char_next(DM)                                              \  
   (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1)))  
   
 /* Returns the character at the current position, and advances the  
    current position to the next character.  */  
 #define next_char(DM)           (*((DM)->next)++)  
   
 /* Returns non-zero if the current position is the end of the mangled  
    name, i.e. one past the last character.  */  
 #define end_of_name_p(DM)       (peek_char (DM) == '\0')  
   
 /* Advances the current position by one character.  */  
 #define advance_char(DM)        (++(DM)->next)  
   
 /* Returns the string containing the current demangled result.  */  
 #define result_string(DM)       (&(DM)->result->string)  
   
 /* Returns the position at which new text is inserted into the  
    demangled result.  */  
 #define result_caret_pos(DM)                                            \  
   (result_length (DM) +                                                 \  
    ((string_list_t) result_string (DM))->caret_position)  
   
 /* Adds a dyn_string_t to the demangled result.  */  
 #define result_add_string(DM, STRING)                                   \  
   (dyn_string_insert (&(DM)->result->string,                            \  
                       result_caret_pos (DM), (STRING))                  \  
    ? STATUS_OK : STATUS_ALLOCATION_FAILED)  
   
 /* Adds NUL-terminated string CSTR to the demangled result.    */  
 #define result_add(DM, CSTR)                                            \  
   (dyn_string_insert_cstr (&(DM)->result->string,                       \  
                            result_caret_pos (DM), (CSTR))               \  
    ? STATUS_OK : STATUS_ALLOCATION_FAILED)  
   
 /* Adds character CHAR to the demangled result.  */  
 #define result_add_char(DM, CHAR)                                       \  
   (dyn_string_insert_char (&(DM)->result->string,                       \  
                            result_caret_pos (DM), (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)  
   
 /* 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.  */  
   
 static status_t  
 int_to_dyn_string (value, ds)  
      int value;  
      dyn_string_t ds;  
 {  
   int i;  
   int mask = 1;  
356    
357    /* Handle zero up front.  */  static struct demangle_component *
358    if (value == 0)  d_identifier PARAMS ((struct d_info *, int));
     {  
       if (!dyn_string_append_char (ds, '0'))  
         return STATUS_ALLOCATION_FAILED;  
       return STATUS_OK;  
     }  
359    
360    /* For negative numbers, emit a minus sign.  */  static struct demangle_component *
361    if (value < 0)  d_operator_name PARAMS ((struct d_info *));
     {  
       if (!dyn_string_append_char (ds, '-'))  
         return STATUS_ALLOCATION_FAILED;  
       value = -value;  
     }  
     
   /* Find the power of 10 of the first digit.  */  
   i = value;  
   while (i > 9)  
     {  
       mask *= 10;  
       i /= 10;  
     }  
362    
363    /* Write the digits.  */  static struct demangle_component *
364    while (mask > 0)  d_special_name PARAMS ((struct d_info *));
     {  
       int digit = value / mask;  
365    
366        if (!dyn_string_append_char (ds, '0' + digit))  static int
367          return STATUS_ALLOCATION_FAILED;  d_call_offset PARAMS ((struct d_info *, int));
368    
369        value -= digit * mask;  static struct demangle_component *
370        mask /= 10;  d_ctor_dtor_name PARAMS ((struct d_info *));
     }  
371    
372    return STATUS_OK;  static struct demangle_component **
373  }  d_cv_qualifiers PARAMS ((struct d_info *, struct demangle_component **, int));
374    
375  /* Creates a new string list node.  The contents of the string are  static struct demangle_component *
376     empty, but the initial buffer allocation is LENGTH.  The string  d_function_type PARAMS ((struct d_info *));
    list node should be deleted with string_list_delete.  Returns NULL  
    if allocation fails.  */  
377    
378  static string_list_t  static struct demangle_component *
379  string_list_new (length)  d_bare_function_type PARAMS ((struct d_info *, int));
      int length;  
 {  
   string_list_t s = (string_list_t) malloc (sizeof (struct string_list_def));  
   s->caret_position = 0;  
   if (s == NULL)  
     return NULL;  
   if (!dyn_string_init ((dyn_string_t) s, length))  
     return NULL;  
   return s;  
 }    
380    
381  /* Deletes the entire string list starting at NODE.  */  static struct demangle_component *
382    d_class_enum_type PARAMS ((struct d_info *));
383    
384  static void  static struct demangle_component *
385  string_list_delete (node)  d_array_type PARAMS ((struct d_info *));
      string_list_t node;  
 {  
   while (node != NULL)  
     {  
       string_list_t next = node->next;  
       dyn_string_delete ((dyn_string_t) node);  
       node = next;  
     }  
 }  
386    
387  /* Appends CHARACTER to the demangled result.  If the current trailing  static struct demangle_component *
388     character of the result is CHARACTER, a space is inserted first.  */  d_pointer_to_member_type PARAMS ((struct d_info *));
389    
390  static status_t  static struct demangle_component *
391  result_add_separated_char (dm, character)  d_template_param PARAMS ((struct d_info *));
      demangling_t dm;  
      int character;  
 {  
   char *result = dyn_string_buf (result_string (dm));  
   int caret_pos = result_caret_pos (dm);  
392    
393    /* Add a space if the last character is already the character we  static struct demangle_component *
394       want to add.  */  d_template_args PARAMS ((struct d_info *));
   if (caret_pos > 0 && result[caret_pos - 1] == character)  
     RETURN_IF_ERROR (result_add_char (dm, ' '));  
   /* Add the character.  */  
   RETURN_IF_ERROR (result_add_char (dm, character));  
395    
396    return STATUS_OK;  static struct demangle_component *
397  }  d_template_arg PARAMS ((struct d_info *));
398    
399  /* Allocates and pushes a new string onto the demangled results stack  static struct demangle_component *
400     for DM.  Subsequent demangling with DM will emit to the new string.  d_expression PARAMS ((struct d_info *));
    Returns STATUS_OK on success, STATUS_ALLOCATION_FAILED on  
    allocation failure.  */  
401    
402  static status_t  static struct demangle_component *
403  result_push (dm)  d_expr_primary PARAMS ((struct d_info *));
      demangling_t dm;  
 {  
   string_list_t new_string = string_list_new (0);  
   if (new_string == NULL)  
     /* Allocation failed.  */  
     return STATUS_ALLOCATION_FAILED;  
404    
405    /* Link the new string to the front of the list of result strings.  */  static struct demangle_component *
406    new_string->next = (string_list_t) dm->result;  d_local_name PARAMS ((struct d_info *));
   dm->result = new_string;  
   return STATUS_OK;  
 }  
407    
408  /* Removes and returns the topmost element on the demangled results  static int
409     stack for DM.  The caller assumes ownership for the returned  d_discriminator PARAMS ((struct d_info *));
    string.  */  
410    
411  static string_list_t  static int
412  result_pop (dm)  d_add_substitution PARAMS ((struct d_info *, struct demangle_component *));
      demangling_t dm;  
 {  
   string_list_t top = dm->result;  
   dm->result = top->next;  
   return top;  
 }  
413    
414  /* Returns the current value of the caret for the result string.  The  static struct demangle_component *
415     value is an offet from the end of the result string.  */  d_substitution PARAMS ((struct d_info *, int));
416    
417  static int  static void
418  result_get_caret (dm)  d_print_resize PARAMS ((struct d_print_info *, size_t));
      demangling_t dm;  
 {  
   return ((string_list_t) result_string (dm))->caret_position;  
 }  
419    
420  /* Sets the value of the caret for the result string, counted as an  static void
421     offet from the end of the result string.  */  d_print_append_char PARAMS ((struct d_print_info *, int));
422    
423  static void  static void
424  result_set_caret (dm, position)  d_print_append_buffer PARAMS ((struct d_print_info *, const char *, size_t));
      demangling_t dm;  
      int position;  
 {  
   ((string_list_t) result_string (dm))->caret_position = position;  
 }  
425    
426  /* Shifts the position of the next addition to the result by  static void
427     POSITION_OFFSET.  A negative value shifts the caret to the left.  */  d_print_error PARAMS ((struct d_print_info *));
428    
429  static void  static void
430  result_shift_caret (dm, position_offset)  d_print_comp PARAMS ((struct d_print_info *,
431       demangling_t dm;                        const struct demangle_component *));
      int position_offset;  
 {  
   ((string_list_t) result_string (dm))->caret_position += position_offset;  
 }  
432    
433  /* Returns non-zero if the character that comes right before the place  static void
434     where text will be added to the result is a space.  In this case,  d_print_java_identifier PARAMS ((struct d_print_info *, const char *, int));
    the caller should supress adding another space.  */  
435    
436  static int  static void
437  result_previous_char_is_space (dm)  d_print_mod_list PARAMS ((struct d_print_info *, struct d_print_mod *, int));
      demangling_t dm;  
 {  
   char *result = dyn_string_buf (result_string (dm));  
   int pos = result_caret_pos (dm);  
   return pos > 0 && result[pos - 1] == ' ';  
 }  
438    
439  /* Returns the start position of a fragment of the demangled result  static void
440     that will be a substitution candidate.  Should be called at the  d_print_mod PARAMS ((struct d_print_info *,
441     start of productions that can add substitutions.  */                       const struct demangle_component *));
442    
443  static int  static void
444  substitution_start (dm)  d_print_function_type PARAMS ((struct d_print_info *,
445       demangling_t dm;                                 const struct demangle_component *,
446  {                                 struct d_print_mod *));
   return result_caret_pos (dm);  
 }  
447    
448  /* Adds the suffix of the current demangled result of DM starting at  static void
449     START_POSITION as a potential substitution.  If TEMPLATE_P is  d_print_array_type PARAMS ((struct d_print_info *,
450     non-zero, this potential substitution is a template-id.  */                              const struct demangle_component *,
451                                struct d_print_mod *));
452    
453  static status_t  static void
454  substitution_add (dm, start_position, template_p)  d_print_expr_op PARAMS ((struct d_print_info *,
455       demangling_t dm;                           const struct demangle_component *));
456       int start_position;  
457       int template_p;  static void
458    d_print_cast PARAMS ((struct d_print_info *,
459                          const struct demangle_component *));
460    
461    static char *
462    d_demangle PARAMS ((const char *, int, size_t *));
463    
464    #ifdef CP_DEMANGLE_DEBUG
465    
466    static void
467    d_dump (dc, indent)
468         struct demangle_component *dc;
469         int indent;
470  {  {
   dyn_string_t result = result_string (dm);  
   dyn_string_t substitution = dyn_string_new (0);  
471    int i;    int i;
472    
473    if (substitution == NULL)    if (dc == NULL)
474      return STATUS_ALLOCATION_FAILED;      return;
475    
476    /* Extract the substring of the current demangling result that    for (i = 0; i < indent; ++i)
477       represents the subsitution candidate.  */      putchar (' ');
   if (!dyn_string_substring (substitution,  
                              result, start_position, result_caret_pos (dm)))  
     {  
       dyn_string_delete (substitution);  
       return STATUS_ALLOCATION_FAILED;  
     }  
478    
479    /* If there's no room for the new entry, grow the array.  */    switch (dc->type)
   if (dm->substitutions_allocated == dm->num_substitutions)  
480      {      {
481        size_t new_array_size;      case DEMANGLE_COMPONENT_NAME:
482        if (dm->substitutions_allocated > 0)        printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
483          dm->substitutions_allocated *= 2;        return;
484        else      case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
485          dm->substitutions_allocated = 2;        printf ("template parameter %ld\n", dc->u.s_number.number);
486        new_array_size =        return;
487          sizeof (struct substitution_def) * dm->substitutions_allocated;      case DEMANGLE_COMPONENT_CTOR:
488          printf ("constructor %d\n", (int) dc->u.s_ctor.kind);
489          d_dump (dc->u.s_ctor.name, indent + 2);
490          return;
491        case DEMANGLE_COMPONENT_DTOR:
492          printf ("destructor %d\n", (int) dc->u.s_dtor.kind);
493          d_dump (dc->u.s_dtor.name, indent + 2);
494          return;
495        case DEMANGLE_COMPONENT_SUB_STD:
496          printf ("standard substitution %s\n", dc->u.s_string.string);
497          return;
498        case DEMANGLE_COMPONENT_BUILTIN_TYPE:
499          printf ("builtin type %s\n", dc->u.s_builtin.type->name);
500          return;
501        case DEMANGLE_COMPONENT_OPERATOR:
502          printf ("operator %s\n", dc->u.s_operator.op->name);
503          return;
504        case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
505          printf ("extended operator with %d args\n",
506                  dc->u.s_extended_operator.args);
507          d_dump (dc->u.s_extended_operator.name, indent + 2);
508          return;
509    
510        dm->substitutions = (struct substitution_def *)      case DEMANGLE_COMPONENT_QUAL_NAME:
511          realloc (dm->substitutions, new_array_size);        printf ("qualified name\n");
512        if (dm->substitutions == NULL)        break;
513          /* Realloc failed.  */      case DEMANGLE_COMPONENT_LOCAL_NAME:
514          {        printf ("local name\n");
515            dyn_string_delete (substitution);        break;
516            return STATUS_ALLOCATION_FAILED;      case DEMANGLE_COMPONENT_TYPED_NAME:
517          }        printf ("typed name\n");
518          break;
519        case DEMANGLE_COMPONENT_TEMPLATE:
520          printf ("template\n");
521          break;
522        case DEMANGLE_COMPONENT_VTABLE:
523          printf ("vtable\n");
524          break;
525        case DEMANGLE_COMPONENT_VTT:
526          printf ("VTT\n");
527          break;
528        case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
529          printf ("construction vtable\n");
530          break;
531        case DEMANGLE_COMPONENT_TYPEINFO:
532          printf ("typeinfo\n");
533          break;
534        case DEMANGLE_COMPONENT_TYPEINFO_NAME:
535          printf ("typeinfo name\n");
536          break;
537        case DEMANGLE_COMPONENT_TYPEINFO_FN:
538          printf ("typeinfo function\n");
539          break;
540        case DEMANGLE_COMPONENT_THUNK:
541          printf ("thunk\n");
542          break;
543        case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
544          printf ("virtual thunk\n");
545          break;
546        case DEMANGLE_COMPONENT_COVARIANT_THUNK:
547          printf ("covariant thunk\n");
548          break;
549        case DEMANGLE_COMPONENT_JAVA_CLASS:
550          printf ("java class\n");
551          break;
552        case DEMANGLE_COMPONENT_GUARD:
553          printf ("guard\n");
554          break;
555        case DEMANGLE_COMPONENT_REFTEMP:
556          printf ("reference temporary\n");
557          break;
558        case DEMANGLE_COMPONENT_RESTRICT:
559          printf ("restrict\n");
560          break;
561        case DEMANGLE_COMPONENT_VOLATILE:
562          printf ("volatile\n");
563          break;
564        case DEMANGLE_COMPONENT_CONST:
565          printf ("const\n");
566          break;
567        case DEMANGLE_COMPONENT_RESTRICT_THIS:
568          printf ("restrict this\n");
569          break;
570        case DEMANGLE_COMPONENT_VOLATILE_THIS:
571          printf ("volatile this\n");
572          break;
573        case DEMANGLE_COMPONENT_CONST_THIS:
574          printf ("const this\n");
575          break;
576        case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
577          printf ("vendor type qualifier\n");
578          break;
579        case DEMANGLE_COMPONENT_POINTER:
580          printf ("pointer\n");
581          break;
582        case DEMANGLE_COMPONENT_REFERENCE:
583          printf ("reference\n");
584          break;
585        case DEMANGLE_COMPONENT_COMPLEX:
586          printf ("complex\n");
587          break;
588        case DEMANGLE_COMPONENT_IMAGINARY:
589          printf ("imaginary\n");
590          break;
591        case DEMANGLE_COMPONENT_VENDOR_TYPE:
592          printf ("vendor type\n");
593          break;
594        case DEMANGLE_COMPONENT_FUNCTION_TYPE:
595          printf ("function type\n");
596          break;
597        case DEMANGLE_COMPONENT_ARRAY_TYPE:
598          printf ("array type\n");
599          break;
600        case DEMANGLE_COMPONENT_PTRMEM_TYPE:
601          printf ("pointer to member type\n");
602          break;
603        case DEMANGLE_COMPONENT_ARGLIST:
604          printf ("argument list\n");
605          break;
606        case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
607          printf ("template argument list\n");
608          break;
609        case DEMANGLE_COMPONENT_CAST:
610          printf ("cast\n");
611          break;
612        case DEMANGLE_COMPONENT_UNARY:
613          printf ("unary operator\n");
614          break;
615        case DEMANGLE_COMPONENT_BINARY:
616          printf ("binary operator\n");
617          break;
618        case DEMANGLE_COMPONENT_BINARY_ARGS:
619          printf ("binary operator arguments\n");
620          break;
621        case DEMANGLE_COMPONENT_TRINARY:
622          printf ("trinary operator\n");
623          break;
624        case DEMANGLE_COMPONENT_TRINARY_ARG1:
625          printf ("trinary operator arguments 1\n");
626          break;
627        case DEMANGLE_COMPONENT_TRINARY_ARG2:
628          printf ("trinary operator arguments 1\n");
629          break;
630        case DEMANGLE_COMPONENT_LITERAL:
631          printf ("literal\n");
632          break;
633        case DEMANGLE_COMPONENT_LITERAL_NEG:
634          printf ("negative literal\n");
635          break;
636      }      }
637    
638    /* Add the substitution to the array.  */    d_dump (d_left (dc), indent + 2);
639    i = dm->num_substitutions++;    d_dump (d_right (dc), indent + 2);
   dm->substitutions[i].text = substitution;  
   dm->substitutions[i].template_p = template_p;  
   
 #ifdef CP_DEMANGLE_DEBUG  
   substitutions_print (dm, stderr);  
 #endif  
   
   return STATUS_OK;  
640  }  }
641    
642  /* Returns the Nth-most-recent substitution.  Sets *TEMPLATE_P to  #endif /* CP_DEMANGLE_DEBUG */
    non-zero if the substitution is a template-id, zero otherwise.    
    N is numbered from zero.  DM retains ownership of the returned  
    string.  If N is negative, or equal to or greater than the current  
    number of substitution candidates, returns NULL.  */  
   
 static dyn_string_t  
 substitution_get (dm, n, template_p)  
      demangling_t dm;  
      int n;  
      int *template_p;  
 {  
   struct substitution_def *sub;  
643    
644    /* Make sure N is in the valid range.  */  /* Fill in a DEMANGLE_COMPONENT_NAME.  */
   if (n < 0 || n >= dm->num_substitutions)  
     return NULL;  
645    
646    sub = &(dm->substitutions[n]);  CP_STATIC_IF_GLIBCPP_V3
647    *template_p = sub->template_p;  int
648    return sub->text;  cplus_demangle_fill_name (p, s, len)
649         struct demangle_component *p;
650         const char *s;
651         int len;
652    {
653      if (p == NULL || s == NULL || len == 0)
654        return 0;
655      p->type = DEMANGLE_COMPONENT_NAME;
656      p->u.s_name.s = s;
657      p->u.s_name.len = len;
658      return 1;
659  }  }
660    
661  #ifdef CP_DEMANGLE_DEBUG  /* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR.  */
 /* Debugging routine to print the current substitutions to FP.  */  
662    
663  static void  CP_STATIC_IF_GLIBCPP_V3
664  substitutions_print (dm, fp)  int
665       demangling_t dm;  cplus_demangle_fill_extended_operator (p, args, name)
666       FILE *fp;       struct demangle_component *p;
667         int args;
668         struct demangle_component *name;
669  {  {
670    int seq_id;    if (p == NULL || args < 0 || name == NULL)
671    int num = dm->num_substitutions;      return 0;
672      p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR;
673      p->u.s_extended_operator.args = args;
674      p->u.s_extended_operator.name = name;
675      return 1;
676    }
677    
678    fprintf (fp, "SUBSTITUTIONS:\n");  /* Fill in a DEMANGLE_COMPONENT_CTOR.  */
   for (seq_id = -1; seq_id < num - 1; ++seq_id)  
     {  
       int template_p;  
       dyn_string_t text = substitution_get (dm, seq_id + 1, &template_p);  
679    
680        if (seq_id == -1)  CP_STATIC_IF_GLIBCPP_V3
681          fprintf (fp, " S_ ");  int
682        else  cplus_demangle_fill_ctor (p, kind, name)
683          fprintf (fp, " S%d_", seq_id);       struct demangle_component *p;
684        fprintf (fp, " %c: %s\n", template_p ? '*' : ' ', dyn_string_buf (text));       enum gnu_v3_ctor_kinds kind;
685      }       struct demangle_component *name;
686    {
687      if (p == NULL
688          || name == NULL
689          || (kind < gnu_v3_complete_object_ctor
690              && kind > gnu_v3_complete_object_allocating_ctor))
691        return 0;
692      p->type = DEMANGLE_COMPONENT_CTOR;
693      p->u.s_ctor.kind = kind;
694      p->u.s_ctor.name = name;
695      return 1;
696  }  }
697    
698  #endif /* CP_DEMANGLE_DEBUG */  /* Fill in a DEMANGLE_COMPONENT_DTOR.  */
699    
700  /* Creates a new template argument list.  Returns NULL if allocation  CP_STATIC_IF_GLIBCPP_V3
701     fails.  */  int
702    cplus_demangle_fill_dtor (p, kind, name)
703  static template_arg_list_t       struct demangle_component *p;
704  template_arg_list_new ()       enum gnu_v3_dtor_kinds kind;
705  {       struct demangle_component *name;
706    template_arg_list_t new_list =  {
707      (template_arg_list_t) malloc (sizeof (struct template_arg_list_def));    if (p == NULL
708    if (new_list == NULL)        || name == NULL
709      return NULL;        || (kind < gnu_v3_deleting_dtor
710    /* Initialize the new list to have no arguments.  */            && kind > gnu_v3_base_object_dtor))
711    new_list->first_argument = NULL;      return 0;
712    new_list->last_argument = NULL;    p->type = DEMANGLE_COMPONENT_DTOR;
713    /* Return the new list.  */    p->u.s_dtor.kind = kind;
714    return new_list;    p->u.s_dtor.name = name;
715      return 1;
716  }  }
717    
718  /* Deletes a template argument list and the template arguments it  /* Add a new component.  */
    contains.  */  
719    
720  static void  static struct demangle_component *
721  template_arg_list_delete (list)  d_make_empty (di)
722       template_arg_list_t list;       struct d_info *di;
723  {  {
724    /* If there are any arguments on LIST, delete them.  */    struct demangle_component *p;
   if (list->first_argument != NULL)  
     string_list_delete (list->first_argument);  
   /* Delete LIST.  */  
   free (list);  
 }  
725    
726  /* Adds ARG to the template argument list ARG_LIST.  */    if (di->next_comp >= di->num_comps)
727        return NULL;
728      p = &di->comps[di->next_comp];
729      ++di->next_comp;
730      return p;
731    }
732    
733    /* Add a new generic component.  */
734    
735    static struct demangle_component *
736    d_make_comp (di, type, left, right)
737         struct d_info *di;
738         enum demangle_component_type type;
739         struct demangle_component *left;
740         struct demangle_component *right;
741    {
742      struct demangle_component *p;
743    
744      /* We check for errors here.  A typical error would be a NULL return
745         from a subroutine.  We catch those here, and return NULL
746         upward.  */
747      switch (type)
748        {
749          /* These types require two parameters.  */
750        case DEMANGLE_COMPONENT_QUAL_NAME:
751        case DEMANGLE_COMPONENT_LOCAL_NAME:
752        case DEMANGLE_COMPONENT_TYPED_NAME:
753        case DEMANGLE_COMPONENT_TEMPLATE:
754        case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
755        case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
756        case DEMANGLE_COMPONENT_PTRMEM_TYPE:
757        case DEMANGLE_COMPONENT_UNARY:
758        case DEMANGLE_COMPONENT_BINARY:
759        case DEMANGLE_COMPONENT_BINARY_ARGS:
760        case DEMANGLE_COMPONENT_TRINARY:
761        case DEMANGLE_COMPONENT_TRINARY_ARG1:
762        case DEMANGLE_COMPONENT_TRINARY_ARG2:
763        case DEMANGLE_COMPONENT_LITERAL:
764        case DEMANGLE_COMPONENT_LITERAL_NEG:
765          if (left == NULL || right == NULL)
766            return NULL;
767          break;
768    
769  static void        /* These types only require one parameter.  */
770  template_arg_list_add_arg (arg_list, arg)      case DEMANGLE_COMPONENT_VTABLE:
771       template_arg_list_t arg_list;      case DEMANGLE_COMPONENT_VTT:
772       string_list_t arg;      case DEMANGLE_COMPONENT_TYPEINFO:
773  {      case DEMANGLE_COMPONENT_TYPEINFO_NAME:
774    if (arg_list->first_argument == NULL)      case DEMANGLE_COMPONENT_TYPEINFO_FN:
775      /* If there were no arguments before, ARG is the first one.  */      case DEMANGLE_COMPONENT_THUNK:
776      arg_list->first_argument = arg;      case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
777    else      case DEMANGLE_COMPONENT_COVARIANT_THUNK:
778      /* Make ARG the last argument on the list.  */      case DEMANGLE_COMPONENT_JAVA_CLASS:
779      arg_list->last_argument->next = arg;      case DEMANGLE_COMPONENT_GUARD:
780    /* Make ARG the last on the list.  */      case DEMANGLE_COMPONENT_REFTEMP:
781    arg_list->last_argument = arg;      case DEMANGLE_COMPONENT_POINTER:
782    arg->next = NULL;      case DEMANGLE_COMPONENT_REFERENCE:
783  }      case DEMANGLE_COMPONENT_COMPLEX:
784        case DEMANGLE_COMPONENT_IMAGINARY:
785  /* Returns the template arugment at position INDEX in template      case DEMANGLE_COMPONENT_VENDOR_TYPE:
786     argument list ARG_LIST.  */      case DEMANGLE_COMPONENT_ARGLIST:
787        case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
788  static string_list_t      case DEMANGLE_COMPONENT_CAST:
789  template_arg_list_get_arg (arg_list, index)        if (left == NULL)
790       template_arg_list_t arg_list;          return NULL;
791       int index;        break;
792  {  
793    string_list_t arg = arg_list->first_argument;        /* This needs a right parameter, but the left parameter can be
794    /* Scan down the list of arguments to find the one at position           empty.  */
795       INDEX.  */      case DEMANGLE_COMPONENT_ARRAY_TYPE:
796    while (index--)        if (right == NULL)
     {  
       arg = arg->next;  
       if (arg == NULL)  
         /* Ran out of arguments before INDEX hit zero.  That's an  
            error.  */  
797          return NULL;          return NULL;
798          break;
799    
800          /* These are allowed to have no parameters--in some cases they
801             will be filled in later.  */
802        case DEMANGLE_COMPONENT_FUNCTION_TYPE:
803        case DEMANGLE_COMPONENT_RESTRICT:
804        case DEMANGLE_COMPONENT_VOLATILE:
805        case DEMANGLE_COMPONENT_CONST:
806        case DEMANGLE_COMPONENT_RESTRICT_THIS:
807        case DEMANGLE_COMPONENT_VOLATILE_THIS:
808        case DEMANGLE_COMPONENT_CONST_THIS:
809          break;
810    
811          /* Other types should not be seen here.  */
812        default:
813          return NULL;
814        }
815    
816      p = d_make_empty (di);
817      if (p != NULL)
818        {
819          p->type = type;
820          p->u.s_binary.left = left;
821          p->u.s_binary.right = right;
822      }      }
823    /* Return the argument at position INDEX.  */    return p;
   return arg;  
824  }  }
825    
826  /* Pushes ARG_LIST onto the top of the template argument list stack.  */  /* Add a new name component.  */
827    
828  static void  static struct demangle_component *
829  push_template_arg_list (dm, arg_list)  d_make_name (di, s, len)
830       demangling_t dm;       struct d_info *di;
831       template_arg_list_t arg_list;       const char *s;
832         int len;
833  {  {
834    arg_list->next = dm->template_arg_lists;    struct demangle_component *p;
835    dm->template_arg_lists = arg_list;  
836  #ifdef CP_DEMANGLE_DEBUG    p = d_make_empty (di);
837    fprintf (stderr, " ** pushing template arg list\n");    if (! cplus_demangle_fill_name (p, s, len))
838    template_arg_list_print (arg_list, stderr);      return NULL;
839  #endif    return p;
840  }  }
841    
842  /* Pops and deletes elements on the template argument list stack until  /* Add a new builtin type component.  */
    arg_list is the topmost element.  If arg_list is NULL, all elements  
    are popped and deleted.  */  
843    
844  static void  static struct demangle_component *
845  pop_to_template_arg_list (dm, arg_list)  d_make_builtin_type (di, type)
846       demangling_t dm;       struct d_info *di;
847       template_arg_list_t arg_list;       const struct demangle_builtin_type_info *type;
848  {  {
849    while (dm->template_arg_lists != arg_list)    struct demangle_component *p;
850      {  
851        template_arg_list_t top = dm->template_arg_lists;    if (type == NULL)
852        /* Disconnect the topmost element from the list.  */      return NULL;
853        dm->template_arg_lists = top->next;    p = d_make_empty (di);
854        /* Delete the popped element.  */    if (p != NULL)
855        template_arg_list_delete (top);      {
856  #ifdef CP_DEMANGLE_DEBUG        p->type = DEMANGLE_COMPONENT_BUILTIN_TYPE;
857        fprintf (stderr, " ** removing template arg list\n");        p->u.s_builtin.type = type;
 #endif  
858      }      }
859      return p;
860  }  }
861    
862  #ifdef CP_DEMANGLE_DEBUG  /* Add a new operator component.  */
   
 /* Prints the contents of ARG_LIST to FP.  */  
863    
864  static void  static struct demangle_component *
865  template_arg_list_print (arg_list, fp)  d_make_operator (di, op)
866    template_arg_list_t arg_list;       struct d_info *di;
867    FILE *fp;       const struct demangle_operator_info *op;
868  {  {
869    string_list_t arg;    struct demangle_component *p;
   int index = -1;  
870    
871    fprintf (fp, "TEMPLATE ARGUMENT LIST:\n");    p = d_make_empty (di);
872    for (arg = arg_list->first_argument; arg != NULL; arg = arg->next)    if (p != NULL)
873      {      {
874        if (index == -1)        p->type = DEMANGLE_COMPONENT_OPERATOR;
875          fprintf (fp, " T_  : ");        p->u.s_operator.op = op;
       else  
         fprintf (fp, " T%d_ : ", index);  
       ++index;  
       fprintf (fp, "%s\n", dyn_string_buf ((dyn_string_t) arg));  
876      }      }
877      return p;
878  }  }
879    
880  #endif /* CP_DEMANGLE_DEBUG */  /* Add a new extended operator component.  */
   
 /* Returns the topmost element on the stack of template argument  
    lists.  If there is no list of template arguments, returns NULL.  */  
881    
882  static template_arg_list_t  static struct demangle_component *
883  current_template_arg_list (dm)  d_make_extended_operator (di, args, name)
884       demangling_t dm;       struct d_info *di;
885         int args;
886         struct demangle_component *name;
887  {  {
888    return dm->template_arg_lists;    struct demangle_component *p;
889    
890      p = d_make_empty (di);
891      if (! cplus_demangle_fill_extended_operator (p, args, name))
892        return NULL;
893      return p;
894  }  }
895    
896  /* Allocates a demangling_t object for demangling mangled NAME.  A new  /* Add a new constructor component.  */
    result must be pushed before the returned object can be used.  
    Returns NULL if allocation fails.  */  
897    
898  static demangling_t  static struct demangle_component *
899  demangling_new (name, style)  d_make_ctor (di, kind,  name)
900       const char *name;       struct d_info *di;
901       int style;       enum gnu_v3_ctor_kinds kind;
902         struct demangle_component *name;
903  {  {
904    demangling_t dm;    struct demangle_component *p;
   dm = (demangling_t) malloc (sizeof (struct demangling_def));  
   if (dm == NULL)  
     return NULL;  
905    
906    dm->name = name;    p = d_make_empty (di);
907    dm->next = name;    if (! cplus_demangle_fill_ctor (p, kind, name))
   dm->result = NULL;  
   dm->num_substitutions = 0;  
   dm->substitutions_allocated = 10;  
   dm->template_arg_lists = NULL;  
   dm->last_source_name = dyn_string_new (0);  
   if (dm->last_source_name == NULL)  
908      return NULL;      return NULL;
909    dm->substitutions = (struct substitution_def *)    return p;
     malloc (dm->substitutions_allocated * sizeof (struct substitution_def));  
   if (dm->substitutions == NULL)  
     {  
       dyn_string_delete (dm->last_source_name);  
       return NULL;  
     }  
   dm->style = style;  
   dm->is_constructor = 0;  
   dm->is_destructor = 0;  
   
   return dm;  
910  }  }
911    
912  /* Deallocates a demangling_t object and all memory associated with  /* Add a new destructor component.  */
    it.  */  
913    
914  static void  static struct demangle_component *
915  demangling_delete (dm)  d_make_dtor (di, kind, name)
916       demangling_t dm;       struct d_info *di;
917         enum gnu_v3_dtor_kinds kind;
918         struct demangle_component *name;
919  {  {
920    int i;    struct demangle_component *p;
   template_arg_list_t arg_list = dm->template_arg_lists;  
921    
922    /* Delete the stack of template argument lists.  */    p = d_make_empty (di);
923    while (arg_list != NULL)    if (! cplus_demangle_fill_dtor (p, kind, name))
924      {      return NULL;
925        template_arg_list_t next = arg_list->next;    return p;
926        template_arg_list_delete (arg_list);  }
927        arg_list = next;  
928      }  /* Add a new template parameter.  */
929    /* Delete the list of substitutions.  */  
930    for (i = dm->num_substitutions; --i >= 0; )  static struct demangle_component *
931      dyn_string_delete (dm->substitutions[i].text);  d_make_template_param (di, i)
932    free (dm->substitutions);       struct d_info *di;
933    /* Delete the demangled result.  */       long i;
   string_list_delete (dm->result);  
   /* Delete the stored identifier name.  */  
   dyn_string_delete (dm->last_source_name);  
   /* Delete the context object itself.  */  
   free (dm);  
 }  
   
 /* These functions demangle an alternative of the corresponding  
    production in the mangling spec.  The first argument of each is a  
    demangling context structure for the current demangling  
    operation.  Most emit demangled text directly to the topmost result  
    string on the result string stack in the demangling context  
    structure.  */  
   
 static status_t demangle_char  
   PARAMS ((demangling_t, int));  
 static status_t demangle_mangled_name  
   PARAMS ((demangling_t));  
 static status_t demangle_encoding  
   PARAMS ((demangling_t));  
 static status_t demangle_name  
   PARAMS ((demangling_t, int *));  
 static status_t demangle_nested_name  
   PARAMS ((demangling_t, int *));  
 static status_t demangle_prefix  
   PARAMS ((demangling_t, int *));  
 static status_t demangle_unqualified_name  
   PARAMS ((demangling_t, int *));  
 static status_t demangle_source_name  
   PARAMS ((demangling_t));  
 static status_t demangle_number  
   PARAMS ((demangling_t, int *, int, int));  
 static status_t demangle_number_literally  
   PARAMS ((demangling_t, dyn_string_t, int, int));  
 static status_t demangle_identifier  
   PARAMS ((demangling_t, int, dyn_string_t));  
 static status_t demangle_operator_name  
   PARAMS ((demangling_t, int, 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));  
 static status_t demangle_type  
   PARAMS ((demangling_t));  
 static status_t demangle_CV_qualifiers  
   PARAMS ((demangling_t, dyn_string_t));  
 static status_t demangle_builtin_type  
   PARAMS ((demangling_t));  
 static status_t demangle_function_type  
   PARAMS ((demangling_t, int *));  
 static status_t demangle_bare_function_type  
   PARAMS ((demangling_t, int *));  
 static status_t demangle_class_enum_type  
   PARAMS ((demangling_t, int *));  
 static status_t demangle_array_type  
   PARAMS ((demangling_t, int *));  
 static status_t demangle_template_param  
   PARAMS ((demangling_t));  
 static status_t demangle_template_args  
   PARAMS ((demangling_t));  
 static status_t demangle_literal  
   PARAMS ((demangling_t));  
 static status_t demangle_template_arg  
   PARAMS ((demangling_t));  
 static status_t demangle_expression  
   PARAMS ((demangling_t));  
 static status_t demangle_scope_expression  
   PARAMS ((demangling_t));  
 static status_t demangle_expr_primary  
   PARAMS ((demangling_t));  
 static status_t demangle_substitution  
   PARAMS ((demangling_t, 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, int));  
 static status_t cp_demangle_type  
   PARAMS ((const char*, dyn_string_t));  
   
 /* 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  
   
 /* Check that the next character is C.  If so, consume it.  If not,  
    return an error.  */  
   
 static status_t  
 demangle_char (dm, c)  
      demangling_t dm;  
      int c;  
934  {  {
935    static char *error_message = NULL;    struct demangle_component *p;
936    
937    if (peek_char (dm) == c)    p = d_make_empty (di);
938      if (p != NULL)
939      {      {
940        advance_char (dm);        p->type = DEMANGLE_COMPONENT_TEMPLATE_PARAM;
941        return STATUS_OK;        p->u.s_number.number = i;
942      }      }
943    else    return p;
944    }
945    
946    /* Add a new standard substitution component.  */
947    
948    static struct demangle_component *
949    d_make_sub (di, name, len)
950         struct d_info *di;
951         const char *name;
952         int len;
953    {
954      struct demangle_component *p;
955    
956      p = d_make_empty (di);
957      if (p != NULL)
958      {      {
959        if (error_message == NULL)        p->type = DEMANGLE_COMPONENT_SUB_STD;
960          error_message = strdup ("Expected ?");        p->u.s_string.string = name;
961        error_message[9] = c;        p->u.s_string.len = len;
       return error_message;  
962      }      }
963      return p;
964  }  }
965    
966  /* Demangles and emits a <mangled-name>.    /* <mangled-name> ::= _Z <encoding>
967    
968      <mangled-name>      ::= _Z <encoding>  */     TOP_LEVEL is non-zero when called at the top level.  */
969    
970  static status_t  CP_STATIC_IF_GLIBCPP_V3
971  demangle_mangled_name (dm)  struct demangle_component *
972       demangling_t dm;  cplus_demangle_mangled_name (di, top_level)
973         struct d_info *di;
974         int top_level;
975  {  {
976    DEMANGLE_TRACE ("mangled-name", dm);    if (d_next_char (di) != '_')
977    RETURN_IF_ERROR (demangle_char (dm, '_'));      return NULL;
978    RETURN_IF_ERROR (demangle_char (dm, 'Z'));    if (d_next_char (di) != 'Z')
979    RETURN_IF_ERROR (demangle_encoding (dm));      return NULL;
980    return STATUS_OK;    return d_encoding (di, top_level);
981  }  }
982    
983  /* Demangles and emits an <encoding>.    /* Return whether a function should have a return type.  The argument
984       is the function name, which may be qualified in various ways.  The
985       rules are that template functions have return types with some
986       exceptions, function types which are not part of a function name
987       mangling have return types with some exceptions, and non-template
988       function names do not have return types.  The exceptions are that
989       constructors, destructors, and conversion operators do not have
990       return types.  */
991    
992    static int
993    has_return_type (dc)
994         struct demangle_component *dc;
995    {
996      if (dc == NULL)
997        return 0;
998      switch (dc->type)
999        {
1000        default:
1001          return 0;
1002        case DEMANGLE_COMPONENT_TEMPLATE:
1003          return ! is_ctor_dtor_or_conversion (d_left (dc));
1004        case DEMANGLE_COMPONENT_RESTRICT_THIS:
1005        case DEMANGLE_COMPONENT_VOLATILE_THIS:
1006        case DEMANGLE_COMPONENT_CONST_THIS:
1007          return has_return_type (d_left (dc));
1008        }
1009    }
1010    
1011      <encoding>          ::= <function name> <bare-function-type>  /* Return whether a name is a constructor, a destructor, or a
1012                          ::= <data name>     conversion operator.  */
                         ::= <special-name>  */  
1013    
1014  static status_t  static int
1015  demangle_encoding (dm)  is_ctor_dtor_or_conversion (dc)
1016       demangling_t dm;       struct demangle_component *dc;
1017  {  {
1018    int encode_return_type;    if (dc == NULL)
1019    int start_position;      return 0;
1020    template_arg_list_t old_arg_list = current_template_arg_list (dm);    switch (dc->type)
1021    char peek = peek_char (dm);      {
1022        default:
1023          return 0;
1024        case DEMANGLE_COMPONENT_QUAL_NAME:
1025        case DEMANGLE_COMPONENT_LOCAL_NAME:
1026          return is_ctor_dtor_or_conversion (d_right (dc));
1027        case DEMANGLE_COMPONENT_CTOR:
1028        case DEMANGLE_COMPONENT_DTOR:
1029        case DEMANGLE_COMPONENT_CAST:
1030          return 1;
1031        }
1032    }
1033    
1034    DEMANGLE_TRACE ("encoding", dm);  /* <encoding> ::= <(function) name> <bare-function-type>
1035                    ::= <(data) name>
1036    /* Remember where the name starts.  If it turns out to be a template                ::= <special-name>
1037       function, we'll have to insert the return type here.  */  
1038    start_position = result_caret_pos (dm);     TOP_LEVEL is non-zero when called at the top level, in which case
1039       if DMGL_PARAMS is not set we do not demangle the function
1040       parameters.  We only set this at the top level, because otherwise
1041       we would not correctly demangle names in local scopes.  */
1042    
1043    static struct demangle_component *
1044    d_encoding (di, top_level)
1045         struct d_info *di;
1046         int top_level;
1047    {
1048      char peek = d_peek_char (di);
1049    
1050    if (peek == 'G' || peek == 'T')    if (peek == 'G' || peek == 'T')
1051      RETURN_IF_ERROR (demangle_special_name (dm));      return d_special_name (di);
1052    else    else
1053      {      {
1054        /* Now demangle the name.  */        struct demangle_component *dc;
       RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));  
   
       /* If there's anything left, the name was a function name, with  
          maybe its return type, and its parameter types, following.  */  
       if (!end_of_name_p (dm)  
           && peek_char (dm) != 'E')  
         {  
           if (encode_return_type)  
             /* 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));  
           else  
             /* Non-template functions don't have their return type  
                encoded.  */  
             RETURN_IF_ERROR  
               (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE));  
         }  
     }  
1055    
1056    /* Pop off template argument lists that were built during the        dc = d_name (di);
      mangling of this name, to restore the old template context.  */  
   pop_to_template_arg_list (dm, old_arg_list);  
1057    
1058    return STATUS_OK;        if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0)
1059  }          {
1060              /* Strip off any initial CV-qualifiers, as they really apply
1061                 to the `this' parameter, and they were not output by the
1062                 v2 demangler without DMGL_PARAMS.  */
1063              while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
1064                     || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
1065                     || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
1066                dc = d_left (dc);
1067    
1068              /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then
1069                 there may be CV-qualifiers on its right argument which
1070                 really apply here; this happens when parsing a class
1071                 which is local to a function.  */
1072              if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME)
1073                {
1074                  struct demangle_component *dcr;
1075    
1076  /* Demangles and emits a <name>.                dcr = d_right (dc);
1077                  while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS
1078                         || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS
1079                         || dcr->type == DEMANGLE_COMPONENT_CONST_THIS)
1080                    dcr = d_left (dcr);
1081                  dc->u.s_binary.right = dcr;
1082                }
1083    
1084      <name>              ::= <unscoped-name>            return dc;
1085                          ::= <unscoped-template-name> <template-args>          }
                         ::= <nested-name>  
                         ::= <local-name>  
1086    
1087      <unscoped-name>     ::= <unqualified-name>        peek = d_peek_char (di);
1088                          ::= St <unqualified-name>   # ::std::        if (peek == '\0' || peek == 'E')
1089            return dc;
1090          return d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, dc,
1091                              d_bare_function_type (di, has_return_type (dc)));
1092        }
1093    }
1094    
1095      <unscoped-template-name>      /* <name> ::= <nested-name>
1096                          ::= <unscoped-name>            ::= <unscoped-name>
1097                          ::= <substitution>  */            ::= <unscoped-template-name> <template-args>
1098              ::= <local-name>
1099    
1100  static status_t     <unscoped-name> ::= <unqualified-name>
1101  demangle_name (dm, encode_return_type)                     ::= St <unqualified-name>
      demangling_t dm;  
      int *encode_return_type;  
 {  
   int start = substitution_start (dm);  
   char peek = peek_char (dm);  
   int is_std_substitution = 0;  
1102    
1103    /* Generally, the return type is encoded if the function is a     <unscoped-template-name> ::= <unscoped-name>
1104       template-id, and suppressed otherwise.  There are a few cases,                              ::= <substitution>
1105       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;  
1106    
1107    DEMANGLE_TRACE ("name", dm);  static struct demangle_component *
1108    d_name (di)
1109         struct d_info *di;
1110    {
1111      char peek = d_peek_char (di);
1112      struct demangle_component *dc;
1113    
1114    switch (peek)    switch (peek)
1115      {      {
1116      case 'N':      case 'N':
1117        /* This is a <nested-name>.  */        return d_nested_name (di);
       RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));  
       break;  
1118    
1119      case 'Z':      case 'Z':
1120        RETURN_IF_ERROR (demangle_local_name (dm));        return d_local_name (di);
       *encode_return_type = 0;  
       break;  
1121    
1122      case 'S':      case 'S':
1123        /* The `St' substitution allows a name nested in std:: to appear        {
1124           without being enclosed in a nested name.  */          int subst;
       if (peek_char_next (dm) == 't')  
         {  
           (void) next_char (dm);  
           (void) next_char (dm);  
           RETURN_IF_ERROR (result_add (dm, "std::"));  
           RETURN_IF_ERROR  
             (demangle_unqualified_name (dm, &suppress_return_type));  
           is_std_substitution = 1;  
         }  
       else  
         RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));  
       /* 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 (demangle_template_args (dm));  
           *encode_return_type = !suppress_return_type;  
         }  
       else  
         *encode_return_type = 0;  
1125    
1126        break;          if (d_peek_next_char (di) != 't')
1127              {
1128                dc = d_substitution (di, 0);
1129                subst = 1;
1130              }
1131            else
1132              {
1133                d_advance (di, 2);
1134                dc = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME,
1135                                  d_make_name (di, "std", 3),
1136                                  d_unqualified_name (di));
1137                di->expansion += 3;
1138                subst = 0;
1139              }
1140    
1141      default:          if (d_peek_char (di) != 'I')
1142        /* This is an <unscoped-name> or <unscoped-template-name>.  */            {
1143        RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));              /* The grammar does not permit this case to occur if we
1144                   called d_substitution() above (i.e., subst == 1).  We
1145                   don't bother to check.  */
1146              }
1147            else
1148              {
1149                /* This is <template-args>, which means that we just saw
1150                   <unscoped-template-name>, which is a substitution
1151                   candidate if we didn't just get it from a
1152                   substitution.  */
1153                if (! subst)
1154                  {
1155                    if (! d_add_substitution (di, dc))
1156                      return NULL;
1157                  }
1158                dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
1159                                  d_template_args (di));
1160              }
1161    
1162        /* If the <unqualified-name> is followed by template args, this          return dc;
1163           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));  
1164    
1165            RETURN_IF_ERROR (demangle_template_args (dm));      default:
1166            *encode_return_type = !suppress_return_type;        dc = d_unqualified_name (di);
1167          if (d_peek_char (di) == 'I')
1168            {
1169              /* This is <template-args>, which means that we just saw
1170                 <unscoped-template-name>, which is a substitution
1171                 candidate.  */
1172              if (! d_add_substitution (di, dc))
1173                return NULL;
1174              dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc,
1175                                d_template_args (di));
1176          }          }
1177        else        return dc;
         *encode_return_type = 0;  
   
       break;  
1178      }      }
   
   return STATUS_OK;  
1179  }  }
1180    
1181  /* Demangles and emits a <nested-name>.  /* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
1182                     ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
1183      <nested-name>     ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E  */  */
1184    
1185  static status_t  static struct demangle_component *
1186  demangle_nested_name (dm, encode_return_type)  d_nested_name (di)
1187       demangling_t dm;       struct d_info *di;
      int *encode_return_type;  
1188  {  {
1189    char peek;    struct demangle_component *ret;
1190      struct demangle_component **pret;
1191    
1192    DEMANGLE_TRACE ("nested-name", dm);    if (d_next_char (di) != 'N')
1193        return NULL;
1194    
1195    RETURN_IF_ERROR (demangle_char (dm, 'N'));    pret = d_cv_qualifiers (di, &ret, 1);
1196      if (pret == NULL)
1197        return NULL;
1198    
1199    peek = peek_char (dm);    *pret = d_prefix (di);
1200    if (peek == 'r' || peek == 'V' || peek == 'K')    if (*pret == NULL)
1201      {      return NULL;
       dyn_string_t cv_qualifiers;  
       status_t status;  
1202    
1203        /* Snarf up CV qualifiers.  */    if (d_next_char (di) != 'E')
1204        cv_qualifiers = dyn_string_new (24);      return NULL;
       if (cv_qualifiers == NULL)  
         return STATUS_ALLOCATION_FAILED;  
       demangle_CV_qualifiers (dm, cv_qualifiers);  
   
       /* Emit them, preceded by a space.  */  
       status = result_add_char (dm, ' ');  
       if (STATUS_NO_ERROR (status))  
         status = result_add_string (dm, cv_qualifiers);  
       /* The CV qualifiers that occur in a <nested-name> will be  
          qualifiers for member functions.  These are placed at the end  
          of the function.  Therefore, shift the caret to the left by  
          the length of the qualifiers, so other text is inserted  
          before them and they stay at the end.  */  
       result_shift_caret (dm, -dyn_string_length (cv_qualifiers) - 1);  
       /* Clean up.  */  
       dyn_string_delete (cv_qualifiers);  
       RETURN_IF_ERROR (status);  
     }  
   
   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_char (dm, 'E'));  
   
   return STATUS_OK;  
 }  
   
 /* Demangles and emits a <prefix>.  
   
     <prefix>            ::= <prefix> <unqualified-name>  
                         ::= <template-prefix> <template-args>  
                         ::= # empty  
                         ::= <substitution>  
   
     <template-prefix>   ::= <prefix>  
                         ::= <substitution>  */  
   
 static status_t  
 demangle_prefix (dm, encode_return_type)  
      demangling_t dm;  
      int *encode_return_type;  
 {  
   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;  
1205    
1206    DEMANGLE_TRACE ("prefix", dm);    return ret;
1207    }
1208    
1209    /* <prefix> ::= <prefix> <unqualified-name>
1210                ::= <template-prefix> <template-args>
1211                ::= <template-param>
1212                ::=
1213                ::= <substitution>
1214    
1215       <template-prefix> ::= <prefix> <(template) unqualified-name>
1216                         ::= <template-param>
1217                         ::= <substitution>
1218    */
1219    
1220    static struct demangle_component *
1221    d_prefix (di)
1222         struct d_info *di;
1223    {
1224      struct demangle_component *ret = NULL;
1225    
1226    while (1)    while (1)
1227      {      {
1228        char peek;        char peek;
1229          enum demangle_component_type comb_type;
1230          struct demangle_component *dc;
1231    
1232        if (end_of_name_p (dm))        peek = d_peek_char (di);
1233          return "Unexpected end of name in <compound-name>.";        if (peek == '\0')
1234            return NULL;
       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'  
           || peek == 'S')  
         {  
           /* We have another level of scope qualification.  */  
           if (nested)  
             RETURN_IF_ERROR (result_add (dm, NAMESPACE_SEPARATOR));  
           else  
             nested = 1;  
1235    
1236            if (peek == 'S')        /* The older code accepts a <local-name> here, but I don't see
1237              /* The substitution determines whether this is a           that in the grammar.  The older code does not accept a
1238                 template-id.  */           <template-param> here.  */
1239              RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));  
1240            else        comb_type = DEMANGLE_COMPONENT_QUAL_NAME;
1241              {        if (IS_DIGIT (peek)
1242                /* It's just a name.  */            || IS_LOWER (peek)
1243                RETURN_IF_ERROR            || peek == 'C'
1244                  (demangle_unqualified_name (dm, &suppress_return_type));            || peek == 'D')
1245                *encode_return_type = 0;          dc = d_unqualified_name (di);
1246              }        else if (peek == 'S')
1247          }          dc = d_substitution (di, 1);
       else if (peek == 'Z')  
         RETURN_IF_ERROR (demangle_local_name (dm));  
1248        else if (peek == 'I')        else if (peek == 'I')
1249          {          {
1250            RETURN_IF_ERROR (demangle_template_args (dm));            if (ret == NULL)
1251                return NULL;
1252            /* Now we want to indicate to the caller that we've            comb_type = DEMANGLE_COMPONENT_TEMPLATE;
1253               demangled template arguments, thus the prefix was a            dc = d_template_args (di);
              <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;  
1254          }          }
1255          else if (peek == 'T')
1256            dc = d_template_param (di);
1257        else if (peek == 'E')        else if (peek == 'E')
1258          /* All done.  */          return ret;
1259          return STATUS_OK;        else
1260            return NULL;
1261    
1262          if (ret == NULL)
1263            ret = dc;
1264        else        else
1265          return "Unexpected character in <compound-name>.";          ret = d_make_comp (di, comb_type, ret, dc);
1266    
1267        if (peek != 'S'        if (peek != 'S' && d_peek_char (di) != 'E')
1268            && peek_char (dm) != 'E')          {
1269          /* Add a new substitution for the prefix thus far.  */            if (! d_add_substitution (di, ret))
1270          RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));              return NULL;
1271            }
1272      }      }
1273  }  }
1274    
1275  /* Demangles and emits an <unqualified-name>.  If this  /* <unqualified-name> ::= <operator-name>
1276     <unqualified-name> is for a special function type that should never                        ::= <ctor-dtor-name>
1277     have its return type encoded (particularly, a constructor or                        ::= <source-name>
1278     conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise,  */
    it is set to zero.  
   
     <unqualified-name>  ::= <operator-name>  
                         ::= <special-name>    
                         ::= <source-name>  */  
1279    
1280  static status_t  static struct demangle_component *
1281  demangle_unqualified_name (dm, suppress_return_type)  d_unqualified_name (di)
1282       demangling_t dm;       struct d_info *di;
      int *suppress_return_type;  
1283  {  {
1284    char peek = peek_char (dm);    char peek;
1285    
1286    DEMANGLE_TRACE ("unqualified-name", dm);    peek = d_peek_char (di);
1287      if (IS_DIGIT (peek))
1288        return d_source_name (di);
1289      else if (IS_LOWER (peek))
1290        {
1291          struct demangle_component *ret;
1292    
1293          ret = d_operator_name (di);
1294          if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR)
1295            di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2;
1296          return ret;
1297        }
1298      else if (peek == 'C' || peek == 'D')
1299        return d_ctor_dtor_name (di);
1300      else
1301        return NULL;
1302    }
1303    
1304    /* By default, don't force suppression of the return type (though  /* <source-name> ::= <(positive length) number> <identifier>  */
      non-template functions still don't get a return type encoded).  */  
   *suppress_return_type = 0;  
1305    
1306    if (IS_DIGIT ((unsigned char) peek))  static struct demangle_component *
1307      RETURN_IF_ERROR (demangle_source_name (dm));  d_source_name (di)
1308    else if (peek >= 'a' && peek <= 'z')       struct d_info *di;
1309      {  {
1310        int num_args;    long len;
1311      struct demangle_component *ret;
1312    
1313        /* Conversion operators never have a return type encoded.  */    len = d_number (di);
1314        if (peek == 'c' && peek_char_next (dm) == 'v')    if (len <= 0)
1315          *suppress_return_type = 1;      return NULL;
1316      ret = d_identifier (di, len);
1317      di->last_name = ret;
1318      return ret;
1319    }
1320    
1321        RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args, NULL));  /* number ::= [n] <(non-negative decimal integer)>  */
     }  
   else if (peek == 'C' || peek == 'D')  
     {  
       /* Constructors never have a return type encoded.  */  
       if (peek == 'C')  
         *suppress_return_type = 1;  
1322    
1323        RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));  static long
1324    d_number (di)
1325         struct d_info *di;
1326    {
1327      int negative;
1328      char peek;
1329      long ret;
1330    
1331      negative = 0;
1332      peek = d_peek_char (di);
1333      if (peek == 'n')
1334        {
1335          negative = 1;
1336          d_advance (di, 1);
1337          peek = d_peek_char (di);
1338      }      }
   else  
     return "Unexpected character in <unqualified-name>.";  
1339    
1340    return STATUS_OK;    ret = 0;
1341      while (1)
1342        {
1343          if (! IS_DIGIT (peek))
1344            {
1345              if (negative)
1346                ret = - ret;
1347              return ret;
1348            }
1349          ret = ret * 10 + peek - '0';
1350          d_advance (di, 1);
1351          peek = d_peek_char (di);
1352        }
1353  }  }
1354    
1355  /* Demangles and emits <source-name>.    /* identifier ::= <(unqualified source code identifier)>  */
1356    
1357      <source-name> ::= <length number> <identifier>  */  static struct demangle_component *
1358    d_identifier (di, len)
1359  static status_t       struct d_info *di;
1360  demangle_source_name (dm)       int len;
      demangling_t dm;  
1361  {  {
1362    int length;    const char *name;
1363    
1364    DEMANGLE_TRACE ("source-name", dm);    name = d_str (di);
1365    
1366    /* Decode the length of the identifier.  */    if (di->send - name < len)
1367    RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0));      return NULL;
   if (length == 0)  
     return "Zero length in <source-name>.";  
1368    
1369    /* Now the identifier itself.  It's placed into last_source_name,    d_advance (di, len);
      where it can be used to build a constructor or destructor name.  */  
   RETURN_IF_ERROR (demangle_identifier (dm, length,  
                                         dm->last_source_name));  
1370    
1371    /* Emit it.  */    /* A Java mangled name may have a trailing '$' if it is a C++
1372    RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));       keyword.  This '$' is not included in the length count.  We just
1373         ignore the '$'.  */
1374      if ((di->options & DMGL_JAVA) != 0
1375          && d_peek_char (di) == '$')
1376        d_advance (di, 1);
1377    
1378      /* Look for something which looks like a gcc encoding of an
1379         anonymous namespace, and replace it with a more user friendly
1380         name.  */
1381      if (len >= (int) ANONYMOUS_NAMESPACE_PREFIX_LEN + 2
1382          && memcmp (name, ANONYMOUS_NAMESPACE_PREFIX,
1383                     ANONYMOUS_NAMESPACE_PREFIX_LEN) == 0)
1384        {
1385          const char *s;
1386    
1387          s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN;
1388          if ((*s == '.' || *s == '_' || *s == '$')
1389              && s[1] == 'N')
1390            {
1391              di->expansion -= len - sizeof "(anonymous namespace)";
1392              return d_make_name (di, "(anonymous namespace)",
1393                                  sizeof "(anonymous namespace)" - 1);
1394            }
1395        }
1396    
1397    return STATUS_OK;    return d_make_name (di, name, len);
1398  }  }
1399    
1400  /* Demangles a number, either a <number> or a <positive-number> at the  /* operator_name ::= many different two character encodings.
1401     current position, consuming all consecutive digit characters.  Sets                   ::= cv <type>
1402     *VALUE to the resulting numberand returns STATUS_OK.  The number is                   ::= v <digit> <source-name>
1403     interpreted as BASE, which must be either 10 or 36.  If IS_SIGNED  */
    is non-zero, negative numbers -- prefixed with `n' -- are accepted.  
   
     <number> ::= [n] <positive-number>  
1404    
1405      <positive-number> ::= <decimal integer>  */  #define NL(s) s, (sizeof s) - 1
1406    
1407  static status_t  CP_STATIC_IF_GLIBCPP_V3
1408  demangle_number (dm, value, base, is_signed)  const struct demangle_operator_info cplus_demangle_operators[] =
      demangling_t dm;  
      int *value;  
      int base;  
      int is_signed;  
1409  {  {
1410    dyn_string_t number = dyn_string_new (10);    { "aN", NL ("&="),        2 },
1411      { "aS", NL ("="),         2 },
1412      { "aa", NL ("&&"),        2 },
1413      { "ad", NL ("&"),         1 },
1414      { "an", NL ("&"),         2 },
1415      { "cl", NL ("()"),        0 },
1416      { "cm", NL (","),         2 },
1417      { "co", NL ("~"),         1 },
1418      { "dV", NL ("/="),        2 },
1419      { "da", NL ("delete[]"),  1 },
1420      { "de", NL ("*"),         1 },
1421      { "dl", NL ("delete"),    1 },
1422      { "dv", NL ("/"),         2 },
1423      { "eO", NL ("^="),        2 },
1424      { "eo", NL ("^"),         2 },
1425      { "eq", NL ("=="),        2 },
1426      { "ge", NL (">="),        2 },
1427      { "gt", NL (">"),         2 },
1428      { "ix", NL ("[]"),        2 },
1429      { "lS", NL ("<<="),       2 },
1430      { "le", NL ("<="),        2 },
1431      { "ls", NL ("<<"),        2 },
1432      { "lt", NL ("<"),         2 },
1433      { "mI", NL ("-="),        2 },
1434      { "mL", NL ("*="),        2 },
1435      { "mi", NL ("-"),         2 },
1436      { "ml", NL ("*"),         2 },
1437      { "mm", NL ("--"),        1 },
1438      { "na", NL ("new[]"),     1 },
1439      { "ne", NL ("!="),        2 },
1440      { "ng", NL ("-"),         1 },
1441      { "nt", NL ("!"),         1 },
1442      { "nw", NL ("new"),       1 },
1443      { "oR", NL ("|="),        2 },
1444      { "oo", NL ("||"),        2 },
1445      { "or", NL ("|"),         2 },
1446      { "pL", NL ("+="),        2 },
1447      { "pl", NL ("+"),         2 },
1448      { "pm", NL ("->*"),       2 },
1449      { "pp", NL ("++"),        1 },
1450      { "ps", NL ("+"),         1 },
1451      { "pt", NL ("->"),        2 },
1452      { "qu", NL ("?"),         3 },
1453      { "rM", NL ("%="),        2 },
1454      { "rS", NL (">>="),       2 },
1455      { "rm", NL ("%"),         2 },
1456      { "rs", NL (">>"),        2 },
1457      { "st", NL ("sizeof "),   1 },
1458      { "sz", NL ("sizeof "),   1 },
1459      { NULL, NULL, 0,          0 }
1460    };
1461    
1462    static struct demangle_component *
1463    d_operator_name (di)
1464         struct d_info *di;
1465    {
1466      char c1;
1467      char c2;
1468    
1469      c1 = d_next_char (di);
1470      c2 = d_next_char (di);
1471      if (c1 == 'v' && IS_DIGIT (c2))
1472        return d_make_extended_operator (di, c2 - '0', d_source_name (di));
1473      else if (c1 == 'c' && c2 == 'v')
1474        return d_make_comp (di, DEMANGLE_COMPONENT_CAST,
1475                            cplus_demangle_type (di), NULL);
1476      else
1477        {
1478          /* LOW is the inclusive lower bound.  */
1479          int low = 0;
1480          /* HIGH is the exclusive upper bound.  We subtract one to ignore
1481             the sentinel at the end of the array.  */
1482          int high = ((sizeof (cplus_demangle_operators)
1483                       / sizeof (cplus_demangle_operators[0]))
1484                      - 1);
1485    
1486    DEMANGLE_TRACE ("number", dm);        while (1)
1487            {
1488              int i;
1489              const struct demangle_operator_info *p;
1490    
1491    if (number == NULL)            i = low + (high - low) / 2;
1492      return STATUS_ALLOCATION_FAILED;            p = cplus_demangle_operators + i;
1493    
1494    demangle_number_literally (dm, number, base, is_signed);            if (c1 == p->code[0] && c2 == p->code[1])
1495    *value = strtol (dyn_string_buf (number), NULL, base);              return d_make_operator (di, p);
   dyn_string_delete (number);  
1496    
1497    return STATUS_OK;            if (c1 < p->code[0] || (c1 == p->code[0] && c2 < p->code[1]))
1498                high = i;
1499              else
1500                low = i + 1;
1501              if (low == high)
1502                return NULL;
1503            }
1504        }
1505  }  }
1506    
1507  /* Demangles a number at the current position.  The digits (and minus  /* <special-name> ::= TV <type>
1508     sign, if present) that make up the number are appended to STR.                    ::= TT <type>
1509     Only base-BASE digits are accepted; BASE must be either 10 or 36.                    ::= TI <type>
1510     If IS_SIGNED, negative numbers -- prefixed with `n' -- are                    ::= TS <type>
1511     accepted.  Does not consume a trailing underscore or other                    ::= GV <(object) name>
1512     terminating character.  */                    ::= T <call-offset> <(base) encoding>
1513                      ::= Tc <call-offset> <call-offset> <(base) encoding>
1514       Also g++ extensions:
1515                      ::= TC <type> <(offset) number> _ <(base) type>
1516                      ::= TF <type>
1517                      ::= TJ <type>
1518                      ::= GR <name>
1519    */
1520    
1521  static status_t  static struct demangle_component *
1522  demangle_number_literally (dm, str, base, is_signed)  d_special_name (di)
1523       demangling_t dm;       struct d_info *di;
      dyn_string_t str;  
      int base;  
      int is_signed;  
1524  {  {
1525    DEMANGLE_TRACE ("number*", dm);    char c;
   
   if (base != 10 && base != 36)  
     return STATUS_INTERNAL_ERROR;  
1526    
1527    /* An `n' denotes a negative number.  */    di->expansion += 20;
1528    if (is_signed && peek_char (dm) == 'n')    c = d_next_char (di);
1529      if (c == 'T')
1530      {      {
1531        /* Skip past the n.  */        switch (d_next_char (di))
1532        advance_char (dm);          {
1533        /* The normal way to write a negative number is with a minus          case 'V':
1534           sign.  */            di->expansion -= 5;
1535        if (!dyn_string_append_char (str, '-'))            return d_make_comp (di, DEMANGLE_COMPONENT_VTABLE,
1536          return STATUS_ALLOCATION_FAILED;                                cplus_demangle_type (di), NULL);
1537      }          case 'T':
1538              di->expansion -= 10;
1539              return d_make_comp (di, DEMANGLE_COMPONENT_VTT,
1540                                  cplus_demangle_type (di), NULL);
1541            case 'I':
1542              return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO,
1543                                  cplus_demangle_type (di), NULL);
1544            case 'S':
1545              return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_NAME,
1546                                  cplus_demangle_type (di), NULL);
1547    
1548    /* Loop until we hit a non-digit.  */          case 'h':
1549    while (1)            if (! d_call_offset (di, 'h'))
1550      {              return NULL;
1551        char peek = peek_char (dm);            return d_make_comp (di, DEMANGLE_COMPONENT_THUNK,
1552        if (IS_DIGIT ((unsigned char) peek)                                d_encoding (di, 0), NULL);
1553            || (base == 36 && peek >= 'A' && peek <= 'Z'))  
1554          {          case 'v':
1555            /* Accumulate digits.  */            if (! d_call_offset (di, 'v'))
1556            if (!dyn_string_append_char (str, next_char (dm)))              return NULL;
1557              return STATUS_ALLOCATION_FAILED;            return d_make_comp (di, DEMANGLE_COMPONENT_VIRTUAL_THUNK,
1558                                  d_encoding (di, 0), NULL);
1559    
1560            case 'c':
1561              if (! d_call_offset (di, '\0'))
1562                return NULL;
1563              if (! d_call_offset (di, '\0'))
1564                return NULL;
1565              return d_make_comp (di, DEMANGLE_COMPONENT_COVARIANT_THUNK,
1566                                  d_encoding (di, 0), NULL);
1567    
1568            case 'C':
1569              {
1570                struct demangle_component *derived_type;
1571                long offset;
1572                struct demangle_component *base_type;
1573    
1574                derived_type = cplus_demangle_type (di);
1575                offset = d_number (di);
1576                if (offset < 0)
1577                  return NULL;
1578                if (d_next_char (di) != '_')
1579                  return NULL;
1580                base_type = cplus_demangle_type (di);
1581                /* We don't display the offset.  FIXME: We should display
1582                   it in verbose mode.  */
1583                di->expansion += 5;
1584                return d_make_comp (di, DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE,
1585                                    base_type, derived_type);
1586              }
1587    
1588            case 'F':
1589              return d_make_comp (di, DEMANGLE_COMPONENT_TYPEINFO_FN,
1590                                  cplus_demangle_type (di), NULL);
1591            case 'J':
1592              return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS,
1593                                  cplus_demangle_type (di), NULL);
1594    
1595            default:
1596              return NULL;
1597          }          }
       else  
         /* Not a digit?  All done.  */  
         break;  
1598      }      }
1599      else if (c == 'G')
1600        {
1601          switch (d_next_char (di))
1602            {
1603            case 'V':
1604              return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL);
1605    
1606            case 'R':
1607              return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, d_name (di),
1608                                  NULL);
1609    
1610    return STATUS_OK;          default:
1611              return NULL;
1612            }
1613        }
1614      else
1615        return NULL;
1616  }  }
1617    
1618  /* Demangles an identifier at the current position of LENGTH  /* <call-offset> ::= h <nv-offset> _
1619     characters and places it in IDENTIFIER.  */                   ::= v <v-offset> _
1620    
1621  static status_t     <nv-offset> ::= <(offset) number>
 demangle_identifier (dm, length, identifier)  
      demangling_t dm;  
      int length;  
      dyn_string_t identifier;  
 {  
   DEMANGLE_TRACE ("identifier", dm);  
   
   dyn_string_clear (identifier);  
   if (!dyn_string_resize (identifier, length))  
     return STATUS_ALLOCATION_FAILED;  
   
   while (length-- > 0)  
     {  
       int ch;  
       if (end_of_name_p (dm))  
         return "Unexpected end of name in <identifier>.";  
       ch = next_char (dm);  
   
       /* Handle extended Unicode characters.  We encode them as __U{hex}_,  
          where {hex} omits leading 0's.  For instance, '$' is encoded as  
          "__U24_".  */  
       if (ch == '_'  
           && peek_char (dm) == '_'  
           && peek_char_next (dm) == 'U')  
         {  
           char buf[10];  
           int pos = 0;  
           advance_char (dm); advance_char (dm); length -= 2;  
           while (length-- > 0)  
             {  
               ch = next_char (dm);  
               if (!isxdigit (ch))  
                 break;  
               buf[pos++] = ch;  
             }  
           if (ch != '_' || length < 0)  
             return STATUS_ERROR;  
           if (pos == 0)  
             {  
               /* __U_ just means __U.  */  
               if (!dyn_string_append_cstr (identifier, "__U"))  
                 return STATUS_ALLOCATION_FAILED;  
               continue;  
             }  
           else  
             {  
               buf[pos] = '\0';  
               ch = strtol (buf, 0, 16);  
             }  
         }  
1622    
1623        if (!dyn_string_append_char (identifier, ch))     <v-offset> ::= <(offset) number> _ <(virtual offset) number>
1624          return STATUS_ALLOCATION_FAILED;  
1625      }     The C parameter, if not '\0', is a character we just read which is
1626       the start of the <call-offset>.
1627    
1628    /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'     We don't display the offset information anywhere.  FIXME: We should
1629       followed by the source file name and some random characters.     display it in verbose mode.  */
1630       Unless we're in strict mode, decipher these names appropriately.  */  
1631    if (!flag_strict)  static int
1632      {  d_call_offset (di, c)
1633        char *name = dyn_string_buf (identifier);       struct d_info *di;
1634        int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);       int c;
   
       /* 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;  
 }  
   
 /* Demangles and emits an <operator-name>.  If SHORT_NAME is non-zero,  
    the short form is emitted; otherwise the full source form  
    (`operator +' etc.) is emitted.  *NUM_ARGS is set to the number of  
    operands that the operator takes.  If TYPE_ARG is non-NULL,  
    *TYPE_ARG is set to 1 if the first argument is a type and 0  
    otherwise.  
   
     <operator-name>  
                   ::= nw        # new            
                   ::= na        # new[]  
                   ::= dl        # delete          
                   ::= da        # delete[]        
                   ::= ps        # + (unary)  
                   ::= ng        # - (unary)      
                   ::= ad        # & (unary)      
                   ::= de        # * (unary)      
                   ::= co        # ~              
                   ::= pl        # +              
                   ::= mi        # -              
                   ::= ml        # *              
                   ::= dv        # /              
                   ::= rm        # %              
                   ::= an        # &              
                   ::= or        # |              
                   ::= eo        # ^              
                   ::= aS        # =              
                   ::= pL        # +=              
                   ::= mI        # -=              
                   ::= mL        # *=              
                   ::= dV        # /=              
                   ::= rM        # %=              
                   ::= aN        # &=              
                   ::= oR        # |=              
                   ::= eO        # ^=              
                   ::= ls        # <<              
                   ::= rs        # >>              
                   ::= lS        # <<=            
                   ::= rS        # >>=            
                   ::= eq        # ==              
                   ::= ne        # !=              
                   ::= lt        # <              
                   ::= gt        # >              
                   ::= le        # <=              
                   ::= ge        # >=              
                   ::= nt        # !              
                   ::= aa        # &&              
                   ::= oo        # ||              
                   ::= pp        # ++              
                   ::= mm        # --              
                   ::= cm        # ,              
                   ::= pm        # ->*            
                   ::= pt        # ->              
                   ::= cl        # ()              
                   ::= ix        # []              
                   ::= qu        # ?  
                   ::= st        # sizeof (a type)  
                   ::= sz        # sizeof (an expression)  
                   ::= cv <type> # cast          
                   ::= v [0-9] <source-name>  # vendor extended operator  */  
   
 static status_t  
 demangle_operator_name (dm, short_name, num_args, type_arg)  
      demangling_t dm;  
      int short_name;  
      int *num_args;  
      int *type_arg;  
1635  {  {
1636    struct operator_code    if (c == '\0')
1637    {      c = d_next_char (di);
     /* The mangled code for this operator.  */  
     const char *const code;  
     /* The source name of this operator.  */  
     const char *const name;  
     /* The number of arguments this operator takes.  */  
     const int num_args;  
   };  
1638    
1639    static const struct operator_code operators[] =    if (c == 'h')
1640    {      d_number (di);
1641      { "aN", "&="       , 2 },    else if (c == 'v')
1642      { "aS", "="        , 2 },      {
1643      { "aa", "&&"       , 2 },        d_number (di);
1644      { "ad", "&"        , 1 },        if (d_next_char (di) != '_')
1645      { "an", "&"        , 2 },          return 0;
1646      { "cl", "()"       , 0 },        d_number (di);
     { "cm", ","        , 2 },  
     { "co", "~"        , 1 },  
     { "dV", "/="       , 2 },  
     { "da", " delete[]", 1 },  
     { "de", "*"        , 1 },  
     { "dl", " delete"  , 1 },  
     { "dv", "/"        , 2 },  
     { "eO", "^="       , 2 },  
     { "eo", "^"        , 2 },  
     { "eq", "=="       , 2 },  
     { "ge", ">="       , 2 },  
     { "gt", ">"        , 2 },  
     { "ix", "[]"       , 2 },  
     { "lS", "<<="      , 2 },  
     { "le", "<="       , 2 },  
     { "ls", "<<"       , 2 },  
     { "lt", "<"        , 2 },  
     { "mI", "-="       , 2 },  
     { "mL", "*="       , 2 },  
     { "mi", "-"        , 2 },  
     { "ml", "*"        , 2 },  
     { "mm", "--"       , 1 },  
     { "na", " new[]"   , 1 },  
     { "ne", "!="       , 2 },  
     { "ng", "-"        , 1 },  
     { "nt", "!"        , 1 },  
     { "nw", " new"     , 1 },  
     { "oR", "|="       , 2 },  
     { "oo", "||"       , 2 },  
     { "or", "|"        , 2 },  
     { "pL", "+="       , 2 },  
     { "pl", "+"        , 2 },  
     { "pm", "->*"      , 2 },  
     { "pp", "++"       , 1 },  
     { "ps", "+"        , 1 },  
     { "pt", "->"       , 2 },  
     { "qu", "?"        , 3 },  
     { "rM", "%="       , 2 },  
     { "rS", ">>="      , 2 },  
     { "rm", "%"        , 2 },  
     { "rs", ">>"       , 2 },  
     { "sz", " sizeof"  , 1 }  
   };  
   
   const int num_operators =  
     sizeof (operators) / sizeof (struct operator_code);  
   
   int c0 = next_char (dm);  
   int c1 = next_char (dm);  
   const struct operator_code* p1 = operators;  
   const struct operator_code* p2 = operators + num_operators;  
   
   DEMANGLE_TRACE ("operator-name", dm);  
   
   /* Assume the first argument is not a type.  */  
   if (type_arg)  
     *type_arg = 0;  
   
   /* Is this a vendor-extended operator?  */  
   if (c0 == 'v' && IS_DIGIT (c1))  
     {  
       RETURN_IF_ERROR (result_add (dm, "operator "));  
       RETURN_IF_ERROR (demangle_source_name (dm));  
       *num_args = 0;  
       return STATUS_OK;  
     }  
   
   /* Is this a conversion operator?  */  
   if (c0 == 'c' && c1 == 'v')  
     {  
       RETURN_IF_ERROR (result_add (dm, "operator "));  
       /* Demangle the converted-to type.  */  
       RETURN_IF_ERROR (demangle_type (dm));  
       *num_args = 0;  
       return STATUS_OK;  
     }  
   
   /* Is it the sizeof variant that takes a type?  */  
   if (c0 == 's' && c1 == 't')  
     {  
       RETURN_IF_ERROR (result_add (dm, " sizeof"));  
       *num_args = 1;  
       if (type_arg)  
         *type_arg = 1;  
       return STATUS_OK;  
1647      }      }
1648      else
1649        return 0;
1650    
1651    /* Perform a binary search for the operator code.  */    if (d_next_char (di) != '_')
1652    while (1)      return 0;
1653    
1654      return 1;
1655    }
1656    
1657    /* <ctor-dtor-name> ::= C1
1658                        ::= C2
1659                        ::= C3
1660                        ::= D0
1661                        ::= D1
1662                        ::= D2
1663    */
1664    
1665    static struct demangle_component *
1666    d_ctor_dtor_name (di)
1667         struct d_info *di;
1668    {
1669      if (di->last_name != NULL)
1670        {
1671          if (di->last_name->type == DEMANGLE_COMPONENT_NAME)
1672            di->expansion += di->last_name->u.s_name.len;
1673          else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD)
1674            di->expansion += di->last_name->u.s_string.len;
1675        }
1676      switch (d_next_char (di))
1677      {      {
1678        const struct operator_code* p = p1 + (p2 - p1) / 2;      case 'C':
1679        char match0 = p->code[0];        {
1680        char match1 = p->code[1];          enum gnu_v3_ctor_kinds kind;
1681    
1682        if (c0 == match0 && c1 == match1)          switch (d_next_char (di))
1683          /* Found it.  */            {
1684          {            case '1':
1685            if (!short_name)              kind = gnu_v3_complete_object_ctor;
1686              RETURN_IF_ERROR (result_add (dm, "operator"));              break;
1687            RETURN_IF_ERROR (result_add (dm, p->name));            case '2':
1688            *num_args = p->num_args;              kind = gnu_v3_base_object_ctor;
1689                break;
1690              case '3':
1691                kind = gnu_v3_complete_object_allocating_ctor;
1692                break;
1693              default:
1694                return NULL;
1695              }
1696            return d_make_ctor (di, kind, di->last_name);
1697          }
1698    
1699            return STATUS_OK;      case 'D':
1700          }        {
1701            enum gnu_v3_dtor_kinds kind;
1702    
1703        if (p == p1)          switch (d_next_char (di))
1704          /* Couldn't find it.  */            {
1705          return "Unknown code in <operator-name>.";            case '0':
1706                kind = gnu_v3_deleting_dtor;
1707                break;
1708              case '1':
1709                kind = gnu_v3_complete_object_dtor;
1710                break;
1711              case '2':
1712                kind = gnu_v3_base_object_dtor;
1713                break;
1714              default:
1715                return NULL;
1716              }
1717            return d_make_dtor (di, kind, di->last_name);
1718          }
1719    
1720        /* Try again.  */      default:
1721        if (c0 < match0 || (c0 == match0 && c1 < match1))        return NULL;
         p2 = p;  
       else  
         p1 = p;  
1722      }      }
1723  }  }
1724    
1725  /* Demangles and omits an <nv-offset>.  /* <type> ::= <builtin-type>
1726              ::= <function-type>
1727              ::= <class-enum-type>
1728              ::= <array-type>
1729              ::= <pointer-to-member-type>
1730              ::= <template-param>
1731              ::= <template-template-param> <template-args>
1732              ::= <substitution>
1733              ::= <CV-qualifiers> <type>
1734              ::= P <type>
1735              ::= R <type>
1736              ::= C <type>
1737              ::= G <type>
1738              ::= U <source-name> <type>
1739    
1740      <nv-offset> ::= <offset number>   # non-virtual base override  */     <builtin-type> ::= various one letter codes
1741                      ::= u <source-name>
1742    */
1743    
1744  static status_t  CP_STATIC_IF_GLIBCPP_V3
1745  demangle_nv_offset (dm)  const struct demangle_builtin_type_info
1746       demangling_t dm;  cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
1747  {  {
1748    dyn_string_t number;    /* a */ { NL ("signed char"), NL ("signed char"),     D_PRINT_DEFAULT },
1749    status_t status = STATUS_OK;    /* b */ { NL ("bool"),        NL ("boolean"),         D_PRINT_BOOL },
1750      /* c */ { NL ("char"),        NL ("byte"),            D_PRINT_DEFAULT },
1751      /* d */ { NL ("double"),      NL ("double"),          D_PRINT_FLOAT },
1752      /* e */ { NL ("long double"), NL ("long double"),     D_PRINT_FLOAT },
1753      /* f */ { NL ("float"),       NL ("float"),           D_PRINT_FLOAT },
1754      /* g */ { NL ("__float128"),  NL ("__float128"),      D_PRINT_FLOAT },
1755      /* h */ { NL ("unsigned char"), NL ("unsigned char"), D_PRINT_DEFAULT },
1756      /* i */ { NL ("int"),         NL ("int"),             D_PRINT_INT },
1757      /* j */ { NL ("unsigned int"), NL ("unsigned"),       D_PRINT_UNSIGNED },
1758      /* k */ { NULL, 0,            NULL, 0,                D_PRINT_DEFAULT },
1759      /* l */ { NL ("long"),        NL ("long"),            D_PRINT_LONG },
1760      /* m */ { NL ("unsigned long"), NL ("unsigned long"), D_PRINT_UNSIGNED_LONG },
1761      /* n */ { NL ("__int128"),    NL ("__int128"),        D_PRINT_DEFAULT },
1762      /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"),
1763                D_PRINT_DEFAULT },
1764      /* p */ { NULL, 0,            NULL, 0,                D_PRINT_DEFAULT },
1765      /* q */ { NULL, 0,            NULL, 0,                D_PRINT_DEFAULT },
1766      /* r */ { NULL, 0,            NULL, 0,                D_PRINT_DEFAULT },
1767      /* s */ { NL ("short"),       NL ("short"),           D_PRINT_DEFAULT },
1768      /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_DEFAULT },
1769      /* u */ { NULL, 0,            NULL, 0,                D_PRINT_DEFAULT },
1770      /* v */ { NL ("void"),        NL ("void"),            D_PRINT_VOID },
1771      /* w */ { NL ("wchar_t"),     NL ("char"),            D_PRINT_DEFAULT },
1772      /* x */ { NL ("long long"),   NL ("long"),            D_PRINT_LONG_LONG },
1773      /* y */ { NL ("unsigned long long"), NL ("unsigned long long"),
1774                D_PRINT_UNSIGNED_LONG_LONG },
1775      /* z */ { NL ("..."),         NL ("..."),             D_PRINT_DEFAULT },
1776    };
1777    
1778    DEMANGLE_TRACE ("h-offset", dm);  CP_STATIC_IF_GLIBCPP_V3
1779    struct demangle_component *
1780    cplus_demangle_type (di)
1781         struct d_info *di;
1782    {
1783      char peek;
1784      struct demangle_component *ret;
1785      int can_subst;
1786    
1787    /* Demangle the offset.  */    /* The ABI specifies that when CV-qualifiers are used, the base type
1788    number = dyn_string_new (4);       is substitutable, and the fully qualified type is substitutable,
1789    if (number == NULL)       but the base type with a strict subset of the CV-qualifiers is
1790      return STATUS_ALLOCATION_FAILED;       not substitutable.  The natural recursive implementation of the
1791    demangle_number_literally (dm, number, 10, 1);       CV-qualifiers would cause subsets to be substitutable, so instead
1792         we pull them all off now.
1793    
1794         FIXME: The ABI says that order-insensitive vendor qualifiers
1795         should be handled in the same way, but we have no way to tell
1796         which vendor qualifiers are order-insensitive and which are
1797         order-sensitive.  So we just assume that they are all
1798         order-sensitive.  g++ 3.4 supports only one vendor qualifier,
1799         __vector, and it treats it as order-sensitive when mangling
1800         names.  */
1801    
1802    /* Don't display the offset unless in verbose mode.  */    peek = d_peek_char (di);
1803    if (flag_verbose)    if (peek == 'r' || peek == 'V' || peek == 'K')
1804      {      {
1805        status = result_add (dm, " [nv:");        struct demangle_component **pret;
1806        if (STATUS_NO_ERROR (status))  
1807          status = result_add_string (dm, number);        pret = d_cv_qualifiers (di, &ret, 0);
1808        if (STATUS_NO_ERROR (status))        if (pret == NULL)
1809          status = result_add_char (dm, ']');          return NULL;
1810          *pret = cplus_demangle_type (di);
1811          if (! d_add_substitution (di, ret))
1812            return NULL;
1813          return ret;
1814      }      }
1815    
1816    /* Clean up.  */    can_subst = 1;
   dyn_string_delete (number);  
   RETURN_IF_ERROR (status);  
   return STATUS_OK;  
 }  
1817    
1818  /* Demangles and emits a <v-offset>.    switch (peek)
1819        {
1820        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
1821        case 'h': case 'i': case 'j':           case 'l': case 'm': case 'n':
1822        case 'o':                               case 's': case 't':
1823        case 'v': case 'w': case 'x': case 'y': case 'z':
1824          ret = d_make_builtin_type (di,
1825                                     &cplus_demangle_builtin_types[peek - 'a']);
1826          di->expansion += ret->u.s_builtin.type->len;
1827          can_subst = 0;
1828          d_advance (di, 1);
1829          break;
1830    
1831      <v-offset>  ::= <offset number> _ <virtual offset number>      case 'u':
1832                          # virtual base override, with vcall offset  */        d_advance (di, 1);
1833          ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE,
1834                             d_source_name (di), NULL);
1835          break;
1836    
1837  static status_t      case 'F':
1838  demangle_v_offset (dm)        ret = d_function_type (di);
1839       demangling_t dm;        break;
 {  
   dyn_string_t number;  
   status_t status = STATUS_OK;  
1840    
1841    DEMANGLE_TRACE ("v-offset", dm);      case '0': case '1': case '2': case '3': case '4':
1842        case '5': case '6': case '7': case '8': case '9':
1843        case 'N':
1844        case 'Z':
1845          ret = d_class_enum_type (di);
1846          break;
1847    
1848    /* Demangle the offset.  */      case 'A':
1849    number = dyn_string_new (4);        ret = d_array_type (di);
1850    if (number == NULL)        break;
     return STATUS_ALLOCATION_FAILED;  
   demangle_number_literally (dm, number, 10, 1);  
1851    
1852    /* Don't display the offset unless in verbose mode.  */      case 'M':
1853    if (flag_verbose)        ret = d_pointer_to_member_type (di);
1854      {        break;
       status = result_add (dm, " [v:");  
       if (STATUS_NO_ERROR (status))  
         status = result_add_string (dm, number);  
       if (STATUS_NO_ERROR (status))  
         result_add_char (dm, ',');  
     }  
   dyn_string_delete (number);  
   RETURN_IF_ERROR (status);  
1855    
1856    /* Demangle the separator.  */      case 'T':
1857    RETURN_IF_ERROR (demangle_char (dm, '_'));        ret = d_template_param (di);
1858          if (d_peek_char (di) == 'I')
1859            {
1860              /* This is <template-template-param> <template-args>.  The
1861                 <template-template-param> part is a substitution
1862                 candidate.  */
1863              if (! d_add_substitution (di, ret))
1864                return NULL;
1865              ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
1866                                 d_template_args (di));
1867            }
1868          break;
1869    
1870    /* Demangle the vcall offset.  */      case 'S':
1871    number = dyn_string_new (4);        /* If this is a special substitution, then it is the start of
1872    if (number == NULL)           <class-enum-type>.  */
1873      return STATUS_ALLOCATION_FAILED;        {
1874    demangle_number_literally (dm, number, 10, 1);          char peek_next;
1875    
1876    /* Don't display the vcall offset unless in verbose mode.  */          peek_next = d_peek_next_char (di);
1877    if (flag_verbose)          if (IS_DIGIT (peek_next)
1878                || peek_next == '_'
1879                || IS_UPPER (peek_next))
1880              {
1881                ret = d_substitution (di, 0);
1882                /* The substituted name may have been a template name and
1883                   may be followed by tepmlate args.  */
1884                if (d_peek_char (di) == 'I')
1885                  ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
1886                                     d_template_args (di));
1887                else
1888                  can_subst = 0;
1889              }
1890            else
1891              {
1892                ret = d_class_enum_type (di);
1893                /* If the substitution was a complete type, then it is not
1894                   a new substitution candidate.  However, if the
1895                   substitution was followed by template arguments, then
1896                   the whole thing is a substitution candidate.  */
1897                if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD)
1898                  can_subst = 0;
1899              }
1900          }
1901          break;
1902    
1903        case 'P':
1904          d_advance (di, 1);
1905          ret = d_make_comp (di, DEMANGLE_COMPONENT_POINTER,
1906                             cplus_demangle_type (di), NULL);
1907          break;
1908    
1909        case 'R':
1910          d_advance (di, 1);
1911          ret = d_make_comp (di, DEMANGLE_COMPONENT_REFERENCE,
1912                             cplus_demangle_type (di), NULL);
1913          break;
1914    
1915        case 'C':
1916          d_advance (di, 1);
1917          ret = d_make_comp (di, DEMANGLE_COMPONENT_COMPLEX,
1918                             cplus_demangle_type (di), NULL);
1919          break;
1920    
1921        case 'G':
1922          d_advance (di, 1);
1923          ret = d_make_comp (di, DEMANGLE_COMPONENT_IMAGINARY,
1924                             cplus_demangle_type (di), NULL);
1925          break;
1926    
1927        case 'U':
1928          d_advance (di, 1);
1929          ret = d_source_name (di);
1930          ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
1931                             cplus_demangle_type (di), ret);
1932          break;
1933    
1934        default:
1935          return NULL;
1936        }
1937    
1938      if (can_subst)
1939      {      {
1940        status = result_add_string (dm, number);        if (! d_add_substitution (di, ret))
1941        if (STATUS_NO_ERROR (status))          return NULL;
         status = result_add_char (dm, ']');  
1942      }      }
   dyn_string_delete (number);  
   RETURN_IF_ERROR (status);  
1943    
1944    return STATUS_OK;    return ret;
1945  }  }
1946    
1947  /* Demangles and emits a <call-offset>.  /* <CV-qualifiers> ::= [r] [V] [K]  */
   
     <call-offset> ::= h <nv-offset> _  
                   ::= v <v-offset> _  */  
1948    
1949  static status_t  static struct demangle_component **
1950  demangle_call_offset (dm)  d_cv_qualifiers (di, pret, member_fn)
1951       demangling_t dm;       struct d_info *di;
1952         struct demangle_component **pret;
1953         int member_fn;
1954  {  {
1955    DEMANGLE_TRACE ("call-offset", dm);    char peek;
1956    
1957    switch (peek_char (dm))    peek = d_peek_char (di);
1958      while (peek == 'r' || peek == 'V' || peek == 'K')
1959      {      {
1960      case 'h':        enum demangle_component_type t;
       advance_char (dm);  
       /* Demangle the offset.  */  
       RETURN_IF_ERROR (demangle_nv_offset (dm));  
       /* Demangle the separator.  */  
       RETURN_IF_ERROR (demangle_char (dm, '_'));  
       break;  
1961    
1962      case 'v':        d_advance (di, 1);
1963        advance_char (dm);        if (peek == 'r')
1964        /* Demangle the offset.  */          {
1965        RETURN_IF_ERROR (demangle_v_offset (dm));            t = (member_fn
1966        /* Demangle the separator.  */                 ? DEMANGLE_COMPONENT_RESTRICT_THIS
1967        RETURN_IF_ERROR (demangle_char (dm, '_'));                 : DEMANGLE_COMPONENT_RESTRICT);
1968        break;            di->expansion += sizeof "restrict";
1969            }
1970          else if (peek == 'V')
1971            {
1972              t = (member_fn
1973                   ? DEMANGLE_COMPONENT_VOLATILE_THIS
1974                   : DEMANGLE_COMPONENT_VOLATILE);
1975              di->expansion += sizeof "volatile";
1976            }
1977          else
1978            {
1979              t = (member_fn
1980                   ? DEMANGLE_COMPONENT_CONST_THIS
1981                   : DEMANGLE_COMPONENT_CONST);
1982              di->expansion += sizeof "const";
1983            }
1984    
1985      default:        *pret = d_make_comp (di, t, NULL, NULL);
1986        return "Unrecognized <call-offset>.";        if (*pret == NULL)
1987            return NULL;
1988          pret = &d_left (*pret);
1989    
1990          peek = d_peek_char (di);
1991      }      }
1992    
1993    return STATUS_OK;    return pret;
1994    }
1995    
1996    /* <function-type> ::= F [Y] <bare-function-type> E  */
1997    
1998    static struct demangle_component *
1999    d_function_type (di)
2000         struct d_info *di;
2001    {
2002      struct demangle_component *ret;
2003    
2004      if (d_next_char (di) != 'F')
2005        return NULL;
2006      if (d_peek_char (di) == 'Y')
2007        {
2008          /* Function has C linkage.  We don't print this information.
2009             FIXME: We should print it in verbose mode.  */
2010          d_advance (di, 1);
2011        }
2012      ret = d_bare_function_type (di, 1);
2013      if (d_next_char (di) != 'E')
2014        return NULL;
2015      return ret;
2016  }  }
2017    
2018  /* Demangles and emits a <special-name>.    /* <bare-function-type> ::= <type>+  */
2019    
2020      <special-name> ::= GV <object name>   # Guard variable  static struct demangle_component *
2021                     ::= TV <type>          # virtual table  d_bare_function_type (di, has_return_type)
2022                     ::= TT <type>          # VTT       struct d_info *di;
2023                     ::= TI <type>          # typeinfo structure       int has_return_type;
2024                     ::= TS <type>          # typeinfo name    {
2025      struct demangle_component *return_type;
2026      struct demangle_component *tl;
2027      struct demangle_component **ptl;
2028    
2029     Other relevant productions include thunks:    return_type = NULL;
2030      tl = NULL;
2031      ptl = &tl;
2032      while (1)
2033        {
2034          char peek;
2035          struct demangle_component *type;
2036    
2037          peek = d_peek_char (di);
2038          if (peek == '\0' || peek == 'E')
2039            break;
2040          type = cplus_demangle_type (di);
2041          if (type == NULL)
2042            return NULL;
2043          if (has_return_type)
2044            {
2045              return_type = type;
2046              has_return_type = 0;
2047            }
2048          else
2049            {
2050              *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL);
2051              if (*ptl == NULL)
2052                return NULL;
2053              ptl = &d_right (*ptl);
2054            }
2055        }
2056    
2057      <special-name> ::= T <call-offset> <base encoding>    /* There should be at least one parameter type besides the optional
2058                           # base is the nominal target function of thunk       return type.  A function which takes no arguments will have a
2059         single parameter type void.  */
2060      if (tl == NULL)
2061        return NULL;
2062    
2063      <special-name> ::= Tc <call-offset> <call-offset> <base encoding>    /* If we have a single parameter type void, omit it.  */
2064                           # base is the nominal target function of thunk    if (d_right (tl) == NULL
2065                           # first call-offset is 'this' adjustment        && d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE
2066                           # second call-offset is result adjustment        && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID)
2067        {
2068          di->expansion -= d_left (tl)->u.s_builtin.type->len;
2069          tl = NULL;
2070        }
2071    
2072     where    return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl);
2073    }
2074    
2075      <call-offset>  ::= h <nv-offset> _  /* <class-enum-type> ::= <name>  */
                    ::= v <v-offset> _  
2076    
2077     Also demangles the special g++ manglings,  static struct demangle_component *
2078    d_class_enum_type (di)
2079         struct d_info *di;
2080    {
2081      return d_name (di);
2082    }
2083    
2084      <special-name> ::= TC <type> <offset number> _ <base type>  /* <array-type> ::= A <(positive dimension) number> _ <(element) type>
2085                                            # construction vtable                  ::= A [<(dimension) expression>] _ <(element) type>
2086                     ::= TF <type>          # typeinfo function (old ABI only)  */
                    ::= TJ <type>          # java Class structure  */  
2087    
2088  static status_t  static struct demangle_component *
2089  demangle_special_name (dm)  d_array_type (di)
2090       demangling_t dm;       struct d_info *di;
2091  {  {
2092    dyn_string_t number;    char peek;
2093    int unused;    struct demangle_component *dim;
   char peek = peek_char (dm);  
2094    
2095    DEMANGLE_TRACE ("special-name", dm);    if (d_next_char (di) != 'A')
2096        return NULL;
2097    
2098    if (peek == 'G')    peek = d_peek_char (di);
2099      if (peek == '_')
2100        dim = NULL;
2101      else if (IS_DIGIT (peek))
2102      {      {
2103        /* Consume the G.  */        const char *s;
       advance_char (dm);  
       switch (peek_char (dm))  
         {  
         case 'V':  
           /* A guard variable name.  */  
           advance_char (dm);  
           RETURN_IF_ERROR (result_add (dm, "guard variable for "));  
           RETURN_IF_ERROR (demangle_name (dm, &unused));  
           break;  
2104    
2105          case 'R':        s = d_str (di);
2106            /* A reference temporary.  */        do
2107            advance_char (dm);          {
2108            RETURN_IF_ERROR (result_add (dm, "reference temporary for "));            d_advance (di, 1);
2109            RETURN_IF_ERROR (demangle_name (dm, &unused));            peek = d_peek_char (di);
           break;  
             
         default:  
           return "Unrecognized <special-name>.";  
2110          }          }
2111          while (IS_DIGIT (peek));
2112          dim = d_make_name (di, s, d_str (di) - s);
2113          if (dim == NULL)
2114            return NULL;
2115      }      }
2116    else if (peek == 'T')    else
2117      {      {
2118        status_t status = STATUS_OK;        dim = d_expression (di);
2119          if (dim == NULL)
2120            return NULL;
2121        }
2122    
2123        /* Other C++ implementation miscellania.  Consume the T.  */    if (d_next_char (di) != '_')
2124        advance_char (dm);      return NULL;
2125    
2126        switch (peek_char (dm))    return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim,
2127          {                        cplus_demangle_type (di));
2128          case 'V':  }
           /* Virtual table.  */  
           advance_char (dm);  
           RETURN_IF_ERROR (result_add (dm, "vtable for "));  
           RETURN_IF_ERROR (demangle_type (dm));  
           break;  
2129    
2130          case 'T':  /* <pointer-to-member-type> ::= M <(class) type> <(member) type>  */
           /* VTT structure.  */  
           advance_char (dm);  
           RETURN_IF_ERROR (result_add (dm, "VTT for "));  
           RETURN_IF_ERROR (demangle_type (dm));  
           break;  
2131    
2132          case 'I':  static struct demangle_component *
2133            /* Typeinfo structure.  */  d_pointer_to_member_type (di)
2134            advance_char (dm);       struct d_info *di;
2135            RETURN_IF_ERROR (result_add (dm, "typeinfo for "));  {
2136            RETURN_IF_ERROR (demangle_type (dm));    struct demangle_component *cl;
2137            break;    struct demangle_component *mem;
2138      struct demangle_component **pmem;
2139    
2140          case 'F':    if (d_next_char (di) != 'M')
2141            /* Typeinfo function.  Used only in old ABI with new mangling.  */      return NULL;
           advance_char (dm);  
           RETURN_IF_ERROR (result_add (dm, "typeinfo fn for "));  
           RETURN_IF_ERROR (demangle_type (dm));  
           break;  
2142    
2143          case 'S':    cl = cplus_demangle_type (di);
           /* Character string containing type name, used in typeinfo. */  
           advance_char (dm);  
           RETURN_IF_ERROR (result_add (dm, "typeinfo name for "));  
           RETURN_IF_ERROR (demangle_type (dm));  
           break;  
2144    
2145          case 'J':    /* The ABI specifies that any type can be a substitution source, and
2146            /* The java Class variable corresponding to a C++ class.  */       that M is followed by two types, and that when a CV-qualified
2147            advance_char (dm);       type is seen both the base type and the CV-qualified types are
2148            RETURN_IF_ERROR (result_add (dm, "java Class for "));       substitution sources.  The ABI also specifies that for a pointer
2149            RETURN_IF_ERROR (demangle_type (dm));       to a CV-qualified member function, the qualifiers are attached to
2150            break;       the second type.  Given the grammar, a plain reading of the ABI
2151         suggests that both the CV-qualified member function and the
2152         non-qualified member function are substitution sources.  However,
2153         g++ does not work that way.  g++ treats only the CV-qualified
2154         member function as a substitution source.  FIXME.  So to work
2155         with g++, we need to pull off the CV-qualifiers here, in order to
2156         avoid calling add_substitution() in cplus_demangle_type().  */
2157    
2158          case 'h':    pmem = d_cv_qualifiers (di, &mem, 1);
2159            /* Non-virtual thunk.  */    if (pmem == NULL)
2160            advance_char (dm);      return NULL;
2161            RETURN_IF_ERROR (result_add (dm, "non-virtual thunk"));    *pmem = cplus_demangle_type (di);
           RETURN_IF_ERROR (demangle_nv_offset (dm));  
           /* Demangle the separator.  */  
           RETURN_IF_ERROR (demangle_char (dm, '_'));  
           /* Demangle and emit the target name and function type.  */  
           RETURN_IF_ERROR (result_add (dm, " to "));  
           RETURN_IF_ERROR (demangle_encoding (dm));  
           break;  
2162    
2163          case 'v':    return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
2164            /* Virtual thunk.  */  }
           advance_char (dm);  
           RETURN_IF_ERROR (result_add (dm, "virtual thunk"));  
           RETURN_IF_ERROR (demangle_v_offset (dm));  
           /* Demangle the separator.  */  
           RETURN_IF_ERROR (demangle_char (dm, '_'));  
           /* Demangle and emit the target function.  */  
           RETURN_IF_ERROR (result_add (dm, " to "));  
           RETURN_IF_ERROR (demangle_encoding (dm));  
           break;  
2165    
2166          case 'c':  /* <template-param> ::= T_
2167            /* Covariant return thunk.  */                      ::= T <(parameter-2 non-negative) number> _
2168            advance_char (dm);  */
           RETURN_IF_ERROR (result_add (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_add (dm, " to "));  
           RETURN_IF_ERROR (demangle_encoding (dm));  
           break;  
2169    
2170          case 'C':  static struct demangle_component *
2171            /* TC is a special g++ mangling for a construction vtable. */  d_template_param (di)
2172            if (!flag_strict)       struct d_info *di;
2173              {  {
2174                dyn_string_t derived_type;    long param;
2175    
2176                advance_char (dm);    if (d_next_char (di) != 'T')
2177                RETURN_IF_ERROR (result_add (dm, "construction vtable for "));      return NULL;
2178    
2179                /* Demangle the derived type off to the side.  */    if (d_peek_char (di) == '_')
2180                RETURN_IF_ERROR (result_push (dm));      param = 0;
2181                RETURN_IF_ERROR (demangle_type (dm));    else
2182                derived_type = (dyn_string_t) result_pop (dm);      {
2183          param = d_number (di);
2184                /* Demangle the offset.  */        if (param < 0)
2185                number = dyn_string_new (4);          return NULL;
2186                if (number == NULL)        param += 1;
2187                  {      }
                   dyn_string_delete (derived_type);  
                   return STATUS_ALLOCATION_FAILED;  
                 }  
               demangle_number_literally (dm, number, 10, 1);  
               /* Demangle the underscore separator.  */  
               status = demangle_char (dm, '_');  
   
               /* Demangle the base type.  */  
               if (STATUS_NO_ERROR (status))  
                 status = demangle_type (dm);  
   
               /* Emit the derived type.  */  
               if (STATUS_NO_ERROR (status))  
                 status = result_add (dm, "-in-");  
               if (STATUS_NO_ERROR (status))  
                 status = result_add_string (dm, derived_type);  
               dyn_string_delete (derived_type);  
2188    
2189                /* Don't display the offset unless in verbose mode.  */    if (d_next_char (di) != '_')
2190                if (flag_verbose)      return NULL;
                 {  
                   status = result_add_char (dm, ' ');  
                   if (STATUS_NO_ERROR (status))  
                     result_add_string (dm, number);  
                 }  
               dyn_string_delete (number);  
               RETURN_IF_ERROR (status);  
               break;  
             }  
           /* If flag_strict, fall through.  */  
2191    
2192          default:    ++di->did_subs;
           return "Unrecognized <special-name>.";  
         }  
     }  
   else  
     return STATUS_ERROR;  
2193    
2194    return STATUS_OK;    return d_make_template_param (di, param);
2195  }  }
2196    
2197  /* Demangles and emits a <ctor-dtor-name>.    /* <template-args> ::= I <template-arg>+ E  */
2198      
2199      <ctor-dtor-name>  static struct demangle_component *
2200                     ::= C1  # complete object (in-charge) ctor  d_template_args (di)
2201                     ::= C2  # base object (not-in-charge) ctor       struct d_info *di;
                    ::= C3  # complete object (in-charge) allocating ctor  
                    ::= D0  # deleting (in-charge) dtor  
                    ::= D1  # complete object (in-charge) dtor  
                    ::= D2  # base object (not-in-charge) dtor  */  
   
 static status_t  
 demangle_ctor_dtor_name (dm)  
      demangling_t dm;  
2202  {  {
2203    static const char *const ctor_flavors[] =    struct demangle_component *hold_last_name;
2204    {    struct demangle_component *al;
2205      "in-charge",    struct demangle_component **pal;
2206      "not-in-charge",  
2207      "allocating"    /* Preserve the last name we saw--don't let the template arguments
2208    };       clobber it, as that would give us the wrong name for a subsequent
2209    static const char *const dtor_flavors[] =       constructor or destructor.  */
2210    {    hold_last_name = di->last_name;
2211      "in-charge deleting",  
2212      "in-charge",    if (d_next_char (di) != 'I')
2213      "not-in-charge"      return NULL;
2214    };  
2215      al = NULL;
2216    int flavor;    pal = &al;
2217    char peek = peek_char (dm);    while (1)
2218        {
2219    DEMANGLE_TRACE ("ctor-dtor-name", dm);        struct demangle_component *a;
2220      
2221    if (peek == 'C')        a = d_template_arg (di);
2222      {        if (a == NULL)
2223        /* A constructor name.  Consume the C.  */          return NULL;
2224        advance_char (dm);  
2225        flavor = next_char (dm);        *pal = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, a, NULL);
2226        if (flavor < '1' || flavor > '3')        if (*pal == NULL)
2227          return "Unrecognized constructor.";          return NULL;
2228        RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));        pal = &d_right (*pal);
2229        switch (flavor)  
2230          {        if (d_peek_char (di) == 'E')
         case '1': dm->is_constructor = gnu_v3_complete_object_ctor;  
           break;  
         case '2': dm->is_constructor = gnu_v3_base_object_ctor;  
           break;  
         case '3': dm->is_constructor = gnu_v3_complete_object_allocating_ctor;  
           break;  
         }  
       /* Print the flavor of the constructor if in verbose mode.  */  
       if (flag_verbose)  
         {  
           RETURN_IF_ERROR (result_add (dm, "["));  
           RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor - '1']));  
           RETURN_IF_ERROR (result_add_char (dm, ']'));  
         }  
     }  
   else if (peek == 'D')  
     {  
       /* A destructor name.  Consume the D.  */  
       advance_char (dm);  
       flavor = next_char (dm);  
       if (flavor < '0' || flavor > '2')  
         return "Unrecognized destructor.";  
       RETURN_IF_ERROR (result_add_char (dm, '~'));  
       RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));  
       switch (flavor)  
2231          {          {
2232          case '0': dm->is_destructor = gnu_v3_deleting_dtor;            d_advance (di, 1);
           break;  
         case '1': dm->is_destructor = gnu_v3_complete_object_dtor;  
           break;  
         case '2': dm->is_destructor = gnu_v3_base_object_dtor;  
2233            break;            break;
2234          }          }
       /* Print the flavor of the destructor if in verbose mode.  */  
       if (flag_verbose)  
         {  
           RETURN_IF_ERROR (result_add (dm, " ["));  
           RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor - '0']));  
           RETURN_IF_ERROR (result_add_char (dm, ']'));  
         }  
2235      }      }
   else  
     return STATUS_ERROR;  
2236    
2237    return STATUS_OK;    di->last_name = hold_last_name;
2238    
2239      return al;
2240  }  }
2241    
2242  /* Handle pointer, reference, and pointer-to-member cases for  /* <template-arg> ::= <type>
2243     demangle_type.  All consecutive `P's, `R's, and 'M's are joined to                    ::= X <expression> E
2244     build a pointer/reference type.  We snarf all these, plus the                    ::= <expr-primary>
2245     following <type>, all at once since we need to know whether we have  */
    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>  
   
      <pointer-to-member-type> ::= M </class/ type> </member/ type>  */  
   
 static status_t  
 demangle_type_ptr (dm, insert_pos, substitution_start)  
      demangling_t dm;  
      int *insert_pos;  
      int substitution_start;  
 {  
   status_t status;  
   int is_substitution_candidate = 1;  
   
   DEMANGLE_TRACE ("type*", dm);  
   
   /* Scan forward, collecting pointers and references into symbols,  
      until we hit something else.  Then emit the type.  */  
   switch (peek_char (dm))  
     {  
     case '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.  If we're doing Java style output,  
          there is no pointer symbol.  */  
       if (dm->style != DMGL_JAVA)  
         RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));  
       /* The next (outermost) pointer or reference character should go  
          after this one.  */  
       ++(*insert_pos);  
       break;  
2246    
2247      case 'R':  static struct demangle_component *
2248        /* A reference.  Snarf the `R'.  */  d_template_arg (di)
2249        advance_char (dm);       struct d_info *di;
2250        /* Demangle the underlying type.  */  {
2251        RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,    struct demangle_component *ret;
                                           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);  
       break;  
2252    
2253      case 'M':    switch (d_peek_char (di))
2254      {      {
2255        /* A pointer-to-member.  */      case 'X':
2256        dyn_string_t class_type;        d_advance (di, 1);
2257                ret = d_expression (di);
2258        /* Eat the 'M'.  */        if (d_next_char (di) != 'E')
2259        advance_char (dm);          return NULL;
2260                return ret;
       /* 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 if (peek_char (dm) == 'A')  
         /* A pointer-to-member array variable.  We want output that  
            looks like `int (Klass::*) [10]'.  Demangle the array type  
            as `int () [10]', and set *insert_pos to the spot between  
            the parentheses.  */  
         status = demangle_array_type (dm, insert_pos);  
       else  
         {  
           /* A pointer-to-member variable.  Demangle the type of the  
              pointed-to member.  */  
           status = demangle_type (dm);  
           /* Make it pretty.  */  
           if (STATUS_NO_ERROR (status)  
               && !result_previous_char_is_space (dm))  
             status = result_add_char (dm, ' ');  
           /* The pointer-to-member notation (e.g. `C::*') follows the  
              member's type.  */  
           *insert_pos = result_caret_pos (dm);  
         }  
   
       /* 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;  
2261    
2262        /* Clean up. */      case 'L':
2263        dyn_string_delete (class_type);        return d_expr_primary (di);
2264    
2265        RETURN_IF_ERROR (status);      default:
2266          return cplus_demangle_type (di);
2267      }      }
2268      break;  }
2269    
2270      case 'F':  /* <expression> ::= <(unary) operator-name> <expression>
2271        /* Ooh, tricky, a pointer-to-function.  When we demangle the                  ::= <(binary) operator-name> <expression> <expression>
2272           function type, the return type should go at the very                  ::= <(trinary) operator-name> <expression> <expression> <expression>
2273           beginning.  */                  ::= st <type>
2274        *insert_pos = result_caret_pos (dm);                  ::= <template-param>
2275        /* The parentheses indicate this is a function pointer or                  ::= sr <type> <unqualified-name>
2276           reference type.  */                  ::= sr <type> <unqualified-name> <template-args>
2277        RETURN_IF_ERROR (result_add (dm, "()"));                  ::= <expr-primary>
2278        /* 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);  
       break;  
2279    
2280      case 'A':  static struct demangle_component *
2281        /* An array pointer or reference.  demangle_array_type will figure  d_expression (di)
2282           out where the asterisks and ampersands go.  */       struct d_info *di;
2283        RETURN_IF_ERROR (demangle_array_type (dm, insert_pos));  {
2284        break;    char peek;
2285    
2286      default:    peek = d_peek_char (di);
2287        /* No more pointer or reference tokens; this is therefore a    if (peek == 'L')
2288           pointer to data.  Finish up by demangling the underlying      return d_expr_primary (di);
2289           type.  */    else if (peek == 'T')
2290        RETURN_IF_ERROR (demangle_type (dm));      return d_template_param (di);
2291        /* The pointer or reference characters follow the underlying    else if (peek == 's' && d_peek_next_char (di) == 'r')
2292           type, as in `int*&'.  */      {
2293        *insert_pos = result_caret_pos (dm);        struct demangle_component *type;
2294        /* Because of the production <type> ::= <substitution>,        struct demangle_component *name;
2295           demangle_type will already have added the underlying type as  
2296           a substitution candidate.  Don't do it again.  */        d_advance (di, 2);
2297        is_substitution_candidate = 0;        type = cplus_demangle_type (di);
2298        break;        name = d_unqualified_name (di);
2299      }        if (d_peek_char (di) != 'I')
2300              return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name);
2301    if (is_substitution_candidate)        else
2302      RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));          return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type,
2303                                  d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
2304    return STATUS_OK;                                           d_template_args (di)));
 }  
   
 /* Demangles and emits a <type>.    
   
     <type> ::= <builtin-type>  
            ::= <function-type>  
            ::= <class-enum-type>  
            ::= <array-type>  
            ::= <pointer-to-member-type>  
            ::= <template-param>  
            ::= <template-template-param> <template-args>  
            ::= <CV-qualifiers> <type>  
            ::= P <type>   # pointer-to  
            ::= R <type>   # reference-to  
            ::= C <type>   # complex pair (C 2000)  
            ::= G <type>   # imaginary (C 2000)  
            ::= U <source-name> <type>     # vendor extended type qualifier  
            ::= <substitution>  */  
   
 static status_t  
 demangle_type (dm)  
      demangling_t dm;  
 {  
   int start = substitution_start (dm);  
   char peek = peek_char (dm);  
   char peek_next;  
   int encode_return_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;  
   
   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_builtin_type (dm));  
       /* Built-in types are not substitution candidates.  */  
       is_substitution_candidate = 0;  
2305      }      }
2306    else    else
2307      switch (peek)      {
2308        {        struct demangle_component *op;
2309        case 'r':        int args;
       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);  
           int old_caret_position = result_get_caret (dm);  
   
           if (cv_qualifiers == NULL)  
             return STATUS_ALLOCATION_FAILED;  
   
           /* Decode all adjacent CV qualifiers.  */  
           demangle_CV_qualifiers (dm, cv_qualifiers);  
           /* Emit them, and shift the caret left so that the  
              underlying type will be emitted before the qualifiers.  */  
           status = result_add_string (dm, cv_qualifiers);  
           result_shift_caret (dm, -dyn_string_length (cv_qualifiers));  
           /* Clean up.  */  
           dyn_string_delete (cv_qualifiers);  
           RETURN_IF_ERROR (status);  
           /* Also prepend a blank, if needed.  */  
           RETURN_IF_ERROR (result_add_char (dm, ' '));  
           result_shift_caret (dm, -1);  
   
           /* Demangle the underlying type.  It will be emitted before  
              the CV qualifiers, since we moved the caret.  */  
           RETURN_IF_ERROR (demangle_type (dm));  
   
           /* Put the caret back where it was previously.  */  
           result_set_caret (dm, old_caret_position);  
         }  
         break;  
2310    
2311        case 'F':        op = d_operator_name (di);
2312          return "Non-pointer or -reference function type.";        if (op == NULL)
2313            return NULL;
2314    
2315        case 'A':        if (op->type == DEMANGLE_COMPONENT_OPERATOR)
2316          RETURN_IF_ERROR (demangle_array_type (dm, NULL));          di->expansion += op->u.s_operator.op->len - 2;
         break;  
2317    
2318        case 'T':        if (op->type == DEMANGLE_COMPONENT_OPERATOR
2319          /* It's either a <template-param> or a            && strcmp (op->u.s_operator.op->code, "st") == 0)
2320             <template-template-param>.  In either case, demangle the          return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
2321             `T' token first.  */                              cplus_demangle_type (di));
         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.  */  
           }  
2322    
2323          break;        switch (op->type)
2324            {
2325            default:
2326              return NULL;
2327            case DEMANGLE_COMPONENT_OPERATOR:
2328              args = op->u.s_operator.op->args;
2329              break;
2330            case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
2331              args = op->u.s_extended_operator.args;
2332              break;
2333            case DEMANGLE_COMPONENT_CAST:
2334              args = 1;
2335              break;
2336            }
2337    
2338        case 'S':        switch (args)
2339          /* First check if this is a special substitution.  If it is,          {
2340             this is a <class-enum-type>.  Special substitutions have a          case 1:
2341             letter following the `S'; other substitutions have a digit            return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
2342             or underscore.  */                                d_expression (di));
2343          peek_next = peek_char_next (dm);          case 2:
         if (IS_DIGIT (peek_next) || peek_next == '_')  
2344            {            {
2345              RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));              struct demangle_component *left;
2346                
2347              /* The substituted name may have been a template name.              left = d_expression (di);
2348                 Check if template arguments follow, and if so, demangle              return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op,
2349                 them.  */                                  d_make_comp (di,
2350              if (peek_char (dm) == 'I')                                               DEMANGLE_COMPONENT_BINARY_ARGS,
2351                RETURN_IF_ERROR (demangle_template_args (dm));                                               left,
2352              else                                               d_expression (di)));
               /* A substitution token is not itself a substitution  
                  candidate.  (However, if the substituted template is  
                  instantiated, the resulting type is.)  */  
               is_substitution_candidate = 0;  
2353            }            }
2354          else          case 3:
2355            {            {
2356              /* Now some trickiness.  We have a special substitution              struct demangle_component *first;
2357                 here.  Often, the special substitution provides the              struct demangle_component *second;
                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;  
           }  
   
         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;  
         break;  
   
       case 'C':  
         /* A C99 complex type.  */  
         RETURN_IF_ERROR (result_add (dm, "complex "));  
         advance_char (dm);  
         RETURN_IF_ERROR (demangle_type (dm));  
         break;  
2358    
2359        case 'G':              first = d_expression (di);
2360          /* A C99 imaginary type.  */              second = d_expression (di);
2361          RETURN_IF_ERROR (result_add (dm, "imaginary "));              return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op,
2362          advance_char (dm);                                  d_make_comp (di,
2363          RETURN_IF_ERROR (demangle_type (dm));                                               DEMANGLE_COMPONENT_TRINARY_ARG1,
2364          break;                                               first,
2365                                                 d_make_comp (di,
2366                                                              DEMANGLE_COMPONENT_TRINARY_ARG2,
2367                                                              second,
2368                                                              d_expression (di))));
2369              }
2370            default:
2371              return NULL;
2372            }
2373        }
2374    }
2375    
2376        case 'U':  /* <expr-primary> ::= L <type> <(value) number> E
2377          /* Vendor-extended type qualifier.  */                    ::= L <type> <(value) float> E
2378          advance_char (dm);                    ::= L <mangled-name> E
2379          RETURN_IF_ERROR (demangle_source_name (dm));  */
         RETURN_IF_ERROR (result_add_char (dm, ' '));  
         RETURN_IF_ERROR (demangle_type (dm));  
         break;  
2380    
2381        default:  static struct demangle_component *
2382          return "Unexpected character in <type>.";  d_expr_primary (di)
2383        }       struct d_info *di;
2384    {
2385      struct demangle_component *ret;
2386    
2387    if (is_substitution_candidate)    if (d_next_char (di) != 'L')
2388      /* Add a new substitution for the type. If this type was a      return NULL;
2389         <template-param>, pass its index since from the point of    if (d_peek_char (di) == '_')
2390         substitutions; a <template-param> token is a substitution      ret = cplus_demangle_mangled_name (di, 0);
2391         candidate distinct from the type that is substituted for it.  */    else
2392      RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));      {
2393          struct demangle_component *type;
2394    /* Pop off template argument lists added during mangling of this        enum demangle_component_type t;
2395       type.  */        const char *s;
   pop_to_template_arg_list (dm, old_arg_list);  
   
   return STATUS_OK;  
 }  
   
 /* C++ source names of builtin types, indexed by the mangled code  
    letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc).  */  
 static const char *const builtin_type_names[26] =  
 {  
   "signed char",              /* a */  
   "bool",                     /* b */  
   "char",                     /* c */  
   "double",                   /* d */  
   "long double",              /* e */  
   "float",                    /* f */  
   "__float128",               /* g */  
   "unsigned char",            /* h */  
   "int",                      /* i */  
   "unsigned",                 /* j */  
   NULL,                       /* k */  
   "long",                     /* l */  
   "unsigned long",            /* m */  
   "__int128",                 /* n */  
   "unsigned __int128",        /* o */  
   NULL,                       /* p */  
   NULL,                       /* q */  
   NULL,                       /* r */  
   "short",                    /* s */  
   "unsigned short",           /* t */  
   NULL,                       /* u */  
   "void",                     /* v */  
   "wchar_t",                  /* w */  
   "long long",                /* x */  
   "unsigned long long",       /* y */  
   "..."                       /* z */  
 };  
2396    
2397  /* Java source names of builtin types.  Types that arn't valid in Java        type = cplus_demangle_type (di);
2398     are also included here - we don't fail if someone attempts to demangle a        if (type == NULL)
2399     C++ symbol in Java style. */          return NULL;
 static const char *const java_builtin_type_names[26] =  
 {  
   "signed char",                /* a */  
   "boolean", /* C++ "bool" */   /* b */  
   "byte", /* C++ "char" */      /* c */  
   "double",                     /* d */  
   "long double",                /* e */  
   "float",                      /* f */  
   "__float128",                 /* g */  
   "unsigned char",              /* h */  
   "int",                        /* i */  
   "unsigned",                   /* j */  
   NULL,                         /* k */  
   "long",                       /* l */  
   "unsigned long",              /* m */  
   "__int128",                   /* n */  
   "unsigned __int128",          /* o */  
   NULL,                         /* p */  
   NULL,                         /* q */  
   NULL,                         /* r */  
   "short",                      /* s */  
   "unsigned short",             /* t */  
   NULL,                         /* u */  
   "void",                       /* v */  
   "char", /* C++ "wchar_t" */   /* w */  
   "long", /* C++ "long long" */ /* x */  
   "unsigned long long",         /* y */  
   "..."                         /* z */  
 };  
2400    
2401  /* Demangles and emits a <builtin-type>.          /* If we have a type we know how to print, we aren't going to
2402             print the type name itself.  */
2403          if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE
2404              && type->u.s_builtin.type->print != D_PRINT_DEFAULT)
2405            di->expansion -= type->u.s_builtin.type->len;
2406    
2407          /* Rather than try to interpret the literal value, we just
2408             collect it as a string.  Note that it's possible to have a
2409             floating point literal here.  The ABI specifies that the
2410             format of such literals is machine independent.  That's fine,
2411             but what's not fine is that versions of g++ up to 3.2 with
2412             -fabi-version=1 used upper case letters in the hex constant,
2413             and dumped out gcc's internal representation.  That makes it
2414             hard to tell where the constant ends, and hard to dump the
2415             constant in any readable form anyhow.  We don't attempt to
2416             handle these cases.  */
2417    
2418      <builtin-type> ::= v  # void        t = DEMANGLE_COMPONENT_LITERAL;
2419                     ::= w  # wchar_t        if (d_peek_char (di) == 'n')
2420                     ::= b  # bool          {
2421                     ::= c  # char            t = DEMANGLE_COMPONENT_LITERAL_NEG;
2422                     ::= a  # signed char            d_advance (di, 1);
2423                     ::= h  # unsigned char          }
2424                     ::= s  # short        s = d_str (di);
2425                     ::= t  # unsigned short        while (d_peek_char (di) != 'E')
2426                     ::= i  # int          d_advance (di, 1);
2427                     ::= j  # unsigned int        ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
                    ::= l  # long  
                    ::= m  # unsigned long  
                    ::= x  # long long, __int64  
                    ::= y  # unsigned long long, __int64  
                    ::= n  # __int128  
                    ::= o  # unsigned __int128  
                    ::= f  # float  
                    ::= d  # double  
                    ::= e  # long double, __float80  
                    ::= g  # __float128  
                    ::= z  # ellipsis  
                    ::= u <source-name>    # vendor extended type  */  
   
 static status_t  
 demangle_builtin_type (dm)  
      demangling_t dm;  
 {  
   
   char code = peek_char (dm);  
   
   DEMANGLE_TRACE ("builtin-type", dm);  
   
   if (code == 'u')  
     {  
       advance_char (dm);  
       RETURN_IF_ERROR (demangle_source_name (dm));  
       return STATUS_OK;  
     }  
   else if (code >= 'a' && code <= 'z')  
     {  
       const char *type_name;  
       /* Java uses different names for some built-in types. */  
       if (dm->style == DMGL_JAVA)  
         type_name = java_builtin_type_names[code - 'a'];  
       else  
         type_name = builtin_type_names[code - 'a'];  
       if (type_name == NULL)  
         return "Unrecognized <builtin-type> code.";  
   
       RETURN_IF_ERROR (result_add (dm, type_name));  
       advance_char (dm);  
       return STATUS_OK;  
2428      }      }
2429    else    if (d_next_char (di) != 'E')
2430      return "Non-alphabetic <builtin-type> code.";      return NULL;
2431      return ret;
2432  }  }
2433    
2434  /* Demangles all consecutive CV-qualifiers (const, volatile, and  /* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
2435     restrict) at the current position.  The qualifiers are appended to                  ::= Z <(function) encoding> E s [<discriminator>]
2436     QUALIFIERS.  Returns STATUS_OK.  */  */
2437    
2438  static status_t  static struct demangle_component *
2439  demangle_CV_qualifiers (dm, qualifiers)  d_local_name (di)
2440       demangling_t dm;       struct d_info *di;
      dyn_string_t qualifiers;  
2441  {  {
2442    DEMANGLE_TRACE ("CV-qualifiers", dm);    struct demangle_component *function;
2443    
2444    while (1)    if (d_next_char (di) != 'Z')
2445      {      return NULL;
       switch (peek_char (dm))  
         {  
         case 'r':  
           if (!dyn_string_append_space (qualifiers))  
             return STATUS_ALLOCATION_FAILED;  
           if (!dyn_string_append_cstr (qualifiers, "restrict"))  
             return STATUS_ALLOCATION_FAILED;  
           break;  
2446    
2447          case 'V':    function = d_encoding (di, 0);
           if (!dyn_string_append_space (qualifiers))  
             return STATUS_ALLOCATION_FAILED;  
           if (!dyn_string_append_cstr (qualifiers, "volatile"))  
             return STATUS_ALLOCATION_FAILED;  
           break;  
2448    
2449          case 'K':    if (d_next_char (di) != 'E')
2450            if (!dyn_string_append_space (qualifiers))      return NULL;
             return STATUS_ALLOCATION_FAILED;  
           if (!dyn_string_append_cstr (qualifiers, "const"))  
             return STATUS_ALLOCATION_FAILED;  
           break;  
2451    
2452          default:    if (d_peek_char (di) == 's')
2453            return STATUS_OK;      {
2454          }        d_advance (di, 1);
2455          if (! d_discriminator (di))
2456            return NULL;
2457          return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function,
2458                              d_make_name (di, "string literal",
2459                                           sizeof "string literal" - 1));
2460        }
2461      else
2462        {
2463          struct demangle_component *name;
2464    
2465        advance_char (dm);        name = d_name (di);
2466          if (! d_discriminator (di))
2467            return NULL;
2468          return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name);
2469      }      }
2470  }  }
2471    
2472  /* Demangles and emits a <function-type>.  *FUNCTION_NAME_POS is the  /* <discriminator> ::= _ <(non-negative) number>
    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.  
2473    
2474      <function-type> ::= F [Y] <bare-function-type> E  */     We demangle the discriminator, but we don't print it out.  FIXME:
2475       We should print it out in verbose mode.  */
2476    
2477  static status_t  static int
2478  demangle_function_type (dm, function_name_pos)  d_discriminator (di)
2479       demangling_t dm;       struct d_info *di;
      int *function_name_pos;  
2480  {  {
2481    DEMANGLE_TRACE ("function-type", dm);    long discrim;
2482    RETURN_IF_ERROR (demangle_char (dm, 'F'));    
2483    if (peek_char (dm) == 'Y')    if (d_peek_char (di) != '_')
2484      {      return 1;
2485        /* Indicate this function has C linkage if in verbose mode.  */    d_advance (di, 1);
2486        if (flag_verbose)    discrim = d_number (di);
2487          RETURN_IF_ERROR (result_add (dm, " [extern \"C\"] "));    if (discrim < 0)
2488        advance_char (dm);      return 0;
2489      }    return 1;
   RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));  
   RETURN_IF_ERROR (demangle_char (dm, 'E'));  
   return STATUS_OK;  
2490  }  }
2491    
2492  /* Demangles and emits a <bare-function-type>.  RETURN_TYPE_POS is the  /* Add a new substitution.  */
    position in the result string at which the function return type  
    should be inserted.  If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the  
    function's return type is assumed not to be encoded.    
2493    
2494      <bare-function-type> ::= <signature type>+  */  static int
2495    d_add_substitution (di, dc)
2496         struct d_info *di;
2497         struct demangle_component *dc;
2498    {
2499      if (dc == NULL)
2500        return 0;
2501      if (di->next_sub >= di->num_subs)
2502        return 0;
2503      di->subs[di->next_sub] = dc;
2504      ++di->next_sub;
2505      return 1;
2506    }
2507    
2508    /* <substitution> ::= S <seq-id> _
2509                      ::= S_
2510                      ::= St
2511                      ::= Sa
2512                      ::= Sb
2513                      ::= Ss
2514                      ::= Si
2515                      ::= So
2516                      ::= Sd
2517    
2518       If PREFIX is non-zero, then this type is being used as a prefix in
2519       a qualified name.  In this case, for the standard substitutions, we
2520       need to check whether we are being used as a prefix for a
2521       constructor or destructor, and return a full template name.
2522       Otherwise we will get something like std::iostream::~iostream()
2523       which does not correspond particularly well to any function which
2524       actually appears in the source.
2525    */
2526    
2527  static status_t  static const struct d_standard_sub_info standard_subs[] =
 demangle_bare_function_type (dm, return_type_pos)  
      demangling_t dm;  
      int *return_type_pos;  
2528  {  {
2529    /* Sequence is the index of the current function parameter, counting    { 't', NL ("std"),
2530       from zero.  The value -1 denotes the return type.  */      NL ("std"),
2531    int sequence =      NULL, 0 },
2532      (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);    { 'a', NL ("std::allocator"),
2533        NL ("std::allocator"),
2534        NL ("allocator") },
2535      { 'b', NL ("std::basic_string"),
2536        NL ("std::basic_string"),
2537        NL ("basic_string") },
2538      { 's', NL ("std::string"),
2539        NL ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
2540        NL ("basic_string") },
2541      { 'i', NL ("std::istream"),
2542        NL ("std::basic_istream<char, std::char_traits<char> >"),
2543        NL ("basic_istream") },
2544      { 'o', NL ("std::ostream"),
2545        NL ("std::basic_ostream<char, std::char_traits<char> >"),
2546        NL ("basic_ostream") },
2547      { 'd', NL ("std::iostream"),
2548        NL ("std::basic_iostream<char, std::char_traits<char> >"),
2549        NL ("basic_iostream") }
2550    };
2551    
2552    DEMANGLE_TRACE ("bare-function-type", dm);  static struct demangle_component *
2553    d_substitution (di, prefix)
2554         struct d_info *di;
2555         int prefix;
2556    {
2557      char c;
2558    
2559    RETURN_IF_ERROR (result_add_char (dm, '('));    if (d_next_char (di) != 'S')
2560    while (!end_of_name_p (dm) && peek_char (dm) != 'E')      return NULL;
     {  
       if (sequence == -1)  
         /* We're decoding the function's return type.  */  
         {  
           dyn_string_t return_type;  
           status_t status = STATUS_OK;  
2561    
2562            /* Decode the return type off to the side.  */    c = d_next_char (di);
2563            RETURN_IF_ERROR (result_push (dm));    if (c == '_' || IS_DIGIT (c) || IS_UPPER (c))
2564            RETURN_IF_ERROR (demangle_type (dm));      {
2565            return_type = (dyn_string_t) result_pop (dm);        int id;
2566    
2567            /* Add a space to the end of the type.  Insert the return        id = 0;
2568               type where we've been asked to. */        if (c != '_')
2569            if (!dyn_string_append_space (return_type))          {
2570              status = STATUS_ALLOCATION_FAILED;            do
           if (STATUS_NO_ERROR (status))  
2571              {              {
2572                if (!dyn_string_insert (result_string (dm), *return_type_pos,                if (IS_DIGIT (c))
2573                                        return_type))                  id = id * 36 + c - '0';
2574                  status = STATUS_ALLOCATION_FAILED;                else if (IS_UPPER (c))
2575                    id = id * 36 + c - 'A' + 10;
2576                else                else
2577                  *return_type_pos += dyn_string_length (return_type);                  return NULL;
2578                  c = d_next_char (di);
2579              }              }
2580              while (c != '_');
2581    
2582            dyn_string_delete (return_type);            ++id;
           RETURN_IF_ERROR (status);  
2583          }          }
2584        else  
2585          if (id >= di->next_sub)
2586            return NULL;
2587    
2588          ++di->did_subs;
2589    
2590          return di->subs[id];
2591        }
2592      else
2593        {
2594          int verbose;
2595          const struct d_standard_sub_info *p;
2596          const struct d_standard_sub_info *pend;
2597    
2598          verbose = (di->options & DMGL_VERBOSE) != 0;
2599          if (! verbose && prefix)
2600          {          {
2601            /* Skip `void' parameter types.  One should only occur as            char peek;
2602               the only type in a parameter list; in that case, we want  
2603               to print `foo ()' instead of `foo (void)'.  */            peek = d_peek_char (di);
2604            if (peek_char (dm) == 'v')            if (peek == 'C' || peek == 'D')
2605              /* Consume the v.  */              verbose = 1;
2606              advance_char (dm);          }
2607            else  
2608          pend = (&standard_subs[0]
2609                  + sizeof standard_subs / sizeof standard_subs[0]);
2610          for (p = &standard_subs[0]; p < pend; ++p)
2611            {
2612              if (c == p->code)
2613              {              {
2614                /* Separate parameter types by commas.  */                const char *s;
2615                if (sequence > 0)                int len;
2616                  RETURN_IF_ERROR (result_add (dm, ", "));  
2617                /* Demangle the type.  */                if (p->set_last_name != NULL)
2618                RETURN_IF_ERROR (demangle_type (dm));                  di->last_name = d_make_sub (di, p->set_last_name,
2619                                                p->set_last_name_len);
2620                  if (verbose)
2621                    {
2622                      s = p->full_expansion;
2623                      len = p->full_len;
2624                    }
2625                  else
2626                    {
2627                      s = p->simple_expansion;
2628                      len = p->simple_len;
2629                    }
2630                  di->expansion += len;
2631                  return d_make_sub (di, s, len);
2632              }              }
2633          }          }
2634    
2635        ++sequence;        return NULL;
2636      }      }
2637    RETURN_IF_ERROR (result_add_char (dm, ')'));  }
2638    
2639    /* We should have demangled at least one parameter type (which would  /* Resize the print buffer.  */
      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.";  
2640    
2641    return STATUS_OK;  static void
2642    d_print_resize (dpi, add)
2643         struct d_print_info *dpi;
2644         size_t add;
2645    {
2646      size_t need;
2647    
2648      if (dpi->buf == NULL)
2649        return;
2650      need = dpi->len + add;
2651      while (need > dpi->alc)
2652        {
2653          size_t newalc;
2654          char *newbuf;
2655    
2656          newalc = dpi->alc * 2;
2657          newbuf = realloc (dpi->buf, newalc);
2658          if (newbuf == NULL)
2659            {
2660              free (dpi->buf);
2661              dpi->buf = NULL;
2662              dpi->allocation_failure = 1;
2663              return;
2664            }
2665          dpi->buf = newbuf;
2666          dpi->alc = newalc;
2667        }
2668  }  }
2669    
2670  /* Demangles and emits a <class-enum-type>.  *ENCODE_RETURN_TYPE is set to  /* Append a character to the print buffer.  */
    non-zero if the type is a template-id, zero otherwise.    
   
     <class-enum-type> ::= <name>  */  
2671    
2672  static status_t  static void
2673  demangle_class_enum_type (dm, encode_return_type)  d_print_append_char (dpi, c)
2674       demangling_t dm;       struct d_print_info *dpi;
2675       int *encode_return_type;       int c;
2676  {  {
2677    DEMANGLE_TRACE ("class-enum-type", dm);    if (dpi->buf != NULL)
2678        {
2679          if (dpi->len >= dpi->alc)
2680            {
2681              d_print_resize (dpi, 1);
2682              if (dpi->buf == NULL)
2683                return;
2684            }
2685    
2686    RETURN_IF_ERROR (demangle_name (dm, encode_return_type));        dpi->buf[dpi->len] = c;
2687    return STATUS_OK;        ++dpi->len;
2688        }
2689  }  }
2690    
2691  /* Demangles and emits an <array-type>.    /* Append a buffer to the print buffer.  */
2692    
2693     If PTR_INSERT_POS is not NULL, the array type is formatted as a  static void
2694     pointer or reference to an array, except that asterisk and  d_print_append_buffer (dpi, s, l)
2695     ampersand punctuation is omitted (since it's not know at this       struct d_print_info *dpi;
2696     point).  *PTR_INSERT_POS is set to the position in the demangled       const char *s;
2697     name at which this punctuation should be inserted.  For example,       size_t l;
2698     `A10_i' is demangled to `int () [10]' and *PTR_INSERT_POS points  {
2699     between the parentheses.    if (dpi->buf != NULL)
2700        {
2701          if (dpi->len + l > dpi->alc)
2702            {
2703              d_print_resize (dpi, l);
2704              if (dpi->buf == NULL)
2705                return;
2706            }
2707    
2708     If PTR_INSERT_POS is NULL, the array type is assumed not to be        memcpy (dpi->buf + dpi->len, s, l);
2709     pointer- or reference-qualified.  Then, for example, `A10_i' is        dpi->len += l;
2710     demangled simply as `int[10]'.        }
2711    }
2712    
2713      <array-type> ::= A [<dimension number>] _ <element type>    /* Indicate that an error occurred during printing.  */
                  ::= A <dimension expression> _ <element type>  */  
2714    
2715  static status_t  static void
2716  demangle_array_type (dm, ptr_insert_pos)  d_print_error (dpi)
2717       demangling_t dm;       struct d_print_info *dpi;
      int *ptr_insert_pos;  
2718  {  {
2719    status_t status = STATUS_OK;    free (dpi->buf);
2720    dyn_string_t array_size = NULL;    dpi->buf = NULL;
2721    char peek;  }
2722    
2723    /* Turn components into a human readable string.  OPTIONS is the
2724       options bits passed to the demangler.  DC is the tree to print.
2725       ESTIMATE is a guess at the length of the result.  This returns a
2726       string allocated by malloc, or NULL on error.  On success, this
2727       sets *PALC to the size of the allocated buffer.  On failure, this
2728       sets *PALC to 0 for a bad parse, or to 1 for a memory allocation
2729       failure.  */
2730    
2731    DEMANGLE_TRACE ("array-type", dm);  CP_STATIC_IF_GLIBCPP_V3
2732    char *
2733    cplus_demangle_print (options, dc, estimate, palc)
2734         int options;
2735         const struct demangle_component *dc;
2736         int estimate;
2737         size_t *palc;
2738    {
2739      struct d_print_info dpi;
2740    
2741    RETURN_IF_ERROR (demangle_char (dm, 'A'));    dpi.options = options;
2742    
2743    /* Demangle the array size into array_size.  */    dpi.alc = estimate + 1;
2744    peek = peek_char (dm);    dpi.buf = malloc (dpi.alc);
2745    if (peek == '_')    if (dpi.buf == NULL)
     /* 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  
2746      {      {
2747        /* Anything is must be an expression for a nont-constant array        *palc = 1;
2748           bound.  This happens if the array type occurs in a template        return NULL;
2749           and the array bound references a template parameter.  */      }
2750        RETURN_IF_ERROR (result_push (dm));  
2751        RETURN_IF_ERROR (demangle_expression (dm));    dpi.len = 0;
2752        array_size = (dyn_string_t) result_pop (dm);    dpi.templates = NULL;
2753      }    dpi.modifiers = NULL;
2754    /* array_size may have been allocated by now, so we can't use  
2755       RETURN_IF_ERROR until it's been deallocated.  */    dpi.allocation_failure = 0;
2756    
2757    /* Demangle the base type of the array.  */    d_print_comp (&dpi, dc);
2758    if (STATUS_NO_ERROR (status))  
2759      status = demangle_char (dm, '_');    d_append_char (&dpi, '\0');
2760    if (STATUS_NO_ERROR (status))  
2761      status = demangle_type (dm);    if (dpi.buf != NULL)
2762        *palc = dpi.alc;
   if (ptr_insert_pos != NULL)  
     {  
       /* This array is actually part of an pointer- or  
          reference-to-array type.  Format appropriately, except we  
          don't know which and how much punctuation to use.  */  
       if (STATUS_NO_ERROR (status))  
         status = result_add (dm, " () ");  
       /* Let the caller know where to insert the punctuation.  */  
       *ptr_insert_pos = result_caret_pos (dm) - 2;  
     }  
   
   /* Emit the array dimension syntax.  */  
   if (STATUS_NO_ERROR (status))  
     status = result_add_char (dm, '[');  
   if (STATUS_NO_ERROR (status) && array_size != NULL)  
     status = result_add_string (dm, array_size);  
   if (STATUS_NO_ERROR (status))  
     status = result_add_char (dm, ']');  
   if (array_size != NULL)  
     dyn_string_delete (array_size);  
     
   RETURN_IF_ERROR (status);  
   
   return STATUS_OK;  
 }  
   
 /* Demangles and emits a <template-param>.    
   
     <template-param> ::= T_       # first template parameter  
                      ::= T <parameter-2 number> _  */  
   
 static status_t  
 demangle_template_param (dm)  
      demangling_t dm;  
 {  
   int parm_number;  
   template_arg_list_t current_arg_list = current_template_arg_list (dm);  
   string_list_t arg;  
   
   DEMANGLE_TRACE ("template-param", dm);  
   
   /* Make sure there is a template argmust list in which to look up  
      this parameter reference.  */  
   if (current_arg_list == NULL)  
     return "Template parameter outside of template.";  
   
   RETURN_IF_ERROR (demangle_char (dm, 'T'));  
   if (peek_char (dm) == '_')  
     parm_number = 0;  
2763    else    else
2764        *palc = dpi.allocation_failure;
2765    
2766      return dpi.buf;
2767    }
2768    
2769    /* Subroutine to handle components.  */
2770    
2771    static void
2772    d_print_comp (dpi, dc)
2773         struct d_print_info *dpi;
2774         const struct demangle_component *dc;
2775    {
2776      if (dc == NULL)
2777      {      {
2778        RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));        d_print_error (dpi);
2779        ++parm_number;        return;
2780      }      }
2781    RETURN_IF_ERROR (demangle_char (dm, '_'));    if (d_print_saw_error (dpi))
2782        return;
2783    
2784    arg = template_arg_list_get_arg (current_arg_list, parm_number);    switch (dc->type)
2785    if (arg == NULL)      {
2786      /* parm_number exceeded the number of arguments in the current      case DEMANGLE_COMPONENT_NAME:
2787         template argument list.  */        if ((dpi->options & DMGL_JAVA) == 0)
2788      return "Template parameter number out of bounds.";          d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len);
2789    RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));        else
2790            d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
2791          return;
2792    
2793    return STATUS_OK;      case DEMANGLE_COMPONENT_QUAL_NAME:
2794  }      case DEMANGLE_COMPONENT_LOCAL_NAME:
2795          d_print_comp (dpi, d_left (dc));
2796          if ((dpi->options & DMGL_JAVA) == 0)
2797            d_append_string_constant (dpi, "::");
2798          else
2799            d_append_char (dpi, '.');
2800          d_print_comp (dpi, d_right (dc));
2801          return;
2802    
2803        case DEMANGLE_COMPONENT_TYPED_NAME:
2804          {
2805            struct d_print_mod *hold_modifiers;
2806            struct demangle_component *typed_name;
2807            struct d_print_mod adpm[4];
2808            unsigned int i;
2809            struct d_print_template dpt;
2810    
2811            /* Pass the name down to the type so that it can be printed in
2812               the right place for the type.  We also have to pass down
2813               any CV-qualifiers, which apply to the this parameter.  */
2814            hold_modifiers = dpi->modifiers;
2815            i = 0;
2816            typed_name = d_left (dc);
2817            while (typed_name != NULL)
2818              {
2819                if (i >= sizeof adpm / sizeof adpm[0])
2820                  {
2821                    d_print_error (dpi);
2822                    return;
2823                  }
2824    
2825                adpm[i].next = dpi->modifiers;
2826                dpi->modifiers = &adpm[i];
2827                adpm[i].mod = typed_name;
2828                adpm[i].printed = 0;
2829                adpm[i].templates = dpi->templates;
2830                ++i;
2831    
2832                if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS
2833                    && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
2834                    && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS)
2835                  break;
2836    
2837  /* Demangles and emits a <template-args>.                typed_name = d_left (typed_name);
2838              }
2839    
2840      <template-args> ::= I <template-arg>+ E  */          /* If typed_name is a template, then it applies to the
2841               function type as well.  */
2842            if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
2843              {
2844                dpt.next = dpi->templates;
2845                dpi->templates = &dpt;
2846                dpt.template = typed_name;
2847              }
2848    
2849  static status_t          /* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then
2850  demangle_template_args (dm)             there may be CV-qualifiers on its right argument which
2851       demangling_t dm;             really apply here; this happens when parsing a class which
2852  {             is local to a function.  */
2853    int first = 1;          if (typed_name->type == DEMANGLE_COMPONENT_LOCAL_NAME)
2854    dyn_string_t old_last_source_name;            {
2855    template_arg_list_t arg_list = template_arg_list_new ();              struct demangle_component *local_name;
2856    
2857    if (arg_list == NULL)              local_name = d_right (typed_name);
2858      return STATUS_ALLOCATION_FAILED;              while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
2859                       || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
2860                       || local_name->type == DEMANGLE_COMPONENT_CONST_THIS)
2861                  {
2862                    if (i >= sizeof adpm / sizeof adpm[0])
2863                      {
2864                        d_print_error (dpi);
2865                        return;
2866                      }
2867    
2868                    adpm[i] = adpm[i - 1];
2869                    adpm[i].next = &adpm[i - 1];
2870                    dpi->modifiers = &adpm[i];
2871    
2872                    adpm[i - 1].mod = local_name;
2873                    adpm[i - 1].printed = 0;
2874                    adpm[i - 1].templates = dpi->templates;
2875                    ++i;
2876    
2877    /* Preserve the most recently demangled source name.  */                  local_name = d_left (local_name);
2878    old_last_source_name = dm->last_source_name;                }
2879    dm->last_source_name = dyn_string_new (0);            }
2880    
2881    DEMANGLE_TRACE ("template-args", dm);          d_print_comp (dpi, d_right (dc));
2882    
2883    if (dm->last_source_name == NULL)          if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
2884      return STATUS_ALLOCATION_FAILED;            dpi->templates = dpt.next;
2885    
2886    RETURN_IF_ERROR (demangle_char (dm, 'I'));          /* If the modifiers didn't get printed by the type, print them
2887    RETURN_IF_ERROR (result_open_template_list (dm));             now.  */
2888    do          while (i > 0)
2889      {            {
2890        string_list_t arg;              --i;
2891                if (! adpm[i].printed)
2892                  {
2893                    d_append_char (dpi, ' ');
2894                    d_print_mod (dpi, adpm[i].mod);
2895                  }
2896              }
2897    
2898        if (first)          dpi->modifiers = hold_modifiers;
2899          first = 0;  
2900            return;
2901          }
2902    
2903        case DEMANGLE_COMPONENT_TEMPLATE:
2904          {
2905            struct d_print_mod *hold_dpm;
2906    
2907            /* Don't push modifiers into a template definition.  Doing so
2908               could give the wrong definition for a template argument.
2909               Instead, treat the template essentially as a name.  */
2910    
2911            hold_dpm = dpi->modifiers;
2912            dpi->modifiers = NULL;
2913    
2914            d_print_comp (dpi, d_left (dc));
2915            if (d_last_char (dpi) == '<')
2916              d_append_char (dpi, ' ');
2917            d_append_char (dpi, '<');
2918            d_print_comp (dpi, d_right (dc));
2919            /* Avoid generating two consecutive '>' characters, to avoid
2920               the C++ syntactic ambiguity.  */
2921            if (d_last_char (dpi) == '>')
2922              d_append_char (dpi, ' ');
2923            d_append_char (dpi, '>');
2924    
2925            dpi->modifiers = hold_dpm;
2926    
2927            return;
2928          }
2929    
2930        case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
2931          {
2932            long i;
2933            struct demangle_component *a;
2934            struct d_print_template *hold_dpt;
2935    
2936            if (dpi->templates == NULL)
2937              {
2938                d_print_error (dpi);
2939                return;
2940              }
2941            i = dc->u.s_number.number;
2942            for (a = d_right (dpi->templates->template);
2943                 a != NULL;
2944                 a = d_right (a))
2945              {
2946                if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
2947                  {
2948                    d_print_error (dpi);
2949                    return;
2950                  }
2951                if (i <= 0)
2952                  break;
2953                --i;
2954              }
2955            if (i != 0 || a == NULL)
2956              {
2957                d_print_error (dpi);
2958                return;
2959              }
2960    
2961            /* While processing this parameter, we need to pop the list of
2962               templates.  This is because the template parameter may
2963               itself be a reference to a parameter of an outer
2964               template.  */
2965    
2966            hold_dpt = dpi->templates;
2967            dpi->templates = hold_dpt->next;
2968    
2969            d_print_comp (dpi, d_left (a));
2970    
2971            dpi->templates = hold_dpt;
2972    
2973            return;
2974          }
2975    
2976        case DEMANGLE_COMPONENT_CTOR:
2977          d_print_comp (dpi, dc->u.s_ctor.name);
2978          return;
2979    
2980        case DEMANGLE_COMPONENT_DTOR:
2981          d_append_char (dpi, '~');
2982          d_print_comp (dpi, dc->u.s_dtor.name);
2983          return;
2984    
2985        case DEMANGLE_COMPONENT_VTABLE:
2986          d_append_string_constant (dpi, "vtable for ");
2987          d_print_comp (dpi, d_left (dc));
2988          return;
2989    
2990        case DEMANGLE_COMPONENT_VTT:
2991          d_append_string_constant (dpi, "VTT for ");
2992          d_print_comp (dpi, d_left (dc));
2993          return;
2994    
2995        case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
2996          d_append_string_constant (dpi, "construction vtable for ");
2997          d_print_comp (dpi, d_left (dc));
2998          d_append_string_constant (dpi, "-in-");
2999          d_print_comp (dpi, d_right (dc));
3000          return;
3001    
3002        case DEMANGLE_COMPONENT_TYPEINFO:
3003          d_append_string_constant (dpi, "typeinfo for ");
3004          d_print_comp (dpi, d_left (dc));
3005          return;
3006    
3007        case DEMANGLE_COMPONENT_TYPEINFO_NAME:
3008          d_append_string_constant (dpi, "typeinfo name for ");
3009          d_print_comp (dpi, d_left (dc));
3010          return;
3011    
3012        case DEMANGLE_COMPONENT_TYPEINFO_FN:
3013          d_append_string_constant (dpi, "typeinfo fn for ");
3014          d_print_comp (dpi, d_left (dc));
3015          return;
3016    
3017        case DEMANGLE_COMPONENT_THUNK:
3018          d_append_string_constant (dpi, "non-virtual thunk to ");
3019          d_print_comp (dpi, d_left (dc));
3020          return;
3021    
3022        case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
3023          d_append_string_constant (dpi, "virtual thunk to ");
3024          d_print_comp (dpi, d_left (dc));
3025          return;
3026    
3027        case DEMANGLE_COMPONENT_COVARIANT_THUNK:
3028          d_append_string_constant (dpi, "covariant return thunk to ");
3029          d_print_comp (dpi, d_left (dc));
3030          return;
3031    
3032        case DEMANGLE_COMPONENT_JAVA_CLASS:
3033          d_append_string_constant (dpi, "java Class for ");
3034          d_print_comp (dpi, d_left (dc));
3035          return;
3036    
3037        case DEMANGLE_COMPONENT_GUARD:
3038          d_append_string_constant (dpi, "guard variable for ");
3039          d_print_comp (dpi, d_left (dc));
3040          return;
3041    
3042        case DEMANGLE_COMPONENT_REFTEMP:
3043          d_append_string_constant (dpi, "reference temporary for ");
3044          d_print_comp (dpi, d_left (dc));
3045          return;
3046    
3047        case DEMANGLE_COMPONENT_SUB_STD:
3048          d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len);
3049          return;
3050    
3051        case DEMANGLE_COMPONENT_RESTRICT:
3052        case DEMANGLE_COMPONENT_VOLATILE:
3053        case DEMANGLE_COMPONENT_CONST:
3054          {
3055            struct d_print_mod *pdpm;
3056    
3057            /* When printing arrays, it's possible to have cases where the
3058               same CV-qualifier gets pushed on the stack multiple times.
3059               We only need to print it once.  */
3060    
3061            for (pdpm = dpi->modifiers; pdpm != NULL; pdpm = pdpm->next)
3062              {
3063                if (! pdpm->printed)
3064                  {
3065                    if (pdpm->mod->type != DEMANGLE_COMPONENT_RESTRICT
3066                        && pdpm->mod->type != DEMANGLE_COMPONENT_VOLATILE
3067                        && pdpm->mod->type != DEMANGLE_COMPONENT_CONST)
3068                      break;
3069                    if (pdpm->mod->type == dc->type)
3070                      {
3071                        d_print_comp (dpi, d_left (dc));
3072                        return;
3073                      }
3074                  }
3075              }
3076          }
3077          /* Fall through.  */
3078        case DEMANGLE_COMPONENT_RESTRICT_THIS:
3079        case DEMANGLE_COMPONENT_VOLATILE_THIS:
3080        case DEMANGLE_COMPONENT_CONST_THIS:
3081        case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
3082        case DEMANGLE_COMPONENT_POINTER:
3083        case DEMANGLE_COMPONENT_REFERENCE:
3084        case DEMANGLE_COMPONENT_COMPLEX:
3085        case DEMANGLE_COMPONENT_IMAGINARY:
3086          {
3087            /* We keep a list of modifiers on the stack.  */
3088            struct d_print_mod dpm;
3089    
3090            dpm.next = dpi->modifiers;
3091            dpi->modifiers = &dpm;
3092            dpm.mod = dc;
3093            dpm.printed = 0;
3094            dpm.templates = dpi->templates;
3095    
3096            d_print_comp (dpi, d_left (dc));
3097    
3098            /* If the modifier didn't get printed by the type, print it
3099               now.  */
3100            if (! dpm.printed)
3101              d_print_mod (dpi, dc);
3102    
3103            dpi->modifiers = dpm.next;
3104    
3105            return;
3106          }
3107    
3108        case DEMANGLE_COMPONENT_BUILTIN_TYPE:
3109          if ((dpi->options & DMGL_JAVA) == 0)
3110            d_append_buffer (dpi, dc->u.s_builtin.type->name,
3111                             dc->u.s_builtin.type->len);
3112        else        else
3113          RETURN_IF_ERROR (result_add (dm, ", "));          d_append_buffer (dpi, dc->u.s_builtin.type->java_name,
3114                             dc->u.s_builtin.type->java_len);
3115          return;
3116    
3117        case DEMANGLE_COMPONENT_VENDOR_TYPE:
3118          d_print_comp (dpi, d_left (dc));
3119          return;
3120    
3121        /* Capture the template arg.  */      case DEMANGLE_COMPONENT_FUNCTION_TYPE:
3122        RETURN_IF_ERROR (result_push (dm));        {
3123        RETURN_IF_ERROR (demangle_template_arg (dm));          if (d_left (dc) != NULL)
3124        arg = result_pop (dm);            {
3125                struct d_print_mod dpm;
       /* Emit it in the demangled name.  */  
       RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));  
   
       /* Save it for use in expanding <template-param>s.  */  
       template_arg_list_add_arg (arg_list, arg);  
     }  
   while (peek_char (dm) != 'E');  
   /* Append the '>'.  */  
   RETURN_IF_ERROR (result_close_template_list (dm));  
   
   /* Consume the 'E'.  */  
   advance_char (dm);  
   
   /* Restore the most recent demangled source name.  */  
   dyn_string_delete (dm->last_source_name);  
   dm->last_source_name = old_last_source_name;  
   
   /* Push the list onto the top of the stack of template argument  
      lists, so that arguments from it are used from now on when  
      expanding <template-param>s.  */  
   push_template_arg_list (dm, arg_list);  
   
   return STATUS_OK;  
 }  
   
 /* This function, which does not correspond to a production in the  
    mangling spec, handles the `literal' production for both  
    <template-arg> and <expr-primary>.  It does not expect or consume  
    the initial `L' or final `E'.  The demangling is given by:  
   
      <literal> ::= <type> </value/ number>  
   
    and the emitted output is `(type)number'.  */  
   
 static status_t  
 demangle_literal (dm)  
      demangling_t dm;  
 {  
   char peek = peek_char (dm);  
   dyn_string_t value_string;  
   status_t status;  
   
   DEMANGLE_TRACE ("literal", dm);  
   
   if (!flag_verbose && peek >= 'a' && peek <= 'z')  
     {  
       /* If not in verbose mode and this is a builtin type, see if we  
          can produce simpler numerical output.  In particular, for  
          integer types shorter than `long', just write the number  
          without type information; for bools, write `true' or `false'.  
          Other refinements could be made here too.  */  
   
       /* This constant string is used to map from <builtin-type> codes  
          (26 letters of the alphabet) to codes that determine how the  
          value will be displayed.  The codes are:  
            b: display as bool  
            i: display as int  
            l: display as long  
          A space means the value will be represented using cast  
          notation. */  
       static const char *const code_map = "ibi    iii ll     ii  i  ";  
   
       char code = code_map[peek - 'a'];  
       /* FIXME: Implement demangling of floats and doubles.  */  
       if (code == 'u')  
         return STATUS_UNIMPLEMENTED;  
       if (code == 'b')  
         {  
           /* It's a boolean.  */  
           char value;  
   
           /* Consume the b.  */  
           advance_char (dm);  
           /* Look at the next character.  It should be 0 or 1,  
              corresponding to false or true, respectively.  */  
           value = peek_char (dm);  
           if (value == '0')  
             RETURN_IF_ERROR (result_add (dm, "false"));  
           else if (value == '1')  
             RETURN_IF_ERROR (result_add (dm, "true"));  
           else  
             return "Unrecognized bool constant.";  
           /* Consume the 0 or 1.  */  
           advance_char (dm);  
           return STATUS_OK;  
         }  
       else if (code == 'i' || code == 'l')  
         {  
           /* It's an integer or long.  */  
3126    
3127            /* Consume the type character.  */              /* We must pass this type down as a modifier in order to
3128            advance_char (dm);                 print it in the right location.  */
3129    
3130            /* Demangle the number and write it out.  */              dpm.next = dpi->modifiers;
3131            value_string = dyn_string_new (0);              dpi->modifiers = &dpm;
3132            status = demangle_number_literally (dm, value_string, 10, 1);              dpm.mod = dc;
3133            if (STATUS_NO_ERROR (status))              dpm.printed = 0;
3134              status = result_add_string (dm, value_string);              dpm.templates = dpi->templates;
           /* For long integers, append an l.  */  
           if (code == 'l' && STATUS_NO_ERROR (status))  
             status = result_add_char (dm, code);  
           dyn_string_delete (value_string);  
3135    
3136            RETURN_IF_ERROR (status);              d_print_comp (dpi, d_left (dc));
           return STATUS_OK;  
         }  
       /* ...else code == ' ', so fall through to represent this  
          literal's type explicitly using cast syntax.  */  
     }  
3137    
3138    RETURN_IF_ERROR (result_add_char (dm, '('));              dpi->modifiers = dpm.next;
   RETURN_IF_ERROR (demangle_type (dm));  
   RETURN_IF_ERROR (result_add_char (dm, ')'));  
3139    
3140    value_string = dyn_string_new (0);              if (dpm.printed)
3141    if (value_string == NULL)                return;
     return STATUS_ALLOCATION_FAILED;  
3142    
3143    status = demangle_number_literally (dm, value_string, 10, 1);              d_append_char (dpi, ' ');
3144    if (STATUS_NO_ERROR (status))            }
     status = result_add_string (dm, value_string);  
   dyn_string_delete (value_string);  
   RETURN_IF_ERROR (status);  
3145    
3146    return STATUS_OK;          d_print_function_type (dpi, dc, dpi->modifiers);
 }  
3147    
3148  /* Demangles and emits a <template-arg>.            return;
3149          }
3150    
3151      <template-arg> ::= <type>                     # type      case DEMANGLE_COMPONENT_ARRAY_TYPE:
3152                     ::= L <type> <value number> E  # literal        {
3153                     ::= LZ <encoding> E            # external name          struct d_print_mod *hold_modifiers;
3154                     ::= X <expression> E           # expression  */          struct d_print_mod adpm[4];
3155            unsigned int i;
3156            struct d_print_mod *pdpm;
3157    
3158            /* We must pass this type down as a modifier in order to print
3159               multi-dimensional arrays correctly.  If the array itself is
3160               CV-qualified, we act as though the element type were
3161               CV-qualified.  We do this by copying the modifiers down
3162               rather than fiddling pointers, so that we don't wind up
3163               with a d_print_mod higher on the stack pointing into our
3164               stack frame after we return.  */
3165    
3166            hold_modifiers = dpi->modifiers;
3167    
3168            adpm[0].next = hold_modifiers;
3169            dpi->modifiers = &adpm[0];
3170            adpm[0].mod = dc;
3171            adpm[0].printed = 0;
3172            adpm[0].templates = dpi->templates;
3173    
3174            i = 1;
3175            pdpm = hold_modifiers;
3176            while (pdpm != NULL
3177                   && (pdpm->mod->type == DEMANGLE_COMPONENT_RESTRICT
3178                       || pdpm->mod->type == DEMANGLE_COMPONENT_VOLATILE
3179                       || pdpm->mod->type == DEMANGLE_COMPONENT_CONST))
3180              {
3181                if (! pdpm->printed)
3182                  {
3183                    if (i >= sizeof adpm / sizeof adpm[0])
3184                      {
3185                        d_print_error (dpi);
3186                        return;
3187                      }
3188    
3189                    adpm[i] = *pdpm;
3190                    adpm[i].next = dpi->modifiers;
3191                    dpi->modifiers = &adpm[i];
3192                    pdpm->printed = 1;
3193                    ++i;
3194                  }
3195    
3196  static status_t              pdpm = pdpm->next;
3197  demangle_template_arg (dm)            }
      demangling_t dm;  
 {  
   DEMANGLE_TRACE ("template-arg", dm);  
3198    
3199    switch (peek_char (dm))          d_print_comp (dpi, d_right (dc));
3200      {  
3201      case 'L':          dpi->modifiers = hold_modifiers;
3202        advance_char (dm);  
3203            if (adpm[0].printed)
3204              return;
3205    
3206            while (i > 1)
3207              {
3208                --i;
3209                d_print_mod (dpi, adpm[i].mod);
3210              }
3211    
3212            d_print_array_type (dpi, dc, dpi->modifiers);
3213    
3214            return;
3215          }
3216    
3217        case DEMANGLE_COMPONENT_PTRMEM_TYPE:
3218          {
3219            struct d_print_mod dpm;
3220    
3221            dpm.next = dpi->modifiers;
3222            dpi->modifiers = &dpm;
3223            dpm.mod = dc;
3224            dpm.printed = 0;
3225            dpm.templates = dpi->templates;
3226    
3227            d_print_comp (dpi, d_right (dc));
3228    
3229            /* If the modifier didn't get printed by the type, print it
3230               now.  */
3231            if (! dpm.printed)
3232              {
3233                d_append_char (dpi, ' ');
3234                d_print_comp (dpi, d_left (dc));
3235                d_append_string_constant (dpi, "::*");
3236              }
3237    
3238        if (peek_char (dm) == 'Z')          dpi->modifiers = dpm.next;
3239    
3240            return;
3241          }
3242    
3243        case DEMANGLE_COMPONENT_ARGLIST:
3244        case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
3245          d_print_comp (dpi, d_left (dc));
3246          if (d_right (dc) != NULL)
3247          {          {
3248            /* External name.  */            d_append_string_constant (dpi, ", ");
3249            advance_char (dm);            d_print_comp (dpi, d_right (dc));
           /* FIXME: Standard is contradictory here.  */  
           RETURN_IF_ERROR (demangle_encoding (dm));  
3250          }          }
3251          return;
3252    
3253        case DEMANGLE_COMPONENT_OPERATOR:
3254          {
3255            char c;
3256    
3257            d_append_string_constant (dpi, "operator");
3258            c = dc->u.s_operator.op->name[0];
3259            if (IS_LOWER (c))
3260              d_append_char (dpi, ' ');
3261            d_append_buffer (dpi, dc->u.s_operator.op->name,
3262                             dc->u.s_operator.op->len);
3263            return;
3264          }
3265    
3266        case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
3267          d_append_string_constant (dpi, "operator ");
3268          d_print_comp (dpi, dc->u.s_extended_operator.name);
3269          return;
3270    
3271        case DEMANGLE_COMPONENT_CAST:
3272          d_append_string_constant (dpi, "operator ");
3273          d_print_cast (dpi, dc);
3274          return;
3275    
3276        case DEMANGLE_COMPONENT_UNARY:
3277          if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST)
3278            d_print_expr_op (dpi, d_left (dc));
3279        else        else
3280          RETURN_IF_ERROR (demangle_literal (dm));          {
3281        RETURN_IF_ERROR (demangle_char (dm, 'E'));            d_append_char (dpi, '(');
3282        break;            d_print_cast (dpi, d_left (dc));
3283              d_append_char (dpi, ')');
3284            }
3285          d_append_char (dpi, '(');
3286          d_print_comp (dpi, d_right (dc));
3287          d_append_char (dpi, ')');
3288          return;
3289    
3290      case 'X':      case DEMANGLE_COMPONENT_BINARY:
3291        /* Expression.  */        if (d_right (dc)->type != DEMANGLE_COMPONENT_BINARY_ARGS)
3292        advance_char (dm);          {
3293        RETURN_IF_ERROR (demangle_expression (dm));            d_print_error (dpi);
3294        RETURN_IF_ERROR (demangle_char (dm, 'E'));            return;
3295        break;          }
3296    
3297          /* We wrap an expression which uses the greater-than operator in
3298             an extra layer of parens so that it does not get confused
3299             with the '>' which ends the template parameters.  */
3300          if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
3301              && d_left (dc)->u.s_operator.op->len == 1
3302              && d_left (dc)->u.s_operator.op->name[0] == '>')
3303            d_append_char (dpi, '(');
3304    
3305          d_append_char (dpi, '(');
3306          d_print_comp (dpi, d_left (d_right (dc)));
3307          d_append_string_constant (dpi, ") ");
3308          d_print_expr_op (dpi, d_left (dc));
3309          d_append_string_constant (dpi, " (");
3310          d_print_comp (dpi, d_right (d_right (dc)));
3311          d_append_char (dpi, ')');
3312    
3313          if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
3314              && d_left (dc)->u.s_operator.op->len == 1
3315              && d_left (dc)->u.s_operator.op->name[0] == '>')
3316            d_append_char (dpi, ')');
3317    
3318          return;
3319    
3320        case DEMANGLE_COMPONENT_BINARY_ARGS:
3321          /* We should only see this as part of DEMANGLE_COMPONENT_BINARY.  */
3322          d_print_error (dpi);
3323          return;
3324    
3325        case DEMANGLE_COMPONENT_TRINARY:
3326          if (d_right (dc)->type != DEMANGLE_COMPONENT_TRINARY_ARG1
3327              || d_right (d_right (dc))->type != DEMANGLE_COMPONENT_TRINARY_ARG2)
3328            {
3329              d_print_error (dpi);
3330              return;
3331            }
3332          d_append_char (dpi, '(');
3333          d_print_comp (dpi, d_left (d_right (dc)));
3334          d_append_string_constant (dpi, ") ");
3335          d_print_expr_op (dpi, d_left (dc));
3336          d_append_string_constant (dpi, " (");
3337          d_print_comp (dpi, d_left (d_right (d_right (dc))));
3338          d_append_string_constant (dpi, ") : (");
3339          d_print_comp (dpi, d_right (d_right (d_right (dc))));
3340          d_append_char (dpi, ')');
3341          return;
3342    
3343        case DEMANGLE_COMPONENT_TRINARY_ARG1:
3344        case DEMANGLE_COMPONENT_TRINARY_ARG2:
3345          /* We should only see these are part of DEMANGLE_COMPONENT_TRINARY.  */
3346          d_print_error (dpi);
3347          return;
3348    
3349        case DEMANGLE_COMPONENT_LITERAL:
3350        case DEMANGLE_COMPONENT_LITERAL_NEG:
3351          {
3352            enum d_builtin_type_print tp;
3353    
3354            /* For some builtin types, produce simpler output.  */
3355            tp = D_PRINT_DEFAULT;
3356            if (d_left (dc)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE)
3357              {
3358                tp = d_left (dc)->u.s_builtin.type->print;
3359                switch (tp)
3360                  {
3361                  case D_PRINT_INT:
3362                  case D_PRINT_UNSIGNED:
3363                  case D_PRINT_LONG:
3364                  case D_PRINT_UNSIGNED_LONG:
3365                  case D_PRINT_LONG_LONG:
3366                  case D_PRINT_UNSIGNED_LONG_LONG:
3367                    if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME)
3368                      {
3369                        if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
3370                          d_append_char (dpi, '-');
3371                        d_print_comp (dpi, d_right (dc));
3372                        switch (tp)
3373                          {
3374                          default:
3375                            break;
3376                          case D_PRINT_UNSIGNED:
3377                            d_append_char (dpi, 'u');
3378                            break;
3379                          case D_PRINT_LONG:
3380                            d_append_char (dpi, 'l');
3381                            break;
3382                          case D_PRINT_UNSIGNED_LONG:
3383                            d_append_string_constant (dpi, "ul");
3384                            break;
3385                          case D_PRINT_LONG_LONG:
3386                            d_append_string_constant (dpi, "ll");
3387                            break;
3388                          case D_PRINT_UNSIGNED_LONG_LONG:
3389                            d_append_string_constant (dpi, "ull");
3390                            break;
3391                          }
3392                        return;
3393                      }
3394                    break;
3395    
3396                  case D_PRINT_BOOL:
3397                    if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME
3398                        && d_right (dc)->u.s_name.len == 1
3399                        && dc->type == DEMANGLE_COMPONENT_LITERAL)
3400                      {
3401                        switch (d_right (dc)->u.s_name.s[0])
3402                          {
3403                          case '0':
3404                            d_append_string_constant (dpi, "false");
3405                            return;
3406                          case '1':
3407                            d_append_string_constant (dpi, "true");
3408                            return;
3409                          default:
3410                            break;
3411                          }
3412                      }
3413                    break;
3414    
3415                  default:
3416                    break;
3417                  }
3418              }
3419    
3420            d_append_char (dpi, '(');
3421            d_print_comp (dpi, d_left (dc));
3422            d_append_char (dpi, ')');
3423            if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
3424              d_append_char (dpi, '-');
3425            if (tp == D_PRINT_FLOAT)
3426              d_append_char (dpi, '[');
3427            d_print_comp (dpi, d_right (dc));
3428            if (tp == D_PRINT_FLOAT)
3429              d_append_char (dpi, ']');
3430          }
3431          return;
3432    
3433      default:      default:
3434        RETURN_IF_ERROR (demangle_type (dm));        d_print_error (dpi);
3435        break;        return;
3436      }      }
   
   return STATUS_OK;  
3437  }  }
3438    
3439  /* Demangles and emits an <expression>.  /* Print a Java dentifier.  For Java we try to handle encoded extended
3440       Unicode characters.  The C++ ABI doesn't mention Unicode encoding,
3441       so we don't it for C++.  Characters are encoded as
3442       __U<hex-char>+_.  */
3443    
3444      <expression> ::= <unary operator-name> <expression>  static void
3445                   ::= <binary operator-name> <expression> <expression>  d_print_java_identifier (dpi, name, len)
3446                   ::= <expr-primary>         struct d_print_info *dpi;
3447                   ::= <scope-expression>  */       const char *name;
3448         int len;
 static status_t  
 demangle_expression (dm)  
      demangling_t dm;  
3449  {  {
3450    char peek = peek_char (dm);    const char *p;
3451      const char *end;
   DEMANGLE_TRACE ("expression", dm);  
3452    
3453    if (peek == 'L' || peek == 'T')    end = name + len;
3454      RETURN_IF_ERROR (demangle_expr_primary (dm));    for (p = name; p < end; ++p)
   else if (peek == 's' && peek_char_next (dm) == 'r')  
     RETURN_IF_ERROR (demangle_scope_expression (dm));  
   else  
     /* An operator expression.  */  
3455      {      {
3456        int num_args;        if (end - p > 3
3457        int type_arg;            && p[0] == '_'
3458        status_t status = STATUS_OK;            && p[1] == '_'
3459        dyn_string_t operator_name;            && p[2] == 'U')
   
       /* We have an operator name.  Since we want to output binary  
          operations in infix notation, capture the operator name  
          first.  */  
       RETURN_IF_ERROR (result_push (dm));  
       RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args,  
                                                &type_arg));  
       operator_name = (dyn_string_t) result_pop (dm);  
   
       /* If it's binary, do an operand first.  */  
       if (num_args > 1)  
         {  
           status = result_add_char (dm, '(');  
           if (STATUS_NO_ERROR (status))  
             status = demangle_expression (dm);  
           if (STATUS_NO_ERROR (status))  
             status = result_add_char (dm, ')');  
         }  
   
       /* Emit the operator.  */    
       if (STATUS_NO_ERROR (status))  
         status = result_add_string (dm, operator_name);  
       dyn_string_delete (operator_name);  
       RETURN_IF_ERROR (status);  
         
       /* Emit its second (if binary) or only (if unary) operand.  */  
       RETURN_IF_ERROR (result_add_char (dm, '('));  
       if (type_arg)  
         RETURN_IF_ERROR (demangle_type (dm));  
       else  
         RETURN_IF_ERROR (demangle_expression (dm));  
       RETURN_IF_ERROR (result_add_char (dm, ')'));  
   
       /* The ternary operator takes a third operand.  */  
       if (num_args == 3)  
3460          {          {
3461            RETURN_IF_ERROR (result_add (dm, ":("));            unsigned long c;
3462            RETURN_IF_ERROR (demangle_expression (dm));            const char *q;
3463            RETURN_IF_ERROR (result_add_char (dm, ')'));  
3464              c = 0;
3465              for (q = p + 3; q < end; ++q)
3466                {
3467                  int dig;
3468    
3469                  if (IS_DIGIT (*q))
3470                    dig = *q - '0';
3471                  else if (*q >= 'A' && *q <= 'F')
3472                    dig = *q - 'A' + 10;
3473                  else if (*q >= 'a' && *q <= 'f')
3474                    dig = *q - 'a' + 10;
3475                  else
3476                    break;
3477    
3478                  c = c * 16 + dig;
3479                }
3480              /* If the Unicode character is larger than 256, we don't try
3481                 to deal with it here.  FIXME.  */
3482              if (q < end && *q == '_' && c < 256)
3483                {
3484                  d_append_char (dpi, c);
3485                  p = q;
3486                  continue;
3487                }
3488          }          }
     }  
3489    
3490    return STATUS_OK;        d_append_char (dpi, *p);
3491        }
3492  }  }
3493    
3494  /* Demangles and emits a <scope-expression>.    /* Print a list of modifiers.  SUFFIX is 1 if we are printing
3495       qualifiers on this after printing a function.  */
3496    
3497      <scope-expression> ::= sr <qualifying type> <source-name>  static void
3498                         ::= sr <qualifying type> <encoding>  */  d_print_mod_list (dpi, mods, suffix)
3499         struct d_print_info *dpi;
3500  static status_t       struct d_print_mod *mods;
3501  demangle_scope_expression (dm)       int suffix;
      demangling_t dm;  
3502  {  {
3503    RETURN_IF_ERROR (demangle_char (dm, 's'));    struct d_print_template *hold_dpt;
   RETURN_IF_ERROR (demangle_char (dm, 'r'));  
   RETURN_IF_ERROR (demangle_type (dm));  
   RETURN_IF_ERROR (result_add (dm, "::"));  
   RETURN_IF_ERROR (demangle_encoding (dm));  
   return STATUS_OK;  
 }  
3504    
3505  /* Demangles and emits an <expr-primary>.      if (mods == NULL || d_print_saw_error (dpi))
3506        return;
3507    
3508      <expr-primary> ::= <template-param>    if (mods->printed
3509                     ::= L <type> <value number> E  # literal        || (! suffix
3510                     ::= L <mangled-name> E         # external name  */            && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS
3511                  || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
3512                  || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS)))
3513        {
3514          d_print_mod_list (dpi, mods->next, suffix);
3515          return;
3516        }
3517    
3518  static status_t    mods->printed = 1;
 demangle_expr_primary (dm)  
      demangling_t dm;  
 {  
   char peek = peek_char (dm);  
3519    
3520    DEMANGLE_TRACE ("expr-primary", dm);    hold_dpt = dpi->templates;
3521      dpi->templates = mods->templates;
3522    
3523    if (peek == 'T')    if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
     RETURN_IF_ERROR (demangle_template_param (dm));  
   else if (peek == 'L')  
3524      {      {
3525        /* Consume the `L'.  */        d_print_function_type (dpi, mods->mod, mods->next);
3526        advance_char (dm);        dpi->templates = hold_dpt;
3527        peek = peek_char (dm);        return;
3528        }
3529      else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
3530        {
3531          d_print_array_type (dpi, mods->mod, mods->next);
3532          dpi->templates = hold_dpt;
3533          return;
3534        }
3535      else if (mods->mod->type == DEMANGLE_COMPONENT_LOCAL_NAME)
3536        {
3537          struct d_print_mod *hold_modifiers;
3538          struct demangle_component *dc;
3539    
3540          /* When this is on the modifier stack, we have pulled any
3541             qualifiers off the right argument already.  Otherwise, we
3542             print it as usual, but don't let the left argument see any
3543             modifiers.  */
3544    
3545          hold_modifiers = dpi->modifiers;
3546          dpi->modifiers = NULL;
3547          d_print_comp (dpi, d_left (mods->mod));
3548          dpi->modifiers = hold_modifiers;
3549    
3550        if (peek == '_')        if ((dpi->options & DMGL_JAVA) == 0)
3551          RETURN_IF_ERROR (demangle_mangled_name (dm));          d_append_string_constant (dpi, "::");
3552        else        else
3553          RETURN_IF_ERROR (demangle_literal (dm));          d_append_char (dpi, '.');
3554    
3555        RETURN_IF_ERROR (demangle_char (dm, 'E'));        dc = d_right (mods->mod);
3556          while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
3557                 || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
3558                 || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
3559            dc = d_left (dc);
3560    
3561          d_print_comp (dpi, dc);
3562    
3563          dpi->templates = hold_dpt;
3564          return;
3565      }      }
   else  
     return STATUS_ERROR;  
3566    
3567    return STATUS_OK;    d_print_mod (dpi, mods->mod);
3568    
3569      dpi->templates = hold_dpt;
3570    
3571      d_print_mod_list (dpi, mods->next, suffix);
3572  }  }
3573    
3574  /* Demangles and emits a <substitution>.  Sets *TEMPLATE_P to non-zero  /* Print a modifier.  */
    if the substitution is the name of a template, zero otherwise.  
3575    
3576       <substitution> ::= S <seq-id> _  static void
3577                      ::= S_  d_print_mod (dpi, mod)
3578         struct d_print_info *dpi;
3579                      ::= St   # ::std::       const struct demangle_component *mod;
3580                      ::= Sa   # ::std::allocator  {
3581                      ::= Sb   # ::std::basic_string    switch (mod->type)
3582                      ::= Ss   # ::std::basic_string<char,      {
3583                                                     ::std::char_traits<char>,      case DEMANGLE_COMPONENT_RESTRICT:
3584                                                     ::std::allocator<char> >      case DEMANGLE_COMPONENT_RESTRICT_THIS:
3585                      ::= Si   # ::std::basic_istream<char,          d_append_string_constant (dpi, " restrict");
3586                                                      std::char_traits<char> >        return;
3587                      ::= So   # ::std::basic_ostream<char,        case DEMANGLE_COMPONENT_VOLATILE:
3588                                                      std::char_traits<char> >      case DEMANGLE_COMPONENT_VOLATILE_THIS:
3589                      ::= Sd   # ::std::basic_iostream<char,        d_append_string_constant (dpi, " volatile");
3590                                                      std::char_traits<char> >        return;
3591  */      case DEMANGLE_COMPONENT_CONST:
3592        case DEMANGLE_COMPONENT_CONST_THIS:
3593          d_append_string_constant (dpi, " const");
3594          return;
3595        case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
3596          d_append_char (dpi, ' ');
3597          d_print_comp (dpi, d_right (mod));
3598          return;
3599        case DEMANGLE_COMPONENT_POINTER:
3600          /* There is no pointer symbol in Java.  */
3601          if ((dpi->options & DMGL_JAVA) == 0)
3602            d_append_char (dpi, '*');
3603          return;
3604        case DEMANGLE_COMPONENT_REFERENCE:
3605          d_append_char (dpi, '&');
3606          return;
3607        case DEMANGLE_COMPONENT_COMPLEX:
3608          d_append_string_constant (dpi, "complex ");
3609          return;
3610        case DEMANGLE_COMPONENT_IMAGINARY:
3611          d_append_string_constant (dpi, "imaginary ");
3612          return;
3613        case DEMANGLE_COMPONENT_PTRMEM_TYPE:
3614          if (d_last_char (dpi) != '(')
3615            d_append_char (dpi, ' ');
3616          d_print_comp (dpi, d_left (mod));
3617          d_append_string_constant (dpi, "::*");
3618          return;
3619        case DEMANGLE_COMPONENT_TYPED_NAME:
3620          d_print_comp (dpi, d_left (mod));
3621          return;
3622        default:
3623          /* Otherwise, we have something that won't go back on the
3624             modifier stack, so we can just print it.  */
3625          d_print_comp (dpi, mod);
3626          return;
3627        }
3628    }
3629    
3630  static status_t  /* Print a function type, except for the return type.  */
3631  demangle_substitution (dm, template_p)  
3632       demangling_t dm;  static void
3633       int *template_p;  d_print_function_type (dpi, dc, mods)
3634  {       struct d_print_info *dpi;
3635    int seq_id;       const struct demangle_component *dc;
3636    int peek;       struct d_print_mod *mods;
3637    dyn_string_t text;  {
3638      int need_paren;
3639    DEMANGLE_TRACE ("substitution", dm);    int saw_mod;
3640      int need_space;
3641    RETURN_IF_ERROR (demangle_char (dm, 'S'));    struct d_print_mod *p;
3642      struct d_print_mod *hold_modifiers;
3643    /* Scan the substitution sequence index.  A missing number denotes  
3644       the first index.  */    need_paren = 0;
3645    peek = peek_char (dm);    saw_mod = 0;
3646    if (peek == '_')    need_space = 0;
3647      seq_id = -1;    for (p = mods; p != NULL; p = p->next)
   /* If the following character is 0-9 or a capital letter, interpret  
      the sequence up to the next underscore as a base-36 substitution  
      index.  */  
   else if (IS_DIGIT ((unsigned char) peek)  
            || (peek >= 'A' && peek <= 'Z'))  
     RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));  
   else  
3648      {      {
3649        const char *new_last_source_name = NULL;        if (p->printed)
3650            break;
3651    
3652        switch (peek)        saw_mod = 1;
3653          switch (p->mod->type)
3654          {          {
3655          case 't':          case DEMANGLE_COMPONENT_POINTER:
3656            RETURN_IF_ERROR (result_add (dm, "std"));          case DEMANGLE_COMPONENT_REFERENCE:
3657              need_paren = 1;
3658            break;            break;
3659            case DEMANGLE_COMPONENT_RESTRICT:
3660          case 'a':          case DEMANGLE_COMPONENT_VOLATILE:
3661            RETURN_IF_ERROR (result_add (dm, "std::allocator"));          case DEMANGLE_COMPONENT_CONST:
3662            new_last_source_name = "allocator";          case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
3663            *template_p = 1;          case DEMANGLE_COMPONENT_COMPLEX:
3664            case DEMANGLE_COMPONENT_IMAGINARY:
3665            case DEMANGLE_COMPONENT_PTRMEM_TYPE:
3666              need_space = 1;
3667              need_paren = 1;
3668            break;            break;
3669            case DEMANGLE_COMPONENT_RESTRICT_THIS:
3670          case 'b':          case DEMANGLE_COMPONENT_VOLATILE_THIS:
3671            RETURN_IF_ERROR (result_add (dm, "std::basic_string"));          case DEMANGLE_COMPONENT_CONST_THIS:
           new_last_source_name = "basic_string";  
           *template_p = 1;  
3672            break;            break;
3673                      default:
         case 's':  
           if (!flag_verbose)  
             {  
               RETURN_IF_ERROR (result_add (dm, "std::string"));  
               new_last_source_name = "string";  
             }  
           else  
             {  
               RETURN_IF_ERROR (result_add (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));  
               new_last_source_name = "basic_string";  
             }  
           *template_p = 0;  
3674            break;            break;
3675            }
3676          if (need_paren)
3677            break;
3678        }
3679    
3680          case 'i':    if (d_left (dc) != NULL && ! saw_mod)
3681            if (!flag_verbose)      need_paren = 1;
             {  
               RETURN_IF_ERROR (result_add (dm, "std::istream"));  
               new_last_source_name = "istream";  
             }  
           else  
             {  
               RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traints<char> >"));  
               new_last_source_name = "basic_istream";  
             }  
           *template_p = 0;  
           break;  
3682    
3683          case 'o':    if (need_paren)
3684            if (!flag_verbose)      {
3685              {        if (! need_space)
3686                RETURN_IF_ERROR (result_add (dm, "std::ostream"));          {
3687                new_last_source_name = "ostream";            if (d_last_char (dpi) != '('
3688              }                && d_last_char (dpi) != '*')
3689            else              need_space = 1;
3690              {          }
3691                RETURN_IF_ERROR (result_add (dm, "std::basic_ostream<char, std::char_traits<char> >"));        if (need_space && d_last_char (dpi) != ' ')
3692                new_last_source_name = "basic_ostream";          d_append_char (dpi, ' ');
3693              }        d_append_char (dpi, '(');
3694            *template_p = 0;      }
           break;  
3695    
3696          case 'd':    hold_modifiers = dpi->modifiers;
3697            if (!flag_verbose)    dpi->modifiers = NULL;
             {  
               RETURN_IF_ERROR (result_add (dm, "std::iostream"));  
               new_last_source_name = "iostream";  
             }  
           else  
             {  
               RETURN_IF_ERROR (result_add (dm, "std::basic_iostream<char, std::char_traits<char> >"));  
               new_last_source_name = "basic_iostream";  
             }  
           *template_p = 0;  
           break;  
3698    
3699          default:    d_print_mod_list (dpi, mods, 0);
3700            return "Unrecognized <substitution>.";  
3701          }    if (need_paren)
3702              d_append_char (dpi, ')');
3703        /* Consume the character we just processed.  */  
3704        advance_char (dm);    d_append_char (dpi, '(');
3705    
3706      if (d_right (dc) != NULL)
3707        d_print_comp (dpi, d_right (dc));
3708    
3709      d_append_char (dpi, ')');
3710    
3711        if (new_last_source_name != NULL)    d_print_mod_list (dpi, mods, 1);
3712    
3713      dpi->modifiers = hold_modifiers;
3714    }
3715    
3716    /* Print an array type, except for the element type.  */
3717    
3718    static void
3719    d_print_array_type (dpi, dc, mods)
3720         struct d_print_info *dpi;
3721         const struct demangle_component *dc;
3722         struct d_print_mod *mods;
3723    {
3724      int need_space;
3725    
3726      need_space = 1;
3727      if (mods != NULL)
3728        {
3729          int need_paren;
3730          struct d_print_mod *p;
3731    
3732          need_paren = 0;
3733          for (p = mods; p != NULL; p = p->next)
3734          {          {
3735            if (!dyn_string_copy_cstr (dm->last_source_name,            if (! p->printed)
3736                                       new_last_source_name))              {
3737              return STATUS_ALLOCATION_FAILED;                if (p->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
3738                    {
3739                      need_space = 0;
3740                      break;
3741                    }
3742                  else
3743                    {
3744                      need_paren = 1;
3745                      need_space = 1;
3746                      break;
3747                    }
3748                }
3749          }          }
3750    
3751        return STATUS_OK;        if (need_paren)
3752            d_append_string_constant (dpi, " (");
3753    
3754          d_print_mod_list (dpi, mods, 0);
3755    
3756          if (need_paren)
3757            d_append_char (dpi, ')');
3758      }      }
3759    
3760    /* Look up the substitution text.  Since `S_' is the most recent    if (need_space)
3761       substitution, `S0_' is the second-most-recent, etc., shift the      d_append_char (dpi, ' ');
      numbering by one.  */  
   text = substitution_get (dm, seq_id + 1, template_p);  
   if (text == NULL)  
     return "Substitution number out of range.";  
3762    
3763    /* Emit the substitution text.  */    d_append_char (dpi, '[');
   RETURN_IF_ERROR (result_add_string (dm, text));  
3764    
3765    RETURN_IF_ERROR (demangle_char (dm, '_'));    if (d_left (dc) != NULL)
3766    return STATUS_OK;      d_print_comp (dpi, d_left (dc));
 }  
3767    
3768  /* Demangles and emits a <local-name>.      d_append_char (dpi, ']');
3769    }
3770    
3771      <local-name> := Z <function encoding> E <entity name> [<discriminator>]  /* Print an operator in an expression.  */
                  := Z <function encoding> E s [<discriminator>]  */  
3772    
3773  static status_t  static void
3774  demangle_local_name (dm)  d_print_expr_op (dpi, dc)
3775       demangling_t dm;       struct d_print_info *dpi;
3776  {       const struct demangle_component *dc;
3777    DEMANGLE_TRACE ("local-name", dm);  {
3778      if (dc->type == DEMANGLE_COMPONENT_OPERATOR)
3779        d_append_buffer (dpi, dc->u.s_operator.op->name,
3780                         dc->u.s_operator.op->len);
3781      else
3782        d_print_comp (dpi, dc);
3783    }
3784    
3785    RETURN_IF_ERROR (demangle_char (dm, 'Z'));  /* Print a cast.  */
   RETURN_IF_ERROR (demangle_encoding (dm));  
   RETURN_IF_ERROR (demangle_char (dm, 'E'));  
   RETURN_IF_ERROR (result_add (dm, "::"));  
3786    
3787    if (peek_char (dm) == 's')  static void
3788      {  d_print_cast (dpi, dc)
3789        /* Local character string literal.  */       struct d_print_info *dpi;
3790        RETURN_IF_ERROR (result_add (dm, "string literal"));       const struct demangle_component *dc;
3791        /* Consume the s.  */  {
3792        advance_char (dm);    if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
3793        RETURN_IF_ERROR (demangle_discriminator (dm, 0));      d_print_comp (dpi, d_left (dc));
     }  
3794    else    else
3795      {      {
3796        int unused;        struct d_print_mod *hold_dpm;
3797        /* Local name for some other entity.  Demangle its name.  */        struct d_print_template dpt;
3798        RETURN_IF_ERROR (demangle_name (dm, &unused));  
3799        RETURN_IF_ERROR (demangle_discriminator (dm, 1));        /* It appears that for a templated cast operator, we need to put
3800       }           the template parameters in scope for the operator name, but
3801             not for the parameters.  The effect is that we need to handle
3802     return STATUS_OK;           the template printing here.  */
3803   }  
3804          hold_dpm = dpi->modifiers;
3805   /* Optimonally demangles and emits a <discriminator>.  If there is no        dpi->modifiers = NULL;
3806      <discriminator> at the current position in the mangled string, the  
3807      descriminator is assumed to be zero.  Emit the discriminator number        dpt.next = dpi->templates;
3808      in parentheses, unless SUPPRESS_FIRST is non-zero and the        dpi->templates = &dpt;
3809      discriminator is zero.          dpt.template = d_left (dc);
3810    
3811       <discriminator> ::= _ <number>  */        d_print_comp (dpi, d_left (d_left (dc)));
3812    
3813  static status_t        dpi->templates = dpt.next;
3814  demangle_discriminator (dm, suppress_first)  
3815       demangling_t dm;        if (d_last_char (dpi) == '<')
3816       int suppress_first;          d_append_char (dpi, ' ');
3817  {        d_append_char (dpi, '<');
3818    /* Output for <discriminator>s to the demangled name is completely        d_print_comp (dpi, d_right (d_left (dc)));
3819       suppressed if not in verbose mode.  */        /* Avoid generating two consecutive '>' characters, to avoid
3820             the C++ syntactic ambiguity.  */
3821    if (peek_char (dm) == '_')        if (d_last_char (dpi) == '>')
3822      {          d_append_char (dpi, ' ');
3823        /* Consume the underscore.  */        d_append_char (dpi, '>');
3824        advance_char (dm);  
3825        if (flag_verbose)        dpi->modifiers = hold_dpm;
         RETURN_IF_ERROR (result_add (dm, " [#"));  
       /* Check if there's a number following the underscore.  */  
       if (IS_DIGIT ((unsigned char) peek_char (dm)))  
         {  
           int discriminator;  
           /* Demangle the number.  */  
           RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));  
           if (flag_verbose)  
             /* Write the discriminator.  The mangled number is two  
                less than the discriminator ordinal, counting from  
                zero.  */  
             RETURN_IF_ERROR (int_to_dyn_string (discriminator + 1,  
                                                 (dyn_string_t) dm->result));  
         }  
       else  
         return STATUS_ERROR;  
       if (flag_verbose)  
         RETURN_IF_ERROR (result_add_char (dm, ']'));  
     }  
   else if (!suppress_first)  
     {  
       if (flag_verbose)  
         RETURN_IF_ERROR (result_add (dm, " [#0]"));  
3826      }      }
3827    }
3828    
3829    /* Initialize the information structure we use to pass around
3830       information.  */
3831    
3832    CP_STATIC_IF_GLIBCPP_V3
3833    void
3834    cplus_demangle_init_info (mangled, options, len, di)
3835         const char *mangled;
3836         int options;
3837         size_t len;
3838         struct d_info *di;
3839    {
3840      di->s = mangled;
3841      di->send = mangled + len;
3842      di->options = options;
3843    
3844    return STATUS_OK;    di->n = mangled;
3845    
3846      /* We can not need more components than twice the number of chars in
3847         the mangled string.  Most components correspond directly to
3848         chars, but the ARGLIST types are exceptions.  */
3849      di->num_comps = 2 * len;
3850      di->next_comp = 0;
3851    
3852      /* Similarly, we can not need more substitutions than there are
3853         chars in the mangled string.  */
3854      di->num_subs = len;
3855      di->next_sub = 0;
3856      di->did_subs = 0;
3857    
3858      di->last_name = NULL;
3859    
3860      di->expansion = 0;
3861  }  }
3862    
3863  /* Demangle NAME into RESULT, which must be an initialized  /* Entry point for the demangler.  If MANGLED is a g++ v3 ABI mangled
3864     dyn_string_t.  On success, returns STATUS_OK.  On failure, returns     name, return a buffer allocated with malloc holding the demangled
3865     an error message, and the contents of RESULT are unchanged.  */     name.  OPTIONS is the usual libiberty demangler options.  On
3866       success, this sets *PALC to the allocated size of the returned
3867       buffer.  On failure, this sets *PALC to 0 for a bad name, or 1 for
3868       a memory allocation failure.  On failure, this returns NULL.  */
3869    
3870  static status_t  static char *
3871  cp_demangle (name, result, style)  d_demangle (mangled, options, palc)
3872       const char *name;       const char* mangled;
3873       dyn_string_t result;       int options;
3874       int style;       size_t *palc;
3875  {  {
3876    status_t status;    size_t len;
3877    int length = strlen (name);    int type;
3878      struct d_info di;
3879      struct demangle_component *dc;
3880      int estimate;
3881      char *ret;
3882    
3883    if (length > 2 && name[0] == '_' && name[1] == 'Z')    *palc = 0;
     {  
       demangling_t dm = demangling_new (name, style);  
       if (dm == NULL)  
         return STATUS_ALLOCATION_FAILED;  
3884    
3885        status = result_push (dm);    len = strlen (mangled);
       if (status != STATUS_OK)  
         {  
           demangling_delete (dm);  
           return status;  
         }  
3886    
3887        status = demangle_mangled_name (dm);    if (mangled[0] == '_' && mangled[1] == 'Z')
3888        if (STATUS_NO_ERROR (status))      type = 0;
3889      else if (strncmp (mangled, "_GLOBAL_", 8) == 0
3890               && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$')
3891               && (mangled[9] == 'D' || mangled[9] == 'I')
3892               && mangled[10] == '_')
3893        {
3894          char *r;
3895    
3896          r = malloc (40 + len - 11);
3897          if (r == NULL)
3898            *palc = 1;
3899          else
3900          {          {
3901            dyn_string_t demangled = (dyn_string_t) result_pop (dm);            if (mangled[9] == 'I')
3902            if (!dyn_string_copy (result, demangled))              strcpy (r, "global constructors keyed to ");
3903              return STATUS_ALLOCATION_FAILED;            else
3904            dyn_string_delete (demangled);              strcpy (r, "global destructors keyed to ");
3905              strcat (r, mangled + 11);
3906          }          }
3907                return r;
       demangling_delete (dm);  
3908      }      }
3909    else    else
3910      {      {
3911        /* It's evidently not a mangled C++ name.  It could be the name        if ((options & DMGL_TYPES) == 0)
3912           of something with C linkage, though, so just copy NAME into          return NULL;
3913           RESULT.  */        type = 1;
       if (!dyn_string_copy_cstr (result, name))  
         return STATUS_ALLOCATION_FAILED;  
       status = STATUS_OK;  
3914      }      }
3915    
3916    return status;    cplus_demangle_init_info (mangled, options, len, &di);
 }  
3917    
3918  /* Demangle TYPE_NAME into RESULT, which must be an initialized    {
3919     dyn_string_t.  On success, returns STATUS_OK.  On failiure, returns  #ifdef CP_DYNAMIC_ARRAYS
3920     an error message, and the contents of RESULT are unchanged.  */      __extension__ struct demangle_component comps[di.num_comps];
3921        __extension__ struct demangle_component *subs[di.num_subs];
3922    
3923  static status_t      di.comps = &comps[0];
3924  cp_demangle_type (type_name, result)      di.subs = &subs[0];
3925       const char* type_name;  #else
3926       dyn_string_t result;      di.comps = ((struct demangle_component *)
3927  {                  malloc (di.num_comps * sizeof (struct demangle_component)));
3928    status_t status;      di.subs = ((struct demangle_component **)
3929    demangling_t dm = demangling_new (type_name, DMGL_GNU_V3);                 malloc (di.num_subs * sizeof (struct demangle_component *)));
3930          if (di.comps == NULL || di.subs == NULL)
3931    if (dm == NULL)        {
3932      return STATUS_ALLOCATION_FAILED;          if (di.comps != NULL)
3933              free (di.comps);
3934            if (di.subs != NULL)
3935              free (di.subs);
3936            *palc = 1;
3937            return NULL;
3938          }
3939    #endif
3940    
3941    /* Demangle the type name.  The demangled name is stored in dm.  */      if (! type)
3942    status = result_push (dm);        dc = cplus_demangle_mangled_name (&di, 1);
3943    if (status != STATUS_OK)      else
3944      {        dc = cplus_demangle_type (&di);
3945        demangling_delete (dm);  
3946        return status;      /* If DMGL_PARAMS is set, then if we didn't consume the entire
3947      }         mangled string, then we didn't successfully demangle it.  If
3948           DMGL_PARAMS is not set, we didn't look at the trailing
3949           parameters.  */
3950        if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0')
3951          dc = NULL;
3952    
3953    status = demangle_type (dm);  #ifdef CP_DEMANGLE_DEBUG
3954        if (dc == NULL)
3955          printf ("failed demangling\n");
3956        else
3957          d_dump (dc, 0);
3958    #endif
3959    
3960    if (STATUS_NO_ERROR (status))      /* We try to guess the length of the demangled string, to minimize
3961      {         calls to realloc during demangling.  */
3962        /* The demangling succeeded.  Pop the result out of dm and copy      estimate = len + di.expansion + 10 * di.did_subs;
3963           it into RESULT.  */      estimate += estimate / 8;
3964        dyn_string_t demangled = (dyn_string_t) result_pop (dm);  
3965        if (!dyn_string_copy (result, demangled))      ret = NULL;
3966          return STATUS_ALLOCATION_FAILED;      if (dc != NULL)
3967        dyn_string_delete (demangled);        ret = cplus_demangle_print (options, dc, estimate, palc);
3968      }  
3969    #ifndef CP_DYNAMIC_ARRAYS
3970        free (di.comps);
3971        free (di.subs);
3972    #endif
3973    
3974    /* Clean up.  */  #ifdef CP_DEMANGLE_DEBUG
3975    demangling_delete (dm);      if (ret != NULL)
3976          {
3977            int rlen;
3978    
3979    return status;          rlen = strlen (ret);
3980            if (rlen > 2 * estimate)
3981              printf ("*** Length %d much greater than estimate %d\n",
3982                      rlen, estimate);
3983            else if (rlen > estimate)
3984              printf ("*** Length %d greater than estimate %d\n",
3985                      rlen, estimate);
3986            else if (rlen < estimate / 2)
3987              printf ("*** Length %d much less than estimate %d\n",
3988                      rlen, estimate);
3989          }
3990    #endif
3991      }
3992    
3993      return ret;
3994  }  }
3995    
3996  #if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)  #if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
3997    
3998  extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));  extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
3999    
4000  /* ia64 ABI-mandated entry point in the C++ runtime library for performing  /* ia64 ABI-mandated entry point in the C++ runtime library for
4001     demangling.  MANGLED_NAME is a NUL-terminated character string     performing demangling.  MANGLED_NAME is a NUL-terminated character
4002     containing the name to be demangled.       string containing the name to be demangled.
4003    
4004     OUTPUT_BUFFER is a region of memory, allocated with malloc, of     OUTPUT_BUFFER is a region of memory, allocated with malloc, of
4005     *LENGTH bytes, into which the demangled name is stored.  If     *LENGTH bytes, into which the demangled name is stored.  If
4006     OUTPUT_BUFFER is not long enough, it is expanded using realloc.     OUTPUT_BUFFER is not long enough, it is expanded using realloc.
4007     OUTPUT_BUFFER may instead be NULL; in that case, the demangled name     OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
4008     is placed in a region of memory allocated with malloc.       is placed in a region of memory allocated with malloc.
4009    
4010     If LENGTH is non-NULL, the length of the buffer conaining the     If LENGTH is non-NULL, the length of the buffer conaining the
4011     demangled name, is placed in *LENGTH.       demangled name, is placed in *LENGTH.
4012    
4013     The return value is a pointer to the start of the NUL-terminated     The return value is a pointer to the start of the NUL-terminated
4014     demangled name, or NULL if the demangling fails.  The caller is     demangled name, or NULL if the demangling fails.  The caller is
4015     responsible for deallocating this memory using free.       responsible for deallocating this memory using free.
4016    
4017     *STATUS is set to one of the following values:     *STATUS is set to one of the following values:
4018        0: The demangling operation succeeded.        0: The demangling operation succeeded.
4019       -1: A memory allocation failiure occurred.       -1: A memory allocation failure occurred.
4020       -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.       -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
4021       -3: One of the arguments is invalid.       -3: One of the arguments is invalid.
4022    
4023     The demagling is performed using the C++ ABI mangling rules, with     The demangling is performed using the C++ ABI mangling rules, with
4024     GNU extensions.  */     GNU extensions.  */
4025    
4026  char *  char *
# Line 3674  __cxa_demangle (mangled_name, output_buf Line 4030  __cxa_demangle (mangled_name, output_buf
4030       size_t *length;       size_t *length;
4031       int *status;       int *status;
4032  {  {
4033    struct dyn_string demangled_name;    char *demangled;
4034    status_t result;    size_t alc;
   
   if (status == NULL)  
     return NULL;  
4035    
4036    if (mangled_name == NULL) {    if (mangled_name == NULL)
4037      *status = -3;      {
4038      return NULL;        if (status != NULL)
4039    }          *status = -3;
4040          return NULL;
4041        }
4042    
4043    /* Did the caller provide a buffer for the demangled name?  */    if (output_buffer != NULL && length == NULL)
4044    if (output_buffer == NULL) {      {
4045      /* No; dyn_string will malloc a buffer for us.  */        if (status != NULL)
4046      if (!dyn_string_init (&demangled_name, 0))          *status = -3;
       {  
         *status = -1;  
         return NULL;  
       }  
   }  
   else {  
     /* Yes.  Check that the length was provided.  */  
     if (length == NULL) {  
       *status = -3;  
4047        return NULL;        return NULL;
4048      }      }
     /* Install the buffer into a dyn_string.  */  
     demangled_name.allocated = *length;  
     demangled_name.length = 0;  
     demangled_name.s = output_buffer;  
   }  
4049    
4050    if (mangled_name[0] == '_' && mangled_name[1] == 'Z')    demangled = d_demangle (mangled_name, DMGL_PARAMS | DMGL_TYPES, &alc);
     /* MANGLED_NAME apprears to be a function or variable name.  
        Demangle it accordingly.  */  
     result = cp_demangle (mangled_name, &demangled_name, 0);  
   else  
     /* Try to demangled MANGLED_NAME as the name of a type.  */  
     result = cp_demangle_type (mangled_name, &demangled_name);  
4051    
4052    if (result == STATUS_OK)    if (demangled == NULL)
     /* The demangling succeeded.  */  
     {  
       /* If LENGTH isn't NULL, store the allocated buffer length  
          there; the buffer may have been realloced by dyn_string  
          functions.  */  
       if (length != NULL)  
         *length = demangled_name.allocated;  
       /* The operation was a success.  */  
       *status = 0;  
       return dyn_string_buf (&demangled_name);  
     }  
   else if (result == STATUS_ALLOCATION_FAILED)  
     /* A call to malloc or realloc failed during the demangling  
        operation.  */  
4053      {      {
4054        *status = -1;        if (status != NULL)
4055            {
4056              if (alc == 1)
4057                *status = -1;
4058              else
4059                *status = -2;
4060            }
4061        return NULL;        return NULL;
4062      }      }
4063    
4064      if (output_buffer == NULL)
4065        {
4066          if (length != NULL)
4067            *length = alc;
4068        }
4069    else    else
     /* The demangling failed for another reason, most probably because  
        MANGLED_NAME isn't a valid mangled name.  */  
4070      {      {
4071        /* If the buffer containing the demangled name wasn't provided        if (strlen (demangled) < *length)
4072           by the caller, free it.  */          {
4073        if (output_buffer == NULL)            strcpy (output_buffer, demangled);
4074          free (dyn_string_buf (&demangled_name));            free (demangled);
4075        *status = -2;            demangled = output_buffer;
4076        return NULL;          }
4077          else
4078            {
4079              free (output_buffer);
4080              *length = alc;
4081            }
4082      }      }
4083    
4084      if (status != NULL)
4085        *status = 0;
4086    
4087      return demangled;
4088  }  }
4089    
4090  #else /* ! (IN_LIBGCC2 || IN_GLIBCPP_V3) */  #else /* ! (IN_LIBGCC2 || IN_GLIBCPP_V3) */
4091    
4092  /* Variant entry point for integration with the existing cplus-dem  /* Entry point for libiberty demangler.  If MANGLED is a g++ v3 ABI
4093     demangler.  Attempts to demangle MANGLED.  If the demangling     mangled name, return a buffer allocated with malloc holding the
4094     succeeds, returns a buffer, allocated with malloc, containing the     demangled name.  Otherwise, return NULL.  */
    demangled name.  The caller must deallocate the buffer using free.  
    If the demangling failes, returns NULL.  */  
4095    
4096  char *  char *
4097  cplus_demangle_v3 (mangled, options)  cplus_demangle_v3 (mangled, options)
4098       const char* mangled;       const char* mangled;
4099       int options;       int options;
4100  {  {
4101    dyn_string_t demangled;    size_t alc;
   status_t status;  
   int type = !!(options & DMGL_TYPES);  
4102    
4103    if (mangled[0] == '_' && mangled[1] == 'Z')    return d_demangle (mangled, options, &alc);
     /* It is not a type.  */  
     type = 0;  
   else  
     {  
       /* It is a type. Stop if we don't want to demangle types. */  
       if (!type)  
         return NULL;  
     }  
   
   flag_verbose = !!(options & DMGL_VERBOSE);  
   
   /* Create a dyn_string to hold the demangled name.  */  
   demangled = dyn_string_new (0);  
   /* Attempt the demangling.  */  
   if (!type)  
     /* Appears to be a function or variable name.  */  
     status = cp_demangle (mangled, demangled, 0);  
   else  
     /* Try to demangle it as the name of a type.  */  
     status = cp_demangle_type (mangled, demangled);  
   
   if (STATUS_NO_ERROR (status))  
     /* Demangling succeeded.  */  
     {  
       /* Grab the demangled result from the dyn_string.  It was  
          allocated with malloc, so we can return it directly.  */  
       char *return_value = dyn_string_release (demangled);  
       /* Hand back the demangled name.  */  
       return return_value;  
     }  
   else if (status == STATUS_ALLOCATION_FAILED)  
     {  
       fprintf (stderr, "Memory allocation failed.\n");  
       abort ();  
     }  
   else  
     /* Demangling failed.  */  
     {  
       dyn_string_delete (demangled);  
       return NULL;  
     }  
4104  }  }
4105    
4106  /* Demangle a Java symbol.  Java uses a subset of the V3 ABI C++ mangling  /* Demangle a Java symbol.  Java uses a subset of the V3 ABI C++ mangling
# Line 3818  char * Line 4114  char *
4114  java_demangle_v3 (mangled)  java_demangle_v3 (mangled)
4115       const char* mangled;       const char* mangled;
4116  {  {
4117    dyn_string_t demangled;    size_t alc;
4118    char *next;    char *demangled;
4119    char *end;    int nesting;
4120    int len;    char *from;
4121    status_t status;    char *to;
4122    int nesting = 0;  
4123    char *cplus_demangled;    demangled = d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS, &alc);
4124    char *return_value;  
4125          if (demangled == NULL)
4126    /* Create a dyn_string to hold the demangled name.  */      return NULL;
4127    demangled = dyn_string_new (0);  
4128      nesting = 0;
4129    /* Attempt the demangling.  */    from = demangled;
4130    status = cp_demangle ((char *) mangled, demangled, DMGL_JAVA);    to = from;
4131      while (*from != '\0')
   if (STATUS_NO_ERROR (status))  
     /* Demangling succeeded.  */  
     {  
       /* Grab the demangled result from the dyn_string. */  
       cplus_demangled = dyn_string_release (demangled);  
     }  
   else if (status == STATUS_ALLOCATION_FAILED)  
     {  
       fprintf (stderr, "Memory allocation failed.\n");  
       abort ();  
     }  
   else  
     /* Demangling failed.  */  
4132      {      {
4133        dyn_string_delete (demangled);        if (strncmp (from, "JArray<", 7) == 0)
4134        return NULL;          {
4135      }            from += 7;
     
   len = strlen (cplus_demangled);  
   next = cplus_demangled;  
   end = next + len;  
   demangled = NULL;  
   
   /* Replace occurances of JArray<TYPE> with TYPE[]. */  
   while (next < end)  
     {  
       char *open_str = strstr (next, "JArray<");  
       char *close_str = NULL;  
       if (nesting > 0)  
         close_str = strchr (next, '>');  
       
       if (open_str != NULL && (close_str == NULL || close_str > open_str))  
         {  
4136            ++nesting;            ++nesting;
             
           if (!demangled)  
             demangled = dyn_string_new(len);  
   
           /* Copy prepending symbols, if any. */  
           if (open_str > next)  
             {  
               open_str[0] = 0;  
               dyn_string_append_cstr (demangled, next);  
             }      
           next = open_str + 7;  
4137          }          }
4138        else if (close_str != NULL)        else if (nesting > 0 && *from == '>')
4139          {          {
4140              while (to > demangled && to[-1] == ' ')
4141                --to;
4142              *to++ = '[';
4143              *to++ = ']';
4144            --nesting;            --nesting;
4145                        ++from;
           /* Copy prepending type symbol, if any. Squash any spurious  
              whitespace. */  
           if (close_str > next && next[0] != ' ')  
             {  
               close_str[0] = 0;  
               dyn_string_append_cstr (demangled, next);  
             }  
           dyn_string_append_cstr (demangled, "[]");        
           next = close_str + 1;  
4146          }          }
4147        else        else
4148          {          *to++ = *from++;
           /* There are no more arrays. Copy the rest of the symbol, or  
              simply return the original symbol if no changes were made. */  
           if (next == cplus_demangled)  
             return cplus_demangled;  
   
           dyn_string_append_cstr (demangled, next);  
           next = end;  
         }  
4149      }      }
4150    
4151    free (cplus_demangled);    *to = '\0';
     
   if (demangled)  
     return_value = dyn_string_release (demangled);  
   else  
     return_value = NULL;  
4152    
4153    return return_value;    return demangled;
4154  }  }
4155    
4156  #endif /* IN_LIBGCC2 || IN_GLIBCPP_V3 */  #endif /* IN_LIBGCC2 || IN_GLIBCPP_V3 */
4157    
   
4158  #ifndef IN_GLIBCPP_V3  #ifndef IN_GLIBCPP_V3
 /* Demangle NAME in the G++ V3 ABI demangling style, and return either  
    zero, indicating that some error occurred, or a demangling_t  
    holding the results.  */  
 static demangling_t  
 demangle_v3_with_details (name)  
      const char *name;  
 {  
   demangling_t dm;  
   status_t status;  
4159    
4160    if (strncmp (name, "_Z", 2))  /* Demangle a string in order to find out whether it is a constructor
4161      return 0;     or destructor.  Return non-zero on success.  Set *CTOR_KIND and
4162       *DTOR_KIND appropriately.  */
4163    
4164    dm = demangling_new (name, DMGL_GNU_V3);  static int
4165    if (dm == NULL)  is_ctor_or_dtor (mangled, ctor_kind, dtor_kind)
4166      {       const char *mangled;
4167        fprintf (stderr, "Memory allocation failed.\n");       enum gnu_v3_ctor_kinds *ctor_kind;
4168        abort ();       enum gnu_v3_dtor_kinds *dtor_kind;
4169      }  {
4170      struct d_info di;
4171      struct demangle_component *dc;
4172      int ret;
4173    
4174    status = result_push (dm);    *ctor_kind = (enum gnu_v3_ctor_kinds) 0;
4175    if (! STATUS_NO_ERROR (status))    *dtor_kind = (enum gnu_v3_dtor_kinds) 0;
     {  
       demangling_delete (dm);  
       fprintf (stderr, "%s\n", status);  
       abort ();  
     }  
4176    
4177    status = demangle_mangled_name (dm);    cplus_demangle_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di);
   if (STATUS_NO_ERROR (status))  
     return dm;  
4178    
4179    demangling_delete (dm);    {
4180    return 0;  #ifdef CP_DYNAMIC_ARRAYS
4181        __extension__ struct demangle_component comps[di.num_comps];
4182        __extension__ struct demangle_component *subs[di.num_subs];
4183    
4184        di.comps = &comps[0];
4185        di.subs = &subs[0];
4186    #else
4187        di.comps = ((struct demangle_component *)
4188                    malloc (di.num_comps * sizeof (struct demangle_component)));
4189        di.subs = ((struct demangle_component **)
4190                   malloc (di.num_subs * sizeof (struct demangle_component *)));
4191        if (di.comps == NULL || di.subs == NULL)
4192          {
4193            if (di.comps != NULL)
4194              free (di.comps);
4195            if (di.subs != NULL)
4196              free (di.subs);
4197            return 0;
4198          }
4199    #endif
4200    
4201        dc = cplus_demangle_mangled_name (&di, 1);
4202    
4203        /* Note that because we did not pass DMGL_PARAMS, we don't expect
4204           to demangle the entire string.  */
4205    
4206        ret = 0;
4207        while (dc != NULL)
4208          {
4209            switch (dc->type)
4210              {
4211              default:
4212                dc = NULL;
4213                break;
4214              case DEMANGLE_COMPONENT_TYPED_NAME:
4215              case DEMANGLE_COMPONENT_TEMPLATE:
4216              case DEMANGLE_COMPONENT_RESTRICT_THIS:
4217              case DEMANGLE_COMPONENT_VOLATILE_THIS:
4218              case DEMANGLE_COMPONENT_CONST_THIS:
4219                dc = d_left (dc);
4220                break;
4221              case DEMANGLE_COMPONENT_QUAL_NAME:
4222              case DEMANGLE_COMPONENT_LOCAL_NAME:
4223                dc = d_right (dc);
4224                break;
4225              case DEMANGLE_COMPONENT_CTOR:
4226                *ctor_kind = dc->u.s_ctor.kind;
4227                ret = 1;
4228                dc = NULL;
4229                break;
4230              case DEMANGLE_COMPONENT_DTOR:
4231                *dtor_kind = dc->u.s_dtor.kind;
4232                ret = 1;
4233                dc = NULL;
4234                break;
4235              }
4236          }
4237    
4238    #ifndef CP_DYNAMIC_ARRAYS
4239        free (di.subs);
4240        free (di.comps);
4241    #endif
4242      }
4243    
4244      return ret;
4245  }  }
4246    
4247    /* Return whether NAME is the mangled form of a g++ V3 ABI constructor
4248       name.  A non-zero return indicates the type of constructor.  */
4249    
 /* Return non-zero iff NAME is the mangled form of a constructor name  
    in the G++ V3 ABI demangling style.  Specifically, return:  
    - '1' if NAME is a complete object constructor,  
    - '2' if NAME is a base object constructor, or  
    - '3' if NAME is a complete object allocating constructor.  */  
4250  enum gnu_v3_ctor_kinds  enum gnu_v3_ctor_kinds
4251  is_gnu_v3_mangled_ctor (name)  is_gnu_v3_mangled_ctor (name)
4252       const char *name;       const char *name;
4253  {  {
4254    demangling_t dm = demangle_v3_with_details (name);    enum gnu_v3_ctor_kinds ctor_kind;
4255      enum gnu_v3_dtor_kinds dtor_kind;
4256    
4257    if (dm)    if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind))
4258      {      return (enum gnu_v3_ctor_kinds) 0;
4259        enum gnu_v3_ctor_kinds result = dm->is_constructor;    return ctor_kind;
       demangling_delete (dm);  
       return result;  
     }  
   else  
     return 0;  
4260  }  }
4261    
4262    
4263  /* Return non-zero iff NAME is the mangled form of a destructor name  /* Return whether NAME is the mangled form of a g++ V3 ABI destructor
4264     in the G++ V3 ABI demangling style.  Specifically, return:     name.  A non-zero return indicates the type of destructor.  */
4265     - '0' if NAME is a deleting destructor,  
    - '1' if NAME is a complete object destructor, or  
    - '2' if NAME is a base object destructor.  */  
4266  enum gnu_v3_dtor_kinds  enum gnu_v3_dtor_kinds
4267  is_gnu_v3_mangled_dtor (name)  is_gnu_v3_mangled_dtor (name)
4268       const char *name;       const char *name;
4269  {  {
4270    demangling_t dm = demangle_v3_with_details (name);    enum gnu_v3_ctor_kinds ctor_kind;
4271      enum gnu_v3_dtor_kinds dtor_kind;
4272    
4273    if (dm)    if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind))
4274      {      return (enum gnu_v3_dtor_kinds) 0;
4275        enum gnu_v3_dtor_kinds result = dm->is_destructor;    return dtor_kind;
       demangling_delete (dm);  
       return result;  
     }  
   else  
     return 0;  
4276  }  }
 #endif /* IN_GLIBCPP_V3 */  
4277    
4278    #endif /* IN_GLIBCPP_V3 */
4279    
4280  #ifdef STANDALONE_DEMANGLER  #ifdef STANDALONE_DEMANGLER
4281    
4282  #include "getopt.h"  #include "getopt.h"
4283    #include "dyn-string.h"
4284    
4285    static void print_usage PARAMS ((FILE* fp, int exit_value));
4286    
4287  static void print_usage  #define IS_ALPHA(CHAR)                                                  \
4288    PARAMS ((FILE* fp, int exit_value));    (((CHAR) >= 'a' && (CHAR) <= 'z')                                     \
4289       || ((CHAR) >= 'A' && (CHAR) <= 'Z'))
4290    
4291  /* Non-zero if CHAR is a character than can occur in a mangled name.  */  /* Non-zero if CHAR is a character than can occur in a mangled name.  */
4292  #define is_mangled_char(CHAR)                                           \  #define is_mangled_char(CHAR)                                           \
# Line 4026  print_usage (fp, exit_value) Line 4306  print_usage (fp, exit_value)
4306    fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);    fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
4307    fprintf (fp, "Options:\n");    fprintf (fp, "Options:\n");
4308    fprintf (fp, "  -h,--help       Display this message.\n");    fprintf (fp, "  -h,--help       Display this message.\n");
4309    fprintf (fp, "  -s,--strict     Demangle standard names only.\n");    fprintf (fp, "  -p,--no-params  Don't display function parameters\n");
4310    fprintf (fp, "  -v,--verbose    Produce verbose demanglings.\n");    fprintf (fp, "  -v,--verbose    Produce verbose demanglings.\n");
4311    fprintf (fp, "If names are provided, they are demangled.  Otherwise filters standard input.\n");    fprintf (fp, "If names are provided, they are demangled.  Otherwise filters standard input.\n");
4312    
# Line 4036  print_usage (fp, exit_value) Line 4316  print_usage (fp, exit_value)
4316  /* Option specification for getopt_long.  */  /* Option specification for getopt_long.  */
4317  static const struct option long_options[] =  static const struct option long_options[] =
4318  {  {
4319    { "help",    no_argument, NULL, 'h' },    { "help",      no_argument, NULL, 'h' },
4320    { "strict",  no_argument, NULL, 's' },    { "no-params", no_argument, NULL, 'p' },
4321    { "verbose", no_argument, NULL, 'v' },    { "verbose",   no_argument, NULL, 'v' },
4322    { NULL,      no_argument, NULL, 0   },    { NULL,        no_argument, NULL, 0   },
4323  };  };
4324    
4325  /* Main entry for a demangling filter executable.  It will demangle  /* Main entry for a demangling filter executable.  It will demangle
# Line 4052  main (argc, argv) Line 4332  main (argc, argv)
4332       int argc;       int argc;
4333       char *argv[];       char *argv[];
4334  {  {
   status_t status;  
4335    int i;    int i;
4336    int opt_char;    int opt_char;
4337      int options = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES;
4338    
4339    /* Use the program name of this program, as invoked.  */    /* Use the program name of this program, as invoked.  */
4340    program_name = argv[0];    program_name = argv[0];
# Line 4062  main (argc, argv) Line 4342  main (argc, argv)
4342    /* Parse options.  */    /* Parse options.  */
4343    do    do
4344      {      {
4345        opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);        opt_char = getopt_long (argc, argv, "hpv", long_options, NULL);
4346        switch (opt_char)        switch (opt_char)
4347          {          {
4348          case '?':  /* Unrecognized option.  */          case '?':  /* Unrecognized option.  */
# Line 4073  main (argc, argv) Line 4353  main (argc, argv)
4353            print_usage (stdout, 0);            print_usage (stdout, 0);
4354            break;            break;
4355    
4356          case 's':          case 'p':
4357            flag_strict = 1;            options &= ~ DMGL_PARAMS;
4358            break;            break;
4359    
4360          case 'v':          case 'v':
4361            flag_verbose = 1;            options |= DMGL_VERBOSE;
4362            break;            break;
4363          }          }
4364      }      }
# Line 4088  main (argc, argv) Line 4368  main (argc, argv)
4368      /* No command line arguments were provided.  Filter stdin.  */      /* No command line arguments were provided.  Filter stdin.  */
4369      {      {
4370        dyn_string_t mangled = dyn_string_new (3);        dyn_string_t mangled = dyn_string_new (3);
4371        dyn_string_t demangled = dyn_string_new (0);        char *s;
       status_t status;  
4372    
4373        /* Read all of input.  */        /* Read all of input.  */
4374        while (!feof (stdin))        while (!feof (stdin))
4375          {          {
4376            char c = getchar ();            char c;
   
           /* The first character of a mangled name is an underscore.  */  
           if (feof (stdin))  
             break;  
           if (c != '_')  
             {  
               /* It's not a mangled name.  Print the character and go  
                  on.  */  
               putchar (c);  
               continue;  
             }  
           c = getchar ();  
             
           /* The second character of a mangled name is a capital `Z'.  */  
           if (feof (stdin))  
             break;  
           if (c != 'Z')  
             {  
               /* It's not a mangled name.  Print the previous  
                  underscore, the `Z', and go on.  */  
               putchar ('_');  
               putchar (c);  
               continue;  
             }  
   
           /* Start keeping track of the candidate mangled name.  */  
           dyn_string_append_char (mangled, '_');  
           dyn_string_append_char (mangled, 'Z');  
4377    
4378            /* Pile characters into mangled until we hit one that can't            /* Pile characters into mangled until we hit one that can't
4379               occur in a mangled name.  */               occur in a mangled name.  */
# Line 4135  main (argc, argv) Line 4386  main (argc, argv)
4386                c = getchar ();                c = getchar ();
4387              }              }
4388    
4389            /* Attempt to demangle the name.  */            if (dyn_string_length (mangled) > 0)
           status = cp_demangle (dyn_string_buf (mangled), demangled, 0);  
   
           /* If the demangling succeeded, great!  Print out the  
              demangled version.  */  
           if (STATUS_NO_ERROR (status))  
             fputs (dyn_string_buf (demangled), stdout);  
           /* Abort on allocation failures.  */  
           else if (status == STATUS_ALLOCATION_FAILED)  
4390              {              {
4391                fprintf (stderr, "Memory allocation failed.\n");  #ifdef IN_GLIBCPP_V3
4392                abort ();                s = __cxa_demangle (dyn_string_buf (mangled), NULL, NULL, NULL);
4393    #else
4394                  s = cplus_demangle_v3 (dyn_string_buf (mangled), options);
4395    #endif
4396    
4397                  if (s != NULL)
4398                    {
4399                      fputs (s, stdout);
4400                      free (s);
4401                    }
4402                  else
4403                    {
4404                      /* It might not have been a mangled name.  Print the
4405                         original text.  */
4406                      fputs (dyn_string_buf (mangled), stdout);
4407                    }
4408    
4409                  dyn_string_clear (mangled);
4410              }              }
           /* Otherwise, it might not have been a mangled name.  Just  
              print out the original text.  */  
           else  
             fputs (dyn_string_buf (mangled), stdout);  
4411    
4412            /* If we haven't hit EOF yet, we've read one character that            /* If we haven't hit EOF yet, we've read one character that
4413               can't occur in a mangled name, so print it out.  */               can't occur in a mangled name, so print it out.  */
4414            if (!feof (stdin))            if (!feof (stdin))
4415              putchar (c);              putchar (c);
   
           /* Clear the candidate mangled name, to start afresh next  
              time we hit a `_Z'.  */  
           dyn_string_clear (mangled);  
4416          }          }
4417    
4418        dyn_string_delete (mangled);        dyn_string_delete (mangled);
       dyn_string_delete (demangled);  
4419      }      }
4420    else    else
4421      /* Demangle command line arguments.  */      /* Demangle command line arguments.  */
4422      {      {
       dyn_string_t result = dyn_string_new (0);  
   
4423        /* Loop over command line arguments.  */        /* Loop over command line arguments.  */
4424        for (i = optind; i < argc; ++i)        for (i = optind; i < argc; ++i)
4425          {          {
4426              char *s;
4427    #ifdef IN_GLIBCPP_V3
4428              int status;
4429    #endif
4430    
4431            /* Attempt to demangle.  */            /* Attempt to demangle.  */
4432            status = cp_demangle (argv[i], result, 0);  #ifdef IN_GLIBCPP_V3
4433              s = __cxa_demangle (argv[i], NULL, NULL, &status);
4434    #else
4435              s = cplus_demangle_v3 (argv[i], options);
4436    #endif
4437    
4438            /* If it worked, print the demangled name.  */            /* If it worked, print the demangled name.  */
4439            if (STATUS_NO_ERROR (status))            if (s != NULL)
             printf ("%s\n", dyn_string_buf (result));  
           /* Abort on allocaiton failures.  */  
           else if (status == STATUS_ALLOCATION_FAILED)  
4440              {              {
4441                fprintf (stderr, "Memory allocation failed.\n");                printf ("%s\n", s);
4442                abort ();                free (s);
4443                }
4444              else
4445                {
4446    #ifdef IN_GLIBCPP_V3
4447                  fprintf (stderr, "Failed: %s (status %d)\n", argv[i], status);
4448    #else
4449                  fprintf (stderr, "Failed: %s\n", argv[i]);
4450    #endif
4451              }              }
           /* If not, print the error message to stderr instead.  */  
           else  
             fprintf (stderr, "%s\n", status);  
4452          }          }
       dyn_string_delete (result);  
4453      }      }
4454    
4455    return 0;    return 0;

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26