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