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