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