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