OSDN Git Service

* cp-demangle.c: Fix copyright banner.
[pf3gnuchains/gcc-fork.git] / libiberty / cp-demangle.c
1 /* Demangler for IA64 / g++ standard C++ ABI.
2    Copyright (C) 2000 Free Software Foundation, Inc.
3    Written by Alex Samuel <samuel@codesourcery.com>. 
4
5    This file is part of GNU CC.
6
7    This program is free software; you can redistribute it and/or modify
8    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
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
20 */
21
22 /* This file implements demangling of C++ names mangled according to
23    the IA64 / g++ standard C++ ABI.  Use the cp_demangle function to
24    demangle a mangled name, or compile with the preprocessor macro
25    STANDALONE_DEMANGLER defined to create a demangling filter
26    executable (functionally similar to c++filt, but includes this
27    demangler only).  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <sys/types.h>
34
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif
38
39 #include <stdio.h>
40
41 #ifdef HAVE_STRING_H
42 #include <string.h>
43 #endif
44
45 #include "ansidecl.h"
46 #include "libiberty.h"
47 #include "dyn-string.h"
48 #include "demangle.h"
49
50 /* If CP_DEMANGLE_DEBUG is defined, a trace of the grammar evaluation,
51    and other debugging output, will be generated. */
52 #ifdef CP_DEMANGLE_DEBUG
53 #define DEMANGLE_TRACE(PRODUCTION, DM)                                  \
54   fprintf (stderr, " -> %-24s at position %3d\n",                       \
55            (PRODUCTION), current_position (DM));
56 #else
57 #define DEMANGLE_TRACE(PRODUCTION, DM)
58 #endif
59
60 /* Don't include <ctype.h>, to prevent additional unresolved symbols
61    from being dragged into the C++ runtime library.  */
62 #define IS_DIGIT(CHAR) ((CHAR) >= '0' && (CHAR) <= '9')
63 #define IS_ALPHA(CHAR)                                                  \
64   (((CHAR) >= 'a' && (CHAR) <= 'z')                                     \
65    || ((CHAR) >= 'A' && (CHAR) <= 'Z'))
66
67 /* The prefix prepended by GCC to an identifier represnting the
68    anonymous namespace.  */
69 #define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
70
71 /* If flag_verbose is zero, some simplifications will be made to the
72    output to make it easier to read and supress details that are
73    generally not of interest to the average C++ programmer.
74    Otherwise, the demangled representation will attempt to convey as
75    much information as the mangled form.  */
76 static int flag_verbose;
77
78 /* If flag_strict is non-zero, demangle strictly according to the
79    specification -- don't demangle special g++ manglings.  */
80 static int flag_strict;
81
82 /* String_list_t is an extended form of dyn_string_t which provides a link
83    field.  A string_list_t may safely be cast to and used as a
84    dyn_string_t.  */
85
86 struct string_list_def
87 {
88   struct dyn_string string;
89   struct string_list_def *next;
90 };
91
92 typedef struct string_list_def *string_list_t;
93
94 /* Data structure representing a potential substitution.  */
95
96 struct substitution_def
97 {
98   /* The demangled text of the substitution.  */
99   dyn_string_t text;
100
101   /* Whether this substitution represents a template item.  */
102   int template_p : 1;
103 };
104
105 /* Data structure representing a template argument list.  */
106
107 struct template_arg_list_def
108 {
109   /* The next (lower) template argument list in the stack of currently
110      active template arguments.  */
111   struct template_arg_list_def *next;
112
113   /* The first element in the list of template arguments in
114      left-to-right order.  */
115   string_list_t first_argument;
116
117   /* The last element in the arguments lists.  */
118   string_list_t last_argument;
119 };
120
121 typedef struct template_arg_list_def *template_arg_list_t;
122
123 /* Data structure to maintain the state of the current demangling.  */
124
125 struct demangling_def
126 {
127   /* The full mangled name being mangled.  */
128   const char *name;
129
130   /* Pointer into name at the current position.  */
131   const char *next;
132
133   /* Stack for strings containing demangled result generated so far.
134      Text is emitted to the topmost (first) string.  */
135   string_list_t result;
136
137   /* The number of presently available substitutions.  */
138   int num_substitutions;
139
140   /* The allocated size of the substitutions array.  */
141   int substitutions_allocated;
142
143   /* An array of available substitutions.  The number of elements in
144      the array is given by num_substitions, and the allocated array
145      size in substitutions_size.  
146
147      The most recent substition is at the end, so
148
149        - `S_'  corresponds to substititutions[num_substitutions - 1] 
150        - `S0_' corresponds to substititutions[num_substitutions - 2]
151
152      etc. */
153   struct substitution_def *substitutions;
154
155   /* The stack of template argument lists.  */
156   template_arg_list_t template_arg_lists;
157
158   /* The most recently demangled source-name.  */
159   dyn_string_t last_source_name;
160 };
161
162 typedef struct demangling_def *demangling_t;
163
164 /* This type is the standard return code from most functions.  Values
165    other than STATUS_OK contain descriptive messages.  */
166 typedef const char *status_t;
167
168 /* Special values that can be used as a status_t.  */
169 #define STATUS_OK                       NULL
170 #define STATUS_ERROR                    "Error."
171 #define STATUS_UNIMPLEMENTED            "Unimplemented."
172 #define STATUS_INTERNAL_ERROR           "Internal error."
173
174 /* This status code indicates a failure in malloc or realloc.  */
175 static const char *const status_allocation_failed = "Allocation failed.";
176 #define STATUS_ALLOCATION_FAILED        status_allocation_failed
177
178 /* Non-zero if STATUS indicates that no error has occurred.  */
179 #define STATUS_NO_ERROR(STATUS)         ((STATUS) == STATUS_OK)
180
181 /* Evaluate EXPR, which must produce a status_t.  If the status code
182    indicates an error, return from the current function with that
183    status code.  */
184 #define RETURN_IF_ERROR(EXPR)                                           \
185   do                                                                    \
186     {                                                                   \
187       status_t s = EXPR;                                                \
188       if (!STATUS_NO_ERROR (s))                                         \
189         return s;                                                       \
190     }                                                                   \
191   while (0)
192
193 static status_t int_to_dyn_string 
194   PARAMS ((int, dyn_string_t));
195 static string_list_t string_list_new
196   PARAMS ((int));
197 static void string_list_delete
198   PARAMS ((string_list_t));
199 static status_t result_add_separated_char
200   PARAMS ((demangling_t, int));
201 static status_t result_push
202   PARAMS ((demangling_t));
203 static string_list_t result_pop
204   PARAMS ((demangling_t));
205 static int substitution_start
206   PARAMS ((demangling_t));
207 static status_t substitution_add
208   PARAMS ((demangling_t, int, int));
209 static dyn_string_t substitution_get
210   PARAMS ((demangling_t, int, int *));
211 #ifdef CP_DEMANGLE_DEBUG
212 static void substitutions_print 
213   PARAMS ((demangling_t, FILE *));
214 #endif
215 static template_arg_list_t template_arg_list_new
216   PARAMS ((void));
217 static void template_arg_list_delete
218   PARAMS ((template_arg_list_t));
219 static void template_arg_list_add_arg 
220   PARAMS ((template_arg_list_t, string_list_t));
221 static string_list_t template_arg_list_get_arg
222   PARAMS ((template_arg_list_t, int));
223 static void push_template_arg_list
224   PARAMS ((demangling_t, template_arg_list_t));
225 static void pop_to_template_arg_list
226   PARAMS ((demangling_t, template_arg_list_t));
227 #ifdef CP_DEMANGLE_DEBUG
228 static void template_arg_list_print
229   PARAMS ((template_arg_list_t, FILE *));
230 #endif
231 static template_arg_list_t current_template_arg_list
232   PARAMS ((demangling_t));
233 static demangling_t demangling_new
234   PARAMS ((const char *));
235 static void demangling_delete 
236   PARAMS ((demangling_t));
237
238 /* The last character of DS.  Warning: DS is evaluated twice.  */
239 #define dyn_string_last_char(DS)                                        \
240   (dyn_string_buf (DS)[dyn_string_length (DS) - 1])
241
242 /* Append a space character (` ') to DS if it does not already end
243    with one.  Evaluates to 1 on success, or 0 on allocation failure.  */
244 #define dyn_string_append_space(DS)                                     \
245       ((dyn_string_length (DS) > 0                                      \
246         && dyn_string_last_char (DS) != ' ')                            \
247        ? dyn_string_append_char ((DS), ' ')                             \
248        : 1)
249
250 /* Returns the index of the current position in the mangled name.  */
251 #define current_position(DM)    ((DM)->next - (DM)->name)
252
253 /* Returns the character at the current position of the mangled name.  */
254 #define peek_char(DM)           (*((DM)->next))
255
256 /* Returns the character one past the current position of the mangled
257    name.  */
258 #define peek_char_next(DM)                                              \
259   (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1)))
260
261 /* Returns the character at the current position, and advances the
262    current position to the next character.  */
263 #define next_char(DM)           (*((DM)->next)++)
264
265 /* Returns non-zero if the current position is the end of the mangled
266    name, i.e. one past the last character.  */
267 #define end_of_name_p(DM)       (peek_char (DM) == '\0')
268
269 /* Advances the current position by one character.  */
270 #define advance_char(DM)        (++(DM)->next)
271
272 /* Returns the string containing the current demangled result.  */
273 #define result_string(DM)       (&(DM)->result->string)
274
275 /* Appends a dyn_string_t to the demangled result.  */
276 #define result_append_string(DM, STRING)                                \
277   (dyn_string_append (&(DM)->result->string, (STRING))                  \
278    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
279
280 /* Appends NUL-terminated string CSTR to the demangled result.  */
281 #define result_append(DM, CSTR)                                         \
282   (dyn_string_append_cstr (&(DM)->result->string, (CSTR))               \
283    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
284
285 /* Appends character CHAR to the demangled result.  */
286 #define result_append_char(DM, CHAR)                                    \
287   (dyn_string_append_char (&(DM)->result->string, (CHAR))               \
288    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
289
290 /* Inserts a dyn_string_t to the demangled result at position POS.  */
291 #define result_insert_string(DM, POS, STRING)                           \
292   (dyn_string_insert (&(DM)->result->string, (POS), (STRING))           \
293    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
294
295 /* Inserts NUL-terminated string CSTR to the demangled result at
296    position POS.  */
297 #define result_insert(DM, POS, CSTR)                                    \
298   (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR))        \
299    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
300
301 /* Inserts character CHAR to the demangled result at position POS.  */
302 #define result_insert_char(DM, POS, CHAR)                               \
303   (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR))        \
304    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
305
306 /* The length of the current demangled result.  */
307 #define result_length(DM)                                               \
308   dyn_string_length (&(DM)->result->string)
309
310 /* Appends a space to the demangled result if the last character is
311    not a space.  */
312 #define result_append_space(DM)                                         \
313   (dyn_string_append_space (&(DM)->result->string)                      \
314    ? STATUS_OK : STATUS_ALLOCATION_FAILED)
315
316 /* Appends a (less-than, greater-than) character to the result in DM
317    to (open, close) a template argument or parameter list.  Appends a
318    space first if necessary to prevent spurious elision of angle
319    brackets with the previous character.  */
320 #define result_open_template_list(DM) result_add_separated_char(DM, '<')
321 #define result_close_template_list(DM) result_add_separated_char(DM, '>')
322
323 /* Appends a base 10 representation of VALUE to DS.  STATUS_OK on
324    success.  On failure, deletes DS and returns an error code.  */
325
326 static status_t
327 int_to_dyn_string (value, ds)
328      int value;
329      dyn_string_t ds;
330 {
331   int i;
332   int mask = 1;
333
334   /* Handle zero up front.  */
335   if (value == 0)
336     {
337       if (!dyn_string_append_char (ds, '0'))
338         return STATUS_ALLOCATION_FAILED;
339       return STATUS_OK;
340     }
341
342   /* For negative numbers, emit a minus sign.  */
343   if (value < 0)
344     {
345       if (!dyn_string_append_char (ds, '-'))
346         return STATUS_ALLOCATION_FAILED;
347       value = -value;
348     }
349   
350   /* Find the power of 10 of the first digit.  */
351   i = value;
352   while (i > 9)
353     {
354       mask *= 10;
355       i /= 10;
356     }
357
358   /* Write the digits.  */
359   while (mask > 0)
360     {
361       int digit = value / mask;
362
363       if (!dyn_string_append_char (ds, '0' + digit))
364         return STATUS_ALLOCATION_FAILED;
365
366       value -= digit * mask;
367       mask /= 10;
368     }
369
370   return STATUS_OK;
371 }
372
373 /* Creates a new string list node.  The contents of the string are
374    empty, but the initial buffer allocation is LENGTH.  The string
375    list node should be deleted with string_list_delete.  Returns NULL
376    if allocation fails.  */
377
378 static string_list_t 
379 string_list_new (length)
380      int length;
381 {
382   string_list_t s = (string_list_t) malloc (sizeof (struct string_list_def));
383   if (s == NULL)
384     return NULL;
385   if (!dyn_string_init ((dyn_string_t) s, length))
386     return NULL;
387   return s;
388 }  
389
390 /* Deletes the entire string list starting at NODE.  */
391
392 static void
393 string_list_delete (node)
394      string_list_t node;
395 {
396   while (node != NULL)
397     {
398       string_list_t next = node->next;
399       free (node);
400       node = next;
401     }
402 }
403
404 /* Appends CHARACTER to the demangled result.  If the current trailing
405    character of the result is CHARACTER, a space is inserted first.  */
406
407 static status_t
408 result_add_separated_char (dm, character)
409      demangling_t dm;
410      int character;
411 {
412   dyn_string_t s = &dm->result->string;
413
414   /* Add a space if the last character is already a closing angle
415      bracket, so that a nested template arg list doesn't look like
416      it's closed with a right-shift operator.  */
417   if (dyn_string_last_char (s) == character)
418     {
419       if (!dyn_string_append_char (s, ' '))
420         return STATUS_ALLOCATION_FAILED;
421     }
422
423   /* Add closing angle brackets.  */
424   if (!dyn_string_append_char (s, character))
425     return STATUS_ALLOCATION_FAILED;
426
427   return STATUS_OK;
428 }
429
430 /* Allocates and pushes a new string onto the demangled results stack
431    for DM.  Subsequent demangling with DM will emit to the new string.
432    Returns STATUS_OK on success, STATUS_ALLOCATION_FAILED on
433    allocation failure.  */
434
435 static status_t
436 result_push (dm)
437      demangling_t dm;
438 {
439   string_list_t new_string = string_list_new (0);
440   if (new_string == NULL)
441     /* Allocation failed.  */
442     return STATUS_ALLOCATION_FAILED;
443
444   /* Link the new string to the front of the list of result strings.  */
445   new_string->next = (string_list_t) dm->result;
446   dm->result = new_string;
447   return STATUS_OK;
448 }
449
450 /* Removes and returns the topmost element on the demangled results
451    stack for DM.  The caller assumes ownership for the returned
452    string.  */
453
454 static string_list_t
455 result_pop (dm)
456      demangling_t dm;
457 {
458   string_list_t top = dm->result;
459   dm->result = top->next;
460   return top;
461 }
462
463 /* Returns the start position of a fragment of the demangled result
464    that will be a substitution candidate.  Should be called at the
465    start of productions that can add substitutions.  */
466
467 static int
468 substitution_start (dm)
469      demangling_t dm;
470 {
471   return result_length (dm);
472 }
473
474 /* Adds the suffix of the current demangled result of DM starting at
475    START_POSITION as a potential substitution.  If TEMPLATE_P is
476    non-zero, this potential substitution is a template-id.  */
477
478 static status_t
479 substitution_add (dm, start_position, template_p)
480      demangling_t dm;
481      int start_position;
482      int template_p;
483 {
484   dyn_string_t result = result_string (dm);
485   dyn_string_t substitution = dyn_string_new (0);
486   int i;
487
488   if (substitution == NULL)
489     return STATUS_ALLOCATION_FAILED;
490
491   /* Extract the substring of the current demangling result that
492      represents the subsitution candidate.  */
493   if (!dyn_string_substring (substitution, 
494                              result, start_position, result_length (dm)))
495     {
496       dyn_string_delete (substitution);
497       return STATUS_ALLOCATION_FAILED;
498     }
499
500   /* If there's no room for the new entry, grow the array.  */
501   if (dm->substitutions_allocated == dm->num_substitutions)
502     {
503       size_t new_array_size;
504       if (dm->substitutions_allocated > 0)
505         dm->substitutions_allocated *= 2;
506       else
507         dm->substitutions_allocated = 2;
508       new_array_size = 
509         sizeof (struct substitution_def) * dm->substitutions_allocated;
510
511       dm->substitutions = (struct substitution_def *)
512         realloc (dm->substitutions, new_array_size);
513       if (dm->substitutions == NULL)
514         /* Realloc failed.  */
515         {
516           dyn_string_delete (substitution);
517           return STATUS_ALLOCATION_FAILED;
518         }
519     }
520
521   /* Add the substitution to the array.  */
522   i = dm->num_substitutions++;
523   dm->substitutions[i].text = substitution;
524   dm->substitutions[i].template_p = template_p;
525
526 #ifdef CP_DEMANGLE_DEBUG
527   substitutions_print (dm, stderr);
528 #endif
529
530   return STATUS_OK;
531 }
532
533 /* Returns the Nth-most-recent substitution.  Sets *TEMPLATE_P to
534    non-zero if the substitution is a template-id, zero otherwise.  
535    N is numbered from zero.  DM retains ownership of the returned
536    string.  If N is negative, or equal to or greater than the current
537    number of substitution candidates, returns NULL.  */
538
539 static dyn_string_t
540 substitution_get (dm, n, template_p)
541      demangling_t dm;
542      int n;
543      int *template_p;
544 {
545   struct substitution_def *sub;
546
547   /* Make sure N is in the valid range.  */
548   if (n < 0 || n >= dm->num_substitutions)
549     return NULL;
550
551   sub = &(dm->substitutions[n]);
552   *template_p = sub->template_p;
553   return sub->text;
554 }
555
556 #ifdef CP_DEMANGLE_DEBUG
557 /* Debugging routine to print the current substitutions to FP.  */
558
559 static void
560 substitutions_print (dm, fp)
561      demangling_t dm;
562      FILE *fp;
563 {
564   int seq_id;
565   int num = dm->num_substitutions;
566
567   fprintf (fp, "SUBSTITUTIONS:\n");
568   for (seq_id = -1; seq_id < num - 1; ++seq_id)
569     {
570       int template_p;
571       dyn_string_t text = substitution_get (dm, seq_id + 1, &template_p);
572
573       if (seq_id == -1)
574         fprintf (fp, " S_ ");
575       else
576         fprintf (fp, " S%d_", seq_id);
577       fprintf (fp, " %c: %s\n", template_p ? '*' : ' ', dyn_string_buf (text));
578     }
579 }
580
581 #endif /* CP_DEMANGLE_DEBUG */
582
583 /* Creates a new template argument list.  Returns NULL if allocation
584    fails.  */
585
586 static template_arg_list_t
587 template_arg_list_new ()
588 {
589   template_arg_list_t new_list =
590     (template_arg_list_t) malloc (sizeof (struct template_arg_list_def));
591   if (new_list == NULL)
592     return NULL;
593   /* Initialize the new list to have no arguments.  */
594   new_list->first_argument = NULL;
595   new_list->last_argument = NULL;
596   /* Return the new list.  */
597   return new_list;
598 }
599
600 /* Deletes a template argument list and the template arguments it
601    contains.  */
602
603 static void
604 template_arg_list_delete (list)
605      template_arg_list_t list;
606 {
607   /* If there are any arguments on LIST, delete them.  */
608   if (list->first_argument != NULL)
609     string_list_delete (list->first_argument);
610   /* Delete LIST.  */
611   free (list);
612 }
613
614 /* Adds ARG to the template argument list ARG_LIST.  */
615
616 static void 
617 template_arg_list_add_arg (arg_list, arg)
618      template_arg_list_t arg_list;
619      string_list_t arg;
620 {
621   if (arg_list->first_argument == NULL)
622     /* If there were no arguments before, ARG is the first one.  */
623     arg_list->first_argument = arg;
624   else
625     /* Make ARG the last argument on the list.  */
626     arg_list->last_argument->next = arg;
627   /* Make ARG the last on the list.  */
628   arg_list->last_argument = arg;
629   arg->next = NULL;
630 }
631
632 /* Returns the template arugment at position INDEX in template
633    argument list ARG_LIST.  */
634
635 static string_list_t
636 template_arg_list_get_arg (arg_list, index)
637      template_arg_list_t arg_list;
638      int index;
639 {
640   string_list_t arg = arg_list->first_argument;
641   /* Scan down the list of arguments to find the one at position
642      INDEX.  */
643   while (index--)
644     {
645       arg = arg->next;
646       if (arg == NULL)
647         /* Ran out of arguments before INDEX hit zero.  That's an
648            error.  */
649         return NULL;
650     }
651   /* Return the argument at position INDEX.  */
652   return arg;
653 }
654
655 /* Pushes ARG_LIST onto the top of the template argument list stack.  */
656
657 static void
658 push_template_arg_list (dm, arg_list)
659      demangling_t dm;
660      template_arg_list_t arg_list;
661 {
662   arg_list->next = dm->template_arg_lists;
663   dm->template_arg_lists = arg_list;
664 #ifdef CP_DEMANGLE_DEBUG
665   fprintf (stderr, " ** pushing template arg list\n");
666   template_arg_list_print (arg_list, stderr);
667 #endif 
668 }
669
670 /* Pops and deletes elements on the template argument list stack until
671    arg_list is the topmost element.  If arg_list is NULL, all elements
672    are popped and deleted.  */
673
674 static void
675 pop_to_template_arg_list (dm, arg_list)
676      demangling_t dm;
677      template_arg_list_t arg_list;
678 {
679   while (dm->template_arg_lists != arg_list)
680     {
681       template_arg_list_t top = dm->template_arg_lists;
682       /* Disconnect the topmost element from the list.  */
683       dm->template_arg_lists = top->next;
684       /* Delete the popped element.  */
685       template_arg_list_delete (top);
686 #ifdef CP_DEMANGLE_DEBUG
687       fprintf (stderr, " ** removing template arg list\n");
688 #endif
689     }
690 }
691
692 #ifdef CP_DEMANGLE_DEBUG
693
694 /* Prints the contents of ARG_LIST to FP.  */
695
696 static void
697 template_arg_list_print (arg_list, fp)
698   template_arg_list_t arg_list;
699   FILE *fp;
700 {
701   string_list_t arg;
702   int index = -1;
703
704   fprintf (fp, "TEMPLATE ARGUMENT LIST:\n");
705   for (arg = arg_list->first_argument; arg != NULL; arg = arg->next)
706     {
707       if (index == -1)
708         fprintf (fp, " T_  : ");
709       else
710         fprintf (fp, " T%d_ : ", index);
711       ++index;
712       fprintf (fp, "%s\n", dyn_string_buf ((dyn_string_t) arg));
713     }
714 }
715
716 #endif /* CP_DEMANGLE_DEBUG */
717
718 /* Returns the topmost element on the stack of template argument
719    lists.  If there is no list of template arguments, returns NULL.  */
720
721 static template_arg_list_t
722 current_template_arg_list (dm)
723      demangling_t dm;
724 {
725   return dm->template_arg_lists;
726 }
727
728 /* Allocates a demangling_t object for demangling mangled NAME.  A new
729    result must be pushed before the returned object can be used.
730    Returns NULL if allocation fails.  */
731
732 static demangling_t
733 demangling_new (name)
734      const char *name;
735 {
736   demangling_t dm;
737   dm = (demangling_t) malloc (sizeof (struct demangling_def));
738   if (dm == NULL)
739     return NULL;
740
741   dm->name = name;
742   dm->next = name;
743   dm->result = NULL;
744   dm->num_substitutions = 0;
745   dm->substitutions_allocated = 10;
746   dm->template_arg_lists = NULL;
747   dm->last_source_name = dyn_string_new (0);
748   if (dm->last_source_name == NULL)
749     return NULL;
750   dm->substitutions = (struct substitution_def *)
751     malloc (dm->substitutions_allocated * sizeof (struct substitution_def));
752   if (dm->substitutions == NULL)
753     {
754       dyn_string_delete (dm->last_source_name);
755       return NULL;
756     }
757
758   return dm;
759 }
760
761 /* Deallocates a demangling_t object and all memory associated with
762    it.  */
763
764 static void
765 demangling_delete (dm)
766      demangling_t dm;
767 {
768   int i;
769   template_arg_list_t arg_list = dm->template_arg_lists;
770
771   /* Delete the stack of template argument lists.  */
772   while (arg_list != NULL)
773     {
774       template_arg_list_t next = arg_list->next;
775       template_arg_list_delete (arg_list);
776       arg_list = next;
777     }
778   /* Delete the list of substitutions.  */
779   for (i = dm->num_substitutions; --i >= 0; )
780     dyn_string_delete (dm->substitutions[i].text);
781   free (dm->substitutions);
782   /* Delete the demangled result.  */
783   string_list_delete (dm->result);
784   /* Delete the stored identifier name.  */
785   dyn_string_delete (dm->last_source_name);
786   /* Delete the context object itself.  */
787   free (dm);
788 }
789
790 /* These functions demangle an alternative of the corresponding
791    production in the mangling spec.  The first argument of each is a
792    demangling context structure for the current demangling
793    operation.  Most emit demangled text directly to the topmost result
794    string on the result string stack in the demangling context
795    structure.  */
796
797 static status_t demangle_char
798   PARAMS ((demangling_t, int));
799 static status_t demangle_mangled_name 
800   PARAMS ((demangling_t));
801 static status_t demangle_encoding
802   PARAMS ((demangling_t));
803 static status_t demangle_name
804   PARAMS ((demangling_t, int *));
805 static status_t demangle_nested_name
806   PARAMS ((demangling_t, int *));
807 static status_t demangle_prefix
808   PARAMS ((demangling_t, int *));
809 static status_t demangle_unqualified_name
810   PARAMS ((demangling_t, int *));
811 static status_t demangle_source_name
812   PARAMS ((demangling_t));
813 static status_t demangle_number
814   PARAMS ((demangling_t, int *, int, int));
815 static status_t demangle_number_literally
816   PARAMS ((demangling_t, dyn_string_t, int, int));
817 static status_t demangle_identifier
818   PARAMS ((demangling_t, int, dyn_string_t));
819 static status_t demangle_operator_name
820   PARAMS ((demangling_t, int, int *));
821 static status_t demangle_nv_offset
822   PARAMS ((demangling_t));
823 static status_t demangle_v_offset
824   PARAMS ((demangling_t));
825 static status_t demangle_call_offset
826   PARAMS ((demangling_t));
827 static status_t demangle_special_name
828   PARAMS ((demangling_t));
829 static status_t demangle_ctor_dtor_name
830   PARAMS ((demangling_t));
831 static status_t demangle_type_ptr
832   PARAMS ((demangling_t, int *, int));
833 static status_t demangle_type
834   PARAMS ((demangling_t));
835 static status_t demangle_CV_qualifiers
836   PARAMS ((demangling_t, dyn_string_t));
837 static status_t demangle_builtin_type
838   PARAMS ((demangling_t));
839 static status_t demangle_function_type
840   PARAMS ((demangling_t, int *));
841 static status_t demangle_bare_function_type
842   PARAMS ((demangling_t, int *));
843 static status_t demangle_class_enum_type
844   PARAMS ((demangling_t, int *));
845 static status_t demangle_array_type
846   PARAMS ((demangling_t));
847 static status_t demangle_template_param
848   PARAMS ((demangling_t));
849 static status_t demangle_template_args
850   PARAMS ((demangling_t));
851 static status_t demangle_literal
852   PARAMS ((demangling_t));
853 static status_t demangle_template_arg
854   PARAMS ((demangling_t));
855 static status_t demangle_expression
856   PARAMS ((demangling_t));
857 static status_t demangle_scope_expression
858   PARAMS ((demangling_t));
859 static status_t demangle_expr_primary
860   PARAMS ((demangling_t));
861 static status_t demangle_substitution
862   PARAMS ((demangling_t, int *));
863 static status_t demangle_local_name
864   PARAMS ((demangling_t));
865 static status_t demangle_discriminator 
866   PARAMS ((demangling_t, int));
867 static status_t cp_demangle
868   PARAMS ((const char *, dyn_string_t));
869 #ifdef IN_LIBGCC2
870 static status_t cp_demangle_type
871   PARAMS ((const char*, dyn_string_t));
872 #endif
873
874 /* When passed to demangle_bare_function_type, indicates that the
875    function's return type is not encoded before its parameter types.  */
876 #define BFT_NO_RETURN_TYPE    NULL
877
878 /* Check that the next character is C.  If so, consume it.  If not,
879    return an error.  */
880
881 static status_t
882 demangle_char (dm, c)
883      demangling_t dm;
884      int c;
885 {
886   static char *error_message = NULL;
887
888   if (peek_char (dm) == c)
889     {
890       advance_char (dm);
891       return STATUS_OK;
892     }
893   else
894     {
895       if (error_message == NULL)
896         error_message = strdup ("Expected ?");
897       error_message[9] = c;
898       return error_message;
899     }
900 }
901
902 /* Demangles and emits a <mangled-name>.  
903
904     <mangled-name>      ::= _Z <encoding>  */
905
906 static status_t
907 demangle_mangled_name (dm)
908      demangling_t dm;
909 {
910   DEMANGLE_TRACE ("mangled-name", dm);
911   RETURN_IF_ERROR (demangle_char (dm, '_'));
912   RETURN_IF_ERROR (demangle_char (dm, 'Z'));
913   RETURN_IF_ERROR (demangle_encoding (dm));
914   return STATUS_OK;
915 }
916
917 /* Demangles and emits an <encoding>.  
918
919     <encoding>          ::= <function name> <bare-function-type>
920                         ::= <data name>
921                         ::= <special-name>  */
922
923 static status_t
924 demangle_encoding (dm)
925      demangling_t dm;
926 {
927   int encode_return_type;
928   int start_position;
929   template_arg_list_t old_arg_list = current_template_arg_list (dm);
930   char peek = peek_char (dm);
931
932   DEMANGLE_TRACE ("encoding", dm);
933   
934   /* Remember where the name starts.  If it turns out to be a template
935      function, we'll have to insert the return type here.  */
936   start_position = result_length (dm);
937
938   if (peek == 'G' || peek == 'T')
939     RETURN_IF_ERROR (demangle_special_name (dm));
940   else
941     {
942       /* Now demangle the name.  */
943       RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));
944
945       /* If there's anything left, the name was a function name, with
946          maybe its return type, and its parameters types, following.  */
947       if (!end_of_name_p (dm) 
948           && peek_char (dm) != 'E')
949         {
950           if (encode_return_type)
951             /* Template functions have their return type encoded.  The
952                return type should be inserted at start_position.  */
953             RETURN_IF_ERROR 
954               (demangle_bare_function_type (dm, &start_position));
955           else
956             /* Non-template functions don't have their return type
957                encoded.  */
958             RETURN_IF_ERROR 
959               (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE)); 
960         }
961     }
962
963   /* Pop off template argument lists that were built during the
964      mangling of this name, to restore the old template context.  */
965   pop_to_template_arg_list (dm, old_arg_list);
966
967   return STATUS_OK;
968 }
969
970 /* Demangles and emits a <name>.
971
972     <name>              ::= <unscoped-name>
973                         ::= <unscoped-template-name> <template-args>
974                         ::= <nested-name>
975                         ::= <local-name>
976
977     <unscoped-name>     ::= <unqualified-name>
978                         ::= St <unqualified-name>   # ::std::
979
980     <unscoped-template-name>    
981                         ::= <unscoped-name>
982                         ::= <substitution>  */
983
984 static status_t
985 demangle_name (dm, encode_return_type)
986      demangling_t dm;
987      int *encode_return_type;
988 {
989   int start = substitution_start (dm);
990   char peek = peek_char (dm);
991   int is_std_substitution = 0;
992
993   /* Generally, the return type is encoded if the function is a
994      template-id, and suppressed otherwise.  There are a few cases,
995      though, in which the return type is not encoded even for a
996      templated function.  In these cases, this flag is set.  */
997   int suppress_return_type = 0;
998
999   DEMANGLE_TRACE ("name", dm);
1000
1001   switch (peek)
1002     {
1003     case 'N':
1004       /* This is a <nested-name>.  */
1005       RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));
1006       break;
1007
1008     case 'Z':
1009       RETURN_IF_ERROR (demangle_local_name (dm));
1010       *encode_return_type = 0;
1011       break;
1012
1013     case 'S':
1014       /* The `St' substitution allows a name nested in std:: to appear
1015          without being enclosed in a nested name.  */
1016       if (peek_char_next (dm) == 't') 
1017         {
1018           (void) next_char (dm);
1019           (void) next_char (dm);
1020           RETURN_IF_ERROR (result_append (dm, "std::"));
1021           RETURN_IF_ERROR 
1022             (demangle_unqualified_name (dm, &suppress_return_type));
1023           is_std_substitution = 1;
1024         }
1025       else
1026         RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
1027       /* Check if a template argument list immediately follows.
1028          If so, then we just demangled an <unqualified-template-name>.  */
1029       if (peek_char (dm) == 'I') 
1030         {
1031           /* A template name of the form std::<unqualified-name> is a
1032              substitution candidate.  */
1033           if (is_std_substitution)
1034             RETURN_IF_ERROR (substitution_add (dm, start, 0));
1035           /* Demangle the <template-args> here.  */
1036           RETURN_IF_ERROR (demangle_template_args (dm));
1037           *encode_return_type = !suppress_return_type;
1038         }
1039       else
1040         *encode_return_type = 0;
1041
1042       break;
1043
1044     default:
1045       /* This is an <unscoped-name> or <unscoped-template-name>.  */
1046       RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));
1047
1048       /* If the <unqualified-name> is followed by template args, this
1049          is an <unscoped-template-name>.  */
1050       if (peek_char (dm) == 'I')
1051         {
1052           /* Add a substitution for the unqualified template name.  */
1053           RETURN_IF_ERROR (substitution_add (dm, start, 0));
1054
1055           RETURN_IF_ERROR (demangle_template_args (dm));
1056           *encode_return_type = !suppress_return_type;
1057         }
1058       else
1059         *encode_return_type = 0;
1060
1061       break;
1062     }
1063
1064   return STATUS_OK;
1065 }
1066
1067 /* Demangles and emits a <nested-name>. 
1068
1069     <nested-name>     ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E  */
1070
1071 static status_t
1072 demangle_nested_name (dm, encode_return_type)
1073      demangling_t dm;
1074      int *encode_return_type;
1075 {
1076   char peek;
1077
1078   DEMANGLE_TRACE ("nested-name", dm);
1079
1080   RETURN_IF_ERROR (demangle_char (dm, 'N'));
1081
1082   peek = peek_char (dm);
1083   if (peek == 'r' || peek == 'V' || peek == 'K')
1084     {
1085       status_t status;
1086
1087       /* Snarf up and emit CV qualifiers.  */
1088       dyn_string_t cv_qualifiers = dyn_string_new (24);
1089       if (cv_qualifiers == NULL)
1090         return STATUS_ALLOCATION_FAILED;
1091
1092       demangle_CV_qualifiers (dm, cv_qualifiers);
1093       status = result_append_string (dm, cv_qualifiers);
1094       dyn_string_delete (cv_qualifiers);
1095       RETURN_IF_ERROR (status);
1096       RETURN_IF_ERROR (result_append_space (dm));
1097     }
1098   
1099   RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
1100   /* No need to demangle the final <unqualified-name>; demangle_prefix
1101      will handle it.  */
1102   RETURN_IF_ERROR (demangle_char (dm, 'E'));
1103
1104   return STATUS_OK;
1105 }
1106
1107 /* Demangles and emits a <prefix>.
1108
1109     <prefix>            ::= <prefix> <unqualified-name>
1110                         ::= <template-prefix> <template-args>
1111                         ::= # empty
1112                         ::= <substitution>
1113
1114     <template-prefix>   ::= <prefix>
1115                         ::= <substitution>  */
1116
1117 static status_t
1118 demangle_prefix (dm, encode_return_type)
1119      demangling_t dm;
1120      int *encode_return_type;
1121 {
1122   int start = substitution_start (dm);
1123   int nested = 0;
1124
1125   /* ENCODE_RETURN_TYPE is updated as we decend the nesting chain.
1126      After <template-args>, it is set to non-zero; after everything
1127      else it is set to zero.  */
1128
1129   /* Generally, the return type is encoded if the function is a
1130      template-id, and suppressed otherwise.  There are a few cases,
1131      though, in which the return type is not encoded even for a
1132      templated function.  In these cases, this flag is set.  */
1133   int suppress_return_type = 0;
1134
1135   DEMANGLE_TRACE ("prefix", dm);
1136
1137   while (1)
1138     {
1139       char peek;
1140
1141       if (end_of_name_p (dm))
1142         return "Unexpected end of name in <compound-name>.";
1143
1144       peek = peek_char (dm);
1145       
1146       /* We'll initialize suppress_return_type to false, and set it to true
1147          if we end up demangling a constructor name.  However, make
1148          sure we're not actually about to demangle template arguments
1149          -- if so, this is the <template-args> following a
1150          <template-prefix>, so we'll want the previous flag value
1151          around.  */
1152       if (peek != 'I')
1153         suppress_return_type = 0;
1154
1155       if (IS_DIGIT ((unsigned char) peek)
1156           || (peek >= 'a' && peek <= 'z')
1157           || peek == 'C' || peek == 'D'
1158           || peek == 'S')
1159         {
1160           /* We have another level of scope qualification.  */
1161           if (nested)
1162             RETURN_IF_ERROR (result_append (dm, "::"));
1163           else
1164             nested = 1;
1165
1166           if (peek == 'S')
1167             /* The substitution determines whether this is a
1168                template-id.  */
1169             RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
1170           else
1171             {
1172               /* It's just a name.  */
1173               RETURN_IF_ERROR 
1174                 (demangle_unqualified_name (dm, &suppress_return_type));
1175               *encode_return_type = 0;
1176             }
1177         }
1178       else if (peek == 'Z')
1179         RETURN_IF_ERROR (demangle_local_name (dm));
1180       else if (peek == 'I')
1181         {
1182           RETURN_IF_ERROR (demangle_template_args (dm));
1183
1184           /* Now we want to indicate to the caller that we've
1185              demangled template arguments, thus the prefix was a
1186              <template-prefix>.  That's so that the caller knows to
1187              demangle the function's return type, if this turns out to
1188              be a function name.  But, if it's a member template
1189              constructor or a templated conversion operator, report it
1190              as untemplated.  Those never get encoded return types.  */
1191           *encode_return_type = !suppress_return_type;
1192         }
1193       else if (peek == 'E')
1194         /* All done.  */
1195         return STATUS_OK;
1196       else
1197         return "Unexpected character in <compound-name>.";
1198
1199       if (peek != 'S'
1200           && peek_char (dm) != 'E')
1201         /* Add a new substitution for the prefix thus far.  */
1202         RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));
1203     }
1204 }
1205
1206 /* Demangles and emits an <unqualified-name>.  If this
1207    <unqualified-name> is for a special function type that should never
1208    have its return type encoded (particularly, a constructor or
1209    conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise,
1210    it is set to zero.
1211
1212     <unqualified-name>  ::= <operator-name>
1213                         ::= <special-name>  
1214                         ::= <source-name>  */
1215
1216 static status_t
1217 demangle_unqualified_name (dm, suppress_return_type)
1218      demangling_t dm;
1219      int *suppress_return_type;
1220 {
1221   char peek = peek_char (dm);
1222
1223   DEMANGLE_TRACE ("unqualified-name", dm);
1224
1225   /* By default, don't force suppression of the return type (though
1226      non-template functions still don't get a return type encoded).  */ 
1227   *suppress_return_type = 0;
1228
1229   if (IS_DIGIT ((unsigned char) peek))
1230     RETURN_IF_ERROR (demangle_source_name (dm));
1231   else if (peek >= 'a' && peek <= 'z')
1232     {
1233       int num_args;
1234
1235       /* Conversion operators never have a return type encoded.  */
1236       if (peek == 'c' && peek_char_next (dm) == 'v')
1237         *suppress_return_type = 1;
1238
1239       RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args));
1240     }
1241   else if (peek == 'C' || peek == 'D')
1242     {
1243       /* Constructors never have a return type encoded.  */
1244       if (peek == 'C')
1245         *suppress_return_type = 1;
1246
1247       RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
1248     }
1249   else
1250     return "Unexpected character in <unqualified-name>.";
1251
1252   return STATUS_OK;
1253 }
1254
1255 /* Demangles and emits <source-name>.  
1256
1257     <source-name> ::= <length number> <identifier>  */
1258
1259 static status_t
1260 demangle_source_name (dm)
1261      demangling_t dm;
1262 {
1263   int length;
1264
1265   DEMANGLE_TRACE ("source-name", dm);
1266
1267   /* Decode the length of the identifier.  */
1268   RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0));
1269   if (length == 0)
1270     return "Zero length in <source-name>.";
1271
1272   /* Now the identifier itself.  It's placed into last_source_name,
1273      where it can be used to build a constructor or destructor name.  */
1274   RETURN_IF_ERROR (demangle_identifier (dm, length, 
1275                                         dm->last_source_name));
1276
1277   /* Emit it.  */
1278   RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
1279
1280   return STATUS_OK;
1281 }
1282
1283 /* Demangles a number, either a <number> or a <positive-number> at the
1284    current position, consuming all consecutive digit characters.  Sets
1285    *VALUE to the resulting numberand returns STATUS_OK.  The number is
1286    interpreted as BASE, which must be either 10 or 36.  If IS_SIGNED
1287    is non-zero, negative numbers -- prefixed with `n' -- are accepted.
1288
1289     <number> ::= [n] <positive-number>
1290
1291     <positive-number> ::= <decimal integer>  */
1292
1293 static status_t
1294 demangle_number (dm, value, base, is_signed)
1295      demangling_t dm;
1296      int *value;
1297      int base;
1298      int is_signed;
1299 {
1300   dyn_string_t number = dyn_string_new (10);
1301
1302   DEMANGLE_TRACE ("number", dm);
1303
1304   if (number == NULL)
1305     return STATUS_ALLOCATION_FAILED;
1306
1307   demangle_number_literally (dm, number, base, is_signed);
1308   *value = strtol (dyn_string_buf (number), NULL, base);
1309   dyn_string_delete (number);
1310
1311   return STATUS_OK;
1312 }
1313
1314 /* Demangles a number at the current position.  The digits (and minus
1315    sign, if present) that make up the number are appended to STR.
1316    Only base-BASE digits are accepted; BASE must be either 10 or 36.
1317    If IS_SIGNED, negative numbers -- prefixed with `n' -- are
1318    accepted.  Does not consume a trailing underscore or other
1319    terminating character.  */
1320
1321 static status_t
1322 demangle_number_literally (dm, str, base, is_signed)
1323      demangling_t dm;
1324      dyn_string_t str;
1325      int base;
1326      int is_signed;
1327 {
1328   DEMANGLE_TRACE ("number*", dm);
1329
1330   if (base != 10 && base != 36)
1331     return STATUS_INTERNAL_ERROR;
1332
1333   /* An `n' denotes a negative number.  */
1334   if (is_signed && peek_char (dm) == 'n')
1335     {
1336       /* Skip past the n.  */
1337       advance_char (dm);
1338       /* The normal way to write a negative number is with a minus
1339          sign.  */
1340       if (!dyn_string_append_char (str, '-'))
1341         return STATUS_ALLOCATION_FAILED;
1342     }
1343
1344   /* Loop until we hit a non-digit.  */
1345   while (1)
1346     {
1347       char peek = peek_char (dm);
1348       if (IS_DIGIT ((unsigned char) peek)
1349           || (base == 36 && peek >= 'A' && peek <= 'Z'))
1350         {
1351           /* Accumulate digits.  */
1352           if (!dyn_string_append_char (str, next_char (dm)))
1353             return STATUS_ALLOCATION_FAILED;
1354         }
1355       else
1356         /* Not a digit?  All done.  */
1357         break;
1358     }
1359
1360   return STATUS_OK;
1361 }
1362
1363 /* Demangles an identifier at the current position of LENGTH
1364    characters and places it in IDENTIFIER.  */
1365
1366 static status_t
1367 demangle_identifier (dm, length, identifier)
1368      demangling_t dm;
1369      int length;
1370      dyn_string_t identifier;
1371 {
1372   DEMANGLE_TRACE ("identifier", dm);
1373
1374   dyn_string_clear (identifier);
1375   if (!dyn_string_resize (identifier, length))
1376     return STATUS_ALLOCATION_FAILED;
1377
1378   while (length-- > 0)
1379     {
1380       if (end_of_name_p (dm))
1381         return "Unexpected end of name in <identifier>.";
1382       if (!dyn_string_append_char (identifier, next_char (dm)))
1383         return STATUS_ALLOCATION_FAILED;
1384     }
1385
1386   /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'
1387      followed by the source file name and some random characters.
1388      Unless we're in strict mode, decipher these names appropriately.  */
1389   if (!flag_strict)
1390     {
1391       char *name = dyn_string_buf (identifier);
1392       int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
1393
1394       /* Compare the first, fixed part.  */
1395       if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
1396         {
1397           name += prefix_length;
1398           /* The next character might be a period, an underscore, or
1399              dollar sign, depending on the target architecture's
1400              assembler's capabilities.  After that comes an `N'.  */
1401           if ((*name == '.' || *name == '_' || *name == '$')
1402               && *(name + 1) == 'N')
1403             /* This looks like the anonymous namespace identifier.
1404                Replace it with something comprehensible.  */
1405             dyn_string_copy_cstr (identifier, "(anonymous namespace)");
1406         }
1407     }
1408
1409   return STATUS_OK;
1410 }
1411
1412 /* Demangles and emits an <operator-name>.  If SHORT_NAME is non-zero,
1413    the short form is emitted; otherwise the full source form
1414    (`operator +' etc.) is emitted.  *NUM_ARGS is set to the number of
1415    operands that the operator takes.  
1416
1417     <operator-name>
1418                   ::= nw        # new           
1419                   ::= na        # new[]
1420                   ::= dl        # delete        
1421                   ::= da        # delete[]      
1422                   ::= ps        # + (unary)
1423                   ::= ng        # - (unary)     
1424                   ::= ad        # & (unary)     
1425                   ::= de        # * (unary)     
1426                   ::= co        # ~             
1427                   ::= pl        # +             
1428                   ::= mi        # -             
1429                   ::= ml        # *             
1430                   ::= dv        # /             
1431                   ::= rm        # %             
1432                   ::= an        # &             
1433                   ::= or        # |             
1434                   ::= eo        # ^             
1435                   ::= aS        # =             
1436                   ::= pL        # +=            
1437                   ::= mI        # -=            
1438                   ::= mL        # *=            
1439                   ::= dV        # /=            
1440                   ::= rM        # %=            
1441                   ::= aN        # &=            
1442                   ::= oR        # |=            
1443                   ::= eO        # ^=            
1444                   ::= ls        # <<            
1445                   ::= rs        # >>            
1446                   ::= lS        # <<=           
1447                   ::= rS        # >>=           
1448                   ::= eq        # ==            
1449                   ::= ne        # !=            
1450                   ::= lt        # <             
1451                   ::= gt        # >             
1452                   ::= le        # <=            
1453                   ::= ge        # >=            
1454                   ::= nt        # !             
1455                   ::= aa        # &&            
1456                   ::= oo        # ||            
1457                   ::= pp        # ++            
1458                   ::= mm        # --            
1459                   ::= cm        # ,             
1460                   ::= pm        # ->*           
1461                   ::= pt        # ->            
1462                   ::= cl        # ()            
1463                   ::= ix        # []            
1464                   ::= qu        # ?
1465                   ::= sz        # sizeof 
1466                   ::= cv <type> # cast        
1467                   ::= v [0-9] <source-name>  # vendor extended operator  */
1468
1469 static status_t
1470 demangle_operator_name (dm, short_name, num_args)
1471      demangling_t dm;
1472      int short_name;
1473      int *num_args;
1474 {
1475   struct operator_code
1476   {
1477     /* The mangled code for this operator.  */
1478     const char *code;
1479     /* The source name of this operator.  */
1480     const char *name;
1481     /* The number of arguments this operator takes.  */
1482     int num_args;
1483   };
1484
1485   static const struct operator_code operators[] = 
1486   {
1487     { "aN", "&="       , 2 },
1488     { "aS", "="        , 2 },
1489     { "aa", "&&"       , 2 },
1490     { "ad", "&"        , 1 },
1491     { "an", "&"        , 2 },
1492     { "cl", "()"       , 0 },
1493     { "cm", ","        , 2 },
1494     { "co", "~"        , 1 },
1495     { "dV", "/="       , 2 },
1496     { "da", " delete[]", 1 },
1497     { "de", "*"        , 1 },
1498     { "dl", " delete"  , 1 },
1499     { "dv", "/"        , 2 },
1500     { "eO", "^="       , 2 },
1501     { "eo", "^"        , 2 },
1502     { "eq", "=="       , 2 },
1503     { "ge", ">="       , 2 },
1504     { "gt", ">"        , 2 },
1505     { "ix", "[]"       , 2 },
1506     { "lS", "<<="      , 2 },
1507     { "le", "<="       , 2 },
1508     { "ls", "<<"       , 2 },
1509     { "lt", "<"        , 2 },
1510     { "mI", "-="       , 2 },
1511     { "mL", "*="       , 2 },
1512     { "mi", "-"        , 2 },
1513     { "ml", "*"        , 2 },
1514     { "mm", "--"       , 1 },
1515     { "na", " new[]"   , 1 },
1516     { "ne", "!="       , 2 },
1517     { "ng", "-"        , 1 },
1518     { "nt", "!"        , 1 },
1519     { "nw", " new"     , 1 },
1520     { "oR", "|="       , 2 },
1521     { "oo", "||"       , 2 },
1522     { "or", "|"        , 2 },
1523     { "pL", "+="       , 2 },
1524     { "pl", "+"        , 2 },
1525     { "pm", "->*"      , 2 },
1526     { "pp", "++"       , 1 },
1527     { "ps", "+"        , 1 },
1528     { "pt", "->"       , 2 },
1529     { "qu", "?"        , 3 },
1530     { "rM", "%="       , 2 },
1531     { "rS", ">>="      , 2 },
1532     { "rm", "%"        , 2 },
1533     { "rs", ">>"       , 2 },
1534     { "sz", " sizeof"  , 1 }
1535   };
1536
1537   const int num_operators = 
1538     sizeof (operators) / sizeof (struct operator_code);
1539
1540   int c0 = next_char (dm);
1541   int c1 = next_char (dm);
1542   const struct operator_code* p1 = operators;
1543   const struct operator_code* p2 = operators + num_operators;
1544
1545   DEMANGLE_TRACE ("operator-name", dm);
1546
1547   /* Is this a vendor-extended operator?  */
1548   if (c0 == 'v' && IS_DIGIT (c1))
1549     {
1550       RETURN_IF_ERROR (result_append (dm, "operator "));
1551       RETURN_IF_ERROR (demangle_source_name (dm));
1552       *num_args = 0;
1553       return STATUS_OK;
1554     }
1555
1556   /* Is this a conversion operator?  */
1557   if (c0 == 'c' && c1 == 'v')
1558     {
1559       RETURN_IF_ERROR (result_append (dm, "operator "));
1560       /* Demangle the converted-to type.  */
1561       RETURN_IF_ERROR (demangle_type (dm));
1562       *num_args = 0;
1563       return STATUS_OK;
1564     }
1565
1566   /* Perform a binary search for the operator code.  */
1567   while (1)
1568     {
1569       const struct operator_code* p = p1 + (p2 - p1) / 2;
1570       char match0 = p->code[0];
1571       char match1 = p->code[1];
1572
1573       if (c0 == match0 && c1 == match1)
1574         /* Found it.  */
1575         {
1576           if (!short_name)
1577             RETURN_IF_ERROR (result_append (dm, "operator"));
1578           RETURN_IF_ERROR (result_append (dm, p->name));
1579           *num_args = p->num_args;
1580
1581           return STATUS_OK;
1582         }
1583
1584       if (p == p1)
1585         /* Couldn't find it.  */
1586         return "Unknown code in <operator-name>.";
1587
1588       /* Try again.  */
1589       if (c0 < match0 || (c0 == match0 && c1 < match1))
1590         p2 = p;
1591       else
1592         p1 = p;
1593     }
1594 }
1595
1596 /* Demangles and omits an <nv-offset>.
1597
1598     <nv-offset> ::= <offset number>   # non-virtual base override  */
1599
1600 static status_t
1601 demangle_nv_offset (dm)
1602      demangling_t dm;
1603 {
1604   dyn_string_t number;
1605   status_t status = STATUS_OK;
1606
1607   DEMANGLE_TRACE ("h-offset", dm);
1608
1609   /* Demangle the offset.  */
1610   number = dyn_string_new (4);
1611   if (number == NULL)
1612     return STATUS_ALLOCATION_FAILED;
1613   demangle_number_literally (dm, number, 10, 1);
1614
1615   /* Don't display the offset unless in verbose mode.  */
1616   if (flag_verbose)
1617     {
1618       status = result_append (dm, " [nv:");
1619       if (STATUS_NO_ERROR (status))
1620         status = result_append_string (dm, number);
1621       if (STATUS_NO_ERROR (status))
1622         status = result_append_char (dm, ']');
1623     }
1624
1625   /* Clean up.  */
1626   dyn_string_delete (number);
1627   RETURN_IF_ERROR (status);
1628   return STATUS_OK;
1629 }
1630
1631 /* Demangles and emits a <v-offset>. 
1632
1633     <v-offset>  ::= <offset number> _ <virtual offset number>
1634                         # virtual base override, with vcall offset  */
1635
1636 static status_t
1637 demangle_v_offset (dm)
1638      demangling_t dm;
1639 {
1640   dyn_string_t number;
1641   status_t status = STATUS_OK;
1642
1643   DEMANGLE_TRACE ("v-offset", dm);
1644
1645   /* Demangle the offset.  */
1646   number = dyn_string_new (4);
1647   if (number == NULL)
1648     return STATUS_ALLOCATION_FAILED;
1649   demangle_number_literally (dm, number, 10, 1);
1650
1651   /* Don't display the offset unless in verbose mode.  */
1652   if (flag_verbose)
1653     {
1654       status = result_append (dm, " [v:");
1655       if (STATUS_NO_ERROR (status))
1656         status = result_append_string (dm, number);
1657       if (STATUS_NO_ERROR (status))
1658         result_append_char (dm, ',');
1659     }
1660   dyn_string_delete (number);
1661   RETURN_IF_ERROR (status);
1662
1663   /* Demangle the separator.  */
1664   RETURN_IF_ERROR (demangle_char (dm, '_'));
1665
1666   /* Demangle the vcall offset.  */
1667   number = dyn_string_new (4);
1668   if (number == NULL)
1669     return STATUS_ALLOCATION_FAILED;
1670   demangle_number_literally (dm, number, 10, 1);
1671
1672   /* Don't display the vcall offset unless in verbose mode.  */
1673   if (flag_verbose)
1674     {
1675       status = result_append_string (dm, number);
1676       if (STATUS_NO_ERROR (status))
1677         status = result_append_char (dm, ']');
1678     }
1679   dyn_string_delete (number);
1680   RETURN_IF_ERROR (status);
1681
1682   return STATUS_OK;
1683 }
1684
1685 /* Demangles and emits a <call-offset>.
1686
1687     <call-offset> ::= h <nv-offset> _
1688                   ::= v <v-offset> _  */
1689
1690 static status_t
1691 demangle_call_offset (dm)
1692      demangling_t dm;
1693 {
1694   DEMANGLE_TRACE ("call-offset", dm);
1695
1696   switch (peek_char (dm))
1697     {
1698     case 'h':
1699       advance_char (dm);
1700       /* Demangle the offset.  */
1701       RETURN_IF_ERROR (demangle_nv_offset (dm));
1702       /* Demangle the separator.  */
1703       RETURN_IF_ERROR (demangle_char (dm, '_'));
1704       break;
1705
1706     case 'v':
1707       advance_char (dm);
1708       /* Demangle the offset.  */
1709       RETURN_IF_ERROR (demangle_v_offset (dm));
1710       /* Demangle the separator.  */
1711       RETURN_IF_ERROR (demangle_char (dm, '_'));
1712       break;
1713
1714     default:
1715       return "Unrecognized <call-offset>.";
1716     }
1717
1718   return STATUS_OK;
1719 }
1720
1721 /* Demangles and emits a <special-name>.  
1722
1723     <special-name> ::= GV <object name>   # Guard variable
1724                    ::= TV <type>          # virtual table
1725                    ::= TT <type>          # VTT
1726                    ::= TI <type>          # typeinfo structure
1727                    ::= TS <type>          # typeinfo name  
1728
1729    Other relevant productions include thunks:
1730
1731     <special-name> ::= T <call-offset> <base encoding>
1732                          # base is the nominal target function of thunk
1733
1734     <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
1735                          # base is the nominal target function of thunk
1736                          # first call-offset is 'this' adjustment
1737                          # second call-offset is result adjustment
1738
1739    where
1740
1741     <call-offset>  ::= h <nv-offset> _
1742                    ::= v <v-offset> _
1743
1744    Also demangles the special g++ manglings,
1745
1746     <special-name> ::= TC <type> <offset number> _ <base type>
1747                                           # construction vtable
1748                    ::= TF <type>          # typeinfo function (old ABI only)
1749                    ::= TJ <type>          # java Class structure  */
1750
1751 static status_t
1752 demangle_special_name (dm)
1753      demangling_t dm;
1754 {
1755   dyn_string_t number;
1756   int unused;
1757   char peek = peek_char (dm);
1758
1759   DEMANGLE_TRACE ("special-name", dm);
1760
1761   if (peek == 'G')
1762     {
1763       /* A guard variable name.  Consume the G.  */
1764       advance_char (dm);
1765       RETURN_IF_ERROR (demangle_char (dm, 'V'));
1766       RETURN_IF_ERROR (result_append (dm, "guard variable for "));
1767       RETURN_IF_ERROR (demangle_name (dm, &unused));
1768     }
1769   else if (peek == 'T')
1770     {
1771       status_t status = STATUS_OK;
1772
1773       /* Other C++ implementation miscellania.  Consume the T.  */
1774       advance_char (dm);
1775
1776       switch (peek_char (dm))
1777         {
1778         case 'V':
1779           /* Virtual table.  */
1780           advance_char (dm);
1781           RETURN_IF_ERROR (result_append (dm, "vtable for "));
1782           RETURN_IF_ERROR (demangle_type (dm));
1783           break;
1784
1785         case 'T':
1786           /* VTT structure.  */
1787           advance_char (dm);
1788           RETURN_IF_ERROR (result_append (dm, "VTT for "));
1789           RETURN_IF_ERROR (demangle_type (dm));
1790           break;
1791
1792         case 'I':
1793           /* Typeinfo structure.  */
1794           advance_char (dm);
1795           RETURN_IF_ERROR (result_append (dm, "typeinfo for "));
1796           RETURN_IF_ERROR (demangle_type (dm));
1797           break;
1798
1799         case 'F':
1800           /* Typeinfo function.  Used only in old ABI with new mangling.  */
1801           advance_char (dm);
1802           RETURN_IF_ERROR (result_append (dm, "typeinfo fn for "));
1803           RETURN_IF_ERROR (demangle_type (dm));
1804           break;
1805
1806         case 'S':
1807           /* Character string containing type name, used in typeinfo. */
1808           advance_char (dm);
1809           RETURN_IF_ERROR (result_append (dm, "typeinfo name for "));
1810           RETURN_IF_ERROR (demangle_type (dm));
1811           break;
1812
1813         case 'J':
1814           /* The java Class variable corresponding to a C++ class.  */
1815           advance_char (dm);
1816           RETURN_IF_ERROR (result_append (dm, "java Class for "));
1817           RETURN_IF_ERROR (demangle_type (dm));
1818           break;
1819
1820         case 'h':
1821           /* Non-virtual thunk.  */
1822           advance_char (dm);
1823           RETURN_IF_ERROR (result_append (dm, "non-virtual thunk"));
1824           RETURN_IF_ERROR (demangle_nv_offset (dm));
1825           /* Demangle the separator.  */
1826           RETURN_IF_ERROR (demangle_char (dm, '_'));
1827           /* Demangle and emit the target name and function type.  */
1828           RETURN_IF_ERROR (result_append (dm, " to "));
1829           RETURN_IF_ERROR (demangle_encoding (dm));
1830           break;
1831
1832         case 'v':
1833           /* Virtual thunk.  */
1834           advance_char (dm);
1835           RETURN_IF_ERROR (result_append (dm, "virtual thunk"));
1836           RETURN_IF_ERROR (demangle_v_offset (dm));
1837           /* Demangle the separator.  */
1838           RETURN_IF_ERROR (demangle_char (dm, '_'));
1839           /* Demangle and emit the target function.  */
1840           RETURN_IF_ERROR (result_append (dm, " to "));
1841           RETURN_IF_ERROR (demangle_encoding (dm));
1842           break;
1843
1844         case 'c':
1845           /* Covariant return thunk.  */
1846           advance_char (dm);
1847           RETURN_IF_ERROR (result_append (dm, "covariant return thunk"));
1848           RETURN_IF_ERROR (demangle_call_offset (dm));
1849           RETURN_IF_ERROR (demangle_call_offset (dm));
1850           /* Demangle and emit the target function.  */
1851           RETURN_IF_ERROR (result_append (dm, " to "));
1852           RETURN_IF_ERROR (demangle_encoding (dm));
1853           break;
1854
1855         case 'C':
1856           /* TC is a special g++ mangling for a construction vtable. */
1857           if (!flag_strict)
1858             {
1859               dyn_string_t derived_type;
1860
1861               advance_char (dm);
1862               RETURN_IF_ERROR (result_append (dm, "construction vtable for "));
1863
1864               /* Demangle the derived type off to the side.  */
1865               RETURN_IF_ERROR (result_push (dm));
1866               RETURN_IF_ERROR (demangle_type (dm));
1867               derived_type = (dyn_string_t) result_pop (dm);
1868
1869               /* Demangle the offset.  */
1870               number = dyn_string_new (4);
1871               if (number == NULL)
1872                 {
1873                   dyn_string_delete (derived_type);
1874                   return STATUS_ALLOCATION_FAILED;
1875                 }
1876               demangle_number_literally (dm, number, 10, 1);
1877               /* Demangle the underscore separator.  */
1878               status = demangle_char (dm, '_');
1879
1880               /* Demangle the base type.  */
1881               if (STATUS_NO_ERROR (status))
1882                 status = demangle_type (dm);
1883
1884               /* Emit the derived type.  */
1885               if (STATUS_NO_ERROR (status))
1886                 status = result_append (dm, "-in-");
1887               if (STATUS_NO_ERROR (status))
1888                 status = result_append_string (dm, derived_type);
1889               dyn_string_delete (derived_type);
1890
1891               /* Don't display the offset unless in verbose mode.  */
1892               if (flag_verbose)
1893                 {
1894                   status = result_append_char (dm, ' ');
1895                   if (STATUS_NO_ERROR (status))
1896                     result_append_string (dm, number);
1897                 }
1898               dyn_string_delete (number);
1899               RETURN_IF_ERROR (status);
1900               break;
1901             }
1902           /* If flag_strict, fall through.  */
1903
1904         default:
1905           return "Unrecognized <special-name>.";
1906         }
1907     }
1908   else
1909     return STATUS_ERROR;
1910
1911   return STATUS_OK;
1912 }
1913
1914 /* Demangles and emits a <ctor-dtor-name>.  
1915    
1916     <ctor-dtor-name>
1917                    ::= C1  # complete object (in-charge) ctor
1918                    ::= C2  # base object (not-in-charge) ctor
1919                    ::= C3  # complete object (in-charge) allocating ctor
1920                    ::= D0  # deleting (in-charge) dtor
1921                    ::= D1  # complete object (in-charge) dtor
1922                    ::= D2  # base object (not-in-charge) dtor  */
1923
1924 static status_t
1925 demangle_ctor_dtor_name (dm)
1926      demangling_t dm;
1927 {
1928   static const char *const ctor_flavors[] = 
1929   {
1930     "in-charge",
1931     "not-in-charge",
1932     "allocating"
1933   };
1934   static const char *const dtor_flavors[] = 
1935   {
1936     "in-charge deleting",
1937     "in-charge",
1938     "not-in-charge"
1939   };
1940
1941   int flavor;
1942   char peek = peek_char (dm);
1943
1944   DEMANGLE_TRACE ("ctor-dtor-name", dm);
1945   
1946   if (peek == 'C')
1947     {
1948       /* A constructor name.  Consume the C.  */
1949       advance_char (dm);
1950       if (peek_char (dm) < '1' || peek_char (dm) > '3')
1951         return "Unrecognized constructor.";
1952       RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
1953       /* Print the flavor of the constructor if in verbose mode.  */
1954       flavor = next_char (dm) - '1';
1955       if (flag_verbose)
1956         {
1957           RETURN_IF_ERROR (result_append (dm, "["));
1958           RETURN_IF_ERROR (result_append (dm, ctor_flavors[flavor]));
1959           RETURN_IF_ERROR (result_append_char (dm, ']'));
1960         }
1961     }
1962   else if (peek == 'D')
1963     {
1964       /* A destructor name.  Consume the D.  */
1965       advance_char (dm);
1966       if (peek_char (dm) < '0' || peek_char (dm) > '2')
1967         return "Unrecognized destructor.";
1968       RETURN_IF_ERROR (result_append_char (dm, '~'));
1969       RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
1970       /* Print the flavor of the destructor if in verbose mode.  */
1971       flavor = next_char (dm) - '0';
1972       if (flag_verbose)
1973         {
1974           RETURN_IF_ERROR (result_append (dm, " ["));
1975           RETURN_IF_ERROR (result_append (dm, dtor_flavors[flavor]));
1976           RETURN_IF_ERROR (result_append_char (dm, ']'));
1977         }
1978     }
1979   else
1980     return STATUS_ERROR;
1981
1982   return STATUS_OK;
1983 }
1984
1985 /* Handle pointer, reference, and pointer-to-member cases for
1986    demangle_type.  All consecutive `P's, `R's, and 'M's are joined to
1987    build a pointer/reference type.  We snarf all these, plus the
1988    following <type>, all at once since we need to know whether we have
1989    a pointer to data or pointer to function to construct the right
1990    output syntax.  C++'s pointer syntax is hairy.  
1991
1992    This function adds substitution candidates for every nested
1993    pointer/reference type it processes, including the outermost, final
1994    type, assuming the substitution starts at SUBSTITUTION_START in the
1995    demangling result.  For example, if this function demangles
1996    `PP3Foo', it will add a substitution for `Foo', `Foo*', and
1997    `Foo**', in that order.
1998
1999    *INSERT_POS is a quantity used internally, when this function calls
2000    itself recursively, to figure out where to insert pointer
2001    punctuation on the way up.  On entry to this function, INSERT_POS
2002    should point to a temporary value, but that value need not be
2003    initialized.
2004
2005      <type> ::= P <type>
2006             ::= R <type>
2007             ::= <pointer-to-member-type>
2008
2009      <pointer-to-member-type> ::= M </class/ type> </member/ type>  */
2010
2011 static status_t
2012 demangle_type_ptr (dm, insert_pos, substitution_start)
2013      demangling_t dm;
2014      int *insert_pos;
2015      int substitution_start;
2016 {
2017   char next;
2018   status_t status;
2019   int is_substitution_candidate = 1;
2020
2021   DEMANGLE_TRACE ("type*", dm);
2022
2023   /* Scan forward, collecting pointers and references into symbols,
2024      until we hit something else.  Then emit the type.  */
2025   next = peek_char (dm);
2026   if (next == 'P')
2027     {
2028       /* A pointer.  Snarf the `P'.  */
2029       advance_char (dm);
2030       /* Demangle the underlying type.  */
2031       RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos, 
2032                                           substitution_start));
2033       /* Insert an asterisk where we're told to; it doesn't
2034          necessarily go at the end.  */
2035       RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
2036       /* The next (outermost) pointer or reference character should go
2037          after this one.  */
2038       ++(*insert_pos);
2039     }
2040   else if (next == 'R')
2041     {
2042       /* A reference.  Snarf the `R'.  */
2043       advance_char (dm);
2044       /* Demangle the underlying type.  */
2045       RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos, 
2046                                           substitution_start));
2047       /* Insert an ampersand where we're told to; it doesn't
2048          necessarily go at the end.  */
2049       RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
2050       /* The next (outermost) pointer or reference character should go
2051          after this one.  */
2052       ++(*insert_pos);
2053     }
2054   else if (next == 'M')
2055     {
2056       /* A pointer-to-member.  */
2057       dyn_string_t class_type;
2058       
2059       /* Eat the 'M'.  */
2060       advance_char (dm);
2061       
2062       /* Capture the type of which this is a pointer-to-member.  */
2063       RETURN_IF_ERROR (result_push (dm));
2064       RETURN_IF_ERROR (demangle_type (dm));
2065       class_type = (dyn_string_t) result_pop (dm);
2066       
2067       if (peek_char (dm) == 'F')
2068         /* A pointer-to-member function.  We want output along the
2069            lines of `void (C::*) (int, int)'.  Demangle the function
2070            type, which would in this case give `void () (int, int)'
2071            and set *insert_pos to the spot between the first
2072            parentheses.  */
2073         status = demangle_type_ptr (dm, insert_pos, substitution_start);
2074       else
2075         {
2076           /* A pointer-to-member variable.  Demangle the type of the
2077              pointed-to member.  */
2078           status = demangle_type (dm);
2079           /* Make it pretty.  */
2080           if (STATUS_NO_ERROR (status))
2081             status = result_append_space (dm);
2082           /* The pointer-to-member notation (e.g. `C::*') follows the
2083              member's type.  */
2084           *insert_pos = result_length (dm);
2085         }
2086
2087       /* Build the pointer-to-member notation.  */
2088       if (STATUS_NO_ERROR (status))
2089         status = result_insert (dm, *insert_pos, "::*");
2090       if (STATUS_NO_ERROR (status))
2091         status = result_insert_string (dm, *insert_pos, class_type);
2092       /* There may be additional levels of (pointer or reference)
2093          indirection in this type.  If so, the `*' and `&' should be
2094          added after the pointer-to-member notation (e.g. `C::*&' for
2095          a reference to a pointer-to-member of class C).  */
2096       *insert_pos += dyn_string_length (class_type) + 3;
2097
2098       /* Clean up. */
2099       dyn_string_delete (class_type);
2100
2101       RETURN_IF_ERROR (status);
2102     }
2103   else if (next == 'F')
2104     {
2105       /* Ooh, tricky, a pointer-to-function.  When we demangle the
2106          function type, the return type should go at the very
2107          beginning.  */
2108       *insert_pos = result_length (dm);
2109       /* The parentheses indicate this is a function pointer or
2110          reference type.  */
2111       RETURN_IF_ERROR (result_append (dm, "()"));
2112       /* Now demangle the function type.  The return type will be
2113          inserted before the `()', and the argument list will go after
2114          it.  */
2115       RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
2116       /* We should now have something along the lines of 
2117          `void () (int, int)'.  The pointer or reference characters
2118          have to inside the first set of parentheses.  *insert_pos has
2119          already been updated to point past the end of the return
2120          type.  Move it one character over so it points inside the
2121          `()'.  */
2122       ++(*insert_pos);
2123     }
2124   else
2125     {
2126       /* No more pointer or reference tokens; this is therefore a
2127          pointer to data.  Finish up by demangling the underlying
2128          type.  */
2129       RETURN_IF_ERROR (demangle_type (dm));
2130       /* The pointer or reference characters follow the underlying
2131          type, as in `int*&'.  */
2132       *insert_pos = result_length (dm);
2133       /* Because of the production <type> ::= <substitution>,
2134          demangle_type will already have added the underlying type as
2135          a substitution candidate.  Don't do it again.  */
2136       is_substitution_candidate = 0;
2137     }
2138   
2139   if (is_substitution_candidate)
2140     RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
2141   
2142   return STATUS_OK;
2143 }
2144
2145 /* Demangles and emits a <type>.  
2146
2147     <type> ::= <builtin-type>
2148            ::= <function-type>
2149            ::= <class-enum-type>
2150            ::= <array-type>
2151            ::= <pointer-to-member-type>
2152            ::= <template-param>
2153            ::= <template-template-param> <template-args>
2154            ::= <CV-qualifiers> <type>
2155            ::= P <type>   # pointer-to
2156            ::= R <type>   # reference-to
2157            ::= C <type>   # complex pair (C 2000)
2158            ::= G <type>   # imaginary (C 2000)
2159            ::= U <source-name> <type>     # vendor extended type qualifier
2160            ::= <substitution>  */
2161
2162 static status_t
2163 demangle_type (dm)
2164      demangling_t dm;
2165 {
2166   int start = substitution_start (dm);
2167   char peek = peek_char (dm);
2168   char peek_next;
2169   int encode_return_type = 0;
2170   template_arg_list_t old_arg_list = current_template_arg_list (dm);
2171   int insert_pos;
2172
2173   /* A <type> can be a <substitution>; therefore, this <type> is a
2174      substitution candidate unless a special condition holds (see
2175      below).  */
2176   int is_substitution_candidate = 1;
2177
2178   DEMANGLE_TRACE ("type", dm);
2179
2180   /* A <class-enum-type> can start with a digit (a <source-name>), an
2181      N (a <nested-name>), or a Z (a <local-name>).  */
2182   if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
2183     RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type));
2184   /* Lower-case letters begin <builtin-type>s, except for `r', which
2185      denotes restrict.  */
2186   else if (peek >= 'a' && peek <= 'z' && peek != 'r')
2187     {
2188       RETURN_IF_ERROR (demangle_builtin_type (dm));
2189       /* Built-in types are not substitution candidates.  */
2190       is_substitution_candidate = 0;
2191     }
2192   else
2193     switch (peek)
2194       {
2195       case 'r':
2196       case 'V':
2197       case 'K':
2198         /* CV-qualifiers (including restrict).  We have to demangle
2199            them off to the side, since C++ syntax puts them in a funny
2200            place for qualified pointer and reference types.  */
2201         {
2202           status_t status;
2203           dyn_string_t cv_qualifiers = dyn_string_new (24);
2204
2205           if (cv_qualifiers == NULL)
2206             return STATUS_ALLOCATION_FAILED;
2207
2208           demangle_CV_qualifiers (dm, cv_qualifiers);
2209
2210           /* If the qualifiers apply to a pointer or reference, they
2211              need to come after the whole qualified type.  */
2212           if (peek_char (dm) == 'P' || peek_char (dm) == 'R')
2213             {
2214               status = demangle_type (dm);
2215               if (STATUS_NO_ERROR (status))
2216                 status = result_append_space (dm);
2217               if (STATUS_NO_ERROR (status))
2218                 status = result_append_string (dm, cv_qualifiers);
2219             }
2220           /* Otherwise, the qualifiers come first.  */
2221           else
2222             {
2223               status = result_append_string (dm, cv_qualifiers);
2224               if (STATUS_NO_ERROR (status))
2225                 status = result_append_space (dm);
2226               if (STATUS_NO_ERROR (status))
2227                 status = demangle_type (dm);
2228             }
2229
2230           dyn_string_delete (cv_qualifiers);
2231           RETURN_IF_ERROR (status);
2232         }
2233         break;
2234
2235       case 'F':
2236         return "Non-pointer or -reference function type.";
2237
2238       case 'A':
2239         RETURN_IF_ERROR (demangle_array_type (dm));
2240         break;
2241
2242       case 'T':
2243         /* It's either a <template-param> or a
2244            <template-template-param>.  In either case, demangle the
2245            `T' token first.  */
2246         RETURN_IF_ERROR (demangle_template_param (dm));
2247
2248         /* Check for a template argument list; if one is found, it's a
2249              <template-template-param> ::= <template-param>
2250                                        ::= <substitution>  */
2251         if (peek_char (dm) == 'I')
2252           {
2253             /* Add a substitution candidate.  The template parameter
2254                `T' token is a substitution candidate by itself,
2255                without the template argument list.  */
2256             RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
2257
2258             /* Now demangle the template argument list.  */
2259             RETURN_IF_ERROR (demangle_template_args (dm));
2260             /* The entire type, including the template template
2261                parameter and its argument list, will be added as a
2262                substitution candidate below.  */
2263           }
2264
2265         break;
2266
2267       case 'S':
2268         /* First check if this is a special substitution.  If it is,
2269            this is a <class-enum-type>.  Special substitutions have a
2270            letter following the `S'; other substitutions have a digit
2271            or underscore.  */
2272         peek_next = peek_char_next (dm);
2273         if (IS_DIGIT (peek_next) || peek_next == '_')
2274           {
2275             RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));
2276             
2277             /* The substituted name may have been a template name.
2278                Check if template arguments follow, and if so, demangle
2279                them.  */
2280             if (peek_char (dm) == 'I')
2281               RETURN_IF_ERROR (demangle_template_args (dm));
2282             else
2283               /* A substitution token is not itself a substitution
2284                  candidate.  (However, if the substituted template is
2285                  instantiated, the resulting type is.)  */
2286               is_substitution_candidate = 0;
2287           }
2288         else
2289           {
2290             /* Now some trickiness.  We have a special substitution
2291                here.  Often, the special substitution provides the
2292                name of a template that's subsequently instantiated,
2293                for instance `SaIcE' => std::allocator<char>.  In these
2294                cases we need to add a substitution candidate for the
2295                entire <class-enum-type> and thus don't want to clear
2296                the is_substitution_candidate flag.
2297
2298                However, it's possible that what we have here is a
2299                substitution token representing an entire type, such as
2300                `Ss' => std::string.  In this case, we mustn't add a
2301                new substitution candidate for this substitution token.
2302                To detect this case, remember where the start of the
2303                substitution token is.  */
2304             const char *next = dm->next;
2305             /* Now demangle the <class-enum-type>.  */
2306             RETURN_IF_ERROR 
2307               (demangle_class_enum_type (dm, &encode_return_type));
2308             /* If all that was just demangled is the two-character
2309                special substitution token, supress the addition of a
2310                new candidate for it.  */
2311             if (dm->next == next + 2)
2312               is_substitution_candidate = 0;
2313           }
2314
2315         break;
2316
2317       case 'P':
2318       case 'R':
2319       case 'M':
2320         RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
2321         /* demangle_type_ptr adds all applicable substitution
2322            candidates.  */
2323         is_substitution_candidate = 0;
2324         break;
2325
2326       case 'C':
2327         /* A C99 complex type.  */
2328         RETURN_IF_ERROR (result_append (dm, "complex "));
2329         advance_char (dm);
2330         RETURN_IF_ERROR (demangle_type (dm));
2331         break;
2332
2333       case 'G':
2334         /* A C99 imaginary type.  */
2335         RETURN_IF_ERROR (result_append (dm, "imaginary "));
2336         advance_char (dm);
2337         RETURN_IF_ERROR (demangle_type (dm));
2338         break;
2339
2340       case 'U':
2341         /* Vendor-extended type qualifier.  */
2342         advance_char (dm);
2343         RETURN_IF_ERROR (demangle_source_name (dm));
2344         RETURN_IF_ERROR (result_append_char (dm, ' '));
2345         RETURN_IF_ERROR (demangle_type (dm));
2346         break;
2347
2348       default:
2349         return "Unexpected character in <type>.";
2350       }
2351
2352   if (is_substitution_candidate)
2353     /* Add a new substitution for the type. If this type was a
2354        <template-param>, pass its index since from the point of
2355        substitutions; a <template-param> token is a substitution
2356        candidate distinct from the type that is substituted for it.  */
2357     RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
2358
2359   /* Pop off template argument lists added during mangling of this
2360      type.  */
2361   pop_to_template_arg_list (dm, old_arg_list);
2362
2363   return STATUS_OK;
2364 }
2365
2366 /* C++ source names of builtin types, indexed by the mangled code
2367    letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc).  */
2368 static const char *const builtin_type_names[26] = 
2369 {
2370   "signed char",              /* a */
2371   "bool",                     /* b */
2372   "char",                     /* c */
2373   "double",                   /* d */
2374   "long double",              /* e */
2375   "float",                    /* f */
2376   "__float128",               /* g */
2377   "unsigned char",            /* h */
2378   "int",                      /* i */
2379   "unsigned",                 /* j */
2380   NULL,                       /* k */
2381   "long",                     /* l */
2382   "unsigned long",            /* m */
2383   "__int128",                 /* n */
2384   "unsigned __int128",        /* o */
2385   NULL,                       /* p */
2386   NULL,                       /* q */
2387   NULL,                       /* r */
2388   "short",                    /* s */
2389   "unsigned short",           /* t */
2390   NULL,                       /* u */
2391   "void",                     /* v */
2392   "wchar_t",                  /* w */
2393   "long long",                /* x */
2394   "unsigned long long",       /* y */
2395   "..."                       /* z */
2396 };
2397
2398 /* Demangles and emits a <builtin-type>.  
2399
2400     <builtin-type> ::= v  # void
2401                    ::= w  # wchar_t
2402                    ::= b  # bool
2403                    ::= c  # char
2404                    ::= a  # signed char
2405                    ::= h  # unsigned char
2406                    ::= s  # short
2407                    ::= t  # unsigned short
2408                    ::= i  # int
2409                    ::= j  # unsigned int
2410                    ::= l  # long
2411                    ::= m  # unsigned long
2412                    ::= x  # long long, __int64
2413                    ::= y  # unsigned long long, __int64
2414                    ::= n  # __int128
2415                    ::= o  # unsigned __int128
2416                    ::= f  # float
2417                    ::= d  # double
2418                    ::= e  # long double, __float80
2419                    ::= g  # __float128
2420                    ::= z  # ellipsis
2421                    ::= u <source-name>    # vendor extended type  */
2422
2423 static status_t
2424 demangle_builtin_type (dm)
2425      demangling_t dm;
2426 {
2427
2428   char code = peek_char (dm);
2429
2430   DEMANGLE_TRACE ("builtin-type", dm);
2431
2432   if (code == 'u')
2433     {
2434       advance_char (dm);
2435       RETURN_IF_ERROR (demangle_source_name (dm));
2436       return STATUS_OK;
2437     }
2438   else if (code >= 'a' && code <= 'z')
2439     {
2440       const char *type_name = builtin_type_names[code - 'a'];
2441       if (type_name == NULL)
2442         return "Unrecognized <builtin-type> code.";
2443
2444       RETURN_IF_ERROR (result_append (dm, type_name));
2445       advance_char (dm);
2446       return STATUS_OK;
2447     }
2448   else
2449     return "Non-alphabetic <builtin-type> code.";
2450 }
2451
2452 /* Demangles all consecutive CV-qualifiers (const, volatile, and
2453    restrict) at the current position.  The qualifiers are appended to
2454    QUALIFIERS.  Returns STATUS_OK.  */
2455
2456 static status_t
2457 demangle_CV_qualifiers (dm, qualifiers)
2458      demangling_t dm;
2459      dyn_string_t qualifiers;
2460 {
2461   DEMANGLE_TRACE ("CV-qualifiers", dm);
2462
2463   while (1)
2464     {
2465       switch (peek_char (dm))
2466         {
2467         case 'r':
2468           if (!dyn_string_append_space (qualifiers))
2469             return STATUS_ALLOCATION_FAILED;
2470           if (!dyn_string_append_cstr (qualifiers, "restrict"))
2471             return STATUS_ALLOCATION_FAILED;
2472           break;
2473
2474         case 'V':
2475           if (!dyn_string_append_space (qualifiers))
2476             return STATUS_ALLOCATION_FAILED;
2477           if (!dyn_string_append_cstr (qualifiers, "volatile"))
2478             return STATUS_ALLOCATION_FAILED;
2479           break;
2480
2481         case 'K':
2482           if (!dyn_string_append_space (qualifiers))
2483             return STATUS_ALLOCATION_FAILED;
2484           if (!dyn_string_append_cstr (qualifiers, "const"))
2485             return STATUS_ALLOCATION_FAILED;
2486           break;
2487
2488         default:
2489           return STATUS_OK;
2490         }
2491
2492       advance_char (dm);
2493     }
2494 }
2495
2496 /* Demangles and emits a <function-type>.  *FUNCTION_NAME_POS is the
2497    position in the result string of the start of the function
2498    identifier, at which the function's return type will be inserted;
2499    *FUNCTION_NAME_POS is updated to position past the end of the
2500    function's return type.
2501
2502     <function-type> ::= F [Y] <bare-function-type> E  */
2503
2504 static status_t
2505 demangle_function_type (dm, function_name_pos)
2506      demangling_t dm;
2507      int *function_name_pos;
2508 {
2509   DEMANGLE_TRACE ("function-type", dm);
2510   RETURN_IF_ERROR (demangle_char (dm, 'F'));  
2511   if (peek_char (dm) == 'Y')
2512     {
2513       /* Indicate this function has C linkage if in verbose mode.  */
2514       if (flag_verbose)
2515         RETURN_IF_ERROR (result_append (dm, " [extern \"C\"] "));
2516       advance_char (dm);
2517     }
2518   RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
2519   RETURN_IF_ERROR (demangle_char (dm, 'E'));
2520   return STATUS_OK;
2521 }
2522
2523 /* Demangles and emits a <bare-function-type>.  RETURN_TYPE_POS is the
2524    position in the result string at which the function return type
2525    should be inserted.  If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the
2526    function's return type is assumed not to be encoded.  
2527
2528     <bare-function-type> ::= <signature type>+  */
2529
2530 static status_t
2531 demangle_bare_function_type (dm, return_type_pos)
2532      demangling_t dm;
2533      int *return_type_pos;
2534 {
2535   /* Sequence is the index of the current function parameter, counting
2536      from zero.  The value -1 denotes the return type.  */
2537   int sequence = 
2538     (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);
2539
2540   DEMANGLE_TRACE ("bare-function-type", dm);
2541
2542   RETURN_IF_ERROR (result_append_char (dm, '('));
2543   while (!end_of_name_p (dm) && peek_char (dm) != 'E')
2544     {
2545       if (sequence == -1)
2546         /* We're decoding the function's return type.  */
2547         {
2548           dyn_string_t return_type;
2549           status_t status = STATUS_OK;
2550
2551           /* Decode the return type off to the side.  */
2552           RETURN_IF_ERROR (result_push (dm));
2553           RETURN_IF_ERROR (demangle_type (dm));
2554           return_type = (dyn_string_t) result_pop (dm);
2555
2556           /* Add a space to the end of the type.  Insert the return
2557              type where we've been asked to. */
2558           if (!dyn_string_append_space (return_type))
2559             status = STATUS_ALLOCATION_FAILED;
2560           if (STATUS_NO_ERROR (status))
2561             {
2562               if (!dyn_string_insert (result_string (dm), *return_type_pos, 
2563                                       return_type))
2564                 status = STATUS_ALLOCATION_FAILED;
2565               else
2566                 *return_type_pos += dyn_string_length (return_type);
2567             }
2568
2569           dyn_string_delete (return_type);
2570           RETURN_IF_ERROR (status);
2571         }
2572       else 
2573         {
2574           /* Skip `void' parameter types.  One should only occur as
2575              the only type in a parameter list; in that case, we want
2576              to print `foo ()' instead of `foo (void)'.  */
2577           if (peek_char (dm) == 'v')
2578             /* Consume the v.  */
2579             advance_char (dm);
2580           else
2581             {
2582               /* Separate parameter types by commas.  */
2583               if (sequence > 0)
2584                 RETURN_IF_ERROR (result_append (dm, ", "));
2585               /* Demangle the type.  */
2586               RETURN_IF_ERROR (demangle_type (dm));
2587             }
2588         }
2589
2590       ++sequence;
2591     }
2592   RETURN_IF_ERROR (result_append_char (dm, ')'));
2593
2594   /* We should have demangled at least one parameter type (which would
2595      be void, for a function that takes no parameters), plus the
2596      return type, if we were supposed to demangle that.  */
2597   if (sequence == -1)
2598     return "Missing function return type.";
2599   else if (sequence == 0)
2600     return "Missing function parameter.";
2601
2602   return STATUS_OK;
2603 }
2604
2605 /* Demangles and emits a <class-enum-type>.  *ENCODE_RETURN_TYPE is set to
2606    non-zero if the type is a template-id, zero otherwise.  
2607
2608     <class-enum-type> ::= <name>  */
2609
2610 static status_t
2611 demangle_class_enum_type (dm, encode_return_type)
2612      demangling_t dm;
2613      int *encode_return_type;
2614 {
2615   DEMANGLE_TRACE ("class-enum-type", dm);
2616
2617   RETURN_IF_ERROR (demangle_name (dm, encode_return_type));
2618   return STATUS_OK;
2619 }
2620
2621 /* Demangles and emits an <array-type>.  
2622
2623     <array-type> ::= A [<dimension number>] _ <element type>  
2624                  ::= A <dimension expression> _ <element type>  */
2625
2626 static status_t
2627 demangle_array_type (dm)
2628      demangling_t dm;
2629 {
2630   status_t status = STATUS_OK;
2631   dyn_string_t array_size = NULL;
2632   char peek;
2633
2634   RETURN_IF_ERROR (demangle_char (dm, 'A'));
2635
2636   /* Demangle the array size into array_size.  */
2637   peek = peek_char (dm);
2638   if (peek == '_')
2639     /* Array bound is omitted.  This is a C99-style VLA.  */
2640     ;
2641   else if (IS_DIGIT (peek_char (dm))) 
2642     {
2643       /* It looks like a constant array bound.  */
2644       array_size = dyn_string_new (10);
2645       if (array_size == NULL)
2646         return STATUS_ALLOCATION_FAILED;
2647       status = demangle_number_literally (dm, array_size, 10, 0);
2648     }
2649   else
2650     {
2651       /* Anything is must be an expression for a nont-constant array
2652          bound.  This happens if the array type occurs in a template
2653          and the array bound references a template parameter.  */
2654       RETURN_IF_ERROR (result_push (dm));
2655       RETURN_IF_ERROR (demangle_expression (dm));
2656       array_size = (dyn_string_t) result_pop (dm);
2657     }
2658   /* array_size may have been allocated by now, so we can't use
2659      RETURN_IF_ERROR until it's been deallocated.  */
2660
2661   /* Demangle the base type of the array.  */
2662   if (STATUS_NO_ERROR (status))
2663     status = demangle_char (dm, '_');
2664   if (STATUS_NO_ERROR (status))
2665     status = demangle_type (dm);
2666
2667   /* Emit the array dimension syntax.  */
2668   if (STATUS_NO_ERROR (status))
2669     status = result_append_char (dm, '[');
2670   if (STATUS_NO_ERROR (status) && array_size != NULL)
2671     status = result_append_string (dm, array_size);
2672   if (STATUS_NO_ERROR (status))
2673     status = result_append_char (dm, ']');
2674   if (array_size != NULL)
2675     dyn_string_delete (array_size);
2676   
2677   RETURN_IF_ERROR (status);
2678
2679   return STATUS_OK;
2680 }
2681
2682 /* Demangles and emits a <template-param>.  
2683
2684     <template-param> ::= T_       # first template parameter
2685                      ::= T <parameter-2 number> _  */
2686
2687 static status_t
2688 demangle_template_param (dm)
2689      demangling_t dm;
2690 {
2691   int parm_number;
2692   template_arg_list_t current_arg_list = current_template_arg_list (dm);
2693   string_list_t arg;
2694
2695   DEMANGLE_TRACE ("template-param", dm);
2696
2697   /* Make sure there is a template argmust list in which to look up
2698      this parameter reference.  */
2699   if (current_arg_list == NULL)
2700     return "Template parameter outside of template.";
2701
2702   RETURN_IF_ERROR (demangle_char (dm, 'T'));
2703   if (peek_char (dm) == '_')
2704     parm_number = 0;
2705   else
2706     {
2707       RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));
2708       ++parm_number;
2709     }
2710   RETURN_IF_ERROR (demangle_char (dm, '_'));
2711
2712   arg = template_arg_list_get_arg (current_arg_list, parm_number);
2713   if (arg == NULL)
2714     /* parm_number exceeded the number of arguments in the current
2715        template argument list.  */
2716     return "Template parameter number out of bounds.";
2717   RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
2718
2719   return STATUS_OK;
2720 }
2721
2722 /* Demangles and emits a <template-args>.  
2723
2724     <template-args> ::= I <template-arg>+ E  */
2725
2726 static status_t
2727 demangle_template_args (dm)
2728      demangling_t dm;
2729 {
2730   int first = 1;
2731   dyn_string_t old_last_source_name;
2732   template_arg_list_t arg_list = template_arg_list_new ();
2733
2734   if (arg_list == NULL)
2735     return STATUS_ALLOCATION_FAILED;
2736
2737   /* Preserve the most recently demangled source name.  */
2738   old_last_source_name = dm->last_source_name;
2739   dm->last_source_name = dyn_string_new (0);
2740
2741   DEMANGLE_TRACE ("template-args", dm);
2742
2743   if (dm->last_source_name == NULL)
2744     return STATUS_ALLOCATION_FAILED;
2745
2746   RETURN_IF_ERROR (demangle_char (dm, 'I'));
2747   RETURN_IF_ERROR (result_open_template_list (dm));
2748   do
2749     {
2750       string_list_t arg;
2751
2752       if (first)
2753         first = 0;
2754       else
2755         RETURN_IF_ERROR (result_append (dm, ", "));
2756
2757       /* Capture the template arg.  */
2758       RETURN_IF_ERROR (result_push (dm));
2759       RETURN_IF_ERROR (demangle_template_arg (dm));
2760       arg = result_pop (dm);
2761
2762       /* Emit it in the demangled name.  */
2763       RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
2764
2765       /* Save it for use in expanding <template-param>s.  */
2766       template_arg_list_add_arg (arg_list, arg);
2767     }
2768   while (peek_char (dm) != 'E');
2769   /* Append the '>'.  */
2770   RETURN_IF_ERROR (result_close_template_list (dm));
2771
2772   /* Consume the 'E'.  */
2773   advance_char (dm);
2774
2775   /* Restore the most recent demangled source name.  */
2776   dyn_string_delete (dm->last_source_name);
2777   dm->last_source_name = old_last_source_name;
2778
2779   /* Push the list onto the top of the stack of template argument
2780      lists, so that arguments from it are used from now on when
2781      expanding <template-param>s.  */
2782   push_template_arg_list (dm, arg_list);
2783
2784   return STATUS_OK;
2785 }
2786
2787 /* This function, which does not correspond to a production in the
2788    mangling spec, handles the `literal' production for both
2789    <template-arg> and <expr-primary>.  It does not expect or consume
2790    the initial `L' or final `E'.  The demangling is given by:
2791
2792      <literal> ::= <type> </value/ number>
2793
2794    and the emitted output is `(type)number'.  */
2795
2796 static status_t
2797 demangle_literal (dm)
2798      demangling_t dm;
2799 {
2800   char peek = peek_char (dm);
2801   dyn_string_t value_string;
2802   status_t status;
2803
2804   DEMANGLE_TRACE ("literal", dm);
2805
2806   if (!flag_verbose && peek >= 'a' && peek <= 'z')
2807     {
2808       /* If not in verbose mode and this is a builtin type, see if we
2809          can produce simpler numerical output.  In particular, for
2810          integer types shorter than `long', just write the number
2811          without type information; for bools, write `true' or `false'.
2812          Other refinements could be made here too.  */
2813
2814       /* This constant string is used to map from <builtin-type> codes
2815          (26 letters of the alphabet) to codes that determine how the 
2816          value will be displayed.  The codes are:
2817            b: display as bool
2818            i: display as int
2819            l: display as long
2820          A space means the value will be represented using cast
2821          notation. */
2822       static const char *const code_map = "ibi    iii ll     ii  i  ";
2823
2824       char code = code_map[peek - 'a'];
2825       /* FIXME: Implement demangling of floats and doubles.  */
2826       if (code == 'u')
2827         return STATUS_UNIMPLEMENTED;
2828       if (code == 'b')
2829         {
2830           /* It's a boolean.  */
2831           char value;
2832
2833           /* Consume the b.  */
2834           advance_char (dm);
2835           /* Look at the next character.  It should be 0 or 1,
2836              corresponding to false or true, respectively.  */
2837           value = peek_char (dm);
2838           if (value == '0')
2839             RETURN_IF_ERROR (result_append (dm, "false"));
2840           else if (value == '1')
2841             RETURN_IF_ERROR (result_append (dm, "true"));
2842           else
2843             return "Unrecognized bool constant.";
2844           /* Consume the 0 or 1.  */
2845           advance_char (dm);
2846           return STATUS_OK;
2847         }
2848       else if (code == 'i' || code == 'l')
2849         {
2850           /* It's an integer or long.  */
2851
2852           /* Consume the type character.  */
2853           advance_char (dm);
2854
2855           /* Demangle the number and write it out.  */
2856           value_string = dyn_string_new (0);
2857           status = demangle_number_literally (dm, value_string, 10, 1);
2858           if (STATUS_NO_ERROR (status))
2859             status = result_append_string (dm, value_string);
2860           /* For long integers, append an l.  */
2861           if (code == 'l' && STATUS_NO_ERROR (status))
2862             status = result_append_char (dm, code);
2863           dyn_string_delete (value_string);
2864
2865           RETURN_IF_ERROR (status);
2866           return STATUS_OK;
2867         }
2868       /* ...else code == ' ', so fall through to represent this
2869          literal's type explicitly using cast syntax.  */
2870     }
2871
2872   RETURN_IF_ERROR (result_append_char (dm, '('));
2873   RETURN_IF_ERROR (demangle_type (dm));
2874   RETURN_IF_ERROR (result_append_char (dm, ')'));
2875
2876   value_string = dyn_string_new (0);
2877   if (value_string == NULL)
2878     return STATUS_ALLOCATION_FAILED;
2879
2880   status = demangle_number_literally (dm, value_string, 10, 1);
2881   if (STATUS_NO_ERROR (status))
2882     status = result_append_string (dm, value_string);
2883   dyn_string_delete (value_string);
2884   RETURN_IF_ERROR (status);
2885
2886   return STATUS_OK;
2887 }
2888
2889 /* Demangles and emits a <template-arg>.  
2890
2891     <template-arg> ::= <type>                     # type
2892                    ::= L <type> <value number> E  # literal
2893                    ::= LZ <encoding> E            # external name
2894                    ::= X <expression> E           # expression  */
2895
2896 static status_t
2897 demangle_template_arg (dm)
2898      demangling_t dm;
2899 {
2900   DEMANGLE_TRACE ("template-arg", dm);
2901
2902   switch (peek_char (dm))
2903     {
2904     case 'L':
2905       advance_char (dm);
2906
2907       if (peek_char (dm) == 'Z')
2908         {
2909           /* External name.  */
2910           advance_char (dm);
2911           /* FIXME: Standard is contradictory here.  */
2912           RETURN_IF_ERROR (demangle_encoding (dm));
2913         }
2914       else
2915         RETURN_IF_ERROR (demangle_literal (dm));
2916       RETURN_IF_ERROR (demangle_char (dm, 'E'));
2917       break;
2918
2919     case 'X':
2920       /* Expression.  */
2921       advance_char (dm);
2922       RETURN_IF_ERROR (demangle_expression (dm));
2923       RETURN_IF_ERROR (demangle_char (dm, 'E'));
2924       break;
2925
2926     default:
2927       RETURN_IF_ERROR (demangle_type (dm));
2928       break;
2929     }
2930
2931   return STATUS_OK;
2932 }
2933
2934 /* Demangles and emits an <expression>.
2935
2936     <expression> ::= <unary operator-name> <expression>
2937                  ::= <binary operator-name> <expression> <expression>
2938                  ::= <expr-primary>  
2939                  ::= <scope-expression>  */
2940
2941 static status_t
2942 demangle_expression (dm)
2943      demangling_t dm;
2944 {
2945   char peek = peek_char (dm);
2946
2947   DEMANGLE_TRACE ("expression", dm);
2948
2949   if (peek == 'L' || peek == 'T')
2950     RETURN_IF_ERROR (demangle_expr_primary (dm));
2951   else if (peek == 's' && peek_char_next (dm) == 'r')
2952     RETURN_IF_ERROR (demangle_scope_expression (dm));
2953   else
2954     /* An operator expression.  */
2955     {
2956       int num_args;
2957       status_t status = STATUS_OK;
2958       dyn_string_t operator_name;
2959
2960       /* We have an operator name.  Since we want to output binary
2961          operations in infix notation, capture the operator name
2962          first.  */
2963       RETURN_IF_ERROR (result_push (dm));
2964       RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args));
2965       operator_name = (dyn_string_t) result_pop (dm);
2966
2967       /* If it's binary, do an operand first.  */
2968       if (num_args > 1)
2969         {
2970           status = result_append_char (dm, '(');
2971           if (STATUS_NO_ERROR (status))
2972             status = demangle_expression (dm);
2973           if (STATUS_NO_ERROR (status))
2974             status = result_append_char (dm, ')');
2975         }
2976
2977       /* Emit the operator.  */  
2978       if (STATUS_NO_ERROR (status))
2979         status = result_append_string (dm, operator_name);
2980       dyn_string_delete (operator_name);
2981       RETURN_IF_ERROR (status);
2982       
2983       /* Emit its second (if binary) or only (if unary) operand.  */
2984       RETURN_IF_ERROR (result_append_char (dm, '('));
2985       RETURN_IF_ERROR (demangle_expression (dm));
2986       RETURN_IF_ERROR (result_append_char (dm, ')'));
2987
2988       /* The ternary operator takes a third operand.  */
2989       if (num_args == 3)
2990         {
2991           RETURN_IF_ERROR (result_append (dm, ":("));
2992           RETURN_IF_ERROR (demangle_expression (dm));
2993           RETURN_IF_ERROR (result_append_char (dm, ')'));
2994         }
2995     }
2996
2997   return STATUS_OK;
2998 }
2999
3000 /* Demangles and emits a <scope-expression>.  
3001
3002     <scope-expression> ::= sr <qualifying type> <source-name>
3003                        ::= sr <qualifying type> <encoding>  */
3004
3005 static status_t
3006 demangle_scope_expression (dm)
3007      demangling_t dm;
3008 {
3009   RETURN_IF_ERROR (demangle_char (dm, 's'));
3010   RETURN_IF_ERROR (demangle_char (dm, 'r'));
3011   RETURN_IF_ERROR (demangle_type (dm));
3012   RETURN_IF_ERROR (result_append (dm, "::"));
3013   RETURN_IF_ERROR (demangle_encoding (dm));
3014   return STATUS_OK;
3015 }
3016
3017 /* Demangles and emits an <expr-primary>.  
3018
3019     <expr-primary> ::= <template-param>
3020                    ::= L <type> <value number> E  # literal
3021                    ::= L <mangled-name> E         # external name  */
3022
3023 static status_t
3024 demangle_expr_primary (dm)
3025      demangling_t dm;
3026 {
3027   char peek = peek_char (dm);
3028
3029   DEMANGLE_TRACE ("expr-primary", dm);
3030
3031   if (peek == 'T')
3032     RETURN_IF_ERROR (demangle_template_param (dm));
3033   else if (peek == 'L')
3034     {
3035       /* Consume the `L'.  */
3036       advance_char (dm);
3037       peek = peek_char (dm);
3038
3039       if (peek == '_')
3040         RETURN_IF_ERROR (demangle_mangled_name (dm));
3041       else
3042         RETURN_IF_ERROR (demangle_literal (dm));
3043
3044       RETURN_IF_ERROR (demangle_char (dm, 'E'));
3045     }
3046   else
3047     return STATUS_ERROR;
3048
3049   return STATUS_OK;
3050 }
3051
3052 /* Demangles and emits a <substitution>.  Sets *TEMPLATE_P to non-zero
3053    if the substitution is the name of a template, zero otherwise. 
3054
3055      <substitution> ::= S <seq-id> _
3056                     ::= S_
3057
3058                     ::= St   # ::std::
3059                     ::= Sa   # ::std::allocator
3060                     ::= Sb   # ::std::basic_string
3061                     ::= Ss   # ::std::basic_string<char,
3062                                                    ::std::char_traits<char>,
3063                                                    ::std::allocator<char> >
3064                     ::= Si   # ::std::basic_istream<char,  
3065                                                     std::char_traits<char> >
3066                     ::= So   # ::std::basic_ostream<char,  
3067                                                     std::char_traits<char> >
3068                     ::= Sd   # ::std::basic_iostream<char, 
3069                                                     std::char_traits<char> >
3070 */
3071
3072 static status_t
3073 demangle_substitution (dm, template_p)
3074      demangling_t dm;
3075      int *template_p;
3076 {
3077   int seq_id;
3078   int peek;
3079   dyn_string_t text;
3080
3081   DEMANGLE_TRACE ("substitution", dm);
3082
3083   RETURN_IF_ERROR (demangle_char (dm, 'S'));
3084
3085   /* Scan the substitution sequence index.  A missing number denotes
3086      the first index.  */
3087   peek = peek_char (dm);
3088   if (peek == '_')
3089     seq_id = -1;
3090   /* If the following character is 0-9 or a capital letter, interpret
3091      the sequence up to the next underscore as a base-36 substitution
3092      index.  */
3093   else if (IS_DIGIT ((unsigned char) peek) 
3094            || (peek >= 'A' && peek <= 'Z'))
3095     RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));
3096   else 
3097     {
3098       const char *new_last_source_name = NULL;
3099
3100       switch (peek)
3101         {
3102         case 't':
3103           RETURN_IF_ERROR (result_append (dm, "std"));
3104           break;
3105
3106         case 'a':
3107           RETURN_IF_ERROR (result_append (dm, "std::allocator"));
3108           new_last_source_name = "allocator";
3109           *template_p = 1;
3110           break;
3111
3112         case 'b':
3113           RETURN_IF_ERROR (result_append (dm, "std::basic_string"));
3114           new_last_source_name = "basic_string";
3115           *template_p = 1;
3116           break;
3117           
3118         case 's':
3119           if (!flag_verbose)
3120             {
3121               RETURN_IF_ERROR (result_append (dm, "std::string"));
3122               new_last_source_name = "string";
3123             }
3124           else
3125             {
3126               RETURN_IF_ERROR (result_append (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
3127               new_last_source_name = "basic_string";
3128             }
3129           *template_p = 0;
3130           break;
3131
3132         case 'i':
3133           if (!flag_verbose)
3134             {
3135               RETURN_IF_ERROR (result_append (dm, "std::istream"));
3136               new_last_source_name = "istream";
3137             }
3138           else
3139             {
3140               RETURN_IF_ERROR (result_append (dm, "std::basic_istream<char, std::char_traints<char> >"));
3141               new_last_source_name = "basic_istream";
3142             }
3143           *template_p = 0;
3144           break;
3145
3146         case 'o':
3147           if (!flag_verbose)
3148             {
3149               RETURN_IF_ERROR (result_append (dm, "std::ostream"));
3150               new_last_source_name = "ostream";
3151             }
3152           else
3153             {
3154               RETURN_IF_ERROR (result_append (dm, "std::basic_ostream<char, std::char_traits<char> >"));
3155               new_last_source_name = "basic_ostream";
3156             }
3157           *template_p = 0;
3158           break;
3159
3160         case 'd':
3161           if (!flag_verbose) 
3162             {
3163               RETURN_IF_ERROR (result_append (dm, "std::iostream"));
3164               new_last_source_name = "iostream";
3165             }
3166           else
3167             {
3168               RETURN_IF_ERROR (result_append (dm, "std::basic_iostream<char, std::char_traits<char> >"));
3169               new_last_source_name = "basic_iostream";
3170             }
3171           *template_p = 0;
3172           break;
3173
3174         default:
3175           return "Unrecognized <substitution>.";
3176         }
3177       
3178       /* Consume the character we just processed.  */
3179       advance_char (dm);
3180
3181       if (new_last_source_name != NULL)
3182         {
3183           if (!dyn_string_copy_cstr (dm->last_source_name, 
3184                                      new_last_source_name))
3185             return STATUS_ALLOCATION_FAILED;
3186         }
3187
3188       return STATUS_OK;
3189     }
3190
3191   /* Look up the substitution text.  Since `S_' is the most recent
3192      substitution, `S0_' is the second-most-recent, etc., shift the
3193      numbering by one.  */
3194   text = substitution_get (dm, seq_id + 1, template_p);
3195   if (text == NULL) 
3196     return "Substitution number out of range.";
3197
3198   /* Emit the substitution text.  */
3199   RETURN_IF_ERROR (result_append_string (dm, text));
3200
3201   RETURN_IF_ERROR (demangle_char (dm, '_'));
3202   return STATUS_OK;
3203 }
3204
3205 /* Demangles and emits a <local-name>.  
3206
3207     <local-name> := Z <function encoding> E <entity name> [<discriminator>]
3208                  := Z <function encoding> E s [<discriminator>]  */
3209
3210 static status_t
3211 demangle_local_name (dm)
3212      demangling_t dm;
3213 {
3214   DEMANGLE_TRACE ("local-name", dm);
3215
3216   RETURN_IF_ERROR (demangle_char (dm, 'Z'));
3217   RETURN_IF_ERROR (demangle_encoding (dm));
3218   RETURN_IF_ERROR (demangle_char (dm, 'E'));
3219   RETURN_IF_ERROR (result_append (dm, "::"));
3220
3221   if (peek_char (dm) == 's')
3222     {
3223       /* Local character string literal.  */
3224       RETURN_IF_ERROR (result_append (dm, "string literal"));
3225       /* Consume the s.  */
3226       advance_char (dm);
3227       RETURN_IF_ERROR (demangle_discriminator (dm, 0));
3228     }
3229   else
3230     {
3231       int unused;
3232       /* Local name for some other entity.  Demangle its name.  */
3233       RETURN_IF_ERROR (demangle_name (dm, &unused));
3234       RETURN_IF_ERROR (demangle_discriminator (dm, 1));
3235      }
3236
3237    return STATUS_OK;
3238  }
3239
3240  /* Optimonally demangles and emits a <discriminator>.  If there is no
3241     <discriminator> at the current position in the mangled string, the
3242     descriminator is assumed to be zero.  Emit the discriminator number
3243     in parentheses, unless SUPPRESS_FIRST is non-zero and the
3244     discriminator is zero.  
3245
3246      <discriminator> ::= _ <number>  */
3247
3248 static status_t
3249 demangle_discriminator (dm, suppress_first)
3250      demangling_t dm;
3251      int suppress_first;
3252 {
3253   /* Output for <discriminator>s to the demangled name is completely
3254      suppressed if not in verbose mode.  */
3255
3256   if (peek_char (dm) == '_')
3257     {
3258       /* Consume the underscore.  */
3259       advance_char (dm);
3260       if (flag_verbose)
3261         RETURN_IF_ERROR (result_append (dm, " [#"));
3262       /* Check if there's a number following the underscore.  */
3263       if (IS_DIGIT ((unsigned char) peek_char (dm)))
3264         {
3265           int discriminator;
3266           /* Demangle the number.  */
3267           RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));
3268           if (flag_verbose)
3269             /* Write the discriminator.  The mangled number is two
3270                less than the discriminator ordinal, counting from
3271                zero.  */
3272             RETURN_IF_ERROR (int_to_dyn_string (discriminator + 2, 
3273                                                 (dyn_string_t) dm->result));
3274         }
3275       else
3276         {
3277           if (flag_verbose)
3278             /* A missing digit correspond to one.  */
3279             RETURN_IF_ERROR (result_append_char (dm, '1'));
3280         }
3281       if (flag_verbose)
3282         RETURN_IF_ERROR (result_append_char (dm, ']'));
3283     }
3284   else if (!suppress_first)
3285     {
3286       if (flag_verbose)
3287         RETURN_IF_ERROR (result_append (dm, " [#0]"));
3288     }
3289
3290   return STATUS_OK;
3291 }
3292
3293 /* Demangle NAME into RESULT, which must be an initialized
3294    dyn_string_t.  On success, returns STATUS_OK.  On failure, returns
3295    an error message, and the contents of RESULT are unchanged.  */
3296
3297 static status_t
3298 cp_demangle (name, result)
3299      const char *name;
3300      dyn_string_t result;
3301 {
3302   status_t status;
3303   int length = strlen (name);
3304
3305   if (length > 2 && name[0] == '_' && name[1] == 'Z')
3306     {
3307       demangling_t dm = demangling_new (name);
3308       if (dm == NULL)
3309         return STATUS_ALLOCATION_FAILED;
3310
3311       status = result_push (dm);
3312       if (status != STATUS_OK)
3313         {
3314           demangling_delete (dm);
3315           return status;
3316         }
3317
3318       status = demangle_mangled_name (dm);
3319       if (STATUS_NO_ERROR (status))
3320         {
3321           dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3322           if (!dyn_string_copy (result, demangled))
3323             return STATUS_ALLOCATION_FAILED;
3324           dyn_string_delete (demangled);
3325         }
3326       
3327       demangling_delete (dm);
3328     }
3329   else
3330     {
3331       /* It's evidently not a mangled C++ name.  It could be the name
3332          of something with C linkage, though, so just copy NAME into
3333          RESULT.  */
3334       if (!dyn_string_copy_cstr (result, name))
3335         return STATUS_ALLOCATION_FAILED;
3336       status = STATUS_OK;
3337     }
3338
3339   return status; 
3340 }
3341
3342 /* Demangle TYPE_NAME into RESULT, which must be an initialized
3343    dyn_string_t.  On success, returns STATUS_OK.  On failiure, returns
3344    an error message, and the contents of RESULT are unchanged.  */
3345
3346 #ifdef IN_LIBGCC2
3347 static status_t
3348 cp_demangle_type (type_name, result)
3349      const char* type_name;
3350      dyn_string_t result;
3351 {
3352   status_t status;
3353   demangling_t dm = demangling_new (type_name);
3354   
3355   if (dm == NULL)
3356     return STATUS_ALLOCATION_FAILED;
3357
3358   /* Demangle the type name.  The demangled name is stored in dm.  */
3359   status = result_push (dm);
3360   if (status != STATUS_OK)
3361     {
3362       demangling_delete (dm);
3363       return status;
3364     }
3365
3366   status = demangle_type (dm);
3367
3368   if (STATUS_NO_ERROR (status))
3369     {
3370       /* The demangling succeeded.  Pop the result out of dm and copy
3371          it into RESULT.  */
3372       dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3373       if (!dyn_string_copy (result, demangled))
3374         return STATUS_ALLOCATION_FAILED;
3375       dyn_string_delete (demangled);
3376     }
3377
3378   /* Clean up.  */
3379   demangling_delete (dm);
3380
3381   return status;
3382 }
3383
3384 extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
3385
3386 /* ABI-mandated entry point in the C++ runtime library for performing
3387    demangling.  MANGLED_NAME is a NUL-terminated character string
3388    containing the name to be demangled.  
3389
3390    OUTPUT_BUFFER is a region of memory, allocated with malloc, of
3391    *LENGTH bytes, into which the demangled name is stored.  If
3392    OUTPUT_BUFFER is not long enough, it is expanded using realloc.
3393    OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
3394    is placed in a region of memory allocated with malloc.  
3395
3396    If LENGTH is non-NULL, the length of the buffer conaining the
3397    demangled name, is placed in *LENGTH.  
3398
3399    The return value is a pointer to the start of the NUL-terminated
3400    demangled name, or NULL if the demangling fails.  The caller is
3401    responsible for deallocating this memory using free.  
3402
3403    *STATUS is set to one of the following values:
3404       0: The demangling operation succeeded.
3405      -1: A memory allocation failiure occurred.
3406      -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
3407      -3: One of the arguments is invalid.
3408
3409    The demagling is performed using the C++ ABI mangling rules, with
3410    GNU extensions.  */
3411
3412 char *
3413 __cxa_demangle (mangled_name, output_buffer, length, status)
3414      const char *mangled_name;
3415      char *output_buffer;
3416      size_t *length;
3417      int *status;
3418 {
3419   struct dyn_string demangled_name;
3420   status_t result;
3421
3422   if (status == NULL)
3423     return NULL;
3424
3425   if (mangled_name == NULL) {
3426     *status = -3;
3427     return NULL;
3428   }
3429
3430   /* Did the caller provide a buffer for the demangled name?  */
3431   if (output_buffer == NULL) {
3432     /* No; dyn_string will malloc a buffer for us.  */
3433     if (!dyn_string_init (&demangled_name, 0)) 
3434       {
3435         *status = -1;
3436         return NULL;
3437       }
3438   }
3439   else {
3440     /* Yes.  Check that the length was provided.  */
3441     if (length == NULL) {
3442       *status = -3;
3443       return NULL;
3444     }
3445     /* Install the buffer into a dyn_string.  */
3446     demangled_name.allocated = *length;
3447     demangled_name.length = 0;
3448     demangled_name.s = output_buffer;
3449   }
3450
3451   if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
3452     /* MANGLED_NAME apprears to be a function or variable name.
3453        Demangle it accordingly.  */
3454     result = cp_demangle (mangled_name, &demangled_name);
3455   else
3456     /* Try to demangled MANGLED_NAME as the name of a type.  */
3457     result = cp_demangle_type (mangled_name, &demangled_name);
3458
3459   if (result == STATUS_OK) 
3460     /* The demangling succeeded.  */
3461     {
3462       /* If LENGTH isn't NULL, store the allocated buffer length
3463          there; the buffer may have been realloced by dyn_string
3464          functions.  */
3465       if (length != NULL)
3466         *length = demangled_name.allocated;
3467       /* The operation was a success.  */
3468       *status = 0;
3469       return dyn_string_buf (&demangled_name);
3470     }
3471   else if (result == STATUS_ALLOCATION_FAILED)
3472     /* A call to malloc or realloc failed during the demangling
3473        operation.  */
3474     {
3475       *status = -1;
3476       return NULL;
3477     }
3478   else
3479     /* The demangling failed for another reason, most probably because
3480        MANGLED_NAME isn't a valid mangled name.  */
3481     {
3482       /* If the buffer containing the demangled name wasn't provided
3483          by the caller, free it.  */
3484       if (output_buffer == NULL)
3485         free (dyn_string_buf (&demangled_name));
3486       *status = -2;
3487       return NULL;
3488     }
3489 }
3490
3491 #else /* !IN_LIBGCC2 */
3492
3493 /* Variant entry point for integration with the existing cplus-dem
3494    demangler.  Attempts to demangle MANGLED.  If the demangling
3495    succeeds, returns a buffer, allocated with malloc, containing the
3496    demangled name.  The caller must deallocate the buffer using free.
3497    If the demangling failes, returns NULL.  */
3498
3499 char *
3500 cplus_demangle_new_abi (mangled)
3501      const char* mangled;
3502 {
3503   /* Create a dyn_string to hold the demangled name.  */
3504   dyn_string_t demangled = dyn_string_new (0);
3505   /* Attempt the demangling.  */
3506   status_t status = cp_demangle ((char *) mangled, demangled);
3507   if (STATUS_NO_ERROR (status))
3508     /* Demangling succeeded.  */
3509     {
3510       /* Grab the demangled result from the dyn_string.  It was
3511          allocated with malloc, so we can return it directly.  */
3512       char *return_value = dyn_string_release (demangled);
3513       /* Hand back the demangled name.  */
3514       return return_value;
3515     }
3516   else if (status == STATUS_ALLOCATION_FAILED)
3517     {
3518       fprintf (stderr, "Memory allocation failed.\n");
3519       abort ();
3520     }
3521   else
3522     /* Demangling failed.  */
3523     {
3524       dyn_string_delete (demangled);
3525       return NULL;
3526     }
3527 }
3528
3529 #endif /* IN_LIBGCC2 */
3530
3531 #ifdef STANDALONE_DEMANGLER
3532
3533 #include "getopt.h"
3534
3535 static void print_usage
3536   PARAMS ((FILE* fp, int exit_value));
3537
3538 /* Non-zero if CHAR is a character than can occur in a mangled name.  */
3539 #define is_mangled_char(CHAR)                                           \
3540   (IS_ALPHA (CHAR) || IS_DIGIT (CHAR)                                   \
3541    || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
3542
3543 /* The name of this program, as invoked.  */
3544 const char* program_name;
3545
3546 /* Prints usage summary to FP and then exits with EXIT_VALUE.  */
3547
3548 static void
3549 print_usage (fp, exit_value)
3550      FILE* fp;
3551      int exit_value;
3552 {
3553   fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
3554   fprintf (fp, "Options:\n");
3555   fprintf (fp, "  -h,--help       Display this message.\n");
3556   fprintf (fp, "  -s,--strict     Demangle standard names only.\n");
3557   fprintf (fp, "  -v,--verbose    Produce verbose demanglings.\n");
3558   fprintf (fp, "If names are provided, they are demangled.  Otherwise filters standard input.\n");
3559
3560   exit (exit_value);
3561 }
3562
3563 /* Option specification for getopt_long.  */
3564 static struct option long_options[] = 
3565 {
3566   { "help",    no_argument, NULL, 'h' },
3567   { "strict",  no_argument, NULL, 's' },
3568   { "verbose", no_argument, NULL, 'v' },
3569   { NULL,      no_argument, NULL, 0   },
3570 };
3571
3572 /* Main entry for a demangling filter executable.  It will demangle
3573    its command line arguments, if any.  If none are provided, it will
3574    filter stdin to stdout, replacing any recognized mangled C++ names
3575    with their demangled equivalents.  */
3576
3577 int
3578 main (argc, argv)
3579      int argc;
3580      char *argv[];
3581 {
3582   status_t status;
3583   int i;
3584   int opt_char;
3585
3586   /* Use the program name of this program, as invoked.  */
3587   program_name = argv[0];
3588
3589   /* Parse options.  */
3590   do 
3591     {
3592       opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);
3593       switch (opt_char)
3594         {
3595         case '?':  /* Unrecognized option.  */
3596           print_usage (stderr, 1);
3597           break;
3598
3599         case 'h':
3600           print_usage (stdout, 0);
3601           break;
3602
3603         case 's':
3604           flag_strict = 1;
3605           break;
3606
3607         case 'v':
3608           flag_verbose = 1;
3609           break;
3610         }
3611     }
3612   while (opt_char != -1);
3613
3614   if (optind == argc) 
3615     /* No command line arguments were provided.  Filter stdin.  */
3616     {
3617       dyn_string_t mangled = dyn_string_new (3);
3618       dyn_string_t demangled = dyn_string_new (0);
3619       status_t status;
3620
3621       /* Read all of input.  */
3622       while (!feof (stdin))
3623         {
3624           char c = getchar ();
3625
3626           /* The first character of a mangled name is an underscore.  */
3627           if (feof (stdin))
3628             break;
3629           if (c != '_')
3630             {
3631               /* It's not a mangled name.  Print the character and go
3632                  on.  */
3633               putchar (c);
3634               continue;
3635             }
3636           c = getchar ();
3637           
3638           /* The second character of a mangled name is a capital `Z'.  */
3639           if (feof (stdin))
3640             break;
3641           if (c != 'Z')
3642             {
3643               /* It's not a mangled name.  Print the previous
3644                  underscore, the `Z', and go on.  */
3645               putchar ('_');
3646               putchar (c);
3647               continue;
3648             }
3649
3650           /* Start keeping track of the candidate mangled name.  */
3651           dyn_string_append_char (mangled, '_');
3652           dyn_string_append_char (mangled, 'Z');
3653
3654           /* Pile characters into mangled until we hit one that can't
3655              occur in a mangled name.  */
3656           c = getchar ();
3657           while (!feof (stdin) && is_mangled_char (c))
3658             {
3659               dyn_string_append_char (mangled, c);
3660               if (feof (stdin))
3661                 break;
3662               c = getchar ();
3663             }
3664
3665           /* Attempt to demangle the name.  */
3666           status = cp_demangle (dyn_string_buf (mangled), demangled);
3667
3668           /* If the demangling succeeded, great!  Print out the
3669              demangled version.  */
3670           if (STATUS_NO_ERROR (status))
3671             fputs (dyn_string_buf (demangled), stdout);
3672           /* Abort on allocation failures.  */
3673           else if (status == STATUS_ALLOCATION_FAILED)
3674             {
3675               fprintf (stderr, "Memory allocation failed.\n");
3676               abort ();
3677             }
3678           /* Otherwise, it might not have been a mangled name.  Just
3679              print out the original text.  */
3680           else
3681             fputs (dyn_string_buf (mangled), stdout);
3682
3683           /* If we haven't hit EOF yet, we've read one character that
3684              can't occur in a mangled name, so print it out.  */
3685           if (!feof (stdin))
3686             putchar (c);
3687
3688           /* Clear the candidate mangled name, to start afresh next
3689              time we hit a `_Z'.  */
3690           dyn_string_clear (mangled);
3691         }
3692
3693       dyn_string_delete (mangled);
3694       dyn_string_delete (demangled);
3695     }
3696   else
3697     /* Demangle command line arguments.  */
3698     {
3699       dyn_string_t result = dyn_string_new (0);
3700
3701       /* Loop over command line arguments.  */
3702       for (i = optind; i < argc; ++i)
3703         {
3704           /* Attempt to demangle.  */
3705           status = cp_demangle (argv[i], result);
3706
3707           /* If it worked, print the demangled name.  */
3708           if (STATUS_NO_ERROR (status))
3709             printf ("%s\n", dyn_string_buf (result));
3710           /* Abort on allocaiton failures.  */
3711           else if (status == STATUS_ALLOCATION_FAILED)
3712             {
3713               fprintf (stderr, "Memory allocaiton failed.\n");
3714               abort ();
3715             }
3716           /* If not, print the error message to stderr instead.  */
3717           else 
3718             fprintf (stderr, "%s\n", status);
3719         }
3720       dyn_string_delete (result);
3721     }
3722
3723   return 0;
3724 }
3725
3726 #endif /* STANDALONE_DEMANGLER */