]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/cp-demangle.c
c-common.c (decl_attributes): Differentiate between types and type decls for alignment.
[thirdparty/gcc.git] / libiberty / cp-demangle.c
CommitLineData
69afa80d
AS
1/* Demangler for IA64 / g++ standard C++ ABI.
2 Copyright (C) 2000 CodeSourcery LLC.
3 Written by Alex Samuel <samuel@codesourcery.com>.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18*/
19
20/* This file implements demangling of C++ names mangled according to
21 the IA64 / g++ standard C++ ABI. Use the cp_demangle function to
22 demangle a mangled name, or compile with the preprocessor macro
23 STANDALONE_DEMANGLER defined to create a demangling filter
24 executable. */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
69afa80d
AS
30#ifdef HAVE_STDLIB_H
31#include <stdlib.h>
32#endif
33
69afa80d 34#include <stdio.h>
69afa80d
AS
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"
7eb23b1f 43#include "demangle.h"
69afa80d
AS
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
051664b0
AS
48#define DEMANGLE_TRACE(PRODUCTION, DM) \
49 fprintf (stderr, " -> %-24s at position %3d\n", \
69afa80d
AS
50 (PRODUCTION), current_position (DM));
51#else
52#define DEMANGLE_TRACE(PRODUCTION, DM)
53#endif
54
051664b0
AS
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
69afa80d
AS
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. */
051664b0 126 const char *name;
69afa80d
AS
127
128 /* Pointer into name at the current position. */
051664b0 129 const char *next;
69afa80d
AS
130
131 /* Stack for strings containing demangled result generated so far.
132 Text is emitted to the topmost (first) string. */
133 string_list_t result;
134
135 /* The number of presently available substitutions. */
136 int num_substitutions;
137
138 /* The allocated size of the substitutions array. */
139 int substitutions_allocated;
140
141 /* An array of available substitutions. The number of elements in
142 the array is given by num_substitions, and the allocated array
143 size in substitutions_size.
144
145 The most recent substition is at the end, so
146
147 - `S_' corresponds to substititutions[num_substitutions - 1]
148 - `S0_' corresponds to substititutions[num_substitutions - 2]
149
150 etc. */
151 struct substitution_def *substitutions;
152
153 /* The stack of template argument lists. */
154 template_arg_list_t template_arg_lists;
155
156 /* The most recently demangled source-name. */
157 dyn_string_t last_source_name;
158};
159
160typedef struct demangling_def *demangling_t;
161
162/* This type is the standard return code from most functions. Values
163 other than STATUS_OK contain descriptive messages. */
164typedef const char *status_t;
165
166/* Special values that can be used as a status_t. */
051664b0
AS
167#define STATUS_OK NULL
168#define STATUS_ERROR "Error."
169#define STATUS_UNIMPLEMENTED "Unimplemented."
170#define STATUS_INTERNAL_ERROR "Internal error."
171
172/* This status code indicates a failure in malloc or realloc. */
173static const char* const status_allocation_failed = "Allocation failed.";
174#define STATUS_ALLOCATION_FAILED status_allocation_failed
175
176/* Non-zero if STATUS indicates that no error has occurred. */
177#define STATUS_NO_ERROR(STATUS) ((STATUS) == STATUS_OK)
178
179/* Evaluate EXPR, which must produce a status_t. If the status code
180 indicates an error, return from the current function with that
181 status code. */
182#define RETURN_IF_ERROR(EXPR) \
183 do \
184 { \
185 status_t s = EXPR; \
186 if (!STATUS_NO_ERROR (s)) \
187 return s; \
188 } \
189 while (0)
69afa80d 190
051664b0 191static status_t int_to_dyn_string
69afa80d
AS
192 PARAMS ((int, dyn_string_t));
193static string_list_t string_list_new
194 PARAMS ((int));
195static void string_list_delete
196 PARAMS ((string_list_t));
051664b0 197static status_t result_close_template_list
69afa80d 198 PARAMS ((demangling_t));
051664b0 199static status_t result_push
69afa80d
AS
200 PARAMS ((demangling_t));
201static string_list_t result_pop
202 PARAMS ((demangling_t));
203static int substitution_start
204 PARAMS ((demangling_t));
051664b0 205static status_t substitution_add
69afa80d
AS
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
051664b0 232 PARAMS ((const char *));
69afa80d
AS
233static void demangling_delete
234 PARAMS ((demangling_t));
235
236/* The last character of DS. Warning: DS is evaluated twice. */
237#define dyn_string_last_char(DS) \
238 (dyn_string_buf (DS)[dyn_string_length (DS) - 1])
239
240/* Append a space character (` ') to DS if it does not already end
051664b0 241 with one. Evaluates to 1 on success, or 0 on allocation failure. */
69afa80d 242#define dyn_string_append_space(DS) \
051664b0
AS
243 ((dyn_string_length (DS) > 0 \
244 && dyn_string_last_char (DS) != ' ') \
245 ? dyn_string_append_char ((DS), ' ') \
246 : 1)
69afa80d
AS
247
248/* Returns the index of the current position in the mangled name. */
249#define current_position(DM) ((DM)->next - (DM)->name)
250
251/* Returns the character at the current position of the mangled name. */
252#define peek_char(DM) (*((DM)->next))
253
254/* Returns the character one past the current position of the mangled
255 name. */
256#define peek_char_next(DM) \
257 (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1)))
258
259/* Returns the character at the current position, and advances the
260 current position to the next character. */
261#define next_char(DM) (*((DM)->next)++)
262
263/* Returns non-zero if the current position is the end of the mangled
264 name, i.e. one past the last character. */
265#define end_of_name_p(DM) (peek_char (DM) == '\0')
266
267/* Advances the current position by one character. */
268#define advance_char(DM) (++(DM)->next)
269
270/* Returns the string containing the current demangled result. */
271#define result_string(DM) (&(DM)->result->string)
272
273/* Appends a dyn_string_t to the demangled result. */
274#define result_append_string(DM, STRING) \
051664b0
AS
275 (dyn_string_append (&(DM)->result->string, (STRING)) \
276 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
69afa80d
AS
277
278/* Appends NUL-terminated string CSTR to the demangled result. */
279#define result_append(DM, CSTR) \
051664b0
AS
280 (dyn_string_append_cstr (&(DM)->result->string, (CSTR)) \
281 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
69afa80d
AS
282
283/* Appends character CHAR to the demangled result. */
284#define result_append_char(DM, CHAR) \
051664b0
AS
285 (dyn_string_append_char (&(DM)->result->string, (CHAR)) \
286 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
69afa80d
AS
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) \
051664b0
AS
295 (dyn_string_append_space (&(DM)->result->string) \
296 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
69afa80d 297
051664b0
AS
298/* Appends a base 10 representation of VALUE to DS. STATUS_OK on
299 success. On failure, deletes DS and returns an error code. */
69afa80d 300
051664b0 301static status_t
69afa80d
AS
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 {
051664b0
AS
312 if (!dyn_string_append_char (ds, '0'))
313 return STATUS_ALLOCATION_FAILED;
314 return STATUS_OK;
69afa80d
AS
315 }
316
317 /* For negative numbers, emit a minus sign. */
318 if (value < 0)
319 {
051664b0
AS
320 if (!dyn_string_append_char (ds, '-'))
321 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
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;
051664b0
AS
337
338 if (!dyn_string_append_char (ds, '0' + digit))
339 return STATUS_ALLOCATION_FAILED;
340
69afa80d
AS
341 value -= digit * mask;
342 mask /= 10;
343 }
051664b0
AS
344
345 return STATUS_OK;
69afa80d
AS
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
051664b0
AS
350 list node should be deleted with string_list_delete. Returns NULL
351 if allocation fails. */
69afa80d
AS
352
353static string_list_t
354string_list_new (length)
355 int length;
356{
051664b0
AS
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;
69afa80d
AS
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
051664b0 384static status_t
69afa80d
AS
385result_close_template_list (dm)
386 demangling_t dm;
387{
388 dyn_string_t s = &dm->result->string;
051664b0
AS
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. */
69afa80d 393 if (dyn_string_last_char (s) == '>')
051664b0
AS
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;
69afa80d
AS
404}
405
406/* Allocates and pushes a new string onto the demangled results stack
051664b0
AS
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. */
69afa80d 410
051664b0 411static status_t
69afa80d
AS
412result_push (dm)
413 demangling_t dm;
414{
415 string_list_t new_string = string_list_new (0);
051664b0
AS
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. */
69afa80d
AS
421 new_string->next = (string_list_t) dm->result;
422 dm->result = new_string;
051664b0 423 return STATUS_OK;
69afa80d
AS
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
051664b0 459static status_t
69afa80d
AS
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
051664b0
AS
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 }
69afa80d
AS
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);
051664b0 491 return STATUS_OK;
69afa80d
AS
492 }
493
494 /* If there's no room for the new entry, grow the array. */
495 if (dm->substitutions_allocated == dm->num_substitutions)
496 {
051664b0 497 size_t new_array_size;
69afa80d 498 dm->substitutions_allocated *= 2;
051664b0
AS
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 }
69afa80d
AS
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
051664b0
AS
521
522 return STATUS_OK;
69afa80d
AS
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
051664b0
AS
575/* Creates a new template argument list. Returns NULL if allocation
576 fails. */
69afa80d
AS
577
578static template_arg_list_t
6223e158 579template_arg_list_new ()
69afa80d 580{
051664b0
AS
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;
69afa80d
AS
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
051664b0
AS
721 result must be pushed before the returned object can be used.
722 Returns NULL if allocation fails. */
69afa80d
AS
723
724static demangling_t
725demangling_new (name)
051664b0 726 const char *name;
69afa80d 727{
051664b0
AS
728 demangling_t dm;
729 dm = (demangling_t) malloc (sizeof (struct demangling_def));
730 if (dm == NULL)
731 return NULL;
69afa80d
AS
732
733 dm->name = name;
734 dm->next = name;
735 dm->result = NULL;
69afa80d
AS
736 dm->num_substitutions = 0;
737 dm->substitutions_allocated = 10;
69afa80d 738 dm->template_arg_lists = NULL;
051664b0
AS
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 }
69afa80d
AS
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
69197e7e 790 PARAMS ((demangling_t, int));
69afa80d
AS
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
69197e7e 842 PARAMS ((demangling_t));
69afa80d
AS
843static status_t demangle_scope_expression
844 PARAMS ((demangling_t));
845static status_t demangle_expr_primary
69197e7e 846 PARAMS ((demangling_t));
69afa80d
AS
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));
7eb23b1f 853static status_t cp_demangle
051664b0
AS
854 PARAMS ((const char *, dyn_string_t));
855static status_t cp_demangle_type
856 PARAMS ((const char*, dyn_string_t));
69afa80d
AS
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;
69197e7e 868 int c;
69afa80d
AS
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>
905 ::= <substitution> */
906
907static status_t
908demangle_encoding (dm)
909 demangling_t dm;
910{
911 int template_p;
912 int special_std_substitution;
913 int start_position;
914 int start = substitution_start (dm);
915 template_arg_list_t old_arg_list = current_template_arg_list (dm);
916 char peek = peek_char (dm);
917
918 DEMANGLE_TRACE ("encoding", dm);
919
920 /* Remember where the name starts. If it turns out to be a template
921 function, we'll have to insert the return type here. */
922 start_position = result_length (dm);
923
924 if (peek == 'S')
925 {
926 RETURN_IF_ERROR (demangle_substitution (dm, &template_p,
927 &special_std_substitution));
928 if (special_std_substitution)
929 {
930 /* This was the magic `std::' substitution. */
051664b0 931 RETURN_IF_ERROR (result_append (dm, "::"));
69afa80d
AS
932 RETURN_IF_ERROR (demangle_encoding (dm));
933 }
934 }
935 else if (peek == 'G' || peek == 'T')
936 RETURN_IF_ERROR (demangle_special_name (dm));
937 else
938 {
939 /* Now demangle the name. */
940 RETURN_IF_ERROR (demangle_name (dm, &template_p));
941
942 /* If there's anything left, the name was a function name, with
943 maybe its return type, and its parameters types, following. */
944 if (!end_of_name_p (dm)
945 && peek_char (dm) != 'E')
946 {
947 if (template_p)
948 /* Template functions have their return type encoded. The
949 return type should be inserted at start_position. */
950 RETURN_IF_ERROR
951 (demangle_bare_function_type (dm, start_position));
952 else
953 /* Non-template functions don't have their return type
954 encoded. */
955 RETURN_IF_ERROR
956 (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE));
957 }
958
051664b0
AS
959 RETURN_IF_ERROR (substitution_add (dm, start, template_p,
960 NOT_TEMPLATE_PARM));
69afa80d
AS
961 }
962
963 /* Pop off template argument lists that were built during the
964 mangling of this name, to restore the old template context. */
965 pop_to_template_arg_list (dm, old_arg_list);
966
967 return STATUS_OK;
968}
969
970/* Demangles and emits a <name>.
971
972 <name> ::= <unscoped-name>
973 ::= <unscoped-template-name> <template-args>
974 ::= <nested-name>
975 ::= <local-name>
976
977 <unscoped-name> ::= <unqualified-name>
978 ::= St <unqualified-name> # ::std::
979
980 <unscoped-template-name>
981 ::= <unscoped-name>
982 ::= <substitution> */
983
984static status_t
985demangle_name (dm, template_p)
986 demangling_t dm;
987 int *template_p;
988{
989 int special_std_substitution;
990 int start = substitution_start (dm);
991
992 DEMANGLE_TRACE ("name", dm);
993
994 switch (peek_char (dm))
995 {
996 case 'N':
997 /* This is a <nested-name>. */
998 RETURN_IF_ERROR (demangle_nested_name (dm, template_p));
999 break;
1000
1001 case 'Z':
1002 RETURN_IF_ERROR (demangle_local_name (dm));
1003 break;
1004
1005 case 'S':
1006 /* The `St' substitution allows a name nested in std:: to appear
1007 without being enclosed in a nested name.
1008 <name> ::= St <unqualified-name> # ::std:: */
1009 if (peek_char_next (dm) == 't')
1010 {
1011 (void) next_char (dm);
1012 (void) next_char (dm);
051664b0 1013 RETURN_IF_ERROR (result_append (dm, "std::"));
69afa80d
AS
1014 RETURN_IF_ERROR (demangle_unqualified_name (dm));
1015 }
1016 else
1017 {
1018 RETURN_IF_ERROR (demangle_substitution (dm, template_p,
1019 &special_std_substitution));
1020 if (special_std_substitution)
1021 {
1022 /* This was the magic `std::' substitution. We can have
1023 a <nested-name> or one of the unscoped names
1024 following. */
051664b0 1025 RETURN_IF_ERROR (result_append (dm, "::"));
69afa80d
AS
1026 RETURN_IF_ERROR (demangle_name (dm, template_p));
1027 }
1028 }
1029 break;
1030
1031 default:
1032 /* This is an <unscoped-name> or <unscoped-template-name>. */
1033 RETURN_IF_ERROR (demangle_unqualified_name (dm));
1034
1035 /* If the <unqualified-name> is followed by template args, this
1036 is an <unscoped-template-name>. */
1037 if (peek_char (dm) == 'I')
1038 {
1039 /* Add a substitution for the unqualified template name. */
051664b0
AS
1040 RETURN_IF_ERROR (substitution_add (dm, start, 0,
1041 NOT_TEMPLATE_PARM));
69afa80d
AS
1042
1043 RETURN_IF_ERROR (demangle_template_args (dm));
1044 *template_p = 1;
1045 }
1046 else
1047 *template_p = 0;
1048
1049 break;
1050 }
1051
1052 return STATUS_OK;
1053}
1054
1055/* Demangles and emits a <nested-name>.
1056
1057 <nested-name> ::= N [<CV-qualifiers>] <prefix> <component> E */
1058
1059static status_t
1060demangle_nested_name (dm, template_p)
1061 demangling_t dm;
1062 int *template_p;
1063{
1064 char peek;
1065
1066 DEMANGLE_TRACE ("nested-name", dm);
1067
1068 RETURN_IF_ERROR (demangle_char (dm, 'N'));
1069
1070 peek = peek_char (dm);
1071 if (peek == 'r' || peek == 'V' || peek == 'K')
1072 {
051664b0
AS
1073 status_t status;
1074
69afa80d
AS
1075 /* Snarf up and emit CV qualifiers. */
1076 dyn_string_t cv_qualifiers = dyn_string_new (24);
051664b0
AS
1077 if (cv_qualifiers == NULL)
1078 return STATUS_ALLOCATION_FAILED;
1079
69afa80d 1080 demangle_CV_qualifiers (dm, cv_qualifiers);
051664b0 1081 status = result_append_string (dm, cv_qualifiers);
69afa80d 1082 dyn_string_delete (cv_qualifiers);
051664b0
AS
1083 RETURN_IF_ERROR (status);
1084 RETURN_IF_ERROR (result_append_space (dm));
69afa80d
AS
1085 }
1086
1087 RETURN_IF_ERROR (demangle_prefix (dm, template_p));
1088 /* No need to demangle the final <component>; demangle_prefix will
1089 handle it. */
1090 RETURN_IF_ERROR (demangle_char (dm, 'E'));
1091
1092 return STATUS_OK;
1093}
1094
1095/* Demangles and emits a <prefix>.
1096
1097 <prefix> ::= <prefix> <component>
1098 ::= <template-prefix> <template-args>
1099 ::= # empty
1100 ::= <substitution>
1101
1102 <template-prefix> ::= <prefix>
1103 ::= <substitution>
1104
1105 <component> ::= <unqualified-name>
1106 ::= <local-name> */
1107
1108static status_t
1109demangle_prefix (dm, template_p)
1110 demangling_t dm;
1111 int *template_p;
1112{
1113 int start = substitution_start (dm);
1114 int nested = 0;
1115
1116 /* TEMPLATE_P is updated as we decend the nesting chain. After
1117 <template-args>, it is set to non-zero; after everything else it
1118 is set to zero. */
1119
1120 DEMANGLE_TRACE ("prefix", dm);
1121
1122 while (1)
1123 {
1124 char peek;
1125 int unused;
1126
1127 if (end_of_name_p (dm))
1128 return "Unexpected end of name in <compound-name>.";
1129
1130 peek = peek_char (dm);
1131
051664b0 1132 if (IS_DIGIT ((unsigned char) peek)
69afa80d
AS
1133 || (peek >= 'a' && peek <= 'z')
1134 || peek == 'C' || peek == 'D'
1135 || peek == 'S')
1136 {
1137 /* We have another level of scope qualification. */
1138 if (nested)
051664b0 1139 RETURN_IF_ERROR (result_append (dm, "::"));
69afa80d
AS
1140 else
1141 nested = 1;
1142
1143 if (peek == 'S')
1144 /* The substitution determines whether this is a
1145 template-id. */
1146 RETURN_IF_ERROR (demangle_substitution (dm, template_p,
1147 &unused));
1148 else
1149 {
1150 RETURN_IF_ERROR (demangle_unqualified_name (dm));
1151 *template_p = 0;
1152 }
1153 }
1154 else if (peek == 'Z')
1155 RETURN_IF_ERROR (demangle_local_name (dm));
1156 else if (peek == 'I')
1157 {
1158 if (*template_p)
1159 return STATUS_INTERNAL_ERROR;
1160 /* The template name is a substitution candidate. */
051664b0 1161 RETURN_IF_ERROR (substitution_add (dm, start, 0, NOT_TEMPLATE_PARM));
69afa80d
AS
1162 RETURN_IF_ERROR (demangle_template_args (dm));
1163 *template_p = 1;
1164 }
1165 else if (peek == 'E')
1166 /* All done. */
1167 return STATUS_OK;
1168 else
1169 return "Unexpected character in <compound-name>.";
1170
1171 /* Add a new substitution for the prefix thus far. */
051664b0
AS
1172 RETURN_IF_ERROR (substitution_add (dm, start, *template_p,
1173 NOT_TEMPLATE_PARM));
69afa80d
AS
1174 }
1175}
1176
1177/* Demangles and emits an <unqualified-name>. If the
1178 <unqualified-name> is a function and the first element in the
1179 argument list should be taken to be its return type,
1180 ENCODE_RETURN_TYPE is non-zero.
1181
1182 <unqualified-name> ::= <operator-name>
1183 ::= <special-name>
1184 ::= <source-name> */
1185
1186static status_t
1187demangle_unqualified_name (dm)
1188 demangling_t dm;
1189{
1190 char peek = peek_char (dm);
1191
1192 DEMANGLE_TRACE ("unqualified-name", dm);
1193
051664b0 1194 if (IS_DIGIT ((unsigned char) peek))
69afa80d
AS
1195 RETURN_IF_ERROR (demangle_source_name (dm));
1196 else if (peek >= 'a' && peek <= 'z')
1197 {
1198 int num_args;
1199 RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args));
1200 }
1201 else if (peek == 'C' || peek == 'D')
1202 RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
1203 else
1204 return "Unexpected character in <unqualified-name>.";
1205
1206 return STATUS_OK;
1207}
1208
1209/* Demangles and emits <source-name>.
1210
1211 <source-name> ::= <length number> <identifier> */
1212
1213static status_t
1214demangle_source_name (dm)
1215 demangling_t dm;
1216{
1217 int length;
1218
1219 DEMANGLE_TRACE ("source-name", dm);
1220
1221 /* Decode the length of the identifier. */
1222 RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0));
1223 if (length == 0)
1224 return "Zero length in <source-name>.";
1225
1226 /* Now the identifier itself. It's placed into last_source_name,
1227 where it can be used to build a constructor or destructor name. */
1228 RETURN_IF_ERROR (demangle_identifier (dm, length,
1229 dm->last_source_name));
1230
1231 /* Emit it. */
051664b0 1232 RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
69afa80d
AS
1233
1234 return STATUS_OK;
1235}
1236
1237/* Demangles a number, either a <number> or a <positive-number> at the
1238 current position, consuming all consecutive digit characters. Sets
1239 *VALUE to the resulting numberand returns STATUS_OK. The number is
1240 interpreted as BASE, which must be either 10 or 36. If IS_SIGNED
1241 is non-zero, negative numbers -- prefixed with `n' -- are accepted.
1242
1243 <number> ::= [n] <positive-number>
1244
1245 <positive-number> ::= <decimal integer> */
1246
1247static status_t
1248demangle_number (dm, value, base, is_signed)
1249 demangling_t dm;
1250 int *value;
1251 int base;
1252 int is_signed;
1253{
1254 dyn_string_t number = dyn_string_new (10);
1255
1256 DEMANGLE_TRACE ("number", dm);
1257
051664b0
AS
1258 if (number == NULL)
1259 return STATUS_ALLOCATION_FAILED;
1260
69afa80d
AS
1261 demangle_number_literally (dm, number, base, is_signed);
1262 *value = strtol (dyn_string_buf (number), NULL, base);
1263 dyn_string_delete (number);
1264
1265 return STATUS_OK;
1266}
1267
1268/* Demangles a number at the current position. The digits (and minus
1269 sign, if present) that make up the number are appended to STR.
1270 Only base-BASE digits are accepted; BASE must be either 10 or 36.
1271 If IS_SIGNED, negative numbers -- prefixed with `n' -- are
1272 accepted. Does not consume a trailing underscore or other
1273 terminating character. */
1274
1275static status_t
1276demangle_number_literally (dm, str, base, is_signed)
1277 demangling_t dm;
1278 dyn_string_t str;
1279 int base;
1280 int is_signed;
1281{
1282 DEMANGLE_TRACE ("number*", dm);
1283
1284 if (base != 10 && base != 36)
1285 return STATUS_INTERNAL_ERROR;
1286
1287 /* An `n' denotes a negative number. */
1288 if (is_signed && peek_char (dm) == 'n')
1289 {
1290 /* Skip past the n. */
1291 advance_char (dm);
1292 /* The normal way to write a negative number is with a minus
1293 sign. */
051664b0
AS
1294 if (!dyn_string_append_char (str, '-'))
1295 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1296 }
1297
1298 /* Loop until we hit a non-digit. */
1299 while (1)
1300 {
1301 char peek = peek_char (dm);
051664b0 1302 if (IS_DIGIT ((unsigned char) peek)
69afa80d 1303 || (base == 36 && peek >= 'A' && peek <= 'Z'))
051664b0
AS
1304 {
1305 /* Accumulate digits. */
1306 if (!dyn_string_append_char (str, next_char (dm)))
1307 return STATUS_ALLOCATION_FAILED;
1308 }
69afa80d
AS
1309 else
1310 /* Not a digit? All done. */
1311 break;
1312 }
1313
1314 return STATUS_OK;
1315}
1316
1317/* Demangles an identifier at the current position of LENGTH
1318 characters and places it in IDENTIFIER. */
1319
1320static status_t
1321demangle_identifier (dm, length, identifier)
1322 demangling_t dm;
1323 int length;
1324 dyn_string_t identifier;
1325{
1326 DEMANGLE_TRACE ("identifier", dm);
1327
1328 dyn_string_clear (identifier);
051664b0
AS
1329 if (!dyn_string_resize (identifier, length))
1330 return STATUS_ALLOCATION_FAILED;
1331
69afa80d
AS
1332 while (length-- > 0)
1333 {
1334 if (end_of_name_p (dm))
1335 return "Unexpected end of name in <identifier>.";
051664b0
AS
1336 if (!dyn_string_append_char (identifier, next_char (dm)))
1337 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1338 }
1339
1340 return STATUS_OK;
1341}
1342
1343/* Demangles and emits an <operator-name>. If SHORT_NAME is non-zero,
1344 the short form is emitted; otherwise the full source form
1345 (`operator +' etc.) is emitted. *NUM_ARGS is set to the number of
1346 operands that the operator takes.
1347
1348 <operator-name>
1349 ::= nw # new
1350 ::= na # new[]
1351 ::= dl # delete
1352 ::= da # delete[]
1353 ::= ps # + (unary)
1354 ::= ng # - (unary)
1355 ::= ad # & (unary)
1356 ::= de # * (unary)
1357 ::= co # ~
1358 ::= pl # +
1359 ::= mi # -
1360 ::= ml # *
1361 ::= dv # /
1362 ::= rm # %
1363 ::= an # &
1364 ::= or # |
1365 ::= eo # ^
1366 ::= aS # =
1367 ::= pL # +=
1368 ::= mI # -=
1369 ::= mL # *=
1370 ::= dV # /=
1371 ::= rM # %=
1372 ::= aN # &=
1373 ::= oR # |=
1374 ::= eO # ^=
1375 ::= ls # <<
1376 ::= rs # >>
1377 ::= lS # <<=
1378 ::= rS # >>=
1379 ::= eq # ==
1380 ::= ne # !=
1381 ::= lt # <
1382 ::= gt # >
1383 ::= le # <=
1384 ::= ge # >=
1385 ::= nt # !
1386 ::= aa # &&
1387 ::= oo # ||
1388 ::= pp # ++
1389 ::= mm # --
1390 ::= cm # ,
1391 ::= pm # ->*
1392 ::= pt # ->
1393 ::= cl # ()
1394 ::= ix # []
1395 ::= qu # ?
1396 ::= sz # sizeof
1397 ::= cv <type> # cast
1398 ::= vx <source-name> # vendor extended operator */
1399
1400static status_t
1401demangle_operator_name (dm, short_name, num_args)
1402 demangling_t dm;
1403 int short_name;
1404 int *num_args;
1405{
1406 struct operator_code
1407 {
1408 /* The mangled code for this operator. */
7eb23b1f 1409 const char *code;
69afa80d 1410 /* The source name of this operator. */
7eb23b1f 1411 const char *name;
69afa80d
AS
1412 /* The number of arguments this operator takes. */
1413 int num_args;
1414 };
1415
7eb23b1f 1416 static const struct operator_code operators[] =
69afa80d
AS
1417 {
1418 { "aN", "&=" , 2 },
1419 { "aS", "=" , 2 },
1420 { "aa", "&&" , 2 },
1421 { "ad", "&" , 1 },
1422 { "an", "&" , 2 },
1423 { "cl", "()" , 0 },
1424 { "cm", "," , 2 },
1425 { "co", "~" , 1 },
1426 { "dV", "/=" , 2 },
fe06b696 1427 { "da", " delete[]", 1 },
69afa80d 1428 { "de", "*" , 1 },
fe06b696 1429 { "dl", " delete" , 1 },
69afa80d
AS
1430 { "dv", "/" , 2 },
1431 { "eO", "^=" , 2 },
1432 { "eo", "^" , 2 },
1433 { "eq", "==" , 2 },
1434 { "ge", ">=" , 2 },
1435 { "gt", ">" , 2 },
1436 { "ix", "[]" , 2 },
1437 { "lS", "<<=" , 2 },
1438 { "le", "<=" , 2 },
1439 { "ls", "<<" , 2 },
1440 { "lt", "<" , 2 },
1441 { "mI", "-=" , 2 },
1442 { "mL", "*=" , 2 },
1443 { "mi", "-" , 2 },
1444 { "ml", "*" , 2 },
1445 { "mm", "--" , 1 },
fe06b696 1446 { "na", " new[]" , 1 },
69afa80d
AS
1447 { "ne", "!=" , 2 },
1448 { "ng", "-" , 1 },
1449 { "nt", "!" , 1 },
fe06b696 1450 { "nw", " new" , 1 },
69afa80d
AS
1451 { "oR", "|=" , 2 },
1452 { "oo", "||" , 2 },
1453 { "or", "|" , 2 },
1454 { "pL", "+=" , 2 },
1455 { "pl", "+" , 2 },
1456 { "pm", "->*" , 2 },
1457 { "pp", "++" , 1 },
1458 { "ps", "+" , 1 },
1459 { "qu", "?" , 3 },
1460 { "rM", "%=" , 2 },
1461 { "rS", ">>=" , 2 },
1462 { "rm", "%" , 2 },
1463 { "rs", ">>" , 2 },
fe06b696 1464 { "sz", " sizeof" , 1 }
69afa80d
AS
1465 };
1466
1467 const int num_operators =
1468 sizeof (operators) / sizeof (struct operator_code);
1469
1470 int c0 = next_char (dm);
1471 int c1 = next_char (dm);
7eb23b1f
KG
1472 const struct operator_code* p1 = operators;
1473 const struct operator_code* p2 = operators + num_operators;
69afa80d
AS
1474
1475 DEMANGLE_TRACE ("operator-name", dm);
1476
1477 /* Is this a vendor extended operator? */
1478 if (c0 == 'v' && c1 == 'x')
1479 {
051664b0 1480 RETURN_IF_ERROR (result_append (dm, "operator"));
69afa80d
AS
1481 RETURN_IF_ERROR (demangle_source_name (dm));
1482 *num_args = 0;
1483 return STATUS_OK;
1484 }
1485
1486 /* Is this a conversion operator? */
1487 if (c0 == 'c' && c1 == 'v')
1488 {
051664b0 1489 RETURN_IF_ERROR (result_append (dm, "operator "));
69afa80d
AS
1490 /* Demangle the converted-to type. */
1491 RETURN_IF_ERROR (demangle_type (dm));
1492 *num_args = 0;
1493 return STATUS_OK;
1494 }
1495
1496 /* Perform a binary search for the operator code. */
1497 while (1)
1498 {
7eb23b1f 1499 const struct operator_code* p = p1 + (p2 - p1) / 2;
69afa80d
AS
1500 char match0 = p->code[0];
1501 char match1 = p->code[1];
1502
1503 if (c0 == match0 && c1 == match1)
1504 /* Found it. */
1505 {
1506 if (!short_name)
051664b0
AS
1507 RETURN_IF_ERROR (result_append (dm, "operator"));
1508 RETURN_IF_ERROR (result_append (dm, p->name));
69afa80d
AS
1509 *num_args = p->num_args;
1510
1511 return STATUS_OK;
1512 }
1513
1514 if (p == p1)
1515 /* Couldn't find it. */
1516 return "Unknown code in <operator-name>.";
1517
1518 /* Try again. */
1519 if (c0 < match0 || (c0 == match0 && c1 < match1))
1520 p2 = p;
1521 else
1522 p1 = p;
1523 }
1524}
1525
1526/* Demangles and emits a <special-name>.
1527
1528 <special-name> ::= GV <object name> # Guard variable
1529 ::= Th[n] <offset number> _ <base name> <base encoding>
1530 # non-virtual base override thunk
1531 ::= Tv[n] <offset number> _ <vcall offset number>
1532 _ <base encoding>
1533 # virtual base override thunk
1534 ::= TV <type> # virtual table
1535 ::= TT <type> # VTT
1536 ::= TI <type> # typeinfo structure
1537 ::= TS <type> # typeinfo name
1538
fe06b696 1539 Also demangles the special g++ manglings,
69afa80d
AS
1540
1541 <special-name> ::= CT <type> <offset number> _ <base type>
fe06b696
ZW
1542 # construction vtable
1543 ::= TF <type> # typeinfo function (old ABI only)
1544 ::= TJ <type> # java Class structure */
69afa80d
AS
1545
1546static status_t
1547demangle_special_name (dm)
1548 demangling_t dm;
1549{
1550 dyn_string_t number;
1551 int unused;
1552 char peek = peek_char (dm);
1553
1554 DEMANGLE_TRACE ("special-name", dm);
1555
1556 if (peek == 'G')
1557 {
1558 /* A guard variable name. Consume the G. */
1559 advance_char (dm);
1560 RETURN_IF_ERROR (demangle_char (dm, 'V'));
051664b0 1561 RETURN_IF_ERROR (result_append (dm, "guard variable for "));
69afa80d
AS
1562 RETURN_IF_ERROR (demangle_name (dm, &unused));
1563 }
1564 else if (peek == 'T')
1565 {
051664b0
AS
1566 status_t status = STATUS_OK;
1567
69afa80d
AS
1568 /* Other C++ implementation miscellania. Consume the T. */
1569 advance_char (dm);
1570
1571 switch (peek_char (dm))
1572 {
1573 case 'V':
1574 /* Virtual table. */
1575 advance_char (dm);
051664b0 1576 RETURN_IF_ERROR (result_append (dm, "vtable for "));
69afa80d
AS
1577 RETURN_IF_ERROR (demangle_type (dm));
1578 break;
1579
1580 case 'T':
1581 /* VTT structure. */
1582 advance_char (dm);
051664b0 1583 RETURN_IF_ERROR (result_append (dm, "VTT for "));
69afa80d
AS
1584 RETURN_IF_ERROR (demangle_type (dm));
1585 break;
1586
1587 case 'I':
1588 /* Typeinfo structure. */
1589 advance_char (dm);
051664b0 1590 RETURN_IF_ERROR (result_append (dm, "typeinfo for "));
69afa80d
AS
1591 RETURN_IF_ERROR (demangle_type (dm));
1592 break;
1593
fe06b696
ZW
1594 case 'F':
1595 /* Typeinfo function. Used only in old ABI with new mangling. */
1596 advance_char (dm);
051664b0 1597 RETURN_IF_ERROR (result_append (dm, "typeinfo fn for "));
fe06b696
ZW
1598 RETURN_IF_ERROR (demangle_type (dm));
1599 break;
1600
69afa80d
AS
1601 case 'S':
1602 /* Character string containing type name, used in typeinfo. */
1603 advance_char (dm);
051664b0 1604 RETURN_IF_ERROR (result_append (dm, "typeinfo name for "));
69afa80d
AS
1605 RETURN_IF_ERROR (demangle_type (dm));
1606 break;
1607
fe06b696
ZW
1608 case 'J':
1609 /* The java Class variable corresponding to a C++ class. */
1610 advance_char (dm);
051664b0 1611 RETURN_IF_ERROR (result_append (dm, "java Class for "));
fe06b696
ZW
1612 RETURN_IF_ERROR (demangle_type (dm));
1613 break;
1614
69afa80d
AS
1615 case 'h':
1616 /* Non-virtual thunk. */
1617 advance_char (dm);
051664b0 1618 RETURN_IF_ERROR (result_append (dm, "non-virtual thunk"));
69afa80d
AS
1619 /* Demangle and emit the offset. */
1620 number = dyn_string_new (4);
051664b0
AS
1621 if (number == NULL)
1622 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1623 demangle_number_literally (dm, number, 10, 1);
1624 /* Don't display the offset unless in verbose mode. */
1625 if (flag_verbose)
1626 {
051664b0
AS
1627 status = result_append_char (dm, ' ');
1628 if (STATUS_NO_ERROR (status))
1629 status = result_append_string (dm, number);
69afa80d
AS
1630 }
1631 dyn_string_delete (number);
051664b0 1632 RETURN_IF_ERROR (status);
69afa80d
AS
1633 /* Demangle the separator. */
1634 RETURN_IF_ERROR (demangle_char (dm, '_'));
1635 /* Demangle and emit the target name and function type. */
051664b0 1636 RETURN_IF_ERROR (result_append (dm, " to "));
69afa80d
AS
1637 RETURN_IF_ERROR (demangle_encoding (dm));
1638 break;
1639
1640 case 'v':
1641 /* Virtual thunk. */
1642 advance_char (dm);
051664b0 1643 RETURN_IF_ERROR (result_append (dm, "virtual thunk "));
69afa80d
AS
1644 /* Demangle and emit the offset. */
1645 number = dyn_string_new (4);
051664b0
AS
1646 if (number == NULL)
1647 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1648 demangle_number_literally (dm, number, 10, 1);
1649 /* Don't display the offset unless in verbose mode. */
1650 if (flag_verbose)
1651 {
051664b0
AS
1652 status = result_append_string (dm, number);
1653 if (STATUS_NO_ERROR (status))
1654 result_append_char (dm, ' ');
69afa80d
AS
1655 }
1656 dyn_string_delete (number);
051664b0 1657 RETURN_IF_ERROR (status);
69afa80d
AS
1658 /* Demangle the separator. */
1659 RETURN_IF_ERROR (demangle_char (dm, '_'));
1660 /* Demangle and emit the vcall offset. */
1661 number = dyn_string_new (4);
051664b0
AS
1662 if (number == NULL)
1663 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1664 demangle_number_literally (dm, number, 10, 1);
1665 /* Don't display the vcall offset unless in verbose mode. */
1666 if (flag_verbose)
1667 {
051664b0
AS
1668 status = result_append_string (dm, number);
1669 if (STATUS_NO_ERROR (status))
1670 status = result_append_char (dm, ' ');
69afa80d
AS
1671 }
1672 dyn_string_delete (number);
051664b0 1673 RETURN_IF_ERROR (status);
69afa80d
AS
1674 /* Demangle the separator. */
1675 RETURN_IF_ERROR (demangle_char (dm, '_'));
1676 /* Demangle and emit the target function. */
051664b0 1677 RETURN_IF_ERROR (result_append (dm, "to "));
69afa80d
AS
1678 RETURN_IF_ERROR (demangle_encoding (dm));
1679 break;
1680
1681 case 'C':
1682 /* TC is a special g++ mangling for a construction vtable. */
1683 if (!flag_strict)
1684 {
229b8ec7
AS
1685 dyn_string_t derived_type;
1686
69afa80d 1687 advance_char (dm);
051664b0 1688 RETURN_IF_ERROR (result_append (dm, "construction vtable for "));
229b8ec7
AS
1689
1690 /* Demangle the derived type off to the side. */
1691 RETURN_IF_ERROR (result_push (dm));
69afa80d 1692 RETURN_IF_ERROR (demangle_type (dm));
229b8ec7
AS
1693 derived_type = (dyn_string_t) result_pop (dm);
1694
69afa80d
AS
1695 /* Demangle the offset. */
1696 number = dyn_string_new (4);
051664b0 1697 if (number == NULL)
229b8ec7
AS
1698 {
1699 dyn_string_delete (derived_type);
1700 return STATUS_ALLOCATION_FAILED;
1701 }
69afa80d
AS
1702 demangle_number_literally (dm, number, 10, 1);
1703 /* Demangle the underscore separator. */
229b8ec7
AS
1704 status = demangle_char (dm, '_');
1705
69afa80d 1706 /* Demangle the base type. */
229b8ec7
AS
1707 if (STATUS_NO_ERROR (status))
1708 status = demangle_type (dm);
1709
1710 /* Emit the derived type. */
1711 if (STATUS_NO_ERROR (status))
1712 status = result_append (dm, "-in-");
1713 if (STATUS_NO_ERROR (status))
1714 status = result_append_string (dm, derived_type);
1715 dyn_string_delete (derived_type);
1716
69afa80d
AS
1717 /* Don't display the offset unless in verbose mode. */
1718 if (flag_verbose)
1719 {
051664b0
AS
1720 status = result_append_char (dm, ' ');
1721 if (STATUS_NO_ERROR (status))
1722 result_append_string (dm, number);
69afa80d
AS
1723 }
1724 dyn_string_delete (number);
051664b0 1725 RETURN_IF_ERROR (status);
69afa80d
AS
1726 break;
1727 }
1728 /* If flag_strict, fall through. */
1729
1730 default:
1731 return "Unrecognized <special-name>.";
1732 }
1733 }
1734 else
1735 return STATUS_ERROR;
1736
1737 return STATUS_OK;
1738}
1739
1740/* Demangles and emits a <ctor-dtor-name>.
1741
1742 <ctor-dtor-name>
1743 ::= C1 # complete object (in-charge) ctor
1744 ::= C2 # base object (not-in-charge) ctor
1745 ::= C3 # complete object (in-charge) allocating ctor
1746 ::= C4 # base object (not-in-charge) allocating ctor
1747 ::= D0 # deleting (in-charge) dtor
1748 ::= D1 # complete object (in-charge) dtor
1749 ::= D2 # base object (not-in-charge) dtor */
1750
1751static status_t
1752demangle_ctor_dtor_name (dm)
1753 demangling_t dm;
1754{
1755 static const char *const ctor_flavors[] =
1756 {
1757 "in-charge",
1758 "not-in-charge",
1759 "in-charge allocating",
1760 "not-in-charge allocating"
1761 };
1762 static const char *const dtor_flavors[] =
1763 {
1764 "in-charge deleting",
1765 "in-charge",
1766 "not-in-charge"
1767 };
1768
1769 int flavor;
1770 char peek = peek_char (dm);
1771
1772 DEMANGLE_TRACE ("ctor-dtor-name", dm);
1773
1774 if (peek == 'C')
1775 {
1776 /* A constructor name. Consume the C. */
1777 advance_char (dm);
1778 if (peek_char (dm) < '1' || peek_char (dm) > '4')
1779 return "Unrecognized constructor.";
051664b0 1780 RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
69afa80d
AS
1781 /* Print the flavor of the constructor if in verbose mode. */
1782 flavor = next_char (dm) - '1';
1783 if (flag_verbose)
1784 {
051664b0
AS
1785 RETURN_IF_ERROR (result_append (dm, "["));
1786 RETURN_IF_ERROR (result_append (dm, ctor_flavors[flavor]));
1787 RETURN_IF_ERROR (result_append_char (dm, ']'));
69afa80d
AS
1788 }
1789 }
1790 else if (peek == 'D')
1791 {
1792 /* A destructor name. Consume the D. */
1793 advance_char (dm);
1794 if (peek_char (dm) < '0' || peek_char (dm) > '2')
1795 return "Unrecognized destructor.";
051664b0
AS
1796 RETURN_IF_ERROR (result_append_char (dm, '~'));
1797 RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
69afa80d
AS
1798 /* Print the flavor of the destructor if in verbose mode. */
1799 flavor = next_char (dm) - '0';
1800 if (flag_verbose)
1801 {
051664b0
AS
1802 RETURN_IF_ERROR (result_append (dm, " ["));
1803 RETURN_IF_ERROR (result_append (dm, dtor_flavors[flavor]));
1804 RETURN_IF_ERROR (result_append_char (dm, ']'));
69afa80d
AS
1805 }
1806 }
1807 else
1808 return STATUS_ERROR;
1809
1810 return STATUS_OK;
1811}
1812
1813/* Handle pointer, reference, and pointer-to-member cases for
1814 demangle_type. All consecutive `P's, `R's, and 'M's are joined to
1815 build a pointer/reference type. We snarf all these, plus the
1816 following <type>, all at once since we need to know whether we have
1817 a pointer to data or pointer to function to construct the right
1818 output syntax. C++'s pointer syntax is hairy.
1819
1820 <type> ::= P <type>
1821 ::= R <type>
1822 ::= <pointer-to-member-type>
1823
1824 <pointer-to-member-type> ::= M </class/ type> </member/ type> */
1825
1826static status_t
1827demangle_type_ptr (dm)
1828 demangling_t dm;
1829{
1830 char next;
1831 status_t status;
1832
1833 /* Collect pointer symbols into this string. */
1834 dyn_string_t symbols = dyn_string_new (10);
1835
1836 DEMANGLE_TRACE ("type*", dm);
1837
051664b0
AS
1838 if (symbols == NULL)
1839 return STATUS_ALLOCATION_FAILED;
1840
69afa80d
AS
1841 /* Scan forward, collecting pointers and references into symbols,
1842 until we hit something else. Then emit the type. */
1843 while (1)
1844 {
1845 next = peek_char (dm);
1846 if (next == 'P')
1847 {
051664b0
AS
1848 if (!dyn_string_append_char (symbols, '*'))
1849 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1850 advance_char (dm);
1851 }
1852 else if (next == 'R')
1853 {
051664b0
AS
1854 if (!dyn_string_append_char (symbols, '&'))
1855 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1856 advance_char (dm);
1857 }
1858 else if (next == 'M')
1859 {
1860 /* Pointer-to-member. */
1861 dyn_string_t class_type;
1862
1863 /* Eat the 'M'. */
1864 advance_char (dm);
1865
1866 /* Capture the type of which this is a pointer-to-member. */
051664b0 1867 RETURN_IF_ERROR (result_push (dm));
69afa80d
AS
1868 RETURN_IF_ERROR (demangle_type (dm));
1869 class_type = (dyn_string_t) result_pop (dm);
1870
1871 /* Build the pointer-to-member notation. It comes before
1872 other pointer and reference qualifiers -- */
051664b0
AS
1873 if (!dyn_string_prepend_cstr (symbols, "::*"))
1874 return STATUS_ALLOCATION_FAILED;
1875 if (!dyn_string_prepend (symbols, class_type))
1876 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
1877 dyn_string_delete (class_type);
1878
1879 if (peek_char (dm) == 'F')
1880 continue;
1881
1882 /* Demangle the type of the pointed-to member. */
1883 status = demangle_type (dm);
1884 /* Make it pretty. */
051664b0
AS
1885 if (STATUS_NO_ERROR (status))
1886 status = result_append_space (dm);
69afa80d
AS
1887 /* Add the pointer-to-member syntax, and other pointer and
1888 reference symbols. */
051664b0
AS
1889 if (STATUS_NO_ERROR (status))
1890 status = result_append_string (dm, symbols);
69afa80d
AS
1891 /* Clean up. */
1892 dyn_string_delete (symbols);
1893
1894 RETURN_IF_ERROR (status);
1895 return STATUS_OK;
1896 }
1897 else if (next == 'F')
1898 {
1899 /* Ooh, tricky, a pointer-to-function. */
1900 int position = result_length (dm);
051664b0
AS
1901 status = result_append_char (dm, '(');
1902 if (STATUS_NO_ERROR (status))
1903 status = result_append_string (dm, symbols);
1904 if (STATUS_NO_ERROR (status))
1905 status = result_append_char (dm, ')');
69afa80d 1906 dyn_string_delete (symbols);
051664b0 1907 RETURN_IF_ERROR (status);
69afa80d
AS
1908
1909 RETURN_IF_ERROR (demangle_function_type (dm, position));
1910 return STATUS_OK;
1911 }
1912 else
1913 {
1914 /* No more pointe or reference tokens. Finish up. */
1915 status = demangle_type (dm);
1916
051664b0
AS
1917 if (STATUS_NO_ERROR (status))
1918 status = result_append_string (dm, symbols);
69afa80d 1919 dyn_string_delete (symbols);
051664b0 1920 RETURN_IF_ERROR (status);
69afa80d
AS
1921
1922 RETURN_IF_ERROR (status);
1923 return STATUS_OK;
1924 }
1925 }
1926}
1927
1928/* Demangles and emits a <type>.
1929
1930 <type> ::= <builtin-type>
1931 ::= <function-type>
1932 ::= <class-enum-type>
1933 ::= <array-type>
1934 ::= <pointer-to-member-type>
1935 ::= <template-param>
1936 ::= <CV-qualifiers> <type>
1937 ::= P <type> # pointer-to
1938 ::= R <type> # reference-to
1939 ::= C <type> # complex pair (C 2000)
1940 ::= G <type> # imaginary (C 2000)
1941 ::= U <source-name> <type> # vendor extended type qualifier
1942 ::= <substitution> */
1943
1944static status_t
1945demangle_type (dm)
1946 demangling_t dm;
1947{
1948 int start = substitution_start (dm);
1949 char peek = peek_char (dm);
1950 int template_p = 0;
1951 int special_std_substitution;
1952 int is_builtin_type = 0;
1953 template_arg_list_t old_arg_list = current_template_arg_list (dm);
1954 int template_parm = NOT_TEMPLATE_PARM;
1955
1956 DEMANGLE_TRACE ("type", dm);
1957
1958 /* A <class-enum-type> can start with a digit (a <source-name>), an
1959 N (a <nested-name>), or a Z (a <local-name>). */
051664b0 1960 if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
69afa80d
AS
1961 RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p));
1962 else if (peek >= 'a' && peek <= 'z')
1963 {
1964 RETURN_IF_ERROR (demangle_builtin_type (dm));
1965 is_builtin_type = 1;
1966 }
1967 else
1968 switch (peek)
1969 {
1970 case 'r':
1971 case 'V':
1972 case 'K':
1973 {
1974 status_t status;
1975 dyn_string_t cv_qualifiers = dyn_string_new (24);
051664b0
AS
1976
1977 if (cv_qualifiers == NULL)
1978 return STATUS_ALLOCATION_FAILED;
1979
69afa80d
AS
1980 demangle_CV_qualifiers (dm, cv_qualifiers);
1981
1982 /* If the qualifiers apply to a pointer or reference, they
1983 need to come after the whole qualified type. */
1984 if (peek_char (dm) == 'P' || peek_char (dm) == 'R')
1985 {
1986 status = demangle_type (dm);
051664b0
AS
1987 if (STATUS_NO_ERROR (status))
1988 status = result_append_space (dm);
1989 if (STATUS_NO_ERROR (status))
1990 status = result_append_string (dm, cv_qualifiers);
69afa80d
AS
1991 }
1992 /* Otherwise, the qualifiers come first. */
1993 else
1994 {
051664b0
AS
1995 status = result_append_string (dm, cv_qualifiers);
1996 if (STATUS_NO_ERROR (status))
1997 status = result_append_space (dm);
1998 if (STATUS_NO_ERROR (status))
1999 status = demangle_type (dm);
69afa80d
AS
2000 }
2001
2002 dyn_string_delete (cv_qualifiers);
2003 RETURN_IF_ERROR (status);
2004 }
2005 break;
2006
2007 case 'F':
2008 return "Non-pointer or -reference function type.";
2009
2010 case 'A':
2011 RETURN_IF_ERROR (demangle_array_type (dm));
2012 break;
2013
2014 case 'T':
2015 RETURN_IF_ERROR (demangle_template_param (dm, &template_parm));
2016 break;
2017
2018 case 'S':
2019 RETURN_IF_ERROR (demangle_substitution (dm, &template_p,
2020 &special_std_substitution));
2021 if (special_std_substitution)
2022 {
2023 /* This was the magic `std::' substitution. What follows
2024 must be a class name in that namespace. */
051664b0 2025 RETURN_IF_ERROR (result_append (dm, "::"));
69afa80d
AS
2026 RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p));
2027 }
2028 break;
2029
2030 case 'P':
2031 case 'R':
2032 case 'M':
2033 RETURN_IF_ERROR (demangle_type_ptr (dm));
2034 break;
2035
2036 case 'C':
2037 /* A C99 complex type. */
051664b0 2038 RETURN_IF_ERROR (result_append (dm, "complex "));
69afa80d
AS
2039 advance_char (dm);
2040 RETURN_IF_ERROR (demangle_type (dm));
2041 break;
2042
2043 case 'G':
2044 /* A C99 imaginary type. */
051664b0 2045 RETURN_IF_ERROR (result_append (dm, "imaginary "));
69afa80d
AS
2046 advance_char (dm);
2047 RETURN_IF_ERROR (demangle_type (dm));
2048 break;
2049
2050 case 'U':
2051 /* Vendor extended type qualifier. */
2052 advance_char (dm);
2053 RETURN_IF_ERROR (demangle_source_name (dm));
051664b0 2054 RETURN_IF_ERROR (result_append_char (dm, ' '));
69afa80d
AS
2055 RETURN_IF_ERROR (demangle_type (dm));
2056 break;
2057
2058 default:
2059 return "Unexpected character in <type>.";
2060 }
2061
2062 /* Unqualified builin types are not substitution candidates. */
2063 if (!is_builtin_type)
2064 /* Add a new substitution for the type. If this type was a
2065 <template-param>, pass its index since from the point of
2066 substitutions, a <template-param> token is a substitution
2067 candidate distinct from the type that is substituted for it. */
051664b0 2068 RETURN_IF_ERROR (substitution_add (dm, start, template_p, template_parm));
69afa80d
AS
2069
2070 /* Pop off template argument lists added during mangling of this
2071 type. */
2072 pop_to_template_arg_list (dm, old_arg_list);
2073
2074 return STATUS_OK;
2075}
2076
2077/* C++ source names of builtin types, indexed by the mangled code
2078 letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc). */
2079static const char *const builtin_type_names[26] =
2080{
2081 "signed char", /* a */
2082 "bool", /* b */
2083 "char", /* c */
2084 "double", /* d */
2085 "long double", /* e */
2086 "float", /* f */
2087 "__float128", /* g */
2088 "unsigned char", /* h */
2089 "int", /* i */
2090 "unsigned", /* j */
2091 NULL, /* k */
2092 "long", /* l */
2093 "unsigned long", /* m */
2094 "__int128", /* n */
2095 "unsigned __int128", /* o */
2096 NULL, /* p */
2097 NULL, /* q */
2098 NULL, /* r */
2099 "short", /* s */
2100 "unsigned short", /* t */
2101 NULL, /* u */
2102 "void", /* v */
2103 "wchar_t", /* w */
2104 "long long", /* x */
2105 "unsigned long long", /* y */
2106 "..." /* z */
2107};
2108
2109/* Demangles and emits a <builtin-type>.
2110
2111 <builtin-type> ::= v # void
2112 ::= w # wchar_t
2113 ::= b # bool
2114 ::= c # char
2115 ::= a # signed char
2116 ::= h # unsigned char
2117 ::= s # short
2118 ::= t # unsigned short
2119 ::= i # int
2120 ::= j # unsigned int
2121 ::= l # long
2122 ::= m # unsigned long
2123 ::= x # long long, __int64
2124 ::= y # unsigned long long, __int64
2125 ::= n # __int128
2126 ::= o # unsigned __int128
2127 ::= f # float
2128 ::= d # double
2129 ::= e # long double, __float80
2130 ::= g # __float128
2131 ::= z # ellipsis
2132 ::= u <source-name> # vendor extended type */
2133
2134static status_t
2135demangle_builtin_type (dm)
2136 demangling_t dm;
2137{
2138
2139 char code = peek_char (dm);
2140
2141 DEMANGLE_TRACE ("builtin-type", dm);
2142
2143 if (code == 'u')
2144 {
2145 advance_char (dm);
2146 RETURN_IF_ERROR (demangle_source_name (dm));
2147 return STATUS_OK;
2148 }
2149 else if (code >= 'a' && code <= 'z')
2150 {
2151 const char *type_name = builtin_type_names[code - 'a'];
2152 if (type_name == NULL)
2153 return "Unrecognized <builtin-type> code.";
2154
051664b0 2155 RETURN_IF_ERROR (result_append (dm, type_name));
69afa80d
AS
2156 advance_char (dm);
2157 return STATUS_OK;
2158 }
2159 else
2160 return "Non-alphabetic <builtin-type> code.";
2161}
2162
2163/* Demangles all consecutive CV-qualifiers (const, volatile, and
2164 restrict) at the current position. The qualifiers are appended to
2165 QUALIFIERS. Returns STATUS_OK. */
2166
2167static status_t
2168demangle_CV_qualifiers (dm, qualifiers)
2169 demangling_t dm;
2170 dyn_string_t qualifiers;
2171{
2172 DEMANGLE_TRACE ("CV-qualifiers", dm);
2173
2174 while (1)
2175 {
2176 switch (peek_char (dm))
2177 {
2178 case 'r':
051664b0
AS
2179 if (!dyn_string_append_space (qualifiers))
2180 return STATUS_ALLOCATION_FAILED;
2181 if (!dyn_string_append_cstr (qualifiers, "restrict"))
2182 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
2183 break;
2184
2185 case 'V':
051664b0
AS
2186 if (!dyn_string_append_space (qualifiers))
2187 return STATUS_ALLOCATION_FAILED;
2188 if (!dyn_string_append_cstr (qualifiers, "volatile"))
2189 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
2190 break;
2191
2192 case 'K':
051664b0
AS
2193 if (!dyn_string_append_space (qualifiers))
2194 return STATUS_ALLOCATION_FAILED;
2195 if (!dyn_string_append_cstr (qualifiers, "const"))
2196 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
2197 break;
2198
2199 default:
2200 return STATUS_OK;
2201 }
2202
2203 advance_char (dm);
2204 }
2205}
2206
2207/* Demangles and emits a <function-type> FUNCTION_NAME_POS is the
2208 position in the result string of the start of the function
2209 identifier, at which the function's return type will be inserted.
2210
2211 <function-type> ::= F [Y] <bare-function-type> E */
2212
2213static status_t
2214demangle_function_type (dm, function_name_pos)
2215 demangling_t dm;
2216 int function_name_pos;
2217{
2218 DEMANGLE_TRACE ("function-type", dm);
2219 RETURN_IF_ERROR (demangle_char (dm, 'F'));
2220 if (peek_char (dm) == 'Y')
2221 {
2222 /* Indicate this function has C linkage if in verbose mode. */
2223 if (flag_verbose)
051664b0 2224 RETURN_IF_ERROR (result_append (dm, " [extern \"C\"] "));
69afa80d
AS
2225 advance_char (dm);
2226 }
2227 RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
2228 RETURN_IF_ERROR (demangle_char (dm, 'E'));
2229 return STATUS_OK;
2230}
2231
2232/* Demangles and emits a <bare-function-type>. RETURN_TYPE_POS is the
2233 position in the result string at which the function return type
2234 should be inserted. If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the
2235 function's return type is assumed not to be encoded.
2236
2237 <bare-function-type> ::= <signature type>+ */
2238
2239static status_t
2240demangle_bare_function_type (dm, return_type_pos)
2241 demangling_t dm;
2242 int return_type_pos;
2243{
2244 /* Sequence is the index of the current function parameter, counting
2245 from zero. The value -1 denotes the return type. */
2246 int sequence =
2247 (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);
2248
2249 DEMANGLE_TRACE ("bare-function-type", dm);
2250
051664b0 2251 RETURN_IF_ERROR (result_append_char (dm, '('));
69afa80d
AS
2252 while (!end_of_name_p (dm) && peek_char (dm) != 'E')
2253 {
2254 if (sequence == -1)
2255 /* We're decoding the function's return type. */
2256 {
2257 dyn_string_t return_type;
051664b0 2258 status_t status = STATUS_OK;
69afa80d
AS
2259
2260 /* Decode the return type off to the side. */
051664b0 2261 RETURN_IF_ERROR (result_push (dm));
69afa80d
AS
2262 RETURN_IF_ERROR (demangle_type (dm));
2263 return_type = (dyn_string_t) result_pop (dm);
2264
051664b0
AS
2265 /* Add a space to the end of the type. Insert the return
2266 type where we've been asked to. */
2267 if (!dyn_string_append_space (return_type)
2268 || !dyn_string_insert (result_string (dm), return_type_pos,
2269 return_type))
2270 status = STATUS_ALLOCATION_FAILED;
69afa80d 2271
69afa80d 2272 dyn_string_delete (return_type);
051664b0 2273 RETURN_IF_ERROR (status);
69afa80d
AS
2274 }
2275 else
2276 {
2277 /* Skip `void' parameter types. One should only occur as
2278 the only type in a parameter list; in that case, we want
2279 to print `foo ()' instead of `foo (void)'. */
2280 if (peek_char (dm) == 'v')
2281 {
2282 /* Consume the v. */
2283 advance_char (dm);
2284 continue;
2285 }
2286 /* Separate parameter types by commas. */
2287 if (sequence > 0)
051664b0 2288 RETURN_IF_ERROR (result_append (dm, ", "));
69afa80d
AS
2289 /* Demangle the type. */
2290 RETURN_IF_ERROR (demangle_type (dm));
2291 }
2292
2293 ++sequence;
2294 }
051664b0 2295 RETURN_IF_ERROR (result_append_char (dm, ')'));
69afa80d
AS
2296
2297 return STATUS_OK;
2298}
2299
2300/* Demangles and emits a <class-enum-type>. *TEMPLATE_P is set to
2301 non-zero if the type is a template-id, zero otherwise.
2302
2303 <class-enum-type> ::= <name> */
2304
2305static status_t
2306demangle_class_enum_type (dm, template_p)
2307 demangling_t dm;
2308 int *template_p;
2309{
2310 DEMANGLE_TRACE ("class-enum-type", dm);
2311
2312 RETURN_IF_ERROR (demangle_name (dm, template_p));
2313 return STATUS_OK;
2314}
2315
2316/* Demangles and emits an <array-type>.
2317
2318 <array-type> ::= A [<dimension number>] _ <element type> */
2319
2320static status_t
2321demangle_array_type (dm)
2322 demangling_t dm;
2323{
051664b0 2324 status_t status;
69afa80d
AS
2325 dyn_string_t array_size = dyn_string_new (10);
2326
051664b0
AS
2327 if (array_size == NULL)
2328 return STATUS_ALLOCATION_FAILED;
2329
2330 status = demangle_char (dm, 'A');
69afa80d
AS
2331
2332 /* Demangle the array size into array_size. */
051664b0
AS
2333 if (STATUS_NO_ERROR (status))
2334 status = demangle_number_literally (dm, array_size, 10, 0);
69afa80d
AS
2335
2336 /* Demangle the base type of the array. */
051664b0
AS
2337 if (STATUS_NO_ERROR (status))
2338 status = demangle_char (dm, '_');
2339 if (STATUS_NO_ERROR (status))
2340 status = demangle_type (dm);
69afa80d
AS
2341
2342 /* Emit the array dimension syntax. */
051664b0
AS
2343 if (STATUS_NO_ERROR (status))
2344 status = result_append_char (dm, '[');
2345 if (STATUS_NO_ERROR (status))
2346 status = result_append_string (dm, array_size);
2347 if (STATUS_NO_ERROR (status))
2348 status = result_append_char (dm, ']');
69afa80d
AS
2349 dyn_string_delete (array_size);
2350
051664b0
AS
2351 RETURN_IF_ERROR (status);
2352
69afa80d
AS
2353 return STATUS_OK;
2354}
2355
2356/* Demangles and emits a <template-param>. The zero-indexed position
2357 in the parameter list is placed in *TEMPLATE_PARM_NUMBER.
2358
2359 <template-param> ::= T_ # first template parameter
2360 ::= T <parameter-2 number> _ */
2361
2362static status_t
2363demangle_template_param (dm, template_parm_number)
2364 demangling_t dm;
2365 int *template_parm_number;
2366{
2367 int parm_number;
2368 template_arg_list_t current_arg_list = current_template_arg_list (dm);
2369 string_list_t arg;
2370
2371 DEMANGLE_TRACE ("template-param", dm);
2372
2373 /* Make sure there is a template argmust list in which to look up
2374 this parameter reference. */
2375 if (current_arg_list == NULL)
2376 return "Template parameter outside of template.";
2377
2378 RETURN_IF_ERROR (demangle_char (dm, 'T'));
2379 if (peek_char (dm) == '_')
2380 parm_number = 0;
2381 else
2382 {
2383 RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));
2384 ++parm_number;
2385 }
2386 RETURN_IF_ERROR (demangle_char (dm, '_'));
2387
2388 arg = template_arg_list_get_arg (current_arg_list, parm_number);
2389 if (arg == NULL)
2390 /* parm_number exceeded the number of arguments in the current
2391 template argument list. */
2392 return "Template parameter number out of bounds.";
051664b0 2393 RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
69afa80d
AS
2394
2395 if (peek_char (dm) == 'I')
2396 RETURN_IF_ERROR (demangle_template_args (dm));
2397
2398 *template_parm_number = parm_number;
2399 return STATUS_OK;
2400}
2401
2402/* Demangles and emits a <template-args>.
2403
2404 <template-args> ::= I <template-arg>+ E */
2405
2406static status_t
2407demangle_template_args (dm)
2408 demangling_t dm;
2409{
2410 int first = 1;
051664b0 2411 dyn_string_t old_last_source_name;
69afa80d
AS
2412 template_arg_list_t arg_list = template_arg_list_new ();
2413
051664b0
AS
2414 if (arg_list == NULL)
2415 return STATUS_ALLOCATION_FAILED;
2416
69afa80d 2417 /* Preserve the most recently demangled source name. */
051664b0 2418 old_last_source_name = dm->last_source_name;
69afa80d
AS
2419 dm->last_source_name = dyn_string_new (0);
2420
2421 DEMANGLE_TRACE ("template-args", dm);
2422
051664b0
AS
2423 if (dm->last_source_name == NULL)
2424 return STATUS_ALLOCATION_FAILED;
2425
69afa80d 2426 RETURN_IF_ERROR (demangle_char (dm, 'I'));
051664b0 2427 RETURN_IF_ERROR (result_append_char (dm, '<'));
69afa80d
AS
2428 do
2429 {
2430 string_list_t arg;
2431
2432 if (first)
2433 first = 0;
2434 else
051664b0 2435 RETURN_IF_ERROR (result_append (dm, ", "));
69afa80d
AS
2436
2437 /* Capture the template arg. */
051664b0 2438 RETURN_IF_ERROR (result_push (dm));
69afa80d
AS
2439 RETURN_IF_ERROR (demangle_template_arg (dm));
2440 arg = result_pop (dm);
2441
2442 /* Emit it in the demangled name. */
051664b0 2443 RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
69afa80d
AS
2444
2445 /* Save it for use in expanding <template-param>s. */
2446 template_arg_list_add_arg (arg_list, arg);
2447 }
2448 while (peek_char (dm) != 'E');
2449 /* Append the '>'. */
051664b0 2450 RETURN_IF_ERROR (result_close_template_list (dm));
69afa80d
AS
2451
2452 /* Consume the 'E'. */
2453 advance_char (dm);
2454
2455 /* Restore the most recent demangled source name. */
2456 dyn_string_delete (dm->last_source_name);
2457 dm->last_source_name = old_last_source_name;
2458
2459 /* Push the list onto the top of the stack of template argument
2460 lists, so that arguments from it are used from now on when
2461 expanding <template-param>s. */
2462 push_template_arg_list (dm, arg_list);
2463
2464 return STATUS_OK;
2465}
2466
2467/* This function, which does not correspond to a production in the
2468 mangling spec, handles the `literal' production for both
2469 <template-arg> and <expr-primary>. It does not expect or consume
2470 the initial `L' or final `E'. The demangling is given by:
2471
2472 <literal> ::= <type> </value/ number>
2473
2474 and the emitted output is `(type)number'. */
2475
2476static status_t
2477demangle_literal (dm)
2478 demangling_t dm;
2479{
69afa80d 2480 char peek = peek_char (dm);
051664b0
AS
2481 dyn_string_t value_string;
2482 status_t status;
69afa80d
AS
2483
2484 DEMANGLE_TRACE ("literal", dm);
2485
2486 if (!flag_verbose && peek >= 'a' && peek <= 'z')
2487 {
2488 /* If not in verbose mode and this is a builtin type, see if we
2489 can produce simpler numerical output. In particular, for
2490 integer types shorter than `long', just write the number
2491 without type information; for bools, write `true' or `false'.
2492 Other refinements could be made here too. */
2493
2494 /* This constant string is used to map from <builtin-type> codes
2495 (26 letters of the alphabet) to codes that determine how the
2496 value will be displayed. The codes are:
2497 b: display as bool
2498 i: display as int
2499 l: display as long
2500 A space means the value will be represented using cast
2501 notation. */
2502 static const char *const code_map = "ibi iii ll ii i ";
2503
2504 char code = code_map[peek - 'a'];
2505 /* FIXME: Implement demangling of floats and doubles. */
2506 if (code == 'u')
2507 return STATUS_UNIMPLEMENTED;
2508 if (code == 'b')
2509 {
2510 /* It's a boolean. */
2511 char value;
2512
2513 /* Consume the b. */
2514 advance_char (dm);
2515 /* Look at the next character. It should be 0 or 1,
2516 corresponding to false or true, respectively. */
2517 value = peek_char (dm);
2518 if (value == '0')
051664b0 2519 RETURN_IF_ERROR (result_append (dm, "false"));
69afa80d 2520 else if (value == '1')
051664b0 2521 RETURN_IF_ERROR (result_append (dm, "true"));
69afa80d
AS
2522 else
2523 return "Unrecognized bool constant.";
2524 /* Consume the 0 or 1. */
2525 advance_char (dm);
2526 return STATUS_OK;
2527 }
2528 else if (code == 'i' || code == 'l')
2529 {
2530 /* It's an integer or long. */
2531
2532 /* Consume the type character. */
2533 advance_char (dm);
051664b0 2534
69afa80d 2535 /* Demangle the number and write it out. */
051664b0
AS
2536 value_string = dyn_string_new (0);
2537 status = demangle_number_literally (dm, value_string, 10, 1);
2538 if (STATUS_NO_ERROR (status))
2539 status = result_append_string (dm, value_string);
69afa80d 2540 /* For long integers, append an l. */
051664b0
AS
2541 if (code == 'l' && STATUS_NO_ERROR (status))
2542 status = result_append_char (dm, code);
2543 dyn_string_delete (value_string);
2544
2545 RETURN_IF_ERROR (status);
69afa80d
AS
2546 return STATUS_OK;
2547 }
2548 /* ...else code == ' ', so fall through to represent this
2549 literal's type explicitly using cast syntax. */
2550 }
2551
051664b0 2552 RETURN_IF_ERROR (result_append_char (dm, '('));
69afa80d 2553 RETURN_IF_ERROR (demangle_type (dm));
051664b0
AS
2554 RETURN_IF_ERROR (result_append_char (dm, ')'));
2555
2556 value_string = dyn_string_new (0);
2557 if (value_string == NULL)
2558 return STATUS_ALLOCATION_FAILED;
69afa80d 2559
051664b0
AS
2560 status = demangle_number_literally (dm, value_string, 10, 1);
2561 if (STATUS_NO_ERROR (status))
2562 status = result_append_string (dm, value_string);
2563 dyn_string_delete (value_string);
2564 RETURN_IF_ERROR (status);
69afa80d
AS
2565
2566 return STATUS_OK;
2567}
2568
2569/* Demangles and emits a <template-arg>.
2570
2571 <template-arg> ::= <type> # type
2572 ::= L <type> <value number> E # literal
2573 ::= LZ <encoding> E # external name
2574 ::= X <expression> E # expression */
2575
2576static status_t
2577demangle_template_arg (dm)
2578 demangling_t dm;
2579{
2580 DEMANGLE_TRACE ("template-arg", dm);
2581
2582 switch (peek_char (dm))
2583 {
2584 case 'L':
2585 advance_char (dm);
2586
2587 if (peek_char (dm) == 'Z')
2588 {
2589 /* External name. */
2590 advance_char (dm);
2591 /* FIXME: Standard is contradictory here. */
2592 RETURN_IF_ERROR (demangle_encoding (dm));
2593 }
2594 else
2595 RETURN_IF_ERROR (demangle_literal (dm));
2596 RETURN_IF_ERROR (demangle_char (dm, 'E'));
2597 break;
2598
2599 case 'X':
2600 /* Expression. */
2601 advance_char (dm);
2602 RETURN_IF_ERROR (demangle_expression (dm));
2603 break;
2604
2605 default:
2606 RETURN_IF_ERROR (demangle_type (dm));
2607 break;
2608 }
2609
2610 return STATUS_OK;
2611}
2612
2613/* Demangles and emits an <expression>.
2614
2615 <expression> ::= <unary operator-name> <expression>
2616 ::= <binary operator-name> <expression> <expression>
2617 ::= <expr-primary>
2618 ::= <scope-expression> */
2619
2620static status_t
2621demangle_expression (dm)
2622 demangling_t dm;
2623{
2624 char peek = peek_char (dm);
2625
2626 DEMANGLE_TRACE ("expression", dm);
2627
2628 if (peek == 'L' || peek == 'T')
2629 RETURN_IF_ERROR (demangle_expr_primary (dm));
2630 else if (peek == 's' && peek_char_next (dm) == 'r')
2631 RETURN_IF_ERROR (demangle_scope_expression (dm));
2632 else
2633 /* An operator expression. */
2634 {
2635 int num_args;
051664b0 2636 status_t status = STATUS_OK;
69afa80d
AS
2637 dyn_string_t operator_name;
2638
2639 /* We have an operator name. Since we want to output binary
2640 operations in infix notation, capture the operator name
2641 first. */
051664b0 2642 RETURN_IF_ERROR (result_push (dm));
69afa80d
AS
2643 RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args));
2644 operator_name = (dyn_string_t) result_pop (dm);
2645
2646 /* If it's binary, do an operand first. */
2647 if (num_args > 1)
2648 {
051664b0
AS
2649 status = result_append_char (dm, '(');
2650 if (STATUS_NO_ERROR (status))
2651 status = demangle_expression (dm);
2652 if (STATUS_NO_ERROR (status))
2653 status = result_append_char (dm, ')');
69afa80d
AS
2654 }
2655
051664b0
AS
2656 /* Emit the operator. */
2657 if (STATUS_NO_ERROR (status))
2658 status = result_append_string (dm, operator_name);
69afa80d 2659 dyn_string_delete (operator_name);
051664b0
AS
2660 RETURN_IF_ERROR (status);
2661
2662 /* Emit its second (if binary) or only (if unary) operand. */
2663 RETURN_IF_ERROR (result_append_char (dm, '('));
69afa80d 2664 RETURN_IF_ERROR (demangle_expression (dm));
051664b0 2665 RETURN_IF_ERROR (result_append_char (dm, ')'));
69afa80d
AS
2666
2667 /* The ternary operator takes a third operand. */
2668 if (num_args == 3)
2669 {
051664b0 2670 RETURN_IF_ERROR (result_append (dm, ":("));
69afa80d 2671 RETURN_IF_ERROR (demangle_expression (dm));
051664b0 2672 RETURN_IF_ERROR (result_append_char (dm, ')'));
69afa80d
AS
2673 }
2674 }
2675
2676 return STATUS_OK;
2677}
2678
2679/* Demangles and emits a <scope-expression>.
2680
2681 <scope-expression> ::= sr <qualifying type> <source-name>
2682 ::= sr <qualifying type> <encoding> */
2683
2684static status_t
2685demangle_scope_expression (dm)
2686 demangling_t dm;
2687{
2688 RETURN_IF_ERROR (demangle_char (dm, 's'));
2689 RETURN_IF_ERROR (demangle_char (dm, 'r'));
2690 RETURN_IF_ERROR (demangle_type (dm));
051664b0 2691 RETURN_IF_ERROR (result_append (dm, "::"));
69afa80d
AS
2692 RETURN_IF_ERROR (demangle_encoding (dm));
2693 return STATUS_OK;
2694}
2695
2696/* Demangles and emits an <expr-primary>.
2697
2698 <expr-primary> ::= <template-param>
2699 ::= L <type> <value number> E # literal
2700 ::= L <mangled-name> E # external name */
2701
2702static status_t
2703demangle_expr_primary (dm)
2704 demangling_t dm;
2705{
2706 char peek = peek_char (dm);
2707 int unused;
2708
2709 DEMANGLE_TRACE ("expr-primary", dm);
2710
2711 if (peek == 'T')
2712 RETURN_IF_ERROR (demangle_template_param (dm, &unused));
2713 else if (peek == 'L')
2714 {
2715 /* Consume the `L'. */
2716 advance_char (dm);
2717 peek = peek_char (dm);
2718
2719 if (peek == '_')
2720 RETURN_IF_ERROR (demangle_mangled_name (dm));
2721 else
2722 RETURN_IF_ERROR (demangle_literal (dm));
2723
2724 RETURN_IF_ERROR (demangle_char (dm, 'E'));
2725 }
2726 else
2727 return STATUS_ERROR;
2728
2729 return STATUS_OK;
2730}
2731
2732/* Demangles and emits a <substitution>. Sets *TEMPLATE_P to non-zero
2733 if the substitution is the name of a template, zero otherwise. If
2734 the substitution token is St, which corresponds to the `::std::'
2735 namespace and can appear in a non-nested name, sets
2736 *SPECIAL_STD_SUBSTITUTION to non-zero; zero otherwise.
2737
2738 <substitution> ::= S <seq-id> _
2739 ::= S_
2740
2741 ::= St # ::std::
2742 ::= Sa # ::std::allocator
2743 ::= Sb # ::std::basic_string
2744 ::= Ss # ::std::basic_string<char,
2745 ::std::char_traits<char>,
2746 ::std::allocator<char> >
2747 ::= Si # ::std::basic_istream<char,
2748 std::char_traits<char> >
2749 ::= So # ::std::basic_ostream<char,
2750 std::char_traits<char> >
2751 ::= Sd # ::std::basic_iostream<char,
2752 std::char_traits<char> >
2753*/
2754
2755static status_t
2756demangle_substitution (dm, template_p, special_std_substitution)
2757 demangling_t dm;
2758 int *template_p;
2759 int *special_std_substitution;
2760{
2761 int seq_id;
2762 int peek;
2763 dyn_string_t text;
2764
2765 DEMANGLE_TRACE ("substitution", dm);
2766
2767 RETURN_IF_ERROR (demangle_char (dm, 'S'));
2768 *special_std_substitution = 0;
2769
2770 /* Scan the substitution sequence index. A missing number denotes
2771 the first index. */
2772 peek = peek_char (dm);
2773 if (peek == '_')
2774 seq_id = -1;
2775 /* If the following character is 0-9 or a capital letter, interpret
2776 the sequence up to the next underscore as a base-36 substitution
2777 index. */
051664b0 2778 else if (IS_DIGIT ((unsigned char) peek)
69afa80d
AS
2779 || (peek >= 'A' && peek <= 'Z'))
2780 RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));
2781 else
2782 {
051664b0
AS
2783 const char *new_last_source_name = NULL;
2784
69afa80d
AS
2785 switch (peek)
2786 {
2787 case 't':
051664b0 2788 RETURN_IF_ERROR (result_append (dm, "std"));
69afa80d
AS
2789 *special_std_substitution = 1;
2790 break;
2791
2792 case 'a':
051664b0
AS
2793 RETURN_IF_ERROR (result_append (dm, "std::allocator"));
2794 new_last_source_name = "allocator";
69afa80d
AS
2795 break;
2796
2797 case 'b':
051664b0
AS
2798 RETURN_IF_ERROR (result_append (dm, "std::basic_string"));
2799 new_last_source_name = "basic_string";
69afa80d
AS
2800 break;
2801
2802 case 's':
2803 if (!flag_verbose)
2804 {
051664b0
AS
2805 RETURN_IF_ERROR (result_append (dm, "std::string"));
2806 new_last_source_name = "string";
69afa80d
AS
2807 }
2808 else
2809 {
051664b0
AS
2810 RETURN_IF_ERROR (result_append (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
2811 new_last_source_name = "basic_string";
69afa80d
AS
2812 }
2813 break;
2814
2815 case 'i':
2816 if (!flag_verbose)
2817 {
051664b0
AS
2818 RETURN_IF_ERROR (result_append (dm, "std::istream"));
2819 new_last_source_name = "istream";
69afa80d
AS
2820 }
2821 else
2822 {
051664b0
AS
2823 RETURN_IF_ERROR (result_append (dm, "std::basic_istream<char, std::char_traints<char> >"));
2824 new_last_source_name = "basic_istream";
69afa80d
AS
2825 }
2826 break;
2827
2828 case 'o':
2829 if (!flag_verbose)
2830 {
051664b0
AS
2831 RETURN_IF_ERROR (result_append (dm, "std::ostream"));
2832 new_last_source_name = "ostream";
69afa80d
AS
2833 }
2834 else
2835 {
051664b0
AS
2836 RETURN_IF_ERROR (result_append (dm, "std::basic_ostream<char, std::char_traits<char> >"));
2837 new_last_source_name = "basic_ostream";
69afa80d
AS
2838 }
2839 break;
2840
2841 case 'd':
2842 if (!flag_verbose)
2843 {
051664b0
AS
2844 RETURN_IF_ERROR (result_append (dm, "std::iostream"));
2845 new_last_source_name = "iostream";
69afa80d
AS
2846 }
2847 else
2848 {
051664b0
AS
2849 RETURN_IF_ERROR (result_append (dm, "std::basic_iostream<char, std::char_traits<char> >"));
2850 new_last_source_name = "basic_iostream";
69afa80d
AS
2851 }
2852 break;
2853
2854 default:
2855 return "Unrecognized <substitution>.";
2856 }
2857
051664b0 2858 /* Consume the character we just processed. */
69afa80d 2859 advance_char (dm);
051664b0
AS
2860
2861 if (new_last_source_name != NULL)
2862 {
2863 if (!dyn_string_copy_cstr (dm->last_source_name,
2864 new_last_source_name))
2865 return STATUS_ALLOCATION_FAILED;
2866 }
2867
69afa80d
AS
2868 return STATUS_OK;
2869 }
2870
2871 /* Look up the substitution text. Since `S_' is the most recent
2872 substitution, `S0_' is the second-most-recent, etc., shift the
2873 numbering by one. */
2874 text = substitution_get (dm, seq_id + 1, template_p);
2875 if (text == NULL)
2876 return "Substitution number out of range.";
2877
2878 /* Emit the substitution text. */
051664b0 2879 RETURN_IF_ERROR (result_append_string (dm, text));
69afa80d
AS
2880
2881 RETURN_IF_ERROR (demangle_char (dm, '_'));
2882 return STATUS_OK;
2883}
2884
2885/* Demangles and emits a <local-name>.
2886
2887 <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2888 := Z <function encoding> E s [<discriminator>] */
2889
2890static status_t
2891demangle_local_name (dm)
2892 demangling_t dm;
2893{
2894 DEMANGLE_TRACE ("local-name", dm);
2895
2896 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
2897 RETURN_IF_ERROR (demangle_encoding (dm));
2898 RETURN_IF_ERROR (demangle_char (dm, 'E'));
051664b0 2899 RETURN_IF_ERROR (result_append (dm, "'s "));
69afa80d
AS
2900
2901 if (peek_char (dm) == 's')
2902 {
2903 /* Local character string literal. */
051664b0 2904 RETURN_IF_ERROR (result_append (dm, "string literal"));
69afa80d
AS
2905 /* Consume the s. */
2906 advance_char (dm);
2907 RETURN_IF_ERROR (demangle_discriminator (dm, 0));
2908 }
2909 else
2910 {
2911 int unused;
051664b0 2912 RETURN_IF_ERROR (result_append (dm, "local "));
69afa80d
AS
2913 /* Local name for some other entity. Demangle its name. */
2914 RETURN_IF_ERROR (demangle_name (dm, &unused));
2915 RETURN_IF_ERROR (demangle_discriminator (dm, 1));
2916 }
2917
2918 return STATUS_OK;
2919 }
2920
2921 /* Optimonally demangles and emits a <discriminator>. If there is no
2922 <discriminator> at the current position in the mangled string, the
2923 descriminator is assumed to be zero. Emit the discriminator number
2924 in parentheses, unless SUPPRESS_FIRST is non-zero and the
2925 discriminator is zero.
2926
2927 <discriminator> ::= _ <number> */
2928
2929static status_t
2930demangle_discriminator (dm, suppress_first)
2931 demangling_t dm;
2932 int suppress_first;
2933{
2934 /* Output for <discriminator>s to the demangled name is completely
2935 supressed if not in verbose mode. */
2936
2937 if (peek_char (dm) == '_')
2938 {
2939 /* Consume the underscore. */
2940 advance_char (dm);
2941 if (flag_verbose)
051664b0 2942 RETURN_IF_ERROR (result_append (dm, " [#"));
69afa80d 2943 /* Check if there's a number following the underscore. */
051664b0 2944 if (IS_DIGIT ((unsigned char) peek_char (dm)))
69afa80d
AS
2945 {
2946 int discriminator;
2947 /* Demangle the number. */
2948 RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));
2949 if (flag_verbose)
2950 /* Write the discriminator. The mangled number is two
2951 less than the discriminator ordinal, counting from
2952 zero. */
051664b0
AS
2953 RETURN_IF_ERROR (int_to_dyn_string (discriminator + 2,
2954 (dyn_string_t) dm->result));
69afa80d
AS
2955 }
2956 else
2957 {
2958 if (flag_verbose)
2959 /* A missing digit correspond to one. */
051664b0 2960 RETURN_IF_ERROR (result_append_char (dm, '1'));
69afa80d
AS
2961 }
2962 if (flag_verbose)
051664b0 2963 RETURN_IF_ERROR (result_append_char (dm, ']'));
69afa80d
AS
2964 }
2965 else if (!suppress_first)
2966 {
2967 if (flag_verbose)
051664b0 2968 RETURN_IF_ERROR (result_append (dm, " [#0]"));
69afa80d
AS
2969 }
2970
2971 return STATUS_OK;
2972}
2973
2974/* Demangle NAME into RESULT, which must be an initialized
2975 dyn_string_t. On success, returns STATUS_OK. On failure, returns
2976 an error message, and the contents of RESULT are unchanged. */
2977
7eb23b1f 2978static status_t
69afa80d 2979cp_demangle (name, result)
051664b0 2980 const char *name;
69afa80d
AS
2981 dyn_string_t result;
2982{
2983 status_t status;
2984 int length = strlen (name);
2985
2986 if (length > 2 && name[0] == '_' && name[1] == 'Z')
2987 {
2988 demangling_t dm = demangling_new (name);
051664b0
AS
2989 if (dm == NULL)
2990 return STATUS_ALLOCATION_FAILED;
69afa80d 2991
051664b0
AS
2992 status = result_push (dm);
2993 if (status != STATUS_OK)
2994 {
2995 demangling_delete (dm);
2996 return status;
2997 }
69afa80d 2998
051664b0
AS
2999 status = demangle_mangled_name (dm);
3000 if (STATUS_NO_ERROR (status))
69afa80d
AS
3001 {
3002 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
051664b0
AS
3003 if (!dyn_string_copy (result, demangled))
3004 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
3005 dyn_string_delete (demangled);
3006 }
3007
3008 demangling_delete (dm);
3009 }
3010 else
3011 {
3012 /* It's evidently not a mangled C++ name. It could be the name
3013 of something with C linkage, though, so just copy NAME into
3014 RESULT. */
051664b0
AS
3015 if (!dyn_string_copy_cstr (result, name))
3016 return STATUS_ALLOCATION_FAILED;
69afa80d
AS
3017 status = STATUS_OK;
3018 }
3019
051664b0
AS
3020 return status;
3021}
3022
3023/* Demangle TYPE_NAME into RESULT, which must be an initialized
3024 dyn_string_t. On success, returns STATUS_OK. On failiure, returns
3025 an error message, and the contents of RESULT are unchanged. */
3026
3027static status_t
3028cp_demangle_type (type_name, result)
3029 const char* type_name;
3030 dyn_string_t result;
3031{
3032 status_t status;
3033 demangling_t dm = demangling_new (type_name);
3034
3035 if (dm == NULL)
3036 return STATUS_ALLOCATION_FAILED;
3037
3038 /* Demangle the type name. The demangled name is stored in dm. */
3039 status = result_push (dm);
3040 if (status != STATUS_OK)
3041 {
3042 demangling_delete (dm);
3043 return status;
3044 }
3045
3046 status = demangle_type (dm);
3047
3048 if (STATUS_NO_ERROR (status))
3049 {
3050 /* The demangling succeeded. Pop the result out of dm and copy
3051 it into RESULT. */
3052 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3053 if (!dyn_string_copy (result, demangled))
3054 return STATUS_ALLOCATION_FAILED;
3055 dyn_string_delete (demangled);
3056 }
3057
3058 /* Clean up. */
3059 demangling_delete (dm);
3060
69afa80d
AS
3061 return status;
3062}
3063
051664b0
AS
3064
3065#ifdef IN_LIBGCC2
3066
3067extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
3068
3069/* ABI-mandated entry point in the C++ runtime library for performing
3070 demangling. MANGLED_NAME is a NUL-terminated character string
3071 containing the name to be demangled.
3072
3073 OUTPUT_BUFFER is a region of memory, allocated with malloc, of
3074 *LENGTH bytes, into which the demangled name is stored. If
3075 OUTPUT_BUFFER is not long enough, it is expanded using realloc.
3076 OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
3077 is placed in a region of memory allocated with malloc.
3078
3079 If LENGTH is non-NULL, the length of the buffer conaining the
3080 demangled name, is placed in *LENGTH.
3081
3082 The return value is a pointer to the start of the NUL-terminated
3083 demangled name, or NULL if the demangling fails. The caller is
3084 responsible for deallocating this memory using free.
3085
3086 *STATUS is set to one of the following values:
3087 0: The demangling operation succeeded.
3088 -1: A memory allocation failiure occurred.
3089 -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
3090 -3: One of the arguments is invalid.
3091
3092 The demagling is performed using the C++ ABI mangling rules, with
3093 GNU extensions. */
3094
3095char *
3096__cxa_demangle (mangled_name, output_buffer, length, status)
3097 const char *mangled_name;
3098 char *output_buffer;
3099 size_t *length;
3100 int *status;
3101{
3102 struct dyn_string demangled_name;
3103 status_t result;
3104
3105 if (status == NULL)
3106 return NULL;
3107
3108 if (mangled_name == NULL) {
3109 *status = -3;
3110 return NULL;
3111 }
3112
3113 /* Did the caller provide a buffer for the demangled name? */
3114 if (output_buffer == NULL) {
3115 /* No; dyn_string will malloc a buffer for us. */
3116 if (!dyn_string_init (&demangled_name, 0))
3117 {
3118 *status = -1;
3119 return NULL;
3120 }
3121 }
3122 else {
3123 /* Yes. Check that the length was provided. */
3124 if (length == NULL) {
3125 *status = -3;
3126 return NULL;
3127 }
3128 /* Install the buffer into a dyn_string. */
3129 demangled_name.allocated = *length;
3130 demangled_name.length = 0;
3131 demangled_name.s = output_buffer;
3132 }
3133
3134 if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
3135 /* MANGLED_NAME apprears to be a function or variable name.
3136 Demangle it accordingly. */
3137 result = cp_demangle (mangled_name, &demangled_name);
3138 else
3139 /* Try to demangled MANGLED_NAME as the name of a type. */
3140 result = cp_demangle_type (mangled_name, &demangled_name);
3141
3142 if (result == STATUS_OK)
3143 /* The demangling succeeded. */
3144 {
3145 /* If LENGTH isn't NULL, store the allocated buffer length
3146 there; the buffer may have been realloced by dyn_string
3147 functions. */
3148 if (length != NULL)
3149 *length = demangled_name.allocated;
3150 /* The operation was a success. */
3151 *status = 0;
3152 return dyn_string_buf (&demangled_name);
3153 }
3154 else if (result == STATUS_ALLOCATION_FAILED)
3155 /* A call to malloc or realloc failed during the demangling
3156 operation. */
3157 {
3158 *status = -1;
3159 return NULL;
3160 }
3161 else
3162 /* The demangling failed for another reason, most probably because
3163 MANGLED_NAME isn't a valid mangled name. */
3164 {
3165 /* If the buffer containing the demangled name wasn't provided
3166 by the caller, free it. */
3167 if (output_buffer == NULL)
3168 free (dyn_string_buf (&demangled_name));
3169 *status = -2;
3170 return NULL;
3171 }
3172}
3173
3174#else /* !IN_LIBGCC2 */
3175
69afa80d
AS
3176/* Variant entry point for integration with the existing cplus-dem
3177 demangler. Attempts to demangle MANGLED. If the demangling
3178 succeeds, returns a buffer, allocated with malloc, containing the
3179 demangled name. The caller must deallocate the buffer using free.
3180 If the demangling failes, returns NULL. */
3181
3182char *
3183cplus_demangle_new_abi (mangled)
3184 const char* mangled;
3185{
3186 /* Create a dyn_string to hold the demangled name. */
3187 dyn_string_t demangled = dyn_string_new (0);
3188 /* Attempt the demangling. */
3189 status_t status = cp_demangle ((char *) mangled, demangled);
051664b0 3190 if (STATUS_NO_ERROR (status))
69afa80d
AS
3191 /* Demangling succeeded. */
3192 {
3193 /* Grab the demangled result from the dyn_string. It was
3194 allocated with malloc, so we can return it directly. */
3195 char *return_value = dyn_string_release (demangled);
69afa80d
AS
3196 /* Hand back the demangled name. */
3197 return return_value;
3198 }
051664b0
AS
3199 else if (status == STATUS_ALLOCATION_FAILED)
3200 {
3201 fprintf (stderr, "Memory allocation failed.\n");
3202 abort ();
3203 }
69afa80d
AS
3204 else
3205 /* Demangling failed. */
3206 {
3207 dyn_string_delete (demangled);
3208 return NULL;
3209 }
3210}
3211
051664b0
AS
3212#endif /* IN_LIBGCC2 */
3213
69afa80d
AS
3214#ifdef STANDALONE_DEMANGLER
3215
3216#include "getopt.h"
3217
3218static void print_usage
3219 PARAMS ((FILE* fp, int exit_value));
3220
3221/* Non-zero if CHAR is a character than can occur in a mangled name. */
3faa108c 3222#define is_mangled_char(CHAR) \
051664b0 3223 (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) || (CHAR) == '_')
69afa80d
AS
3224
3225/* The name of this program, as invoked. */
3226const char* program_name;
3227
3228/* Prints usage summary to FP and then exits with EXIT_VALUE. */
3229
3230static void
3231print_usage (fp, exit_value)
3232 FILE* fp;
3233 int exit_value;
3234{
3235 fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
3236 fprintf (fp, "Options:\n", program_name);
3237 fprintf (fp, " -h,--help Display this message.\n");
3238 fprintf (fp, " -s,--strict Demangle standard names only.\n");
3239 fprintf (fp, " -v,--verbose Produce verbose demanglings.\n");
3240 fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n");
3241
3242 exit (exit_value);
3243}
3244
3245/* Option specification for getopt_long. */
3246static struct option long_options[] =
3247{
3248 { "help", no_argument, NULL, 'h' },
3249 { "strict", no_argument, NULL, 's' },
3250 { "verbose", no_argument, NULL, 'v' },
3251 { NULL, no_argument, NULL, 0 },
3252};
3253
3254/* Main entry for a demangling filter executable. It will demangle
3255 its command line arguments, if any. If none are provided, it will
3256 filter stdin to stdout, replacing any recognized mangled C++ names
3257 with their demangled equivalents. */
3258
3259int
3260main (argc, argv)
3261 int argc;
3262 char *argv[];
3263{
3264 status_t status;
3265 int i;
3266 int opt_char;
3267
3268 /* Use the program name of this program, as invoked. */
3269 program_name = argv[0];
3270
3271 /* Parse options. */
3272 do
3273 {
3274 opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);
3275 switch (opt_char)
3276 {
3277 case '?': /* Unrecognized option. */
3278 print_usage (stderr, 1);
3279 break;
3280
3281 case 'h':
3282 print_usage (stdout, 0);
3283 break;
3284
3285 case 's':
3286 flag_strict = 1;
3287 break;
3288
3289 case 'v':
3290 flag_verbose = 1;
3291 break;
3292 }
3293 }
3294 while (opt_char != -1);
3295
3296 if (optind == argc)
3297 /* No command line arguments were provided. Filter stdin. */
3298 {
3299 dyn_string_t mangled = dyn_string_new (3);
3300 dyn_string_t demangled = dyn_string_new (0);
3301 status_t status;
3302
3303 /* Read all of input. */
3304 while (!feof (stdin))
3305 {
3306 char c = getchar ();
3307
3308 /* The first character of a mangled name is an underscore. */
3309 if (feof (stdin))
3310 break;
3311 if (c != '_')
3312 {
3313 /* It's not a mangled name. Print the character and go
3314 on. */
3315 putchar (c);
3316 continue;
3317 }
3318 c = getchar ();
3319
3320 /* The second character of a mangled name is a capital `Z'. */
3321 if (feof (stdin))
3322 break;
3323 if (c != 'Z')
3324 {
3325 /* It's not a mangled name. Print the previous
3326 underscore, the `Z', and go on. */
3327 putchar ('_');
3328 putchar (c);
3329 continue;
3330 }
3331
3332 /* Start keeping track of the candidate mangled name. */
3333 dyn_string_append_char (mangled, '_');
3334 dyn_string_append_char (mangled, 'Z');
3335
3336 /* Pile characters into mangled until we hit one that can't
3337 occur in a mangled name. */
3338 c = getchar ();
3339 while (!feof (stdin) && is_mangled_char (c))
3340 {
3341 dyn_string_append_char (mangled, c);
3342 if (feof (stdin))
3343 break;
3344 c = getchar ();
3345 }
3346
3347 /* Attempt to demangle the name. */
3348 status = cp_demangle (dyn_string_buf (mangled), demangled);
3349
3350 /* If the demangling succeeded, great! Print out the
3351 demangled version. */
051664b0 3352 if (STATUS_NO_ERROR (status))
69afa80d 3353 fputs (dyn_string_buf (demangled), stdout);
051664b0
AS
3354 /* Abort on allocation failures. */
3355 else if (status == STATUS_ALLOCATION_FAILED)
3356 {
3357 fprintf (stderr, "Memory allocation failed.\n");
3358 abort ();
3359 }
69afa80d
AS
3360 /* Otherwise, it might not have been a mangled name. Just
3361 print out the original text. */
3362 else
3363 fputs (dyn_string_buf (mangled), stdout);
3364
3365 /* If we haven't hit EOF yet, we've read one character that
3366 can't occur in a mangled name, so print it out. */
3367 if (!feof (stdin))
3368 putchar (c);
3369
3370 /* Clear the candidate mangled name, to start afresh next
3371 time we hit a `_Z'. */
3372 dyn_string_clear (mangled);
3373 }
3374
3375 dyn_string_delete (mangled);
3376 dyn_string_delete (demangled);
3377 }
3378 else
3379 /* Demangle command line arguments. */
3380 {
3381 dyn_string_t result = dyn_string_new (0);
3382
3383 /* Loop over command line arguments. */
3384 for (i = optind; i < argc; ++i)
3385 {
3386 /* Attempt to demangle. */
3387 status = cp_demangle (argv[i], result);
3388
3389 /* If it worked, print the demangled name. */
051664b0 3390 if (STATUS_NO_ERROR (status))
69afa80d 3391 printf ("%s\n", dyn_string_buf (result));
051664b0
AS
3392 /* Abort on allocaiton failures. */
3393 if (status == STATUS_ALLOCATION_FAILED)
3394 {
3395 fprintf (stderr, "Memory allocaiton failed.\n");
3396 abort ():
3397 }
69afa80d
AS
3398 /* If not, print the error message to stderr instead. */
3399 else
3400 fprintf (stderr, "%s\n", status);
3401 }
3402 dyn_string_delete (result);
3403 }
3404
3405 return 0;
3406}
3407
3408#endif /* STANDALONE_DEMANGLER */