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