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