OSDN Git Service

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