Replace 'arch' field with 'mach'.
[binutils.git] / libiberty / cp-demangle.c
blob136dc723d2ed15f7075e513c84d8ff4aa1a09c8c
1 /* Demangler for IA64 / g++ V3 ABI.
2 Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3 Written by Alex Samuel <samuel@codesourcery.com>.
5 This file is part of GNU CC.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 /* This file implements demangling of C++ names mangled according to
23 the IA64 / g++ V3 ABI. Use the cp_demangle function to
24 demangle a mangled name, or compile with the preprocessor macro
25 STANDALONE_DEMANGLER defined to create a demangling filter
26 executable (functionally similar to c++filt, but includes this
27 demangler only). */
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 #include <sys/types.h>
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif
39 #include <stdio.h>
41 #ifdef HAVE_STRING_H
42 #include <string.h>
43 #endif
45 #include "ansidecl.h"
46 #include "libiberty.h"
47 #include "dyn-string.h"
48 #include "demangle.h"
50 /* If CP_DEMANGLE_DEBUG is defined, a trace of the grammar evaluation,
51 and other debugging output, will be generated. */
52 #ifdef CP_DEMANGLE_DEBUG
53 #define DEMANGLE_TRACE(PRODUCTION, DM) \
54 fprintf (stderr, " -> %-24s at position %3d\n", \
55 (PRODUCTION), current_position (DM));
56 #else
57 #define DEMANGLE_TRACE(PRODUCTION, DM)
58 #endif
60 /* Don't include <ctype.h>, to prevent additional unresolved symbols
61 from being dragged into the C++ runtime library. */
62 #define IS_DIGIT(CHAR) ((CHAR) >= '0' && (CHAR) <= '9')
63 #define IS_ALPHA(CHAR) \
64 (((CHAR) >= 'a' && (CHAR) <= 'z') \
65 || ((CHAR) >= 'A' && (CHAR) <= 'Z'))
67 /* The prefix prepended by GCC to an identifier represnting the
68 anonymous namespace. */
69 #define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
71 /* Character(s) to use for namespace separation in demangled output */
72 #define NAMESPACE_SEPARATOR (dm->style == DMGL_JAVA ? "." : "::")
74 /* If flag_verbose is zero, some simplifications will be made to the
75 output to make it easier to read and supress details that are
76 generally not of interest to the average C++ programmer.
77 Otherwise, the demangled representation will attempt to convey as
78 much information as the mangled form. */
79 static int flag_verbose;
81 /* If flag_strict is non-zero, demangle strictly according to the
82 specification -- don't demangle special g++ manglings. */
83 static int flag_strict;
85 /* String_list_t is an extended form of dyn_string_t which provides a
86 link field and a caret position for additions to the string. A
87 string_list_t may safely be cast to and used as a dyn_string_t. */
89 struct string_list_def
91 /* The dyn_string; must be first. */
92 struct dyn_string string;
94 /* The position at which additional text is added to this string
95 (using the result_add* macros). This value is an offset from the
96 end of the string, not the beginning (and should be
97 non-positive). */
98 int caret_position;
100 /* The next string in the list. */
101 struct string_list_def *next;
104 typedef struct string_list_def *string_list_t;
106 /* Data structure representing a potential substitution. */
108 struct substitution_def
110 /* The demangled text of the substitution. */
111 dyn_string_t text;
113 /* Whether this substitution represents a template item. */
114 int template_p : 1;
117 /* Data structure representing a template argument list. */
119 struct template_arg_list_def
121 /* The next (lower) template argument list in the stack of currently
122 active template arguments. */
123 struct template_arg_list_def *next;
125 /* The first element in the list of template arguments in
126 left-to-right order. */
127 string_list_t first_argument;
129 /* The last element in the arguments lists. */
130 string_list_t last_argument;
133 typedef struct template_arg_list_def *template_arg_list_t;
135 /* Data structure to maintain the state of the current demangling. */
137 struct demangling_def
139 /* The full mangled name being mangled. */
140 const char *name;
142 /* Pointer into name at the current position. */
143 const char *next;
145 /* Stack for strings containing demangled result generated so far.
146 Text is emitted to the topmost (first) string. */
147 string_list_t result;
149 /* The number of presently available substitutions. */
150 int num_substitutions;
152 /* The allocated size of the substitutions array. */
153 int substitutions_allocated;
155 /* An array of available substitutions. The number of elements in
156 the array is given by num_substitions, and the allocated array
157 size in substitutions_size.
159 The most recent substition is at the end, so
161 - `S_' corresponds to substititutions[num_substitutions - 1]
162 - `S0_' corresponds to substititutions[num_substitutions - 2]
164 etc. */
165 struct substitution_def *substitutions;
167 /* The stack of template argument lists. */
168 template_arg_list_t template_arg_lists;
170 /* The most recently demangled source-name. */
171 dyn_string_t last_source_name;
173 /* Language style to use for demangled output. */
174 int style;
176 /* Set to non-zero iff this name is a constructor. The actual value
177 indicates what sort of constructor this is; see demangle.h. */
178 enum gnu_v3_ctor_kinds is_constructor;
180 /* Set to non-zero iff this name is a destructor. The actual value
181 indicates what sort of destructor this is; see demangle.h. */
182 enum gnu_v3_dtor_kinds is_destructor;
186 typedef struct demangling_def *demangling_t;
188 /* This type is the standard return code from most functions. Values
189 other than STATUS_OK contain descriptive messages. */
190 typedef const char *status_t;
192 /* Special values that can be used as a status_t. */
193 #define STATUS_OK NULL
194 #define STATUS_ERROR "Error."
195 #define STATUS_UNIMPLEMENTED "Unimplemented."
196 #define STATUS_INTERNAL_ERROR "Internal error."
198 /* This status code indicates a failure in malloc or realloc. */
199 static const char *const status_allocation_failed = "Allocation failed.";
200 #define STATUS_ALLOCATION_FAILED status_allocation_failed
202 /* Non-zero if STATUS indicates that no error has occurred. */
203 #define STATUS_NO_ERROR(STATUS) ((STATUS) == STATUS_OK)
205 /* Evaluate EXPR, which must produce a status_t. If the status code
206 indicates an error, return from the current function with that
207 status code. */
208 #define RETURN_IF_ERROR(EXPR) \
209 do \
211 status_t s = EXPR; \
212 if (!STATUS_NO_ERROR (s)) \
213 return s; \
215 while (0)
217 static status_t int_to_dyn_string
218 PARAMS ((int, dyn_string_t));
219 static string_list_t string_list_new
220 PARAMS ((int));
221 static void string_list_delete
222 PARAMS ((string_list_t));
223 static status_t result_add_separated_char
224 PARAMS ((demangling_t, int));
225 static status_t result_push
226 PARAMS ((demangling_t));
227 static string_list_t result_pop
228 PARAMS ((demangling_t));
229 static int substitution_start
230 PARAMS ((demangling_t));
231 static status_t substitution_add
232 PARAMS ((demangling_t, int, int));
233 static dyn_string_t substitution_get
234 PARAMS ((demangling_t, int, int *));
235 #ifdef CP_DEMANGLE_DEBUG
236 static void substitutions_print
237 PARAMS ((demangling_t, FILE *));
238 #endif
239 static template_arg_list_t template_arg_list_new
240 PARAMS ((void));
241 static void template_arg_list_delete
242 PARAMS ((template_arg_list_t));
243 static void template_arg_list_add_arg
244 PARAMS ((template_arg_list_t, string_list_t));
245 static string_list_t template_arg_list_get_arg
246 PARAMS ((template_arg_list_t, int));
247 static void push_template_arg_list
248 PARAMS ((demangling_t, template_arg_list_t));
249 static void pop_to_template_arg_list
250 PARAMS ((demangling_t, template_arg_list_t));
251 #ifdef CP_DEMANGLE_DEBUG
252 static void template_arg_list_print
253 PARAMS ((template_arg_list_t, FILE *));
254 #endif
255 static template_arg_list_t current_template_arg_list
256 PARAMS ((demangling_t));
257 static demangling_t demangling_new
258 PARAMS ((const char *, int));
259 static void demangling_delete
260 PARAMS ((demangling_t));
262 /* The last character of DS. Warning: DS is evaluated twice. */
263 #define dyn_string_last_char(DS) \
264 (dyn_string_buf (DS)[dyn_string_length (DS) - 1])
266 /* Append a space character (` ') to DS if it does not already end
267 with one. Evaluates to 1 on success, or 0 on allocation failure. */
268 #define dyn_string_append_space(DS) \
269 ((dyn_string_length (DS) > 0 \
270 && dyn_string_last_char (DS) != ' ') \
271 ? dyn_string_append_char ((DS), ' ') \
272 : 1)
274 /* Returns the index of the current position in the mangled name. */
275 #define current_position(DM) ((DM)->next - (DM)->name)
277 /* Returns the character at the current position of the mangled name. */
278 #define peek_char(DM) (*((DM)->next))
280 /* Returns the character one past the current position of the mangled
281 name. */
282 #define peek_char_next(DM) \
283 (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1)))
285 /* Returns the character at the current position, and advances the
286 current position to the next character. */
287 #define next_char(DM) (*((DM)->next)++)
289 /* Returns non-zero if the current position is the end of the mangled
290 name, i.e. one past the last character. */
291 #define end_of_name_p(DM) (peek_char (DM) == '\0')
293 /* Advances the current position by one character. */
294 #define advance_char(DM) (++(DM)->next)
296 /* Returns the string containing the current demangled result. */
297 #define result_string(DM) (&(DM)->result->string)
299 /* Returns the position at which new text is inserted into the
300 demangled result. */
301 #define result_caret_pos(DM) \
302 (result_length (DM) + \
303 ((string_list_t) result_string (DM))->caret_position)
305 /* Adds a dyn_string_t to the demangled result. */
306 #define result_add_string(DM, STRING) \
307 (dyn_string_insert (&(DM)->result->string, \
308 result_caret_pos (DM), (STRING)) \
309 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
311 /* Adds NUL-terminated string CSTR to the demangled result. */
312 #define result_add(DM, CSTR) \
313 (dyn_string_insert_cstr (&(DM)->result->string, \
314 result_caret_pos (DM), (CSTR)) \
315 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
317 /* Adds character CHAR to the demangled result. */
318 #define result_add_char(DM, CHAR) \
319 (dyn_string_insert_char (&(DM)->result->string, \
320 result_caret_pos (DM), (CHAR)) \
321 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
323 /* Inserts a dyn_string_t to the demangled result at position POS. */
324 #define result_insert_string(DM, POS, STRING) \
325 (dyn_string_insert (&(DM)->result->string, (POS), (STRING)) \
326 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
328 /* Inserts NUL-terminated string CSTR to the demangled result at
329 position POS. */
330 #define result_insert(DM, POS, CSTR) \
331 (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR)) \
332 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
334 /* Inserts character CHAR to the demangled result at position POS. */
335 #define result_insert_char(DM, POS, CHAR) \
336 (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR)) \
337 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
339 /* The length of the current demangled result. */
340 #define result_length(DM) \
341 dyn_string_length (&(DM)->result->string)
343 /* Appends a (less-than, greater-than) character to the result in DM
344 to (open, close) a template argument or parameter list. Appends a
345 space first if necessary to prevent spurious elision of angle
346 brackets with the previous character. */
347 #define result_open_template_list(DM) result_add_separated_char(DM, '<')
348 #define result_close_template_list(DM) result_add_separated_char(DM, '>')
350 /* Appends a base 10 representation of VALUE to DS. STATUS_OK on
351 success. On failure, deletes DS and returns an error code. */
353 static status_t
354 int_to_dyn_string (value, ds)
355 int value;
356 dyn_string_t ds;
358 int i;
359 int mask = 1;
361 /* Handle zero up front. */
362 if (value == 0)
364 if (!dyn_string_append_char (ds, '0'))
365 return STATUS_ALLOCATION_FAILED;
366 return STATUS_OK;
369 /* For negative numbers, emit a minus sign. */
370 if (value < 0)
372 if (!dyn_string_append_char (ds, '-'))
373 return STATUS_ALLOCATION_FAILED;
374 value = -value;
377 /* Find the power of 10 of the first digit. */
378 i = value;
379 while (i > 9)
381 mask *= 10;
382 i /= 10;
385 /* Write the digits. */
386 while (mask > 0)
388 int digit = value / mask;
390 if (!dyn_string_append_char (ds, '0' + digit))
391 return STATUS_ALLOCATION_FAILED;
393 value -= digit * mask;
394 mask /= 10;
397 return STATUS_OK;
400 /* Creates a new string list node. The contents of the string are
401 empty, but the initial buffer allocation is LENGTH. The string
402 list node should be deleted with string_list_delete. Returns NULL
403 if allocation fails. */
405 static string_list_t
406 string_list_new (length)
407 int length;
409 string_list_t s = (string_list_t) malloc (sizeof (struct string_list_def));
410 s->caret_position = 0;
411 if (s == NULL)
412 return NULL;
413 if (!dyn_string_init ((dyn_string_t) s, length))
414 return NULL;
415 return s;
418 /* Deletes the entire string list starting at NODE. */
420 static void
421 string_list_delete (node)
422 string_list_t node;
424 while (node != NULL)
426 string_list_t next = node->next;
427 dyn_string_delete ((dyn_string_t) node);
428 node = next;
432 /* Appends CHARACTER to the demangled result. If the current trailing
433 character of the result is CHARACTER, a space is inserted first. */
435 static status_t
436 result_add_separated_char (dm, character)
437 demangling_t dm;
438 int character;
440 char *result = dyn_string_buf (result_string (dm));
441 int caret_pos = result_caret_pos (dm);
443 /* Add a space if the last character is already the character we
444 want to add. */
445 if (caret_pos > 0 && result[caret_pos - 1] == character)
446 RETURN_IF_ERROR (result_add_char (dm, ' '));
447 /* Add the character. */
448 RETURN_IF_ERROR (result_add_char (dm, character));
450 return STATUS_OK;
453 /* Allocates and pushes a new string onto the demangled results stack
454 for DM. Subsequent demangling with DM will emit to the new string.
455 Returns STATUS_OK on success, STATUS_ALLOCATION_FAILED on
456 allocation failure. */
458 static status_t
459 result_push (dm)
460 demangling_t dm;
462 string_list_t new_string = string_list_new (0);
463 if (new_string == NULL)
464 /* Allocation failed. */
465 return STATUS_ALLOCATION_FAILED;
467 /* Link the new string to the front of the list of result strings. */
468 new_string->next = (string_list_t) dm->result;
469 dm->result = new_string;
470 return STATUS_OK;
473 /* Removes and returns the topmost element on the demangled results
474 stack for DM. The caller assumes ownership for the returned
475 string. */
477 static string_list_t
478 result_pop (dm)
479 demangling_t dm;
481 string_list_t top = dm->result;
482 dm->result = top->next;
483 return top;
486 /* Returns the current value of the caret for the result string. The
487 value is an offet from the end of the result string. */
489 static int
490 result_get_caret (dm)
491 demangling_t dm;
493 return ((string_list_t) result_string (dm))->caret_position;
496 /* Sets the value of the caret for the result string, counted as an
497 offet from the end of the result string. */
499 static void
500 result_set_caret (dm, position)
501 demangling_t dm;
502 int position;
504 ((string_list_t) result_string (dm))->caret_position = position;
507 /* Shifts the position of the next addition to the result by
508 POSITION_OFFSET. A negative value shifts the caret to the left. */
510 static void
511 result_shift_caret (dm, position_offset)
512 demangling_t dm;
513 int position_offset;
515 ((string_list_t) result_string (dm))->caret_position += position_offset;
518 /* Returns non-zero if the character that comes right before the place
519 where text will be added to the result is a space. In this case,
520 the caller should supress adding another space. */
522 static int
523 result_previous_char_is_space (dm)
524 demangling_t dm;
526 char *result = dyn_string_buf (result_string (dm));
527 int pos = result_caret_pos (dm);
528 return pos > 0 && result[pos - 1] == ' ';
531 /* Returns the start position of a fragment of the demangled result
532 that will be a substitution candidate. Should be called at the
533 start of productions that can add substitutions. */
535 static int
536 substitution_start (dm)
537 demangling_t dm;
539 return result_caret_pos (dm);
542 /* Adds the suffix of the current demangled result of DM starting at
543 START_POSITION as a potential substitution. If TEMPLATE_P is
544 non-zero, this potential substitution is a template-id. */
546 static status_t
547 substitution_add (dm, start_position, template_p)
548 demangling_t dm;
549 int start_position;
550 int template_p;
552 dyn_string_t result = result_string (dm);
553 dyn_string_t substitution = dyn_string_new (0);
554 int i;
556 if (substitution == NULL)
557 return STATUS_ALLOCATION_FAILED;
559 /* Extract the substring of the current demangling result that
560 represents the subsitution candidate. */
561 if (!dyn_string_substring (substitution,
562 result, start_position, result_caret_pos (dm)))
564 dyn_string_delete (substitution);
565 return STATUS_ALLOCATION_FAILED;
568 /* If there's no room for the new entry, grow the array. */
569 if (dm->substitutions_allocated == dm->num_substitutions)
571 size_t new_array_size;
572 if (dm->substitutions_allocated > 0)
573 dm->substitutions_allocated *= 2;
574 else
575 dm->substitutions_allocated = 2;
576 new_array_size =
577 sizeof (struct substitution_def) * dm->substitutions_allocated;
579 dm->substitutions = (struct substitution_def *)
580 realloc (dm->substitutions, new_array_size);
581 if (dm->substitutions == NULL)
582 /* Realloc failed. */
584 dyn_string_delete (substitution);
585 return STATUS_ALLOCATION_FAILED;
589 /* Add the substitution to the array. */
590 i = dm->num_substitutions++;
591 dm->substitutions[i].text = substitution;
592 dm->substitutions[i].template_p = template_p;
594 #ifdef CP_DEMANGLE_DEBUG
595 substitutions_print (dm, stderr);
596 #endif
598 return STATUS_OK;
601 /* Returns the Nth-most-recent substitution. Sets *TEMPLATE_P to
602 non-zero if the substitution is a template-id, zero otherwise.
603 N is numbered from zero. DM retains ownership of the returned
604 string. If N is negative, or equal to or greater than the current
605 number of substitution candidates, returns NULL. */
607 static dyn_string_t
608 substitution_get (dm, n, template_p)
609 demangling_t dm;
610 int n;
611 int *template_p;
613 struct substitution_def *sub;
615 /* Make sure N is in the valid range. */
616 if (n < 0 || n >= dm->num_substitutions)
617 return NULL;
619 sub = &(dm->substitutions[n]);
620 *template_p = sub->template_p;
621 return sub->text;
624 #ifdef CP_DEMANGLE_DEBUG
625 /* Debugging routine to print the current substitutions to FP. */
627 static void
628 substitutions_print (dm, fp)
629 demangling_t dm;
630 FILE *fp;
632 int seq_id;
633 int num = dm->num_substitutions;
635 fprintf (fp, "SUBSTITUTIONS:\n");
636 for (seq_id = -1; seq_id < num - 1; ++seq_id)
638 int template_p;
639 dyn_string_t text = substitution_get (dm, seq_id + 1, &template_p);
641 if (seq_id == -1)
642 fprintf (fp, " S_ ");
643 else
644 fprintf (fp, " S%d_", seq_id);
645 fprintf (fp, " %c: %s\n", template_p ? '*' : ' ', dyn_string_buf (text));
649 #endif /* CP_DEMANGLE_DEBUG */
651 /* Creates a new template argument list. Returns NULL if allocation
652 fails. */
654 static template_arg_list_t
655 template_arg_list_new ()
657 template_arg_list_t new_list =
658 (template_arg_list_t) malloc (sizeof (struct template_arg_list_def));
659 if (new_list == NULL)
660 return NULL;
661 /* Initialize the new list to have no arguments. */
662 new_list->first_argument = NULL;
663 new_list->last_argument = NULL;
664 /* Return the new list. */
665 return new_list;
668 /* Deletes a template argument list and the template arguments it
669 contains. */
671 static void
672 template_arg_list_delete (list)
673 template_arg_list_t list;
675 /* If there are any arguments on LIST, delete them. */
676 if (list->first_argument != NULL)
677 string_list_delete (list->first_argument);
678 /* Delete LIST. */
679 free (list);
682 /* Adds ARG to the template argument list ARG_LIST. */
684 static void
685 template_arg_list_add_arg (arg_list, arg)
686 template_arg_list_t arg_list;
687 string_list_t arg;
689 if (arg_list->first_argument == NULL)
690 /* If there were no arguments before, ARG is the first one. */
691 arg_list->first_argument = arg;
692 else
693 /* Make ARG the last argument on the list. */
694 arg_list->last_argument->next = arg;
695 /* Make ARG the last on the list. */
696 arg_list->last_argument = arg;
697 arg->next = NULL;
700 /* Returns the template arugment at position INDEX in template
701 argument list ARG_LIST. */
703 static string_list_t
704 template_arg_list_get_arg (arg_list, index)
705 template_arg_list_t arg_list;
706 int index;
708 string_list_t arg = arg_list->first_argument;
709 /* Scan down the list of arguments to find the one at position
710 INDEX. */
711 while (index--)
713 arg = arg->next;
714 if (arg == NULL)
715 /* Ran out of arguments before INDEX hit zero. That's an
716 error. */
717 return NULL;
719 /* Return the argument at position INDEX. */
720 return arg;
723 /* Pushes ARG_LIST onto the top of the template argument list stack. */
725 static void
726 push_template_arg_list (dm, arg_list)
727 demangling_t dm;
728 template_arg_list_t arg_list;
730 arg_list->next = dm->template_arg_lists;
731 dm->template_arg_lists = arg_list;
732 #ifdef CP_DEMANGLE_DEBUG
733 fprintf (stderr, " ** pushing template arg list\n");
734 template_arg_list_print (arg_list, stderr);
735 #endif
738 /* Pops and deletes elements on the template argument list stack until
739 arg_list is the topmost element. If arg_list is NULL, all elements
740 are popped and deleted. */
742 static void
743 pop_to_template_arg_list (dm, arg_list)
744 demangling_t dm;
745 template_arg_list_t arg_list;
747 while (dm->template_arg_lists != arg_list)
749 template_arg_list_t top = dm->template_arg_lists;
750 /* Disconnect the topmost element from the list. */
751 dm->template_arg_lists = top->next;
752 /* Delete the popped element. */
753 template_arg_list_delete (top);
754 #ifdef CP_DEMANGLE_DEBUG
755 fprintf (stderr, " ** removing template arg list\n");
756 #endif
760 #ifdef CP_DEMANGLE_DEBUG
762 /* Prints the contents of ARG_LIST to FP. */
764 static void
765 template_arg_list_print (arg_list, fp)
766 template_arg_list_t arg_list;
767 FILE *fp;
769 string_list_t arg;
770 int index = -1;
772 fprintf (fp, "TEMPLATE ARGUMENT LIST:\n");
773 for (arg = arg_list->first_argument; arg != NULL; arg = arg->next)
775 if (index == -1)
776 fprintf (fp, " T_ : ");
777 else
778 fprintf (fp, " T%d_ : ", index);
779 ++index;
780 fprintf (fp, "%s\n", dyn_string_buf ((dyn_string_t) arg));
784 #endif /* CP_DEMANGLE_DEBUG */
786 /* Returns the topmost element on the stack of template argument
787 lists. If there is no list of template arguments, returns NULL. */
789 static template_arg_list_t
790 current_template_arg_list (dm)
791 demangling_t dm;
793 return dm->template_arg_lists;
796 /* Allocates a demangling_t object for demangling mangled NAME. A new
797 result must be pushed before the returned object can be used.
798 Returns NULL if allocation fails. */
800 static demangling_t
801 demangling_new (name, style)
802 const char *name;
803 int style;
805 demangling_t dm;
806 dm = (demangling_t) malloc (sizeof (struct demangling_def));
807 if (dm == NULL)
808 return NULL;
810 dm->name = name;
811 dm->next = name;
812 dm->result = NULL;
813 dm->num_substitutions = 0;
814 dm->substitutions_allocated = 10;
815 dm->template_arg_lists = NULL;
816 dm->last_source_name = dyn_string_new (0);
817 if (dm->last_source_name == NULL)
818 return NULL;
819 dm->substitutions = (struct substitution_def *)
820 malloc (dm->substitutions_allocated * sizeof (struct substitution_def));
821 if (dm->substitutions == NULL)
823 dyn_string_delete (dm->last_source_name);
824 return NULL;
826 dm->style = style;
827 dm->is_constructor = 0;
828 dm->is_destructor = 0;
830 return dm;
833 /* Deallocates a demangling_t object and all memory associated with
834 it. */
836 static void
837 demangling_delete (dm)
838 demangling_t dm;
840 int i;
841 template_arg_list_t arg_list = dm->template_arg_lists;
843 /* Delete the stack of template argument lists. */
844 while (arg_list != NULL)
846 template_arg_list_t next = arg_list->next;
847 template_arg_list_delete (arg_list);
848 arg_list = next;
850 /* Delete the list of substitutions. */
851 for (i = dm->num_substitutions; --i >= 0; )
852 dyn_string_delete (dm->substitutions[i].text);
853 free (dm->substitutions);
854 /* Delete the demangled result. */
855 string_list_delete (dm->result);
856 /* Delete the stored identifier name. */
857 dyn_string_delete (dm->last_source_name);
858 /* Delete the context object itself. */
859 free (dm);
862 /* These functions demangle an alternative of the corresponding
863 production in the mangling spec. The first argument of each is a
864 demangling context structure for the current demangling
865 operation. Most emit demangled text directly to the topmost result
866 string on the result string stack in the demangling context
867 structure. */
869 static status_t demangle_char
870 PARAMS ((demangling_t, int));
871 static status_t demangle_mangled_name
872 PARAMS ((demangling_t));
873 static status_t demangle_encoding
874 PARAMS ((demangling_t));
875 static status_t demangle_name
876 PARAMS ((demangling_t, int *));
877 static status_t demangle_nested_name
878 PARAMS ((demangling_t, int *));
879 static status_t demangle_prefix
880 PARAMS ((demangling_t, int *));
881 static status_t demangle_unqualified_name
882 PARAMS ((demangling_t, int *));
883 static status_t demangle_source_name
884 PARAMS ((demangling_t));
885 static status_t demangle_number
886 PARAMS ((demangling_t, int *, int, int));
887 static status_t demangle_number_literally
888 PARAMS ((demangling_t, dyn_string_t, int, int));
889 static status_t demangle_identifier
890 PARAMS ((demangling_t, int, dyn_string_t));
891 static status_t demangle_operator_name
892 PARAMS ((demangling_t, int, int *));
893 static status_t demangle_nv_offset
894 PARAMS ((demangling_t));
895 static status_t demangle_v_offset
896 PARAMS ((demangling_t));
897 static status_t demangle_call_offset
898 PARAMS ((demangling_t));
899 static status_t demangle_special_name
900 PARAMS ((demangling_t));
901 static status_t demangle_ctor_dtor_name
902 PARAMS ((demangling_t));
903 static status_t demangle_type_ptr
904 PARAMS ((demangling_t, int *, int));
905 static status_t demangle_type
906 PARAMS ((demangling_t));
907 static status_t demangle_CV_qualifiers
908 PARAMS ((demangling_t, dyn_string_t));
909 static status_t demangle_builtin_type
910 PARAMS ((demangling_t));
911 static status_t demangle_function_type
912 PARAMS ((demangling_t, int *));
913 static status_t demangle_bare_function_type
914 PARAMS ((demangling_t, int *));
915 static status_t demangle_class_enum_type
916 PARAMS ((demangling_t, int *));
917 static status_t demangle_array_type
918 PARAMS ((demangling_t, int *));
919 static status_t demangle_template_param
920 PARAMS ((demangling_t));
921 static status_t demangle_template_args
922 PARAMS ((demangling_t));
923 static status_t demangle_literal
924 PARAMS ((demangling_t));
925 static status_t demangle_template_arg
926 PARAMS ((demangling_t));
927 static status_t demangle_expression
928 PARAMS ((demangling_t));
929 static status_t demangle_scope_expression
930 PARAMS ((demangling_t));
931 static status_t demangle_expr_primary
932 PARAMS ((demangling_t));
933 static status_t demangle_substitution
934 PARAMS ((demangling_t, int *));
935 static status_t demangle_local_name
936 PARAMS ((demangling_t));
937 static status_t demangle_discriminator
938 PARAMS ((demangling_t, int));
939 static status_t cp_demangle
940 PARAMS ((const char *, dyn_string_t, int));
941 static status_t cp_demangle_type
942 PARAMS ((const char*, dyn_string_t));
944 /* When passed to demangle_bare_function_type, indicates that the
945 function's return type is not encoded before its parameter types. */
946 #define BFT_NO_RETURN_TYPE NULL
948 /* Check that the next character is C. If so, consume it. If not,
949 return an error. */
951 static status_t
952 demangle_char (dm, c)
953 demangling_t dm;
954 int c;
956 static char *error_message = NULL;
958 if (peek_char (dm) == c)
960 advance_char (dm);
961 return STATUS_OK;
963 else
965 if (error_message == NULL)
966 error_message = strdup ("Expected ?");
967 error_message[9] = c;
968 return error_message;
972 /* Demangles and emits a <mangled-name>.
974 <mangled-name> ::= _Z <encoding> */
976 static status_t
977 demangle_mangled_name (dm)
978 demangling_t dm;
980 DEMANGLE_TRACE ("mangled-name", dm);
981 RETURN_IF_ERROR (demangle_char (dm, '_'));
982 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
983 RETURN_IF_ERROR (demangle_encoding (dm));
984 return STATUS_OK;
987 /* Demangles and emits an <encoding>.
989 <encoding> ::= <function name> <bare-function-type>
990 ::= <data name>
991 ::= <special-name> */
993 static status_t
994 demangle_encoding (dm)
995 demangling_t dm;
997 int encode_return_type;
998 int start_position;
999 template_arg_list_t old_arg_list = current_template_arg_list (dm);
1000 char peek = peek_char (dm);
1002 DEMANGLE_TRACE ("encoding", dm);
1004 /* Remember where the name starts. If it turns out to be a template
1005 function, we'll have to insert the return type here. */
1006 start_position = result_caret_pos (dm);
1008 if (peek == 'G' || peek == 'T')
1009 RETURN_IF_ERROR (demangle_special_name (dm));
1010 else
1012 /* Now demangle the name. */
1013 RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));
1015 /* If there's anything left, the name was a function name, with
1016 maybe its return type, and its parameter types, following. */
1017 if (!end_of_name_p (dm)
1018 && peek_char (dm) != 'E')
1020 if (encode_return_type)
1021 /* Template functions have their return type encoded. The
1022 return type should be inserted at start_position. */
1023 RETURN_IF_ERROR
1024 (demangle_bare_function_type (dm, &start_position));
1025 else
1026 /* Non-template functions don't have their return type
1027 encoded. */
1028 RETURN_IF_ERROR
1029 (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE));
1033 /* Pop off template argument lists that were built during the
1034 mangling of this name, to restore the old template context. */
1035 pop_to_template_arg_list (dm, old_arg_list);
1037 return STATUS_OK;
1040 /* Demangles and emits a <name>.
1042 <name> ::= <unscoped-name>
1043 ::= <unscoped-template-name> <template-args>
1044 ::= <nested-name>
1045 ::= <local-name>
1047 <unscoped-name> ::= <unqualified-name>
1048 ::= St <unqualified-name> # ::std::
1050 <unscoped-template-name>
1051 ::= <unscoped-name>
1052 ::= <substitution> */
1054 static status_t
1055 demangle_name (dm, encode_return_type)
1056 demangling_t dm;
1057 int *encode_return_type;
1059 int start = substitution_start (dm);
1060 char peek = peek_char (dm);
1061 int is_std_substitution = 0;
1063 /* Generally, the return type is encoded if the function is a
1064 template-id, and suppressed otherwise. There are a few cases,
1065 though, in which the return type is not encoded even for a
1066 templated function. In these cases, this flag is set. */
1067 int suppress_return_type = 0;
1069 DEMANGLE_TRACE ("name", dm);
1071 switch (peek)
1073 case 'N':
1074 /* This is a <nested-name>. */
1075 RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));
1076 break;
1078 case 'Z':
1079 RETURN_IF_ERROR (demangle_local_name (dm));
1080 *encode_return_type = 0;
1081 break;
1083 case 'S':
1084 /* The `St' substitution allows a name nested in std:: to appear
1085 without being enclosed in a nested name. */
1086 if (peek_char_next (dm) == 't')
1088 (void) next_char (dm);
1089 (void) next_char (dm);
1090 RETURN_IF_ERROR (result_add (dm, "std::"));
1091 RETURN_IF_ERROR
1092 (demangle_unqualified_name (dm, &suppress_return_type));
1093 is_std_substitution = 1;
1095 else
1096 RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
1097 /* Check if a template argument list immediately follows.
1098 If so, then we just demangled an <unqualified-template-name>. */
1099 if (peek_char (dm) == 'I')
1101 /* A template name of the form std::<unqualified-name> is a
1102 substitution candidate. */
1103 if (is_std_substitution)
1104 RETURN_IF_ERROR (substitution_add (dm, start, 0));
1105 /* Demangle the <template-args> here. */
1106 RETURN_IF_ERROR (demangle_template_args (dm));
1107 *encode_return_type = !suppress_return_type;
1109 else
1110 *encode_return_type = 0;
1112 break;
1114 default:
1115 /* This is an <unscoped-name> or <unscoped-template-name>. */
1116 RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));
1118 /* If the <unqualified-name> is followed by template args, this
1119 is an <unscoped-template-name>. */
1120 if (peek_char (dm) == 'I')
1122 /* Add a substitution for the unqualified template name. */
1123 RETURN_IF_ERROR (substitution_add (dm, start, 0));
1125 RETURN_IF_ERROR (demangle_template_args (dm));
1126 *encode_return_type = !suppress_return_type;
1128 else
1129 *encode_return_type = 0;
1131 break;
1134 return STATUS_OK;
1137 /* Demangles and emits a <nested-name>.
1139 <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E */
1141 static status_t
1142 demangle_nested_name (dm, encode_return_type)
1143 demangling_t dm;
1144 int *encode_return_type;
1146 char peek;
1148 DEMANGLE_TRACE ("nested-name", dm);
1150 RETURN_IF_ERROR (demangle_char (dm, 'N'));
1152 peek = peek_char (dm);
1153 if (peek == 'r' || peek == 'V' || peek == 'K')
1155 dyn_string_t cv_qualifiers;
1156 status_t status;
1158 /* Snarf up CV qualifiers. */
1159 cv_qualifiers = dyn_string_new (24);
1160 if (cv_qualifiers == NULL)
1161 return STATUS_ALLOCATION_FAILED;
1162 demangle_CV_qualifiers (dm, cv_qualifiers);
1164 /* Emit them, preceded by a space. */
1165 status = result_add_char (dm, ' ');
1166 if (STATUS_NO_ERROR (status))
1167 status = result_add_string (dm, cv_qualifiers);
1168 /* The CV qualifiers that occur in a <nested-name> will be
1169 qualifiers for member functions. These are placed at the end
1170 of the function. Therefore, shift the caret to the left by
1171 the length of the qualifiers, so other text is inserted
1172 before them and they stay at the end. */
1173 result_shift_caret (dm, -dyn_string_length (cv_qualifiers) - 1);
1174 /* Clean up. */
1175 dyn_string_delete (cv_qualifiers);
1176 RETURN_IF_ERROR (status);
1179 RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
1180 /* No need to demangle the final <unqualified-name>; demangle_prefix
1181 will handle it. */
1182 RETURN_IF_ERROR (demangle_char (dm, 'E'));
1184 return STATUS_OK;
1187 /* Demangles and emits a <prefix>.
1189 <prefix> ::= <prefix> <unqualified-name>
1190 ::= <template-prefix> <template-args>
1191 ::= # empty
1192 ::= <substitution>
1194 <template-prefix> ::= <prefix>
1195 ::= <substitution> */
1197 static status_t
1198 demangle_prefix (dm, encode_return_type)
1199 demangling_t dm;
1200 int *encode_return_type;
1202 int start = substitution_start (dm);
1203 int nested = 0;
1205 /* ENCODE_RETURN_TYPE is updated as we decend the nesting chain.
1206 After <template-args>, it is set to non-zero; after everything
1207 else it is set to zero. */
1209 /* Generally, the return type is encoded if the function is a
1210 template-id, and suppressed otherwise. There are a few cases,
1211 though, in which the return type is not encoded even for a
1212 templated function. In these cases, this flag is set. */
1213 int suppress_return_type = 0;
1215 DEMANGLE_TRACE ("prefix", dm);
1217 while (1)
1219 char peek;
1221 if (end_of_name_p (dm))
1222 return "Unexpected end of name in <compound-name>.";
1224 peek = peek_char (dm);
1226 /* We'll initialize suppress_return_type to false, and set it to true
1227 if we end up demangling a constructor name. However, make
1228 sure we're not actually about to demangle template arguments
1229 -- if so, this is the <template-args> following a
1230 <template-prefix>, so we'll want the previous flag value
1231 around. */
1232 if (peek != 'I')
1233 suppress_return_type = 0;
1235 if (IS_DIGIT ((unsigned char) peek)
1236 || (peek >= 'a' && peek <= 'z')
1237 || peek == 'C' || peek == 'D'
1238 || peek == 'S')
1240 /* We have another level of scope qualification. */
1241 if (nested)
1242 RETURN_IF_ERROR (result_add (dm, NAMESPACE_SEPARATOR));
1243 else
1244 nested = 1;
1246 if (peek == 'S')
1247 /* The substitution determines whether this is a
1248 template-id. */
1249 RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
1250 else
1252 /* It's just a name. */
1253 RETURN_IF_ERROR
1254 (demangle_unqualified_name (dm, &suppress_return_type));
1255 *encode_return_type = 0;
1258 else if (peek == 'Z')
1259 RETURN_IF_ERROR (demangle_local_name (dm));
1260 else if (peek == 'I')
1262 RETURN_IF_ERROR (demangle_template_args (dm));
1264 /* Now we want to indicate to the caller that we've
1265 demangled template arguments, thus the prefix was a
1266 <template-prefix>. That's so that the caller knows to
1267 demangle the function's return type, if this turns out to
1268 be a function name. But, if it's a member template
1269 constructor or a templated conversion operator, report it
1270 as untemplated. Those never get encoded return types. */
1271 *encode_return_type = !suppress_return_type;
1273 else if (peek == 'E')
1274 /* All done. */
1275 return STATUS_OK;
1276 else
1277 return "Unexpected character in <compound-name>.";
1279 if (peek != 'S'
1280 && peek_char (dm) != 'E')
1281 /* Add a new substitution for the prefix thus far. */
1282 RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));
1286 /* Demangles and emits an <unqualified-name>. If this
1287 <unqualified-name> is for a special function type that should never
1288 have its return type encoded (particularly, a constructor or
1289 conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise,
1290 it is set to zero.
1292 <unqualified-name> ::= <operator-name>
1293 ::= <special-name>
1294 ::= <source-name> */
1296 static status_t
1297 demangle_unqualified_name (dm, suppress_return_type)
1298 demangling_t dm;
1299 int *suppress_return_type;
1301 char peek = peek_char (dm);
1303 DEMANGLE_TRACE ("unqualified-name", dm);
1305 /* By default, don't force suppression of the return type (though
1306 non-template functions still don't get a return type encoded). */
1307 *suppress_return_type = 0;
1309 if (IS_DIGIT ((unsigned char) peek))
1310 RETURN_IF_ERROR (demangle_source_name (dm));
1311 else if (peek >= 'a' && peek <= 'z')
1313 int num_args;
1315 /* Conversion operators never have a return type encoded. */
1316 if (peek == 'c' && peek_char_next (dm) == 'v')
1317 *suppress_return_type = 1;
1319 RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args));
1321 else if (peek == 'C' || peek == 'D')
1323 /* Constructors never have a return type encoded. */
1324 if (peek == 'C')
1325 *suppress_return_type = 1;
1327 RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
1329 else
1330 return "Unexpected character in <unqualified-name>.";
1332 return STATUS_OK;
1335 /* Demangles and emits <source-name>.
1337 <source-name> ::= <length number> <identifier> */
1339 static status_t
1340 demangle_source_name (dm)
1341 demangling_t dm;
1343 int length;
1345 DEMANGLE_TRACE ("source-name", dm);
1347 /* Decode the length of the identifier. */
1348 RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0));
1349 if (length == 0)
1350 return "Zero length in <source-name>.";
1352 /* Now the identifier itself. It's placed into last_source_name,
1353 where it can be used to build a constructor or destructor name. */
1354 RETURN_IF_ERROR (demangle_identifier (dm, length,
1355 dm->last_source_name));
1357 /* Emit it. */
1358 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
1360 return STATUS_OK;
1363 /* Demangles a number, either a <number> or a <positive-number> at the
1364 current position, consuming all consecutive digit characters. Sets
1365 *VALUE to the resulting numberand returns STATUS_OK. The number is
1366 interpreted as BASE, which must be either 10 or 36. If IS_SIGNED
1367 is non-zero, negative numbers -- prefixed with `n' -- are accepted.
1369 <number> ::= [n] <positive-number>
1371 <positive-number> ::= <decimal integer> */
1373 static status_t
1374 demangle_number (dm, value, base, is_signed)
1375 demangling_t dm;
1376 int *value;
1377 int base;
1378 int is_signed;
1380 dyn_string_t number = dyn_string_new (10);
1382 DEMANGLE_TRACE ("number", dm);
1384 if (number == NULL)
1385 return STATUS_ALLOCATION_FAILED;
1387 demangle_number_literally (dm, number, base, is_signed);
1388 *value = strtol (dyn_string_buf (number), NULL, base);
1389 dyn_string_delete (number);
1391 return STATUS_OK;
1394 /* Demangles a number at the current position. The digits (and minus
1395 sign, if present) that make up the number are appended to STR.
1396 Only base-BASE digits are accepted; BASE must be either 10 or 36.
1397 If IS_SIGNED, negative numbers -- prefixed with `n' -- are
1398 accepted. Does not consume a trailing underscore or other
1399 terminating character. */
1401 static status_t
1402 demangle_number_literally (dm, str, base, is_signed)
1403 demangling_t dm;
1404 dyn_string_t str;
1405 int base;
1406 int is_signed;
1408 DEMANGLE_TRACE ("number*", dm);
1410 if (base != 10 && base != 36)
1411 return STATUS_INTERNAL_ERROR;
1413 /* An `n' denotes a negative number. */
1414 if (is_signed && peek_char (dm) == 'n')
1416 /* Skip past the n. */
1417 advance_char (dm);
1418 /* The normal way to write a negative number is with a minus
1419 sign. */
1420 if (!dyn_string_append_char (str, '-'))
1421 return STATUS_ALLOCATION_FAILED;
1424 /* Loop until we hit a non-digit. */
1425 while (1)
1427 char peek = peek_char (dm);
1428 if (IS_DIGIT ((unsigned char) peek)
1429 || (base == 36 && peek >= 'A' && peek <= 'Z'))
1431 /* Accumulate digits. */
1432 if (!dyn_string_append_char (str, next_char (dm)))
1433 return STATUS_ALLOCATION_FAILED;
1435 else
1436 /* Not a digit? All done. */
1437 break;
1440 return STATUS_OK;
1443 /* Demangles an identifier at the current position of LENGTH
1444 characters and places it in IDENTIFIER. */
1446 static status_t
1447 demangle_identifier (dm, length, identifier)
1448 demangling_t dm;
1449 int length;
1450 dyn_string_t identifier;
1452 DEMANGLE_TRACE ("identifier", dm);
1454 dyn_string_clear (identifier);
1455 if (!dyn_string_resize (identifier, length))
1456 return STATUS_ALLOCATION_FAILED;
1458 while (length-- > 0)
1460 if (end_of_name_p (dm))
1461 return "Unexpected end of name in <identifier>.";
1462 if (!dyn_string_append_char (identifier, next_char (dm)))
1463 return STATUS_ALLOCATION_FAILED;
1466 /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'
1467 followed by the source file name and some random characters.
1468 Unless we're in strict mode, decipher these names appropriately. */
1469 if (!flag_strict)
1471 char *name = dyn_string_buf (identifier);
1472 int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
1474 /* Compare the first, fixed part. */
1475 if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
1477 name += prefix_length;
1478 /* The next character might be a period, an underscore, or
1479 dollar sign, depending on the target architecture's
1480 assembler's capabilities. After that comes an `N'. */
1481 if ((*name == '.' || *name == '_' || *name == '$')
1482 && *(name + 1) == 'N')
1483 /* This looks like the anonymous namespace identifier.
1484 Replace it with something comprehensible. */
1485 dyn_string_copy_cstr (identifier, "(anonymous namespace)");
1489 return STATUS_OK;
1492 /* Demangles and emits an <operator-name>. If SHORT_NAME is non-zero,
1493 the short form is emitted; otherwise the full source form
1494 (`operator +' etc.) is emitted. *NUM_ARGS is set to the number of
1495 operands that the operator takes.
1497 <operator-name>
1498 ::= nw # new
1499 ::= na # new[]
1500 ::= dl # delete
1501 ::= da # delete[]
1502 ::= ps # + (unary)
1503 ::= ng # - (unary)
1504 ::= ad # & (unary)
1505 ::= de # * (unary)
1506 ::= co # ~
1507 ::= pl # +
1508 ::= mi # -
1509 ::= ml # *
1510 ::= dv # /
1511 ::= rm # %
1512 ::= an # &
1513 ::= or # |
1514 ::= eo # ^
1515 ::= aS # =
1516 ::= pL # +=
1517 ::= mI # -=
1518 ::= mL # *=
1519 ::= dV # /=
1520 ::= rM # %=
1521 ::= aN # &=
1522 ::= oR # |=
1523 ::= eO # ^=
1524 ::= ls # <<
1525 ::= rs # >>
1526 ::= lS # <<=
1527 ::= rS # >>=
1528 ::= eq # ==
1529 ::= ne # !=
1530 ::= lt # <
1531 ::= gt # >
1532 ::= le # <=
1533 ::= ge # >=
1534 ::= nt # !
1535 ::= aa # &&
1536 ::= oo # ||
1537 ::= pp # ++
1538 ::= mm # --
1539 ::= cm # ,
1540 ::= pm # ->*
1541 ::= pt # ->
1542 ::= cl # ()
1543 ::= ix # []
1544 ::= qu # ?
1545 ::= sz # sizeof
1546 ::= cv <type> # cast
1547 ::= v [0-9] <source-name> # vendor extended operator */
1549 static status_t
1550 demangle_operator_name (dm, short_name, num_args)
1551 demangling_t dm;
1552 int short_name;
1553 int *num_args;
1555 struct operator_code
1557 /* The mangled code for this operator. */
1558 const char *const code;
1559 /* The source name of this operator. */
1560 const char *const name;
1561 /* The number of arguments this operator takes. */
1562 const int num_args;
1565 static const struct operator_code operators[] =
1567 { "aN", "&=" , 2 },
1568 { "aS", "=" , 2 },
1569 { "aa", "&&" , 2 },
1570 { "ad", "&" , 1 },
1571 { "an", "&" , 2 },
1572 { "cl", "()" , 0 },
1573 { "cm", "," , 2 },
1574 { "co", "~" , 1 },
1575 { "dV", "/=" , 2 },
1576 { "da", " delete[]", 1 },
1577 { "de", "*" , 1 },
1578 { "dl", " delete" , 1 },
1579 { "dv", "/" , 2 },
1580 { "eO", "^=" , 2 },
1581 { "eo", "^" , 2 },
1582 { "eq", "==" , 2 },
1583 { "ge", ">=" , 2 },
1584 { "gt", ">" , 2 },
1585 { "ix", "[]" , 2 },
1586 { "lS", "<<=" , 2 },
1587 { "le", "<=" , 2 },
1588 { "ls", "<<" , 2 },
1589 { "lt", "<" , 2 },
1590 { "mI", "-=" , 2 },
1591 { "mL", "*=" , 2 },
1592 { "mi", "-" , 2 },
1593 { "ml", "*" , 2 },
1594 { "mm", "--" , 1 },
1595 { "na", " new[]" , 1 },
1596 { "ne", "!=" , 2 },
1597 { "ng", "-" , 1 },
1598 { "nt", "!" , 1 },
1599 { "nw", " new" , 1 },
1600 { "oR", "|=" , 2 },
1601 { "oo", "||" , 2 },
1602 { "or", "|" , 2 },
1603 { "pL", "+=" , 2 },
1604 { "pl", "+" , 2 },
1605 { "pm", "->*" , 2 },
1606 { "pp", "++" , 1 },
1607 { "ps", "+" , 1 },
1608 { "pt", "->" , 2 },
1609 { "qu", "?" , 3 },
1610 { "rM", "%=" , 2 },
1611 { "rS", ">>=" , 2 },
1612 { "rm", "%" , 2 },
1613 { "rs", ">>" , 2 },
1614 { "sz", " sizeof" , 1 }
1617 const int num_operators =
1618 sizeof (operators) / sizeof (struct operator_code);
1620 int c0 = next_char (dm);
1621 int c1 = next_char (dm);
1622 const struct operator_code* p1 = operators;
1623 const struct operator_code* p2 = operators + num_operators;
1625 DEMANGLE_TRACE ("operator-name", dm);
1627 /* Is this a vendor-extended operator? */
1628 if (c0 == 'v' && IS_DIGIT (c1))
1630 RETURN_IF_ERROR (result_add (dm, "operator "));
1631 RETURN_IF_ERROR (demangle_source_name (dm));
1632 *num_args = 0;
1633 return STATUS_OK;
1636 /* Is this a conversion operator? */
1637 if (c0 == 'c' && c1 == 'v')
1639 RETURN_IF_ERROR (result_add (dm, "operator "));
1640 /* Demangle the converted-to type. */
1641 RETURN_IF_ERROR (demangle_type (dm));
1642 *num_args = 0;
1643 return STATUS_OK;
1646 /* Perform a binary search for the operator code. */
1647 while (1)
1649 const struct operator_code* p = p1 + (p2 - p1) / 2;
1650 char match0 = p->code[0];
1651 char match1 = p->code[1];
1653 if (c0 == match0 && c1 == match1)
1654 /* Found it. */
1656 if (!short_name)
1657 RETURN_IF_ERROR (result_add (dm, "operator"));
1658 RETURN_IF_ERROR (result_add (dm, p->name));
1659 *num_args = p->num_args;
1661 return STATUS_OK;
1664 if (p == p1)
1665 /* Couldn't find it. */
1666 return "Unknown code in <operator-name>.";
1668 /* Try again. */
1669 if (c0 < match0 || (c0 == match0 && c1 < match1))
1670 p2 = p;
1671 else
1672 p1 = p;
1676 /* Demangles and omits an <nv-offset>.
1678 <nv-offset> ::= <offset number> # non-virtual base override */
1680 static status_t
1681 demangle_nv_offset (dm)
1682 demangling_t dm;
1684 dyn_string_t number;
1685 status_t status = STATUS_OK;
1687 DEMANGLE_TRACE ("h-offset", dm);
1689 /* Demangle the offset. */
1690 number = dyn_string_new (4);
1691 if (number == NULL)
1692 return STATUS_ALLOCATION_FAILED;
1693 demangle_number_literally (dm, number, 10, 1);
1695 /* Don't display the offset unless in verbose mode. */
1696 if (flag_verbose)
1698 status = result_add (dm, " [nv:");
1699 if (STATUS_NO_ERROR (status))
1700 status = result_add_string (dm, number);
1701 if (STATUS_NO_ERROR (status))
1702 status = result_add_char (dm, ']');
1705 /* Clean up. */
1706 dyn_string_delete (number);
1707 RETURN_IF_ERROR (status);
1708 return STATUS_OK;
1711 /* Demangles and emits a <v-offset>.
1713 <v-offset> ::= <offset number> _ <virtual offset number>
1714 # virtual base override, with vcall offset */
1716 static status_t
1717 demangle_v_offset (dm)
1718 demangling_t dm;
1720 dyn_string_t number;
1721 status_t status = STATUS_OK;
1723 DEMANGLE_TRACE ("v-offset", dm);
1725 /* Demangle the offset. */
1726 number = dyn_string_new (4);
1727 if (number == NULL)
1728 return STATUS_ALLOCATION_FAILED;
1729 demangle_number_literally (dm, number, 10, 1);
1731 /* Don't display the offset unless in verbose mode. */
1732 if (flag_verbose)
1734 status = result_add (dm, " [v:");
1735 if (STATUS_NO_ERROR (status))
1736 status = result_add_string (dm, number);
1737 if (STATUS_NO_ERROR (status))
1738 result_add_char (dm, ',');
1740 dyn_string_delete (number);
1741 RETURN_IF_ERROR (status);
1743 /* Demangle the separator. */
1744 RETURN_IF_ERROR (demangle_char (dm, '_'));
1746 /* Demangle the vcall offset. */
1747 number = dyn_string_new (4);
1748 if (number == NULL)
1749 return STATUS_ALLOCATION_FAILED;
1750 demangle_number_literally (dm, number, 10, 1);
1752 /* Don't display the vcall offset unless in verbose mode. */
1753 if (flag_verbose)
1755 status = result_add_string (dm, number);
1756 if (STATUS_NO_ERROR (status))
1757 status = result_add_char (dm, ']');
1759 dyn_string_delete (number);
1760 RETURN_IF_ERROR (status);
1762 return STATUS_OK;
1765 /* Demangles and emits a <call-offset>.
1767 <call-offset> ::= h <nv-offset> _
1768 ::= v <v-offset> _ */
1770 static status_t
1771 demangle_call_offset (dm)
1772 demangling_t dm;
1774 DEMANGLE_TRACE ("call-offset", dm);
1776 switch (peek_char (dm))
1778 case 'h':
1779 advance_char (dm);
1780 /* Demangle the offset. */
1781 RETURN_IF_ERROR (demangle_nv_offset (dm));
1782 /* Demangle the separator. */
1783 RETURN_IF_ERROR (demangle_char (dm, '_'));
1784 break;
1786 case 'v':
1787 advance_char (dm);
1788 /* Demangle the offset. */
1789 RETURN_IF_ERROR (demangle_v_offset (dm));
1790 /* Demangle the separator. */
1791 RETURN_IF_ERROR (demangle_char (dm, '_'));
1792 break;
1794 default:
1795 return "Unrecognized <call-offset>.";
1798 return STATUS_OK;
1801 /* Demangles and emits a <special-name>.
1803 <special-name> ::= GV <object name> # Guard variable
1804 ::= TV <type> # virtual table
1805 ::= TT <type> # VTT
1806 ::= TI <type> # typeinfo structure
1807 ::= TS <type> # typeinfo name
1809 Other relevant productions include thunks:
1811 <special-name> ::= T <call-offset> <base encoding>
1812 # base is the nominal target function of thunk
1814 <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
1815 # base is the nominal target function of thunk
1816 # first call-offset is 'this' adjustment
1817 # second call-offset is result adjustment
1819 where
1821 <call-offset> ::= h <nv-offset> _
1822 ::= v <v-offset> _
1824 Also demangles the special g++ manglings,
1826 <special-name> ::= TC <type> <offset number> _ <base type>
1827 # construction vtable
1828 ::= TF <type> # typeinfo function (old ABI only)
1829 ::= TJ <type> # java Class structure */
1831 static status_t
1832 demangle_special_name (dm)
1833 demangling_t dm;
1835 dyn_string_t number;
1836 int unused;
1837 char peek = peek_char (dm);
1839 DEMANGLE_TRACE ("special-name", dm);
1841 if (peek == 'G')
1843 /* Consume the G. */
1844 advance_char (dm);
1845 switch (peek_char (dm))
1847 case 'V':
1848 /* A guard variable name. */
1849 advance_char (dm);
1850 RETURN_IF_ERROR (result_add (dm, "guard variable for "));
1851 RETURN_IF_ERROR (demangle_name (dm, &unused));
1852 break;
1854 case 'R':
1855 /* A reference temporary. */
1856 advance_char (dm);
1857 RETURN_IF_ERROR (result_add (dm, "reference temporary for "));
1858 RETURN_IF_ERROR (demangle_name (dm, &unused));
1859 break;
1861 default:
1862 return "Unrecognized <special-name>.";
1865 else if (peek == 'T')
1867 status_t status = STATUS_OK;
1869 /* Other C++ implementation miscellania. Consume the T. */
1870 advance_char (dm);
1872 switch (peek_char (dm))
1874 case 'V':
1875 /* Virtual table. */
1876 advance_char (dm);
1877 RETURN_IF_ERROR (result_add (dm, "vtable for "));
1878 RETURN_IF_ERROR (demangle_type (dm));
1879 break;
1881 case 'T':
1882 /* VTT structure. */
1883 advance_char (dm);
1884 RETURN_IF_ERROR (result_add (dm, "VTT for "));
1885 RETURN_IF_ERROR (demangle_type (dm));
1886 break;
1888 case 'I':
1889 /* Typeinfo structure. */
1890 advance_char (dm);
1891 RETURN_IF_ERROR (result_add (dm, "typeinfo for "));
1892 RETURN_IF_ERROR (demangle_type (dm));
1893 break;
1895 case 'F':
1896 /* Typeinfo function. Used only in old ABI with new mangling. */
1897 advance_char (dm);
1898 RETURN_IF_ERROR (result_add (dm, "typeinfo fn for "));
1899 RETURN_IF_ERROR (demangle_type (dm));
1900 break;
1902 case 'S':
1903 /* Character string containing type name, used in typeinfo. */
1904 advance_char (dm);
1905 RETURN_IF_ERROR (result_add (dm, "typeinfo name for "));
1906 RETURN_IF_ERROR (demangle_type (dm));
1907 break;
1909 case 'J':
1910 /* The java Class variable corresponding to a C++ class. */
1911 advance_char (dm);
1912 RETURN_IF_ERROR (result_add (dm, "java Class for "));
1913 RETURN_IF_ERROR (demangle_type (dm));
1914 break;
1916 case 'h':
1917 /* Non-virtual thunk. */
1918 advance_char (dm);
1919 RETURN_IF_ERROR (result_add (dm, "non-virtual thunk"));
1920 RETURN_IF_ERROR (demangle_nv_offset (dm));
1921 /* Demangle the separator. */
1922 RETURN_IF_ERROR (demangle_char (dm, '_'));
1923 /* Demangle and emit the target name and function type. */
1924 RETURN_IF_ERROR (result_add (dm, " to "));
1925 RETURN_IF_ERROR (demangle_encoding (dm));
1926 break;
1928 case 'v':
1929 /* Virtual thunk. */
1930 advance_char (dm);
1931 RETURN_IF_ERROR (result_add (dm, "virtual thunk"));
1932 RETURN_IF_ERROR (demangle_v_offset (dm));
1933 /* Demangle the separator. */
1934 RETURN_IF_ERROR (demangle_char (dm, '_'));
1935 /* Demangle and emit the target function. */
1936 RETURN_IF_ERROR (result_add (dm, " to "));
1937 RETURN_IF_ERROR (demangle_encoding (dm));
1938 break;
1940 case 'c':
1941 /* Covariant return thunk. */
1942 advance_char (dm);
1943 RETURN_IF_ERROR (result_add (dm, "covariant return thunk"));
1944 RETURN_IF_ERROR (demangle_call_offset (dm));
1945 RETURN_IF_ERROR (demangle_call_offset (dm));
1946 /* Demangle and emit the target function. */
1947 RETURN_IF_ERROR (result_add (dm, " to "));
1948 RETURN_IF_ERROR (demangle_encoding (dm));
1949 break;
1951 case 'C':
1952 /* TC is a special g++ mangling for a construction vtable. */
1953 if (!flag_strict)
1955 dyn_string_t derived_type;
1957 advance_char (dm);
1958 RETURN_IF_ERROR (result_add (dm, "construction vtable for "));
1960 /* Demangle the derived type off to the side. */
1961 RETURN_IF_ERROR (result_push (dm));
1962 RETURN_IF_ERROR (demangle_type (dm));
1963 derived_type = (dyn_string_t) result_pop (dm);
1965 /* Demangle the offset. */
1966 number = dyn_string_new (4);
1967 if (number == NULL)
1969 dyn_string_delete (derived_type);
1970 return STATUS_ALLOCATION_FAILED;
1972 demangle_number_literally (dm, number, 10, 1);
1973 /* Demangle the underscore separator. */
1974 status = demangle_char (dm, '_');
1976 /* Demangle the base type. */
1977 if (STATUS_NO_ERROR (status))
1978 status = demangle_type (dm);
1980 /* Emit the derived type. */
1981 if (STATUS_NO_ERROR (status))
1982 status = result_add (dm, "-in-");
1983 if (STATUS_NO_ERROR (status))
1984 status = result_add_string (dm, derived_type);
1985 dyn_string_delete (derived_type);
1987 /* Don't display the offset unless in verbose mode. */
1988 if (flag_verbose)
1990 status = result_add_char (dm, ' ');
1991 if (STATUS_NO_ERROR (status))
1992 result_add_string (dm, number);
1994 dyn_string_delete (number);
1995 RETURN_IF_ERROR (status);
1996 break;
1998 /* If flag_strict, fall through. */
2000 default:
2001 return "Unrecognized <special-name>.";
2004 else
2005 return STATUS_ERROR;
2007 return STATUS_OK;
2010 /* Demangles and emits a <ctor-dtor-name>.
2012 <ctor-dtor-name>
2013 ::= C1 # complete object (in-charge) ctor
2014 ::= C2 # base object (not-in-charge) ctor
2015 ::= C3 # complete object (in-charge) allocating ctor
2016 ::= D0 # deleting (in-charge) dtor
2017 ::= D1 # complete object (in-charge) dtor
2018 ::= D2 # base object (not-in-charge) dtor */
2020 static status_t
2021 demangle_ctor_dtor_name (dm)
2022 demangling_t dm;
2024 static const char *const ctor_flavors[] =
2026 "in-charge",
2027 "not-in-charge",
2028 "allocating"
2030 static const char *const dtor_flavors[] =
2032 "in-charge deleting",
2033 "in-charge",
2034 "not-in-charge"
2037 int flavor;
2038 char peek = peek_char (dm);
2040 DEMANGLE_TRACE ("ctor-dtor-name", dm);
2042 if (peek == 'C')
2044 /* A constructor name. Consume the C. */
2045 advance_char (dm);
2046 flavor = next_char (dm);
2047 if (flavor < '1' || flavor > '3')
2048 return "Unrecognized constructor.";
2049 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
2050 switch (flavor)
2052 case '1': dm->is_constructor = gnu_v3_complete_object_ctor;
2053 break;
2054 case '2': dm->is_constructor = gnu_v3_base_object_ctor;
2055 break;
2056 case '3': dm->is_constructor = gnu_v3_complete_object_allocating_ctor;
2057 break;
2059 /* Print the flavor of the constructor if in verbose mode. */
2060 if (flag_verbose)
2062 RETURN_IF_ERROR (result_add (dm, "["));
2063 RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor - '1']));
2064 RETURN_IF_ERROR (result_add_char (dm, ']'));
2067 else if (peek == 'D')
2069 /* A destructor name. Consume the D. */
2070 advance_char (dm);
2071 flavor = next_char (dm);
2072 if (flavor < '0' || flavor > '2')
2073 return "Unrecognized destructor.";
2074 RETURN_IF_ERROR (result_add_char (dm, '~'));
2075 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
2076 switch (flavor)
2078 case '0': dm->is_destructor = gnu_v3_deleting_dtor;
2079 break;
2080 case '1': dm->is_destructor = gnu_v3_complete_object_dtor;
2081 break;
2082 case '2': dm->is_destructor = gnu_v3_base_object_dtor;
2083 break;
2085 /* Print the flavor of the destructor if in verbose mode. */
2086 if (flag_verbose)
2088 RETURN_IF_ERROR (result_add (dm, " ["));
2089 RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor - '0']));
2090 RETURN_IF_ERROR (result_add_char (dm, ']'));
2093 else
2094 return STATUS_ERROR;
2096 return STATUS_OK;
2099 /* Handle pointer, reference, and pointer-to-member cases for
2100 demangle_type. All consecutive `P's, `R's, and 'M's are joined to
2101 build a pointer/reference type. We snarf all these, plus the
2102 following <type>, all at once since we need to know whether we have
2103 a pointer to data or pointer to function to construct the right
2104 output syntax. C++'s pointer syntax is hairy.
2106 This function adds substitution candidates for every nested
2107 pointer/reference type it processes, including the outermost, final
2108 type, assuming the substitution starts at SUBSTITUTION_START in the
2109 demangling result. For example, if this function demangles
2110 `PP3Foo', it will add a substitution for `Foo', `Foo*', and
2111 `Foo**', in that order.
2113 *INSERT_POS is a quantity used internally, when this function calls
2114 itself recursively, to figure out where to insert pointer
2115 punctuation on the way up. On entry to this function, INSERT_POS
2116 should point to a temporary value, but that value need not be
2117 initialized.
2119 <type> ::= P <type>
2120 ::= R <type>
2121 ::= <pointer-to-member-type>
2123 <pointer-to-member-type> ::= M </class/ type> </member/ type> */
2125 static status_t
2126 demangle_type_ptr (dm, insert_pos, substitution_start)
2127 demangling_t dm;
2128 int *insert_pos;
2129 int substitution_start;
2131 status_t status;
2132 int is_substitution_candidate = 1;
2134 DEMANGLE_TRACE ("type*", dm);
2136 /* Scan forward, collecting pointers and references into symbols,
2137 until we hit something else. Then emit the type. */
2138 switch (peek_char (dm))
2140 case 'P':
2141 /* A pointer. Snarf the `P'. */
2142 advance_char (dm);
2143 /* Demangle the underlying type. */
2144 RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
2145 substitution_start));
2146 /* Insert an asterisk where we're told to; it doesn't
2147 necessarily go at the end. If we're doing Java style output,
2148 there is no pointer symbol. */
2149 if (dm->style != DMGL_JAVA)
2150 RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
2151 /* The next (outermost) pointer or reference character should go
2152 after this one. */
2153 ++(*insert_pos);
2154 break;
2156 case 'R':
2157 /* A reference. Snarf the `R'. */
2158 advance_char (dm);
2159 /* Demangle the underlying type. */
2160 RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
2161 substitution_start));
2162 /* Insert an ampersand where we're told to; it doesn't
2163 necessarily go at the end. */
2164 RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
2165 /* The next (outermost) pointer or reference character should go
2166 after this one. */
2167 ++(*insert_pos);
2168 break;
2170 case 'M':
2172 /* A pointer-to-member. */
2173 dyn_string_t class_type;
2175 /* Eat the 'M'. */
2176 advance_char (dm);
2178 /* Capture the type of which this is a pointer-to-member. */
2179 RETURN_IF_ERROR (result_push (dm));
2180 RETURN_IF_ERROR (demangle_type (dm));
2181 class_type = (dyn_string_t) result_pop (dm);
2183 if (peek_char (dm) == 'F')
2184 /* A pointer-to-member function. We want output along the
2185 lines of `void (C::*) (int, int)'. Demangle the function
2186 type, which would in this case give `void () (int, int)'
2187 and set *insert_pos to the spot between the first
2188 parentheses. */
2189 status = demangle_type_ptr (dm, insert_pos, substitution_start);
2190 else if (peek_char (dm) == 'A')
2191 /* A pointer-to-member array variable. We want output that
2192 looks like `int (Klass::*) [10]'. Demangle the array type
2193 as `int () [10]', and set *insert_pos to the spot between
2194 the parentheses. */
2195 status = demangle_array_type (dm, insert_pos);
2196 else
2198 /* A pointer-to-member variable. Demangle the type of the
2199 pointed-to member. */
2200 status = demangle_type (dm);
2201 /* Make it pretty. */
2202 if (STATUS_NO_ERROR (status)
2203 && !result_previous_char_is_space (dm))
2204 status = result_add_char (dm, ' ');
2205 /* The pointer-to-member notation (e.g. `C::*') follows the
2206 member's type. */
2207 *insert_pos = result_caret_pos (dm);
2210 /* Build the pointer-to-member notation. */
2211 if (STATUS_NO_ERROR (status))
2212 status = result_insert (dm, *insert_pos, "::*");
2213 if (STATUS_NO_ERROR (status))
2214 status = result_insert_string (dm, *insert_pos, class_type);
2215 /* There may be additional levels of (pointer or reference)
2216 indirection in this type. If so, the `*' and `&' should be
2217 added after the pointer-to-member notation (e.g. `C::*&' for
2218 a reference to a pointer-to-member of class C). */
2219 *insert_pos += dyn_string_length (class_type) + 3;
2221 /* Clean up. */
2222 dyn_string_delete (class_type);
2224 RETURN_IF_ERROR (status);
2226 break;
2228 case 'F':
2229 /* Ooh, tricky, a pointer-to-function. When we demangle the
2230 function type, the return type should go at the very
2231 beginning. */
2232 *insert_pos = result_caret_pos (dm);
2233 /* The parentheses indicate this is a function pointer or
2234 reference type. */
2235 RETURN_IF_ERROR (result_add (dm, "()"));
2236 /* Now demangle the function type. The return type will be
2237 inserted before the `()', and the argument list will go after
2238 it. */
2239 RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
2240 /* We should now have something along the lines of
2241 `void () (int, int)'. The pointer or reference characters
2242 have to inside the first set of parentheses. *insert_pos has
2243 already been updated to point past the end of the return
2244 type. Move it one character over so it points inside the
2245 `()'. */
2246 ++(*insert_pos);
2247 break;
2249 case 'A':
2250 /* An array pointer or reference. demangle_array_type will figure
2251 out where the asterisks and ampersands go. */
2252 RETURN_IF_ERROR (demangle_array_type (dm, insert_pos));
2253 break;
2255 default:
2256 /* No more pointer or reference tokens; this is therefore a
2257 pointer to data. Finish up by demangling the underlying
2258 type. */
2259 RETURN_IF_ERROR (demangle_type (dm));
2260 /* The pointer or reference characters follow the underlying
2261 type, as in `int*&'. */
2262 *insert_pos = result_caret_pos (dm);
2263 /* Because of the production <type> ::= <substitution>,
2264 demangle_type will already have added the underlying type as
2265 a substitution candidate. Don't do it again. */
2266 is_substitution_candidate = 0;
2267 break;
2270 if (is_substitution_candidate)
2271 RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
2273 return STATUS_OK;
2276 /* Demangles and emits a <type>.
2278 <type> ::= <builtin-type>
2279 ::= <function-type>
2280 ::= <class-enum-type>
2281 ::= <array-type>
2282 ::= <pointer-to-member-type>
2283 ::= <template-param>
2284 ::= <template-template-param> <template-args>
2285 ::= <CV-qualifiers> <type>
2286 ::= P <type> # pointer-to
2287 ::= R <type> # reference-to
2288 ::= C <type> # complex pair (C 2000)
2289 ::= G <type> # imaginary (C 2000)
2290 ::= U <source-name> <type> # vendor extended type qualifier
2291 ::= <substitution> */
2293 static status_t
2294 demangle_type (dm)
2295 demangling_t dm;
2297 int start = substitution_start (dm);
2298 char peek = peek_char (dm);
2299 char peek_next;
2300 int encode_return_type = 0;
2301 template_arg_list_t old_arg_list = current_template_arg_list (dm);
2302 int insert_pos;
2304 /* A <type> can be a <substitution>; therefore, this <type> is a
2305 substitution candidate unless a special condition holds (see
2306 below). */
2307 int is_substitution_candidate = 1;
2309 DEMANGLE_TRACE ("type", dm);
2311 /* A <class-enum-type> can start with a digit (a <source-name>), an
2312 N (a <nested-name>), or a Z (a <local-name>). */
2313 if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
2314 RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type));
2315 /* Lower-case letters begin <builtin-type>s, except for `r', which
2316 denotes restrict. */
2317 else if (peek >= 'a' && peek <= 'z' && peek != 'r')
2319 RETURN_IF_ERROR (demangle_builtin_type (dm));
2320 /* Built-in types are not substitution candidates. */
2321 is_substitution_candidate = 0;
2323 else
2324 switch (peek)
2326 case 'r':
2327 case 'V':
2328 case 'K':
2329 /* CV-qualifiers (including restrict). We have to demangle
2330 them off to the side, since C++ syntax puts them in a funny
2331 place for qualified pointer and reference types. */
2333 status_t status;
2334 dyn_string_t cv_qualifiers = dyn_string_new (24);
2335 int old_caret_position = result_get_caret (dm);
2337 if (cv_qualifiers == NULL)
2338 return STATUS_ALLOCATION_FAILED;
2340 /* Decode all adjacent CV qualifiers. */
2341 demangle_CV_qualifiers (dm, cv_qualifiers);
2342 /* Emit them, and shift the caret left so that the
2343 underlying type will be emitted before the qualifiers. */
2344 status = result_add_string (dm, cv_qualifiers);
2345 result_shift_caret (dm, -dyn_string_length (cv_qualifiers));
2346 /* Clean up. */
2347 dyn_string_delete (cv_qualifiers);
2348 RETURN_IF_ERROR (status);
2349 /* Also prepend a blank, if needed. */
2350 RETURN_IF_ERROR (result_add_char (dm, ' '));
2351 result_shift_caret (dm, -1);
2353 /* Demangle the underlying type. It will be emitted before
2354 the CV qualifiers, since we moved the caret. */
2355 RETURN_IF_ERROR (demangle_type (dm));
2357 /* Put the caret back where it was previously. */
2358 result_set_caret (dm, old_caret_position);
2360 break;
2362 case 'F':
2363 return "Non-pointer or -reference function type.";
2365 case 'A':
2366 RETURN_IF_ERROR (demangle_array_type (dm, NULL));
2367 break;
2369 case 'T':
2370 /* It's either a <template-param> or a
2371 <template-template-param>. In either case, demangle the
2372 `T' token first. */
2373 RETURN_IF_ERROR (demangle_template_param (dm));
2375 /* Check for a template argument list; if one is found, it's a
2376 <template-template-param> ::= <template-param>
2377 ::= <substitution> */
2378 if (peek_char (dm) == 'I')
2380 /* Add a substitution candidate. The template parameter
2381 `T' token is a substitution candidate by itself,
2382 without the template argument list. */
2383 RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
2385 /* Now demangle the template argument list. */
2386 RETURN_IF_ERROR (demangle_template_args (dm));
2387 /* The entire type, including the template template
2388 parameter and its argument list, will be added as a
2389 substitution candidate below. */
2392 break;
2394 case 'S':
2395 /* First check if this is a special substitution. If it is,
2396 this is a <class-enum-type>. Special substitutions have a
2397 letter following the `S'; other substitutions have a digit
2398 or underscore. */
2399 peek_next = peek_char_next (dm);
2400 if (IS_DIGIT (peek_next) || peek_next == '_')
2402 RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));
2404 /* The substituted name may have been a template name.
2405 Check if template arguments follow, and if so, demangle
2406 them. */
2407 if (peek_char (dm) == 'I')
2408 RETURN_IF_ERROR (demangle_template_args (dm));
2409 else
2410 /* A substitution token is not itself a substitution
2411 candidate. (However, if the substituted template is
2412 instantiated, the resulting type is.) */
2413 is_substitution_candidate = 0;
2415 else
2417 /* Now some trickiness. We have a special substitution
2418 here. Often, the special substitution provides the
2419 name of a template that's subsequently instantiated,
2420 for instance `SaIcE' => std::allocator<char>. In these
2421 cases we need to add a substitution candidate for the
2422 entire <class-enum-type> and thus don't want to clear
2423 the is_substitution_candidate flag.
2425 However, it's possible that what we have here is a
2426 substitution token representing an entire type, such as
2427 `Ss' => std::string. In this case, we mustn't add a
2428 new substitution candidate for this substitution token.
2429 To detect this case, remember where the start of the
2430 substitution token is. */
2431 const char *next = dm->next;
2432 /* Now demangle the <class-enum-type>. */
2433 RETURN_IF_ERROR
2434 (demangle_class_enum_type (dm, &encode_return_type));
2435 /* If all that was just demangled is the two-character
2436 special substitution token, supress the addition of a
2437 new candidate for it. */
2438 if (dm->next == next + 2)
2439 is_substitution_candidate = 0;
2442 break;
2444 case 'P':
2445 case 'R':
2446 case 'M':
2447 RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
2448 /* demangle_type_ptr adds all applicable substitution
2449 candidates. */
2450 is_substitution_candidate = 0;
2451 break;
2453 case 'C':
2454 /* A C99 complex type. */
2455 RETURN_IF_ERROR (result_add (dm, "complex "));
2456 advance_char (dm);
2457 RETURN_IF_ERROR (demangle_type (dm));
2458 break;
2460 case 'G':
2461 /* A C99 imaginary type. */
2462 RETURN_IF_ERROR (result_add (dm, "imaginary "));
2463 advance_char (dm);
2464 RETURN_IF_ERROR (demangle_type (dm));
2465 break;
2467 case 'U':
2468 /* Vendor-extended type qualifier. */
2469 advance_char (dm);
2470 RETURN_IF_ERROR (demangle_source_name (dm));
2471 RETURN_IF_ERROR (result_add_char (dm, ' '));
2472 RETURN_IF_ERROR (demangle_type (dm));
2473 break;
2475 default:
2476 return "Unexpected character in <type>.";
2479 if (is_substitution_candidate)
2480 /* Add a new substitution for the type. If this type was a
2481 <template-param>, pass its index since from the point of
2482 substitutions; a <template-param> token is a substitution
2483 candidate distinct from the type that is substituted for it. */
2484 RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
2486 /* Pop off template argument lists added during mangling of this
2487 type. */
2488 pop_to_template_arg_list (dm, old_arg_list);
2490 return STATUS_OK;
2493 /* C++ source names of builtin types, indexed by the mangled code
2494 letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc). */
2495 static const char *const builtin_type_names[26] =
2497 "signed char", /* a */
2498 "bool", /* b */
2499 "char", /* c */
2500 "double", /* d */
2501 "long double", /* e */
2502 "float", /* f */
2503 "__float128", /* g */
2504 "unsigned char", /* h */
2505 "int", /* i */
2506 "unsigned", /* j */
2507 NULL, /* k */
2508 "long", /* l */
2509 "unsigned long", /* m */
2510 "__int128", /* n */
2511 "unsigned __int128", /* o */
2512 NULL, /* p */
2513 NULL, /* q */
2514 NULL, /* r */
2515 "short", /* s */
2516 "unsigned short", /* t */
2517 NULL, /* u */
2518 "void", /* v */
2519 "wchar_t", /* w */
2520 "long long", /* x */
2521 "unsigned long long", /* y */
2522 "..." /* z */
2525 /* Java source names of builtin types. Types that arn't valid in Java
2526 are also included here - we don't fail if someone attempts to demangle a
2527 C++ symbol in Java style. */
2528 static const char *const java_builtin_type_names[26] =
2530 "signed char", /* a */
2531 "boolean", /* C++ "bool" */ /* b */
2532 "byte", /* C++ "char" */ /* c */
2533 "double", /* d */
2534 "long double", /* e */
2535 "float", /* f */
2536 "__float128", /* g */
2537 "unsigned char", /* h */
2538 "int", /* i */
2539 "unsigned", /* j */
2540 NULL, /* k */
2541 "long", /* l */
2542 "unsigned long", /* m */
2543 "__int128", /* n */
2544 "unsigned __int128", /* o */
2545 NULL, /* p */
2546 NULL, /* q */
2547 NULL, /* r */
2548 "short", /* s */
2549 "unsigned short", /* t */
2550 NULL, /* u */
2551 "void", /* v */
2552 "char", /* C++ "wchar_t" */ /* w */
2553 "long", /* C++ "long long" */ /* x */
2554 "unsigned long long", /* y */
2555 "..." /* z */
2558 /* Demangles and emits a <builtin-type>.
2560 <builtin-type> ::= v # void
2561 ::= w # wchar_t
2562 ::= b # bool
2563 ::= c # char
2564 ::= a # signed char
2565 ::= h # unsigned char
2566 ::= s # short
2567 ::= t # unsigned short
2568 ::= i # int
2569 ::= j # unsigned int
2570 ::= l # long
2571 ::= m # unsigned long
2572 ::= x # long long, __int64
2573 ::= y # unsigned long long, __int64
2574 ::= n # __int128
2575 ::= o # unsigned __int128
2576 ::= f # float
2577 ::= d # double
2578 ::= e # long double, __float80
2579 ::= g # __float128
2580 ::= z # ellipsis
2581 ::= u <source-name> # vendor extended type */
2583 static status_t
2584 demangle_builtin_type (dm)
2585 demangling_t dm;
2588 char code = peek_char (dm);
2590 DEMANGLE_TRACE ("builtin-type", dm);
2592 if (code == 'u')
2594 advance_char (dm);
2595 RETURN_IF_ERROR (demangle_source_name (dm));
2596 return STATUS_OK;
2598 else if (code >= 'a' && code <= 'z')
2600 const char *type_name;
2601 /* Java uses different names for some built-in types. */
2602 if (dm->style == DMGL_JAVA)
2603 type_name = java_builtin_type_names[code - 'a'];
2604 else
2605 type_name = builtin_type_names[code - 'a'];
2606 if (type_name == NULL)
2607 return "Unrecognized <builtin-type> code.";
2609 RETURN_IF_ERROR (result_add (dm, type_name));
2610 advance_char (dm);
2611 return STATUS_OK;
2613 else
2614 return "Non-alphabetic <builtin-type> code.";
2617 /* Demangles all consecutive CV-qualifiers (const, volatile, and
2618 restrict) at the current position. The qualifiers are appended to
2619 QUALIFIERS. Returns STATUS_OK. */
2621 static status_t
2622 demangle_CV_qualifiers (dm, qualifiers)
2623 demangling_t dm;
2624 dyn_string_t qualifiers;
2626 DEMANGLE_TRACE ("CV-qualifiers", dm);
2628 while (1)
2630 switch (peek_char (dm))
2632 case 'r':
2633 if (!dyn_string_append_space (qualifiers))
2634 return STATUS_ALLOCATION_FAILED;
2635 if (!dyn_string_append_cstr (qualifiers, "restrict"))
2636 return STATUS_ALLOCATION_FAILED;
2637 break;
2639 case 'V':
2640 if (!dyn_string_append_space (qualifiers))
2641 return STATUS_ALLOCATION_FAILED;
2642 if (!dyn_string_append_cstr (qualifiers, "volatile"))
2643 return STATUS_ALLOCATION_FAILED;
2644 break;
2646 case 'K':
2647 if (!dyn_string_append_space (qualifiers))
2648 return STATUS_ALLOCATION_FAILED;
2649 if (!dyn_string_append_cstr (qualifiers, "const"))
2650 return STATUS_ALLOCATION_FAILED;
2651 break;
2653 default:
2654 return STATUS_OK;
2657 advance_char (dm);
2661 /* Demangles and emits a <function-type>. *FUNCTION_NAME_POS is the
2662 position in the result string of the start of the function
2663 identifier, at which the function's return type will be inserted;
2664 *FUNCTION_NAME_POS is updated to position past the end of the
2665 function's return type.
2667 <function-type> ::= F [Y] <bare-function-type> E */
2669 static status_t
2670 demangle_function_type (dm, function_name_pos)
2671 demangling_t dm;
2672 int *function_name_pos;
2674 DEMANGLE_TRACE ("function-type", dm);
2675 RETURN_IF_ERROR (demangle_char (dm, 'F'));
2676 if (peek_char (dm) == 'Y')
2678 /* Indicate this function has C linkage if in verbose mode. */
2679 if (flag_verbose)
2680 RETURN_IF_ERROR (result_add (dm, " [extern \"C\"] "));
2681 advance_char (dm);
2683 RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
2684 RETURN_IF_ERROR (demangle_char (dm, 'E'));
2685 return STATUS_OK;
2688 /* Demangles and emits a <bare-function-type>. RETURN_TYPE_POS is the
2689 position in the result string at which the function return type
2690 should be inserted. If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the
2691 function's return type is assumed not to be encoded.
2693 <bare-function-type> ::= <signature type>+ */
2695 static status_t
2696 demangle_bare_function_type (dm, return_type_pos)
2697 demangling_t dm;
2698 int *return_type_pos;
2700 /* Sequence is the index of the current function parameter, counting
2701 from zero. The value -1 denotes the return type. */
2702 int sequence =
2703 (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);
2705 DEMANGLE_TRACE ("bare-function-type", dm);
2707 RETURN_IF_ERROR (result_add_char (dm, '('));
2708 while (!end_of_name_p (dm) && peek_char (dm) != 'E')
2710 if (sequence == -1)
2711 /* We're decoding the function's return type. */
2713 dyn_string_t return_type;
2714 status_t status = STATUS_OK;
2716 /* Decode the return type off to the side. */
2717 RETURN_IF_ERROR (result_push (dm));
2718 RETURN_IF_ERROR (demangle_type (dm));
2719 return_type = (dyn_string_t) result_pop (dm);
2721 /* Add a space to the end of the type. Insert the return
2722 type where we've been asked to. */
2723 if (!dyn_string_append_space (return_type))
2724 status = STATUS_ALLOCATION_FAILED;
2725 if (STATUS_NO_ERROR (status))
2727 if (!dyn_string_insert (result_string (dm), *return_type_pos,
2728 return_type))
2729 status = STATUS_ALLOCATION_FAILED;
2730 else
2731 *return_type_pos += dyn_string_length (return_type);
2734 dyn_string_delete (return_type);
2735 RETURN_IF_ERROR (status);
2737 else
2739 /* Skip `void' parameter types. One should only occur as
2740 the only type in a parameter list; in that case, we want
2741 to print `foo ()' instead of `foo (void)'. */
2742 if (peek_char (dm) == 'v')
2743 /* Consume the v. */
2744 advance_char (dm);
2745 else
2747 /* Separate parameter types by commas. */
2748 if (sequence > 0)
2749 RETURN_IF_ERROR (result_add (dm, ", "));
2750 /* Demangle the type. */
2751 RETURN_IF_ERROR (demangle_type (dm));
2755 ++sequence;
2757 RETURN_IF_ERROR (result_add_char (dm, ')'));
2759 /* We should have demangled at least one parameter type (which would
2760 be void, for a function that takes no parameters), plus the
2761 return type, if we were supposed to demangle that. */
2762 if (sequence == -1)
2763 return "Missing function return type.";
2764 else if (sequence == 0)
2765 return "Missing function parameter.";
2767 return STATUS_OK;
2770 /* Demangles and emits a <class-enum-type>. *ENCODE_RETURN_TYPE is set to
2771 non-zero if the type is a template-id, zero otherwise.
2773 <class-enum-type> ::= <name> */
2775 static status_t
2776 demangle_class_enum_type (dm, encode_return_type)
2777 demangling_t dm;
2778 int *encode_return_type;
2780 DEMANGLE_TRACE ("class-enum-type", dm);
2782 RETURN_IF_ERROR (demangle_name (dm, encode_return_type));
2783 return STATUS_OK;
2786 /* Demangles and emits an <array-type>.
2788 If PTR_INSERT_POS is not NULL, the array type is formatted as a
2789 pointer or reference to an array, except that asterisk and
2790 ampersand punctuation is omitted (since it's not know at this
2791 point). *PTR_INSERT_POS is set to the position in the demangled
2792 name at which this punctuation should be inserted. For example,
2793 `A10_i' is demangled to `int () [10]' and *PTR_INSERT_POS points
2794 between the parentheses.
2796 If PTR_INSERT_POS is NULL, the array type is assumed not to be
2797 pointer- or reference-qualified. Then, for example, `A10_i' is
2798 demangled simply as `int[10]'.
2800 <array-type> ::= A [<dimension number>] _ <element type>
2801 ::= A <dimension expression> _ <element type> */
2803 static status_t
2804 demangle_array_type (dm, ptr_insert_pos)
2805 demangling_t dm;
2806 int *ptr_insert_pos;
2808 status_t status = STATUS_OK;
2809 dyn_string_t array_size = NULL;
2810 char peek;
2812 DEMANGLE_TRACE ("array-type", dm);
2814 RETURN_IF_ERROR (demangle_char (dm, 'A'));
2816 /* Demangle the array size into array_size. */
2817 peek = peek_char (dm);
2818 if (peek == '_')
2819 /* Array bound is omitted. This is a C99-style VLA. */
2821 else if (IS_DIGIT (peek_char (dm)))
2823 /* It looks like a constant array bound. */
2824 array_size = dyn_string_new (10);
2825 if (array_size == NULL)
2826 return STATUS_ALLOCATION_FAILED;
2827 status = demangle_number_literally (dm, array_size, 10, 0);
2829 else
2831 /* Anything is must be an expression for a nont-constant array
2832 bound. This happens if the array type occurs in a template
2833 and the array bound references a template parameter. */
2834 RETURN_IF_ERROR (result_push (dm));
2835 RETURN_IF_ERROR (demangle_expression (dm));
2836 array_size = (dyn_string_t) result_pop (dm);
2838 /* array_size may have been allocated by now, so we can't use
2839 RETURN_IF_ERROR until it's been deallocated. */
2841 /* Demangle the base type of the array. */
2842 if (STATUS_NO_ERROR (status))
2843 status = demangle_char (dm, '_');
2844 if (STATUS_NO_ERROR (status))
2845 status = demangle_type (dm);
2847 if (ptr_insert_pos != NULL)
2849 /* This array is actually part of an pointer- or
2850 reference-to-array type. Format appropriately, except we
2851 don't know which and how much punctuation to use. */
2852 if (STATUS_NO_ERROR (status))
2853 status = result_add (dm, " () ");
2854 /* Let the caller know where to insert the punctuation. */
2855 *ptr_insert_pos = result_caret_pos (dm) - 2;
2858 /* Emit the array dimension syntax. */
2859 if (STATUS_NO_ERROR (status))
2860 status = result_add_char (dm, '[');
2861 if (STATUS_NO_ERROR (status) && array_size != NULL)
2862 status = result_add_string (dm, array_size);
2863 if (STATUS_NO_ERROR (status))
2864 status = result_add_char (dm, ']');
2865 if (array_size != NULL)
2866 dyn_string_delete (array_size);
2868 RETURN_IF_ERROR (status);
2870 return STATUS_OK;
2873 /* Demangles and emits a <template-param>.
2875 <template-param> ::= T_ # first template parameter
2876 ::= T <parameter-2 number> _ */
2878 static status_t
2879 demangle_template_param (dm)
2880 demangling_t dm;
2882 int parm_number;
2883 template_arg_list_t current_arg_list = current_template_arg_list (dm);
2884 string_list_t arg;
2886 DEMANGLE_TRACE ("template-param", dm);
2888 /* Make sure there is a template argmust list in which to look up
2889 this parameter reference. */
2890 if (current_arg_list == NULL)
2891 return "Template parameter outside of template.";
2893 RETURN_IF_ERROR (demangle_char (dm, 'T'));
2894 if (peek_char (dm) == '_')
2895 parm_number = 0;
2896 else
2898 RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));
2899 ++parm_number;
2901 RETURN_IF_ERROR (demangle_char (dm, '_'));
2903 arg = template_arg_list_get_arg (current_arg_list, parm_number);
2904 if (arg == NULL)
2905 /* parm_number exceeded the number of arguments in the current
2906 template argument list. */
2907 return "Template parameter number out of bounds.";
2908 RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
2910 return STATUS_OK;
2913 /* Demangles and emits a <template-args>.
2915 <template-args> ::= I <template-arg>+ E */
2917 static status_t
2918 demangle_template_args (dm)
2919 demangling_t dm;
2921 int first = 1;
2922 dyn_string_t old_last_source_name;
2923 template_arg_list_t arg_list = template_arg_list_new ();
2925 if (arg_list == NULL)
2926 return STATUS_ALLOCATION_FAILED;
2928 /* Preserve the most recently demangled source name. */
2929 old_last_source_name = dm->last_source_name;
2930 dm->last_source_name = dyn_string_new (0);
2932 DEMANGLE_TRACE ("template-args", dm);
2934 if (dm->last_source_name == NULL)
2935 return STATUS_ALLOCATION_FAILED;
2937 RETURN_IF_ERROR (demangle_char (dm, 'I'));
2938 RETURN_IF_ERROR (result_open_template_list (dm));
2941 string_list_t arg;
2943 if (first)
2944 first = 0;
2945 else
2946 RETURN_IF_ERROR (result_add (dm, ", "));
2948 /* Capture the template arg. */
2949 RETURN_IF_ERROR (result_push (dm));
2950 RETURN_IF_ERROR (demangle_template_arg (dm));
2951 arg = result_pop (dm);
2953 /* Emit it in the demangled name. */
2954 RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
2956 /* Save it for use in expanding <template-param>s. */
2957 template_arg_list_add_arg (arg_list, arg);
2959 while (peek_char (dm) != 'E');
2960 /* Append the '>'. */
2961 RETURN_IF_ERROR (result_close_template_list (dm));
2963 /* Consume the 'E'. */
2964 advance_char (dm);
2966 /* Restore the most recent demangled source name. */
2967 dyn_string_delete (dm->last_source_name);
2968 dm->last_source_name = old_last_source_name;
2970 /* Push the list onto the top of the stack of template argument
2971 lists, so that arguments from it are used from now on when
2972 expanding <template-param>s. */
2973 push_template_arg_list (dm, arg_list);
2975 return STATUS_OK;
2978 /* This function, which does not correspond to a production in the
2979 mangling spec, handles the `literal' production for both
2980 <template-arg> and <expr-primary>. It does not expect or consume
2981 the initial `L' or final `E'. The demangling is given by:
2983 <literal> ::= <type> </value/ number>
2985 and the emitted output is `(type)number'. */
2987 static status_t
2988 demangle_literal (dm)
2989 demangling_t dm;
2991 char peek = peek_char (dm);
2992 dyn_string_t value_string;
2993 status_t status;
2995 DEMANGLE_TRACE ("literal", dm);
2997 if (!flag_verbose && peek >= 'a' && peek <= 'z')
2999 /* If not in verbose mode and this is a builtin type, see if we
3000 can produce simpler numerical output. In particular, for
3001 integer types shorter than `long', just write the number
3002 without type information; for bools, write `true' or `false'.
3003 Other refinements could be made here too. */
3005 /* This constant string is used to map from <builtin-type> codes
3006 (26 letters of the alphabet) to codes that determine how the
3007 value will be displayed. The codes are:
3008 b: display as bool
3009 i: display as int
3010 l: display as long
3011 A space means the value will be represented using cast
3012 notation. */
3013 static const char *const code_map = "ibi iii ll ii i ";
3015 char code = code_map[peek - 'a'];
3016 /* FIXME: Implement demangling of floats and doubles. */
3017 if (code == 'u')
3018 return STATUS_UNIMPLEMENTED;
3019 if (code == 'b')
3021 /* It's a boolean. */
3022 char value;
3024 /* Consume the b. */
3025 advance_char (dm);
3026 /* Look at the next character. It should be 0 or 1,
3027 corresponding to false or true, respectively. */
3028 value = peek_char (dm);
3029 if (value == '0')
3030 RETURN_IF_ERROR (result_add (dm, "false"));
3031 else if (value == '1')
3032 RETURN_IF_ERROR (result_add (dm, "true"));
3033 else
3034 return "Unrecognized bool constant.";
3035 /* Consume the 0 or 1. */
3036 advance_char (dm);
3037 return STATUS_OK;
3039 else if (code == 'i' || code == 'l')
3041 /* It's an integer or long. */
3043 /* Consume the type character. */
3044 advance_char (dm);
3046 /* Demangle the number and write it out. */
3047 value_string = dyn_string_new (0);
3048 status = demangle_number_literally (dm, value_string, 10, 1);
3049 if (STATUS_NO_ERROR (status))
3050 status = result_add_string (dm, value_string);
3051 /* For long integers, append an l. */
3052 if (code == 'l' && STATUS_NO_ERROR (status))
3053 status = result_add_char (dm, code);
3054 dyn_string_delete (value_string);
3056 RETURN_IF_ERROR (status);
3057 return STATUS_OK;
3059 /* ...else code == ' ', so fall through to represent this
3060 literal's type explicitly using cast syntax. */
3063 RETURN_IF_ERROR (result_add_char (dm, '('));
3064 RETURN_IF_ERROR (demangle_type (dm));
3065 RETURN_IF_ERROR (result_add_char (dm, ')'));
3067 value_string = dyn_string_new (0);
3068 if (value_string == NULL)
3069 return STATUS_ALLOCATION_FAILED;
3071 status = demangle_number_literally (dm, value_string, 10, 1);
3072 if (STATUS_NO_ERROR (status))
3073 status = result_add_string (dm, value_string);
3074 dyn_string_delete (value_string);
3075 RETURN_IF_ERROR (status);
3077 return STATUS_OK;
3080 /* Demangles and emits a <template-arg>.
3082 <template-arg> ::= <type> # type
3083 ::= L <type> <value number> E # literal
3084 ::= LZ <encoding> E # external name
3085 ::= X <expression> E # expression */
3087 static status_t
3088 demangle_template_arg (dm)
3089 demangling_t dm;
3091 DEMANGLE_TRACE ("template-arg", dm);
3093 switch (peek_char (dm))
3095 case 'L':
3096 advance_char (dm);
3098 if (peek_char (dm) == 'Z')
3100 /* External name. */
3101 advance_char (dm);
3102 /* FIXME: Standard is contradictory here. */
3103 RETURN_IF_ERROR (demangle_encoding (dm));
3105 else
3106 RETURN_IF_ERROR (demangle_literal (dm));
3107 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3108 break;
3110 case 'X':
3111 /* Expression. */
3112 advance_char (dm);
3113 RETURN_IF_ERROR (demangle_expression (dm));
3114 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3115 break;
3117 default:
3118 RETURN_IF_ERROR (demangle_type (dm));
3119 break;
3122 return STATUS_OK;
3125 /* Demangles and emits an <expression>.
3127 <expression> ::= <unary operator-name> <expression>
3128 ::= <binary operator-name> <expression> <expression>
3129 ::= <expr-primary>
3130 ::= <scope-expression> */
3132 static status_t
3133 demangle_expression (dm)
3134 demangling_t dm;
3136 char peek = peek_char (dm);
3138 DEMANGLE_TRACE ("expression", dm);
3140 if (peek == 'L' || peek == 'T')
3141 RETURN_IF_ERROR (demangle_expr_primary (dm));
3142 else if (peek == 's' && peek_char_next (dm) == 'r')
3143 RETURN_IF_ERROR (demangle_scope_expression (dm));
3144 else
3145 /* An operator expression. */
3147 int num_args;
3148 status_t status = STATUS_OK;
3149 dyn_string_t operator_name;
3151 /* We have an operator name. Since we want to output binary
3152 operations in infix notation, capture the operator name
3153 first. */
3154 RETURN_IF_ERROR (result_push (dm));
3155 RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args));
3156 operator_name = (dyn_string_t) result_pop (dm);
3158 /* If it's binary, do an operand first. */
3159 if (num_args > 1)
3161 status = result_add_char (dm, '(');
3162 if (STATUS_NO_ERROR (status))
3163 status = demangle_expression (dm);
3164 if (STATUS_NO_ERROR (status))
3165 status = result_add_char (dm, ')');
3168 /* Emit the operator. */
3169 if (STATUS_NO_ERROR (status))
3170 status = result_add_string (dm, operator_name);
3171 dyn_string_delete (operator_name);
3172 RETURN_IF_ERROR (status);
3174 /* Emit its second (if binary) or only (if unary) operand. */
3175 RETURN_IF_ERROR (result_add_char (dm, '('));
3176 RETURN_IF_ERROR (demangle_expression (dm));
3177 RETURN_IF_ERROR (result_add_char (dm, ')'));
3179 /* The ternary operator takes a third operand. */
3180 if (num_args == 3)
3182 RETURN_IF_ERROR (result_add (dm, ":("));
3183 RETURN_IF_ERROR (demangle_expression (dm));
3184 RETURN_IF_ERROR (result_add_char (dm, ')'));
3188 return STATUS_OK;
3191 /* Demangles and emits a <scope-expression>.
3193 <scope-expression> ::= sr <qualifying type> <source-name>
3194 ::= sr <qualifying type> <encoding> */
3196 static status_t
3197 demangle_scope_expression (dm)
3198 demangling_t dm;
3200 RETURN_IF_ERROR (demangle_char (dm, 's'));
3201 RETURN_IF_ERROR (demangle_char (dm, 'r'));
3202 RETURN_IF_ERROR (demangle_type (dm));
3203 RETURN_IF_ERROR (result_add (dm, "::"));
3204 RETURN_IF_ERROR (demangle_encoding (dm));
3205 return STATUS_OK;
3208 /* Demangles and emits an <expr-primary>.
3210 <expr-primary> ::= <template-param>
3211 ::= L <type> <value number> E # literal
3212 ::= L <mangled-name> E # external name */
3214 static status_t
3215 demangle_expr_primary (dm)
3216 demangling_t dm;
3218 char peek = peek_char (dm);
3220 DEMANGLE_TRACE ("expr-primary", dm);
3222 if (peek == 'T')
3223 RETURN_IF_ERROR (demangle_template_param (dm));
3224 else if (peek == 'L')
3226 /* Consume the `L'. */
3227 advance_char (dm);
3228 peek = peek_char (dm);
3230 if (peek == '_')
3231 RETURN_IF_ERROR (demangle_mangled_name (dm));
3232 else
3233 RETURN_IF_ERROR (demangle_literal (dm));
3235 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3237 else
3238 return STATUS_ERROR;
3240 return STATUS_OK;
3243 /* Demangles and emits a <substitution>. Sets *TEMPLATE_P to non-zero
3244 if the substitution is the name of a template, zero otherwise.
3246 <substitution> ::= S <seq-id> _
3247 ::= S_
3249 ::= St # ::std::
3250 ::= Sa # ::std::allocator
3251 ::= Sb # ::std::basic_string
3252 ::= Ss # ::std::basic_string<char,
3253 ::std::char_traits<char>,
3254 ::std::allocator<char> >
3255 ::= Si # ::std::basic_istream<char,
3256 std::char_traits<char> >
3257 ::= So # ::std::basic_ostream<char,
3258 std::char_traits<char> >
3259 ::= Sd # ::std::basic_iostream<char,
3260 std::char_traits<char> >
3263 static status_t
3264 demangle_substitution (dm, template_p)
3265 demangling_t dm;
3266 int *template_p;
3268 int seq_id;
3269 int peek;
3270 dyn_string_t text;
3272 DEMANGLE_TRACE ("substitution", dm);
3274 RETURN_IF_ERROR (demangle_char (dm, 'S'));
3276 /* Scan the substitution sequence index. A missing number denotes
3277 the first index. */
3278 peek = peek_char (dm);
3279 if (peek == '_')
3280 seq_id = -1;
3281 /* If the following character is 0-9 or a capital letter, interpret
3282 the sequence up to the next underscore as a base-36 substitution
3283 index. */
3284 else if (IS_DIGIT ((unsigned char) peek)
3285 || (peek >= 'A' && peek <= 'Z'))
3286 RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));
3287 else
3289 const char *new_last_source_name = NULL;
3291 switch (peek)
3293 case 't':
3294 RETURN_IF_ERROR (result_add (dm, "std"));
3295 break;
3297 case 'a':
3298 RETURN_IF_ERROR (result_add (dm, "std::allocator"));
3299 new_last_source_name = "allocator";
3300 *template_p = 1;
3301 break;
3303 case 'b':
3304 RETURN_IF_ERROR (result_add (dm, "std::basic_string"));
3305 new_last_source_name = "basic_string";
3306 *template_p = 1;
3307 break;
3309 case 's':
3310 if (!flag_verbose)
3312 RETURN_IF_ERROR (result_add (dm, "std::string"));
3313 new_last_source_name = "string";
3315 else
3317 RETURN_IF_ERROR (result_add (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
3318 new_last_source_name = "basic_string";
3320 *template_p = 0;
3321 break;
3323 case 'i':
3324 if (!flag_verbose)
3326 RETURN_IF_ERROR (result_add (dm, "std::istream"));
3327 new_last_source_name = "istream";
3329 else
3331 RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traints<char> >"));
3332 new_last_source_name = "basic_istream";
3334 *template_p = 0;
3335 break;
3337 case 'o':
3338 if (!flag_verbose)
3340 RETURN_IF_ERROR (result_add (dm, "std::ostream"));
3341 new_last_source_name = "ostream";
3343 else
3345 RETURN_IF_ERROR (result_add (dm, "std::basic_ostream<char, std::char_traits<char> >"));
3346 new_last_source_name = "basic_ostream";
3348 *template_p = 0;
3349 break;
3351 case 'd':
3352 if (!flag_verbose)
3354 RETURN_IF_ERROR (result_add (dm, "std::iostream"));
3355 new_last_source_name = "iostream";
3357 else
3359 RETURN_IF_ERROR (result_add (dm, "std::basic_iostream<char, std::char_traits<char> >"));
3360 new_last_source_name = "basic_iostream";
3362 *template_p = 0;
3363 break;
3365 default:
3366 return "Unrecognized <substitution>.";
3369 /* Consume the character we just processed. */
3370 advance_char (dm);
3372 if (new_last_source_name != NULL)
3374 if (!dyn_string_copy_cstr (dm->last_source_name,
3375 new_last_source_name))
3376 return STATUS_ALLOCATION_FAILED;
3379 return STATUS_OK;
3382 /* Look up the substitution text. Since `S_' is the most recent
3383 substitution, `S0_' is the second-most-recent, etc., shift the
3384 numbering by one. */
3385 text = substitution_get (dm, seq_id + 1, template_p);
3386 if (text == NULL)
3387 return "Substitution number out of range.";
3389 /* Emit the substitution text. */
3390 RETURN_IF_ERROR (result_add_string (dm, text));
3392 RETURN_IF_ERROR (demangle_char (dm, '_'));
3393 return STATUS_OK;
3396 /* Demangles and emits a <local-name>.
3398 <local-name> := Z <function encoding> E <entity name> [<discriminator>]
3399 := Z <function encoding> E s [<discriminator>] */
3401 static status_t
3402 demangle_local_name (dm)
3403 demangling_t dm;
3405 DEMANGLE_TRACE ("local-name", dm);
3407 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
3408 RETURN_IF_ERROR (demangle_encoding (dm));
3409 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3410 RETURN_IF_ERROR (result_add (dm, "::"));
3412 if (peek_char (dm) == 's')
3414 /* Local character string literal. */
3415 RETURN_IF_ERROR (result_add (dm, "string literal"));
3416 /* Consume the s. */
3417 advance_char (dm);
3418 RETURN_IF_ERROR (demangle_discriminator (dm, 0));
3420 else
3422 int unused;
3423 /* Local name for some other entity. Demangle its name. */
3424 RETURN_IF_ERROR (demangle_name (dm, &unused));
3425 RETURN_IF_ERROR (demangle_discriminator (dm, 1));
3428 return STATUS_OK;
3431 /* Optimonally demangles and emits a <discriminator>. If there is no
3432 <discriminator> at the current position in the mangled string, the
3433 descriminator is assumed to be zero. Emit the discriminator number
3434 in parentheses, unless SUPPRESS_FIRST is non-zero and the
3435 discriminator is zero.
3437 <discriminator> ::= _ <number> */
3439 static status_t
3440 demangle_discriminator (dm, suppress_first)
3441 demangling_t dm;
3442 int suppress_first;
3444 /* Output for <discriminator>s to the demangled name is completely
3445 suppressed if not in verbose mode. */
3447 if (peek_char (dm) == '_')
3449 /* Consume the underscore. */
3450 advance_char (dm);
3451 if (flag_verbose)
3452 RETURN_IF_ERROR (result_add (dm, " [#"));
3453 /* Check if there's a number following the underscore. */
3454 if (IS_DIGIT ((unsigned char) peek_char (dm)))
3456 int discriminator;
3457 /* Demangle the number. */
3458 RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));
3459 if (flag_verbose)
3460 /* Write the discriminator. The mangled number is two
3461 less than the discriminator ordinal, counting from
3462 zero. */
3463 RETURN_IF_ERROR (int_to_dyn_string (discriminator + 1,
3464 (dyn_string_t) dm->result));
3466 else
3467 return STATUS_ERROR;
3468 if (flag_verbose)
3469 RETURN_IF_ERROR (result_add_char (dm, ']'));
3471 else if (!suppress_first)
3473 if (flag_verbose)
3474 RETURN_IF_ERROR (result_add (dm, " [#0]"));
3477 return STATUS_OK;
3480 /* Demangle NAME into RESULT, which must be an initialized
3481 dyn_string_t. On success, returns STATUS_OK. On failure, returns
3482 an error message, and the contents of RESULT are unchanged. */
3484 static status_t
3485 cp_demangle (name, result, style)
3486 const char *name;
3487 dyn_string_t result;
3488 int style;
3490 status_t status;
3491 int length = strlen (name);
3493 if (length > 2 && name[0] == '_' && name[1] == 'Z')
3495 demangling_t dm = demangling_new (name, style);
3496 if (dm == NULL)
3497 return STATUS_ALLOCATION_FAILED;
3499 status = result_push (dm);
3500 if (status != STATUS_OK)
3502 demangling_delete (dm);
3503 return status;
3506 status = demangle_mangled_name (dm);
3507 if (STATUS_NO_ERROR (status))
3509 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3510 if (!dyn_string_copy (result, demangled))
3511 return STATUS_ALLOCATION_FAILED;
3512 dyn_string_delete (demangled);
3515 demangling_delete (dm);
3517 else
3519 /* It's evidently not a mangled C++ name. It could be the name
3520 of something with C linkage, though, so just copy NAME into
3521 RESULT. */
3522 if (!dyn_string_copy_cstr (result, name))
3523 return STATUS_ALLOCATION_FAILED;
3524 status = STATUS_OK;
3527 return status;
3530 /* Demangle TYPE_NAME into RESULT, which must be an initialized
3531 dyn_string_t. On success, returns STATUS_OK. On failiure, returns
3532 an error message, and the contents of RESULT are unchanged. */
3534 static status_t
3535 cp_demangle_type (type_name, result)
3536 const char* type_name;
3537 dyn_string_t result;
3539 status_t status;
3540 demangling_t dm = demangling_new (type_name, DMGL_GNU_V3);
3542 if (dm == NULL)
3543 return STATUS_ALLOCATION_FAILED;
3545 /* Demangle the type name. The demangled name is stored in dm. */
3546 status = result_push (dm);
3547 if (status != STATUS_OK)
3549 demangling_delete (dm);
3550 return status;
3553 status = demangle_type (dm);
3555 if (STATUS_NO_ERROR (status))
3557 /* The demangling succeeded. Pop the result out of dm and copy
3558 it into RESULT. */
3559 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3560 if (!dyn_string_copy (result, demangled))
3561 return STATUS_ALLOCATION_FAILED;
3562 dyn_string_delete (demangled);
3565 /* Clean up. */
3566 demangling_delete (dm);
3568 return status;
3571 #ifdef IN_LIBGCC2
3572 extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
3574 /* ia64 ABI-mandated entry point in the C++ runtime library for performing
3575 demangling. MANGLED_NAME is a NUL-terminated character string
3576 containing the name to be demangled.
3578 OUTPUT_BUFFER is a region of memory, allocated with malloc, of
3579 *LENGTH bytes, into which the demangled name is stored. If
3580 OUTPUT_BUFFER is not long enough, it is expanded using realloc.
3581 OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
3582 is placed in a region of memory allocated with malloc.
3584 If LENGTH is non-NULL, the length of the buffer conaining the
3585 demangled name, is placed in *LENGTH.
3587 The return value is a pointer to the start of the NUL-terminated
3588 demangled name, or NULL if the demangling fails. The caller is
3589 responsible for deallocating this memory using free.
3591 *STATUS is set to one of the following values:
3592 0: The demangling operation succeeded.
3593 -1: A memory allocation failiure occurred.
3594 -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
3595 -3: One of the arguments is invalid.
3597 The demagling is performed using the C++ ABI mangling rules, with
3598 GNU extensions. */
3600 char *
3601 __cxa_demangle (mangled_name, output_buffer, length, status)
3602 const char *mangled_name;
3603 char *output_buffer;
3604 size_t *length;
3605 int *status;
3607 struct dyn_string demangled_name;
3608 status_t result;
3610 if (status == NULL)
3611 return NULL;
3613 if (mangled_name == NULL) {
3614 *status = -3;
3615 return NULL;
3618 /* Did the caller provide a buffer for the demangled name? */
3619 if (output_buffer == NULL) {
3620 /* No; dyn_string will malloc a buffer for us. */
3621 if (!dyn_string_init (&demangled_name, 0))
3623 *status = -1;
3624 return NULL;
3627 else {
3628 /* Yes. Check that the length was provided. */
3629 if (length == NULL) {
3630 *status = -3;
3631 return NULL;
3633 /* Install the buffer into a dyn_string. */
3634 demangled_name.allocated = *length;
3635 demangled_name.length = 0;
3636 demangled_name.s = output_buffer;
3639 if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
3640 /* MANGLED_NAME apprears to be a function or variable name.
3641 Demangle it accordingly. */
3642 result = cp_demangle (mangled_name, &demangled_name, 0);
3643 else
3644 /* Try to demangled MANGLED_NAME as the name of a type. */
3645 result = cp_demangle_type (mangled_name, &demangled_name);
3647 if (result == STATUS_OK)
3648 /* The demangling succeeded. */
3650 /* If LENGTH isn't NULL, store the allocated buffer length
3651 there; the buffer may have been realloced by dyn_string
3652 functions. */
3653 if (length != NULL)
3654 *length = demangled_name.allocated;
3655 /* The operation was a success. */
3656 *status = 0;
3657 return dyn_string_buf (&demangled_name);
3659 else if (result == STATUS_ALLOCATION_FAILED)
3660 /* A call to malloc or realloc failed during the demangling
3661 operation. */
3663 *status = -1;
3664 return NULL;
3666 else
3667 /* The demangling failed for another reason, most probably because
3668 MANGLED_NAME isn't a valid mangled name. */
3670 /* If the buffer containing the demangled name wasn't provided
3671 by the caller, free it. */
3672 if (output_buffer == NULL)
3673 free (dyn_string_buf (&demangled_name));
3674 *status = -2;
3675 return NULL;
3679 #else /* !IN_LIBGCC2 */
3681 /* Variant entry point for integration with the existing cplus-dem
3682 demangler. Attempts to demangle MANGLED. If the demangling
3683 succeeds, returns a buffer, allocated with malloc, containing the
3684 demangled name. The caller must deallocate the buffer using free.
3685 If the demangling failes, returns NULL. */
3687 char *
3688 cplus_demangle_v3 (mangled, options)
3689 const char* mangled;
3690 int options;
3692 dyn_string_t demangled;
3693 status_t status;
3694 int type = !!(options & DMGL_TYPES);
3696 if (mangled[0] == '_' && mangled[1] == 'Z')
3697 /* It is not a type. */
3698 type = 0;
3699 else
3701 /* It is a type. Stop if we don't want to demangle types. */
3702 if (!type)
3703 return NULL;
3706 flag_verbose = !!(options & DMGL_VERBOSE);
3708 /* Create a dyn_string to hold the demangled name. */
3709 demangled = dyn_string_new (0);
3710 /* Attempt the demangling. */
3711 if (!type)
3712 /* Appears to be a function or variable name. */
3713 status = cp_demangle (mangled, demangled, 0);
3714 else
3715 /* Try to demangle it as the name of a type. */
3716 status = cp_demangle_type (mangled, demangled);
3718 if (STATUS_NO_ERROR (status))
3719 /* Demangling succeeded. */
3721 /* Grab the demangled result from the dyn_string. It was
3722 allocated with malloc, so we can return it directly. */
3723 char *return_value = dyn_string_release (demangled);
3724 /* Hand back the demangled name. */
3725 return return_value;
3727 else if (status == STATUS_ALLOCATION_FAILED)
3729 fprintf (stderr, "Memory allocation failed.\n");
3730 abort ();
3732 else
3733 /* Demangling failed. */
3735 dyn_string_delete (demangled);
3736 return NULL;
3740 /* Demangle a Java symbol. Java uses a subset of the V3 ABI C++ mangling
3741 conventions, but the output formatting is a little different.
3742 This instructs the C++ demangler not to emit pointer characters ("*"), and
3743 to use Java's namespace separator symbol ("." instead of "::"). It then
3744 does an additional pass over the demangled output to replace instances
3745 of JArray<TYPE> with TYPE[]. */
3747 char *
3748 java_demangle_v3 (mangled)
3749 const char* mangled;
3751 dyn_string_t demangled;
3752 char *next;
3753 char *end;
3754 int len;
3755 status_t status;
3756 int nesting = 0;
3757 char *cplus_demangled;
3758 char *return_value;
3760 /* Create a dyn_string to hold the demangled name. */
3761 demangled = dyn_string_new (0);
3763 /* Attempt the demangling. */
3764 status = cp_demangle ((char *) mangled, demangled, DMGL_JAVA);
3766 if (STATUS_NO_ERROR (status))
3767 /* Demangling succeeded. */
3769 /* Grab the demangled result from the dyn_string. */
3770 cplus_demangled = dyn_string_release (demangled);
3772 else if (status == STATUS_ALLOCATION_FAILED)
3774 fprintf (stderr, "Memory allocation failed.\n");
3775 abort ();
3777 else
3778 /* Demangling failed. */
3780 dyn_string_delete (demangled);
3781 return NULL;
3784 len = strlen (cplus_demangled);
3785 next = cplus_demangled;
3786 end = next + len;
3787 demangled = NULL;
3789 /* Replace occurances of JArray<TYPE> with TYPE[]. */
3790 while (next < end)
3792 char *open_str = strstr (next, "JArray<");
3793 char *close_str = NULL;
3794 if (nesting > 0)
3795 close_str = strchr (next, '>');
3797 if (open_str != NULL && (close_str == NULL || close_str > open_str))
3799 ++nesting;
3801 if (!demangled)
3802 demangled = dyn_string_new(len);
3804 /* Copy prepending symbols, if any. */
3805 if (open_str > next)
3807 open_str[0] = 0;
3808 dyn_string_append_cstr (demangled, next);
3810 next = open_str + 7;
3812 else if (close_str != NULL)
3814 --nesting;
3816 /* Copy prepending type symbol, if any. Squash any spurious
3817 whitespace. */
3818 if (close_str > next && next[0] != ' ')
3820 close_str[0] = 0;
3821 dyn_string_append_cstr (demangled, next);
3823 dyn_string_append_cstr (demangled, "[]");
3824 next = close_str + 1;
3826 else
3828 /* There are no more arrays. Copy the rest of the symbol, or
3829 simply return the original symbol if no changes were made. */
3830 if (next == cplus_demangled)
3831 return cplus_demangled;
3833 dyn_string_append_cstr (demangled, next);
3834 next = end;
3838 free (cplus_demangled);
3840 return_value = dyn_string_release (demangled);
3841 return return_value;
3844 #endif /* IN_LIBGCC2 */
3847 /* Demangle NAME in the G++ V3 ABI demangling style, and return either
3848 zero, indicating that some error occurred, or a demangling_t
3849 holding the results. */
3850 static demangling_t
3851 demangle_v3_with_details (name)
3852 const char *name;
3854 demangling_t dm;
3855 status_t status;
3857 if (strncmp (name, "_Z", 2))
3858 return 0;
3860 dm = demangling_new (name, DMGL_GNU_V3);
3861 if (dm == NULL)
3863 fprintf (stderr, "Memory allocation failed.\n");
3864 abort ();
3867 status = result_push (dm);
3868 if (! STATUS_NO_ERROR (status))
3870 demangling_delete (dm);
3871 fprintf (stderr, "%s\n", status);
3872 abort ();
3875 status = demangle_mangled_name (dm);
3876 if (STATUS_NO_ERROR (status))
3877 return dm;
3879 demangling_delete (dm);
3880 return 0;
3884 /* Return non-zero iff NAME is the mangled form of a constructor name
3885 in the G++ V3 ABI demangling style. Specifically, return:
3886 - '1' if NAME is a complete object constructor,
3887 - '2' if NAME is a base object constructor, or
3888 - '3' if NAME is a complete object allocating constructor. */
3889 enum gnu_v3_ctor_kinds
3890 is_gnu_v3_mangled_ctor (name)
3891 const char *name;
3893 demangling_t dm = demangle_v3_with_details (name);
3895 if (dm)
3897 enum gnu_v3_ctor_kinds result = dm->is_constructor;
3898 demangling_delete (dm);
3899 return result;
3901 else
3902 return 0;
3906 /* Return non-zero iff NAME is the mangled form of a destructor name
3907 in the G++ V3 ABI demangling style. Specifically, return:
3908 - '0' if NAME is a deleting destructor,
3909 - '1' if NAME is a complete object destructor, or
3910 - '2' if NAME is a base object destructor. */
3911 enum gnu_v3_dtor_kinds
3912 is_gnu_v3_mangled_dtor (name)
3913 const char *name;
3915 demangling_t dm = demangle_v3_with_details (name);
3917 if (dm)
3919 enum gnu_v3_dtor_kinds result = dm->is_destructor;
3920 demangling_delete (dm);
3921 return result;
3923 else
3924 return 0;
3928 #ifdef STANDALONE_DEMANGLER
3930 #include "getopt.h"
3932 static void print_usage
3933 PARAMS ((FILE* fp, int exit_value));
3935 /* Non-zero if CHAR is a character than can occur in a mangled name. */
3936 #define is_mangled_char(CHAR) \
3937 (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \
3938 || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
3940 /* The name of this program, as invoked. */
3941 const char* program_name;
3943 /* Prints usage summary to FP and then exits with EXIT_VALUE. */
3945 static void
3946 print_usage (fp, exit_value)
3947 FILE* fp;
3948 int exit_value;
3950 fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
3951 fprintf (fp, "Options:\n");
3952 fprintf (fp, " -h,--help Display this message.\n");
3953 fprintf (fp, " -s,--strict Demangle standard names only.\n");
3954 fprintf (fp, " -v,--verbose Produce verbose demanglings.\n");
3955 fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n");
3957 exit (exit_value);
3960 /* Option specification for getopt_long. */
3961 static const struct option long_options[] =
3963 { "help", no_argument, NULL, 'h' },
3964 { "strict", no_argument, NULL, 's' },
3965 { "verbose", no_argument, NULL, 'v' },
3966 { NULL, no_argument, NULL, 0 },
3969 /* Main entry for a demangling filter executable. It will demangle
3970 its command line arguments, if any. If none are provided, it will
3971 filter stdin to stdout, replacing any recognized mangled C++ names
3972 with their demangled equivalents. */
3975 main (argc, argv)
3976 int argc;
3977 char *argv[];
3979 status_t status;
3980 int i;
3981 int opt_char;
3983 /* Use the program name of this program, as invoked. */
3984 program_name = argv[0];
3986 /* Parse options. */
3989 opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);
3990 switch (opt_char)
3992 case '?': /* Unrecognized option. */
3993 print_usage (stderr, 1);
3994 break;
3996 case 'h':
3997 print_usage (stdout, 0);
3998 break;
4000 case 's':
4001 flag_strict = 1;
4002 break;
4004 case 'v':
4005 flag_verbose = 1;
4006 break;
4009 while (opt_char != -1);
4011 if (optind == argc)
4012 /* No command line arguments were provided. Filter stdin. */
4014 dyn_string_t mangled = dyn_string_new (3);
4015 dyn_string_t demangled = dyn_string_new (0);
4016 status_t status;
4018 /* Read all of input. */
4019 while (!feof (stdin))
4021 char c = getchar ();
4023 /* The first character of a mangled name is an underscore. */
4024 if (feof (stdin))
4025 break;
4026 if (c != '_')
4028 /* It's not a mangled name. Print the character and go
4029 on. */
4030 putchar (c);
4031 continue;
4033 c = getchar ();
4035 /* The second character of a mangled name is a capital `Z'. */
4036 if (feof (stdin))
4037 break;
4038 if (c != 'Z')
4040 /* It's not a mangled name. Print the previous
4041 underscore, the `Z', and go on. */
4042 putchar ('_');
4043 putchar (c);
4044 continue;
4047 /* Start keeping track of the candidate mangled name. */
4048 dyn_string_append_char (mangled, '_');
4049 dyn_string_append_char (mangled, 'Z');
4051 /* Pile characters into mangled until we hit one that can't
4052 occur in a mangled name. */
4053 c = getchar ();
4054 while (!feof (stdin) && is_mangled_char (c))
4056 dyn_string_append_char (mangled, c);
4057 if (feof (stdin))
4058 break;
4059 c = getchar ();
4062 /* Attempt to demangle the name. */
4063 status = cp_demangle (dyn_string_buf (mangled), demangled, 0);
4065 /* If the demangling succeeded, great! Print out the
4066 demangled version. */
4067 if (STATUS_NO_ERROR (status))
4068 fputs (dyn_string_buf (demangled), stdout);
4069 /* Abort on allocation failures. */
4070 else if (status == STATUS_ALLOCATION_FAILED)
4072 fprintf (stderr, "Memory allocation failed.\n");
4073 abort ();
4075 /* Otherwise, it might not have been a mangled name. Just
4076 print out the original text. */
4077 else
4078 fputs (dyn_string_buf (mangled), stdout);
4080 /* If we haven't hit EOF yet, we've read one character that
4081 can't occur in a mangled name, so print it out. */
4082 if (!feof (stdin))
4083 putchar (c);
4085 /* Clear the candidate mangled name, to start afresh next
4086 time we hit a `_Z'. */
4087 dyn_string_clear (mangled);
4090 dyn_string_delete (mangled);
4091 dyn_string_delete (demangled);
4093 else
4094 /* Demangle command line arguments. */
4096 dyn_string_t result = dyn_string_new (0);
4098 /* Loop over command line arguments. */
4099 for (i = optind; i < argc; ++i)
4101 /* Attempt to demangle. */
4102 status = cp_demangle (argv[i], result, 0);
4104 /* If it worked, print the demangled name. */
4105 if (STATUS_NO_ERROR (status))
4106 printf ("%s\n", dyn_string_buf (result));
4107 /* Abort on allocaiton failures. */
4108 else if (status == STATUS_ALLOCATION_FAILED)
4110 fprintf (stderr, "Memory allocation failed.\n");
4111 abort ();
4113 /* If not, print the error message to stderr instead. */
4114 else
4115 fprintf (stderr, "%s\n", status);
4117 dyn_string_delete (result);
4120 return 0;
4123 #endif /* STANDALONE_DEMANGLER */