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