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