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