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