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