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