OSDN Git Service

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