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