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