]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/cp-demangle.c
use "#if defined( HAV..." instead of "#if HAV..."
[thirdparty/gcc.git] / libiberty / cp-demangle.c
CommitLineData
168d63e5 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
62c2feed 24 executable (functionally similar to c++filt, but includes this
25 demangler only). */
168d63e5 26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
68e6b6e1 31#include <sys/types.h>
32
168d63e5 33#ifdef HAVE_STDLIB_H
34#include <stdlib.h>
35#endif
36
168d63e5 37#include <stdio.h>
168d63e5 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"
4b7bc488 46#include "demangle.h"
168d63e5 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
140d75d7 51#define DEMANGLE_TRACE(PRODUCTION, DM) \
52 fprintf (stderr, " -> %-24s at position %3d\n", \
168d63e5 53 (PRODUCTION), current_position (DM));
54#else
55#define DEMANGLE_TRACE(PRODUCTION, DM)
56#endif
57
140d75d7 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
40e00cb0 65/* The prefix prepended by GCC to an identifier represnting the
66 anonymous namespace. */
67#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
68
168d63e5 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
168d63e5 99 /* Whether this substitution represents a template item. */
100 int template_p : 1;
101};
102
168d63e5 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. */
140d75d7 126 const char *name;
168d63e5 127
128 /* Pointer into name at the current position. */
140d75d7 129 const char *next;
168d63e5 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. */
140d75d7 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)
168d63e5 190
140d75d7 191static status_t int_to_dyn_string
168d63e5 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));
c1b316c0 197static status_t result_add_separated_char
62c2feed 198 PARAMS ((demangling_t, int));
140d75d7 199static status_t result_push
168d63e5 200 PARAMS ((demangling_t));
201static string_list_t result_pop
202 PARAMS ((demangling_t));
203static int substitution_start
204 PARAMS ((demangling_t));
140d75d7 205static status_t substitution_add
40e00cb0 206 PARAMS ((demangling_t, int, int));
168d63e5 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
140d75d7 232 PARAMS ((const char *));
168d63e5 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
140d75d7 241 with one. Evaluates to 1 on success, or 0 on allocation failure. */
168d63e5 242#define dyn_string_append_space(DS) \
140d75d7 243 ((dyn_string_length (DS) > 0 \
244 && dyn_string_last_char (DS) != ' ') \
245 ? dyn_string_append_char ((DS), ' ') \
246 : 1)
168d63e5 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) \
140d75d7 275 (dyn_string_append (&(DM)->result->string, (STRING)) \
276 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
168d63e5 277
278/* Appends NUL-terminated string CSTR to the demangled result. */
279#define result_append(DM, CSTR) \
140d75d7 280 (dyn_string_append_cstr (&(DM)->result->string, (CSTR)) \
281 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
168d63e5 282
283/* Appends character CHAR to the demangled result. */
284#define result_append_char(DM, CHAR) \
140d75d7 285 (dyn_string_append_char (&(DM)->result->string, (CHAR)) \
286 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
168d63e5 287
40e00cb0 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
168d63e5 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) \
140d75d7 311 (dyn_string_append_space (&(DM)->result->string) \
312 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
168d63e5 313
c1b316c0 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
140d75d7 321/* Appends a base 10 representation of VALUE to DS. STATUS_OK on
322 success. On failure, deletes DS and returns an error code. */
168d63e5 323
140d75d7 324static status_t
168d63e5 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 {
140d75d7 335 if (!dyn_string_append_char (ds, '0'))
336 return STATUS_ALLOCATION_FAILED;
337 return STATUS_OK;
168d63e5 338 }
339
340 /* For negative numbers, emit a minus sign. */
341 if (value < 0)
342 {
140d75d7 343 if (!dyn_string_append_char (ds, '-'))
344 return STATUS_ALLOCATION_FAILED;
168d63e5 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;
140d75d7 360
361 if (!dyn_string_append_char (ds, '0' + digit))
362 return STATUS_ALLOCATION_FAILED;
363
168d63e5 364 value -= digit * mask;
365 mask /= 10;
366 }
140d75d7 367
368 return STATUS_OK;
168d63e5 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
140d75d7 373 list node should be deleted with string_list_delete. Returns NULL
374 if allocation fails. */
168d63e5 375
376static string_list_t
377string_list_new (length)
378 int length;
379{
140d75d7 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;
168d63e5 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
c1b316c0 402/* Appends CHARACTER to the demangled result. If the current trailing
403 character of the result is CHARACTER, a space is inserted first. */
168d63e5 404
140d75d7 405static status_t
c1b316c0 406result_add_separated_char (dm, character)
168d63e5 407 demangling_t dm;
62c2feed 408 int character;
168d63e5 409{
410 dyn_string_t s = &dm->result->string;
140d75d7 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. */
c1b316c0 415 if (dyn_string_last_char (s) == character)
140d75d7 416 {
417 if (!dyn_string_append_char (s, ' '))
418 return STATUS_ALLOCATION_FAILED;
419 }
420
421 /* Add closing angle brackets. */
c1b316c0 422 if (!dyn_string_append_char (s, character))
140d75d7 423 return STATUS_ALLOCATION_FAILED;
424
425 return STATUS_OK;
168d63e5 426}
427
428/* Allocates and pushes a new string onto the demangled results stack
140d75d7 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. */
168d63e5 432
140d75d7 433static status_t
168d63e5 434result_push (dm)
435 demangling_t dm;
436{
437 string_list_t new_string = string_list_new (0);
140d75d7 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. */
168d63e5 443 new_string->next = (string_list_t) dm->result;
444 dm->result = new_string;
140d75d7 445 return STATUS_OK;
168d63e5 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
40e00cb0 474 non-zero, this potential substitution is a template-id. */
168d63e5 475
140d75d7 476static status_t
40e00cb0 477substitution_add (dm, start_position, template_p)
168d63e5 478 demangling_t dm;
479 int start_position;
480 int template_p;
168d63e5 481{
482 dyn_string_t result = result_string (dm);
483 dyn_string_t substitution = dyn_string_new (0);
484 int i;
485
140d75d7 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 }
168d63e5 497
168d63e5 498 /* If there's no room for the new entry, grow the array. */
499 if (dm->substitutions_allocated == dm->num_substitutions)
500 {
140d75d7 501 size_t new_array_size;
62c2feed 502 if (dm->substitutions_allocated > 0)
503 dm->substitutions_allocated *= 2;
504 else
505 dm->substitutions_allocated = 2;
140d75d7 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 }
168d63e5 517 }
518
519 /* Add the substitution to the array. */
62c2feed 520 i = dm->num_substitutions++;
168d63e5 521 dm->substitutions[i].text = substitution;
522 dm->substitutions[i].template_p = template_p;
168d63e5 523
524#ifdef CP_DEMANGLE_DEBUG
525 substitutions_print (dm, stderr);
526#endif
140d75d7 527
528 return STATUS_OK;
168d63e5 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
140d75d7 581/* Creates a new template argument list. Returns NULL if allocation
582 fails. */
168d63e5 583
584static template_arg_list_t
0b4450c1 585template_arg_list_new ()
168d63e5 586{
140d75d7 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;
168d63e5 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
140d75d7 727 result must be pushed before the returned object can be used.
728 Returns NULL if allocation fails. */
168d63e5 729
730static demangling_t
731demangling_new (name)
140d75d7 732 const char *name;
168d63e5 733{
140d75d7 734 demangling_t dm;
735 dm = (demangling_t) malloc (sizeof (struct demangling_def));
736 if (dm == NULL)
737 return NULL;
168d63e5 738
739 dm->name = name;
740 dm->next = name;
741 dm->result = NULL;
168d63e5 742 dm->num_substitutions = 0;
743 dm->substitutions_allocated = 10;
168d63e5 744 dm->template_arg_lists = NULL;
140d75d7 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 }
168d63e5 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
da8bd873 796 PARAMS ((demangling_t, int));
168d63e5 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 *));
2b6805b4 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));
168d63e5 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
40e00cb0 830 PARAMS ((demangling_t, int *, int));
168d63e5 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
40e00cb0 838 PARAMS ((demangling_t, int *));
168d63e5 839static status_t demangle_bare_function_type
40e00cb0 840 PARAMS ((demangling_t, int *));
168d63e5 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
40e00cb0 846 PARAMS ((demangling_t));
168d63e5 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
da8bd873 854 PARAMS ((demangling_t));
168d63e5 855static status_t demangle_scope_expression
856 PARAMS ((demangling_t));
857static status_t demangle_expr_primary
da8bd873 858 PARAMS ((demangling_t));
168d63e5 859static status_t demangle_substitution
62c2feed 860 PARAMS ((demangling_t, int *));
168d63e5 861static status_t demangle_local_name
862 PARAMS ((demangling_t));
863static status_t demangle_discriminator
864 PARAMS ((demangling_t, int));
4b7bc488 865static status_t cp_demangle
140d75d7 866 PARAMS ((const char *, dyn_string_t));
bb37062f 867#ifdef IN_LIBGCC2
140d75d7 868static status_t cp_demangle_type
869 PARAMS ((const char*, dyn_string_t));
bb37062f 870#endif
168d63e5 871
872/* When passed to demangle_bare_function_type, indicates that the
873 function's return type is not encoded before its parameter types. */
40e00cb0 874#define BFT_NO_RETURN_TYPE NULL
168d63e5 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;
da8bd873 882 int c;
168d63e5 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>
b7f68aff 919 ::= <special-name> */
168d63e5 920
921static status_t
922demangle_encoding (dm)
923 demangling_t dm;
924{
925 int template_p;
168d63e5 926 int start_position;
168d63e5 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
b7f68aff 936 if (peek == 'G' || peek == 'T')
168d63e5 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
40e00cb0 952 (demangle_bare_function_type (dm, &start_position));
168d63e5 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 }
168d63e5 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{
168d63e5 987 int start = substitution_start (dm);
f8aeab41 988 char peek = peek_char (dm);
40e00cb0 989 int is_std_substitution = 0;
168d63e5 990
991 DEMANGLE_TRACE ("name", dm);
992
f8aeab41 993 switch (peek)
168d63e5 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));
f8aeab41 1002 *template_p = 0;
168d63e5 1003 break;
1004
1005 case 'S':
1006 /* The `St' substitution allows a name nested in std:: to appear
b7f68aff 1007 without being enclosed in a nested name. */
168d63e5 1008 if (peek_char_next (dm) == 't')
1009 {
1010 (void) next_char (dm);
1011 (void) next_char (dm);
140d75d7 1012 RETURN_IF_ERROR (result_append (dm, "std::"));
168d63e5 1013 RETURN_IF_ERROR (demangle_unqualified_name (dm));
40e00cb0 1014 is_std_substitution = 1;
168d63e5 1015 }
1016 else
1017 {
62c2feed 1018 RETURN_IF_ERROR (demangle_substitution (dm, template_p));
168d63e5 1019 }
b7f68aff 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 {
40e00cb0 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. */
b7f68aff 1029 RETURN_IF_ERROR (demangle_template_args (dm));
62c2feed 1030 *template_p = 1;
b7f68aff 1031 }
62c2feed 1032 else
1033 *template_p = 0;
1034
168d63e5 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. */
40e00cb0 1046 RETURN_IF_ERROR (substitution_add (dm, start, 0));
168d63e5 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
f8aeab41 1062 <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E */
168d63e5 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 {
140d75d7 1078 status_t status;
1079
168d63e5 1080 /* Snarf up and emit CV qualifiers. */
1081 dyn_string_t cv_qualifiers = dyn_string_new (24);
140d75d7 1082 if (cv_qualifiers == NULL)
1083 return STATUS_ALLOCATION_FAILED;
1084
168d63e5 1085 demangle_CV_qualifiers (dm, cv_qualifiers);
140d75d7 1086 status = result_append_string (dm, cv_qualifiers);
168d63e5 1087 dyn_string_delete (cv_qualifiers);
140d75d7 1088 RETURN_IF_ERROR (status);
1089 RETURN_IF_ERROR (result_append_space (dm));
168d63e5 1090 }
1091
1092 RETURN_IF_ERROR (demangle_prefix (dm, template_p));
f8aeab41 1093 /* No need to demangle the final <unqualified-name>; demangle_prefix
1094 will handle it. */
168d63e5 1095 RETURN_IF_ERROR (demangle_char (dm, 'E'));
1096
1097 return STATUS_OK;
1098}
1099
1100/* Demangles and emits a <prefix>.
1101
f8aeab41 1102 <prefix> ::= <prefix> <unqualified-name>
168d63e5 1103 ::= <template-prefix> <template-args>
1104 ::= # empty
1105 ::= <substitution>
1106
1107 <template-prefix> ::= <prefix>
f8aeab41 1108 ::= <substitution> */
168d63e5 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
c1b316c0 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
168d63e5 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;
168d63e5 1131
1132 if (end_of_name_p (dm))
1133 return "Unexpected end of name in <compound-name>.";
1134
1135 peek = peek_char (dm);
1136
c1b316c0 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
140d75d7 1146 if (IS_DIGIT ((unsigned char) peek)
168d63e5 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)
140d75d7 1153 RETURN_IF_ERROR (result_append (dm, "::"));
168d63e5 1154 else
1155 nested = 1;
1156
1157 if (peek == 'S')
1158 /* The substitution determines whether this is a
c1b316c0 1159 template-id. */
62c2feed 1160 RETURN_IF_ERROR (demangle_substitution (dm, template_p));
168d63e5 1161 else
1162 {
f8aeab41 1163 /* It's just a name. */
168d63e5 1164 RETURN_IF_ERROR (demangle_unqualified_name (dm));
1165 *template_p = 0;
1166 }
c1b316c0 1167
1168 /* If this element was a constructor name, make a note of
1169 that. */
1170 if (peek == 'C')
1171 last_was_ctor = 1;
168d63e5 1172 }
1173 else if (peek == 'Z')
1174 RETURN_IF_ERROR (demangle_local_name (dm));
1175 else if (peek == 'I')
1176 {
168d63e5 1177 RETURN_IF_ERROR (demangle_template_args (dm));
c1b316c0 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;
168d63e5 1191 }
1192 else if (peek == 'E')
1193 /* All done. */
1194 return STATUS_OK;
1195 else
1196 return "Unexpected character in <compound-name>.";
1197
f8aeab41 1198 if (peek != 'S'
1199 && peek_char (dm) != 'E')
1200 /* Add a new substitution for the prefix thus far. */
40e00cb0 1201 RETURN_IF_ERROR (substitution_add (dm, start, *template_p));
168d63e5 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
140d75d7 1222 if (IS_DIGIT ((unsigned char) peek))
168d63e5 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. */
140d75d7 1260 RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
168d63e5 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
140d75d7 1286 if (number == NULL)
1287 return STATUS_ALLOCATION_FAILED;
1288
168d63e5 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. */
140d75d7 1322 if (!dyn_string_append_char (str, '-'))
1323 return STATUS_ALLOCATION_FAILED;
168d63e5 1324 }
1325
1326 /* Loop until we hit a non-digit. */
1327 while (1)
1328 {
1329 char peek = peek_char (dm);
140d75d7 1330 if (IS_DIGIT ((unsigned char) peek)
168d63e5 1331 || (base == 36 && peek >= 'A' && peek <= 'Z'))
140d75d7 1332 {
1333 /* Accumulate digits. */
1334 if (!dyn_string_append_char (str, next_char (dm)))
1335 return STATUS_ALLOCATION_FAILED;
1336 }
168d63e5 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);
140d75d7 1357 if (!dyn_string_resize (identifier, length))
1358 return STATUS_ALLOCATION_FAILED;
1359
168d63e5 1360 while (length-- > 0)
1361 {
1362 if (end_of_name_p (dm))
1363 return "Unexpected end of name in <identifier>.";
140d75d7 1364 if (!dyn_string_append_char (identifier, next_char (dm)))
1365 return STATUS_ALLOCATION_FAILED;
168d63e5 1366 }
1367
40e00cb0 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
168d63e5 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
40e00cb0 1449 ::= v [0-9] <source-name> # vendor extended operator */
168d63e5 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. */
4b7bc488 1460 const char *code;
168d63e5 1461 /* The source name of this operator. */
4b7bc488 1462 const char *name;
168d63e5 1463 /* The number of arguments this operator takes. */
1464 int num_args;
1465 };
1466
4b7bc488 1467 static const struct operator_code operators[] =
168d63e5 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 },
210aba33 1478 { "da", " delete[]", 1 },
168d63e5 1479 { "de", "*" , 1 },
210aba33 1480 { "dl", " delete" , 1 },
168d63e5 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 },
210aba33 1497 { "na", " new[]" , 1 },
168d63e5 1498 { "ne", "!=" , 2 },
1499 { "ng", "-" , 1 },
1500 { "nt", "!" , 1 },
210aba33 1501 { "nw", " new" , 1 },
168d63e5 1502 { "oR", "|=" , 2 },
1503 { "oo", "||" , 2 },
1504 { "or", "|" , 2 },
1505 { "pL", "+=" , 2 },
1506 { "pl", "+" , 2 },
1507 { "pm", "->*" , 2 },
1508 { "pp", "++" , 1 },
1509 { "ps", "+" , 1 },
62c2feed 1510 { "pt", "->" , 2 },
168d63e5 1511 { "qu", "?" , 3 },
1512 { "rM", "%=" , 2 },
1513 { "rS", ">>=" , 2 },
1514 { "rm", "%" , 2 },
1515 { "rs", ">>" , 2 },
210aba33 1516 { "sz", " sizeof" , 1 }
168d63e5 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);
4b7bc488 1524 const struct operator_code* p1 = operators;
1525 const struct operator_code* p2 = operators + num_operators;
168d63e5 1526
1527 DEMANGLE_TRACE ("operator-name", dm);
1528
40e00cb0 1529 /* Is this a vendor-extended operator? */
1530 if (c0 == 'v' && IS_DIGIT (c1))
168d63e5 1531 {
40e00cb0 1532 RETURN_IF_ERROR (result_append (dm, "operator "));
168d63e5 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 {
140d75d7 1541 RETURN_IF_ERROR (result_append (dm, "operator "));
168d63e5 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 {
4b7bc488 1551 const struct operator_code* p = p1 + (p2 - p1) / 2;
168d63e5 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)
140d75d7 1559 RETURN_IF_ERROR (result_append (dm, "operator"));
1560 RETURN_IF_ERROR (result_append (dm, p->name));
168d63e5 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
2b6805b4 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
168d63e5 1703/* Demangles and emits a <special-name>.
1704
1705 <special-name> ::= GV <object name> # Guard variable
168d63e5 1706 ::= TV <type> # virtual table
1707 ::= TT <type> # VTT
1708 ::= TI <type> # typeinfo structure
1709 ::= TS <type> # typeinfo name
1710
2b6805b4 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
210aba33 1726 Also demangles the special g++ manglings,
168d63e5 1727
1728 <special-name> ::= CT <type> <offset number> _ <base type>
210aba33 1729 # construction vtable
1730 ::= TF <type> # typeinfo function (old ABI only)
1731 ::= TJ <type> # java Class structure */
168d63e5 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'));
140d75d7 1748 RETURN_IF_ERROR (result_append (dm, "guard variable for "));
168d63e5 1749 RETURN_IF_ERROR (demangle_name (dm, &unused));
1750 }
1751 else if (peek == 'T')
1752 {
140d75d7 1753 status_t status = STATUS_OK;
1754
168d63e5 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);
140d75d7 1763 RETURN_IF_ERROR (result_append (dm, "vtable for "));
168d63e5 1764 RETURN_IF_ERROR (demangle_type (dm));
1765 break;
1766
1767 case 'T':
1768 /* VTT structure. */
1769 advance_char (dm);
140d75d7 1770 RETURN_IF_ERROR (result_append (dm, "VTT for "));
168d63e5 1771 RETURN_IF_ERROR (demangle_type (dm));
1772 break;
1773
1774 case 'I':
1775 /* Typeinfo structure. */
1776 advance_char (dm);
140d75d7 1777 RETURN_IF_ERROR (result_append (dm, "typeinfo for "));
168d63e5 1778 RETURN_IF_ERROR (demangle_type (dm));
1779 break;
1780
210aba33 1781 case 'F':
1782 /* Typeinfo function. Used only in old ABI with new mangling. */
1783 advance_char (dm);
140d75d7 1784 RETURN_IF_ERROR (result_append (dm, "typeinfo fn for "));
210aba33 1785 RETURN_IF_ERROR (demangle_type (dm));
1786 break;
1787
168d63e5 1788 case 'S':
1789 /* Character string containing type name, used in typeinfo. */
1790 advance_char (dm);
140d75d7 1791 RETURN_IF_ERROR (result_append (dm, "typeinfo name for "));
168d63e5 1792 RETURN_IF_ERROR (demangle_type (dm));
1793 break;
1794
210aba33 1795 case 'J':
1796 /* The java Class variable corresponding to a C++ class. */
1797 advance_char (dm);
140d75d7 1798 RETURN_IF_ERROR (result_append (dm, "java Class for "));
210aba33 1799 RETURN_IF_ERROR (demangle_type (dm));
1800 break;
1801
168d63e5 1802 case 'h':
1803 /* Non-virtual thunk. */
1804 advance_char (dm);
140d75d7 1805 RETURN_IF_ERROR (result_append (dm, "non-virtual thunk"));
2b6805b4 1806 RETURN_IF_ERROR (demangle_nv_offset (dm));
168d63e5 1807 /* Demangle the separator. */
1808 RETURN_IF_ERROR (demangle_char (dm, '_'));
1809 /* Demangle and emit the target name and function type. */
140d75d7 1810 RETURN_IF_ERROR (result_append (dm, " to "));
168d63e5 1811 RETURN_IF_ERROR (demangle_encoding (dm));
1812 break;
1813
1814 case 'v':
1815 /* Virtual thunk. */
1816 advance_char (dm);
2b6805b4 1817 RETURN_IF_ERROR (result_append (dm, "virtual thunk"));
1818 RETURN_IF_ERROR (demangle_v_offset (dm));
168d63e5 1819 /* Demangle the separator. */
1820 RETURN_IF_ERROR (demangle_char (dm, '_'));
1821 /* Demangle and emit the target function. */
2b6805b4 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 "));
168d63e5 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 {
597f928d 1841 dyn_string_t derived_type;
1842
168d63e5 1843 advance_char (dm);
140d75d7 1844 RETURN_IF_ERROR (result_append (dm, "construction vtable for "));
597f928d 1845
1846 /* Demangle the derived type off to the side. */
1847 RETURN_IF_ERROR (result_push (dm));
168d63e5 1848 RETURN_IF_ERROR (demangle_type (dm));
597f928d 1849 derived_type = (dyn_string_t) result_pop (dm);
1850
168d63e5 1851 /* Demangle the offset. */
1852 number = dyn_string_new (4);
140d75d7 1853 if (number == NULL)
597f928d 1854 {
1855 dyn_string_delete (derived_type);
1856 return STATUS_ALLOCATION_FAILED;
1857 }
168d63e5 1858 demangle_number_literally (dm, number, 10, 1);
1859 /* Demangle the underscore separator. */
597f928d 1860 status = demangle_char (dm, '_');
1861
168d63e5 1862 /* Demangle the base type. */
597f928d 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
168d63e5 1873 /* Don't display the offset unless in verbose mode. */
1874 if (flag_verbose)
1875 {
140d75d7 1876 status = result_append_char (dm, ' ');
1877 if (STATUS_NO_ERROR (status))
1878 result_append_string (dm, number);
168d63e5 1879 }
1880 dyn_string_delete (number);
140d75d7 1881 RETURN_IF_ERROR (status);
168d63e5 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
168d63e5 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",
65bcf503 1914 "allocating"
168d63e5 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);
65bcf503 1932 if (peek_char (dm) < '1' || peek_char (dm) > '3')
168d63e5 1933 return "Unrecognized constructor.";
140d75d7 1934 RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
168d63e5 1935 /* Print the flavor of the constructor if in verbose mode. */
1936 flavor = next_char (dm) - '1';
1937 if (flag_verbose)
1938 {
140d75d7 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, ']'));
168d63e5 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.";
140d75d7 1950 RETURN_IF_ERROR (result_append_char (dm, '~'));
1951 RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
168d63e5 1952 /* Print the flavor of the destructor if in verbose mode. */
1953 flavor = next_char (dm) - '0';
1954 if (flag_verbose)
1955 {
140d75d7 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, ']'));
168d63e5 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
40e00cb0 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
168d63e5 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
40e00cb0 1994demangle_type_ptr (dm, insert_pos, substitution_start)
168d63e5 1995 demangling_t dm;
40e00cb0 1996 int *insert_pos;
1997 int substitution_start;
168d63e5 1998{
1999 char next;
2000 status_t status;
40e00cb0 2001 int is_substitution_candidate = 1;
168d63e5 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. */
40e00cb0 2007 next = peek_char (dm);
2008 if (next == 'P')
168d63e5 2009 {
40e00cb0 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, '*'));
e015a852 2018 /* The next (outermost) pointer or reference character should go
2019 after this one. */
2020 ++(*insert_pos);
40e00cb0 2021 }
2022 else if (next == 'R')
2023 {
2024 /* A reference. Snarf the `R'. */
2025 advance_char (dm);
2026 /* Demangle the underlying type. */
2027 RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
2028 substitution_start));
2029 /* Insert an ampersand where we're told to; it doesn't
2030 necessarily go at the end. */
2031 RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
e015a852 2032 /* The next (outermost) pointer or reference character should go
2033 after this one. */
2034 ++(*insert_pos);
40e00cb0 2035 }
2036 else if (next == 'M')
2037 {
2038 /* A pointer-to-member. */
2039 dyn_string_t class_type;
2040
2041 /* Eat the 'M'. */
2042 advance_char (dm);
2043
2044 /* Capture the type of which this is a pointer-to-member. */
2045 RETURN_IF_ERROR (result_push (dm));
2046 RETURN_IF_ERROR (demangle_type (dm));
2047 class_type = (dyn_string_t) result_pop (dm);
2048
2049 if (peek_char (dm) == 'F')
2050 /* A pointer-to-member function. We want output along the
2051 lines of `void (C::*) (int, int)'. Demangle the function
2052 type, which would in this case give `void () (int, int)'
2053 and set *insert_pos to the spot between the first
2054 parentheses. */
2055 status = demangle_type_ptr (dm, insert_pos, substitution_start);
2056 else
2057 {
2058 /* A pointer-to-member variable. Demangle the type of the
2059 pointed-to member. */
168d63e5 2060 status = demangle_type (dm);
2061 /* Make it pretty. */
140d75d7 2062 if (STATUS_NO_ERROR (status))
2063 status = result_append_space (dm);
40e00cb0 2064 /* The pointer-to-member notation (e.g. `C::*') follows the
2065 member's type. */
2066 *insert_pos = result_length (dm);
168d63e5 2067 }
168d63e5 2068
40e00cb0 2069 /* Build the pointer-to-member notation. */
2070 if (STATUS_NO_ERROR (status))
2071 status = result_insert (dm, *insert_pos, "::*");
2072 if (STATUS_NO_ERROR (status))
2073 status = result_insert_string (dm, *insert_pos, class_type);
2074 /* There may be additional levels of (pointer or reference)
2075 indirection in this type. If so, the `*' and `&' should be
2076 added after the pointer-to-member notation (e.g. `C::*&' for
2077 a reference to a pointer-to-member of class C). */
2078 *insert_pos += dyn_string_length (class_type) + 3;
168d63e5 2079
40e00cb0 2080 /* Clean up. */
2081 dyn_string_delete (class_type);
168d63e5 2082
40e00cb0 2083 RETURN_IF_ERROR (status);
2084 }
2085 else if (next == 'F')
2086 {
2087 /* Ooh, tricky, a pointer-to-function. When we demangle the
2088 function type, the return type should go at the very
2089 beginning. */
2090 *insert_pos = result_length (dm);
2091 /* The parentheses indicate this is a function pointer or
2092 reference type. */
2093 RETURN_IF_ERROR (result_append (dm, "()"));
2094 /* Now demangle the function type. The return type will be
2095 inserted before the `()', and the argument list will go after
2096 it. */
2097 RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
2098 /* We should now have something along the lines of
2099 `void () (int, int)'. The pointer or reference characters
2100 have to inside the first set of parentheses. *insert_pos has
2101 already been updated to point past the end of the return
2102 type. Move it one character over so it points inside the
2103 `()'. */
2104 ++(*insert_pos);
168d63e5 2105 }
40e00cb0 2106 else
2107 {
2108 /* No more pointer or reference tokens; this is therefore a
2109 pointer to data. Finish up by demangling the underlying
2110 type. */
2111 RETURN_IF_ERROR (demangle_type (dm));
2112 /* The pointer or reference characters follow the underlying
2113 type, as in `int*&'. */
2114 *insert_pos = result_length (dm);
2115 /* Because of the production <type> ::= <substitution>,
2116 demangle_type will already have added the underlying type as
2117 a substitution candidate. Don't do it again. */
2118 is_substitution_candidate = 0;
2119 }
2120
2121 if (is_substitution_candidate)
2122 RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
2123
2124 return STATUS_OK;
168d63e5 2125}
2126
2127/* Demangles and emits a <type>.
2128
2129 <type> ::= <builtin-type>
2130 ::= <function-type>
2131 ::= <class-enum-type>
2132 ::= <array-type>
2133 ::= <pointer-to-member-type>
2134 ::= <template-param>
62c2feed 2135 ::= <template-template-param> <template-args>
168d63e5 2136 ::= <CV-qualifiers> <type>
2137 ::= P <type> # pointer-to
2138 ::= R <type> # reference-to
2139 ::= C <type> # complex pair (C 2000)
2140 ::= G <type> # imaginary (C 2000)
2141 ::= U <source-name> <type> # vendor extended type qualifier
2142 ::= <substitution> */
2143
2144static status_t
2145demangle_type (dm)
2146 demangling_t dm;
2147{
2148 int start = substitution_start (dm);
2149 char peek = peek_char (dm);
b7f68aff 2150 char peek_next;
168d63e5 2151 int template_p = 0;
168d63e5 2152 template_arg_list_t old_arg_list = current_template_arg_list (dm);
40e00cb0 2153 int insert_pos;
168d63e5 2154
62c2feed 2155 /* A <type> can be a <substitution>; therefore, this <type> is a
2156 substitution candidate unless a special condition holds (see
2157 below). */
2158 int is_substitution_candidate = 1;
2159
168d63e5 2160 DEMANGLE_TRACE ("type", dm);
2161
2162 /* A <class-enum-type> can start with a digit (a <source-name>), an
2163 N (a <nested-name>), or a Z (a <local-name>). */
140d75d7 2164 if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
168d63e5 2165 RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p));
62c2feed 2166 /* Lower-case letters begin <builtin-type>s, except for `r', which
2167 denotes restrict. */
2168 else if (peek >= 'a' && peek <= 'z' && peek != 'r')
168d63e5 2169 {
2170 RETURN_IF_ERROR (demangle_builtin_type (dm));
62c2feed 2171 /* Built-in types are not substitution candidates. */
2172 is_substitution_candidate = 0;
168d63e5 2173 }
2174 else
2175 switch (peek)
2176 {
2177 case 'r':
2178 case 'V':
2179 case 'K':
62c2feed 2180 /* CV-qualifiers (including restrict). We have to demangle
2181 them off to the side, since C++ syntax puts them in a funny
2182 place for qualified pointer and reference types. */
168d63e5 2183 {
2184 status_t status;
2185 dyn_string_t cv_qualifiers = dyn_string_new (24);
140d75d7 2186
2187 if (cv_qualifiers == NULL)
2188 return STATUS_ALLOCATION_FAILED;
2189
168d63e5 2190 demangle_CV_qualifiers (dm, cv_qualifiers);
2191
2192 /* If the qualifiers apply to a pointer or reference, they
2193 need to come after the whole qualified type. */
2194 if (peek_char (dm) == 'P' || peek_char (dm) == 'R')
2195 {
2196 status = demangle_type (dm);
140d75d7 2197 if (STATUS_NO_ERROR (status))
2198 status = result_append_space (dm);
2199 if (STATUS_NO_ERROR (status))
2200 status = result_append_string (dm, cv_qualifiers);
168d63e5 2201 }
2202 /* Otherwise, the qualifiers come first. */
2203 else
2204 {
140d75d7 2205 status = result_append_string (dm, cv_qualifiers);
2206 if (STATUS_NO_ERROR (status))
2207 status = result_append_space (dm);
2208 if (STATUS_NO_ERROR (status))
2209 status = demangle_type (dm);
168d63e5 2210 }
2211
2212 dyn_string_delete (cv_qualifiers);
2213 RETURN_IF_ERROR (status);
2214 }
2215 break;
2216
2217 case 'F':
2218 return "Non-pointer or -reference function type.";
2219
2220 case 'A':
2221 RETURN_IF_ERROR (demangle_array_type (dm));
2222 break;
2223
2224 case 'T':
62c2feed 2225 /* It's either a <template-param> or a
2226 <template-template-param>. In either case, demangle the
2227 `T' token first. */
40e00cb0 2228 RETURN_IF_ERROR (demangle_template_param (dm));
62c2feed 2229
2230 /* Check for a template argument list; if one is found, it's a
2231 <template-template-param> ::= <template-param>
2232 ::= <substitution> */
2233 if (peek_char (dm) == 'I')
2234 {
2235 /* Add a substitution candidate. The template parameter
2236 `T' token is a substitution candidate by itself,
2237 without the template argument list. */
40e00cb0 2238 RETURN_IF_ERROR (substitution_add (dm, start, template_p));
62c2feed 2239
2240 /* Now demangle the template argument list. */
2241 RETURN_IF_ERROR (demangle_template_args (dm));
2242 /* The entire type, including the template template
2243 parameter and its argument list, will be added as a
2244 substitution candidate below. */
2245 }
2246
168d63e5 2247 break;
2248
2249 case 'S':
b7f68aff 2250 /* First check if this is a special substitution. If it is,
2251 this is a <class-enum-type>. Special substitutions have a
2252 letter following the `S'; other substitutions have a digit
2253 or underscore. */
2254 peek_next = peek_char_next (dm);
2255 if (IS_DIGIT (peek_next) || peek_next == '_')
c1b316c0 2256 {
62c2feed 2257 RETURN_IF_ERROR (demangle_substitution (dm, &template_p));
c1b316c0 2258
2259 /* The substituted name may have been a template name.
2260 Check if template arguments follow, and if so, demangle
2261 them. */
2262 if (peek_char (dm) == 'I')
2263 RETURN_IF_ERROR (demangle_template_args (dm));
40e00cb0 2264 else
2265 /* A substitution token is not itself a substitution
2266 candidate. (However, if the substituted template is
2267 instantiated, the resulting type is.) */
2268 is_substitution_candidate = 0;
c1b316c0 2269 }
b7f68aff 2270 else
62c2feed 2271 /* While the special substitution token itself is not a
2272 substitution candidate, the <class-enum-type> is, so
2273 don't clear is_substitution_candidate. */
40e00cb0 2274 RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p));
62c2feed 2275
168d63e5 2276 break;
2277
2278 case 'P':
2279 case 'R':
2280 case 'M':
40e00cb0 2281 RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
2282 /* demangle_type_ptr adds all applicable substitution
2283 candidates. */
2284 is_substitution_candidate = 0;
168d63e5 2285 break;
2286
2287 case 'C':
2288 /* A C99 complex type. */
140d75d7 2289 RETURN_IF_ERROR (result_append (dm, "complex "));
168d63e5 2290 advance_char (dm);
2291 RETURN_IF_ERROR (demangle_type (dm));
2292 break;
2293
2294 case 'G':
2295 /* A C99 imaginary type. */
140d75d7 2296 RETURN_IF_ERROR (result_append (dm, "imaginary "));
168d63e5 2297 advance_char (dm);
2298 RETURN_IF_ERROR (demangle_type (dm));
2299 break;
2300
2301 case 'U':
40e00cb0 2302 /* Vendor-extended type qualifier. */
168d63e5 2303 advance_char (dm);
2304 RETURN_IF_ERROR (demangle_source_name (dm));
140d75d7 2305 RETURN_IF_ERROR (result_append_char (dm, ' '));
168d63e5 2306 RETURN_IF_ERROR (demangle_type (dm));
2307 break;
2308
2309 default:
2310 return "Unexpected character in <type>.";
2311 }
2312
62c2feed 2313 if (is_substitution_candidate)
168d63e5 2314 /* Add a new substitution for the type. If this type was a
2315 <template-param>, pass its index since from the point of
62c2feed 2316 substitutions; a <template-param> token is a substitution
168d63e5 2317 candidate distinct from the type that is substituted for it. */
40e00cb0 2318 RETURN_IF_ERROR (substitution_add (dm, start, template_p));
168d63e5 2319
2320 /* Pop off template argument lists added during mangling of this
2321 type. */
2322 pop_to_template_arg_list (dm, old_arg_list);
2323
2324 return STATUS_OK;
2325}
2326
2327/* C++ source names of builtin types, indexed by the mangled code
2328 letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc). */
2329static const char *const builtin_type_names[26] =
2330{
2331 "signed char", /* a */
2332 "bool", /* b */
2333 "char", /* c */
2334 "double", /* d */
2335 "long double", /* e */
2336 "float", /* f */
2337 "__float128", /* g */
2338 "unsigned char", /* h */
2339 "int", /* i */
2340 "unsigned", /* j */
2341 NULL, /* k */
2342 "long", /* l */
2343 "unsigned long", /* m */
2344 "__int128", /* n */
2345 "unsigned __int128", /* o */
2346 NULL, /* p */
2347 NULL, /* q */
2348 NULL, /* r */
2349 "short", /* s */
2350 "unsigned short", /* t */
2351 NULL, /* u */
2352 "void", /* v */
2353 "wchar_t", /* w */
2354 "long long", /* x */
2355 "unsigned long long", /* y */
2356 "..." /* z */
2357};
2358
2359/* Demangles and emits a <builtin-type>.
2360
2361 <builtin-type> ::= v # void
2362 ::= w # wchar_t
2363 ::= b # bool
2364 ::= c # char
2365 ::= a # signed char
2366 ::= h # unsigned char
2367 ::= s # short
2368 ::= t # unsigned short
2369 ::= i # int
2370 ::= j # unsigned int
2371 ::= l # long
2372 ::= m # unsigned long
2373 ::= x # long long, __int64
2374 ::= y # unsigned long long, __int64
2375 ::= n # __int128
2376 ::= o # unsigned __int128
2377 ::= f # float
2378 ::= d # double
2379 ::= e # long double, __float80
2380 ::= g # __float128
2381 ::= z # ellipsis
2382 ::= u <source-name> # vendor extended type */
2383
2384static status_t
2385demangle_builtin_type (dm)
2386 demangling_t dm;
2387{
2388
2389 char code = peek_char (dm);
2390
2391 DEMANGLE_TRACE ("builtin-type", dm);
2392
2393 if (code == 'u')
2394 {
2395 advance_char (dm);
2396 RETURN_IF_ERROR (demangle_source_name (dm));
2397 return STATUS_OK;
2398 }
2399 else if (code >= 'a' && code <= 'z')
2400 {
2401 const char *type_name = builtin_type_names[code - 'a'];
2402 if (type_name == NULL)
2403 return "Unrecognized <builtin-type> code.";
2404
140d75d7 2405 RETURN_IF_ERROR (result_append (dm, type_name));
168d63e5 2406 advance_char (dm);
2407 return STATUS_OK;
2408 }
2409 else
2410 return "Non-alphabetic <builtin-type> code.";
2411}
2412
2413/* Demangles all consecutive CV-qualifiers (const, volatile, and
2414 restrict) at the current position. The qualifiers are appended to
2415 QUALIFIERS. Returns STATUS_OK. */
2416
2417static status_t
2418demangle_CV_qualifiers (dm, qualifiers)
2419 demangling_t dm;
2420 dyn_string_t qualifiers;
2421{
2422 DEMANGLE_TRACE ("CV-qualifiers", dm);
2423
2424 while (1)
2425 {
2426 switch (peek_char (dm))
2427 {
2428 case 'r':
140d75d7 2429 if (!dyn_string_append_space (qualifiers))
2430 return STATUS_ALLOCATION_FAILED;
2431 if (!dyn_string_append_cstr (qualifiers, "restrict"))
2432 return STATUS_ALLOCATION_FAILED;
168d63e5 2433 break;
2434
2435 case 'V':
140d75d7 2436 if (!dyn_string_append_space (qualifiers))
2437 return STATUS_ALLOCATION_FAILED;
2438 if (!dyn_string_append_cstr (qualifiers, "volatile"))
2439 return STATUS_ALLOCATION_FAILED;
168d63e5 2440 break;
2441
2442 case 'K':
140d75d7 2443 if (!dyn_string_append_space (qualifiers))
2444 return STATUS_ALLOCATION_FAILED;
2445 if (!dyn_string_append_cstr (qualifiers, "const"))
2446 return STATUS_ALLOCATION_FAILED;
168d63e5 2447 break;
2448
2449 default:
2450 return STATUS_OK;
2451 }
2452
2453 advance_char (dm);
2454 }
2455}
2456
40e00cb0 2457/* Demangles and emits a <function-type>. *FUNCTION_NAME_POS is the
168d63e5 2458 position in the result string of the start of the function
40e00cb0 2459 identifier, at which the function's return type will be inserted;
2460 *FUNCTION_NAME_POS is updated to position past the end of the
2461 function's return type.
168d63e5 2462
2463 <function-type> ::= F [Y] <bare-function-type> E */
2464
2465static status_t
2466demangle_function_type (dm, function_name_pos)
2467 demangling_t dm;
40e00cb0 2468 int *function_name_pos;
168d63e5 2469{
2470 DEMANGLE_TRACE ("function-type", dm);
2471 RETURN_IF_ERROR (demangle_char (dm, 'F'));
2472 if (peek_char (dm) == 'Y')
2473 {
2474 /* Indicate this function has C linkage if in verbose mode. */
2475 if (flag_verbose)
140d75d7 2476 RETURN_IF_ERROR (result_append (dm, " [extern \"C\"] "));
168d63e5 2477 advance_char (dm);
2478 }
2479 RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
2480 RETURN_IF_ERROR (demangle_char (dm, 'E'));
2481 return STATUS_OK;
2482}
2483
2484/* Demangles and emits a <bare-function-type>. RETURN_TYPE_POS is the
2485 position in the result string at which the function return type
2486 should be inserted. If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the
2487 function's return type is assumed not to be encoded.
2488
2489 <bare-function-type> ::= <signature type>+ */
2490
2491static status_t
2492demangle_bare_function_type (dm, return_type_pos)
2493 demangling_t dm;
40e00cb0 2494 int *return_type_pos;
168d63e5 2495{
2496 /* Sequence is the index of the current function parameter, counting
2497 from zero. The value -1 denotes the return type. */
2498 int sequence =
2499 (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);
2500
2501 DEMANGLE_TRACE ("bare-function-type", dm);
2502
140d75d7 2503 RETURN_IF_ERROR (result_append_char (dm, '('));
168d63e5 2504 while (!end_of_name_p (dm) && peek_char (dm) != 'E')
2505 {
2506 if (sequence == -1)
2507 /* We're decoding the function's return type. */
2508 {
2509 dyn_string_t return_type;
140d75d7 2510 status_t status = STATUS_OK;
168d63e5 2511
2512 /* Decode the return type off to the side. */
140d75d7 2513 RETURN_IF_ERROR (result_push (dm));
168d63e5 2514 RETURN_IF_ERROR (demangle_type (dm));
2515 return_type = (dyn_string_t) result_pop (dm);
2516
140d75d7 2517 /* Add a space to the end of the type. Insert the return
2518 type where we've been asked to. */
40e00cb0 2519 if (!dyn_string_append_space (return_type))
140d75d7 2520 status = STATUS_ALLOCATION_FAILED;
40e00cb0 2521 if (STATUS_NO_ERROR (status))
2522 {
2523 if (!dyn_string_insert (result_string (dm), *return_type_pos,
2524 return_type))
2525 status = STATUS_ALLOCATION_FAILED;
2526 else
2527 *return_type_pos += dyn_string_length (return_type);
2528 }
168d63e5 2529
168d63e5 2530 dyn_string_delete (return_type);
140d75d7 2531 RETURN_IF_ERROR (status);
168d63e5 2532 }
2533 else
2534 {
2535 /* Skip `void' parameter types. One should only occur as
2536 the only type in a parameter list; in that case, we want
2537 to print `foo ()' instead of `foo (void)'. */
2538 if (peek_char (dm) == 'v')
2539 {
2540 /* Consume the v. */
2541 advance_char (dm);
2542 continue;
2543 }
2544 /* Separate parameter types by commas. */
2545 if (sequence > 0)
140d75d7 2546 RETURN_IF_ERROR (result_append (dm, ", "));
168d63e5 2547 /* Demangle the type. */
2548 RETURN_IF_ERROR (demangle_type (dm));
2549 }
2550
2551 ++sequence;
2552 }
140d75d7 2553 RETURN_IF_ERROR (result_append_char (dm, ')'));
168d63e5 2554
2555 return STATUS_OK;
2556}
2557
2558/* Demangles and emits a <class-enum-type>. *TEMPLATE_P is set to
2559 non-zero if the type is a template-id, zero otherwise.
2560
2561 <class-enum-type> ::= <name> */
2562
2563static status_t
2564demangle_class_enum_type (dm, template_p)
2565 demangling_t dm;
2566 int *template_p;
2567{
2568 DEMANGLE_TRACE ("class-enum-type", dm);
2569
2570 RETURN_IF_ERROR (demangle_name (dm, template_p));
2571 return STATUS_OK;
2572}
2573
2574/* Demangles and emits an <array-type>.
2575
65bcf503 2576 <array-type> ::= A [<dimension number>] _ <element type>
2577 ::= A <dimension expression> _ <element type> */
168d63e5 2578
2579static status_t
2580demangle_array_type (dm)
2581 demangling_t dm;
2582{
65bcf503 2583 status_t status = STATUS_OK;
2584 dyn_string_t array_size = NULL;
2585 char peek;
140d75d7 2586
65bcf503 2587 RETURN_IF_ERROR (demangle_char (dm, 'A'));
168d63e5 2588
2589 /* Demangle the array size into array_size. */
65bcf503 2590 peek = peek_char (dm);
2591 if (peek == '_')
2592 /* Array bound is omitted. This is a C99-style VLA. */
2593 ;
2594 else if (IS_DIGIT (peek_char (dm)))
2595 {
2596 /* It looks like a constant array bound. */
2597 array_size = dyn_string_new (10);
2598 if (array_size == NULL)
2599 return STATUS_ALLOCATION_FAILED;
2600 status = demangle_number_literally (dm, array_size, 10, 0);
2601 }
2602 else
2603 {
2604 /* Anything is must be an expression for a nont-constant array
2605 bound. This happens if the array type occurs in a template
2606 and the array bound references a template parameter. */
2607 RETURN_IF_ERROR (result_push (dm));
2608 RETURN_IF_ERROR (demangle_expression (dm));
2609 array_size = (dyn_string_t) result_pop (dm);
2610 }
2611 /* array_size may have been allocated by now, so we can't use
2612 RETURN_IF_ERROR until it's been deallocated. */
168d63e5 2613
2614 /* Demangle the base type of the array. */
140d75d7 2615 if (STATUS_NO_ERROR (status))
2616 status = demangle_char (dm, '_');
2617 if (STATUS_NO_ERROR (status))
2618 status = demangle_type (dm);
168d63e5 2619
2620 /* Emit the array dimension syntax. */
140d75d7 2621 if (STATUS_NO_ERROR (status))
2622 status = result_append_char (dm, '[');
65bcf503 2623 if (STATUS_NO_ERROR (status) && array_size != NULL)
140d75d7 2624 status = result_append_string (dm, array_size);
2625 if (STATUS_NO_ERROR (status))
2626 status = result_append_char (dm, ']');
65bcf503 2627 if (array_size != NULL)
2628 dyn_string_delete (array_size);
168d63e5 2629
140d75d7 2630 RETURN_IF_ERROR (status);
2631
168d63e5 2632 return STATUS_OK;
2633}
2634
40e00cb0 2635/* Demangles and emits a <template-param>.
168d63e5 2636
2637 <template-param> ::= T_ # first template parameter
2638 ::= T <parameter-2 number> _ */
2639
2640static status_t
40e00cb0 2641demangle_template_param (dm)
168d63e5 2642 demangling_t dm;
168d63e5 2643{
2644 int parm_number;
2645 template_arg_list_t current_arg_list = current_template_arg_list (dm);
2646 string_list_t arg;
2647
2648 DEMANGLE_TRACE ("template-param", dm);
2649
2650 /* Make sure there is a template argmust list in which to look up
2651 this parameter reference. */
2652 if (current_arg_list == NULL)
2653 return "Template parameter outside of template.";
2654
2655 RETURN_IF_ERROR (demangle_char (dm, 'T'));
2656 if (peek_char (dm) == '_')
2657 parm_number = 0;
2658 else
2659 {
2660 RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));
2661 ++parm_number;
2662 }
2663 RETURN_IF_ERROR (demangle_char (dm, '_'));
2664
2665 arg = template_arg_list_get_arg (current_arg_list, parm_number);
2666 if (arg == NULL)
2667 /* parm_number exceeded the number of arguments in the current
2668 template argument list. */
2669 return "Template parameter number out of bounds.";
140d75d7 2670 RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
168d63e5 2671
168d63e5 2672 return STATUS_OK;
2673}
2674
2675/* Demangles and emits a <template-args>.
2676
2677 <template-args> ::= I <template-arg>+ E */
2678
2679static status_t
2680demangle_template_args (dm)
2681 demangling_t dm;
2682{
2683 int first = 1;
140d75d7 2684 dyn_string_t old_last_source_name;
168d63e5 2685 template_arg_list_t arg_list = template_arg_list_new ();
2686
140d75d7 2687 if (arg_list == NULL)
2688 return STATUS_ALLOCATION_FAILED;
2689
168d63e5 2690 /* Preserve the most recently demangled source name. */
140d75d7 2691 old_last_source_name = dm->last_source_name;
168d63e5 2692 dm->last_source_name = dyn_string_new (0);
2693
2694 DEMANGLE_TRACE ("template-args", dm);
2695
140d75d7 2696 if (dm->last_source_name == NULL)
2697 return STATUS_ALLOCATION_FAILED;
2698
168d63e5 2699 RETURN_IF_ERROR (demangle_char (dm, 'I'));
c1b316c0 2700 RETURN_IF_ERROR (result_open_template_list (dm));
168d63e5 2701 do
2702 {
2703 string_list_t arg;
2704
2705 if (first)
2706 first = 0;
2707 else
140d75d7 2708 RETURN_IF_ERROR (result_append (dm, ", "));
168d63e5 2709
2710 /* Capture the template arg. */
140d75d7 2711 RETURN_IF_ERROR (result_push (dm));
168d63e5 2712 RETURN_IF_ERROR (demangle_template_arg (dm));
2713 arg = result_pop (dm);
2714
2715 /* Emit it in the demangled name. */
140d75d7 2716 RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
168d63e5 2717
2718 /* Save it for use in expanding <template-param>s. */
2719 template_arg_list_add_arg (arg_list, arg);
2720 }
2721 while (peek_char (dm) != 'E');
2722 /* Append the '>'. */
140d75d7 2723 RETURN_IF_ERROR (result_close_template_list (dm));
168d63e5 2724
2725 /* Consume the 'E'. */
2726 advance_char (dm);
2727
2728 /* Restore the most recent demangled source name. */
2729 dyn_string_delete (dm->last_source_name);
2730 dm->last_source_name = old_last_source_name;
2731
2732 /* Push the list onto the top of the stack of template argument
2733 lists, so that arguments from it are used from now on when
2734 expanding <template-param>s. */
2735 push_template_arg_list (dm, arg_list);
2736
2737 return STATUS_OK;
2738}
2739
2740/* This function, which does not correspond to a production in the
2741 mangling spec, handles the `literal' production for both
2742 <template-arg> and <expr-primary>. It does not expect or consume
2743 the initial `L' or final `E'. The demangling is given by:
2744
2745 <literal> ::= <type> </value/ number>
2746
2747 and the emitted output is `(type)number'. */
2748
2749static status_t
2750demangle_literal (dm)
2751 demangling_t dm;
2752{
168d63e5 2753 char peek = peek_char (dm);
140d75d7 2754 dyn_string_t value_string;
2755 status_t status;
168d63e5 2756
2757 DEMANGLE_TRACE ("literal", dm);
2758
2759 if (!flag_verbose && peek >= 'a' && peek <= 'z')
2760 {
2761 /* If not in verbose mode and this is a builtin type, see if we
2762 can produce simpler numerical output. In particular, for
2763 integer types shorter than `long', just write the number
2764 without type information; for bools, write `true' or `false'.
2765 Other refinements could be made here too. */
2766
2767 /* This constant string is used to map from <builtin-type> codes
2768 (26 letters of the alphabet) to codes that determine how the
2769 value will be displayed. The codes are:
2770 b: display as bool
2771 i: display as int
2772 l: display as long
2773 A space means the value will be represented using cast
2774 notation. */
2775 static const char *const code_map = "ibi iii ll ii i ";
2776
2777 char code = code_map[peek - 'a'];
2778 /* FIXME: Implement demangling of floats and doubles. */
2779 if (code == 'u')
2780 return STATUS_UNIMPLEMENTED;
2781 if (code == 'b')
2782 {
2783 /* It's a boolean. */
2784 char value;
2785
2786 /* Consume the b. */
2787 advance_char (dm);
2788 /* Look at the next character. It should be 0 or 1,
2789 corresponding to false or true, respectively. */
2790 value = peek_char (dm);
2791 if (value == '0')
140d75d7 2792 RETURN_IF_ERROR (result_append (dm, "false"));
168d63e5 2793 else if (value == '1')
140d75d7 2794 RETURN_IF_ERROR (result_append (dm, "true"));
168d63e5 2795 else
2796 return "Unrecognized bool constant.";
2797 /* Consume the 0 or 1. */
2798 advance_char (dm);
2799 return STATUS_OK;
2800 }
2801 else if (code == 'i' || code == 'l')
2802 {
2803 /* It's an integer or long. */
2804
2805 /* Consume the type character. */
2806 advance_char (dm);
140d75d7 2807
168d63e5 2808 /* Demangle the number and write it out. */
140d75d7 2809 value_string = dyn_string_new (0);
2810 status = demangle_number_literally (dm, value_string, 10, 1);
2811 if (STATUS_NO_ERROR (status))
2812 status = result_append_string (dm, value_string);
168d63e5 2813 /* For long integers, append an l. */
140d75d7 2814 if (code == 'l' && STATUS_NO_ERROR (status))
2815 status = result_append_char (dm, code);
2816 dyn_string_delete (value_string);
2817
2818 RETURN_IF_ERROR (status);
168d63e5 2819 return STATUS_OK;
2820 }
2821 /* ...else code == ' ', so fall through to represent this
2822 literal's type explicitly using cast syntax. */
2823 }
2824
140d75d7 2825 RETURN_IF_ERROR (result_append_char (dm, '('));
168d63e5 2826 RETURN_IF_ERROR (demangle_type (dm));
140d75d7 2827 RETURN_IF_ERROR (result_append_char (dm, ')'));
2828
2829 value_string = dyn_string_new (0);
2830 if (value_string == NULL)
2831 return STATUS_ALLOCATION_FAILED;
168d63e5 2832
140d75d7 2833 status = demangle_number_literally (dm, value_string, 10, 1);
2834 if (STATUS_NO_ERROR (status))
2835 status = result_append_string (dm, value_string);
2836 dyn_string_delete (value_string);
2837 RETURN_IF_ERROR (status);
168d63e5 2838
2839 return STATUS_OK;
2840}
2841
2842/* Demangles and emits a <template-arg>.
2843
2844 <template-arg> ::= <type> # type
2845 ::= L <type> <value number> E # literal
2846 ::= LZ <encoding> E # external name
2847 ::= X <expression> E # expression */
2848
2849static status_t
2850demangle_template_arg (dm)
2851 demangling_t dm;
2852{
2853 DEMANGLE_TRACE ("template-arg", dm);
2854
2855 switch (peek_char (dm))
2856 {
2857 case 'L':
2858 advance_char (dm);
2859
2860 if (peek_char (dm) == 'Z')
2861 {
2862 /* External name. */
2863 advance_char (dm);
2864 /* FIXME: Standard is contradictory here. */
2865 RETURN_IF_ERROR (demangle_encoding (dm));
2866 }
2867 else
2868 RETURN_IF_ERROR (demangle_literal (dm));
2869 RETURN_IF_ERROR (demangle_char (dm, 'E'));
2870 break;
2871
2872 case 'X':
2873 /* Expression. */
2874 advance_char (dm);
2875 RETURN_IF_ERROR (demangle_expression (dm));
804ddfd1 2876 RETURN_IF_ERROR (demangle_char (dm, 'E'));
168d63e5 2877 break;
2878
2879 default:
2880 RETURN_IF_ERROR (demangle_type (dm));
2881 break;
2882 }
2883
2884 return STATUS_OK;
2885}
2886
2887/* Demangles and emits an <expression>.
2888
2889 <expression> ::= <unary operator-name> <expression>
2890 ::= <binary operator-name> <expression> <expression>
2891 ::= <expr-primary>
2892 ::= <scope-expression> */
2893
2894static status_t
2895demangle_expression (dm)
2896 demangling_t dm;
2897{
2898 char peek = peek_char (dm);
2899
2900 DEMANGLE_TRACE ("expression", dm);
2901
2902 if (peek == 'L' || peek == 'T')
2903 RETURN_IF_ERROR (demangle_expr_primary (dm));
2904 else if (peek == 's' && peek_char_next (dm) == 'r')
2905 RETURN_IF_ERROR (demangle_scope_expression (dm));
2906 else
2907 /* An operator expression. */
2908 {
2909 int num_args;
140d75d7 2910 status_t status = STATUS_OK;
168d63e5 2911 dyn_string_t operator_name;
2912
2913 /* We have an operator name. Since we want to output binary
2914 operations in infix notation, capture the operator name
2915 first. */
140d75d7 2916 RETURN_IF_ERROR (result_push (dm));
168d63e5 2917 RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args));
2918 operator_name = (dyn_string_t) result_pop (dm);
2919
2920 /* If it's binary, do an operand first. */
2921 if (num_args > 1)
2922 {
140d75d7 2923 status = result_append_char (dm, '(');
2924 if (STATUS_NO_ERROR (status))
2925 status = demangle_expression (dm);
2926 if (STATUS_NO_ERROR (status))
2927 status = result_append_char (dm, ')');
168d63e5 2928 }
2929
140d75d7 2930 /* Emit the operator. */
2931 if (STATUS_NO_ERROR (status))
2932 status = result_append_string (dm, operator_name);
168d63e5 2933 dyn_string_delete (operator_name);
140d75d7 2934 RETURN_IF_ERROR (status);
2935
2936 /* Emit its second (if binary) or only (if unary) operand. */
2937 RETURN_IF_ERROR (result_append_char (dm, '('));
168d63e5 2938 RETURN_IF_ERROR (demangle_expression (dm));
140d75d7 2939 RETURN_IF_ERROR (result_append_char (dm, ')'));
168d63e5 2940
2941 /* The ternary operator takes a third operand. */
2942 if (num_args == 3)
2943 {
140d75d7 2944 RETURN_IF_ERROR (result_append (dm, ":("));
168d63e5 2945 RETURN_IF_ERROR (demangle_expression (dm));
140d75d7 2946 RETURN_IF_ERROR (result_append_char (dm, ')'));
168d63e5 2947 }
2948 }
2949
2950 return STATUS_OK;
2951}
2952
2953/* Demangles and emits a <scope-expression>.
2954
2955 <scope-expression> ::= sr <qualifying type> <source-name>
2956 ::= sr <qualifying type> <encoding> */
2957
2958static status_t
2959demangle_scope_expression (dm)
2960 demangling_t dm;
2961{
2962 RETURN_IF_ERROR (demangle_char (dm, 's'));
2963 RETURN_IF_ERROR (demangle_char (dm, 'r'));
2964 RETURN_IF_ERROR (demangle_type (dm));
140d75d7 2965 RETURN_IF_ERROR (result_append (dm, "::"));
168d63e5 2966 RETURN_IF_ERROR (demangle_encoding (dm));
2967 return STATUS_OK;
2968}
2969
2970/* Demangles and emits an <expr-primary>.
2971
2972 <expr-primary> ::= <template-param>
2973 ::= L <type> <value number> E # literal
2974 ::= L <mangled-name> E # external name */
2975
2976static status_t
2977demangle_expr_primary (dm)
2978 demangling_t dm;
2979{
2980 char peek = peek_char (dm);
168d63e5 2981
2982 DEMANGLE_TRACE ("expr-primary", dm);
2983
2984 if (peek == 'T')
40e00cb0 2985 RETURN_IF_ERROR (demangle_template_param (dm));
168d63e5 2986 else if (peek == 'L')
2987 {
2988 /* Consume the `L'. */
2989 advance_char (dm);
2990 peek = peek_char (dm);
2991
2992 if (peek == '_')
2993 RETURN_IF_ERROR (demangle_mangled_name (dm));
2994 else
2995 RETURN_IF_ERROR (demangle_literal (dm));
2996
2997 RETURN_IF_ERROR (demangle_char (dm, 'E'));
2998 }
2999 else
3000 return STATUS_ERROR;
3001
3002 return STATUS_OK;
3003}
3004
3005/* Demangles and emits a <substitution>. Sets *TEMPLATE_P to non-zero
62c2feed 3006 if the substitution is the name of a template, zero otherwise.
168d63e5 3007
3008 <substitution> ::= S <seq-id> _
3009 ::= S_
3010
3011 ::= St # ::std::
3012 ::= Sa # ::std::allocator
3013 ::= Sb # ::std::basic_string
3014 ::= Ss # ::std::basic_string<char,
3015 ::std::char_traits<char>,
3016 ::std::allocator<char> >
3017 ::= Si # ::std::basic_istream<char,
3018 std::char_traits<char> >
3019 ::= So # ::std::basic_ostream<char,
3020 std::char_traits<char> >
3021 ::= Sd # ::std::basic_iostream<char,
40e00cb0 3022 std::char_traits<char> >
168d63e5 3023*/
3024
3025static status_t
62c2feed 3026demangle_substitution (dm, template_p)
168d63e5 3027 demangling_t dm;
3028 int *template_p;
168d63e5 3029{
3030 int seq_id;
3031 int peek;
3032 dyn_string_t text;
3033
3034 DEMANGLE_TRACE ("substitution", dm);
3035
3036 RETURN_IF_ERROR (demangle_char (dm, 'S'));
168d63e5 3037
3038 /* Scan the substitution sequence index. A missing number denotes
3039 the first index. */
3040 peek = peek_char (dm);
3041 if (peek == '_')
3042 seq_id = -1;
3043 /* If the following character is 0-9 or a capital letter, interpret
3044 the sequence up to the next underscore as a base-36 substitution
3045 index. */
140d75d7 3046 else if (IS_DIGIT ((unsigned char) peek)
168d63e5 3047 || (peek >= 'A' && peek <= 'Z'))
3048 RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));
3049 else
3050 {
140d75d7 3051 const char *new_last_source_name = NULL;
3052
168d63e5 3053 switch (peek)
3054 {
3055 case 't':
140d75d7 3056 RETURN_IF_ERROR (result_append (dm, "std"));
168d63e5 3057 break;
3058
3059 case 'a':
140d75d7 3060 RETURN_IF_ERROR (result_append (dm, "std::allocator"));
3061 new_last_source_name = "allocator";
b7f68aff 3062 *template_p = 1;
168d63e5 3063 break;
3064
3065 case 'b':
140d75d7 3066 RETURN_IF_ERROR (result_append (dm, "std::basic_string"));
3067 new_last_source_name = "basic_string";
b7f68aff 3068 *template_p = 1;
168d63e5 3069 break;
3070
3071 case 's':
3072 if (!flag_verbose)
3073 {
140d75d7 3074 RETURN_IF_ERROR (result_append (dm, "std::string"));
3075 new_last_source_name = "string";
168d63e5 3076 }
3077 else
3078 {
140d75d7 3079 RETURN_IF_ERROR (result_append (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
3080 new_last_source_name = "basic_string";
168d63e5 3081 }
b7f68aff 3082 *template_p = 0;
168d63e5 3083 break;
3084
3085 case 'i':
3086 if (!flag_verbose)
3087 {
140d75d7 3088 RETURN_IF_ERROR (result_append (dm, "std::istream"));
3089 new_last_source_name = "istream";
168d63e5 3090 }
3091 else
3092 {
140d75d7 3093 RETURN_IF_ERROR (result_append (dm, "std::basic_istream<char, std::char_traints<char> >"));
3094 new_last_source_name = "basic_istream";
168d63e5 3095 }
b7f68aff 3096 *template_p = 0;
168d63e5 3097 break;
3098
3099 case 'o':
3100 if (!flag_verbose)
3101 {
140d75d7 3102 RETURN_IF_ERROR (result_append (dm, "std::ostream"));
3103 new_last_source_name = "ostream";
168d63e5 3104 }
3105 else
3106 {
140d75d7 3107 RETURN_IF_ERROR (result_append (dm, "std::basic_ostream<char, std::char_traits<char> >"));
3108 new_last_source_name = "basic_ostream";
168d63e5 3109 }
b7f68aff 3110 *template_p = 0;
168d63e5 3111 break;
3112
3113 case 'd':
3114 if (!flag_verbose)
3115 {
140d75d7 3116 RETURN_IF_ERROR (result_append (dm, "std::iostream"));
3117 new_last_source_name = "iostream";
168d63e5 3118 }
3119 else
3120 {
140d75d7 3121 RETURN_IF_ERROR (result_append (dm, "std::basic_iostream<char, std::char_traits<char> >"));
3122 new_last_source_name = "basic_iostream";
168d63e5 3123 }
b7f68aff 3124 *template_p = 0;
168d63e5 3125 break;
3126
3127 default:
3128 return "Unrecognized <substitution>.";
3129 }
3130
140d75d7 3131 /* Consume the character we just processed. */
168d63e5 3132 advance_char (dm);
140d75d7 3133
3134 if (new_last_source_name != NULL)
3135 {
3136 if (!dyn_string_copy_cstr (dm->last_source_name,
3137 new_last_source_name))
3138 return STATUS_ALLOCATION_FAILED;
3139 }
3140
168d63e5 3141 return STATUS_OK;
3142 }
3143
3144 /* Look up the substitution text. Since `S_' is the most recent
3145 substitution, `S0_' is the second-most-recent, etc., shift the
3146 numbering by one. */
3147 text = substitution_get (dm, seq_id + 1, template_p);
b7f68aff 3148 if (text == NULL)
168d63e5 3149 return "Substitution number out of range.";
3150
3151 /* Emit the substitution text. */
140d75d7 3152 RETURN_IF_ERROR (result_append_string (dm, text));
168d63e5 3153
3154 RETURN_IF_ERROR (demangle_char (dm, '_'));
3155 return STATUS_OK;
3156}
3157
3158/* Demangles and emits a <local-name>.
3159
3160 <local-name> := Z <function encoding> E <entity name> [<discriminator>]
3161 := Z <function encoding> E s [<discriminator>] */
3162
3163static status_t
3164demangle_local_name (dm)
3165 demangling_t dm;
3166{
3167 DEMANGLE_TRACE ("local-name", dm);
3168
3169 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
3170 RETURN_IF_ERROR (demangle_encoding (dm));
3171 RETURN_IF_ERROR (demangle_char (dm, 'E'));
f8aeab41 3172 RETURN_IF_ERROR (result_append (dm, "::"));
168d63e5 3173
3174 if (peek_char (dm) == 's')
3175 {
3176 /* Local character string literal. */
140d75d7 3177 RETURN_IF_ERROR (result_append (dm, "string literal"));
168d63e5 3178 /* Consume the s. */
3179 advance_char (dm);
3180 RETURN_IF_ERROR (demangle_discriminator (dm, 0));
3181 }
3182 else
3183 {
3184 int unused;
168d63e5 3185 /* Local name for some other entity. Demangle its name. */
3186 RETURN_IF_ERROR (demangle_name (dm, &unused));
3187 RETURN_IF_ERROR (demangle_discriminator (dm, 1));
3188 }
3189
3190 return STATUS_OK;
3191 }
3192
3193 /* Optimonally demangles and emits a <discriminator>. If there is no
3194 <discriminator> at the current position in the mangled string, the
3195 descriminator is assumed to be zero. Emit the discriminator number
3196 in parentheses, unless SUPPRESS_FIRST is non-zero and the
3197 discriminator is zero.
3198
3199 <discriminator> ::= _ <number> */
3200
3201static status_t
3202demangle_discriminator (dm, suppress_first)
3203 demangling_t dm;
3204 int suppress_first;
3205{
3206 /* Output for <discriminator>s to the demangled name is completely
3207 supressed if not in verbose mode. */
3208
3209 if (peek_char (dm) == '_')
3210 {
3211 /* Consume the underscore. */
3212 advance_char (dm);
3213 if (flag_verbose)
140d75d7 3214 RETURN_IF_ERROR (result_append (dm, " [#"));
168d63e5 3215 /* Check if there's a number following the underscore. */
140d75d7 3216 if (IS_DIGIT ((unsigned char) peek_char (dm)))
168d63e5 3217 {
3218 int discriminator;
3219 /* Demangle the number. */
3220 RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));
3221 if (flag_verbose)
3222 /* Write the discriminator. The mangled number is two
3223 less than the discriminator ordinal, counting from
3224 zero. */
140d75d7 3225 RETURN_IF_ERROR (int_to_dyn_string (discriminator + 2,
3226 (dyn_string_t) dm->result));
168d63e5 3227 }
3228 else
3229 {
3230 if (flag_verbose)
3231 /* A missing digit correspond to one. */
140d75d7 3232 RETURN_IF_ERROR (result_append_char (dm, '1'));
168d63e5 3233 }
3234 if (flag_verbose)
140d75d7 3235 RETURN_IF_ERROR (result_append_char (dm, ']'));
168d63e5 3236 }
3237 else if (!suppress_first)
3238 {
3239 if (flag_verbose)
140d75d7 3240 RETURN_IF_ERROR (result_append (dm, " [#0]"));
168d63e5 3241 }
3242
3243 return STATUS_OK;
3244}
3245
3246/* Demangle NAME into RESULT, which must be an initialized
3247 dyn_string_t. On success, returns STATUS_OK. On failure, returns
3248 an error message, and the contents of RESULT are unchanged. */
3249
4b7bc488 3250static status_t
168d63e5 3251cp_demangle (name, result)
140d75d7 3252 const char *name;
168d63e5 3253 dyn_string_t result;
3254{
3255 status_t status;
3256 int length = strlen (name);
3257
3258 if (length > 2 && name[0] == '_' && name[1] == 'Z')
3259 {
3260 demangling_t dm = demangling_new (name);
140d75d7 3261 if (dm == NULL)
3262 return STATUS_ALLOCATION_FAILED;
168d63e5 3263
140d75d7 3264 status = result_push (dm);
3265 if (status != STATUS_OK)
3266 {
3267 demangling_delete (dm);
3268 return status;
3269 }
168d63e5 3270
140d75d7 3271 status = demangle_mangled_name (dm);
3272 if (STATUS_NO_ERROR (status))
168d63e5 3273 {
3274 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
140d75d7 3275 if (!dyn_string_copy (result, demangled))
3276 return STATUS_ALLOCATION_FAILED;
168d63e5 3277 dyn_string_delete (demangled);
3278 }
3279
3280 demangling_delete (dm);
3281 }
3282 else
3283 {
3284 /* It's evidently not a mangled C++ name. It could be the name
3285 of something with C linkage, though, so just copy NAME into
3286 RESULT. */
140d75d7 3287 if (!dyn_string_copy_cstr (result, name))
3288 return STATUS_ALLOCATION_FAILED;
168d63e5 3289 status = STATUS_OK;
3290 }
3291
140d75d7 3292 return status;
3293}
3294
3295/* Demangle TYPE_NAME into RESULT, which must be an initialized
3296 dyn_string_t. On success, returns STATUS_OK. On failiure, returns
3297 an error message, and the contents of RESULT are unchanged. */
3298
bb37062f 3299#ifdef IN_LIBGCC2
140d75d7 3300static status_t
3301cp_demangle_type (type_name, result)
3302 const char* type_name;
3303 dyn_string_t result;
3304{
3305 status_t status;
3306 demangling_t dm = demangling_new (type_name);
3307
3308 if (dm == NULL)
3309 return STATUS_ALLOCATION_FAILED;
3310
3311 /* Demangle the type name. The demangled name is stored in dm. */
3312 status = result_push (dm);
3313 if (status != STATUS_OK)
3314 {
3315 demangling_delete (dm);
3316 return status;
3317 }
3318
3319 status = demangle_type (dm);
3320
3321 if (STATUS_NO_ERROR (status))
3322 {
3323 /* The demangling succeeded. Pop the result out of dm and copy
3324 it into RESULT. */
3325 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3326 if (!dyn_string_copy (result, demangled))
3327 return STATUS_ALLOCATION_FAILED;
3328 dyn_string_delete (demangled);
3329 }
3330
3331 /* Clean up. */
3332 demangling_delete (dm);
3333
168d63e5 3334 return status;
3335}
3336
140d75d7 3337extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
3338
3339/* ABI-mandated entry point in the C++ runtime library for performing
3340 demangling. MANGLED_NAME is a NUL-terminated character string
3341 containing the name to be demangled.
3342
3343 OUTPUT_BUFFER is a region of memory, allocated with malloc, of
3344 *LENGTH bytes, into which the demangled name is stored. If
3345 OUTPUT_BUFFER is not long enough, it is expanded using realloc.
3346 OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
3347 is placed in a region of memory allocated with malloc.
3348
3349 If LENGTH is non-NULL, the length of the buffer conaining the
3350 demangled name, is placed in *LENGTH.
3351
3352 The return value is a pointer to the start of the NUL-terminated
3353 demangled name, or NULL if the demangling fails. The caller is
3354 responsible for deallocating this memory using free.
3355
3356 *STATUS is set to one of the following values:
3357 0: The demangling operation succeeded.
3358 -1: A memory allocation failiure occurred.
3359 -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
3360 -3: One of the arguments is invalid.
3361
3362 The demagling is performed using the C++ ABI mangling rules, with
3363 GNU extensions. */
3364
3365char *
3366__cxa_demangle (mangled_name, output_buffer, length, status)
3367 const char *mangled_name;
3368 char *output_buffer;
3369 size_t *length;
3370 int *status;
3371{
3372 struct dyn_string demangled_name;
3373 status_t result;
3374
3375 if (status == NULL)
3376 return NULL;
3377
3378 if (mangled_name == NULL) {
3379 *status = -3;
3380 return NULL;
3381 }
3382
3383 /* Did the caller provide a buffer for the demangled name? */
3384 if (output_buffer == NULL) {
3385 /* No; dyn_string will malloc a buffer for us. */
3386 if (!dyn_string_init (&demangled_name, 0))
3387 {
3388 *status = -1;
3389 return NULL;
3390 }
3391 }
3392 else {
3393 /* Yes. Check that the length was provided. */
3394 if (length == NULL) {
3395 *status = -3;
3396 return NULL;
3397 }
3398 /* Install the buffer into a dyn_string. */
3399 demangled_name.allocated = *length;
3400 demangled_name.length = 0;
3401 demangled_name.s = output_buffer;
3402 }
3403
3404 if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
3405 /* MANGLED_NAME apprears to be a function or variable name.
3406 Demangle it accordingly. */
3407 result = cp_demangle (mangled_name, &demangled_name);
3408 else
3409 /* Try to demangled MANGLED_NAME as the name of a type. */
3410 result = cp_demangle_type (mangled_name, &demangled_name);
3411
3412 if (result == STATUS_OK)
3413 /* The demangling succeeded. */
3414 {
3415 /* If LENGTH isn't NULL, store the allocated buffer length
3416 there; the buffer may have been realloced by dyn_string
3417 functions. */
3418 if (length != NULL)
3419 *length = demangled_name.allocated;
3420 /* The operation was a success. */
3421 *status = 0;
3422 return dyn_string_buf (&demangled_name);
3423 }
3424 else if (result == STATUS_ALLOCATION_FAILED)
3425 /* A call to malloc or realloc failed during the demangling
3426 operation. */
3427 {
3428 *status = -1;
3429 return NULL;
3430 }
3431 else
3432 /* The demangling failed for another reason, most probably because
3433 MANGLED_NAME isn't a valid mangled name. */
3434 {
3435 /* If the buffer containing the demangled name wasn't provided
3436 by the caller, free it. */
3437 if (output_buffer == NULL)
3438 free (dyn_string_buf (&demangled_name));
3439 *status = -2;
3440 return NULL;
3441 }
3442}
3443
3444#else /* !IN_LIBGCC2 */
3445
168d63e5 3446/* Variant entry point for integration with the existing cplus-dem
3447 demangler. Attempts to demangle MANGLED. If the demangling
3448 succeeds, returns a buffer, allocated with malloc, containing the
3449 demangled name. The caller must deallocate the buffer using free.
3450 If the demangling failes, returns NULL. */
3451
3452char *
3453cplus_demangle_new_abi (mangled)
3454 const char* mangled;
3455{
3456 /* Create a dyn_string to hold the demangled name. */
3457 dyn_string_t demangled = dyn_string_new (0);
3458 /* Attempt the demangling. */
3459 status_t status = cp_demangle ((char *) mangled, demangled);
140d75d7 3460 if (STATUS_NO_ERROR (status))
168d63e5 3461 /* Demangling succeeded. */
3462 {
3463 /* Grab the demangled result from the dyn_string. It was
3464 allocated with malloc, so we can return it directly. */
3465 char *return_value = dyn_string_release (demangled);
168d63e5 3466 /* Hand back the demangled name. */
3467 return return_value;
3468 }
140d75d7 3469 else if (status == STATUS_ALLOCATION_FAILED)
3470 {
3471 fprintf (stderr, "Memory allocation failed.\n");
3472 abort ();
3473 }
168d63e5 3474 else
3475 /* Demangling failed. */
3476 {
3477 dyn_string_delete (demangled);
3478 return NULL;
3479 }
3480}
3481
140d75d7 3482#endif /* IN_LIBGCC2 */
3483
168d63e5 3484#ifdef STANDALONE_DEMANGLER
3485
3486#include "getopt.h"
3487
3488static void print_usage
3489 PARAMS ((FILE* fp, int exit_value));
3490
3491/* Non-zero if CHAR is a character than can occur in a mangled name. */
7ae7b54c 3492#define is_mangled_char(CHAR) \
40e00cb0 3493 (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \
3494 || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
168d63e5 3495
3496/* The name of this program, as invoked. */
3497const char* program_name;
3498
3499/* Prints usage summary to FP and then exits with EXIT_VALUE. */
3500
3501static void
3502print_usage (fp, exit_value)
3503 FILE* fp;
3504 int exit_value;
3505{
3506 fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
62c2feed 3507 fprintf (fp, "Options:\n");
168d63e5 3508 fprintf (fp, " -h,--help Display this message.\n");
3509 fprintf (fp, " -s,--strict Demangle standard names only.\n");
3510 fprintf (fp, " -v,--verbose Produce verbose demanglings.\n");
3511 fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n");
3512
3513 exit (exit_value);
3514}
3515
3516/* Option specification for getopt_long. */
3517static struct option long_options[] =
3518{
3519 { "help", no_argument, NULL, 'h' },
3520 { "strict", no_argument, NULL, 's' },
3521 { "verbose", no_argument, NULL, 'v' },
3522 { NULL, no_argument, NULL, 0 },
3523};
3524
3525/* Main entry for a demangling filter executable. It will demangle
3526 its command line arguments, if any. If none are provided, it will
3527 filter stdin to stdout, replacing any recognized mangled C++ names
3528 with their demangled equivalents. */
3529
3530int
3531main (argc, argv)
3532 int argc;
3533 char *argv[];
3534{
3535 status_t status;
3536 int i;
3537 int opt_char;
3538
3539 /* Use the program name of this program, as invoked. */
3540 program_name = argv[0];
3541
3542 /* Parse options. */
3543 do
3544 {
3545 opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);
3546 switch (opt_char)
3547 {
3548 case '?': /* Unrecognized option. */
3549 print_usage (stderr, 1);
3550 break;
3551
3552 case 'h':
3553 print_usage (stdout, 0);
3554 break;
3555
3556 case 's':
3557 flag_strict = 1;
3558 break;
3559
3560 case 'v':
3561 flag_verbose = 1;
3562 break;
3563 }
3564 }
3565 while (opt_char != -1);
3566
3567 if (optind == argc)
3568 /* No command line arguments were provided. Filter stdin. */
3569 {
3570 dyn_string_t mangled = dyn_string_new (3);
3571 dyn_string_t demangled = dyn_string_new (0);
3572 status_t status;
3573
3574 /* Read all of input. */
3575 while (!feof (stdin))
3576 {
3577 char c = getchar ();
3578
3579 /* The first character of a mangled name is an underscore. */
3580 if (feof (stdin))
3581 break;
3582 if (c != '_')
3583 {
3584 /* It's not a mangled name. Print the character and go
3585 on. */
3586 putchar (c);
3587 continue;
3588 }
3589 c = getchar ();
3590
3591 /* The second character of a mangled name is a capital `Z'. */
3592 if (feof (stdin))
3593 break;
3594 if (c != 'Z')
3595 {
3596 /* It's not a mangled name. Print the previous
3597 underscore, the `Z', and go on. */
3598 putchar ('_');
3599 putchar (c);
3600 continue;
3601 }
3602
3603 /* Start keeping track of the candidate mangled name. */
3604 dyn_string_append_char (mangled, '_');
3605 dyn_string_append_char (mangled, 'Z');
3606
3607 /* Pile characters into mangled until we hit one that can't
3608 occur in a mangled name. */
3609 c = getchar ();
3610 while (!feof (stdin) && is_mangled_char (c))
3611 {
3612 dyn_string_append_char (mangled, c);
3613 if (feof (stdin))
3614 break;
3615 c = getchar ();
3616 }
3617
3618 /* Attempt to demangle the name. */
3619 status = cp_demangle (dyn_string_buf (mangled), demangled);
3620
3621 /* If the demangling succeeded, great! Print out the
3622 demangled version. */
140d75d7 3623 if (STATUS_NO_ERROR (status))
168d63e5 3624 fputs (dyn_string_buf (demangled), stdout);
140d75d7 3625 /* Abort on allocation failures. */
3626 else if (status == STATUS_ALLOCATION_FAILED)
3627 {
3628 fprintf (stderr, "Memory allocation failed.\n");
3629 abort ();
3630 }
168d63e5 3631 /* Otherwise, it might not have been a mangled name. Just
3632 print out the original text. */
3633 else
3634 fputs (dyn_string_buf (mangled), stdout);
3635
3636 /* If we haven't hit EOF yet, we've read one character that
3637 can't occur in a mangled name, so print it out. */
3638 if (!feof (stdin))
3639 putchar (c);
3640
3641 /* Clear the candidate mangled name, to start afresh next
3642 time we hit a `_Z'. */
3643 dyn_string_clear (mangled);
3644 }
3645
3646 dyn_string_delete (mangled);
3647 dyn_string_delete (demangled);
3648 }
3649 else
3650 /* Demangle command line arguments. */
3651 {
3652 dyn_string_t result = dyn_string_new (0);
3653
3654 /* Loop over command line arguments. */
3655 for (i = optind; i < argc; ++i)
3656 {
3657 /* Attempt to demangle. */
3658 status = cp_demangle (argv[i], result);
3659
3660 /* If it worked, print the demangled name. */
140d75d7 3661 if (STATUS_NO_ERROR (status))
168d63e5 3662 printf ("%s\n", dyn_string_buf (result));
140d75d7 3663 /* Abort on allocaiton failures. */
b7f68aff 3664 else if (status == STATUS_ALLOCATION_FAILED)
140d75d7 3665 {
3666 fprintf (stderr, "Memory allocaiton failed.\n");
b7f68aff 3667 abort ();
140d75d7 3668 }
168d63e5 3669 /* If not, print the error message to stderr instead. */
3670 else
3671 fprintf (stderr, "%s\n", status);
3672 }
3673 dyn_string_delete (result);
3674 }
3675
3676 return 0;
3677}
3678
3679#endif /* STANDALONE_DEMANGLER */