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