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