OSDN Git Service

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