]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/cp-demangle.c
rtlanal.c (find_first_parameter_load): Call note_stores only on the instructions.
[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));
838f8562 941#ifdef IN_LIBGCC2
051664b0
AS
942static status_t cp_demangle_type
943 PARAMS ((const char*, dyn_string_t));
838f8562 944#endif
69afa80d
AS
945
946/* When passed to demangle_bare_function_type, indicates that the
947 function's return type is not encoded before its parameter types. */
31e0ab1f 948#define BFT_NO_RETURN_TYPE NULL
69afa80d
AS
949
950/* Check that the next character is C. If so, consume it. If not,
951 return an error. */
952
953static status_t
954demangle_char (dm, c)
955 demangling_t dm;
69197e7e 956 int c;
69afa80d
AS
957{
958 static char *error_message = NULL;
959
960 if (peek_char (dm) == c)
961 {
962 advance_char (dm);
963 return STATUS_OK;
964 }
965 else
966 {
967 if (error_message == NULL)
968 error_message = strdup ("Expected ?");
969 error_message[9] = c;
970 return error_message;
971 }
972}
973
974/* Demangles and emits a <mangled-name>.
975
976 <mangled-name> ::= _Z <encoding> */
977
978static status_t
979demangle_mangled_name (dm)
980 demangling_t dm;
981{
982 DEMANGLE_TRACE ("mangled-name", dm);
983 RETURN_IF_ERROR (demangle_char (dm, '_'));
984 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
985 RETURN_IF_ERROR (demangle_encoding (dm));
986 return STATUS_OK;
987}
988
989/* Demangles and emits an <encoding>.
990
991 <encoding> ::= <function name> <bare-function-type>
992 ::= <data name>
bece74bd 993 ::= <special-name> */
69afa80d
AS
994
995static status_t
996demangle_encoding (dm)
997 demangling_t dm;
998{
1056d228 999 int encode_return_type;
69afa80d 1000 int start_position;
69afa80d
AS
1001 template_arg_list_t old_arg_list = current_template_arg_list (dm);
1002 char peek = peek_char (dm);
1003
1004 DEMANGLE_TRACE ("encoding", dm);
1005
1006 /* Remember where the name starts. If it turns out to be a template
1007 function, we'll have to insert the return type here. */
0870bfd6 1008 start_position = result_caret_pos (dm);
69afa80d 1009
bece74bd 1010 if (peek == 'G' || peek == 'T')
69afa80d
AS
1011 RETURN_IF_ERROR (demangle_special_name (dm));
1012 else
1013 {
1014 /* Now demangle the name. */
1056d228 1015 RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));
69afa80d
AS
1016
1017 /* If there's anything left, the name was a function name, with
0870bfd6 1018 maybe its return type, and its parameter types, following. */
69afa80d
AS
1019 if (!end_of_name_p (dm)
1020 && peek_char (dm) != 'E')
1021 {
1056d228 1022 if (encode_return_type)
69afa80d
AS
1023 /* Template functions have their return type encoded. The
1024 return type should be inserted at start_position. */
1025 RETURN_IF_ERROR
31e0ab1f 1026 (demangle_bare_function_type (dm, &start_position));
69afa80d
AS
1027 else
1028 /* Non-template functions don't have their return type
1029 encoded. */
1030 RETURN_IF_ERROR
1031 (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE));
1032 }
69afa80d
AS
1033 }
1034
1035 /* Pop off template argument lists that were built during the
1036 mangling of this name, to restore the old template context. */
1037 pop_to_template_arg_list (dm, old_arg_list);
1038
1039 return STATUS_OK;
1040}
1041
1042/* Demangles and emits a <name>.
1043
1044 <name> ::= <unscoped-name>
1045 ::= <unscoped-template-name> <template-args>
1046 ::= <nested-name>
1047 ::= <local-name>
1048
1049 <unscoped-name> ::= <unqualified-name>
1050 ::= St <unqualified-name> # ::std::
1051
1052 <unscoped-template-name>
1053 ::= <unscoped-name>
1054 ::= <substitution> */
1055
1056static status_t
1056d228 1057demangle_name (dm, encode_return_type)
69afa80d 1058 demangling_t dm;
1056d228 1059 int *encode_return_type;
69afa80d 1060{
69afa80d 1061 int start = substitution_start (dm);
a440fd19 1062 char peek = peek_char (dm);
31e0ab1f 1063 int is_std_substitution = 0;
69afa80d 1064
1056d228
AS
1065 /* Generally, the return type is encoded if the function is a
1066 template-id, and suppressed otherwise. There are a few cases,
1067 though, in which the return type is not encoded even for a
1068 templated function. In these cases, this flag is set. */
1069 int suppress_return_type = 0;
1070
69afa80d
AS
1071 DEMANGLE_TRACE ("name", dm);
1072
a440fd19 1073 switch (peek)
69afa80d
AS
1074 {
1075 case 'N':
1076 /* This is a <nested-name>. */
1056d228 1077 RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));
69afa80d
AS
1078 break;
1079
1080 case 'Z':
1081 RETURN_IF_ERROR (demangle_local_name (dm));
1056d228 1082 *encode_return_type = 0;
69afa80d
AS
1083 break;
1084
1085 case 'S':
1086 /* The `St' substitution allows a name nested in std:: to appear
bece74bd 1087 without being enclosed in a nested name. */
69afa80d
AS
1088 if (peek_char_next (dm) == 't')
1089 {
1090 (void) next_char (dm);
1091 (void) next_char (dm);
0870bfd6 1092 RETURN_IF_ERROR (result_add (dm, "std::"));
1056d228
AS
1093 RETURN_IF_ERROR
1094 (demangle_unqualified_name (dm, &suppress_return_type));
31e0ab1f 1095 is_std_substitution = 1;
69afa80d
AS
1096 }
1097 else
1056d228 1098 RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
bece74bd
AS
1099 /* Check if a template argument list immediately follows.
1100 If so, then we just demangled an <unqualified-template-name>. */
1101 if (peek_char (dm) == 'I')
1102 {
31e0ab1f
AS
1103 /* A template name of the form std::<unqualified-name> is a
1104 substitution candidate. */
1105 if (is_std_substitution)
1106 RETURN_IF_ERROR (substitution_add (dm, start, 0));
1107 /* Demangle the <template-args> here. */
bece74bd 1108 RETURN_IF_ERROR (demangle_template_args (dm));
1056d228 1109 *encode_return_type = !suppress_return_type;
bece74bd 1110 }
d01ce591 1111 else
1056d228 1112 *encode_return_type = 0;
d01ce591 1113
69afa80d
AS
1114 break;
1115
1116 default:
1117 /* This is an <unscoped-name> or <unscoped-template-name>. */
1056d228 1118 RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));
69afa80d
AS
1119
1120 /* If the <unqualified-name> is followed by template args, this
1121 is an <unscoped-template-name>. */
1122 if (peek_char (dm) == 'I')
1123 {
1124 /* Add a substitution for the unqualified template name. */
31e0ab1f 1125 RETURN_IF_ERROR (substitution_add (dm, start, 0));
69afa80d
AS
1126
1127 RETURN_IF_ERROR (demangle_template_args (dm));
1056d228 1128 *encode_return_type = !suppress_return_type;
69afa80d
AS
1129 }
1130 else
1056d228 1131 *encode_return_type = 0;
69afa80d
AS
1132
1133 break;
1134 }
1135
1136 return STATUS_OK;
1137}
1138
1139/* Demangles and emits a <nested-name>.
1140
a440fd19 1141 <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E */
69afa80d
AS
1142
1143static status_t
1056d228 1144demangle_nested_name (dm, encode_return_type)
69afa80d 1145 demangling_t dm;
1056d228 1146 int *encode_return_type;
69afa80d
AS
1147{
1148 char peek;
1149
1150 DEMANGLE_TRACE ("nested-name", dm);
1151
1152 RETURN_IF_ERROR (demangle_char (dm, 'N'));
1153
1154 peek = peek_char (dm);
1155 if (peek == 'r' || peek == 'V' || peek == 'K')
1156 {
0870bfd6 1157 dyn_string_t cv_qualifiers;
051664b0
AS
1158 status_t status;
1159
0870bfd6
AS
1160 /* Snarf up CV qualifiers. */
1161 cv_qualifiers = dyn_string_new (24);
051664b0
AS
1162 if (cv_qualifiers == NULL)
1163 return STATUS_ALLOCATION_FAILED;
69afa80d 1164 demangle_CV_qualifiers (dm, cv_qualifiers);
0870bfd6
AS
1165
1166 /* Emit them, preceded by a space. */
1167 status = result_add_char (dm, ' ');
1168 if (STATUS_NO_ERROR (status))
1169 status = result_add_string (dm, cv_qualifiers);
1170 /* The CV qualifiers that occur in a <nested-name> will be
1171 qualifiers for member functions. These are placed at the end
1172 of the function. Therefore, shift the caret to the left by
1173 the length of the qualifiers, so other text is inserted
1174 before them and they stay at the end. */
1175 result_shift_caret (dm, -dyn_string_length (cv_qualifiers) - 1);
1176 /* Clean up. */
69afa80d 1177 dyn_string_delete (cv_qualifiers);
051664b0 1178 RETURN_IF_ERROR (status);
69afa80d 1179 }
0870bfd6 1180
1056d228 1181 RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
a440fd19
AS
1182 /* No need to demangle the final <unqualified-name>; demangle_prefix
1183 will handle it. */
69afa80d
AS
1184 RETURN_IF_ERROR (demangle_char (dm, 'E'));
1185
1186 return STATUS_OK;
1187}
1188
1189/* Demangles and emits a <prefix>.
1190
a440fd19 1191 <prefix> ::= <prefix> <unqualified-name>
69afa80d
AS
1192 ::= <template-prefix> <template-args>
1193 ::= # empty
1194 ::= <substitution>
1195
1196 <template-prefix> ::= <prefix>
a440fd19 1197 ::= <substitution> */
69afa80d
AS
1198
1199static status_t
1056d228 1200demangle_prefix (dm, encode_return_type)
69afa80d 1201 demangling_t dm;
1056d228 1202 int *encode_return_type;
69afa80d
AS
1203{
1204 int start = substitution_start (dm);
1205 int nested = 0;
1206
1056d228
AS
1207 /* ENCODE_RETURN_TYPE is updated as we decend the nesting chain.
1208 After <template-args>, it is set to non-zero; after everything
1209 else it is set to zero. */
e282c9c9 1210
1056d228
AS
1211 /* Generally, the return type is encoded if the function is a
1212 template-id, and suppressed otherwise. There are a few cases,
1213 though, in which the return type is not encoded even for a
1214 templated function. In these cases, this flag is set. */
1215 int suppress_return_type = 0;
69afa80d
AS
1216
1217 DEMANGLE_TRACE ("prefix", dm);
1218
1219 while (1)
1220 {
1221 char peek;
69afa80d
AS
1222
1223 if (end_of_name_p (dm))
1224 return "Unexpected end of name in <compound-name>.";
1225
1226 peek = peek_char (dm);
1227
1056d228 1228 /* We'll initialize suppress_return_type to false, and set it to true
e282c9c9
AS
1229 if we end up demangling a constructor name. However, make
1230 sure we're not actually about to demangle template arguments
1231 -- if so, this is the <template-args> following a
1232 <template-prefix>, so we'll want the previous flag value
1233 around. */
1234 if (peek != 'I')
1056d228 1235 suppress_return_type = 0;
e282c9c9 1236
051664b0 1237 if (IS_DIGIT ((unsigned char) peek)
69afa80d
AS
1238 || (peek >= 'a' && peek <= 'z')
1239 || peek == 'C' || peek == 'D'
1240 || peek == 'S')
1241 {
1242 /* We have another level of scope qualification. */
1243 if (nested)
3b60dd8e 1244 RETURN_IF_ERROR (result_add (dm, NAMESPACE_SEPARATOR));
69afa80d
AS
1245 else
1246 nested = 1;
1247
1248 if (peek == 'S')
1249 /* The substitution determines whether this is a
e282c9c9 1250 template-id. */
1056d228 1251 RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
69afa80d
AS
1252 else
1253 {
a440fd19 1254 /* It's just a name. */
1056d228
AS
1255 RETURN_IF_ERROR
1256 (demangle_unqualified_name (dm, &suppress_return_type));
1257 *encode_return_type = 0;
69afa80d
AS
1258 }
1259 }
1260 else if (peek == 'Z')
1261 RETURN_IF_ERROR (demangle_local_name (dm));
1262 else if (peek == 'I')
1263 {
69afa80d 1264 RETURN_IF_ERROR (demangle_template_args (dm));
e282c9c9
AS
1265
1266 /* Now we want to indicate to the caller that we've
1267 demangled template arguments, thus the prefix was a
1268 <template-prefix>. That's so that the caller knows to
1269 demangle the function's return type, if this turns out to
1056d228
AS
1270 be a function name. But, if it's a member template
1271 constructor or a templated conversion operator, report it
1272 as untemplated. Those never get encoded return types. */
1273 *encode_return_type = !suppress_return_type;
69afa80d
AS
1274 }
1275 else if (peek == 'E')
1276 /* All done. */
1277 return STATUS_OK;
1278 else
1279 return "Unexpected character in <compound-name>.";
1280
a440fd19
AS
1281 if (peek != 'S'
1282 && peek_char (dm) != 'E')
1283 /* Add a new substitution for the prefix thus far. */
1056d228 1284 RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));
69afa80d
AS
1285 }
1286}
1287
1056d228
AS
1288/* Demangles and emits an <unqualified-name>. If this
1289 <unqualified-name> is for a special function type that should never
1290 have its return type encoded (particularly, a constructor or
1291 conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise,
1292 it is set to zero.
69afa80d
AS
1293
1294 <unqualified-name> ::= <operator-name>
1295 ::= <special-name>
1296 ::= <source-name> */
1297
1298static status_t
1056d228 1299demangle_unqualified_name (dm, suppress_return_type)
69afa80d 1300 demangling_t dm;
1056d228 1301 int *suppress_return_type;
69afa80d
AS
1302{
1303 char peek = peek_char (dm);
1304
1305 DEMANGLE_TRACE ("unqualified-name", dm);
1306
1056d228
AS
1307 /* By default, don't force suppression of the return type (though
1308 non-template functions still don't get a return type encoded). */
1309 *suppress_return_type = 0;
1310
051664b0 1311 if (IS_DIGIT ((unsigned char) peek))
69afa80d
AS
1312 RETURN_IF_ERROR (demangle_source_name (dm));
1313 else if (peek >= 'a' && peek <= 'z')
1314 {
1315 int num_args;
1056d228
AS
1316
1317 /* Conversion operators never have a return type encoded. */
1318 if (peek == 'c' && peek_char_next (dm) == 'v')
1319 *suppress_return_type = 1;
1320
69afa80d
AS
1321 RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args));
1322 }
1323 else if (peek == 'C' || peek == 'D')
1056d228
AS
1324 {
1325 /* Constructors never have a return type encoded. */
1326 if (peek == 'C')
1327 *suppress_return_type = 1;
1328
1329 RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
1330 }
69afa80d
AS
1331 else
1332 return "Unexpected character in <unqualified-name>.";
1333
1334 return STATUS_OK;
1335}
1336
1337/* Demangles and emits <source-name>.
1338
1339 <source-name> ::= <length number> <identifier> */
1340
1341static status_t
1342demangle_source_name (dm)
1343 demangling_t dm;
1344{
1345 int length;
1346
1347 DEMANGLE_TRACE ("source-name", dm);
1348
1349 /* Decode the length of the identifier. */
1350 RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0));
1351 if (length == 0)
1352 return "Zero length in <source-name>.";
1353
1354 /* Now the identifier itself. It's placed into last_source_name,
1355 where it can be used to build a constructor or destructor name. */
1356 RETURN_IF_ERROR (demangle_identifier (dm, length,
1357 dm->last_source_name));
1358
1359 /* Emit it. */
0870bfd6 1360 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
69afa80d
AS
1361
1362 return STATUS_OK;
1363}
1364
1365/* Demangles a number, either a <number> or a <positive-number> at the
1366 current position, consuming all consecutive digit characters. Sets
1367 *VALUE to the resulting numberand returns STATUS_OK. The number is
1368 interpreted as BASE, which must be either 10 or 36. If IS_SIGNED
1369 is non-zero, negative numbers -- prefixed with `n' -- are accepted.
1370
1371 <number> ::= [n] <positive-number>
1372
1373 <positive-number> ::= <decimal integer> */
1374
1375static status_t
1376demangle_number (dm, value, base, is_signed)
1377 demangling_t dm;
1378 int *value;
1379 int base;
1380 int is_signed;
1381{
1382 dyn_string_t number = dyn_string_new (10);
1383
1384 DEMANGLE_TRACE ("number", dm);
1385
051664b0
AS
1386 if (number == NULL)
1387 return STATUS_ALLOCATION_FAILED;
1388
69afa80d
AS
1389 demangle_number_literally (dm, number, base, is_signed);
1390 *value = strtol (dyn_string_buf (number), NULL, base);
1391 dyn_string_delete (number);
1392
1393 return STATUS_OK;
1394}
1395
1396/* Demangles a number at the current position. The digits (and minus
1397 sign, if present) that make up the number are appended to STR.
1398 Only base-BASE digits are accepted; BASE must be either 10 or 36.
1399 If IS_SIGNED, negative numbers -- prefixed with `n' -- are
1400 accepted. Does not consume a trailing underscore or other
1401 terminating character. */
1402
1403static status_t
1404demangle_number_literally (dm, str, base, is_signed)
1405 demangling_t dm;
1406 dyn_string_t str;
1407 int base;
1408 int is_signed;
1409{
1410 DEMANGLE_TRACE ("number*", dm);
1411
1412 if (base != 10 && base != 36)
1413 return STATUS_INTERNAL_ERROR;
1414
1415 /* An `n' denotes a negative number. */
1416 if (is_signed && peek_char (dm) == 'n')
1417 {
1418 /* Skip past the n. */
1419 advance_char (dm);
1420 /* The normal way to write a negative number is with a minus
1421 sign. */
051664b0
AS
1422 if (!dyn_string_append_char (str, '-'))
1423 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1424 }
1425
1426 /* Loop until we hit a non-digit. */
1427 while (1)
1428 {
1429 char peek = peek_char (dm);
051664b0 1430 if (IS_DIGIT ((unsigned char) peek)
69afa80d 1431 || (base == 36 && peek >= 'A' && peek <= 'Z'))
051664b0
AS
1432 {
1433 /* Accumulate digits. */
1434 if (!dyn_string_append_char (str, next_char (dm)))
1435 return STATUS_ALLOCATION_FAILED;
1436 }
69afa80d
AS
1437 else
1438 /* Not a digit? All done. */
1439 break;
1440 }
1441
1442 return STATUS_OK;
1443}
1444
1445/* Demangles an identifier at the current position of LENGTH
1446 characters and places it in IDENTIFIER. */
1447
1448static status_t
1449demangle_identifier (dm, length, identifier)
1450 demangling_t dm;
1451 int length;
1452 dyn_string_t identifier;
1453{
1454 DEMANGLE_TRACE ("identifier", dm);
1455
1456 dyn_string_clear (identifier);
051664b0
AS
1457 if (!dyn_string_resize (identifier, length))
1458 return STATUS_ALLOCATION_FAILED;
1459
69afa80d
AS
1460 while (length-- > 0)
1461 {
1462 if (end_of_name_p (dm))
1463 return "Unexpected end of name in <identifier>.";
051664b0
AS
1464 if (!dyn_string_append_char (identifier, next_char (dm)))
1465 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1466 }
1467
31e0ab1f
AS
1468 /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'
1469 followed by the source file name and some random characters.
1470 Unless we're in strict mode, decipher these names appropriately. */
1471 if (!flag_strict)
1472 {
1473 char *name = dyn_string_buf (identifier);
1474 int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
1475
1476 /* Compare the first, fixed part. */
1477 if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
1478 {
1479 name += prefix_length;
1480 /* The next character might be a period, an underscore, or
1481 dollar sign, depending on the target architecture's
1482 assembler's capabilities. After that comes an `N'. */
1483 if ((*name == '.' || *name == '_' || *name == '$')
1484 && *(name + 1) == 'N')
1485 /* This looks like the anonymous namespace identifier.
1486 Replace it with something comprehensible. */
1487 dyn_string_copy_cstr (identifier, "(anonymous namespace)");
1488 }
1489 }
1490
69afa80d
AS
1491 return STATUS_OK;
1492}
1493
1494/* Demangles and emits an <operator-name>. If SHORT_NAME is non-zero,
1495 the short form is emitted; otherwise the full source form
1496 (`operator +' etc.) is emitted. *NUM_ARGS is set to the number of
1497 operands that the operator takes.
1498
1499 <operator-name>
1500 ::= nw # new
1501 ::= na # new[]
1502 ::= dl # delete
1503 ::= da # delete[]
1504 ::= ps # + (unary)
1505 ::= ng # - (unary)
1506 ::= ad # & (unary)
1507 ::= de # * (unary)
1508 ::= co # ~
1509 ::= pl # +
1510 ::= mi # -
1511 ::= ml # *
1512 ::= dv # /
1513 ::= rm # %
1514 ::= an # &
1515 ::= or # |
1516 ::= eo # ^
1517 ::= aS # =
1518 ::= pL # +=
1519 ::= mI # -=
1520 ::= mL # *=
1521 ::= dV # /=
1522 ::= rM # %=
1523 ::= aN # &=
1524 ::= oR # |=
1525 ::= eO # ^=
1526 ::= ls # <<
1527 ::= rs # >>
1528 ::= lS # <<=
1529 ::= rS # >>=
1530 ::= eq # ==
1531 ::= ne # !=
1532 ::= lt # <
1533 ::= gt # >
1534 ::= le # <=
1535 ::= ge # >=
1536 ::= nt # !
1537 ::= aa # &&
1538 ::= oo # ||
1539 ::= pp # ++
1540 ::= mm # --
1541 ::= cm # ,
1542 ::= pm # ->*
1543 ::= pt # ->
1544 ::= cl # ()
1545 ::= ix # []
1546 ::= qu # ?
1547 ::= sz # sizeof
1548 ::= cv <type> # cast
31e0ab1f 1549 ::= v [0-9] <source-name> # vendor extended operator */
69afa80d
AS
1550
1551static status_t
1552demangle_operator_name (dm, short_name, num_args)
1553 demangling_t dm;
1554 int short_name;
1555 int *num_args;
1556{
1557 struct operator_code
1558 {
1559 /* The mangled code for this operator. */
7eb23b1f 1560 const char *code;
69afa80d 1561 /* The source name of this operator. */
7eb23b1f 1562 const char *name;
69afa80d
AS
1563 /* The number of arguments this operator takes. */
1564 int num_args;
1565 };
1566
7eb23b1f 1567 static const struct operator_code operators[] =
69afa80d
AS
1568 {
1569 { "aN", "&=" , 2 },
1570 { "aS", "=" , 2 },
1571 { "aa", "&&" , 2 },
1572 { "ad", "&" , 1 },
1573 { "an", "&" , 2 },
1574 { "cl", "()" , 0 },
1575 { "cm", "," , 2 },
1576 { "co", "~" , 1 },
1577 { "dV", "/=" , 2 },
fe06b696 1578 { "da", " delete[]", 1 },
69afa80d 1579 { "de", "*" , 1 },
fe06b696 1580 { "dl", " delete" , 1 },
69afa80d
AS
1581 { "dv", "/" , 2 },
1582 { "eO", "^=" , 2 },
1583 { "eo", "^" , 2 },
1584 { "eq", "==" , 2 },
1585 { "ge", ">=" , 2 },
1586 { "gt", ">" , 2 },
1587 { "ix", "[]" , 2 },
1588 { "lS", "<<=" , 2 },
1589 { "le", "<=" , 2 },
1590 { "ls", "<<" , 2 },
1591 { "lt", "<" , 2 },
1592 { "mI", "-=" , 2 },
1593 { "mL", "*=" , 2 },
1594 { "mi", "-" , 2 },
1595 { "ml", "*" , 2 },
1596 { "mm", "--" , 1 },
fe06b696 1597 { "na", " new[]" , 1 },
69afa80d
AS
1598 { "ne", "!=" , 2 },
1599 { "ng", "-" , 1 },
1600 { "nt", "!" , 1 },
fe06b696 1601 { "nw", " new" , 1 },
69afa80d
AS
1602 { "oR", "|=" , 2 },
1603 { "oo", "||" , 2 },
1604 { "or", "|" , 2 },
1605 { "pL", "+=" , 2 },
1606 { "pl", "+" , 2 },
1607 { "pm", "->*" , 2 },
1608 { "pp", "++" , 1 },
1609 { "ps", "+" , 1 },
d01ce591 1610 { "pt", "->" , 2 },
69afa80d
AS
1611 { "qu", "?" , 3 },
1612 { "rM", "%=" , 2 },
1613 { "rS", ">>=" , 2 },
1614 { "rm", "%" , 2 },
1615 { "rs", ">>" , 2 },
fe06b696 1616 { "sz", " sizeof" , 1 }
69afa80d
AS
1617 };
1618
1619 const int num_operators =
1620 sizeof (operators) / sizeof (struct operator_code);
1621
1622 int c0 = next_char (dm);
1623 int c1 = next_char (dm);
7eb23b1f
KG
1624 const struct operator_code* p1 = operators;
1625 const struct operator_code* p2 = operators + num_operators;
69afa80d
AS
1626
1627 DEMANGLE_TRACE ("operator-name", dm);
1628
31e0ab1f
AS
1629 /* Is this a vendor-extended operator? */
1630 if (c0 == 'v' && IS_DIGIT (c1))
69afa80d 1631 {
0870bfd6 1632 RETURN_IF_ERROR (result_add (dm, "operator "));
69afa80d
AS
1633 RETURN_IF_ERROR (demangle_source_name (dm));
1634 *num_args = 0;
1635 return STATUS_OK;
1636 }
1637
1638 /* Is this a conversion operator? */
1639 if (c0 == 'c' && c1 == 'v')
1640 {
0870bfd6 1641 RETURN_IF_ERROR (result_add (dm, "operator "));
69afa80d
AS
1642 /* Demangle the converted-to type. */
1643 RETURN_IF_ERROR (demangle_type (dm));
1644 *num_args = 0;
1645 return STATUS_OK;
1646 }
1647
1648 /* Perform a binary search for the operator code. */
1649 while (1)
1650 {
7eb23b1f 1651 const struct operator_code* p = p1 + (p2 - p1) / 2;
69afa80d
AS
1652 char match0 = p->code[0];
1653 char match1 = p->code[1];
1654
1655 if (c0 == match0 && c1 == match1)
1656 /* Found it. */
1657 {
1658 if (!short_name)
0870bfd6
AS
1659 RETURN_IF_ERROR (result_add (dm, "operator"));
1660 RETURN_IF_ERROR (result_add (dm, p->name));
69afa80d
AS
1661 *num_args = p->num_args;
1662
1663 return STATUS_OK;
1664 }
1665
1666 if (p == p1)
1667 /* Couldn't find it. */
1668 return "Unknown code in <operator-name>.";
1669
1670 /* Try again. */
1671 if (c0 < match0 || (c0 == match0 && c1 < match1))
1672 p2 = p;
1673 else
1674 p1 = p;
1675 }
1676}
1677
92a16bbe
AS
1678/* Demangles and omits an <nv-offset>.
1679
1680 <nv-offset> ::= <offset number> # non-virtual base override */
1681
1682static status_t
1683demangle_nv_offset (dm)
1684 demangling_t dm;
1685{
1686 dyn_string_t number;
1687 status_t status = STATUS_OK;
1688
1689 DEMANGLE_TRACE ("h-offset", dm);
1690
1691 /* Demangle the offset. */
1692 number = dyn_string_new (4);
1693 if (number == NULL)
1694 return STATUS_ALLOCATION_FAILED;
1695 demangle_number_literally (dm, number, 10, 1);
1696
1697 /* Don't display the offset unless in verbose mode. */
1698 if (flag_verbose)
1699 {
0870bfd6 1700 status = result_add (dm, " [nv:");
92a16bbe 1701 if (STATUS_NO_ERROR (status))
0870bfd6 1702 status = result_add_string (dm, number);
92a16bbe 1703 if (STATUS_NO_ERROR (status))
0870bfd6 1704 status = result_add_char (dm, ']');
92a16bbe
AS
1705 }
1706
1707 /* Clean up. */
1708 dyn_string_delete (number);
1709 RETURN_IF_ERROR (status);
1710 return STATUS_OK;
1711}
1712
1713/* Demangles and emits a <v-offset>.
1714
1715 <v-offset> ::= <offset number> _ <virtual offset number>
1716 # virtual base override, with vcall offset */
1717
1718static status_t
1719demangle_v_offset (dm)
1720 demangling_t dm;
1721{
1722 dyn_string_t number;
1723 status_t status = STATUS_OK;
1724
1725 DEMANGLE_TRACE ("v-offset", dm);
1726
1727 /* Demangle the offset. */
1728 number = dyn_string_new (4);
1729 if (number == NULL)
1730 return STATUS_ALLOCATION_FAILED;
1731 demangle_number_literally (dm, number, 10, 1);
1732
1733 /* Don't display the offset unless in verbose mode. */
1734 if (flag_verbose)
1735 {
0870bfd6 1736 status = result_add (dm, " [v:");
92a16bbe 1737 if (STATUS_NO_ERROR (status))
0870bfd6 1738 status = result_add_string (dm, number);
92a16bbe 1739 if (STATUS_NO_ERROR (status))
0870bfd6 1740 result_add_char (dm, ',');
92a16bbe
AS
1741 }
1742 dyn_string_delete (number);
1743 RETURN_IF_ERROR (status);
1744
1745 /* Demangle the separator. */
1746 RETURN_IF_ERROR (demangle_char (dm, '_'));
1747
1748 /* Demangle the vcall offset. */
1749 number = dyn_string_new (4);
1750 if (number == NULL)
1751 return STATUS_ALLOCATION_FAILED;
1752 demangle_number_literally (dm, number, 10, 1);
1753
1754 /* Don't display the vcall offset unless in verbose mode. */
1755 if (flag_verbose)
1756 {
0870bfd6 1757 status = result_add_string (dm, number);
92a16bbe 1758 if (STATUS_NO_ERROR (status))
0870bfd6 1759 status = result_add_char (dm, ']');
92a16bbe
AS
1760 }
1761 dyn_string_delete (number);
1762 RETURN_IF_ERROR (status);
1763
1764 return STATUS_OK;
1765}
1766
1767/* Demangles and emits a <call-offset>.
1768
1769 <call-offset> ::= h <nv-offset> _
1770 ::= v <v-offset> _ */
1771
1772static status_t
1773demangle_call_offset (dm)
1774 demangling_t dm;
1775{
1776 DEMANGLE_TRACE ("call-offset", dm);
1777
1778 switch (peek_char (dm))
1779 {
1780 case 'h':
1781 advance_char (dm);
1782 /* Demangle the offset. */
1783 RETURN_IF_ERROR (demangle_nv_offset (dm));
1784 /* Demangle the separator. */
1785 RETURN_IF_ERROR (demangle_char (dm, '_'));
1786 break;
1787
1788 case 'v':
1789 advance_char (dm);
1790 /* Demangle the offset. */
1791 RETURN_IF_ERROR (demangle_v_offset (dm));
1792 /* Demangle the separator. */
1793 RETURN_IF_ERROR (demangle_char (dm, '_'));
1794 break;
1795
1796 default:
1797 return "Unrecognized <call-offset>.";
1798 }
1799
1800 return STATUS_OK;
1801}
1802
69afa80d
AS
1803/* Demangles and emits a <special-name>.
1804
1805 <special-name> ::= GV <object name> # Guard variable
69afa80d
AS
1806 ::= TV <type> # virtual table
1807 ::= TT <type> # VTT
1808 ::= TI <type> # typeinfo structure
1809 ::= TS <type> # typeinfo name
1810
92a16bbe
AS
1811 Other relevant productions include thunks:
1812
1813 <special-name> ::= T <call-offset> <base encoding>
1814 # base is the nominal target function of thunk
1815
1816 <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
1817 # base is the nominal target function of thunk
1818 # first call-offset is 'this' adjustment
1819 # second call-offset is result adjustment
1820
1821 where
1822
1823 <call-offset> ::= h <nv-offset> _
1824 ::= v <v-offset> _
1825
fe06b696 1826 Also demangles the special g++ manglings,
69afa80d 1827
1056d228 1828 <special-name> ::= TC <type> <offset number> _ <base type>
fe06b696
ZW
1829 # construction vtable
1830 ::= TF <type> # typeinfo function (old ABI only)
1831 ::= TJ <type> # java Class structure */
69afa80d
AS
1832
1833static status_t
1834demangle_special_name (dm)
1835 demangling_t dm;
1836{
1837 dyn_string_t number;
1838 int unused;
1839 char peek = peek_char (dm);
1840
1841 DEMANGLE_TRACE ("special-name", dm);
1842
1843 if (peek == 'G')
1844 {
1845 /* A guard variable name. Consume the G. */
1846 advance_char (dm);
1847 RETURN_IF_ERROR (demangle_char (dm, 'V'));
0870bfd6 1848 RETURN_IF_ERROR (result_add (dm, "guard variable for "));
69afa80d
AS
1849 RETURN_IF_ERROR (demangle_name (dm, &unused));
1850 }
1851 else if (peek == 'T')
1852 {
051664b0
AS
1853 status_t status = STATUS_OK;
1854
69afa80d
AS
1855 /* Other C++ implementation miscellania. Consume the T. */
1856 advance_char (dm);
1857
1858 switch (peek_char (dm))
1859 {
1860 case 'V':
1861 /* Virtual table. */
1862 advance_char (dm);
0870bfd6 1863 RETURN_IF_ERROR (result_add (dm, "vtable for "));
69afa80d
AS
1864 RETURN_IF_ERROR (demangle_type (dm));
1865 break;
1866
1867 case 'T':
1868 /* VTT structure. */
1869 advance_char (dm);
0870bfd6 1870 RETURN_IF_ERROR (result_add (dm, "VTT for "));
69afa80d
AS
1871 RETURN_IF_ERROR (demangle_type (dm));
1872 break;
1873
1874 case 'I':
1875 /* Typeinfo structure. */
1876 advance_char (dm);
0870bfd6 1877 RETURN_IF_ERROR (result_add (dm, "typeinfo for "));
69afa80d
AS
1878 RETURN_IF_ERROR (demangle_type (dm));
1879 break;
1880
fe06b696
ZW
1881 case 'F':
1882 /* Typeinfo function. Used only in old ABI with new mangling. */
1883 advance_char (dm);
0870bfd6 1884 RETURN_IF_ERROR (result_add (dm, "typeinfo fn for "));
fe06b696
ZW
1885 RETURN_IF_ERROR (demangle_type (dm));
1886 break;
1887
69afa80d
AS
1888 case 'S':
1889 /* Character string containing type name, used in typeinfo. */
1890 advance_char (dm);
0870bfd6 1891 RETURN_IF_ERROR (result_add (dm, "typeinfo name for "));
69afa80d
AS
1892 RETURN_IF_ERROR (demangle_type (dm));
1893 break;
1894
fe06b696
ZW
1895 case 'J':
1896 /* The java Class variable corresponding to a C++ class. */
1897 advance_char (dm);
0870bfd6 1898 RETURN_IF_ERROR (result_add (dm, "java Class for "));
fe06b696
ZW
1899 RETURN_IF_ERROR (demangle_type (dm));
1900 break;
1901
69afa80d
AS
1902 case 'h':
1903 /* Non-virtual thunk. */
1904 advance_char (dm);
0870bfd6 1905 RETURN_IF_ERROR (result_add (dm, "non-virtual thunk"));
92a16bbe 1906 RETURN_IF_ERROR (demangle_nv_offset (dm));
69afa80d
AS
1907 /* Demangle the separator. */
1908 RETURN_IF_ERROR (demangle_char (dm, '_'));
1909 /* Demangle and emit the target name and function type. */
0870bfd6 1910 RETURN_IF_ERROR (result_add (dm, " to "));
69afa80d
AS
1911 RETURN_IF_ERROR (demangle_encoding (dm));
1912 break;
1913
1914 case 'v':
1915 /* Virtual thunk. */
1916 advance_char (dm);
0870bfd6 1917 RETURN_IF_ERROR (result_add (dm, "virtual thunk"));
92a16bbe 1918 RETURN_IF_ERROR (demangle_v_offset (dm));
69afa80d
AS
1919 /* Demangle the separator. */
1920 RETURN_IF_ERROR (demangle_char (dm, '_'));
1921 /* Demangle and emit the target function. */
0870bfd6 1922 RETURN_IF_ERROR (result_add (dm, " to "));
92a16bbe
AS
1923 RETURN_IF_ERROR (demangle_encoding (dm));
1924 break;
1925
1926 case 'c':
1927 /* Covariant return thunk. */
1928 advance_char (dm);
0870bfd6 1929 RETURN_IF_ERROR (result_add (dm, "covariant return thunk"));
92a16bbe
AS
1930 RETURN_IF_ERROR (demangle_call_offset (dm));
1931 RETURN_IF_ERROR (demangle_call_offset (dm));
1932 /* Demangle and emit the target function. */
0870bfd6 1933 RETURN_IF_ERROR (result_add (dm, " to "));
69afa80d
AS
1934 RETURN_IF_ERROR (demangle_encoding (dm));
1935 break;
1936
1937 case 'C':
1938 /* TC is a special g++ mangling for a construction vtable. */
1939 if (!flag_strict)
1940 {
229b8ec7
AS
1941 dyn_string_t derived_type;
1942
69afa80d 1943 advance_char (dm);
0870bfd6 1944 RETURN_IF_ERROR (result_add (dm, "construction vtable for "));
229b8ec7
AS
1945
1946 /* Demangle the derived type off to the side. */
1947 RETURN_IF_ERROR (result_push (dm));
69afa80d 1948 RETURN_IF_ERROR (demangle_type (dm));
229b8ec7
AS
1949 derived_type = (dyn_string_t) result_pop (dm);
1950
69afa80d
AS
1951 /* Demangle the offset. */
1952 number = dyn_string_new (4);
051664b0 1953 if (number == NULL)
229b8ec7
AS
1954 {
1955 dyn_string_delete (derived_type);
1956 return STATUS_ALLOCATION_FAILED;
1957 }
69afa80d
AS
1958 demangle_number_literally (dm, number, 10, 1);
1959 /* Demangle the underscore separator. */
229b8ec7
AS
1960 status = demangle_char (dm, '_');
1961
69afa80d 1962 /* Demangle the base type. */
229b8ec7
AS
1963 if (STATUS_NO_ERROR (status))
1964 status = demangle_type (dm);
1965
1966 /* Emit the derived type. */
1967 if (STATUS_NO_ERROR (status))
0870bfd6 1968 status = result_add (dm, "-in-");
229b8ec7 1969 if (STATUS_NO_ERROR (status))
0870bfd6 1970 status = result_add_string (dm, derived_type);
229b8ec7
AS
1971 dyn_string_delete (derived_type);
1972
69afa80d
AS
1973 /* Don't display the offset unless in verbose mode. */
1974 if (flag_verbose)
1975 {
0870bfd6 1976 status = result_add_char (dm, ' ');
051664b0 1977 if (STATUS_NO_ERROR (status))
0870bfd6 1978 result_add_string (dm, number);
69afa80d
AS
1979 }
1980 dyn_string_delete (number);
051664b0 1981 RETURN_IF_ERROR (status);
69afa80d
AS
1982 break;
1983 }
1984 /* If flag_strict, fall through. */
1985
1986 default:
1987 return "Unrecognized <special-name>.";
1988 }
1989 }
1990 else
1991 return STATUS_ERROR;
1992
1993 return STATUS_OK;
1994}
1995
1996/* Demangles and emits a <ctor-dtor-name>.
1997
1998 <ctor-dtor-name>
1999 ::= C1 # complete object (in-charge) ctor
2000 ::= C2 # base object (not-in-charge) ctor
2001 ::= C3 # complete object (in-charge) allocating ctor
69afa80d
AS
2002 ::= D0 # deleting (in-charge) dtor
2003 ::= D1 # complete object (in-charge) dtor
2004 ::= D2 # base object (not-in-charge) dtor */
2005
2006static status_t
2007demangle_ctor_dtor_name (dm)
2008 demangling_t dm;
2009{
2010 static const char *const ctor_flavors[] =
2011 {
2012 "in-charge",
2013 "not-in-charge",
0fac482e 2014 "allocating"
69afa80d
AS
2015 };
2016 static const char *const dtor_flavors[] =
2017 {
2018 "in-charge deleting",
2019 "in-charge",
2020 "not-in-charge"
2021 };
2022
2023 int flavor;
2024 char peek = peek_char (dm);
2025
2026 DEMANGLE_TRACE ("ctor-dtor-name", dm);
2027
2028 if (peek == 'C')
2029 {
2030 /* A constructor name. Consume the C. */
2031 advance_char (dm);
7dce2eff
JB
2032 flavor = next_char (dm);
2033 if (flavor < '1' || flavor > '3')
69afa80d 2034 return "Unrecognized constructor.";
0870bfd6 2035 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
7dce2eff
JB
2036 switch (flavor)
2037 {
2038 case '1': dm->is_constructor = gnu_v3_complete_object_ctor;
2039 break;
2040 case '2': dm->is_constructor = gnu_v3_base_object_ctor;
2041 break;
2042 case '3': dm->is_constructor = gnu_v3_complete_object_allocating_ctor;
2043 break;
2044 }
69afa80d 2045 /* Print the flavor of the constructor if in verbose mode. */
69afa80d
AS
2046 if (flag_verbose)
2047 {
0870bfd6 2048 RETURN_IF_ERROR (result_add (dm, "["));
7dce2eff 2049 RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor - '1']));
0870bfd6 2050 RETURN_IF_ERROR (result_add_char (dm, ']'));
69afa80d
AS
2051 }
2052 }
2053 else if (peek == 'D')
2054 {
2055 /* A destructor name. Consume the D. */
2056 advance_char (dm);
7dce2eff
JB
2057 flavor = next_char (dm);
2058 if (flavor < '0' || flavor > '2')
69afa80d 2059 return "Unrecognized destructor.";
0870bfd6
AS
2060 RETURN_IF_ERROR (result_add_char (dm, '~'));
2061 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
7dce2eff
JB
2062 switch (flavor)
2063 {
2064 case '0': dm->is_destructor = gnu_v3_deleting_dtor;
2065 break;
2066 case '1': dm->is_destructor = gnu_v3_complete_object_dtor;
2067 break;
2068 case '2': dm->is_destructor = gnu_v3_base_object_dtor;
2069 break;
2070 }
69afa80d 2071 /* Print the flavor of the destructor if in verbose mode. */
69afa80d
AS
2072 if (flag_verbose)
2073 {
0870bfd6 2074 RETURN_IF_ERROR (result_add (dm, " ["));
7dce2eff 2075 RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor - '0']));
0870bfd6 2076 RETURN_IF_ERROR (result_add_char (dm, ']'));
69afa80d
AS
2077 }
2078 }
2079 else
2080 return STATUS_ERROR;
2081
2082 return STATUS_OK;
2083}
2084
2085/* Handle pointer, reference, and pointer-to-member cases for
2086 demangle_type. All consecutive `P's, `R's, and 'M's are joined to
2087 build a pointer/reference type. We snarf all these, plus the
2088 following <type>, all at once since we need to know whether we have
2089 a pointer to data or pointer to function to construct the right
2090 output syntax. C++'s pointer syntax is hairy.
2091
31e0ab1f
AS
2092 This function adds substitution candidates for every nested
2093 pointer/reference type it processes, including the outermost, final
2094 type, assuming the substitution starts at SUBSTITUTION_START in the
2095 demangling result. For example, if this function demangles
2096 `PP3Foo', it will add a substitution for `Foo', `Foo*', and
2097 `Foo**', in that order.
2098
2099 *INSERT_POS is a quantity used internally, when this function calls
2100 itself recursively, to figure out where to insert pointer
2101 punctuation on the way up. On entry to this function, INSERT_POS
2102 should point to a temporary value, but that value need not be
2103 initialized.
2104
69afa80d
AS
2105 <type> ::= P <type>
2106 ::= R <type>
2107 ::= <pointer-to-member-type>
2108
2109 <pointer-to-member-type> ::= M </class/ type> </member/ type> */
2110
2111static status_t
31e0ab1f 2112demangle_type_ptr (dm, insert_pos, substitution_start)
69afa80d 2113 demangling_t dm;
31e0ab1f
AS
2114 int *insert_pos;
2115 int substitution_start;
69afa80d 2116{
69afa80d 2117 status_t status;
31e0ab1f 2118 int is_substitution_candidate = 1;
69afa80d
AS
2119
2120 DEMANGLE_TRACE ("type*", dm);
2121
2122 /* Scan forward, collecting pointers and references into symbols,
2123 until we hit something else. Then emit the type. */
0870bfd6 2124 switch (peek_char (dm))
69afa80d 2125 {
0870bfd6 2126 case 'P':
31e0ab1f
AS
2127 /* A pointer. Snarf the `P'. */
2128 advance_char (dm);
2129 /* Demangle the underlying type. */
2130 RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
2131 substitution_start));
2132 /* Insert an asterisk where we're told to; it doesn't
3b60dd8e
BM
2133 necessarily go at the end. If we're doing Java style output,
2134 there is no pointer symbol. */
2135 if (dm->style != DMGL_JAVA)
2136 RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
aee749cf
AS
2137 /* The next (outermost) pointer or reference character should go
2138 after this one. */
2139 ++(*insert_pos);
0870bfd6
AS
2140 break;
2141
2142 case 'R':
31e0ab1f
AS
2143 /* A reference. Snarf the `R'. */
2144 advance_char (dm);
2145 /* Demangle the underlying type. */
2146 RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
2147 substitution_start));
2148 /* Insert an ampersand where we're told to; it doesn't
2149 necessarily go at the end. */
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 'M':
31e0ab1f
AS
2157 {
2158 /* A pointer-to-member. */
2159 dyn_string_t class_type;
2160
2161 /* Eat the 'M'. */
2162 advance_char (dm);
2163
2164 /* Capture the type of which this is a pointer-to-member. */
2165 RETURN_IF_ERROR (result_push (dm));
2166 RETURN_IF_ERROR (demangle_type (dm));
2167 class_type = (dyn_string_t) result_pop (dm);
2168
2169 if (peek_char (dm) == 'F')
2170 /* A pointer-to-member function. We want output along the
2171 lines of `void (C::*) (int, int)'. Demangle the function
2172 type, which would in this case give `void () (int, int)'
2173 and set *insert_pos to the spot between the first
2174 parentheses. */
2175 status = demangle_type_ptr (dm, insert_pos, substitution_start);
0870bfd6
AS
2176 else if (peek_char (dm) == 'A')
2177 /* A pointer-to-member array variable. We want output that
2178 looks like `int (Klass::*) [10]'. Demangle the array type
2179 as `int () [10]', and set *insert_pos to the spot between
2180 the parentheses. */
2181 status = demangle_array_type (dm, insert_pos);
31e0ab1f
AS
2182 else
2183 {
2184 /* A pointer-to-member variable. Demangle the type of the
2185 pointed-to member. */
69afa80d
AS
2186 status = demangle_type (dm);
2187 /* Make it pretty. */
0870bfd6
AS
2188 if (STATUS_NO_ERROR (status)
2189 && !result_previous_char_is_space (dm))
2190 status = result_add_char (dm, ' ');
31e0ab1f
AS
2191 /* The pointer-to-member notation (e.g. `C::*') follows the
2192 member's type. */
0870bfd6 2193 *insert_pos = result_caret_pos (dm);
69afa80d 2194 }
69afa80d 2195
31e0ab1f
AS
2196 /* Build the pointer-to-member notation. */
2197 if (STATUS_NO_ERROR (status))
2198 status = result_insert (dm, *insert_pos, "::*");
2199 if (STATUS_NO_ERROR (status))
2200 status = result_insert_string (dm, *insert_pos, class_type);
2201 /* There may be additional levels of (pointer or reference)
2202 indirection in this type. If so, the `*' and `&' should be
2203 added after the pointer-to-member notation (e.g. `C::*&' for
2204 a reference to a pointer-to-member of class C). */
2205 *insert_pos += dyn_string_length (class_type) + 3;
69afa80d 2206
31e0ab1f
AS
2207 /* Clean up. */
2208 dyn_string_delete (class_type);
69afa80d 2209
31e0ab1f
AS
2210 RETURN_IF_ERROR (status);
2211 }
0870bfd6
AS
2212 break;
2213
2214 case 'F':
31e0ab1f
AS
2215 /* Ooh, tricky, a pointer-to-function. When we demangle the
2216 function type, the return type should go at the very
2217 beginning. */
0870bfd6 2218 *insert_pos = result_caret_pos (dm);
31e0ab1f
AS
2219 /* The parentheses indicate this is a function pointer or
2220 reference type. */
0870bfd6 2221 RETURN_IF_ERROR (result_add (dm, "()"));
31e0ab1f
AS
2222 /* Now demangle the function type. The return type will be
2223 inserted before the `()', and the argument list will go after
2224 it. */
2225 RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
2226 /* We should now have something along the lines of
2227 `void () (int, int)'. The pointer or reference characters
2228 have to inside the first set of parentheses. *insert_pos has
2229 already been updated to point past the end of the return
2230 type. Move it one character over so it points inside the
2231 `()'. */
2232 ++(*insert_pos);
0870bfd6
AS
2233 break;
2234
2235 case 'A':
2236 /* An array pointer or reference. demangle_array_type will figure
2237 out where the asterisks and ampersands go. */
2238 RETURN_IF_ERROR (demangle_array_type (dm, insert_pos));
2239 break;
2240
2241 default:
31e0ab1f
AS
2242 /* No more pointer or reference tokens; this is therefore a
2243 pointer to data. Finish up by demangling the underlying
2244 type. */
2245 RETURN_IF_ERROR (demangle_type (dm));
2246 /* The pointer or reference characters follow the underlying
2247 type, as in `int*&'. */
0870bfd6 2248 *insert_pos = result_caret_pos (dm);
31e0ab1f
AS
2249 /* Because of the production <type> ::= <substitution>,
2250 demangle_type will already have added the underlying type as
2251 a substitution candidate. Don't do it again. */
2252 is_substitution_candidate = 0;
0870bfd6 2253 break;
31e0ab1f
AS
2254 }
2255
2256 if (is_substitution_candidate)
2257 RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
2258
2259 return STATUS_OK;
69afa80d
AS
2260}
2261
2262/* Demangles and emits a <type>.
2263
2264 <type> ::= <builtin-type>
2265 ::= <function-type>
2266 ::= <class-enum-type>
2267 ::= <array-type>
2268 ::= <pointer-to-member-type>
2269 ::= <template-param>
d01ce591 2270 ::= <template-template-param> <template-args>
69afa80d
AS
2271 ::= <CV-qualifiers> <type>
2272 ::= P <type> # pointer-to
2273 ::= R <type> # reference-to
2274 ::= C <type> # complex pair (C 2000)
2275 ::= G <type> # imaginary (C 2000)
2276 ::= U <source-name> <type> # vendor extended type qualifier
2277 ::= <substitution> */
2278
2279static status_t
2280demangle_type (dm)
2281 demangling_t dm;
2282{
2283 int start = substitution_start (dm);
2284 char peek = peek_char (dm);
bece74bd 2285 char peek_next;
1056d228 2286 int encode_return_type = 0;
69afa80d 2287 template_arg_list_t old_arg_list = current_template_arg_list (dm);
31e0ab1f 2288 int insert_pos;
69afa80d 2289
d01ce591
AS
2290 /* A <type> can be a <substitution>; therefore, this <type> is a
2291 substitution candidate unless a special condition holds (see
2292 below). */
2293 int is_substitution_candidate = 1;
2294
69afa80d
AS
2295 DEMANGLE_TRACE ("type", dm);
2296
2297 /* A <class-enum-type> can start with a digit (a <source-name>), an
2298 N (a <nested-name>), or a Z (a <local-name>). */
051664b0 2299 if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
1056d228 2300 RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type));
d01ce591
AS
2301 /* Lower-case letters begin <builtin-type>s, except for `r', which
2302 denotes restrict. */
2303 else if (peek >= 'a' && peek <= 'z' && peek != 'r')
69afa80d
AS
2304 {
2305 RETURN_IF_ERROR (demangle_builtin_type (dm));
d01ce591
AS
2306 /* Built-in types are not substitution candidates. */
2307 is_substitution_candidate = 0;
69afa80d
AS
2308 }
2309 else
2310 switch (peek)
2311 {
2312 case 'r':
2313 case 'V':
2314 case 'K':
d01ce591
AS
2315 /* CV-qualifiers (including restrict). We have to demangle
2316 them off to the side, since C++ syntax puts them in a funny
2317 place for qualified pointer and reference types. */
69afa80d
AS
2318 {
2319 status_t status;
2320 dyn_string_t cv_qualifiers = dyn_string_new (24);
0870bfd6 2321 int old_caret_position = result_get_caret (dm);
051664b0
AS
2322
2323 if (cv_qualifiers == NULL)
2324 return STATUS_ALLOCATION_FAILED;
2325
0870bfd6 2326 /* Decode all adjacent CV qualifiers. */
69afa80d 2327 demangle_CV_qualifiers (dm, cv_qualifiers);
0870bfd6
AS
2328 /* Emit them, and shift the caret left so that the
2329 underlying type will be emitted before the qualifiers. */
2330 status = result_add_string (dm, cv_qualifiers);
2331 result_shift_caret (dm, -dyn_string_length (cv_qualifiers));
2332 /* Clean up. */
69afa80d
AS
2333 dyn_string_delete (cv_qualifiers);
2334 RETURN_IF_ERROR (status);
0870bfd6
AS
2335 /* Also prepend a blank, if needed. */
2336 RETURN_IF_ERROR (result_add_char (dm, ' '));
2337 result_shift_caret (dm, -1);
2338
2339 /* Demangle the underlying type. It will be emitted before
2340 the CV qualifiers, since we moved the caret. */
2341 RETURN_IF_ERROR (demangle_type (dm));
2342
2343 /* Put the caret back where it was previously. */
2344 result_set_caret (dm, old_caret_position);
69afa80d
AS
2345 }
2346 break;
2347
2348 case 'F':
2349 return "Non-pointer or -reference function type.";
2350
2351 case 'A':
0870bfd6 2352 RETURN_IF_ERROR (demangle_array_type (dm, NULL));
69afa80d
AS
2353 break;
2354
2355 case 'T':
d01ce591
AS
2356 /* It's either a <template-param> or a
2357 <template-template-param>. In either case, demangle the
2358 `T' token first. */
31e0ab1f 2359 RETURN_IF_ERROR (demangle_template_param (dm));
d01ce591
AS
2360
2361 /* Check for a template argument list; if one is found, it's a
2362 <template-template-param> ::= <template-param>
2363 ::= <substitution> */
2364 if (peek_char (dm) == 'I')
2365 {
2366 /* Add a substitution candidate. The template parameter
2367 `T' token is a substitution candidate by itself,
2368 without the template argument list. */
1056d228 2369 RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
d01ce591
AS
2370
2371 /* Now demangle the template argument list. */
2372 RETURN_IF_ERROR (demangle_template_args (dm));
2373 /* The entire type, including the template template
2374 parameter and its argument list, will be added as a
2375 substitution candidate below. */
2376 }
2377
69afa80d
AS
2378 break;
2379
2380 case 'S':
bece74bd
AS
2381 /* First check if this is a special substitution. If it is,
2382 this is a <class-enum-type>. Special substitutions have a
2383 letter following the `S'; other substitutions have a digit
2384 or underscore. */
2385 peek_next = peek_char_next (dm);
2386 if (IS_DIGIT (peek_next) || peek_next == '_')
e282c9c9 2387 {
1056d228 2388 RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));
e282c9c9
AS
2389
2390 /* The substituted name may have been a template name.
2391 Check if template arguments follow, and if so, demangle
2392 them. */
2393 if (peek_char (dm) == 'I')
2394 RETURN_IF_ERROR (demangle_template_args (dm));
31e0ab1f
AS
2395 else
2396 /* A substitution token is not itself a substitution
2397 candidate. (However, if the substituted template is
2398 instantiated, the resulting type is.) */
2399 is_substitution_candidate = 0;
e282c9c9 2400 }
bece74bd 2401 else
d93998ec
AS
2402 {
2403 /* Now some trickiness. We have a special substitution
2404 here. Often, the special substitution provides the
2405 name of a template that's subsequently instantiated,
2406 for instance `SaIcE' => std::allocator<char>. In these
2407 cases we need to add a substitution candidate for the
2408 entire <class-enum-type> and thus don't want to clear
2409 the is_substitution_candidate flag.
2410
2411 However, it's possible that what we have here is a
2412 substitution token representing an entire type, such as
2413 `Ss' => std::string. In this case, we mustn't add a
2414 new substitution candidate for this substitution token.
2415 To detect this case, remember where the start of the
2416 substitution token is. */
2417 const char *next = dm->next;
2418 /* Now demangle the <class-enum-type>. */
2419 RETURN_IF_ERROR
2420 (demangle_class_enum_type (dm, &encode_return_type));
2421 /* If all that was just demangled is the two-character
2422 special substitution token, supress the addition of a
2423 new candidate for it. */
2424 if (dm->next == next + 2)
2425 is_substitution_candidate = 0;
2426 }
d01ce591 2427
69afa80d
AS
2428 break;
2429
2430 case 'P':
2431 case 'R':
2432 case 'M':
31e0ab1f
AS
2433 RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
2434 /* demangle_type_ptr adds all applicable substitution
2435 candidates. */
2436 is_substitution_candidate = 0;
69afa80d
AS
2437 break;
2438
2439 case 'C':
2440 /* A C99 complex type. */
0870bfd6 2441 RETURN_IF_ERROR (result_add (dm, "complex "));
69afa80d
AS
2442 advance_char (dm);
2443 RETURN_IF_ERROR (demangle_type (dm));
2444 break;
2445
2446 case 'G':
2447 /* A C99 imaginary type. */
0870bfd6 2448 RETURN_IF_ERROR (result_add (dm, "imaginary "));
69afa80d
AS
2449 advance_char (dm);
2450 RETURN_IF_ERROR (demangle_type (dm));
2451 break;
2452
2453 case 'U':
31e0ab1f 2454 /* Vendor-extended type qualifier. */
69afa80d
AS
2455 advance_char (dm);
2456 RETURN_IF_ERROR (demangle_source_name (dm));
0870bfd6 2457 RETURN_IF_ERROR (result_add_char (dm, ' '));
69afa80d
AS
2458 RETURN_IF_ERROR (demangle_type (dm));
2459 break;
2460
2461 default:
2462 return "Unexpected character in <type>.";
2463 }
2464
d01ce591 2465 if (is_substitution_candidate)
69afa80d
AS
2466 /* Add a new substitution for the type. If this type was a
2467 <template-param>, pass its index since from the point of
d01ce591 2468 substitutions; a <template-param> token is a substitution
69afa80d 2469 candidate distinct from the type that is substituted for it. */
1056d228 2470 RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
69afa80d
AS
2471
2472 /* Pop off template argument lists added during mangling of this
2473 type. */
2474 pop_to_template_arg_list (dm, old_arg_list);
2475
2476 return STATUS_OK;
2477}
2478
2479/* C++ source names of builtin types, indexed by the mangled code
2480 letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc). */
2481static const char *const builtin_type_names[26] =
2482{
2483 "signed char", /* a */
2484 "bool", /* b */
2485 "char", /* c */
2486 "double", /* d */
2487 "long double", /* e */
2488 "float", /* f */
2489 "__float128", /* g */
2490 "unsigned char", /* h */
2491 "int", /* i */
2492 "unsigned", /* j */
2493 NULL, /* k */
2494 "long", /* l */
2495 "unsigned long", /* m */
2496 "__int128", /* n */
2497 "unsigned __int128", /* o */
2498 NULL, /* p */
2499 NULL, /* q */
2500 NULL, /* r */
2501 "short", /* s */
2502 "unsigned short", /* t */
2503 NULL, /* u */
2504 "void", /* v */
2505 "wchar_t", /* w */
2506 "long long", /* x */
2507 "unsigned long long", /* y */
2508 "..." /* z */
2509};
2510
3b60dd8e
BM
2511/* Java source names of builtin types. Types that arn't valid in Java
2512 are also included here - we don't fail if someone attempts to demangle a
2513 C++ symbol in Java style. */
2514static const char *const java_builtin_type_names[26] =
2515{
2516 "signed char", /* a */
2517 "boolean", /* C++ "bool" */ /* b */
2518 "byte", /* C++ "char" */ /* c */
2519 "double", /* d */
2520 "long double", /* e */
2521 "float", /* f */
2522 "__float128", /* g */
2523 "unsigned char", /* h */
2524 "int", /* i */
2525 "unsigned", /* j */
2526 NULL, /* k */
2527 "long", /* l */
2528 "unsigned long", /* m */
2529 "__int128", /* n */
2530 "unsigned __int128", /* o */
2531 NULL, /* p */
2532 NULL, /* q */
2533 NULL, /* r */
2534 "short", /* s */
2535 "unsigned short", /* t */
2536 NULL, /* u */
2537 "void", /* v */
2538 "char", /* C++ "wchar_t" */ /* w */
2539 "long", /* C++ "long long" */ /* x */
2540 "unsigned long long", /* y */
2541 "..." /* z */
2542};
2543
69afa80d
AS
2544/* Demangles and emits a <builtin-type>.
2545
2546 <builtin-type> ::= v # void
2547 ::= w # wchar_t
2548 ::= b # bool
2549 ::= c # char
2550 ::= a # signed char
2551 ::= h # unsigned char
2552 ::= s # short
2553 ::= t # unsigned short
2554 ::= i # int
2555 ::= j # unsigned int
2556 ::= l # long
2557 ::= m # unsigned long
2558 ::= x # long long, __int64
2559 ::= y # unsigned long long, __int64
2560 ::= n # __int128
2561 ::= o # unsigned __int128
2562 ::= f # float
2563 ::= d # double
2564 ::= e # long double, __float80
2565 ::= g # __float128
2566 ::= z # ellipsis
2567 ::= u <source-name> # vendor extended type */
2568
2569static status_t
2570demangle_builtin_type (dm)
2571 demangling_t dm;
2572{
2573
2574 char code = peek_char (dm);
2575
2576 DEMANGLE_TRACE ("builtin-type", dm);
2577
2578 if (code == 'u')
2579 {
2580 advance_char (dm);
2581 RETURN_IF_ERROR (demangle_source_name (dm));
2582 return STATUS_OK;
2583 }
2584 else if (code >= 'a' && code <= 'z')
2585 {
3b60dd8e
BM
2586 const char *type_name;
2587 /* Java uses different names for some built-in types. */
2588 if (dm->style == DMGL_JAVA)
2589 type_name = java_builtin_type_names[code - 'a'];
2590 else
2591 type_name = builtin_type_names[code - 'a'];
69afa80d
AS
2592 if (type_name == NULL)
2593 return "Unrecognized <builtin-type> code.";
2594
0870bfd6 2595 RETURN_IF_ERROR (result_add (dm, type_name));
69afa80d
AS
2596 advance_char (dm);
2597 return STATUS_OK;
2598 }
2599 else
2600 return "Non-alphabetic <builtin-type> code.";
2601}
2602
2603/* Demangles all consecutive CV-qualifiers (const, volatile, and
2604 restrict) at the current position. The qualifiers are appended to
2605 QUALIFIERS. Returns STATUS_OK. */
2606
2607static status_t
2608demangle_CV_qualifiers (dm, qualifiers)
2609 demangling_t dm;
2610 dyn_string_t qualifiers;
2611{
2612 DEMANGLE_TRACE ("CV-qualifiers", dm);
2613
2614 while (1)
2615 {
2616 switch (peek_char (dm))
2617 {
2618 case 'r':
051664b0
AS
2619 if (!dyn_string_append_space (qualifiers))
2620 return STATUS_ALLOCATION_FAILED;
2621 if (!dyn_string_append_cstr (qualifiers, "restrict"))
2622 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
2623 break;
2624
2625 case 'V':
051664b0
AS
2626 if (!dyn_string_append_space (qualifiers))
2627 return STATUS_ALLOCATION_FAILED;
2628 if (!dyn_string_append_cstr (qualifiers, "volatile"))
2629 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
2630 break;
2631
2632 case 'K':
051664b0
AS
2633 if (!dyn_string_append_space (qualifiers))
2634 return STATUS_ALLOCATION_FAILED;
2635 if (!dyn_string_append_cstr (qualifiers, "const"))
2636 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
2637 break;
2638
2639 default:
2640 return STATUS_OK;
2641 }
2642
2643 advance_char (dm);
2644 }
2645}
2646
31e0ab1f 2647/* Demangles and emits a <function-type>. *FUNCTION_NAME_POS is the
69afa80d 2648 position in the result string of the start of the function
31e0ab1f
AS
2649 identifier, at which the function's return type will be inserted;
2650 *FUNCTION_NAME_POS is updated to position past the end of the
2651 function's return type.
69afa80d
AS
2652
2653 <function-type> ::= F [Y] <bare-function-type> E */
2654
2655static status_t
2656demangle_function_type (dm, function_name_pos)
2657 demangling_t dm;
31e0ab1f 2658 int *function_name_pos;
69afa80d
AS
2659{
2660 DEMANGLE_TRACE ("function-type", dm);
2661 RETURN_IF_ERROR (demangle_char (dm, 'F'));
2662 if (peek_char (dm) == 'Y')
2663 {
2664 /* Indicate this function has C linkage if in verbose mode. */
2665 if (flag_verbose)
0870bfd6 2666 RETURN_IF_ERROR (result_add (dm, " [extern \"C\"] "));
69afa80d
AS
2667 advance_char (dm);
2668 }
2669 RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
2670 RETURN_IF_ERROR (demangle_char (dm, 'E'));
2671 return STATUS_OK;
2672}
2673
2674/* Demangles and emits a <bare-function-type>. RETURN_TYPE_POS is the
2675 position in the result string at which the function return type
2676 should be inserted. If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the
2677 function's return type is assumed not to be encoded.
2678
2679 <bare-function-type> ::= <signature type>+ */
2680
2681static status_t
2682demangle_bare_function_type (dm, return_type_pos)
2683 demangling_t dm;
31e0ab1f 2684 int *return_type_pos;
69afa80d
AS
2685{
2686 /* Sequence is the index of the current function parameter, counting
2687 from zero. The value -1 denotes the return type. */
2688 int sequence =
2689 (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);
2690
2691 DEMANGLE_TRACE ("bare-function-type", dm);
2692
0870bfd6 2693 RETURN_IF_ERROR (result_add_char (dm, '('));
69afa80d
AS
2694 while (!end_of_name_p (dm) && peek_char (dm) != 'E')
2695 {
2696 if (sequence == -1)
2697 /* We're decoding the function's return type. */
2698 {
2699 dyn_string_t return_type;
051664b0 2700 status_t status = STATUS_OK;
69afa80d
AS
2701
2702 /* Decode the return type off to the side. */
051664b0 2703 RETURN_IF_ERROR (result_push (dm));
69afa80d
AS
2704 RETURN_IF_ERROR (demangle_type (dm));
2705 return_type = (dyn_string_t) result_pop (dm);
2706
051664b0
AS
2707 /* Add a space to the end of the type. Insert the return
2708 type where we've been asked to. */
31e0ab1f 2709 if (!dyn_string_append_space (return_type))
051664b0 2710 status = STATUS_ALLOCATION_FAILED;
31e0ab1f
AS
2711 if (STATUS_NO_ERROR (status))
2712 {
2713 if (!dyn_string_insert (result_string (dm), *return_type_pos,
2714 return_type))
2715 status = STATUS_ALLOCATION_FAILED;
2716 else
2717 *return_type_pos += dyn_string_length (return_type);
2718 }
69afa80d 2719
69afa80d 2720 dyn_string_delete (return_type);
051664b0 2721 RETURN_IF_ERROR (status);
69afa80d
AS
2722 }
2723 else
2724 {
2725 /* Skip `void' parameter types. One should only occur as
2726 the only type in a parameter list; in that case, we want
2727 to print `foo ()' instead of `foo (void)'. */
2728 if (peek_char (dm) == 'v')
1056d228
AS
2729 /* Consume the v. */
2730 advance_char (dm);
2731 else
69afa80d 2732 {
1056d228
AS
2733 /* Separate parameter types by commas. */
2734 if (sequence > 0)
0870bfd6 2735 RETURN_IF_ERROR (result_add (dm, ", "));
1056d228
AS
2736 /* Demangle the type. */
2737 RETURN_IF_ERROR (demangle_type (dm));
69afa80d 2738 }
69afa80d
AS
2739 }
2740
2741 ++sequence;
2742 }
0870bfd6 2743 RETURN_IF_ERROR (result_add_char (dm, ')'));
69afa80d 2744
1056d228
AS
2745 /* We should have demangled at least one parameter type (which would
2746 be void, for a function that takes no parameters), plus the
2747 return type, if we were supposed to demangle that. */
2748 if (sequence == -1)
2749 return "Missing function return type.";
2750 else if (sequence == 0)
2751 return "Missing function parameter.";
2752
69afa80d
AS
2753 return STATUS_OK;
2754}
2755
1056d228 2756/* Demangles and emits a <class-enum-type>. *ENCODE_RETURN_TYPE is set to
69afa80d
AS
2757 non-zero if the type is a template-id, zero otherwise.
2758
2759 <class-enum-type> ::= <name> */
2760
2761static status_t
1056d228 2762demangle_class_enum_type (dm, encode_return_type)
69afa80d 2763 demangling_t dm;
1056d228 2764 int *encode_return_type;
69afa80d
AS
2765{
2766 DEMANGLE_TRACE ("class-enum-type", dm);
2767
1056d228 2768 RETURN_IF_ERROR (demangle_name (dm, encode_return_type));
69afa80d
AS
2769 return STATUS_OK;
2770}
2771
2772/* Demangles and emits an <array-type>.
2773
0870bfd6
AS
2774 If PTR_INSERT_POS is not NULL, the array type is formatted as a
2775 pointer or reference to an array, except that asterisk and
2776 ampersand punctuation is omitted (since it's not know at this
2777 point). *PTR_INSERT_POS is set to the position in the demangled
2778 name at which this punctuation should be inserted. For example,
2779 `A10_i' is demangled to `int () [10]' and *PTR_INSERT_POS points
2780 between the parentheses.
2781
2782 If PTR_INSERT_POS is NULL, the array type is assumed not to be
2783 pointer- or reference-qualified. Then, for example, `A10_i' is
2784 demangled simply as `int[10]'.
2785
0fac482e
AS
2786 <array-type> ::= A [<dimension number>] _ <element type>
2787 ::= A <dimension expression> _ <element type> */
69afa80d
AS
2788
2789static status_t
0870bfd6 2790demangle_array_type (dm, ptr_insert_pos)
69afa80d 2791 demangling_t dm;
0870bfd6 2792 int *ptr_insert_pos;
69afa80d 2793{
0fac482e
AS
2794 status_t status = STATUS_OK;
2795 dyn_string_t array_size = NULL;
2796 char peek;
051664b0 2797
0870bfd6
AS
2798 DEMANGLE_TRACE ("array-type", dm);
2799
0fac482e 2800 RETURN_IF_ERROR (demangle_char (dm, 'A'));
69afa80d
AS
2801
2802 /* Demangle the array size into array_size. */
0fac482e
AS
2803 peek = peek_char (dm);
2804 if (peek == '_')
2805 /* Array bound is omitted. This is a C99-style VLA. */
2806 ;
2807 else if (IS_DIGIT (peek_char (dm)))
2808 {
2809 /* It looks like a constant array bound. */
2810 array_size = dyn_string_new (10);
2811 if (array_size == NULL)
2812 return STATUS_ALLOCATION_FAILED;
2813 status = demangle_number_literally (dm, array_size, 10, 0);
2814 }
2815 else
2816 {
2817 /* Anything is must be an expression for a nont-constant array
2818 bound. This happens if the array type occurs in a template
2819 and the array bound references a template parameter. */
2820 RETURN_IF_ERROR (result_push (dm));
2821 RETURN_IF_ERROR (demangle_expression (dm));
2822 array_size = (dyn_string_t) result_pop (dm);
2823 }
2824 /* array_size may have been allocated by now, so we can't use
2825 RETURN_IF_ERROR until it's been deallocated. */
69afa80d
AS
2826
2827 /* Demangle the base type of the array. */
051664b0
AS
2828 if (STATUS_NO_ERROR (status))
2829 status = demangle_char (dm, '_');
2830 if (STATUS_NO_ERROR (status))
2831 status = demangle_type (dm);
69afa80d 2832
0870bfd6
AS
2833 if (ptr_insert_pos != NULL)
2834 {
2835 /* This array is actually part of an pointer- or
2836 reference-to-array type. Format appropriately, except we
2837 don't know which and how much punctuation to use. */
2838 if (STATUS_NO_ERROR (status))
2839 status = result_add (dm, " () ");
2840 /* Let the caller know where to insert the punctuation. */
2841 *ptr_insert_pos = result_caret_pos (dm) - 2;
2842 }
2843
69afa80d 2844 /* Emit the array dimension syntax. */
051664b0 2845 if (STATUS_NO_ERROR (status))
0870bfd6 2846 status = result_add_char (dm, '[');
0fac482e 2847 if (STATUS_NO_ERROR (status) && array_size != NULL)
0870bfd6 2848 status = result_add_string (dm, array_size);
051664b0 2849 if (STATUS_NO_ERROR (status))
0870bfd6 2850 status = result_add_char (dm, ']');
0fac482e
AS
2851 if (array_size != NULL)
2852 dyn_string_delete (array_size);
69afa80d 2853
051664b0
AS
2854 RETURN_IF_ERROR (status);
2855
69afa80d
AS
2856 return STATUS_OK;
2857}
2858
31e0ab1f 2859/* Demangles and emits a <template-param>.
69afa80d
AS
2860
2861 <template-param> ::= T_ # first template parameter
2862 ::= T <parameter-2 number> _ */
2863
2864static status_t
31e0ab1f 2865demangle_template_param (dm)
69afa80d 2866 demangling_t dm;
69afa80d
AS
2867{
2868 int parm_number;
2869 template_arg_list_t current_arg_list = current_template_arg_list (dm);
2870 string_list_t arg;
2871
2872 DEMANGLE_TRACE ("template-param", dm);
2873
2874 /* Make sure there is a template argmust list in which to look up
2875 this parameter reference. */
2876 if (current_arg_list == NULL)
2877 return "Template parameter outside of template.";
2878
2879 RETURN_IF_ERROR (demangle_char (dm, 'T'));
2880 if (peek_char (dm) == '_')
2881 parm_number = 0;
2882 else
2883 {
2884 RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));
2885 ++parm_number;
2886 }
2887 RETURN_IF_ERROR (demangle_char (dm, '_'));
2888
2889 arg = template_arg_list_get_arg (current_arg_list, parm_number);
2890 if (arg == NULL)
2891 /* parm_number exceeded the number of arguments in the current
2892 template argument list. */
2893 return "Template parameter number out of bounds.";
0870bfd6 2894 RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
69afa80d 2895
69afa80d
AS
2896 return STATUS_OK;
2897}
2898
2899/* Demangles and emits a <template-args>.
2900
2901 <template-args> ::= I <template-arg>+ E */
2902
2903static status_t
2904demangle_template_args (dm)
2905 demangling_t dm;
2906{
2907 int first = 1;
051664b0 2908 dyn_string_t old_last_source_name;
69afa80d
AS
2909 template_arg_list_t arg_list = template_arg_list_new ();
2910
051664b0
AS
2911 if (arg_list == NULL)
2912 return STATUS_ALLOCATION_FAILED;
2913
69afa80d 2914 /* Preserve the most recently demangled source name. */
051664b0 2915 old_last_source_name = dm->last_source_name;
69afa80d
AS
2916 dm->last_source_name = dyn_string_new (0);
2917
2918 DEMANGLE_TRACE ("template-args", dm);
2919
051664b0
AS
2920 if (dm->last_source_name == NULL)
2921 return STATUS_ALLOCATION_FAILED;
2922
69afa80d 2923 RETURN_IF_ERROR (demangle_char (dm, 'I'));
e282c9c9 2924 RETURN_IF_ERROR (result_open_template_list (dm));
69afa80d
AS
2925 do
2926 {
2927 string_list_t arg;
2928
2929 if (first)
2930 first = 0;
2931 else
0870bfd6 2932 RETURN_IF_ERROR (result_add (dm, ", "));
69afa80d
AS
2933
2934 /* Capture the template arg. */
051664b0 2935 RETURN_IF_ERROR (result_push (dm));
69afa80d
AS
2936 RETURN_IF_ERROR (demangle_template_arg (dm));
2937 arg = result_pop (dm);
2938
2939 /* Emit it in the demangled name. */
0870bfd6 2940 RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
69afa80d
AS
2941
2942 /* Save it for use in expanding <template-param>s. */
2943 template_arg_list_add_arg (arg_list, arg);
2944 }
2945 while (peek_char (dm) != 'E');
2946 /* Append the '>'. */
051664b0 2947 RETURN_IF_ERROR (result_close_template_list (dm));
69afa80d
AS
2948
2949 /* Consume the 'E'. */
2950 advance_char (dm);
2951
2952 /* Restore the most recent demangled source name. */
2953 dyn_string_delete (dm->last_source_name);
2954 dm->last_source_name = old_last_source_name;
2955
2956 /* Push the list onto the top of the stack of template argument
2957 lists, so that arguments from it are used from now on when
2958 expanding <template-param>s. */
2959 push_template_arg_list (dm, arg_list);
2960
2961 return STATUS_OK;
2962}
2963
2964/* This function, which does not correspond to a production in the
2965 mangling spec, handles the `literal' production for both
2966 <template-arg> and <expr-primary>. It does not expect or consume
2967 the initial `L' or final `E'. The demangling is given by:
2968
2969 <literal> ::= <type> </value/ number>
2970
2971 and the emitted output is `(type)number'. */
2972
2973static status_t
2974demangle_literal (dm)
2975 demangling_t dm;
2976{
69afa80d 2977 char peek = peek_char (dm);
051664b0
AS
2978 dyn_string_t value_string;
2979 status_t status;
69afa80d
AS
2980
2981 DEMANGLE_TRACE ("literal", dm);
2982
2983 if (!flag_verbose && peek >= 'a' && peek <= 'z')
2984 {
2985 /* If not in verbose mode and this is a builtin type, see if we
2986 can produce simpler numerical output. In particular, for
2987 integer types shorter than `long', just write the number
2988 without type information; for bools, write `true' or `false'.
2989 Other refinements could be made here too. */
2990
2991 /* This constant string is used to map from <builtin-type> codes
2992 (26 letters of the alphabet) to codes that determine how the
2993 value will be displayed. The codes are:
2994 b: display as bool
2995 i: display as int
2996 l: display as long
2997 A space means the value will be represented using cast
2998 notation. */
2999 static const char *const code_map = "ibi iii ll ii i ";
3000
3001 char code = code_map[peek - 'a'];
3002 /* FIXME: Implement demangling of floats and doubles. */
3003 if (code == 'u')
3004 return STATUS_UNIMPLEMENTED;
3005 if (code == 'b')
3006 {
3007 /* It's a boolean. */
3008 char value;
3009
3010 /* Consume the b. */
3011 advance_char (dm);
3012 /* Look at the next character. It should be 0 or 1,
3013 corresponding to false or true, respectively. */
3014 value = peek_char (dm);
3015 if (value == '0')
0870bfd6 3016 RETURN_IF_ERROR (result_add (dm, "false"));
69afa80d 3017 else if (value == '1')
0870bfd6 3018 RETURN_IF_ERROR (result_add (dm, "true"));
69afa80d
AS
3019 else
3020 return "Unrecognized bool constant.";
3021 /* Consume the 0 or 1. */
3022 advance_char (dm);
3023 return STATUS_OK;
3024 }
3025 else if (code == 'i' || code == 'l')
3026 {
3027 /* It's an integer or long. */
3028
3029 /* Consume the type character. */
3030 advance_char (dm);
051664b0 3031
69afa80d 3032 /* Demangle the number and write it out. */
051664b0
AS
3033 value_string = dyn_string_new (0);
3034 status = demangle_number_literally (dm, value_string, 10, 1);
3035 if (STATUS_NO_ERROR (status))
0870bfd6 3036 status = result_add_string (dm, value_string);
69afa80d 3037 /* For long integers, append an l. */
051664b0 3038 if (code == 'l' && STATUS_NO_ERROR (status))
0870bfd6 3039 status = result_add_char (dm, code);
051664b0
AS
3040 dyn_string_delete (value_string);
3041
3042 RETURN_IF_ERROR (status);
69afa80d
AS
3043 return STATUS_OK;
3044 }
3045 /* ...else code == ' ', so fall through to represent this
3046 literal's type explicitly using cast syntax. */
3047 }
3048
0870bfd6 3049 RETURN_IF_ERROR (result_add_char (dm, '('));
69afa80d 3050 RETURN_IF_ERROR (demangle_type (dm));
0870bfd6 3051 RETURN_IF_ERROR (result_add_char (dm, ')'));
051664b0
AS
3052
3053 value_string = dyn_string_new (0);
3054 if (value_string == NULL)
3055 return STATUS_ALLOCATION_FAILED;
69afa80d 3056
051664b0
AS
3057 status = demangle_number_literally (dm, value_string, 10, 1);
3058 if (STATUS_NO_ERROR (status))
0870bfd6 3059 status = result_add_string (dm, value_string);
051664b0
AS
3060 dyn_string_delete (value_string);
3061 RETURN_IF_ERROR (status);
69afa80d
AS
3062
3063 return STATUS_OK;
3064}
3065
3066/* Demangles and emits a <template-arg>.
3067
3068 <template-arg> ::= <type> # type
3069 ::= L <type> <value number> E # literal
3070 ::= LZ <encoding> E # external name
3071 ::= X <expression> E # expression */
3072
3073static status_t
3074demangle_template_arg (dm)
3075 demangling_t dm;
3076{
3077 DEMANGLE_TRACE ("template-arg", dm);
3078
3079 switch (peek_char (dm))
3080 {
3081 case 'L':
3082 advance_char (dm);
3083
3084 if (peek_char (dm) == 'Z')
3085 {
3086 /* External name. */
3087 advance_char (dm);
3088 /* FIXME: Standard is contradictory here. */
3089 RETURN_IF_ERROR (demangle_encoding (dm));
3090 }
3091 else
3092 RETURN_IF_ERROR (demangle_literal (dm));
3093 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3094 break;
3095
3096 case 'X':
3097 /* Expression. */
3098 advance_char (dm);
3099 RETURN_IF_ERROR (demangle_expression (dm));
02bcb9c6 3100 RETURN_IF_ERROR (demangle_char (dm, 'E'));
69afa80d
AS
3101 break;
3102
3103 default:
3104 RETURN_IF_ERROR (demangle_type (dm));
3105 break;
3106 }
3107
3108 return STATUS_OK;
3109}
3110
3111/* Demangles and emits an <expression>.
3112
3113 <expression> ::= <unary operator-name> <expression>
3114 ::= <binary operator-name> <expression> <expression>
3115 ::= <expr-primary>
3116 ::= <scope-expression> */
3117
3118static status_t
3119demangle_expression (dm)
3120 demangling_t dm;
3121{
3122 char peek = peek_char (dm);
3123
3124 DEMANGLE_TRACE ("expression", dm);
3125
3126 if (peek == 'L' || peek == 'T')
3127 RETURN_IF_ERROR (demangle_expr_primary (dm));
3128 else if (peek == 's' && peek_char_next (dm) == 'r')
3129 RETURN_IF_ERROR (demangle_scope_expression (dm));
3130 else
3131 /* An operator expression. */
3132 {
3133 int num_args;
051664b0 3134 status_t status = STATUS_OK;
69afa80d
AS
3135 dyn_string_t operator_name;
3136
3137 /* We have an operator name. Since we want to output binary
3138 operations in infix notation, capture the operator name
3139 first. */
051664b0 3140 RETURN_IF_ERROR (result_push (dm));
69afa80d
AS
3141 RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args));
3142 operator_name = (dyn_string_t) result_pop (dm);
3143
3144 /* If it's binary, do an operand first. */
3145 if (num_args > 1)
3146 {
0870bfd6 3147 status = result_add_char (dm, '(');
051664b0
AS
3148 if (STATUS_NO_ERROR (status))
3149 status = demangle_expression (dm);
3150 if (STATUS_NO_ERROR (status))
0870bfd6 3151 status = result_add_char (dm, ')');
69afa80d
AS
3152 }
3153
051664b0
AS
3154 /* Emit the operator. */
3155 if (STATUS_NO_ERROR (status))
0870bfd6 3156 status = result_add_string (dm, operator_name);
69afa80d 3157 dyn_string_delete (operator_name);
051664b0
AS
3158 RETURN_IF_ERROR (status);
3159
3160 /* Emit its second (if binary) or only (if unary) operand. */
0870bfd6 3161 RETURN_IF_ERROR (result_add_char (dm, '('));
69afa80d 3162 RETURN_IF_ERROR (demangle_expression (dm));
0870bfd6 3163 RETURN_IF_ERROR (result_add_char (dm, ')'));
69afa80d
AS
3164
3165 /* The ternary operator takes a third operand. */
3166 if (num_args == 3)
3167 {
0870bfd6 3168 RETURN_IF_ERROR (result_add (dm, ":("));
69afa80d 3169 RETURN_IF_ERROR (demangle_expression (dm));
0870bfd6 3170 RETURN_IF_ERROR (result_add_char (dm, ')'));
69afa80d
AS
3171 }
3172 }
3173
3174 return STATUS_OK;
3175}
3176
3177/* Demangles and emits a <scope-expression>.
3178
3179 <scope-expression> ::= sr <qualifying type> <source-name>
3180 ::= sr <qualifying type> <encoding> */
3181
3182static status_t
3183demangle_scope_expression (dm)
3184 demangling_t dm;
3185{
3186 RETURN_IF_ERROR (demangle_char (dm, 's'));
3187 RETURN_IF_ERROR (demangle_char (dm, 'r'));
3188 RETURN_IF_ERROR (demangle_type (dm));
0870bfd6 3189 RETURN_IF_ERROR (result_add (dm, "::"));
69afa80d
AS
3190 RETURN_IF_ERROR (demangle_encoding (dm));
3191 return STATUS_OK;
3192}
3193
3194/* Demangles and emits an <expr-primary>.
3195
3196 <expr-primary> ::= <template-param>
3197 ::= L <type> <value number> E # literal
3198 ::= L <mangled-name> E # external name */
3199
3200static status_t
3201demangle_expr_primary (dm)
3202 demangling_t dm;
3203{
3204 char peek = peek_char (dm);
69afa80d
AS
3205
3206 DEMANGLE_TRACE ("expr-primary", dm);
3207
3208 if (peek == 'T')
31e0ab1f 3209 RETURN_IF_ERROR (demangle_template_param (dm));
69afa80d
AS
3210 else if (peek == 'L')
3211 {
3212 /* Consume the `L'. */
3213 advance_char (dm);
3214 peek = peek_char (dm);
3215
3216 if (peek == '_')
3217 RETURN_IF_ERROR (demangle_mangled_name (dm));
3218 else
3219 RETURN_IF_ERROR (demangle_literal (dm));
3220
3221 RETURN_IF_ERROR (demangle_char (dm, 'E'));
3222 }
3223 else
3224 return STATUS_ERROR;
3225
3226 return STATUS_OK;
3227}
3228
3229/* Demangles and emits a <substitution>. Sets *TEMPLATE_P to non-zero
d01ce591 3230 if the substitution is the name of a template, zero otherwise.
69afa80d
AS
3231
3232 <substitution> ::= S <seq-id> _
3233 ::= S_
3234
3235 ::= St # ::std::
3236 ::= Sa # ::std::allocator
3237 ::= Sb # ::std::basic_string
3238 ::= Ss # ::std::basic_string<char,
3239 ::std::char_traits<char>,
3240 ::std::allocator<char> >
3241 ::= Si # ::std::basic_istream<char,
3242 std::char_traits<char> >
3243 ::= So # ::std::basic_ostream<char,
3244 std::char_traits<char> >
3245 ::= Sd # ::std::basic_iostream<char,
31e0ab1f 3246 std::char_traits<char> >
69afa80d
AS
3247*/
3248
3249static status_t
d01ce591 3250demangle_substitution (dm, template_p)
69afa80d
AS
3251 demangling_t dm;
3252 int *template_p;
69afa80d
AS
3253{
3254 int seq_id;
3255 int peek;
3256 dyn_string_t text;
3257
3258 DEMANGLE_TRACE ("substitution", dm);
3259
3260 RETURN_IF_ERROR (demangle_char (dm, 'S'));
69afa80d
AS
3261
3262 /* Scan the substitution sequence index. A missing number denotes
3263 the first index. */
3264 peek = peek_char (dm);
3265 if (peek == '_')
3266 seq_id = -1;
3267 /* If the following character is 0-9 or a capital letter, interpret
3268 the sequence up to the next underscore as a base-36 substitution
3269 index. */
051664b0 3270 else if (IS_DIGIT ((unsigned char) peek)
69afa80d
AS
3271 || (peek >= 'A' && peek <= 'Z'))
3272 RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));
3273 else
3274 {
051664b0
AS
3275 const char *new_last_source_name = NULL;
3276
69afa80d
AS
3277 switch (peek)
3278 {
3279 case 't':
0870bfd6 3280 RETURN_IF_ERROR (result_add (dm, "std"));
69afa80d
AS
3281 break;
3282
3283 case 'a':
0870bfd6 3284 RETURN_IF_ERROR (result_add (dm, "std::allocator"));
051664b0 3285 new_last_source_name = "allocator";
bece74bd 3286 *template_p = 1;
69afa80d
AS
3287 break;
3288
3289 case 'b':
0870bfd6 3290 RETURN_IF_ERROR (result_add (dm, "std::basic_string"));
051664b0 3291 new_last_source_name = "basic_string";
bece74bd 3292 *template_p = 1;
69afa80d
AS
3293 break;
3294
3295 case 's':
3296 if (!flag_verbose)
3297 {
0870bfd6 3298 RETURN_IF_ERROR (result_add (dm, "std::string"));
051664b0 3299 new_last_source_name = "string";
69afa80d
AS
3300 }
3301 else
3302 {
0870bfd6 3303 RETURN_IF_ERROR (result_add (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
051664b0 3304 new_last_source_name = "basic_string";
69afa80d 3305 }
bece74bd 3306 *template_p = 0;
69afa80d
AS
3307 break;
3308
3309 case 'i':
3310 if (!flag_verbose)
3311 {
0870bfd6 3312 RETURN_IF_ERROR (result_add (dm, "std::istream"));
051664b0 3313 new_last_source_name = "istream";
69afa80d
AS
3314 }
3315 else
3316 {
0870bfd6 3317 RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traints<char> >"));
051664b0 3318 new_last_source_name = "basic_istream";
69afa80d 3319 }
bece74bd 3320 *template_p = 0;
69afa80d
AS
3321 break;
3322
3323 case 'o':
3324 if (!flag_verbose)
3325 {
0870bfd6 3326 RETURN_IF_ERROR (result_add (dm, "std::ostream"));
051664b0 3327 new_last_source_name = "ostream";
69afa80d
AS
3328 }
3329 else
3330 {
0870bfd6 3331 RETURN_IF_ERROR (result_add (dm, "std::basic_ostream<char, std::char_traits<char> >"));
051664b0 3332 new_last_source_name = "basic_ostream";
69afa80d 3333 }
bece74bd 3334 *template_p = 0;
69afa80d
AS
3335 break;
3336
3337 case 'd':
3338 if (!flag_verbose)
3339 {
0870bfd6 3340 RETURN_IF_ERROR (result_add (dm, "std::iostream"));
051664b0 3341 new_last_source_name = "iostream";
69afa80d
AS
3342 }
3343 else
3344 {
0870bfd6 3345 RETURN_IF_ERROR (result_add (dm, "std::basic_iostream<char, std::char_traits<char> >"));
051664b0 3346 new_last_source_name = "basic_iostream";
69afa80d 3347 }
bece74bd 3348 *template_p = 0;
69afa80d
AS
3349 break;
3350
3351 default:
3352 return "Unrecognized <substitution>.";
3353 }
3354
051664b0 3355 /* Consume the character we just processed. */
69afa80d 3356 advance_char (dm);
051664b0
AS
3357
3358 if (new_last_source_name != NULL)
3359 {
3360 if (!dyn_string_copy_cstr (dm->last_source_name,
3361 new_last_source_name))
3362 return STATUS_ALLOCATION_FAILED;
3363 }
3364
69afa80d
AS
3365 return STATUS_OK;
3366 }
3367
3368 /* Look up the substitution text. Since `S_' is the most recent
3369 substitution, `S0_' is the second-most-recent, etc., shift the
3370 numbering by one. */
3371 text = substitution_get (dm, seq_id + 1, template_p);
bece74bd 3372 if (text == NULL)
69afa80d
AS
3373 return "Substitution number out of range.";
3374
3375 /* Emit the substitution text. */
0870bfd6 3376 RETURN_IF_ERROR (result_add_string (dm, text));
69afa80d
AS
3377
3378 RETURN_IF_ERROR (demangle_char (dm, '_'));
3379 return STATUS_OK;
3380}
3381
3382/* Demangles and emits a <local-name>.
3383
3384 <local-name> := Z <function encoding> E <entity name> [<discriminator>]
3385 := Z <function encoding> E s [<discriminator>] */
3386
3387static status_t
3388demangle_local_name (dm)
3389 demangling_t dm;
3390{
3391 DEMANGLE_TRACE ("local-name", dm);
3392
3393 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
3394 RETURN_IF_ERROR (demangle_encoding (dm));
3395 RETURN_IF_ERROR (demangle_char (dm, 'E'));
0870bfd6 3396 RETURN_IF_ERROR (result_add (dm, "::"));
69afa80d
AS
3397
3398 if (peek_char (dm) == 's')
3399 {
3400 /* Local character string literal. */
0870bfd6 3401 RETURN_IF_ERROR (result_add (dm, "string literal"));
69afa80d
AS
3402 /* Consume the s. */
3403 advance_char (dm);
3404 RETURN_IF_ERROR (demangle_discriminator (dm, 0));
3405 }
3406 else
3407 {
3408 int unused;
69afa80d
AS
3409 /* Local name for some other entity. Demangle its name. */
3410 RETURN_IF_ERROR (demangle_name (dm, &unused));
3411 RETURN_IF_ERROR (demangle_discriminator (dm, 1));
3412 }
3413
3414 return STATUS_OK;
3415 }
3416
3417 /* Optimonally demangles and emits a <discriminator>. If there is no
3418 <discriminator> at the current position in the mangled string, the
3419 descriminator is assumed to be zero. Emit the discriminator number
3420 in parentheses, unless SUPPRESS_FIRST is non-zero and the
3421 discriminator is zero.
3422
3423 <discriminator> ::= _ <number> */
3424
3425static status_t
3426demangle_discriminator (dm, suppress_first)
3427 demangling_t dm;
3428 int suppress_first;
3429{
3430 /* Output for <discriminator>s to the demangled name is completely
1056d228 3431 suppressed if not in verbose mode. */
69afa80d
AS
3432
3433 if (peek_char (dm) == '_')
3434 {
3435 /* Consume the underscore. */
3436 advance_char (dm);
3437 if (flag_verbose)
0870bfd6 3438 RETURN_IF_ERROR (result_add (dm, " [#"));
69afa80d 3439 /* Check if there's a number following the underscore. */
051664b0 3440 if (IS_DIGIT ((unsigned char) peek_char (dm)))
69afa80d
AS
3441 {
3442 int discriminator;
3443 /* Demangle the number. */
3444 RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));
3445 if (flag_verbose)
3446 /* Write the discriminator. The mangled number is two
3447 less than the discriminator ordinal, counting from
3448 zero. */
f1a0345c 3449 RETURN_IF_ERROR (int_to_dyn_string (discriminator + 1,
051664b0 3450 (dyn_string_t) dm->result));
69afa80d
AS
3451 }
3452 else
f1a0345c 3453 return STATUS_ERROR;
69afa80d 3454 if (flag_verbose)
0870bfd6 3455 RETURN_IF_ERROR (result_add_char (dm, ']'));
69afa80d
AS
3456 }
3457 else if (!suppress_first)
3458 {
3459 if (flag_verbose)
0870bfd6 3460 RETURN_IF_ERROR (result_add (dm, " [#0]"));
69afa80d
AS
3461 }
3462
3463 return STATUS_OK;
3464}
3465
3466/* Demangle NAME into RESULT, which must be an initialized
3467 dyn_string_t. On success, returns STATUS_OK. On failure, returns
3468 an error message, and the contents of RESULT are unchanged. */
3469
7eb23b1f 3470static status_t
3b60dd8e 3471cp_demangle (name, result, style)
051664b0 3472 const char *name;
69afa80d 3473 dyn_string_t result;
3b60dd8e 3474 int style;
69afa80d
AS
3475{
3476 status_t status;
3477 int length = strlen (name);
3478
3479 if (length > 2 && name[0] == '_' && name[1] == 'Z')
3480 {
3b60dd8e 3481 demangling_t dm = demangling_new (name, style);
051664b0
AS
3482 if (dm == NULL)
3483 return STATUS_ALLOCATION_FAILED;
69afa80d 3484
051664b0
AS
3485 status = result_push (dm);
3486 if (status != STATUS_OK)
3487 {
3488 demangling_delete (dm);
3489 return status;
3490 }
69afa80d 3491
051664b0
AS
3492 status = demangle_mangled_name (dm);
3493 if (STATUS_NO_ERROR (status))
69afa80d
AS
3494 {
3495 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
051664b0
AS
3496 if (!dyn_string_copy (result, demangled))
3497 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
3498 dyn_string_delete (demangled);
3499 }
3500
3501 demangling_delete (dm);
3502 }
3503 else
3504 {
3505 /* It's evidently not a mangled C++ name. It could be the name
3506 of something with C linkage, though, so just copy NAME into
3507 RESULT. */
051664b0
AS
3508 if (!dyn_string_copy_cstr (result, name))
3509 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
3510 status = STATUS_OK;
3511 }
3512
051664b0
AS
3513 return status;
3514}
3515
3516/* Demangle TYPE_NAME into RESULT, which must be an initialized
3517 dyn_string_t. On success, returns STATUS_OK. On failiure, returns
3518 an error message, and the contents of RESULT are unchanged. */
3519
838f8562 3520#ifdef IN_LIBGCC2
051664b0
AS
3521static status_t
3522cp_demangle_type (type_name, result)
3523 const char* type_name;
3524 dyn_string_t result;
3525{
3526 status_t status;
3527 demangling_t dm = demangling_new (type_name);
3528
3529 if (dm == NULL)
3530 return STATUS_ALLOCATION_FAILED;
3531
3532 /* Demangle the type name. The demangled name is stored in dm. */
3533 status = result_push (dm);
3534 if (status != STATUS_OK)
3535 {
3536 demangling_delete (dm);
3537 return status;
3538 }
3539
3540 status = demangle_type (dm);
3541
3542 if (STATUS_NO_ERROR (status))
3543 {
3544 /* The demangling succeeded. Pop the result out of dm and copy
3545 it into RESULT. */
3546 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3547 if (!dyn_string_copy (result, demangled))
3548 return STATUS_ALLOCATION_FAILED;
3549 dyn_string_delete (demangled);
3550 }
3551
3552 /* Clean up. */
3553 demangling_delete (dm);
3554
69afa80d
AS
3555 return status;
3556}
3557
051664b0
AS
3558extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
3559
c6e13630 3560/* ia64 ABI-mandated entry point in the C++ runtime library for performing
051664b0
AS
3561 demangling. MANGLED_NAME is a NUL-terminated character string
3562 containing the name to be demangled.
3563
3564 OUTPUT_BUFFER is a region of memory, allocated with malloc, of
3565 *LENGTH bytes, into which the demangled name is stored. If
3566 OUTPUT_BUFFER is not long enough, it is expanded using realloc.
3567 OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
3568 is placed in a region of memory allocated with malloc.
3569
3570 If LENGTH is non-NULL, the length of the buffer conaining the
3571 demangled name, is placed in *LENGTH.
3572
3573 The return value is a pointer to the start of the NUL-terminated
3574 demangled name, or NULL if the demangling fails. The caller is
3575 responsible for deallocating this memory using free.
3576
3577 *STATUS is set to one of the following values:
3578 0: The demangling operation succeeded.
3579 -1: A memory allocation failiure occurred.
3580 -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
3581 -3: One of the arguments is invalid.
3582
3583 The demagling is performed using the C++ ABI mangling rules, with
3584 GNU extensions. */
3585
3586char *
3587__cxa_demangle (mangled_name, output_buffer, length, status)
3588 const char *mangled_name;
3589 char *output_buffer;
3590 size_t *length;
3591 int *status;
3592{
3593 struct dyn_string demangled_name;
3594 status_t result;
3595
3596 if (status == NULL)
3597 return NULL;
3598
3599 if (mangled_name == NULL) {
3600 *status = -3;
3601 return NULL;
3602 }
3603
3604 /* Did the caller provide a buffer for the demangled name? */
3605 if (output_buffer == NULL) {
3606 /* No; dyn_string will malloc a buffer for us. */
3607 if (!dyn_string_init (&demangled_name, 0))
3608 {
3609 *status = -1;
3610 return NULL;
3611 }
3612 }
3613 else {
3614 /* Yes. Check that the length was provided. */
3615 if (length == NULL) {
3616 *status = -3;
3617 return NULL;
3618 }
3619 /* Install the buffer into a dyn_string. */
3620 demangled_name.allocated = *length;
3621 demangled_name.length = 0;
3622 demangled_name.s = output_buffer;
3623 }
3624
3625 if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
3626 /* MANGLED_NAME apprears to be a function or variable name.
3627 Demangle it accordingly. */
3b60dd8e 3628 result = cp_demangle (mangled_name, &demangled_name, 0);
051664b0
AS
3629 else
3630 /* Try to demangled MANGLED_NAME as the name of a type. */
3631 result = cp_demangle_type (mangled_name, &demangled_name);
3632
3633 if (result == STATUS_OK)
3634 /* The demangling succeeded. */
3635 {
3636 /* If LENGTH isn't NULL, store the allocated buffer length
3637 there; the buffer may have been realloced by dyn_string
3638 functions. */
3639 if (length != NULL)
3640 *length = demangled_name.allocated;
3641 /* The operation was a success. */
3642 *status = 0;
3643 return dyn_string_buf (&demangled_name);
3644 }
3645 else if (result == STATUS_ALLOCATION_FAILED)
3646 /* A call to malloc or realloc failed during the demangling
3647 operation. */
3648 {
3649 *status = -1;
3650 return NULL;
3651 }
3652 else
3653 /* The demangling failed for another reason, most probably because
3654 MANGLED_NAME isn't a valid mangled name. */
3655 {
3656 /* If the buffer containing the demangled name wasn't provided
3657 by the caller, free it. */
3658 if (output_buffer == NULL)
3659 free (dyn_string_buf (&demangled_name));
3660 *status = -2;
3661 return NULL;
3662 }
3663}
3664
3665#else /* !IN_LIBGCC2 */
3666
69afa80d
AS
3667/* Variant entry point for integration with the existing cplus-dem
3668 demangler. Attempts to demangle MANGLED. If the demangling
3669 succeeds, returns a buffer, allocated with malloc, containing the
3670 demangled name. The caller must deallocate the buffer using free.
3671 If the demangling failes, returns NULL. */
3672
3673char *
c6e13630 3674cplus_demangle_v3 (mangled)
69afa80d
AS
3675 const char* mangled;
3676{
b5d1497d
JM
3677 dyn_string_t demangled;
3678 status_t status;
3679
3680 /* If this isn't a mangled name, don't pretend to demangle it. */
3681 if (strncmp (mangled, "_Z", 2) != 0)
3682 return NULL;
3683
69afa80d 3684 /* Create a dyn_string to hold the demangled name. */
b5d1497d 3685 demangled = dyn_string_new (0);
69afa80d 3686 /* Attempt the demangling. */
3b60dd8e 3687 status = cp_demangle ((char *) mangled, demangled, 0);
b5d1497d 3688
051664b0 3689 if (STATUS_NO_ERROR (status))
69afa80d
AS
3690 /* Demangling succeeded. */
3691 {
3692 /* Grab the demangled result from the dyn_string. It was
3693 allocated with malloc, so we can return it directly. */
3694 char *return_value = dyn_string_release (demangled);
69afa80d
AS
3695 /* Hand back the demangled name. */
3696 return return_value;
3697 }
051664b0
AS
3698 else if (status == STATUS_ALLOCATION_FAILED)
3699 {
3700 fprintf (stderr, "Memory allocation failed.\n");
3701 abort ();
3702 }
69afa80d
AS
3703 else
3704 /* Demangling failed. */
3705 {
3706 dyn_string_delete (demangled);
3707 return NULL;
3708 }
3709}
3710
3b60dd8e
BM
3711/* Demangle a Java symbol. Java uses a subset of the V3 ABI C++ mangling
3712 conventions, but the output formatting is a little different.
3713 This instructs the C++ demangler not to emit pointer characters ("*"), and
3714 to use Java's namespace separator symbol ("." instead of "::"). It then
3715 does an additional pass over the demangled output to replace instances
3716 of JArray<TYPE> with TYPE[]. */
3717
3718char *
3719java_demangle_v3 (mangled)
3720 const char* mangled;
3721{
3722 dyn_string_t demangled;
3723 char *next;
3724 char *end;
3725 int len;
3726 status_t status;
3727 int nesting = 0;
3728 char *cplus_demangled;
3729 char *return_value;
3730
3731 /* Create a dyn_string to hold the demangled name. */
3732 demangled = dyn_string_new (0);
3733
3734 /* Attempt the demangling. */
3735 status = cp_demangle ((char *) mangled, demangled, DMGL_JAVA);
3736
3737 if (STATUS_NO_ERROR (status))
3738 /* Demangling succeeded. */
3739 {
3740 /* Grab the demangled result from the dyn_string. */
3741 cplus_demangled = dyn_string_release (demangled);
3742 }
3743 else if (status == STATUS_ALLOCATION_FAILED)
3744 {
3745 fprintf (stderr, "Memory allocation failed.\n");
3746 abort ();
3747 }
3748 else
3749 /* Demangling failed. */
3750 {
3751 dyn_string_delete (demangled);
3752 return NULL;
3753 }
3754
3755 len = strlen (cplus_demangled);
3756 next = cplus_demangled;
3757 end = next + len;
3758 demangled = NULL;
3759
3760 /* Replace occurances of JArray<TYPE> with TYPE[]. */
3761 while (next < end)
3762 {
3763 char *open_str = strstr (next, "JArray<");
3764 char *close_str = NULL;
3765 if (nesting > 0)
3766 close_str = strchr (next, '>');
3767
3768 if (open_str != NULL && (close_str == NULL || close_str > open_str))
3769 {
3770 ++nesting;
3771
3772 if (!demangled)
3773 demangled = dyn_string_new(len);
3774
3775 /* Copy prepending symbols, if any. */
3776 if (open_str > next)
3777 {
3778 open_str[0] = 0;
3779 dyn_string_append_cstr (demangled, next);
3780 }
3781 next = open_str + 7;
3782 }
3783 else if (close_str != NULL)
3784 {
3785 --nesting;
3786
3787 /* Copy prepending type symbol, if any. Squash any spurious
3788 whitespace. */
3789 if (close_str > next && next[0] != ' ')
3790 {
3791 close_str[0] = 0;
3792 dyn_string_append_cstr (demangled, next);
3793 }
3794 dyn_string_append_cstr (demangled, "[]");
3795 next = close_str + 1;
3796 }
3797 else
3798 {
3799 /* There are no more arrays. Copy the rest of the symbol, or
3800 simply return the original symbol if no changes were made. */
3801 if (next == cplus_demangled)
3802 return cplus_demangled;
3803
3804 dyn_string_append_cstr (demangled, next);
3805 next = end;
3806 }
3807 }
3808
3809 free (cplus_demangled);
3810
3811 return_value = dyn_string_release (demangled);
3812 return return_value;
3813}
3814
051664b0
AS
3815#endif /* IN_LIBGCC2 */
3816
7dce2eff
JB
3817
3818/* Demangle NAME in the G++ V3 ABI demangling style, and return either
3819 zero, indicating that some error occurred, or a demangling_t
3820 holding the results. */
3821static demangling_t
641b2721
ZW
3822demangle_v3_with_details (name)
3823 const char *name;
7dce2eff
JB
3824{
3825 demangling_t dm;
3826 status_t status;
3827
3828 if (strncmp (name, "_Z", 2))
3829 return 0;
3830
3831 dm = demangling_new (name, DMGL_GNU_V3);
3832 if (dm == NULL)
3833 {
3834 fprintf (stderr, "Memory allocation failed.\n");
3835 abort ();
3836 }
3837
3838 status = result_push (dm);
3839 if (! STATUS_NO_ERROR (status))
3840 {
3841 demangling_delete (dm);
3842 fprintf (stderr, "%s\n", status);
3843 abort ();
3844 }
3845
3846 status = demangle_mangled_name (dm);
3847 if (STATUS_NO_ERROR (status))
3848 return dm;
3849
3850 demangling_delete (dm);
3851 return 0;
3852}
3853
3854
3855/* Return non-zero iff NAME is the mangled form of a constructor name
3856 in the G++ V3 ABI demangling style. Specifically, return:
3857 - '1' if NAME is a complete object constructor,
3858 - '2' if NAME is a base object constructor, or
3859 - '3' if NAME is a complete object allocating constructor. */
3860enum gnu_v3_ctor_kinds
641b2721
ZW
3861is_gnu_v3_mangled_ctor (name)
3862 const char *name;
7dce2eff
JB
3863{
3864 demangling_t dm = demangle_v3_with_details (name);
3865
3866 if (dm)
3867 {
3868 enum gnu_v3_ctor_kinds result = dm->is_constructor;
3869 demangling_delete (dm);
3870 return result;
3871 }
3872 else
3873 return 0;
3874}
3875
3876
3877/* Return non-zero iff NAME is the mangled form of a destructor name
3878 in the G++ V3 ABI demangling style. Specifically, return:
3879 - '0' if NAME is a deleting destructor,
3880 - '1' if NAME is a complete object destructor, or
3881 - '2' if NAME is a base object destructor. */
3882enum gnu_v3_dtor_kinds
641b2721
ZW
3883is_gnu_v3_mangled_dtor (name)
3884 const char *name;
7dce2eff
JB
3885{
3886 demangling_t dm = demangle_v3_with_details (name);
3887
3888 if (dm)
3889 {
3890 enum gnu_v3_dtor_kinds result = dm->is_destructor;
3891 demangling_delete (dm);
3892 return result;
3893 }
3894 else
3895 return 0;
3896}
3897
3898
69afa80d
AS
3899#ifdef STANDALONE_DEMANGLER
3900
3901#include "getopt.h"
3902
3903static void print_usage
3904 PARAMS ((FILE* fp, int exit_value));
3905
3906/* Non-zero if CHAR is a character than can occur in a mangled name. */
3faa108c 3907#define is_mangled_char(CHAR) \
31e0ab1f
AS
3908 (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \
3909 || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
69afa80d
AS
3910
3911/* The name of this program, as invoked. */
3912const char* program_name;
3913
3914/* Prints usage summary to FP and then exits with EXIT_VALUE. */
3915
3916static void
3917print_usage (fp, exit_value)
3918 FILE* fp;
3919 int exit_value;
3920{
3921 fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
d01ce591 3922 fprintf (fp, "Options:\n");
69afa80d
AS
3923 fprintf (fp, " -h,--help Display this message.\n");
3924 fprintf (fp, " -s,--strict Demangle standard names only.\n");
3925 fprintf (fp, " -v,--verbose Produce verbose demanglings.\n");
3926 fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n");
3927
3928 exit (exit_value);
3929}
3930
3931/* Option specification for getopt_long. */
3932static struct option long_options[] =
3933{
3934 { "help", no_argument, NULL, 'h' },
3935 { "strict", no_argument, NULL, 's' },
3936 { "verbose", no_argument, NULL, 'v' },
3937 { NULL, no_argument, NULL, 0 },
3938};
3939
3940/* Main entry for a demangling filter executable. It will demangle
3941 its command line arguments, if any. If none are provided, it will
3942 filter stdin to stdout, replacing any recognized mangled C++ names
3943 with their demangled equivalents. */
3944
3945int
3946main (argc, argv)
3947 int argc;
3948 char *argv[];
3949{
3950 status_t status;
3951 int i;
3952 int opt_char;
3953
3954 /* Use the program name of this program, as invoked. */
3955 program_name = argv[0];
3956
3957 /* Parse options. */
3958 do
3959 {
3960 opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);
3961 switch (opt_char)
3962 {
3963 case '?': /* Unrecognized option. */
3964 print_usage (stderr, 1);
3965 break;
3966
3967 case 'h':
3968 print_usage (stdout, 0);
3969 break;
3970
3971 case 's':
3972 flag_strict = 1;
3973 break;
3974
3975 case 'v':
3976 flag_verbose = 1;
3977 break;
3978 }
3979 }
3980 while (opt_char != -1);
3981
3982 if (optind == argc)
3983 /* No command line arguments were provided. Filter stdin. */
3984 {
3985 dyn_string_t mangled = dyn_string_new (3);
3986 dyn_string_t demangled = dyn_string_new (0);
3987 status_t status;
3988
3989 /* Read all of input. */
3990 while (!feof (stdin))
3991 {
3992 char c = getchar ();
3993
3994 /* The first character of a mangled name is an underscore. */
3995 if (feof (stdin))
3996 break;
3997 if (c != '_')
3998 {
3999 /* It's not a mangled name. Print the character and go
4000 on. */
4001 putchar (c);
4002 continue;
4003 }
4004 c = getchar ();
4005
4006 /* The second character of a mangled name is a capital `Z'. */
4007 if (feof (stdin))
4008 break;
4009 if (c != 'Z')
4010 {
4011 /* It's not a mangled name. Print the previous
4012 underscore, the `Z', and go on. */
4013 putchar ('_');
4014 putchar (c);
4015 continue;
4016 }
4017
4018 /* Start keeping track of the candidate mangled name. */
4019 dyn_string_append_char (mangled, '_');
4020 dyn_string_append_char (mangled, 'Z');
4021
4022 /* Pile characters into mangled until we hit one that can't
4023 occur in a mangled name. */
4024 c = getchar ();
4025 while (!feof (stdin) && is_mangled_char (c))
4026 {
4027 dyn_string_append_char (mangled, c);
4028 if (feof (stdin))
4029 break;
4030 c = getchar ();
4031 }
4032
4033 /* Attempt to demangle the name. */
3b60dd8e 4034 status = cp_demangle (dyn_string_buf (mangled), demangled, 0);
69afa80d
AS
4035
4036 /* If the demangling succeeded, great! Print out the
4037 demangled version. */
051664b0 4038 if (STATUS_NO_ERROR (status))
69afa80d 4039 fputs (dyn_string_buf (demangled), stdout);
051664b0
AS
4040 /* Abort on allocation failures. */
4041 else if (status == STATUS_ALLOCATION_FAILED)
4042 {
4043 fprintf (stderr, "Memory allocation failed.\n");
4044 abort ();
4045 }
69afa80d
AS
4046 /* Otherwise, it might not have been a mangled name. Just
4047 print out the original text. */
4048 else
4049 fputs (dyn_string_buf (mangled), stdout);
4050
4051 /* If we haven't hit EOF yet, we've read one character that
4052 can't occur in a mangled name, so print it out. */
4053 if (!feof (stdin))
4054 putchar (c);
4055
4056 /* Clear the candidate mangled name, to start afresh next
4057 time we hit a `_Z'. */
4058 dyn_string_clear (mangled);
4059 }
4060
4061 dyn_string_delete (mangled);
4062 dyn_string_delete (demangled);
4063 }
4064 else
4065 /* Demangle command line arguments. */
4066 {
4067 dyn_string_t result = dyn_string_new (0);
4068
4069 /* Loop over command line arguments. */
4070 for (i = optind; i < argc; ++i)
4071 {
4072 /* Attempt to demangle. */
3b60dd8e 4073 status = cp_demangle (argv[i], result, 0);
69afa80d
AS
4074
4075 /* If it worked, print the demangled name. */
051664b0 4076 if (STATUS_NO_ERROR (status))
69afa80d 4077 printf ("%s\n", dyn_string_buf (result));
051664b0 4078 /* Abort on allocaiton failures. */
bece74bd 4079 else if (status == STATUS_ALLOCATION_FAILED)
051664b0 4080 {
3b60dd8e 4081 fprintf (stderr, "Memory allocation failed.\n");
bece74bd 4082 abort ();
051664b0 4083 }
69afa80d
AS
4084 /* If not, print the error message to stderr instead. */
4085 else
4086 fprintf (stderr, "%s\n", status);
4087 }
4088 dyn_string_delete (result);
4089 }
4090
4091 return 0;
4092}
4093
4094#endif /* STANDALONE_DEMANGLER */