fix typos
[binutils.git] / libiberty / cp-demangle.c
blobdb34b58b1c5b60ed13f99db7be894871400a0296
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;
177 typedef struct demangling_def *demangling_t;
179 /* This type is the standard return code from most functions. Values
180 other than STATUS_OK contain descriptive messages. */
181 typedef const char *status_t;
183 /* Special values that can be used as a status_t. */
184 #define STATUS_OK NULL
185 #define STATUS_ERROR "Error."
186 #define STATUS_UNIMPLEMENTED "Unimplemented."
187 #define STATUS_INTERNAL_ERROR "Internal error."
189 /* This status code indicates a failure in malloc or realloc. */
190 static const char *const status_allocation_failed = "Allocation failed.";
191 #define STATUS_ALLOCATION_FAILED status_allocation_failed
193 /* Non-zero if STATUS indicates that no error has occurred. */
194 #define STATUS_NO_ERROR(STATUS) ((STATUS) == STATUS_OK)
196 /* Evaluate EXPR, which must produce a status_t. If the status code
197 indicates an error, return from the current function with that
198 status code. */
199 #define RETURN_IF_ERROR(EXPR) \
200 do \
202 status_t s = EXPR; \
203 if (!STATUS_NO_ERROR (s)) \
204 return s; \
206 while (0)
208 static status_t int_to_dyn_string
209 PARAMS ((int, dyn_string_t));
210 static string_list_t string_list_new
211 PARAMS ((int));
212 static void string_list_delete
213 PARAMS ((string_list_t));
214 static status_t result_add_separated_char
215 PARAMS ((demangling_t, int));
216 static status_t result_push
217 PARAMS ((demangling_t));
218 static string_list_t result_pop
219 PARAMS ((demangling_t));
220 static int substitution_start
221 PARAMS ((demangling_t));
222 static status_t substitution_add
223 PARAMS ((demangling_t, int, int));
224 static dyn_string_t substitution_get
225 PARAMS ((demangling_t, int, int *));
226 #ifdef CP_DEMANGLE_DEBUG
227 static void substitutions_print
228 PARAMS ((demangling_t, FILE *));
229 #endif
230 static template_arg_list_t template_arg_list_new
231 PARAMS ((void));
232 static void template_arg_list_delete
233 PARAMS ((template_arg_list_t));
234 static void template_arg_list_add_arg
235 PARAMS ((template_arg_list_t, string_list_t));
236 static string_list_t template_arg_list_get_arg
237 PARAMS ((template_arg_list_t, int));
238 static void push_template_arg_list
239 PARAMS ((demangling_t, template_arg_list_t));
240 static void pop_to_template_arg_list
241 PARAMS ((demangling_t, template_arg_list_t));
242 #ifdef CP_DEMANGLE_DEBUG
243 static void template_arg_list_print
244 PARAMS ((template_arg_list_t, FILE *));
245 #endif
246 static template_arg_list_t current_template_arg_list
247 PARAMS ((demangling_t));
248 static demangling_t demangling_new
249 PARAMS ((const char *, int));
250 static void demangling_delete
251 PARAMS ((demangling_t));
253 /* The last character of DS. Warning: DS is evaluated twice. */
254 #define dyn_string_last_char(DS) \
255 (dyn_string_buf (DS)[dyn_string_length (DS) - 1])
257 /* Append a space character (` ') to DS if it does not already end
258 with one. Evaluates to 1 on success, or 0 on allocation failure. */
259 #define dyn_string_append_space(DS) \
260 ((dyn_string_length (DS) > 0 \
261 && dyn_string_last_char (DS) != ' ') \
262 ? dyn_string_append_char ((DS), ' ') \
263 : 1)
265 /* Returns the index of the current position in the mangled name. */
266 #define current_position(DM) ((DM)->next - (DM)->name)
268 /* Returns the character at the current position of the mangled name. */
269 #define peek_char(DM) (*((DM)->next))
271 /* Returns the character one past the current position of the mangled
272 name. */
273 #define peek_char_next(DM) \
274 (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1)))
276 /* Returns the character at the current position, and advances the
277 current position to the next character. */
278 #define next_char(DM) (*((DM)->next)++)
280 /* Returns non-zero if the current position is the end of the mangled
281 name, i.e. one past the last character. */
282 #define end_of_name_p(DM) (peek_char (DM) == '\0')
284 /* Advances the current position by one character. */
285 #define advance_char(DM) (++(DM)->next)
287 /* Returns the string containing the current demangled result. */
288 #define result_string(DM) (&(DM)->result->string)
290 /* Returns the position at which new text is inserted into the
291 demangled result. */
292 #define result_caret_pos(DM) \
293 (result_length (DM) + \
294 ((string_list_t) result_string (DM))->caret_position)
296 /* Adds a dyn_string_t to the demangled result. */
297 #define result_add_string(DM, STRING) \
298 (dyn_string_insert (&(DM)->result->string, \
299 result_caret_pos (DM), (STRING)) \
300 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
302 /* Adds NUL-terminated string CSTR to the demangled result. */
303 #define result_add(DM, CSTR) \
304 (dyn_string_insert_cstr (&(DM)->result->string, \
305 result_caret_pos (DM), (CSTR)) \
306 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
308 /* Adds character CHAR to the demangled result. */
309 #define result_add_char(DM, CHAR) \
310 (dyn_string_insert_char (&(DM)->result->string, \
311 result_caret_pos (DM), (CHAR)) \
312 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
314 /* Inserts a dyn_string_t to the demangled result at position POS. */
315 #define result_insert_string(DM, POS, STRING) \
316 (dyn_string_insert (&(DM)->result->string, (POS), (STRING)) \
317 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
319 /* Inserts NUL-terminated string CSTR to the demangled result at
320 position POS. */
321 #define result_insert(DM, POS, CSTR) \
322 (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR)) \
323 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
325 /* Inserts character CHAR to the demangled result at position POS. */
326 #define result_insert_char(DM, POS, CHAR) \
327 (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR)) \
328 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
330 /* The length of the current demangled result. */
331 #define result_length(DM) \
332 dyn_string_length (&(DM)->result->string)
334 /* Appends a (less-than, greater-than) character to the result in DM
335 to (open, close) a template argument or parameter list. Appends a
336 space first if necessary to prevent spurious elision of angle
337 brackets with the previous character. */
338 #define result_open_template_list(DM) result_add_separated_char(DM, '<')
339 #define result_close_template_list(DM) result_add_separated_char(DM, '>')
341 /* Appends a base 10 representation of VALUE to DS. STATUS_OK on
342 success. On failure, deletes DS and returns an error code. */
344 static status_t
345 int_to_dyn_string (value, ds)
346 int value;
347 dyn_string_t ds;
349 int i;
350 int mask = 1;
352 /* Handle zero up front. */
353 if (value == 0)
355 if (!dyn_string_append_char (ds, '0'))
356 return STATUS_ALLOCATION_FAILED;
357 return STATUS_OK;
360 /* For negative numbers, emit a minus sign. */
361 if (value < 0)
363 if (!dyn_string_append_char (ds, '-'))
364 return STATUS_ALLOCATION_FAILED;
365 value = -value;
368 /* Find the power of 10 of the first digit. */
369 i = value;
370 while (i > 9)
372 mask *= 10;
373 i /= 10;
376 /* Write the digits. */
377 while (mask > 0)
379 int digit = value / mask;
381 if (!dyn_string_append_char (ds, '0' + digit))
382 return STATUS_ALLOCATION_FAILED;
384 value -= digit * mask;
385 mask /= 10;
388 return STATUS_OK;
391 /* Creates a new string list node. The contents of the string are
392 empty, but the initial buffer allocation is LENGTH. The string
393 list node should be deleted with string_list_delete. Returns NULL
394 if allocation fails. */
396 static string_list_t
397 string_list_new (length)
398 int length;
400 string_list_t s = (string_list_t) malloc (sizeof (struct string_list_def));
401 s->caret_position = 0;
402 if (s == NULL)
403 return NULL;
404 if (!dyn_string_init ((dyn_string_t) s, length))
405 return NULL;
406 return s;
409 /* Deletes the entire string list starting at NODE. */
411 static void
412 string_list_delete (node)
413 string_list_t node;
415 while (node != NULL)
417 string_list_t next = node->next;
418 free (node);
419 node = next;
423 /* Appends CHARACTER to the demangled result. If the current trailing
424 character of the result is CHARACTER, a space is inserted first. */
426 static status_t
427 result_add_separated_char (dm, character)
428 demangling_t dm;
429 int character;
431 char *result = dyn_string_buf (result_string (dm));
432 int caret_pos = result_caret_pos (dm);
434 /* Add a space if the last character is already the character we
435 want to add. */
436 if (caret_pos > 0 && result[caret_pos - 1] == character)
437 RETURN_IF_ERROR (result_add_char (dm, ' '));
438 /* Add the character. */
439 RETURN_IF_ERROR (result_add_char (dm, character));
441 return STATUS_OK;
444 /* Allocates and pushes a new string onto the demangled results stack
445 for DM. Subsequent demangling with DM will emit to the new string.
446 Returns STATUS_OK on success, STATUS_ALLOCATION_FAILED on
447 allocation failure. */
449 static status_t
450 result_push (dm)
451 demangling_t dm;
453 string_list_t new_string = string_list_new (0);
454 if (new_string == NULL)
455 /* Allocation failed. */
456 return STATUS_ALLOCATION_FAILED;
458 /* Link the new string to the front of the list of result strings. */
459 new_string->next = (string_list_t) dm->result;
460 dm->result = new_string;
461 return STATUS_OK;
464 /* Removes and returns the topmost element on the demangled results
465 stack for DM. The caller assumes ownership for the returned
466 string. */
468 static string_list_t
469 result_pop (dm)
470 demangling_t dm;
472 string_list_t top = dm->result;
473 dm->result = top->next;
474 return top;
477 /* Returns the current value of the caret for the result string. The
478 value is an offet from the end of the result string. */
480 static int
481 result_get_caret (dm)
482 demangling_t dm;
484 return ((string_list_t) result_string (dm))->caret_position;
487 /* Sets the value of the caret for the result string, counted as an
488 offet from the end of the result string. */
490 static void
491 result_set_caret (dm, position)
492 demangling_t dm;
493 int position;
495 ((string_list_t) result_string (dm))->caret_position = position;
498 /* Shifts the position of the next addition to the result by
499 POSITION_OFFSET. A negative value shifts the caret to the left. */
501 static void
502 result_shift_caret (dm, position_offset)
503 demangling_t dm;
504 int position_offset;
506 ((string_list_t) result_string (dm))->caret_position += position_offset;
509 /* Returns non-zero if the character that comes right before the place
510 where text will be added to the result is a space. In this case,
511 the caller should supress adding another space. */
513 static int
514 result_previous_char_is_space (dm)
515 demangling_t dm;
517 char *result = dyn_string_buf (result_string (dm));
518 int pos = result_caret_pos (dm);
519 return pos > 0 && result[pos - 1] == ' ';
522 /* Returns the start position of a fragment of the demangled result
523 that will be a substitution candidate. Should be called at the
524 start of productions that can add substitutions. */
526 static int
527 substitution_start (dm)
528 demangling_t dm;
530 return result_caret_pos (dm);
533 /* Adds the suffix of the current demangled result of DM starting at
534 START_POSITION as a potential substitution. If TEMPLATE_P is
535 non-zero, this potential substitution is a template-id. */
537 static status_t
538 substitution_add (dm, start_position, template_p)
539 demangling_t dm;
540 int start_position;
541 int template_p;
543 dyn_string_t result = result_string (dm);
544 dyn_string_t substitution = dyn_string_new (0);
545 int i;
547 if (substitution == NULL)
548 return STATUS_ALLOCATION_FAILED;
550 /* Extract the substring of the current demangling result that
551 represents the subsitution candidate. */
552 if (!dyn_string_substring (substitution,
553 result, start_position, result_caret_pos (dm)))
555 dyn_string_delete (substitution);
556 return STATUS_ALLOCATION_FAILED;
559 /* If there's no room for the new entry, grow the array. */
560 if (dm->substitutions_allocated == dm->num_substitutions)
562 size_t new_array_size;
563 if (dm->substitutions_allocated > 0)
564 dm->substitutions_allocated *= 2;
565 else
566 dm->substitutions_allocated = 2;
567 new_array_size =
568 sizeof (struct substitution_def) * dm->substitutions_allocated;
570 dm->substitutions = (struct substitution_def *)
571 realloc (dm->substitutions, new_array_size);
572 if (dm->substitutions == NULL)
573 /* Realloc failed. */
575 dyn_string_delete (substitution);
576 return STATUS_ALLOCATION_FAILED;
580 /* Add the substitution to the array. */
581 i = dm->num_substitutions++;
582 dm->substitutions[i].text = substitution;
583 dm->substitutions[i].template_p = template_p;
585 #ifdef CP_DEMANGLE_DEBUG
586 substitutions_print (dm, stderr);
587 #endif
589 return STATUS_OK;
592 /* Returns the Nth-most-recent substitution. Sets *TEMPLATE_P to
593 non-zero if the substitution is a template-id, zero otherwise.
594 N is numbered from zero. DM retains ownership of the returned
595 string. If N is negative, or equal to or greater than the current
596 number of substitution candidates, returns NULL. */
598 static dyn_string_t
599 substitution_get (dm, n, template_p)
600 demangling_t dm;
601 int n;
602 int *template_p;
604 struct substitution_def *sub;
606 /* Make sure N is in the valid range. */
607 if (n < 0 || n >= dm->num_substitutions)
608 return NULL;
610 sub = &(dm->substitutions[n]);
611 *template_p = sub->template_p;
612 return sub->text;
615 #ifdef CP_DEMANGLE_DEBUG
616 /* Debugging routine to print the current substitutions to FP. */
618 static void
619 substitutions_print (dm, fp)
620 demangling_t dm;
621 FILE *fp;
623 int seq_id;
624 int num = dm->num_substitutions;
626 fprintf (fp, "SUBSTITUTIONS:\n");
627 for (seq_id = -1; seq_id < num - 1; ++seq_id)
629 int template_p;
630 dyn_string_t text = substitution_get (dm, seq_id + 1, &template_p);
632 if (seq_id == -1)
633 fprintf (fp, " S_ ");
634 else
635 fprintf (fp, " S%d_", seq_id);
636 fprintf (fp, " %c: %s\n", template_p ? '*' : ' ', dyn_string_buf (text));
640 #endif /* CP_DEMANGLE_DEBUG */
642 /* Creates a new template argument list. Returns NULL if allocation
643 fails. */
645 static template_arg_list_t
646 template_arg_list_new ()
648 template_arg_list_t new_list =
649 (template_arg_list_t) malloc (sizeof (struct template_arg_list_def));
650 if (new_list == NULL)
651 return NULL;
652 /* Initialize the new list to have no arguments. */
653 new_list->first_argument = NULL;
654 new_list->last_argument = NULL;
655 /* Return the new list. */
656 return new_list;
659 /* Deletes a template argument list and the template arguments it
660 contains. */
662 static void
663 template_arg_list_delete (list)
664 template_arg_list_t list;
666 /* If there are any arguments on LIST, delete them. */
667 if (list->first_argument != NULL)
668 string_list_delete (list->first_argument);
669 /* Delete LIST. */
670 free (list);
673 /* Adds ARG to the template argument list ARG_LIST. */
675 static void
676 template_arg_list_add_arg (arg_list, arg)
677 template_arg_list_t arg_list;
678 string_list_t arg;
680 if (arg_list->first_argument == NULL)
681 /* If there were no arguments before, ARG is the first one. */
682 arg_list->first_argument = arg;
683 else
684 /* Make ARG the last argument on the list. */
685 arg_list->last_argument->next = arg;
686 /* Make ARG the last on the list. */
687 arg_list->last_argument = arg;
688 arg->next = NULL;
691 /* Returns the template arugment at position INDEX in template
692 argument list ARG_LIST. */
694 static string_list_t
695 template_arg_list_get_arg (arg_list, index)
696 template_arg_list_t arg_list;
697 int index;
699 string_list_t arg = arg_list->first_argument;
700 /* Scan down the list of arguments to find the one at position
701 INDEX. */
702 while (index--)
704 arg = arg->next;
705 if (arg == NULL)
706 /* Ran out of arguments before INDEX hit zero. That's an
707 error. */
708 return NULL;
710 /* Return the argument at position INDEX. */
711 return arg;
714 /* Pushes ARG_LIST onto the top of the template argument list stack. */
716 static void
717 push_template_arg_list (dm, arg_list)
718 demangling_t dm;
719 template_arg_list_t arg_list;
721 arg_list->next = dm->template_arg_lists;
722 dm->template_arg_lists = arg_list;
723 #ifdef CP_DEMANGLE_DEBUG
724 fprintf (stderr, " ** pushing template arg list\n");
725 template_arg_list_print (arg_list, stderr);
726 #endif
729 /* Pops and deletes elements on the template argument list stack until
730 arg_list is the topmost element. If arg_list is NULL, all elements
731 are popped and deleted. */
733 static void
734 pop_to_template_arg_list (dm, arg_list)
735 demangling_t dm;
736 template_arg_list_t arg_list;
738 while (dm->template_arg_lists != arg_list)
740 template_arg_list_t top = dm->template_arg_lists;
741 /* Disconnect the topmost element from the list. */
742 dm->template_arg_lists = top->next;
743 /* Delete the popped element. */
744 template_arg_list_delete (top);
745 #ifdef CP_DEMANGLE_DEBUG
746 fprintf (stderr, " ** removing template arg list\n");
747 #endif
751 #ifdef CP_DEMANGLE_DEBUG
753 /* Prints the contents of ARG_LIST to FP. */
755 static void
756 template_arg_list_print (arg_list, fp)
757 template_arg_list_t arg_list;
758 FILE *fp;
760 string_list_t arg;
761 int index = -1;
763 fprintf (fp, "TEMPLATE ARGUMENT LIST:\n");
764 for (arg = arg_list->first_argument; arg != NULL; arg = arg->next)
766 if (index == -1)
767 fprintf (fp, " T_ : ");
768 else
769 fprintf (fp, " T%d_ : ", index);
770 ++index;
771 fprintf (fp, "%s\n", dyn_string_buf ((dyn_string_t) arg));
775 #endif /* CP_DEMANGLE_DEBUG */
777 /* Returns the topmost element on the stack of template argument
778 lists. If there is no list of template arguments, returns NULL. */
780 static template_arg_list_t
781 current_template_arg_list (dm)
782 demangling_t dm;
784 return dm->template_arg_lists;
787 /* Allocates a demangling_t object for demangling mangled NAME. A new
788 result must be pushed before the returned object can be used.
789 Returns NULL if allocation fails. */
791 static demangling_t
792 demangling_new (name, style)
793 const char *name;
794 int style;
796 demangling_t dm;
797 dm = (demangling_t) malloc (sizeof (struct demangling_def));
798 if (dm == NULL)
799 return NULL;
801 dm->name = name;
802 dm->next = name;
803 dm->result = NULL;
804 dm->num_substitutions = 0;
805 dm->substitutions_allocated = 10;
806 dm->template_arg_lists = NULL;
807 dm->last_source_name = dyn_string_new (0);
808 if (dm->last_source_name == NULL)
809 return NULL;
810 dm->substitutions = (struct substitution_def *)
811 malloc (dm->substitutions_allocated * sizeof (struct substitution_def));
812 if (dm->substitutions == NULL)
814 dyn_string_delete (dm->last_source_name);
815 return NULL;
817 dm->style = style;
819 return dm;
822 /* Deallocates a demangling_t object and all memory associated with
823 it. */
825 static void
826 demangling_delete (dm)
827 demangling_t dm;
829 int i;
830 template_arg_list_t arg_list = dm->template_arg_lists;
832 /* Delete the stack of template argument lists. */
833 while (arg_list != NULL)
835 template_arg_list_t next = arg_list->next;
836 template_arg_list_delete (arg_list);
837 arg_list = next;
839 /* Delete the list of substitutions. */
840 for (i = dm->num_substitutions; --i >= 0; )
841 dyn_string_delete (dm->substitutions[i].text);
842 free (dm->substitutions);
843 /* Delete the demangled result. */
844 string_list_delete (dm->result);
845 /* Delete the stored identifier name. */
846 dyn_string_delete (dm->last_source_name);
847 /* Delete the context object itself. */
848 free (dm);
851 /* These functions demangle an alternative of the corresponding
852 production in the mangling spec. The first argument of each is a
853 demangling context structure for the current demangling
854 operation. Most emit demangled text directly to the topmost result
855 string on the result string stack in the demangling context
856 structure. */
858 static status_t demangle_char
859 PARAMS ((demangling_t, int));
860 static status_t demangle_mangled_name
861 PARAMS ((demangling_t));
862 static status_t demangle_encoding
863 PARAMS ((demangling_t));
864 static status_t demangle_name
865 PARAMS ((demangling_t, int *));
866 static status_t demangle_nested_name
867 PARAMS ((demangling_t, int *));
868 static status_t demangle_prefix
869 PARAMS ((demangling_t, int *));
870 static status_t demangle_unqualified_name
871 PARAMS ((demangling_t, int *));
872 static status_t demangle_source_name
873 PARAMS ((demangling_t));
874 static status_t demangle_number
875 PARAMS ((demangling_t, int *, int, int));
876 static status_t demangle_number_literally
877 PARAMS ((demangling_t, dyn_string_t, int, int));
878 static status_t demangle_identifier
879 PARAMS ((demangling_t, int, dyn_string_t));
880 static status_t demangle_operator_name
881 PARAMS ((demangling_t, int, int *));
882 static status_t demangle_nv_offset
883 PARAMS ((demangling_t));
884 static status_t demangle_v_offset
885 PARAMS ((demangling_t));
886 static status_t demangle_call_offset
887 PARAMS ((demangling_t));
888 static status_t demangle_special_name
889 PARAMS ((demangling_t));
890 static status_t demangle_ctor_dtor_name
891 PARAMS ((demangling_t));
892 static status_t demangle_type_ptr
893 PARAMS ((demangling_t, int *, int));
894 static status_t demangle_type
895 PARAMS ((demangling_t));
896 static status_t demangle_CV_qualifiers
897 PARAMS ((demangling_t, dyn_string_t));
898 static status_t demangle_builtin_type
899 PARAMS ((demangling_t));
900 static status_t demangle_function_type
901 PARAMS ((demangling_t, int *));
902 static status_t demangle_bare_function_type
903 PARAMS ((demangling_t, int *));
904 static status_t demangle_class_enum_type
905 PARAMS ((demangling_t, int *));
906 static status_t demangle_array_type
907 PARAMS ((demangling_t, int *));
908 static status_t demangle_template_param
909 PARAMS ((demangling_t));
910 static status_t demangle_template_args
911 PARAMS ((demangling_t));
912 static status_t demangle_literal
913 PARAMS ((demangling_t));
914 static status_t demangle_template_arg
915 PARAMS ((demangling_t));
916 static status_t demangle_expression
917 PARAMS ((demangling_t));
918 static status_t demangle_scope_expression
919 PARAMS ((demangling_t));
920 static status_t demangle_expr_primary
921 PARAMS ((demangling_t));
922 static status_t demangle_substitution
923 PARAMS ((demangling_t, int *));
924 static status_t demangle_local_name
925 PARAMS ((demangling_t));
926 static status_t demangle_discriminator
927 PARAMS ((demangling_t, int));
928 static status_t cp_demangle
929 PARAMS ((const char *, dyn_string_t, int));
930 #ifdef IN_LIBGCC2
931 static status_t cp_demangle_type
932 PARAMS ((const char*, dyn_string_t));
933 #endif
935 /* When passed to demangle_bare_function_type, indicates that the
936 function's return type is not encoded before its parameter types. */
937 #define BFT_NO_RETURN_TYPE NULL
939 /* Check that the next character is C. If so, consume it. If not,
940 return an error. */
942 static status_t
943 demangle_char (dm, c)
944 demangling_t dm;
945 int c;
947 static char *error_message = NULL;
949 if (peek_char (dm) == c)
951 advance_char (dm);
952 return STATUS_OK;
954 else
956 if (error_message == NULL)
957 error_message = strdup ("Expected ?");
958 error_message[9] = c;
959 return error_message;
963 /* Demangles and emits a <mangled-name>.
965 <mangled-name> ::= _Z <encoding> */
967 static status_t
968 demangle_mangled_name (dm)
969 demangling_t dm;
971 DEMANGLE_TRACE ("mangled-name", dm);
972 RETURN_IF_ERROR (demangle_char (dm, '_'));
973 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
974 RETURN_IF_ERROR (demangle_encoding (dm));
975 return STATUS_OK;
978 /* Demangles and emits an <encoding>.
980 <encoding> ::= <function name> <bare-function-type>
981 ::= <data name>
982 ::= <special-name> */
984 static status_t
985 demangle_encoding (dm)
986 demangling_t dm;
988 int encode_return_type;
989 int start_position;
990 template_arg_list_t old_arg_list = current_template_arg_list (dm);
991 char peek = peek_char (dm);
993 DEMANGLE_TRACE ("encoding", dm);
995 /* Remember where the name starts. If it turns out to be a template
996 function, we'll have to insert the return type here. */
997 start_position = result_caret_pos (dm);
999 if (peek == 'G' || peek == 'T')
1000 RETURN_IF_ERROR (demangle_special_name (dm));
1001 else
1003 /* Now demangle the name. */
1004 RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));
1006 /* If there's anything left, the name was a function name, with
1007 maybe its return type, and its parameter types, following. */
1008 if (!end_of_name_p (dm)
1009 && peek_char (dm) != 'E')
1011 if (encode_return_type)
1012 /* Template functions have their return type encoded. The
1013 return type should be inserted at start_position. */
1014 RETURN_IF_ERROR
1015 (demangle_bare_function_type (dm, &start_position));
1016 else
1017 /* Non-template functions don't have their return type
1018 encoded. */
1019 RETURN_IF_ERROR
1020 (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE));
1024 /* Pop off template argument lists that were built during the
1025 mangling of this name, to restore the old template context. */
1026 pop_to_template_arg_list (dm, old_arg_list);
1028 return STATUS_OK;
1031 /* Demangles and emits a <name>.
1033 <name> ::= <unscoped-name>
1034 ::= <unscoped-template-name> <template-args>
1035 ::= <nested-name>
1036 ::= <local-name>
1038 <unscoped-name> ::= <unqualified-name>
1039 ::= St <unqualified-name> # ::std::
1041 <unscoped-template-name>
1042 ::= <unscoped-name>
1043 ::= <substitution> */
1045 static status_t
1046 demangle_name (dm, encode_return_type)
1047 demangling_t dm;
1048 int *encode_return_type;
1050 int start = substitution_start (dm);
1051 char peek = peek_char (dm);
1052 int is_std_substitution = 0;
1054 /* Generally, the return type is encoded if the function is a
1055 template-id, and suppressed otherwise. There are a few cases,
1056 though, in which the return type is not encoded even for a
1057 templated function. In these cases, this flag is set. */
1058 int suppress_return_type = 0;
1060 DEMANGLE_TRACE ("name", dm);
1062 switch (peek)
1064 case 'N':
1065 /* This is a <nested-name>. */
1066 RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));
1067 break;
1069 case 'Z':
1070 RETURN_IF_ERROR (demangle_local_name (dm));
1071 *encode_return_type = 0;
1072 break;
1074 case 'S':
1075 /* The `St' substitution allows a name nested in std:: to appear
1076 without being enclosed in a nested name. */
1077 if (peek_char_next (dm) == 't')
1079 (void) next_char (dm);
1080 (void) next_char (dm);
1081 RETURN_IF_ERROR (result_add (dm, "std::"));
1082 RETURN_IF_ERROR
1083 (demangle_unqualified_name (dm, &suppress_return_type));
1084 is_std_substitution = 1;
1086 else
1087 RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
1088 /* Check if a template argument list immediately follows.
1089 If so, then we just demangled an <unqualified-template-name>. */
1090 if (peek_char (dm) == 'I')
1092 /* A template name of the form std::<unqualified-name> is a
1093 substitution candidate. */
1094 if (is_std_substitution)
1095 RETURN_IF_ERROR (substitution_add (dm, start, 0));
1096 /* Demangle the <template-args> here. */
1097 RETURN_IF_ERROR (demangle_template_args (dm));
1098 *encode_return_type = !suppress_return_type;
1100 else
1101 *encode_return_type = 0;
1103 break;
1105 default:
1106 /* This is an <unscoped-name> or <unscoped-template-name>. */
1107 RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));
1109 /* If the <unqualified-name> is followed by template args, this
1110 is an <unscoped-template-name>. */
1111 if (peek_char (dm) == 'I')
1113 /* Add a substitution for the unqualified template name. */
1114 RETURN_IF_ERROR (substitution_add (dm, start, 0));
1116 RETURN_IF_ERROR (demangle_template_args (dm));
1117 *encode_return_type = !suppress_return_type;
1119 else
1120 *encode_return_type = 0;
1122 break;
1125 return STATUS_OK;
1128 /* Demangles and emits a <nested-name>.
1130 <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E */
1132 static status_t
1133 demangle_nested_name (dm, encode_return_type)
1134 demangling_t dm;
1135 int *encode_return_type;
1137 char peek;
1139 DEMANGLE_TRACE ("nested-name", dm);
1141 RETURN_IF_ERROR (demangle_char (dm, 'N'));
1143 peek = peek_char (dm);
1144 if (peek == 'r' || peek == 'V' || peek == 'K')
1146 dyn_string_t cv_qualifiers;
1147 status_t status;
1149 /* Snarf up CV qualifiers. */
1150 cv_qualifiers = dyn_string_new (24);
1151 if (cv_qualifiers == NULL)
1152 return STATUS_ALLOCATION_FAILED;
1153 demangle_CV_qualifiers (dm, cv_qualifiers);
1155 /* Emit them, preceded by a space. */
1156 status = result_add_char (dm, ' ');
1157 if (STATUS_NO_ERROR (status))
1158 status = result_add_string (dm, cv_qualifiers);
1159 /* The CV qualifiers that occur in a <nested-name> will be
1160 qualifiers for member functions. These are placed at the end
1161 of the function. Therefore, shift the caret to the left by
1162 the length of the qualifiers, so other text is inserted
1163 before them and they stay at the end. */
1164 result_shift_caret (dm, -dyn_string_length (cv_qualifiers) - 1);
1165 /* Clean up. */
1166 dyn_string_delete (cv_qualifiers);
1167 RETURN_IF_ERROR (status);
1170 RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
1171 /* No need to demangle the final <unqualified-name>; demangle_prefix
1172 will handle it. */
1173 RETURN_IF_ERROR (demangle_char (dm, 'E'));
1175 return STATUS_OK;
1178 /* Demangles and emits a <prefix>.
1180 <prefix> ::= <prefix> <unqualified-name>
1181 ::= <template-prefix> <template-args>
1182 ::= # empty
1183 ::= <substitution>
1185 <template-prefix> ::= <prefix>
1186 ::= <substitution> */
1188 static status_t
1189 demangle_prefix (dm, encode_return_type)
1190 demangling_t dm;
1191 int *encode_return_type;
1193 int start = substitution_start (dm);
1194 int nested = 0;
1196 /* ENCODE_RETURN_TYPE is updated as we decend the nesting chain.
1197 After <template-args>, it is set to non-zero; after everything
1198 else it is set to zero. */
1200 /* Generally, the return type is encoded if the function is a
1201 template-id, and suppressed otherwise. There are a few cases,
1202 though, in which the return type is not encoded even for a
1203 templated function. In these cases, this flag is set. */
1204 int suppress_return_type = 0;
1206 DEMANGLE_TRACE ("prefix", dm);
1208 while (1)
1210 char peek;
1212 if (end_of_name_p (dm))
1213 return "Unexpected end of name in <compound-name>.";
1215 peek = peek_char (dm);
1217 /* We'll initialize suppress_return_type to false, and set it to true
1218 if we end up demangling a constructor name. However, make
1219 sure we're not actually about to demangle template arguments
1220 -- if so, this is the <template-args> following a
1221 <template-prefix>, so we'll want the previous flag value
1222 around. */
1223 if (peek != 'I')
1224 suppress_return_type = 0;
1226 if (IS_DIGIT ((unsigned char) peek)
1227 || (peek >= 'a' && peek <= 'z')
1228 || peek == 'C' || peek == 'D'
1229 || peek == 'S')
1231 /* We have another level of scope qualification. */
1232 if (nested)
1233 RETURN_IF_ERROR (result_add (dm, NAMESPACE_SEPARATOR));
1234 else
1235 nested = 1;
1237 if (peek == 'S')
1238 /* The substitution determines whether this is a
1239 template-id. */
1240 RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
1241 else
1243 /* It's just a name. */
1244 RETURN_IF_ERROR
1245 (demangle_unqualified_name (dm, &suppress_return_type));
1246 *encode_return_type = 0;
1249 else if (peek == 'Z')
1250 RETURN_IF_ERROR (demangle_local_name (dm));
1251 else if (peek == 'I')
1253 RETURN_IF_ERROR (demangle_template_args (dm));
1255 /* Now we want to indicate to the caller that we've
1256 demangled template arguments, thus the prefix was a
1257 <template-prefix>. That's so that the caller knows to
1258 demangle the function's return type, if this turns out to
1259 be a function name. But, if it's a member template
1260 constructor or a templated conversion operator, report it
1261 as untemplated. Those never get encoded return types. */
1262 *encode_return_type = !suppress_return_type;
1264 else if (peek == 'E')
1265 /* All done. */
1266 return STATUS_OK;
1267 else
1268 return "Unexpected character in <compound-name>.";
1270 if (peek != 'S'
1271 && peek_char (dm) != 'E')
1272 /* Add a new substitution for the prefix thus far. */
1273 RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));
1277 /* Demangles and emits an <unqualified-name>. If this
1278 <unqualified-name> is for a special function type that should never
1279 have its return type encoded (particularly, a constructor or
1280 conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise,
1281 it is set to zero.
1283 <unqualified-name> ::= <operator-name>
1284 ::= <special-name>
1285 ::= <source-name> */
1287 static status_t
1288 demangle_unqualified_name (dm, suppress_return_type)
1289 demangling_t dm;
1290 int *suppress_return_type;
1292 char peek = peek_char (dm);
1294 DEMANGLE_TRACE ("unqualified-name", dm);
1296 /* By default, don't force suppression of the return type (though
1297 non-template functions still don't get a return type encoded). */
1298 *suppress_return_type = 0;
1300 if (IS_DIGIT ((unsigned char) peek))
1301 RETURN_IF_ERROR (demangle_source_name (dm));
1302 else if (peek >= 'a' && peek <= 'z')
1304 int num_args;
1306 /* Conversion operators never have a return type encoded. */
1307 if (peek == 'c' && peek_char_next (dm) == 'v')
1308 *suppress_return_type = 1;
1310 RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args));
1312 else if (peek == 'C' || peek == 'D')
1314 /* Constructors never have a return type encoded. */
1315 if (peek == 'C')
1316 *suppress_return_type = 1;
1318 RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
1320 else
1321 return "Unexpected character in <unqualified-name>.";
1323 return STATUS_OK;
1326 /* Demangles and emits <source-name>.
1328 <source-name> ::= <length number> <identifier> */
1330 static status_t
1331 demangle_source_name (dm)
1332 demangling_t dm;
1334 int length;
1336 DEMANGLE_TRACE ("source-name", dm);
1338 /* Decode the length of the identifier. */
1339 RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0));
1340 if (length == 0)
1341 return "Zero length in <source-name>.";
1343 /* Now the identifier itself. It's placed into last_source_name,
1344 where it can be used to build a constructor or destructor name. */
1345 RETURN_IF_ERROR (demangle_identifier (dm, length,
1346 dm->last_source_name));
1348 /* Emit it. */
1349 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
1351 return STATUS_OK;
1354 /* Demangles a number, either a <number> or a <positive-number> at the
1355 current position, consuming all consecutive digit characters. Sets
1356 *VALUE to the resulting numberand returns STATUS_OK. The number is
1357 interpreted as BASE, which must be either 10 or 36. If IS_SIGNED
1358 is non-zero, negative numbers -- prefixed with `n' -- are accepted.
1360 <number> ::= [n] <positive-number>
1362 <positive-number> ::= <decimal integer> */
1364 static status_t
1365 demangle_number (dm, value, base, is_signed)
1366 demangling_t dm;
1367 int *value;
1368 int base;
1369 int is_signed;
1371 dyn_string_t number = dyn_string_new (10);
1373 DEMANGLE_TRACE ("number", dm);
1375 if (number == NULL)
1376 return STATUS_ALLOCATION_FAILED;
1378 demangle_number_literally (dm, number, base, is_signed);
1379 *value = strtol (dyn_string_buf (number), NULL, base);
1380 dyn_string_delete (number);
1382 return STATUS_OK;
1385 /* Demangles a number at the current position. The digits (and minus
1386 sign, if present) that make up the number are appended to STR.
1387 Only base-BASE digits are accepted; BASE must be either 10 or 36.
1388 If IS_SIGNED, negative numbers -- prefixed with `n' -- are
1389 accepted. Does not consume a trailing underscore or other
1390 terminating character. */
1392 static status_t
1393 demangle_number_literally (dm, str, base, is_signed)
1394 demangling_t dm;
1395 dyn_string_t str;
1396 int base;
1397 int is_signed;
1399 DEMANGLE_TRACE ("number*", dm);
1401 if (base != 10 && base != 36)
1402 return STATUS_INTERNAL_ERROR;
1404 /* An `n' denotes a negative number. */
1405 if (is_signed && peek_char (dm) == 'n')
1407 /* Skip past the n. */
1408 advance_char (dm);
1409 /* The normal way to write a negative number is with a minus
1410 sign. */
1411 if (!dyn_string_append_char (str, '-'))
1412 return STATUS_ALLOCATION_FAILED;
1415 /* Loop until we hit a non-digit. */
1416 while (1)
1418 char peek = peek_char (dm);
1419 if (IS_DIGIT ((unsigned char) peek)
1420 || (base == 36 && peek >= 'A' && peek <= 'Z'))
1422 /* Accumulate digits. */
1423 if (!dyn_string_append_char (str, next_char (dm)))
1424 return STATUS_ALLOCATION_FAILED;
1426 else
1427 /* Not a digit? All done. */
1428 break;
1431 return STATUS_OK;
1434 /* Demangles an identifier at the current position of LENGTH
1435 characters and places it in IDENTIFIER. */
1437 static status_t
1438 demangle_identifier (dm, length, identifier)
1439 demangling_t dm;
1440 int length;
1441 dyn_string_t identifier;
1443 DEMANGLE_TRACE ("identifier", dm);
1445 dyn_string_clear (identifier);
1446 if (!dyn_string_resize (identifier, length))
1447 return STATUS_ALLOCATION_FAILED;
1449 while (length-- > 0)
1451 if (end_of_name_p (dm))
1452 return "Unexpected end of name in <identifier>.";
1453 if (!dyn_string_append_char (identifier, next_char (dm)))
1454 return STATUS_ALLOCATION_FAILED;
1457 /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'
1458 followed by the source file name and some random characters.
1459 Unless we're in strict mode, decipher these names appropriately. */
1460 if (!flag_strict)
1462 char *name = dyn_string_buf (identifier);
1463 int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
1465 /* Compare the first, fixed part. */
1466 if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
1468 name += prefix_length;
1469 /* The next character might be a period, an underscore, or
1470 dollar sign, depending on the target architecture's
1471 assembler's capabilities. After that comes an `N'. */
1472 if ((*name == '.' || *name == '_' || *name == '$')
1473 && *(name + 1) == 'N')
1474 /* This looks like the anonymous namespace identifier.
1475 Replace it with something comprehensible. */
1476 dyn_string_copy_cstr (identifier, "(anonymous namespace)");
1480 return STATUS_OK;
1483 /* Demangles and emits an <operator-name>. If SHORT_NAME is non-zero,
1484 the short form is emitted; otherwise the full source form
1485 (`operator +' etc.) is emitted. *NUM_ARGS is set to the number of
1486 operands that the operator takes.
1488 <operator-name>
1489 ::= nw # new
1490 ::= na # new[]
1491 ::= dl # delete
1492 ::= da # delete[]
1493 ::= ps # + (unary)
1494 ::= ng # - (unary)
1495 ::= ad # & (unary)
1496 ::= de # * (unary)
1497 ::= co # ~
1498 ::= pl # +
1499 ::= mi # -
1500 ::= ml # *
1501 ::= dv # /
1502 ::= rm # %
1503 ::= an # &
1504 ::= or # |
1505 ::= eo # ^
1506 ::= aS # =
1507 ::= pL # +=
1508 ::= mI # -=
1509 ::= mL # *=
1510 ::= dV # /=
1511 ::= rM # %=
1512 ::= aN # &=
1513 ::= oR # |=
1514 ::= eO # ^=
1515 ::= ls # <<
1516 ::= rs # >>
1517 ::= lS # <<=
1518 ::= rS # >>=
1519 ::= eq # ==
1520 ::= ne # !=
1521 ::= lt # <
1522 ::= gt # >
1523 ::= le # <=
1524 ::= ge # >=
1525 ::= nt # !
1526 ::= aa # &&
1527 ::= oo # ||
1528 ::= pp # ++
1529 ::= mm # --
1530 ::= cm # ,
1531 ::= pm # ->*
1532 ::= pt # ->
1533 ::= cl # ()
1534 ::= ix # []
1535 ::= qu # ?
1536 ::= sz # sizeof
1537 ::= cv <type> # cast
1538 ::= v [0-9] <source-name> # vendor extended operator */
1540 static status_t
1541 demangle_operator_name (dm, short_name, num_args)
1542 demangling_t dm;
1543 int short_name;
1544 int *num_args;
1546 struct operator_code
1548 /* The mangled code for this operator. */
1549 const char *code;
1550 /* The source name of this operator. */
1551 const char *name;
1552 /* The number of arguments this operator takes. */
1553 int num_args;
1556 static const struct operator_code operators[] =
1558 { "aN", "&=" , 2 },
1559 { "aS", "=" , 2 },
1560 { "aa", "&&" , 2 },
1561 { "ad", "&" , 1 },
1562 { "an", "&" , 2 },
1563 { "cl", "()" , 0 },
1564 { "cm", "," , 2 },
1565 { "co", "~" , 1 },
1566 { "dV", "/=" , 2 },
1567 { "da", " delete[]", 1 },
1568 { "de", "*" , 1 },
1569 { "dl", " delete" , 1 },
1570 { "dv", "/" , 2 },
1571 { "eO", "^=" , 2 },
1572 { "eo", "^" , 2 },
1573 { "eq", "==" , 2 },
1574 { "ge", ">=" , 2 },
1575 { "gt", ">" , 2 },
1576 { "ix", "[]" , 2 },
1577 { "lS", "<<=" , 2 },
1578 { "le", "<=" , 2 },
1579 { "ls", "<<" , 2 },
1580 { "lt", "<" , 2 },
1581 { "mI", "-=" , 2 },
1582 { "mL", "*=" , 2 },
1583 { "mi", "-" , 2 },
1584 { "ml", "*" , 2 },
1585 { "mm", "--" , 1 },
1586 { "na", " new[]" , 1 },
1587 { "ne", "!=" , 2 },
1588 { "ng", "-" , 1 },
1589 { "nt", "!" , 1 },
1590 { "nw", " new" , 1 },
1591 { "oR", "|=" , 2 },
1592 { "oo", "||" , 2 },
1593 { "or", "|" , 2 },
1594 { "pL", "+=" , 2 },
1595 { "pl", "+" , 2 },
1596 { "pm", "->*" , 2 },
1597 { "pp", "++" , 1 },
1598 { "ps", "+" , 1 },
1599 { "pt", "->" , 2 },
1600 { "qu", "?" , 3 },
1601 { "rM", "%=" , 2 },
1602 { "rS", ">>=" , 2 },
1603 { "rm", "%" , 2 },
1604 { "rs", ">>" , 2 },
1605 { "sz", " sizeof" , 1 }
1608 const int num_operators =
1609 sizeof (operators) / sizeof (struct operator_code);
1611 int c0 = next_char (dm);
1612 int c1 = next_char (dm);
1613 const struct operator_code* p1 = operators;
1614 const struct operator_code* p2 = operators + num_operators;
1616 DEMANGLE_TRACE ("operator-name", dm);
1618 /* Is this a vendor-extended operator? */
1619 if (c0 == 'v' && IS_DIGIT (c1))
1621 RETURN_IF_ERROR (result_add (dm, "operator "));
1622 RETURN_IF_ERROR (demangle_source_name (dm));
1623 *num_args = 0;
1624 return STATUS_OK;
1627 /* Is this a conversion operator? */
1628 if (c0 == 'c' && c1 == 'v')
1630 RETURN_IF_ERROR (result_add (dm, "operator "));
1631 /* Demangle the converted-to type. */
1632 RETURN_IF_ERROR (demangle_type (dm));
1633 *num_args = 0;
1634 return STATUS_OK;
1637 /* Perform a binary search for the operator code. */
1638 while (1)
1640 const struct operator_code* p = p1 + (p2 - p1) / 2;
1641 char match0 = p->code[0];
1642 char match1 = p->code[1];
1644 if (c0 == match0 && c1 == match1)
1645 /* Found it. */
1647 if (!short_name)
1648 RETURN_IF_ERROR (result_add (dm, "operator"));
1649 RETURN_IF_ERROR (result_add (dm, p->name));
1650 *num_args = p->num_args;
1652 return STATUS_OK;
1655 if (p == p1)
1656 /* Couldn't find it. */
1657 return "Unknown code in <operator-name>.";
1659 /* Try again. */
1660 if (c0 < match0 || (c0 == match0 && c1 < match1))
1661 p2 = p;
1662 else
1663 p1 = p;
1667 /* Demangles and omits an <nv-offset>.
1669 <nv-offset> ::= <offset number> # non-virtual base override */
1671 static status_t
1672 demangle_nv_offset (dm)
1673 demangling_t dm;
1675 dyn_string_t number;
1676 status_t status = STATUS_OK;
1678 DEMANGLE_TRACE ("h-offset", dm);
1680 /* Demangle the offset. */
1681 number = dyn_string_new (4);
1682 if (number == NULL)
1683 return STATUS_ALLOCATION_FAILED;
1684 demangle_number_literally (dm, number, 10, 1);
1686 /* Don't display the offset unless in verbose mode. */
1687 if (flag_verbose)
1689 status = result_add (dm, " [nv:");
1690 if (STATUS_NO_ERROR (status))
1691 status = result_add_string (dm, number);
1692 if (STATUS_NO_ERROR (status))
1693 status = result_add_char (dm, ']');
1696 /* Clean up. */
1697 dyn_string_delete (number);
1698 RETURN_IF_ERROR (status);
1699 return STATUS_OK;
1702 /* Demangles and emits a <v-offset>.
1704 <v-offset> ::= <offset number> _ <virtual offset number>
1705 # virtual base override, with vcall offset */
1707 static status_t
1708 demangle_v_offset (dm)
1709 demangling_t dm;
1711 dyn_string_t number;
1712 status_t status = STATUS_OK;
1714 DEMANGLE_TRACE ("v-offset", dm);
1716 /* Demangle the offset. */
1717 number = dyn_string_new (4);
1718 if (number == NULL)
1719 return STATUS_ALLOCATION_FAILED;
1720 demangle_number_literally (dm, number, 10, 1);
1722 /* Don't display the offset unless in verbose mode. */
1723 if (flag_verbose)
1725 status = result_add (dm, " [v:");
1726 if (STATUS_NO_ERROR (status))
1727 status = result_add_string (dm, number);
1728 if (STATUS_NO_ERROR (status))
1729 result_add_char (dm, ',');
1731 dyn_string_delete (number);
1732 RETURN_IF_ERROR (status);
1734 /* Demangle the separator. */
1735 RETURN_IF_ERROR (demangle_char (dm, '_'));
1737 /* Demangle the vcall offset. */
1738 number = dyn_string_new (4);
1739 if (number == NULL)
1740 return STATUS_ALLOCATION_FAILED;
1741 demangle_number_literally (dm, number, 10, 1);
1743 /* Don't display the vcall offset unless in verbose mode. */
1744 if (flag_verbose)
1746 status = result_add_string (dm, number);
1747 if (STATUS_NO_ERROR (status))
1748 status = result_add_char (dm, ']');
1750 dyn_string_delete (number);
1751 RETURN_IF_ERROR (status);
1753 return STATUS_OK;
1756 /* Demangles and emits a <call-offset>.
1758 <call-offset> ::= h <nv-offset> _
1759 ::= v <v-offset> _ */
1761 static status_t
1762 demangle_call_offset (dm)
1763 demangling_t dm;
1765 DEMANGLE_TRACE ("call-offset", dm);
1767 switch (peek_char (dm))
1769 case 'h':
1770 advance_char (dm);
1771 /* Demangle the offset. */
1772 RETURN_IF_ERROR (demangle_nv_offset (dm));
1773 /* Demangle the separator. */
1774 RETURN_IF_ERROR (demangle_char (dm, '_'));
1775 break;
1777 case 'v':
1778 advance_char (dm);
1779 /* Demangle the offset. */
1780 RETURN_IF_ERROR (demangle_v_offset (dm));
1781 /* Demangle the separator. */
1782 RETURN_IF_ERROR (demangle_char (dm, '_'));
1783 break;
1785 default:
1786 return "Unrecognized <call-offset>.";
1789 return STATUS_OK;
1792 /* Demangles and emits a <special-name>.
1794 <special-name> ::= GV <object name> # Guard variable
1795 ::= TV <type> # virtual table
1796 ::= TT <type> # VTT
1797 ::= TI <type> # typeinfo structure
1798 ::= TS <type> # typeinfo name
1800 Other relevant productions include thunks:
1802 <special-name> ::= T <call-offset> <base encoding>
1803 # base is the nominal target function of thunk
1805 <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
1806 # base is the nominal target function of thunk
1807 # first call-offset is 'this' adjustment
1808 # second call-offset is result adjustment
1810 where
1812 <call-offset> ::= h <nv-offset> _
1813 ::= v <v-offset> _
1815 Also demangles the special g++ manglings,
1817 <special-name> ::= TC <type> <offset number> _ <base type>
1818 # construction vtable
1819 ::= TF <type> # typeinfo function (old ABI only)
1820 ::= TJ <type> # java Class structure */
1822 static status_t
1823 demangle_special_name (dm)
1824 demangling_t dm;
1826 dyn_string_t number;
1827 int unused;
1828 char peek = peek_char (dm);
1830 DEMANGLE_TRACE ("special-name", dm);
1832 if (peek == 'G')
1834 /* A guard variable name. Consume the G. */
1835 advance_char (dm);
1836 RETURN_IF_ERROR (demangle_char (dm, 'V'));
1837 RETURN_IF_ERROR (result_add (dm, "guard variable for "));
1838 RETURN_IF_ERROR (demangle_name (dm, &unused));
1840 else if (peek == 'T')
1842 status_t status = STATUS_OK;
1844 /* Other C++ implementation miscellania. Consume the T. */
1845 advance_char (dm);
1847 switch (peek_char (dm))
1849 case 'V':
1850 /* Virtual table. */
1851 advance_char (dm);
1852 RETURN_IF_ERROR (result_add (dm, "vtable for "));
1853 RETURN_IF_ERROR (demangle_type (dm));
1854 break;
1856 case 'T':
1857 /* VTT structure. */
1858 advance_char (dm);
1859 RETURN_IF_ERROR (result_add (dm, "VTT for "));
1860 RETURN_IF_ERROR (demangle_type (dm));
1861 break;
1863 case 'I':
1864 /* Typeinfo structure. */
1865 advance_char (dm);
1866 RETURN_IF_ERROR (result_add (dm, "typeinfo for "));
1867 RETURN_IF_ERROR (demangle_type (dm));
1868 break;
1870 case 'F':
1871 /* Typeinfo function. Used only in old ABI with new mangling. */
1872 advance_char (dm);
1873 RETURN_IF_ERROR (result_add (dm, "typeinfo fn for "));
1874 RETURN_IF_ERROR (demangle_type (dm));
1875 break;
1877 case 'S':
1878 /* Character string containing type name, used in typeinfo. */
1879 advance_char (dm);
1880 RETURN_IF_ERROR (result_add (dm, "typeinfo name for "));
1881 RETURN_IF_ERROR (demangle_type (dm));
1882 break;
1884 case 'J':
1885 /* The java Class variable corresponding to a C++ class. */
1886 advance_char (dm);
1887 RETURN_IF_ERROR (result_add (dm, "java Class for "));
1888 RETURN_IF_ERROR (demangle_type (dm));
1889 break;
1891 case 'h':
1892 /* Non-virtual thunk. */
1893 advance_char (dm);
1894 RETURN_IF_ERROR (result_add (dm, "non-virtual thunk"));
1895 RETURN_IF_ERROR (demangle_nv_offset (dm));
1896 /* Demangle the separator. */
1897 RETURN_IF_ERROR (demangle_char (dm, '_'));
1898 /* Demangle and emit the target name and function type. */
1899 RETURN_IF_ERROR (result_add (dm, " to "));
1900 RETURN_IF_ERROR (demangle_encoding (dm));
1901 break;
1903 case 'v':
1904 /* Virtual thunk. */
1905 advance_char (dm);
1906 RETURN_IF_ERROR (result_add (dm, "virtual thunk"));
1907 RETURN_IF_ERROR (demangle_v_offset (dm));
1908 /* Demangle the separator. */
1909 RETURN_IF_ERROR (demangle_char (dm, '_'));
1910 /* Demangle and emit the target function. */
1911 RETURN_IF_ERROR (result_add (dm, " to "));
1912 RETURN_IF_ERROR (demangle_encoding (dm));
1913 break;
1915 case 'c':
1916 /* Covariant return thunk. */
1917 advance_char (dm);
1918 RETURN_IF_ERROR (result_add (dm, "covariant return thunk"));
1919 RETURN_IF_ERROR (demangle_call_offset (dm));
1920 RETURN_IF_ERROR (demangle_call_offset (dm));
1921 /* Demangle and emit the target function. */
1922 RETURN_IF_ERROR (result_add (dm, " to "));
1923 RETURN_IF_ERROR (demangle_encoding (dm));
1924 break;
1926 case 'C':
1927 /* TC is a special g++ mangling for a construction vtable. */
1928 if (!flag_strict)
1930 dyn_string_t derived_type;
1932 advance_char (dm);
1933 RETURN_IF_ERROR (result_add (dm, "construction vtable for "));
1935 /* Demangle the derived type off to the side. */
1936 RETURN_IF_ERROR (result_push (dm));
1937 RETURN_IF_ERROR (demangle_type (dm));
1938 derived_type = (dyn_string_t) result_pop (dm);
1940 /* Demangle the offset. */
1941 number = dyn_string_new (4);
1942 if (number == NULL)
1944 dyn_string_delete (derived_type);
1945 return STATUS_ALLOCATION_FAILED;
1947 demangle_number_literally (dm, number, 10, 1);
1948 /* Demangle the underscore separator. */
1949 status = demangle_char (dm, '_');
1951 /* Demangle the base type. */
1952 if (STATUS_NO_ERROR (status))
1953 status = demangle_type (dm);
1955 /* Emit the derived type. */
1956 if (STATUS_NO_ERROR (status))
1957 status = result_add (dm, "-in-");
1958 if (STATUS_NO_ERROR (status))
1959 status = result_add_string (dm, derived_type);
1960 dyn_string_delete (derived_type);
1962 /* Don't display the offset unless in verbose mode. */
1963 if (flag_verbose)
1965 status = result_add_char (dm, ' ');
1966 if (STATUS_NO_ERROR (status))
1967 result_add_string (dm, number);
1969 dyn_string_delete (number);
1970 RETURN_IF_ERROR (status);
1971 break;
1973 /* If flag_strict, fall through. */
1975 default:
1976 return "Unrecognized <special-name>.";
1979 else
1980 return STATUS_ERROR;
1982 return STATUS_OK;
1985 /* Demangles and emits a <ctor-dtor-name>.
1987 <ctor-dtor-name>
1988 ::= C1 # complete object (in-charge) ctor
1989 ::= C2 # base object (not-in-charge) ctor
1990 ::= C3 # complete object (in-charge) allocating ctor
1991 ::= D0 # deleting (in-charge) dtor
1992 ::= D1 # complete object (in-charge) dtor
1993 ::= D2 # base object (not-in-charge) dtor */
1995 static status_t
1996 demangle_ctor_dtor_name (dm)
1997 demangling_t dm;
1999 static const char *const ctor_flavors[] =
2001 "in-charge",
2002 "not-in-charge",
2003 "allocating"
2005 static const char *const dtor_flavors[] =
2007 "in-charge deleting",
2008 "in-charge",
2009 "not-in-charge"
2012 int flavor;
2013 char peek = peek_char (dm);
2015 DEMANGLE_TRACE ("ctor-dtor-name", dm);
2017 if (peek == 'C')
2019 /* A constructor name. Consume the C. */
2020 advance_char (dm);
2021 if (peek_char (dm) < '1' || peek_char (dm) > '3')
2022 return "Unrecognized constructor.";
2023 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
2024 /* Print the flavor of the constructor if in verbose mode. */
2025 flavor = next_char (dm) - '1';
2026 if (flag_verbose)
2028 RETURN_IF_ERROR (result_add (dm, "["));
2029 RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor]));
2030 RETURN_IF_ERROR (result_add_char (dm, ']'));
2033 else if (peek == 'D')
2035 /* A destructor name. Consume the D. */
2036 advance_char (dm);
2037 if (peek_char (dm) < '0' || peek_char (dm) > '2')
2038 return "Unrecognized destructor.";
2039 RETURN_IF_ERROR (result_add_char (dm, '~'));
2040 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
2041 /* Print the flavor of the destructor if in verbose mode. */
2042 flavor = next_char (dm) - '0';
2043 if (flag_verbose)
2045 RETURN_IF_ERROR (result_add (dm, " ["));
2046 RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor]));
2047 RETURN_IF_ERROR (result_add_char (dm, ']'));
2050 else
2051 return STATUS_ERROR;
2053 return STATUS_OK;
2056 /* Handle pointer, reference, and pointer-to-member cases for
2057 demangle_type. All consecutive `P's, `R's, and 'M's are joined to
2058 build a pointer/reference type. We snarf all these, plus the
2059 following <type>, all at once since we need to know whether we have
2060 a pointer to data or pointer to function to construct the right
2061 output syntax. C++'s pointer syntax is hairy.
2063 This function adds substitution candidates for every nested
2064 pointer/reference type it processes, including the outermost, final
2065 type, assuming the substitution starts at SUBSTITUTION_START in the
2066 demangling result. For example, if this function demangles
2067 `PP3Foo', it will add a substitution for `Foo', `Foo*', and
2068 `Foo**', in that order.
2070 *INSERT_POS is a quantity used internally, when this function calls
2071 itself recursively, to figure out where to insert pointer
2072 punctuation on the way up. On entry to this function, INSERT_POS
2073 should point to a temporary value, but that value need not be
2074 initialized.
2076 <type> ::= P <type>
2077 ::= R <type>
2078 ::= <pointer-to-member-type>
2080 <pointer-to-member-type> ::= M </class/ type> </member/ type> */
2082 static status_t
2083 demangle_type_ptr (dm, insert_pos, substitution_start)
2084 demangling_t dm;
2085 int *insert_pos;
2086 int substitution_start;
2088 status_t status;
2089 int is_substitution_candidate = 1;
2091 DEMANGLE_TRACE ("type*", dm);
2093 /* Scan forward, collecting pointers and references into symbols,
2094 until we hit something else. Then emit the type. */
2095 switch (peek_char (dm))
2097 case 'P':
2098 /* A pointer. Snarf the `P'. */
2099 advance_char (dm);
2100 /* Demangle the underlying type. */
2101 RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
2102 substitution_start));
2103 /* Insert an asterisk where we're told to; it doesn't
2104 necessarily go at the end. If we're doing Java style output,
2105 there is no pointer symbol. */
2106 if (dm->style != DMGL_JAVA)
2107 RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
2108 /* The next (outermost) pointer or reference character should go
2109 after this one. */
2110 ++(*insert_pos);
2111 break;
2113 case 'R':
2114 /* A reference. Snarf the `R'. */
2115 advance_char (dm);
2116 /* Demangle the underlying type. */
2117 RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
2118 substitution_start));
2119 /* Insert an ampersand where we're told to; it doesn't
2120 necessarily go at the end. */
2121 RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
2122 /* The next (outermost) pointer or reference character should go
2123 after this one. */
2124 ++(*insert_pos);
2125 break;
2127 case 'M':
2129 /* A pointer-to-member. */
2130 dyn_string_t class_type;
2132 /* Eat the 'M'. */
2133 advance_char (dm);
2135 /* Capture the type of which this is a pointer-to-member. */
2136 RETURN_IF_ERROR (result_push (dm));
2137 RETURN_IF_ERROR (demangle_type (dm));
2138 class_type = (dyn_string_t) result_pop (dm);
2140 if (peek_char (dm) == 'F')
2141 /* A pointer-to-member function. We want output along the
2142 lines of `void (C::*) (int, int)'. Demangle the function
2143 type, which would in this case give `void () (int, int)'
2144 and set *insert_pos to the spot between the first
2145 parentheses. */
2146 status = demangle_type_ptr (dm, insert_pos, substitution_start);
2147 else if (peek_char (dm) == 'A')
2148 /* A pointer-to-member array variable. We want output that
2149 looks like `int (Klass::*) [10]'. Demangle the array type
2150 as `int () [10]', and set *insert_pos to the spot between
2151 the parentheses. */
2152 status = demangle_array_type (dm, insert_pos);
2153 else
2155 /* A pointer-to-member variable. Demangle the type of the
2156 pointed-to member. */
2157 status = demangle_type (dm);
2158 /* Make it pretty. */
2159 if (STATUS_NO_ERROR (status)
2160 && !result_previous_char_is_space (dm))
2161 status = result_add_char (dm, ' ');
2162 /* The pointer-to-member notation (e.g. `C::*') follows the
2163 member's type. */
2164 *insert_pos = result_caret_pos (dm);
2167 /* Build the pointer-to-member notation. */
2168 if (STATUS_NO_ERROR (status))
2169 status = result_insert (dm, *insert_pos, "::*");
2170 if (STATUS_NO_ERROR (status))
2171 status = result_insert_string (dm, *insert_pos, class_type);
2172 /* There may be additional levels of (pointer or reference)
2173 indirection in this type. If so, the `*' and `&' should be
2174 added after the pointer-to-member notation (e.g. `C::*&' for
2175 a reference to a pointer-to-member of class C). */
2176 *insert_pos += dyn_string_length (class_type) + 3;
2178 /* Clean up. */
2179 dyn_string_delete (class_type);
2181 RETURN_IF_ERROR (status);
2183 break;
2185 case 'F':
2186 /* Ooh, tricky, a pointer-to-function. When we demangle the
2187 function type, the return type should go at the very
2188 beginning. */
2189 *insert_pos = result_caret_pos (dm);
2190 /* The parentheses indicate this is a function pointer or
2191 reference type. */
2192 RETURN_IF_ERROR (result_add (dm, "()"));
2193 /* Now demangle the function type. The return type will be
2194 inserted before the `()', and the argument list will go after
2195 it. */
2196 RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
2197 /* We should now have something along the lines of
2198 `void () (int, int)'. The pointer or reference characters
2199 have to inside the first set of parentheses. *insert_pos has
2200 already been updated to point past the end of the return
2201 type. Move it one character over so it points inside the
2202 `()'. */
2203 ++(*insert_pos);
2204 break;
2206 case 'A':
2207 /* An array pointer or reference. demangle_array_type will figure
2208 out where the asterisks and ampersands go. */
2209 RETURN_IF_ERROR (demangle_array_type (dm, insert_pos));
2210 break;
2212 default:
2213 /* No more pointer or reference tokens; this is therefore a
2214 pointer to data. Finish up by demangling the underlying
2215 type. */
2216 RETURN_IF_ERROR (demangle_type (dm));
2217 /* The pointer or reference characters follow the underlying
2218 type, as in `int*&'. */
2219 *insert_pos = result_caret_pos (dm);
2220 /* Because of the production <type> ::= <substitution>,
2221 demangle_type will already have added the underlying type as
2222 a substitution candidate. Don't do it again. */
2223 is_substitution_candidate = 0;
2224 break;
2227 if (is_substitution_candidate)
2228 RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
2230 return STATUS_OK;
2233 /* Demangles and emits a <type>.
2235 <type> ::= <builtin-type>
2236 ::= <function-type>
2237 ::= <class-enum-type>
2238 ::= <array-type>
2239 ::= <pointer-to-member-type>
2240 ::= <template-param>
2241 ::= <template-template-param> <template-args>
2242 ::= <CV-qualifiers> <type>
2243 ::= P <type> # pointer-to
2244 ::= R <type> # reference-to
2245 ::= C <type> # complex pair (C 2000)
2246 ::= G <type> # imaginary (C 2000)
2247 ::= U <source-name> <type> # vendor extended type qualifier
2248 ::= <substitution> */
2250 static status_t
2251 demangle_type (dm)
2252 demangling_t dm;
2254 int start = substitution_start (dm);
2255 char peek = peek_char (dm);
2256 char peek_next;
2257 int encode_return_type = 0;
2258 template_arg_list_t old_arg_list = current_template_arg_list (dm);
2259 int insert_pos;
2261 /* A <type> can be a <substitution>; therefore, this <type> is a
2262 substitution candidate unless a special condition holds (see
2263 below). */
2264 int is_substitution_candidate = 1;
2266 DEMANGLE_TRACE ("type", dm);
2268 /* A <class-enum-type> can start with a digit (a <source-name>), an
2269 N (a <nested-name>), or a Z (a <local-name>). */
2270 if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
2271 RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type));
2272 /* Lower-case letters begin <builtin-type>s, except for `r', which
2273 denotes restrict. */
2274 else if (peek >= 'a' && peek <= 'z' && peek != 'r')
2276 RETURN_IF_ERROR (demangle_builtin_type (dm));
2277 /* Built-in types are not substitution candidates. */
2278 is_substitution_candidate = 0;
2280 else
2281 switch (peek)
2283 case 'r':
2284 case 'V':
2285 case 'K':
2286 /* CV-qualifiers (including restrict). We have to demangle
2287 them off to the side, since C++ syntax puts them in a funny
2288 place for qualified pointer and reference types. */
2290 status_t status;
2291 dyn_string_t cv_qualifiers = dyn_string_new (24);
2292 int old_caret_position = result_get_caret (dm);
2294 if (cv_qualifiers == NULL)
2295 return STATUS_ALLOCATION_FAILED;
2297 /* Decode all adjacent CV qualifiers. */
2298 demangle_CV_qualifiers (dm, cv_qualifiers);
2299 /* Emit them, and shift the caret left so that the
2300 underlying type will be emitted before the qualifiers. */
2301 status = result_add_string (dm, cv_qualifiers);
2302 result_shift_caret (dm, -dyn_string_length (cv_qualifiers));
2303 /* Clean up. */
2304 dyn_string_delete (cv_qualifiers);
2305 RETURN_IF_ERROR (status);
2306 /* Also prepend a blank, if needed. */
2307 RETURN_IF_ERROR (result_add_char (dm, ' '));
2308 result_shift_caret (dm, -1);
2310 /* Demangle the underlying type. It will be emitted before
2311 the CV qualifiers, since we moved the caret. */
2312 RETURN_IF_ERROR (demangle_type (dm));
2314 /* Put the caret back where it was previously. */
2315 result_set_caret (dm, old_caret_position);
2317 break;
2319 case 'F':
2320 return "Non-pointer or -reference function type.";
2322 case 'A':
2323 RETURN_IF_ERROR (demangle_array_type (dm, NULL));
2324 break;
2326 case 'T':
2327 /* It's either a <template-param> or a
2328 <template-template-param>. In either case, demangle the
2329 `T' token first. */
2330 RETURN_IF_ERROR (demangle_template_param (dm));
2332 /* Check for a template argument list; if one is found, it's a
2333 <template-template-param> ::= <template-param>
2334 ::= <substitution> */
2335 if (peek_char (dm) == 'I')
2337 /* Add a substitution candidate. The template parameter
2338 `T' token is a substitution candidate by itself,
2339 without the template argument list. */
2340 RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
2342 /* Now demangle the template argument list. */
2343 RETURN_IF_ERROR (demangle_template_args (dm));
2344 /* The entire type, including the template template
2345 parameter and its argument list, will be added as a
2346 substitution candidate below. */
2349 break;
2351 case 'S':
2352 /* First check if this is a special substitution. If it is,
2353 this is a <class-enum-type>. Special substitutions have a
2354 letter following the `S'; other substitutions have a digit
2355 or underscore. */
2356 peek_next = peek_char_next (dm);
2357 if (IS_DIGIT (peek_next) || peek_next == '_')
2359 RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));
2361 /* The substituted name may have been a template name.
2362 Check if template arguments follow, and if so, demangle
2363 them. */
2364 if (peek_char (dm) == 'I')
2365 RETURN_IF_ERROR (demangle_template_args (dm));
2366 else
2367 /* A substitution token is not itself a substitution
2368 candidate. (However, if the substituted template is
2369 instantiated, the resulting type is.) */
2370 is_substitution_candidate = 0;
2372 else
2374 /* Now some trickiness. We have a special substitution
2375 here. Often, the special substitution provides the
2376 name of a template that's subsequently instantiated,
2377 for instance `SaIcE' => std::allocator<char>. In these
2378 cases we need to add a substitution candidate for the
2379 entire <class-enum-type> and thus don't want to clear
2380 the is_substitution_candidate flag.
2382 However, it's possible that what we have here is a
2383 substitution token representing an entire type, such as
2384 `Ss' => std::string. In this case, we mustn't add a
2385 new substitution candidate for this substitution token.
2386 To detect this case, remember where the start of the
2387 substitution token is. */
2388 const char *next = dm->next;
2389 /* Now demangle the <class-enum-type>. */
2390 RETURN_IF_ERROR
2391 (demangle_class_enum_type (dm, &encode_return_type));
2392 /* If all that was just demangled is the two-character
2393 special substitution token, supress the addition of a
2394 new candidate for it. */
2395 if (dm->next == next + 2)
2396 is_substitution_candidate = 0;
2399 break;
2401 case 'P':
2402 case 'R':
2403 case 'M':
2404 RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
2405 /* demangle_type_ptr adds all applicable substitution
2406 candidates. */
2407 is_substitution_candidate = 0;
2408 break;
2410 case 'C':
2411 /* A C99 complex type. */
2412 RETURN_IF_ERROR (result_add (dm, "complex "));
2413 advance_char (dm);
2414 RETURN_IF_ERROR (demangle_type (dm));
2415 break;
2417 case 'G':
2418 /* A C99 imaginary type. */
2419 RETURN_IF_ERROR (result_add (dm, "imaginary "));
2420 advance_char (dm);
2421 RETURN_IF_ERROR (demangle_type (dm));
2422 break;
2424 case 'U':
2425 /* Vendor-extended type qualifier. */
2426 advance_char (dm);
2427 RETURN_IF_ERROR (demangle_source_name (dm));
2428 RETURN_IF_ERROR (result_add_char (dm, ' '));
2429 RETURN_IF_ERROR (demangle_type (dm));
2430 break;
2432 default:
2433 return "Unexpected character in <type>.";
2436 if (is_substitution_candidate)
2437 /* Add a new substitution for the type. If this type was a
2438 <template-param>, pass its index since from the point of
2439 substitutions; a <template-param> token is a substitution
2440 candidate distinct from the type that is substituted for it. */
2441 RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
2443 /* Pop off template argument lists added during mangling of this
2444 type. */
2445 pop_to_template_arg_list (dm, old_arg_list);
2447 return STATUS_OK;
2450 /* C++ source names of builtin types, indexed by the mangled code
2451 letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc). */
2452 static const char *const builtin_type_names[26] =
2454 "signed char", /* a */
2455 "bool", /* b */
2456 "char", /* c */
2457 "double", /* d */
2458 "long double", /* e */
2459 "float", /* f */
2460 "__float128", /* g */
2461 "unsigned char", /* h */
2462 "int", /* i */
2463 "unsigned", /* j */
2464 NULL, /* k */
2465 "long", /* l */
2466 "unsigned long", /* m */
2467 "__int128", /* n */
2468 "unsigned __int128", /* o */
2469 NULL, /* p */
2470 NULL, /* q */
2471 NULL, /* r */
2472 "short", /* s */
2473 "unsigned short", /* t */
2474 NULL, /* u */
2475 "void", /* v */
2476 "wchar_t", /* w */
2477 "long long", /* x */
2478 "unsigned long long", /* y */
2479 "..." /* z */
2482 /* Java source names of builtin types. Types that arn't valid in Java
2483 are also included here - we don't fail if someone attempts to demangle a
2484 C++ symbol in Java style. */
2485 static const char *const java_builtin_type_names[26] =
2487 "signed char", /* a */
2488 "boolean", /* C++ "bool" */ /* b */
2489 "byte", /* C++ "char" */ /* c */
2490 "double", /* d */
2491 "long double", /* e */
2492 "float", /* f */
2493 "__float128", /* g */
2494 "unsigned char", /* h */
2495 "int", /* i */
2496 "unsigned", /* j */
2497 NULL, /* k */
2498 "long", /* l */
2499 "unsigned long", /* m */
2500 "__int128", /* n */
2501 "unsigned __int128", /* o */
2502 NULL, /* p */
2503 NULL, /* q */
2504 NULL, /* r */
2505 "short", /* s */
2506 "unsigned short", /* t */
2507 NULL, /* u */
2508 "void", /* v */
2509 "char", /* C++ "wchar_t" */ /* w */
2510 "long", /* C++ "long long" */ /* x */
2511 "unsigned long long", /* y */
2512 "..." /* z */
2515 /* Demangles and emits a <builtin-type>.
2517 <builtin-type> ::= v # void
2518 ::= w # wchar_t
2519 ::= b # bool
2520 ::= c # char
2521 ::= a # signed char
2522 ::= h # unsigned char
2523 ::= s # short
2524 ::= t # unsigned short
2525 ::= i # int
2526 ::= j # unsigned int
2527 ::= l # long
2528 ::= m # unsigned long
2529 ::= x # long long, __int64
2530 ::= y # unsigned long long, __int64
2531 ::= n # __int128
2532 ::= o # unsigned __int128
2533 ::= f # float
2534 ::= d # double
2535 ::= e # long double, __float80
2536 ::= g # __float128
2537 ::= z # ellipsis
2538 ::= u <source-name> # vendor extended type */
2540 static status_t
2541 demangle_builtin_type (dm)
2542 demangling_t dm;
2545 char code = peek_char (dm);
2547 DEMANGLE_TRACE ("builtin-type", dm);
2549 if (code == 'u')
2551 advance_char (dm);
2552 RETURN_IF_ERROR (demangle_source_name (dm));
2553 return STATUS_OK;
2555 else if (code >= 'a' && code <= 'z')
2557 const char *type_name;
2558 /* Java uses different names for some built-in types. */
2559 if (dm->style == DMGL_JAVA)
2560 type_name = java_builtin_type_names[code - 'a'];
2561 else
2562 type_name = builtin_type_names[code - 'a'];
2563 if (type_name == NULL)
2564 return "Unrecognized <builtin-type> code.";
2566 RETURN_IF_ERROR (result_add (dm, type_name));
2567 advance_char (dm);
2568 return STATUS_OK;
2570 else
2571 return "Non-alphabetic <builtin-type> code.";
2574 /* Demangles all consecutive CV-qualifiers (const, volatile, and
2575 restrict) at the current position. The qualifiers are appended to
2576 QUALIFIERS. Returns STATUS_OK. */
2578 static status_t
2579 demangle_CV_qualifiers (dm, qualifiers)
2580 demangling_t dm;
2581 dyn_string_t qualifiers;
2583 DEMANGLE_TRACE ("CV-qualifiers", dm);
2585 while (1)
2587 switch (peek_char (dm))
2589 case 'r':
2590 if (!dyn_string_append_space (qualifiers))
2591 return STATUS_ALLOCATION_FAILED;
2592 if (!dyn_string_append_cstr (qualifiers, "restrict"))
2593 return STATUS_ALLOCATION_FAILED;
2594 break;
2596 case 'V':
2597 if (!dyn_string_append_space (qualifiers))
2598 return STATUS_ALLOCATION_FAILED;
2599 if (!dyn_string_append_cstr (qualifiers, "volatile"))
2600 return STATUS_ALLOCATION_FAILED;
2601 break;
2603 case 'K':
2604 if (!dyn_string_append_space (qualifiers))
2605 return STATUS_ALLOCATION_FAILED;
2606 if (!dyn_string_append_cstr (qualifiers, "const"))
2607 return STATUS_ALLOCATION_FAILED;
2608 break;
2610 default:
2611 return STATUS_OK;
2614 advance_char (dm);
2618 /* Demangles and emits a <function-type>. *FUNCTION_NAME_POS is the
2619 position in the result string of the start of the function
2620 identifier, at which the function's return type will be inserted;
2621 *FUNCTION_NAME_POS is updated to position past the end of the
2622 function's return type.
2624 <function-type> ::= F [Y] <bare-function-type> E */
2626 static status_t
2627 demangle_function_type (dm, function_name_pos)
2628 demangling_t dm;
2629 int *function_name_pos;
2631 DEMANGLE_TRACE ("function-type", dm);
2632 RETURN_IF_ERROR (demangle_char (dm, 'F'));
2633 if (peek_char (dm) == 'Y')
2635 /* Indicate this function has C linkage if in verbose mode. */
2636 if (flag_verbose)
2637 RETURN_IF_ERROR (result_add (dm, " [extern \"C\"] "));
2638 advance_char (dm);
2640 RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
2641 RETURN_IF_ERROR (demangle_char (dm, 'E'));
2642 return STATUS_OK;
2645 /* Demangles and emits a <bare-function-type>. RETURN_TYPE_POS is the
2646 position in the result string at which the function return type
2647 should be inserted. If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the
2648 function's return type is assumed not to be encoded.
2650 <bare-function-type> ::= <signature type>+ */
2652 static status_t
2653 demangle_bare_function_type (dm, return_type_pos)
2654 demangling_t dm;
2655 int *return_type_pos;
2657 /* Sequence is the index of the current function parameter, counting
2658 from zero. The value -1 denotes the return type. */
2659 int sequence =
2660 (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);
2662 DEMANGLE_TRACE ("bare-function-type", dm);
2664 RETURN_IF_ERROR (result_add_char (dm, '('));
2665 while (!end_of_name_p (dm) && peek_char (dm) != 'E')
2667 if (sequence == -1)
2668 /* We're decoding the function's return type. */
2670 dyn_string_t return_type;
2671 status_t status = STATUS_OK;
2673 /* Decode the return type off to the side. */
2674 RETURN_IF_ERROR (result_push (dm));
2675 RETURN_IF_ERROR (demangle_type (dm));
2676 return_type = (dyn_string_t) result_pop (dm);
2678 /* Add a space to the end of the type. Insert the return
2679 type where we've been asked to. */
2680 if (!dyn_string_append_space (return_type))
2681 status = STATUS_ALLOCATION_FAILED;
2682 if (STATUS_NO_ERROR (status))
2684 if (!dyn_string_insert (result_string (dm), *return_type_pos,
2685 return_type))
2686 status = STATUS_ALLOCATION_FAILED;
2687 else
2688 *return_type_pos += dyn_string_length (return_type);
2691 dyn_string_delete (return_type);
2692 RETURN_IF_ERROR (status);
2694 else
2696 /* Skip `void' parameter types. One should only occur as
2697 the only type in a parameter list; in that case, we want
2698 to print `foo ()' instead of `foo (void)'. */
2699 if (peek_char (dm) == 'v')
2700 /* Consume the v. */
2701 advance_char (dm);
2702 else
2704 /* Separate parameter types by commas. */
2705 if (sequence > 0)
2706 RETURN_IF_ERROR (result_add (dm, ", "));
2707 /* Demangle the type. */
2708 RETURN_IF_ERROR (demangle_type (dm));
2712 ++sequence;
2714 RETURN_IF_ERROR (result_add_char (dm, ')'));
2716 /* We should have demangled at least one parameter type (which would
2717 be void, for a function that takes no parameters), plus the
2718 return type, if we were supposed to demangle that. */
2719 if (sequence == -1)
2720 return "Missing function return type.";
2721 else if (sequence == 0)
2722 return "Missing function parameter.";
2724 return STATUS_OK;
2727 /* Demangles and emits a <class-enum-type>. *ENCODE_RETURN_TYPE is set to
2728 non-zero if the type is a template-id, zero otherwise.
2730 <class-enum-type> ::= <name> */
2732 static status_t
2733 demangle_class_enum_type (dm, encode_return_type)
2734 demangling_t dm;
2735 int *encode_return_type;
2737 DEMANGLE_TRACE ("class-enum-type", dm);
2739 RETURN_IF_ERROR (demangle_name (dm, encode_return_type));
2740 return STATUS_OK;
2743 /* Demangles and emits an <array-type>.
2745 If PTR_INSERT_POS is not NULL, the array type is formatted as a
2746 pointer or reference to an array, except that asterisk and
2747 ampersand punctuation is omitted (since it's not know at this
2748 point). *PTR_INSERT_POS is set to the position in the demangled
2749 name at which this punctuation should be inserted. For example,
2750 `A10_i' is demangled to `int () [10]' and *PTR_INSERT_POS points
2751 between the parentheses.
2753 If PTR_INSERT_POS is NULL, the array type is assumed not to be
2754 pointer- or reference-qualified. Then, for example, `A10_i' is
2755 demangled simply as `int[10]'.
2757 <array-type> ::= A [<dimension number>] _ <element type>
2758 ::= A <dimension expression> _ <element type> */
2760 static status_t
2761 demangle_array_type (dm, ptr_insert_pos)
2762 demangling_t dm;
2763 int *ptr_insert_pos;
2765 status_t status = STATUS_OK;
2766 dyn_string_t array_size = NULL;
2767 char peek;
2769 DEMANGLE_TRACE ("array-type", dm);
2771 RETURN_IF_ERROR (demangle_char (dm, 'A'));
2773 /* Demangle the array size into array_size. */
2774 peek = peek_char (dm);
2775 if (peek == '_')
2776 /* Array bound is omitted. This is a C99-style VLA. */
2778 else if (IS_DIGIT (peek_char (dm)))
2780 /* It looks like a constant array bound. */
2781 array_size = dyn_string_new (10);
2782 if (array_size == NULL)
2783 return STATUS_ALLOCATION_FAILED;
2784 status = demangle_number_literally (dm, array_size, 10, 0);
2786 else
2788 /* Anything is must be an expression for a nont-constant array
2789 bound. This happens if the array type occurs in a template
2790 and the array bound references a template parameter. */
2791 RETURN_IF_ERROR (result_push (dm));
2792 RETURN_IF_ERROR (demangle_expression (dm));
2793 array_size = (dyn_string_t) result_pop (dm);
2795 /* array_size may have been allocated by now, so we can't use
2796 RETURN_IF_ERROR until it's been deallocated. */
2798 /* Demangle the base type of the array. */
2799 if (STATUS_NO_ERROR (status))
2800 status = demangle_char (dm, '_');
2801 if (STATUS_NO_ERROR (status))
2802 status = demangle_type (dm);
2804 if (ptr_insert_pos != NULL)
2806 /* This array is actually part of an pointer- or
2807 reference-to-array type. Format appropriately, except we
2808 don't know which and how much punctuation to use. */
2809 if (STATUS_NO_ERROR (status))
2810 status = result_add (dm, " () ");
2811 /* Let the caller know where to insert the punctuation. */
2812 *ptr_insert_pos = result_caret_pos (dm) - 2;
2815 /* Emit the array dimension syntax. */
2816 if (STATUS_NO_ERROR (status))
2817 status = result_add_char (dm, '[');
2818 if (STATUS_NO_ERROR (status) && array_size != NULL)
2819 status = result_add_string (dm, array_size);
2820 if (STATUS_NO_ERROR (status))
2821 status = result_add_char (dm, ']');
2822 if (array_size != NULL)
2823 dyn_string_delete (array_size);
2825 RETURN_IF_ERROR (status);
2827 return STATUS_OK;
2830 /* Demangles and emits a <template-param>.
2832 <template-param> ::= T_ # first template parameter
2833 ::= T <parameter-2 number> _ */
2835 static status_t
2836 demangle_template_param (dm)
2837 demangling_t dm;
2839 int parm_number;
2840 template_arg_list_t current_arg_list = current_template_arg_list (dm);
2841 string_list_t arg;
2843 DEMANGLE_TRACE ("template-param", dm);
2845 /* Make sure there is a template argmust list in which to look up
2846 this parameter reference. */
2847 if (current_arg_list == NULL)
2848 return "Template parameter outside of template.";
2850 RETURN_IF_ERROR (demangle_char (dm, 'T'));
2851 if (peek_char (dm) == '_')
2852 parm_number = 0;
2853 else
2855 RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));
2856 ++parm_number;
2858 RETURN_IF_ERROR (demangle_char (dm, '_'));
2860 arg = template_arg_list_get_arg (current_arg_list, parm_number);
2861 if (arg == NULL)
2862 /* parm_number exceeded the number of arguments in the current
2863 template argument list. */
2864 return "Template parameter number out of bounds.";
2865 RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
2867 return STATUS_OK;
2870 /* Demangles and emits a <template-args>.
2872 <template-args> ::= I <template-arg>+ E */
2874 static status_t
2875 demangle_template_args (dm)
2876 demangling_t dm;
2878 int first = 1;
2879 dyn_string_t old_last_source_name;
2880 template_arg_list_t arg_list = template_arg_list_new ();
2882 if (arg_list == NULL)
2883 return STATUS_ALLOCATION_FAILED;
2885 /* Preserve the most recently demangled source name. */
2886 old_last_source_name = dm->last_source_name;
2887 dm->last_source_name = dyn_string_new (0);
2889 DEMANGLE_TRACE ("template-args", dm);
2891 if (dm->last_source_name == NULL)
2892 return STATUS_ALLOCATION_FAILED;
2894 RETURN_IF_ERROR (demangle_char (dm, 'I'));
2895 RETURN_IF_ERROR (result_open_template_list (dm));
2898 string_list_t arg;
2900 if (first)
2901 first = 0;
2902 else
2903 RETURN_IF_ERROR (result_add (dm, ", "));
2905 /* Capture the template arg. */
2906 RETURN_IF_ERROR (result_push (dm));
2907 RETURN_IF_ERROR (demangle_template_arg (dm));
2908 arg = result_pop (dm);
2910 /* Emit it in the demangled name. */
2911 RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
2913 /* Save it for use in expanding <template-param>s. */
2914 template_arg_list_add_arg (arg_list, arg);
2916 while (peek_char (dm) != 'E');
2917 /* Append the '>'. */
2918 RETURN_IF_ERROR (result_close_template_list (dm));
2920 /* Consume the 'E'. */
2921 advance_char (dm);
2923 /* Restore the most recent demangled source name. */
2924 dyn_string_delete (dm->last_source_name);
2925 dm->last_source_name = old_last_source_name;
2927 /* Push the list onto the top of the stack of template argument
2928 lists, so that arguments from it are used from now on when
2929 expanding <template-param>s. */
2930 push_template_arg_list (dm, arg_list);
2932 return STATUS_OK;
2935 /* This function, which does not correspond to a production in the
2936 mangling spec, handles the `literal' production for both
2937 <template-arg> and <expr-primary>. It does not expect or consume
2938 the initial `L' or final `E'. The demangling is given by:
2940 <literal> ::= <type> </value/ number>
2942 and the emitted output is `(type)number'. */
2944 static status_t
2945 demangle_literal (dm)
2946 demangling_t dm;
2948 char peek = peek_char (dm);
2949 dyn_string_t value_string;
2950 status_t status;
2952 DEMANGLE_TRACE ("literal", dm);
2954 if (!flag_verbose && peek >= 'a' && peek <= 'z')
2956 /* If not in verbose mode and this is a builtin type, see if we
2957 can produce simpler numerical output. In particular, for
2958 integer types shorter than `long', just write the number
2959 without type information; for bools, write `true' or `false'.
2960 Other refinements could be made here too. */
2962 /* This constant string is used to map from <builtin-type> codes
2963 (26 letters of the alphabet) to codes that determine how the
2964 value will be displayed. The codes are:
2965 b: display as bool
2966 i: display as int
2967 l: display as long
2968 A space means the value will be represented using cast
2969 notation. */
2970 static const char *const code_map = "ibi iii ll ii i ";
2972 char code = code_map[peek - 'a'];
2973 /* FIXME: Implement demangling of floats and doubles. */
2974 if (code == 'u')
2975 return STATUS_UNIMPLEMENTED;
2976 if (code == 'b')
2978 /* It's a boolean. */
2979 char value;
2981 /* Consume the b. */
2982 advance_char (dm);
2983 /* Look at the next character. It should be 0 or 1,
2984 corresponding to false or true, respectively. */
2985 value = peek_char (dm);
2986 if (value == '0')
2987 RETURN_IF_ERROR (result_add (dm, "false"));
2988 else if (value == '1')
2989 RETURN_IF_ERROR (result_add (dm, "true"));
2990 else
2991 return "Unrecognized bool constant.";
2992 /* Consume the 0 or 1. */
2993 advance_char (dm);
2994 return STATUS_OK;
2996 else if (code == 'i' || code == 'l')
2998 /* It's an integer or long. */
3000 /* Consume the type character. */
3001 advance_char (dm);
3003 /* Demangle the number and write it out. */
3004 value_string = dyn_string_new (0);
3005 status = demangle_number_literally (dm, value_string, 10, 1);
3006 if (STATUS_NO_ERROR (status))
3007 status = result_add_string (dm, value_string);
3008 /* For long integers, append an l. */
3009 if (code == 'l' && STATUS_NO_ERROR (status))
3010 status = result_add_char (dm, code);
3011 dyn_string_delete (value_string);
3013 RETURN_IF_ERROR (status);
3014 return STATUS_OK;
3016 /* ...else code == ' ', so fall through to represent this
3017 literal's type explicitly using cast syntax. */
3020 RETURN_IF_ERROR (result_add_char (dm, '('));
3021 RETURN_IF_ERROR (demangle_type (dm));
3022 RETURN_IF_ERROR (result_add_char (dm, ')'));
3024 value_string = dyn_string_new (0);
3025 if (value_string == NULL)
3026 return STATUS_ALLOCATION_FAILED;
3028 status = demangle_number_literally (dm, value_string, 10, 1);
3029 if (STATUS_NO_ERROR (status))
3030 status = result_add_string (dm, value_string);
3031 dyn_string_delete (value_string);
3032 RETURN_IF_ERROR (status);
3034 return STATUS_OK;
3037 /* Demangles and emits a <template-arg>.
3039 <template-arg> ::= <type> # type
3040 ::= L <type> <value number> E # literal
3041 ::= LZ <encoding> E # external name
3042 ::= X <expression> E # expression */
3044 static status_t
3045 demangle_template_arg (dm)
3046 demangling_t dm;
3048 DEMANGLE_TRACE ("template-arg", dm);
3050 switch (peek_char (dm))
3052 case 'L':
3053 advance_char (dm);
3055 if (peek_char (dm) == 'Z')
3057 /* External name. */
3058 advance_char (dm);
3059 /* FIXME: Standard is contradictory here. */
3060 RETURN_IF_ERROR (demangle_encoding (dm));
3062 else
3063 RETURN_IF_ERROR (demangle_literal (dm));
3064 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3065 break;
3067 case 'X':
3068 /* Expression. */
3069 advance_char (dm);
3070 RETURN_IF_ERROR (demangle_expression (dm));
3071 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3072 break;
3074 default:
3075 RETURN_IF_ERROR (demangle_type (dm));
3076 break;
3079 return STATUS_OK;
3082 /* Demangles and emits an <expression>.
3084 <expression> ::= <unary operator-name> <expression>
3085 ::= <binary operator-name> <expression> <expression>
3086 ::= <expr-primary>
3087 ::= <scope-expression> */
3089 static status_t
3090 demangle_expression (dm)
3091 demangling_t dm;
3093 char peek = peek_char (dm);
3095 DEMANGLE_TRACE ("expression", dm);
3097 if (peek == 'L' || peek == 'T')
3098 RETURN_IF_ERROR (demangle_expr_primary (dm));
3099 else if (peek == 's' && peek_char_next (dm) == 'r')
3100 RETURN_IF_ERROR (demangle_scope_expression (dm));
3101 else
3102 /* An operator expression. */
3104 int num_args;
3105 status_t status = STATUS_OK;
3106 dyn_string_t operator_name;
3108 /* We have an operator name. Since we want to output binary
3109 operations in infix notation, capture the operator name
3110 first. */
3111 RETURN_IF_ERROR (result_push (dm));
3112 RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args));
3113 operator_name = (dyn_string_t) result_pop (dm);
3115 /* If it's binary, do an operand first. */
3116 if (num_args > 1)
3118 status = result_add_char (dm, '(');
3119 if (STATUS_NO_ERROR (status))
3120 status = demangle_expression (dm);
3121 if (STATUS_NO_ERROR (status))
3122 status = result_add_char (dm, ')');
3125 /* Emit the operator. */
3126 if (STATUS_NO_ERROR (status))
3127 status = result_add_string (dm, operator_name);
3128 dyn_string_delete (operator_name);
3129 RETURN_IF_ERROR (status);
3131 /* Emit its second (if binary) or only (if unary) operand. */
3132 RETURN_IF_ERROR (result_add_char (dm, '('));
3133 RETURN_IF_ERROR (demangle_expression (dm));
3134 RETURN_IF_ERROR (result_add_char (dm, ')'));
3136 /* The ternary operator takes a third operand. */
3137 if (num_args == 3)
3139 RETURN_IF_ERROR (result_add (dm, ":("));
3140 RETURN_IF_ERROR (demangle_expression (dm));
3141 RETURN_IF_ERROR (result_add_char (dm, ')'));
3145 return STATUS_OK;
3148 /* Demangles and emits a <scope-expression>.
3150 <scope-expression> ::= sr <qualifying type> <source-name>
3151 ::= sr <qualifying type> <encoding> */
3153 static status_t
3154 demangle_scope_expression (dm)
3155 demangling_t dm;
3157 RETURN_IF_ERROR (demangle_char (dm, 's'));
3158 RETURN_IF_ERROR (demangle_char (dm, 'r'));
3159 RETURN_IF_ERROR (demangle_type (dm));
3160 RETURN_IF_ERROR (result_add (dm, "::"));
3161 RETURN_IF_ERROR (demangle_encoding (dm));
3162 return STATUS_OK;
3165 /* Demangles and emits an <expr-primary>.
3167 <expr-primary> ::= <template-param>
3168 ::= L <type> <value number> E # literal
3169 ::= L <mangled-name> E # external name */
3171 static status_t
3172 demangle_expr_primary (dm)
3173 demangling_t dm;
3175 char peek = peek_char (dm);
3177 DEMANGLE_TRACE ("expr-primary", dm);
3179 if (peek == 'T')
3180 RETURN_IF_ERROR (demangle_template_param (dm));
3181 else if (peek == 'L')
3183 /* Consume the `L'. */
3184 advance_char (dm);
3185 peek = peek_char (dm);
3187 if (peek == '_')
3188 RETURN_IF_ERROR (demangle_mangled_name (dm));
3189 else
3190 RETURN_IF_ERROR (demangle_literal (dm));
3192 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3194 else
3195 return STATUS_ERROR;
3197 return STATUS_OK;
3200 /* Demangles and emits a <substitution>. Sets *TEMPLATE_P to non-zero
3201 if the substitution is the name of a template, zero otherwise.
3203 <substitution> ::= S <seq-id> _
3204 ::= S_
3206 ::= St # ::std::
3207 ::= Sa # ::std::allocator
3208 ::= Sb # ::std::basic_string
3209 ::= Ss # ::std::basic_string<char,
3210 ::std::char_traits<char>,
3211 ::std::allocator<char> >
3212 ::= Si # ::std::basic_istream<char,
3213 std::char_traits<char> >
3214 ::= So # ::std::basic_ostream<char,
3215 std::char_traits<char> >
3216 ::= Sd # ::std::basic_iostream<char,
3217 std::char_traits<char> >
3220 static status_t
3221 demangle_substitution (dm, template_p)
3222 demangling_t dm;
3223 int *template_p;
3225 int seq_id;
3226 int peek;
3227 dyn_string_t text;
3229 DEMANGLE_TRACE ("substitution", dm);
3231 RETURN_IF_ERROR (demangle_char (dm, 'S'));
3233 /* Scan the substitution sequence index. A missing number denotes
3234 the first index. */
3235 peek = peek_char (dm);
3236 if (peek == '_')
3237 seq_id = -1;
3238 /* If the following character is 0-9 or a capital letter, interpret
3239 the sequence up to the next underscore as a base-36 substitution
3240 index. */
3241 else if (IS_DIGIT ((unsigned char) peek)
3242 || (peek >= 'A' && peek <= 'Z'))
3243 RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));
3244 else
3246 const char *new_last_source_name = NULL;
3248 switch (peek)
3250 case 't':
3251 RETURN_IF_ERROR (result_add (dm, "std"));
3252 break;
3254 case 'a':
3255 RETURN_IF_ERROR (result_add (dm, "std::allocator"));
3256 new_last_source_name = "allocator";
3257 *template_p = 1;
3258 break;
3260 case 'b':
3261 RETURN_IF_ERROR (result_add (dm, "std::basic_string"));
3262 new_last_source_name = "basic_string";
3263 *template_p = 1;
3264 break;
3266 case 's':
3267 if (!flag_verbose)
3269 RETURN_IF_ERROR (result_add (dm, "std::string"));
3270 new_last_source_name = "string";
3272 else
3274 RETURN_IF_ERROR (result_add (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
3275 new_last_source_name = "basic_string";
3277 *template_p = 0;
3278 break;
3280 case 'i':
3281 if (!flag_verbose)
3283 RETURN_IF_ERROR (result_add (dm, "std::istream"));
3284 new_last_source_name = "istream";
3286 else
3288 RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traints<char> >"));
3289 new_last_source_name = "basic_istream";
3291 *template_p = 0;
3292 break;
3294 case 'o':
3295 if (!flag_verbose)
3297 RETURN_IF_ERROR (result_add (dm, "std::ostream"));
3298 new_last_source_name = "ostream";
3300 else
3302 RETURN_IF_ERROR (result_add (dm, "std::basic_ostream<char, std::char_traits<char> >"));
3303 new_last_source_name = "basic_ostream";
3305 *template_p = 0;
3306 break;
3308 case 'd':
3309 if (!flag_verbose)
3311 RETURN_IF_ERROR (result_add (dm, "std::iostream"));
3312 new_last_source_name = "iostream";
3314 else
3316 RETURN_IF_ERROR (result_add (dm, "std::basic_iostream<char, std::char_traits<char> >"));
3317 new_last_source_name = "basic_iostream";
3319 *template_p = 0;
3320 break;
3322 default:
3323 return "Unrecognized <substitution>.";
3326 /* Consume the character we just processed. */
3327 advance_char (dm);
3329 if (new_last_source_name != NULL)
3331 if (!dyn_string_copy_cstr (dm->last_source_name,
3332 new_last_source_name))
3333 return STATUS_ALLOCATION_FAILED;
3336 return STATUS_OK;
3339 /* Look up the substitution text. Since `S_' is the most recent
3340 substitution, `S0_' is the second-most-recent, etc., shift the
3341 numbering by one. */
3342 text = substitution_get (dm, seq_id + 1, template_p);
3343 if (text == NULL)
3344 return "Substitution number out of range.";
3346 /* Emit the substitution text. */
3347 RETURN_IF_ERROR (result_add_string (dm, text));
3349 RETURN_IF_ERROR (demangle_char (dm, '_'));
3350 return STATUS_OK;
3353 /* Demangles and emits a <local-name>.
3355 <local-name> := Z <function encoding> E <entity name> [<discriminator>]
3356 := Z <function encoding> E s [<discriminator>] */
3358 static status_t
3359 demangle_local_name (dm)
3360 demangling_t dm;
3362 DEMANGLE_TRACE ("local-name", dm);
3364 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
3365 RETURN_IF_ERROR (demangle_encoding (dm));
3366 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3367 RETURN_IF_ERROR (result_add (dm, "::"));
3369 if (peek_char (dm) == 's')
3371 /* Local character string literal. */
3372 RETURN_IF_ERROR (result_add (dm, "string literal"));
3373 /* Consume the s. */
3374 advance_char (dm);
3375 RETURN_IF_ERROR (demangle_discriminator (dm, 0));
3377 else
3379 int unused;
3380 /* Local name for some other entity. Demangle its name. */
3381 RETURN_IF_ERROR (demangle_name (dm, &unused));
3382 RETURN_IF_ERROR (demangle_discriminator (dm, 1));
3385 return STATUS_OK;
3388 /* Optimonally demangles and emits a <discriminator>. If there is no
3389 <discriminator> at the current position in the mangled string, the
3390 descriminator is assumed to be zero. Emit the discriminator number
3391 in parentheses, unless SUPPRESS_FIRST is non-zero and the
3392 discriminator is zero.
3394 <discriminator> ::= _ <number> */
3396 static status_t
3397 demangle_discriminator (dm, suppress_first)
3398 demangling_t dm;
3399 int suppress_first;
3401 /* Output for <discriminator>s to the demangled name is completely
3402 suppressed if not in verbose mode. */
3404 if (peek_char (dm) == '_')
3406 /* Consume the underscore. */
3407 advance_char (dm);
3408 if (flag_verbose)
3409 RETURN_IF_ERROR (result_add (dm, " [#"));
3410 /* Check if there's a number following the underscore. */
3411 if (IS_DIGIT ((unsigned char) peek_char (dm)))
3413 int discriminator;
3414 /* Demangle the number. */
3415 RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));
3416 if (flag_verbose)
3417 /* Write the discriminator. The mangled number is two
3418 less than the discriminator ordinal, counting from
3419 zero. */
3420 RETURN_IF_ERROR (int_to_dyn_string (discriminator + 2,
3421 (dyn_string_t) dm->result));
3423 else
3425 if (flag_verbose)
3426 /* A missing digit correspond to one. */
3427 RETURN_IF_ERROR (result_add_char (dm, '1'));
3429 if (flag_verbose)
3430 RETURN_IF_ERROR (result_add_char (dm, ']'));
3432 else if (!suppress_first)
3434 if (flag_verbose)
3435 RETURN_IF_ERROR (result_add (dm, " [#0]"));
3438 return STATUS_OK;
3441 /* Demangle NAME into RESULT, which must be an initialized
3442 dyn_string_t. On success, returns STATUS_OK. On failure, returns
3443 an error message, and the contents of RESULT are unchanged. */
3445 static status_t
3446 cp_demangle (name, result, style)
3447 const char *name;
3448 dyn_string_t result;
3449 int style;
3451 status_t status;
3452 int length = strlen (name);
3454 if (length > 2 && name[0] == '_' && name[1] == 'Z')
3456 demangling_t dm = demangling_new (name, style);
3457 if (dm == NULL)
3458 return STATUS_ALLOCATION_FAILED;
3460 status = result_push (dm);
3461 if (status != STATUS_OK)
3463 demangling_delete (dm);
3464 return status;
3467 status = demangle_mangled_name (dm);
3468 if (STATUS_NO_ERROR (status))
3470 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3471 if (!dyn_string_copy (result, demangled))
3472 return STATUS_ALLOCATION_FAILED;
3473 dyn_string_delete (demangled);
3476 demangling_delete (dm);
3478 else
3480 /* It's evidently not a mangled C++ name. It could be the name
3481 of something with C linkage, though, so just copy NAME into
3482 RESULT. */
3483 if (!dyn_string_copy_cstr (result, name))
3484 return STATUS_ALLOCATION_FAILED;
3485 status = STATUS_OK;
3488 return status;
3491 /* Demangle TYPE_NAME into RESULT, which must be an initialized
3492 dyn_string_t. On success, returns STATUS_OK. On failiure, returns
3493 an error message, and the contents of RESULT are unchanged. */
3495 #ifdef IN_LIBGCC2
3496 static status_t
3497 cp_demangle_type (type_name, result)
3498 const char* type_name;
3499 dyn_string_t result;
3501 status_t status;
3502 demangling_t dm = demangling_new (type_name);
3504 if (dm == NULL)
3505 return STATUS_ALLOCATION_FAILED;
3507 /* Demangle the type name. The demangled name is stored in dm. */
3508 status = result_push (dm);
3509 if (status != STATUS_OK)
3511 demangling_delete (dm);
3512 return status;
3515 status = demangle_type (dm);
3517 if (STATUS_NO_ERROR (status))
3519 /* The demangling succeeded. Pop the result out of dm and copy
3520 it into RESULT. */
3521 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3522 if (!dyn_string_copy (result, demangled))
3523 return STATUS_ALLOCATION_FAILED;
3524 dyn_string_delete (demangled);
3527 /* Clean up. */
3528 demangling_delete (dm);
3530 return status;
3533 extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
3535 /* ia64 ABI-mandated entry point in the C++ runtime library for performing
3536 demangling. MANGLED_NAME is a NUL-terminated character string
3537 containing the name to be demangled.
3539 OUTPUT_BUFFER is a region of memory, allocated with malloc, of
3540 *LENGTH bytes, into which the demangled name is stored. If
3541 OUTPUT_BUFFER is not long enough, it is expanded using realloc.
3542 OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
3543 is placed in a region of memory allocated with malloc.
3545 If LENGTH is non-NULL, the length of the buffer conaining the
3546 demangled name, is placed in *LENGTH.
3548 The return value is a pointer to the start of the NUL-terminated
3549 demangled name, or NULL if the demangling fails. The caller is
3550 responsible for deallocating this memory using free.
3552 *STATUS is set to one of the following values:
3553 0: The demangling operation succeeded.
3554 -1: A memory allocation failiure occurred.
3555 -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
3556 -3: One of the arguments is invalid.
3558 The demagling is performed using the C++ ABI mangling rules, with
3559 GNU extensions. */
3561 char *
3562 __cxa_demangle (mangled_name, output_buffer, length, status)
3563 const char *mangled_name;
3564 char *output_buffer;
3565 size_t *length;
3566 int *status;
3568 struct dyn_string demangled_name;
3569 status_t result;
3571 if (status == NULL)
3572 return NULL;
3574 if (mangled_name == NULL) {
3575 *status = -3;
3576 return NULL;
3579 /* Did the caller provide a buffer for the demangled name? */
3580 if (output_buffer == NULL) {
3581 /* No; dyn_string will malloc a buffer for us. */
3582 if (!dyn_string_init (&demangled_name, 0))
3584 *status = -1;
3585 return NULL;
3588 else {
3589 /* Yes. Check that the length was provided. */
3590 if (length == NULL) {
3591 *status = -3;
3592 return NULL;
3594 /* Install the buffer into a dyn_string. */
3595 demangled_name.allocated = *length;
3596 demangled_name.length = 0;
3597 demangled_name.s = output_buffer;
3600 if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
3601 /* MANGLED_NAME apprears to be a function or variable name.
3602 Demangle it accordingly. */
3603 result = cp_demangle (mangled_name, &demangled_name, 0);
3604 else
3605 /* Try to demangled MANGLED_NAME as the name of a type. */
3606 result = cp_demangle_type (mangled_name, &demangled_name);
3608 if (result == STATUS_OK)
3609 /* The demangling succeeded. */
3611 /* If LENGTH isn't NULL, store the allocated buffer length
3612 there; the buffer may have been realloced by dyn_string
3613 functions. */
3614 if (length != NULL)
3615 *length = demangled_name.allocated;
3616 /* The operation was a success. */
3617 *status = 0;
3618 return dyn_string_buf (&demangled_name);
3620 else if (result == STATUS_ALLOCATION_FAILED)
3621 /* A call to malloc or realloc failed during the demangling
3622 operation. */
3624 *status = -1;
3625 return NULL;
3627 else
3628 /* The demangling failed for another reason, most probably because
3629 MANGLED_NAME isn't a valid mangled name. */
3631 /* If the buffer containing the demangled name wasn't provided
3632 by the caller, free it. */
3633 if (output_buffer == NULL)
3634 free (dyn_string_buf (&demangled_name));
3635 *status = -2;
3636 return NULL;
3640 #else /* !IN_LIBGCC2 */
3642 /* Variant entry point for integration with the existing cplus-dem
3643 demangler. Attempts to demangle MANGLED. If the demangling
3644 succeeds, returns a buffer, allocated with malloc, containing the
3645 demangled name. The caller must deallocate the buffer using free.
3646 If the demangling failes, returns NULL. */
3648 char *
3649 cplus_demangle_v3 (mangled)
3650 const char* mangled;
3652 dyn_string_t demangled;
3653 status_t status;
3655 /* If this isn't a mangled name, don't pretend to demangle it. */
3656 if (strncmp (mangled, "_Z", 2) != 0)
3657 return NULL;
3659 /* Create a dyn_string to hold the demangled name. */
3660 demangled = dyn_string_new (0);
3661 /* Attempt the demangling. */
3662 status = cp_demangle ((char *) mangled, demangled, 0);
3664 if (STATUS_NO_ERROR (status))
3665 /* Demangling succeeded. */
3667 /* Grab the demangled result from the dyn_string. It was
3668 allocated with malloc, so we can return it directly. */
3669 char *return_value = dyn_string_release (demangled);
3670 /* Hand back the demangled name. */
3671 return return_value;
3673 else if (status == STATUS_ALLOCATION_FAILED)
3675 fprintf (stderr, "Memory allocation failed.\n");
3676 abort ();
3678 else
3679 /* Demangling failed. */
3681 dyn_string_delete (demangled);
3682 return NULL;
3686 /* Demangle a Java symbol. Java uses a subset of the V3 ABI C++ mangling
3687 conventions, but the output formatting is a little different.
3688 This instructs the C++ demangler not to emit pointer characters ("*"), and
3689 to use Java's namespace separator symbol ("." instead of "::"). It then
3690 does an additional pass over the demangled output to replace instances
3691 of JArray<TYPE> with TYPE[]. */
3693 char *
3694 java_demangle_v3 (mangled)
3695 const char* mangled;
3697 dyn_string_t demangled;
3698 char *next;
3699 char *end;
3700 int len;
3701 status_t status;
3702 int nesting = 0;
3703 char *cplus_demangled;
3704 char *return_value;
3706 /* Create a dyn_string to hold the demangled name. */
3707 demangled = dyn_string_new (0);
3709 /* Attempt the demangling. */
3710 status = cp_demangle ((char *) mangled, demangled, DMGL_JAVA);
3712 if (STATUS_NO_ERROR (status))
3713 /* Demangling succeeded. */
3715 /* Grab the demangled result from the dyn_string. */
3716 cplus_demangled = dyn_string_release (demangled);
3718 else if (status == STATUS_ALLOCATION_FAILED)
3720 fprintf (stderr, "Memory allocation failed.\n");
3721 abort ();
3723 else
3724 /* Demangling failed. */
3726 dyn_string_delete (demangled);
3727 return NULL;
3730 len = strlen (cplus_demangled);
3731 next = cplus_demangled;
3732 end = next + len;
3733 demangled = NULL;
3735 /* Replace occurances of JArray<TYPE> with TYPE[]. */
3736 while (next < end)
3738 char *open_str = strstr (next, "JArray<");
3739 char *close_str = NULL;
3740 if (nesting > 0)
3741 close_str = strchr (next, '>');
3743 if (open_str != NULL && (close_str == NULL || close_str > open_str))
3745 ++nesting;
3747 if (!demangled)
3748 demangled = dyn_string_new(len);
3750 /* Copy prepending symbols, if any. */
3751 if (open_str > next)
3753 open_str[0] = 0;
3754 dyn_string_append_cstr (demangled, next);
3756 next = open_str + 7;
3758 else if (close_str != NULL)
3760 --nesting;
3762 /* Copy prepending type symbol, if any. Squash any spurious
3763 whitespace. */
3764 if (close_str > next && next[0] != ' ')
3766 close_str[0] = 0;
3767 dyn_string_append_cstr (demangled, next);
3769 dyn_string_append_cstr (demangled, "[]");
3770 next = close_str + 1;
3772 else
3774 /* There are no more arrays. Copy the rest of the symbol, or
3775 simply return the original symbol if no changes were made. */
3776 if (next == cplus_demangled)
3777 return cplus_demangled;
3779 dyn_string_append_cstr (demangled, next);
3780 next = end;
3784 free (cplus_demangled);
3786 return_value = dyn_string_release (demangled);
3787 return return_value;
3790 #endif /* IN_LIBGCC2 */
3792 #ifdef STANDALONE_DEMANGLER
3794 #include "getopt.h"
3796 static void print_usage
3797 PARAMS ((FILE* fp, int exit_value));
3799 /* Non-zero if CHAR is a character than can occur in a mangled name. */
3800 #define is_mangled_char(CHAR) \
3801 (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \
3802 || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
3804 /* The name of this program, as invoked. */
3805 const char* program_name;
3807 /* Prints usage summary to FP and then exits with EXIT_VALUE. */
3809 static void
3810 print_usage (fp, exit_value)
3811 FILE* fp;
3812 int exit_value;
3814 fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
3815 fprintf (fp, "Options:\n");
3816 fprintf (fp, " -h,--help Display this message.\n");
3817 fprintf (fp, " -s,--strict Demangle standard names only.\n");
3818 fprintf (fp, " -v,--verbose Produce verbose demanglings.\n");
3819 fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n");
3821 exit (exit_value);
3824 /* Option specification for getopt_long. */
3825 static struct option long_options[] =
3827 { "help", no_argument, NULL, 'h' },
3828 { "strict", no_argument, NULL, 's' },
3829 { "verbose", no_argument, NULL, 'v' },
3830 { NULL, no_argument, NULL, 0 },
3833 /* Main entry for a demangling filter executable. It will demangle
3834 its command line arguments, if any. If none are provided, it will
3835 filter stdin to stdout, replacing any recognized mangled C++ names
3836 with their demangled equivalents. */
3839 main (argc, argv)
3840 int argc;
3841 char *argv[];
3843 status_t status;
3844 int i;
3845 int opt_char;
3847 /* Use the program name of this program, as invoked. */
3848 program_name = argv[0];
3850 /* Parse options. */
3853 opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);
3854 switch (opt_char)
3856 case '?': /* Unrecognized option. */
3857 print_usage (stderr, 1);
3858 break;
3860 case 'h':
3861 print_usage (stdout, 0);
3862 break;
3864 case 's':
3865 flag_strict = 1;
3866 break;
3868 case 'v':
3869 flag_verbose = 1;
3870 break;
3873 while (opt_char != -1);
3875 if (optind == argc)
3876 /* No command line arguments were provided. Filter stdin. */
3878 dyn_string_t mangled = dyn_string_new (3);
3879 dyn_string_t demangled = dyn_string_new (0);
3880 status_t status;
3882 /* Read all of input. */
3883 while (!feof (stdin))
3885 char c = getchar ();
3887 /* The first character of a mangled name is an underscore. */
3888 if (feof (stdin))
3889 break;
3890 if (c != '_')
3892 /* It's not a mangled name. Print the character and go
3893 on. */
3894 putchar (c);
3895 continue;
3897 c = getchar ();
3899 /* The second character of a mangled name is a capital `Z'. */
3900 if (feof (stdin))
3901 break;
3902 if (c != 'Z')
3904 /* It's not a mangled name. Print the previous
3905 underscore, the `Z', and go on. */
3906 putchar ('_');
3907 putchar (c);
3908 continue;
3911 /* Start keeping track of the candidate mangled name. */
3912 dyn_string_append_char (mangled, '_');
3913 dyn_string_append_char (mangled, 'Z');
3915 /* Pile characters into mangled until we hit one that can't
3916 occur in a mangled name. */
3917 c = getchar ();
3918 while (!feof (stdin) && is_mangled_char (c))
3920 dyn_string_append_char (mangled, c);
3921 if (feof (stdin))
3922 break;
3923 c = getchar ();
3926 /* Attempt to demangle the name. */
3927 status = cp_demangle (dyn_string_buf (mangled), demangled, 0);
3929 /* If the demangling succeeded, great! Print out the
3930 demangled version. */
3931 if (STATUS_NO_ERROR (status))
3932 fputs (dyn_string_buf (demangled), stdout);
3933 /* Abort on allocation failures. */
3934 else if (status == STATUS_ALLOCATION_FAILED)
3936 fprintf (stderr, "Memory allocation failed.\n");
3937 abort ();
3939 /* Otherwise, it might not have been a mangled name. Just
3940 print out the original text. */
3941 else
3942 fputs (dyn_string_buf (mangled), stdout);
3944 /* If we haven't hit EOF yet, we've read one character that
3945 can't occur in a mangled name, so print it out. */
3946 if (!feof (stdin))
3947 putchar (c);
3949 /* Clear the candidate mangled name, to start afresh next
3950 time we hit a `_Z'. */
3951 dyn_string_clear (mangled);
3954 dyn_string_delete (mangled);
3955 dyn_string_delete (demangled);
3957 else
3958 /* Demangle command line arguments. */
3960 dyn_string_t result = dyn_string_new (0);
3962 /* Loop over command line arguments. */
3963 for (i = optind; i < argc; ++i)
3965 /* Attempt to demangle. */
3966 status = cp_demangle (argv[i], result, 0);
3968 /* If it worked, print the demangled name. */
3969 if (STATUS_NO_ERROR (status))
3970 printf ("%s\n", dyn_string_buf (result));
3971 /* Abort on allocaiton failures. */
3972 else if (status == STATUS_ALLOCATION_FAILED)
3974 fprintf (stderr, "Memory allocation failed.\n");
3975 abort ();
3977 /* If not, print the error message to stderr instead. */
3978 else
3979 fprintf (stderr, "%s\n", status);
3981 dyn_string_delete (result);
3984 return 0;
3987 #endif /* STANDALONE_DEMANGLER */