OSDN Git Service

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