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