]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/cplus-dem.c
cplus-dem.c (work_stuff): Add dllimported.
[thirdparty/gcc.git] / libiberty / cplus-dem.c
CommitLineData
6599da04 1/* Demangler for GNU C++
4d59ab3f 2 Copyright 1989, 91, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
6599da04
JM
3 Written by James Clark (jjc@jclark.uucp)
4 Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
5
6This file is part of the libiberty library.
7Libiberty is free software; you can redistribute it and/or
8modify it under the terms of the GNU Library General Public
9License as published by the Free Software Foundation; either
10version 2 of the License, or (at your option) any later version.
11
12Libiberty is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15Library General Public License for more details.
16
17You should have received a copy of the GNU Library General Public
18License along with libiberty; see the file COPYING.LIB. If
19not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
23
24 This file imports xmalloc and xrealloc, which are like malloc and
25 realloc except that they generate a fatal error if there is no
26 available memory. */
27
28/* This file lives in both GCC and libiberty. When making changes, please
29 try not to break either. */
30
a7825625
KG
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
6599da04 35#include <ctype.h>
9ee02b5c 36#include <sys/types.h>
6599da04
JM
37#include <string.h>
38#include <stdio.h>
39
9ee02b5c
JL
40#ifdef HAVE_STDLIB_H
41#include <stdlib.h>
a7825625
KG
42#else
43char * malloc ();
44char * realloc ();
9ee02b5c
JL
45#endif
46
6599da04
JM
47#include <demangle.h>
48#undef CURRENT_DEMANGLING_STYLE
49#define CURRENT_DEMANGLING_STYLE work->options
50
51extern char *xmalloc PARAMS((unsigned));
52extern char *xrealloc PARAMS((char *, unsigned));
53
54static const char *mystrstr PARAMS ((const char *, const char *));
55
56static const char *
57mystrstr (s1, s2)
58 const char *s1, *s2;
59{
60 register const char *p = s1;
61 register int len = strlen (s2);
62
63 for (; (p = strchr (p, *s2)) != 0; p++)
64 {
65 if (strncmp (p, s2, len) == 0)
66 {
67 return (p);
68 }
69 }
70 return (0);
71}
72
73/* In order to allow a single demangler executable to demangle strings
74 using various common values of CPLUS_MARKER, as well as any specific
75 one set at compile time, we maintain a string containing all the
76 commonly used ones, and check to see if the marker we are looking for
77 is in that string. CPLUS_MARKER is usually '$' on systems where the
78 assembler can deal with that. Where the assembler can't, it's usually
79 '.' (but on many systems '.' is used for other things). We put the
80 current defined CPLUS_MARKER first (which defaults to '$'), followed
81 by the next most common value, followed by an explicit '$' in case
82 the value of CPLUS_MARKER is not '$'.
83
84 We could avoid this if we could just get g++ to tell us what the actual
85 cplus marker character is as part of the debug information, perhaps by
86 ensuring that it is the character that terminates the gcc<n>_compiled
87 marker symbol (FIXME). */
88
89#if !defined (CPLUS_MARKER)
90#define CPLUS_MARKER '$'
91#endif
92
93enum demangling_styles current_demangling_style = gnu_demangling;
94
95static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
96
97void
98set_cplus_marker_for_demangling (ch)
99 int ch;
100{
101 cplus_markers[0] = ch;
102}
103
9923cc56
MM
104typedef struct string /* Beware: these aren't required to be */
105{ /* '\0' terminated. */
106 char *b; /* pointer to start of string */
107 char *p; /* pointer after last character */
108 char *e; /* pointer after end of allocated space */
109} string;
110
6599da04
JM
111/* Stuff that is shared between sub-routines.
112 Using a shared structure allows cplus_demangle to be reentrant. */
113
114struct work_stuff
115{
116 int options;
117 char **typevec;
5e5199e8
AM
118 char **ktypevec;
119 char **btypevec;
120 int numk;
121 int numb;
122 int ksize;
123 int bsize;
6599da04
JM
124 int ntypes;
125 int typevec_size;
126 int constructor;
127 int destructor;
128 int static_type; /* A static member function */
129 int const_type; /* A const member function */
9923cc56 130 int volatile_type; /* A volatile member function */
a3a5b5b7
MM
131 char **tmpl_argvec; /* Template function arguments. */
132 int ntmpl_args; /* The number of template function arguments. */
9923cc56
MM
133 int forgetting_types; /* Nonzero if we are not remembering the types
134 we see. */
135 string* previous_argument; /* The last function argument demangled. */
136 int nrepeats; /* The number of times to repeat the previous
137 argument. */
6599da04
JM
138};
139
140#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
141#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
142
143static const struct optable
144{
145 const char *in;
146 const char *out;
147 int flags;
148} optable[] = {
149 {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */
150 {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */
151 {"new", " new", 0}, /* old (1.91, and 1.x) */
152 {"delete", " delete", 0}, /* old (1.91, and 1.x) */
153 {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */
154 {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */
155 {"as", "=", DMGL_ANSI}, /* ansi */
156 {"ne", "!=", DMGL_ANSI}, /* old, ansi */
157 {"eq", "==", DMGL_ANSI}, /* old, ansi */
158 {"ge", ">=", DMGL_ANSI}, /* old, ansi */
159 {"gt", ">", DMGL_ANSI}, /* old, ansi */
160 {"le", "<=", DMGL_ANSI}, /* old, ansi */
161 {"lt", "<", DMGL_ANSI}, /* old, ansi */
162 {"plus", "+", 0}, /* old */
163 {"pl", "+", DMGL_ANSI}, /* ansi */
164 {"apl", "+=", DMGL_ANSI}, /* ansi */
165 {"minus", "-", 0}, /* old */
166 {"mi", "-", DMGL_ANSI}, /* ansi */
167 {"ami", "-=", DMGL_ANSI}, /* ansi */
168 {"mult", "*", 0}, /* old */
169 {"ml", "*", DMGL_ANSI}, /* ansi */
170 {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */
171 {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */
172 {"convert", "+", 0}, /* old (unary +) */
173 {"negate", "-", 0}, /* old (unary -) */
174 {"trunc_mod", "%", 0}, /* old */
175 {"md", "%", DMGL_ANSI}, /* ansi */
176 {"amd", "%=", DMGL_ANSI}, /* ansi */
177 {"trunc_div", "/", 0}, /* old */
178 {"dv", "/", DMGL_ANSI}, /* ansi */
179 {"adv", "/=", DMGL_ANSI}, /* ansi */
180 {"truth_andif", "&&", 0}, /* old */
181 {"aa", "&&", DMGL_ANSI}, /* ansi */
182 {"truth_orif", "||", 0}, /* old */
183 {"oo", "||", DMGL_ANSI}, /* ansi */
184 {"truth_not", "!", 0}, /* old */
185 {"nt", "!", DMGL_ANSI}, /* ansi */
186 {"postincrement","++", 0}, /* old */
187 {"pp", "++", DMGL_ANSI}, /* ansi */
188 {"postdecrement","--", 0}, /* old */
189 {"mm", "--", DMGL_ANSI}, /* ansi */
190 {"bit_ior", "|", 0}, /* old */
191 {"or", "|", DMGL_ANSI}, /* ansi */
192 {"aor", "|=", DMGL_ANSI}, /* ansi */
193 {"bit_xor", "^", 0}, /* old */
194 {"er", "^", DMGL_ANSI}, /* ansi */
195 {"aer", "^=", DMGL_ANSI}, /* ansi */
196 {"bit_and", "&", 0}, /* old */
197 {"ad", "&", DMGL_ANSI}, /* ansi */
198 {"aad", "&=", DMGL_ANSI}, /* ansi */
199 {"bit_not", "~", 0}, /* old */
200 {"co", "~", DMGL_ANSI}, /* ansi */
201 {"call", "()", 0}, /* old */
202 {"cl", "()", DMGL_ANSI}, /* ansi */
203 {"alshift", "<<", 0}, /* old */
204 {"ls", "<<", DMGL_ANSI}, /* ansi */
205 {"als", "<<=", DMGL_ANSI}, /* ansi */
206 {"arshift", ">>", 0}, /* old */
207 {"rs", ">>", DMGL_ANSI}, /* ansi */
208 {"ars", ">>=", DMGL_ANSI}, /* ansi */
209 {"component", "->", 0}, /* old */
210 {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */
211 {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */
212 {"indirect", "*", 0}, /* old */
213 {"method_call", "->()", 0}, /* old */
214 {"addr", "&", 0}, /* old (unary &) */
215 {"array", "[]", 0}, /* old */
216 {"vc", "[]", DMGL_ANSI}, /* ansi */
217 {"compound", ", ", 0}, /* old */
218 {"cm", ", ", DMGL_ANSI}, /* ansi */
219 {"cond", "?:", 0}, /* old */
220 {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */
221 {"max", ">?", 0}, /* old */
222 {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */
223 {"min", "<?", 0}, /* old */
224 {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
225 {"nop", "", 0}, /* old (for operator=) */
f9c85454
MM
226 {"rm", "->*", DMGL_ANSI}, /* ansi */
227 {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */
6599da04
JM
228};
229
4d17a06f
MM
230/* These values are used to indicate the various type varieties.
231 They are all non-zero so that they can be used as `success'
232 values. */
233typedef enum type_kind_t
234{
235 tk_none,
236 tk_pointer,
237 tk_integral,
238 tk_bool,
239 tk_char,
240 tk_real
241} type_kind_t;
242
6599da04
JM
243#define STRING_EMPTY(str) ((str) -> b == (str) -> p)
244#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
245 string_prepend(str, " ");}
246#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
247 string_append(str, " ");}
5e5199e8 248#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
6599da04 249
9923cc56
MM
250/* The scope separator appropriate for the language being demangled. */
251#define SCOPE_STRING(work) "::"
252
6599da04
JM
253#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
254#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
255
256/* Prototypes for local functions */
257
258static char *
259mop_up PARAMS ((struct work_stuff *, string *, int));
260
d6f4ec51 261static void
5e5199e8
AM
262squangle_mop_up PARAMS ((struct work_stuff *));
263
6599da04
JM
264#if 0
265static int
5e5199e8 266demangle_method_args PARAMS ((struct work_stuff *, const char **, string *));
6599da04
JM
267#endif
268
5e5199e8 269static char *
d6f4ec51 270internal_cplus_demangle PARAMS ((struct work_stuff *, const char *));
5e5199e8 271
9ee02b5c
JL
272static int
273demangle_template_template_parm PARAMS ((struct work_stuff *work,
274 const char **, string *));
275
6599da04
JM
276static int
277demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
9923cc56 278 string *, int, int));
6599da04
JM
279
280static int
281arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
282 const char **));
283
284static void
285demangle_arm_pt PARAMS ((struct work_stuff *, const char **, int, string *));
286
287static int
288demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
289
290static int
291demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
292 int, int));
293
294static int
295demangle_class PARAMS ((struct work_stuff *, const char **, string *));
296
297static int
298demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
299
300static int
301demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
302
303static int
304demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
305
306static int
307gnu_special PARAMS ((struct work_stuff *, const char **, string *));
308
309static int
9ee02b5c 310arm_special PARAMS ((const char **, string *));
6599da04
JM
311
312static void
313string_need PARAMS ((string *, int));
314
315static void
316string_delete PARAMS ((string *));
317
318static void
319string_init PARAMS ((string *));
320
321static void
322string_clear PARAMS ((string *));
323
324#if 0
325static int
326string_empty PARAMS ((string *));
327#endif
328
329static void
330string_append PARAMS ((string *, const char *));
331
332static void
333string_appends PARAMS ((string *, string *));
334
335static void
336string_appendn PARAMS ((string *, const char *, int));
337
338static void
339string_prepend PARAMS ((string *, const char *));
340
341static void
342string_prependn PARAMS ((string *, const char *, int));
343
344static int
345get_count PARAMS ((const char **, int *));
346
347static int
348consume_count PARAMS ((const char **));
349
a3a5b5b7
MM
350static int
351consume_count_with_underscores PARAMS ((const char**));
352
6599da04
JM
353static int
354demangle_args PARAMS ((struct work_stuff *, const char **, string *));
355
9923cc56
MM
356static int
357demangle_nested_args PARAMS ((struct work_stuff*, const char**, string*));
358
6599da04
JM
359static int
360do_type PARAMS ((struct work_stuff *, const char **, string *));
361
362static int
363do_arg PARAMS ((struct work_stuff *, const char **, string *));
364
365static void
366demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
367 const char *));
368
369static void
370remember_type PARAMS ((struct work_stuff *, const char *, int));
371
5e5199e8
AM
372static void
373remember_Btype PARAMS ((struct work_stuff *, const char *, int, int));
374
375static int
376register_Btype PARAMS ((struct work_stuff *));
377
378static void
379remember_Ktype PARAMS ((struct work_stuff *, const char *, int));
380
6599da04
JM
381static void
382forget_types PARAMS ((struct work_stuff *));
383
5e5199e8
AM
384static void
385forget_B_and_K_types PARAMS ((struct work_stuff *));
386
6599da04
JM
387static void
388string_prepends PARAMS ((string *, string *));
389
f9c85454 390static int
4d17a06f
MM
391demangle_template_value_parm PARAMS ((struct work_stuff*, const char**,
392 string*, type_kind_t));
f9c85454 393
6599da04
JM
394/* Translate count to integer, consuming tokens in the process.
395 Conversion terminates on the first non-digit character.
396 Trying to consume something that isn't a count results in
397 no consumption of input and a return of 0. */
398
399static int
400consume_count (type)
401 const char **type;
402{
403 int count = 0;
404
405 while (isdigit (**type))
406 {
407 count *= 10;
408 count += **type - '0';
409 (*type)++;
410 }
411 return (count);
412}
413
a3a5b5b7 414
9ee02b5c 415/* Like consume_count, but for counts that are preceded and followed
a3a5b5b7
MM
416 by '_' if they are greater than 10. Also, -1 is returned for
417 failure, since 0 can be a valid value. */
418
419static int
420consume_count_with_underscores (mangled)
421 const char **mangled;
422{
423 int idx;
424
425 if (**mangled == '_')
426 {
427 (*mangled)++;
428 if (!isdigit (**mangled))
429 return -1;
430
431 idx = consume_count (mangled);
432 if (**mangled != '_')
433 /* The trailing underscore was missing. */
434 return -1;
435
436 (*mangled)++;
437 }
438 else
439 {
440 if (**mangled < '0' || **mangled > '9')
441 return -1;
442
443 idx = **mangled - '0';
444 (*mangled)++;
445 }
446
447 return idx;
448}
449
6599da04
JM
450int
451cplus_demangle_opname (opname, result, options)
452 const char *opname;
453 char *result;
454 int options;
455{
d6f4ec51 456 int len, len1, ret;
6599da04
JM
457 string type;
458 struct work_stuff work[1];
459 const char *tem;
460
461 len = strlen(opname);
462 result[0] = '\0';
463 ret = 0;
63586755 464 memset ((char *) work, 0, sizeof (work));
6599da04
JM
465 work->options = options;
466
467 if (opname[0] == '_' && opname[1] == '_'
468 && opname[2] == 'o' && opname[3] == 'p')
469 {
470 /* ANSI. */
471 /* type conversion operator. */
472 tem = opname + 4;
473 if (do_type (work, &tem, &type))
474 {
475 strcat (result, "operator ");
476 strncat (result, type.b, type.p - type.b);
477 string_delete (&type);
478 ret = 1;
479 }
480 }
481 else if (opname[0] == '_' && opname[1] == '_'
482 && opname[2] >= 'a' && opname[2] <= 'z'
483 && opname[3] >= 'a' && opname[3] <= 'z')
484 {
485 if (opname[4] == '\0')
486 {
487 /* Operator. */
d6f4ec51 488 size_t i;
6599da04
JM
489 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
490 {
491 if (strlen (optable[i].in) == 2
492 && memcmp (optable[i].in, opname + 2, 2) == 0)
493 {
494 strcat (result, "operator");
495 strcat (result, optable[i].out);
496 ret = 1;
497 break;
498 }
499 }
500 }
501 else
502 {
503 if (opname[2] == 'a' && opname[5] == '\0')
504 {
505 /* Assignment. */
d6f4ec51 506 size_t i;
6599da04
JM
507 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
508 {
509 if (strlen (optable[i].in) == 3
510 && memcmp (optable[i].in, opname + 2, 3) == 0)
511 {
512 strcat (result, "operator");
513 strcat (result, optable[i].out);
514 ret = 1;
515 break;
516 }
517 }
518 }
519 }
520 }
521 else if (len >= 3
522 && opname[0] == 'o'
523 && opname[1] == 'p'
524 && strchr (cplus_markers, opname[2]) != NULL)
525 {
526 /* see if it's an assignment expression */
527 if (len >= 10 /* op$assign_ */
528 && memcmp (opname + 3, "assign_", 7) == 0)
529 {
d6f4ec51 530 size_t i;
6599da04
JM
531 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
532 {
533 len1 = len - 10;
534 if (strlen (optable[i].in) == len1
535 && memcmp (optable[i].in, opname + 10, len1) == 0)
536 {
537 strcat (result, "operator");
538 strcat (result, optable[i].out);
539 strcat (result, "=");
540 ret = 1;
541 break;
542 }
543 }
544 }
545 else
546 {
d6f4ec51 547 size_t i;
6599da04
JM
548 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
549 {
550 len1 = len - 3;
551 if (strlen (optable[i].in) == len1
552 && memcmp (optable[i].in, opname + 3, len1) == 0)
553 {
554 strcat (result, "operator");
555 strcat (result, optable[i].out);
556 ret = 1;
557 break;
558 }
559 }
560 }
561 }
562 else if (len >= 5 && memcmp (opname, "type", 4) == 0
563 && strchr (cplus_markers, opname[4]) != NULL)
564 {
565 /* type conversion operator */
566 tem = opname + 5;
567 if (do_type (work, &tem, &type))
568 {
569 strcat (result, "operator ");
570 strncat (result, type.b, type.p - type.b);
571 string_delete (&type);
572 ret = 1;
573 }
574 }
5e5199e8 575 squangle_mop_up (work);
6599da04
JM
576 return ret;
577
578}
579/* Takes operator name as e.g. "++" and returns mangled
580 operator name (e.g. "postincrement_expr"), or NULL if not found.
581
582 If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
583 if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
584
585const char *
586cplus_mangle_opname (opname, options)
587 const char *opname;
588 int options;
589{
d6f4ec51 590 size_t i;
6599da04
JM
591 int len;
592
593 len = strlen (opname);
594 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
595 {
596 if (strlen (optable[i].out) == len
597 && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
598 && memcmp (optable[i].out, opname, len) == 0)
599 return optable[i].in;
600 }
601 return (0);
602}
603
604/* char *cplus_demangle (const char *mangled, int options)
605
606 If MANGLED is a mangled function name produced by GNU C++, then
607 a pointer to a malloced string giving a C++ representation
608 of the name will be returned; otherwise NULL will be returned.
609 It is the caller's responsibility to free the string which
610 is returned.
611
612 The OPTIONS arg may contain one or more of the following bits:
613
614 DMGL_ANSI ANSI qualifiers such as `const' and `void' are
615 included.
616 DMGL_PARAMS Function parameters are included.
617
618 For example,
619
620 cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
621 cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
622 cplus_demangle ("foo__1Ai", 0) => "A::foo"
623
624 cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
625 cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
626 cplus_demangle ("foo__1Afe", 0) => "A::foo"
627
628 Note that any leading underscores, or other such characters prepended by
629 the compilation system, are presumed to have already been stripped from
630 MANGLED. */
631
632char *
633cplus_demangle (mangled, options)
634 const char *mangled;
635 int options;
636{
5e5199e8
AM
637 char *ret;
638 struct work_stuff work[1];
639 memset ((char *) work, 0, sizeof (work));
640 work -> options = options;
641 if ((work -> options & DMGL_STYLE_MASK) == 0)
642 work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK;
643
d6f4ec51 644 ret = internal_cplus_demangle (work, mangled);
5e5199e8
AM
645 squangle_mop_up (work);
646 return (ret);
647}
648
649
650/* This function performs most of what cplus_demangle use to do, but
651 to be able to demangle a name with a B, K or n code, we need to
652 have a longer term memory of what types have been seen. The original
653 now intializes and cleans up the squangle code info, while internal
654 calls go directly to this routine to avoid resetting that info. */
655
656static char *
d6f4ec51 657internal_cplus_demangle (work, mangled)
5e5199e8
AM
658 struct work_stuff *work;
659 const char *mangled;
5e5199e8
AM
660{
661
6599da04
JM
662 string decl;
663 int success = 0;
6599da04 664 char *demangled = NULL;
5e5199e8 665 int s1,s2,s3,s4;
9923cc56 666 int saved_volatile_type;
5e5199e8
AM
667 s1 = work->constructor;
668 s2 = work->destructor;
669 s3 = work->static_type;
670 s4 = work->const_type;
9923cc56 671 saved_volatile_type = work->volatile_type;
5e5199e8
AM
672 work->constructor = work->destructor = 0;
673 work->static_type = work->const_type = 0;
9923cc56 674 work->volatile_type = 0;
6599da04
JM
675
676 if ((mangled != NULL) && (*mangled != '\0'))
677 {
6599da04
JM
678 string_init (&decl);
679
680 /* First check to see if gnu style demangling is active and if the
681 string to be demangled contains a CPLUS_MARKER. If so, attempt to
682 recognize one of the gnu special forms rather than looking for a
683 standard prefix. In particular, don't worry about whether there
684 is a "__" string in the mangled string. Consider "_$_5__foo" for
685 example. */
686
687 if ((AUTO_DEMANGLING || GNU_DEMANGLING))
688 {
689 success = gnu_special (work, &mangled, &decl);
690 }
691 if (!success)
692 {
693 success = demangle_prefix (work, &mangled, &decl);
694 }
695 if (success && (*mangled != '\0'))
696 {
697 success = demangle_signature (work, &mangled, &decl);
698 }
699 if (work->constructor == 2)
700 {
5e5199e8 701 string_prepend (&decl, "global constructors keyed to ");
6599da04
JM
702 work->constructor = 0;
703 }
704 else if (work->destructor == 2)
705 {
5e5199e8 706 string_prepend (&decl, "global destructors keyed to ");
6599da04
JM
707 work->destructor = 0;
708 }
709 demangled = mop_up (work, &decl, success);
710 }
5e5199e8
AM
711 work->constructor = s1;
712 work->destructor = s2;
713 work->static_type = s3;
714 work->const_type = s4;
9923cc56 715 work->volatile_type = saved_volatile_type;
6599da04
JM
716 return (demangled);
717}
718
5e5199e8
AM
719
720/* Clear out and squangling related storage */
d6f4ec51 721static void
5e5199e8
AM
722squangle_mop_up (work)
723 struct work_stuff *work;
724{
725 /* clean up the B and K type mangling types. */
726 forget_B_and_K_types (work);
727 if (work -> btypevec != NULL)
728 {
729 free ((char *) work -> btypevec);
730 }
731 if (work -> ktypevec != NULL)
732 {
733 free ((char *) work -> ktypevec);
734 }
735}
736
737/* Clear out any mangled storage */
738
6599da04
JM
739static char *
740mop_up (work, declp, success)
741 struct work_stuff *work;
742 string *declp;
743 int success;
744{
745 char *demangled = NULL;
746
747 /* Discard the remembered types, if any. */
748
749 forget_types (work);
750 if (work -> typevec != NULL)
751 {
752 free ((char *) work -> typevec);
5e5199e8 753 work -> typevec = NULL;
6599da04 754 }
a3a5b5b7
MM
755 if (work->tmpl_argvec)
756 {
757 int i;
758
759 for (i = 0; i < work->ntmpl_args; i++)
760 if (work->tmpl_argvec[i])
761 free ((char*) work->tmpl_argvec[i]);
762
763 free ((char*) work->tmpl_argvec);
5e5199e8 764 work->tmpl_argvec = NULL;
a3a5b5b7 765 }
9923cc56
MM
766 if (work->previous_argument)
767 {
768 string_delete (work->previous_argument);
769 free ((char*) work->previous_argument);
770 }
a3a5b5b7 771
6599da04
JM
772 /* If demangling was successful, ensure that the demangled string is null
773 terminated and return it. Otherwise, free the demangling decl. */
774
775 if (!success)
776 {
777 string_delete (declp);
778 }
779 else
780 {
781 string_appendn (declp, "", 1);
782 demangled = declp -> b;
783 }
784 return (demangled);
785}
786
787/*
788
789LOCAL FUNCTION
790
791 demangle_signature -- demangle the signature part of a mangled name
792
793SYNOPSIS
794
795 static int
796 demangle_signature (struct work_stuff *work, const char **mangled,
797 string *declp);
798
799DESCRIPTION
800
801 Consume and demangle the signature portion of the mangled name.
802
803 DECLP is the string where demangled output is being built. At
804 entry it contains the demangled root name from the mangled name
805 prefix. I.E. either a demangled operator name or the root function
806 name. In some special cases, it may contain nothing.
807
808 *MANGLED points to the current unconsumed location in the mangled
809 name. As tokens are consumed and demangling is performed, the
810 pointer is updated to continuously point at the next token to
811 be consumed.
812
813 Demangling GNU style mangled names is nasty because there is no
814 explicit token that marks the start of the outermost function
815 argument list. */
816
817static int
818demangle_signature (work, mangled, declp)
819 struct work_stuff *work;
820 const char **mangled;
821 string *declp;
822{
823 int success = 1;
824 int func_done = 0;
825 int expect_func = 0;
a3a5b5b7 826 int expect_return_type = 0;
6599da04
JM
827 const char *oldmangled = NULL;
828 string trawname;
829 string tname;
830
831 while (success && (**mangled != '\0'))
832 {
833 switch (**mangled)
834 {
835 case 'Q':
836 oldmangled = *mangled;
837 success = demangle_qualified (work, mangled, declp, 1, 0);
838 if (success)
9923cc56 839 remember_type (work, oldmangled, *mangled - oldmangled);
6599da04 840 if (AUTO_DEMANGLING || GNU_DEMANGLING)
9923cc56 841 expect_func = 1;
6599da04
JM
842 oldmangled = NULL;
843 break;
5e5199e8
AM
844
845 case 'K':
846 oldmangled = *mangled;
847 success = demangle_qualified (work, mangled, declp, 1, 0);
848 if (AUTO_DEMANGLING || GNU_DEMANGLING)
849 {
850 expect_func = 1;
851 }
852 oldmangled = NULL;
853 break;
6599da04
JM
854
855 case 'S':
856 /* Static member function */
857 if (oldmangled == NULL)
858 {
859 oldmangled = *mangled;
860 }
861 (*mangled)++;
862 work -> static_type = 1;
863 break;
864
865 case 'C':
9923cc56
MM
866 case 'V':
867 if (**mangled == 'C')
868 work -> const_type = 1;
869 else
870 work->volatile_type = 1;
871
872 /* a qualified member function */
6599da04 873 if (oldmangled == NULL)
9923cc56 874 oldmangled = *mangled;
6599da04 875 (*mangled)++;
6599da04
JM
876 break;
877
878 case '0': case '1': case '2': case '3': case '4':
879 case '5': case '6': case '7': case '8': case '9':
880 if (oldmangled == NULL)
881 {
882 oldmangled = *mangled;
883 }
884 success = demangle_class (work, mangled, declp);
885 if (success)
886 {
887 remember_type (work, oldmangled, *mangled - oldmangled);
888 }
889 if (AUTO_DEMANGLING || GNU_DEMANGLING)
890 {
891 expect_func = 1;
892 }
893 oldmangled = NULL;
894 break;
9923cc56
MM
895
896 case 'B':
897 {
898 string s;
899 success = do_type (work, mangled, &s);
900 if (success)
901 {
902 string_append (&s, SCOPE_STRING (work));
903 string_prepends (declp, &s);
904 }
905 oldmangled = NULL;
906 expect_func = 1;
907 }
908 break;
909
6599da04
JM
910 case 'F':
911 /* Function */
912 /* ARM style demangling includes a specific 'F' character after
913 the class name. For GNU style, it is just implied. So we can
914 safely just consume any 'F' at this point and be compatible
915 with either style. */
916
917 oldmangled = NULL;
918 func_done = 1;
919 (*mangled)++;
920
921 /* For lucid/ARM style we have to forget any types we might
922 have remembered up to this point, since they were not argument
923 types. GNU style considers all types seen as available for
924 back references. See comment in demangle_args() */
925
926 if (LUCID_DEMANGLING || ARM_DEMANGLING)
927 {
928 forget_types (work);
929 }
930 success = demangle_args (work, mangled, declp);
931 break;
932
933 case 't':
934 /* G++ Template */
935 string_init(&trawname);
936 string_init(&tname);
937 if (oldmangled == NULL)
938 {
939 oldmangled = *mangled;
940 }
9923cc56
MM
941 success = demangle_template (work, mangled, &tname,
942 &trawname, 1, 1);
6599da04
JM
943 if (success)
944 {
945 remember_type (work, oldmangled, *mangled - oldmangled);
946 }
4d59ab3f
JM
947 string_append (&tname, SCOPE_STRING (work));
948
6599da04
JM
949 string_prepends(declp, &tname);
950 if (work -> destructor & 1)
951 {
952 string_prepend (&trawname, "~");
953 string_appends (declp, &trawname);
954 work->destructor -= 1;
955 }
956 if ((work->constructor & 1) || (work->destructor & 1))
957 {
958 string_appends (declp, &trawname);
959 work->constructor -= 1;
960 }
961 string_delete(&trawname);
962 string_delete(&tname);
963 oldmangled = NULL;
964 expect_func = 1;
965 break;
966
967 case '_':
a3a5b5b7
MM
968 if (GNU_DEMANGLING && expect_return_type)
969 {
970 /* Read the return type. */
971 string return_type;
972 string_init (&return_type);
973
974 (*mangled)++;
975 success = do_type (work, mangled, &return_type);
976 APPEND_BLANK (&return_type);
977
978 string_prepends (declp, &return_type);
979 string_delete (&return_type);
980 break;
981 }
982 else
983 /* At the outermost level, we cannot have a return type specified,
984 so if we run into another '_' at this point we are dealing with
985 a mangled name that is either bogus, or has been mangled by
986 some algorithm we don't know how to deal with. So just
987 reject the entire demangling. */
988 success = 0;
6599da04
JM
989 break;
990
a3a5b5b7
MM
991 case 'H':
992 if (GNU_DEMANGLING)
993 {
994 /* A G++ template function. Read the template arguments. */
9923cc56
MM
995 success = demangle_template (work, mangled, declp, 0, 0,
996 0);
19ddc834
JM
997 if (!(work->constructor & 1))
998 expect_return_type = 1;
a3a5b5b7
MM
999 (*mangled)++;
1000 break;
1001 }
1002 else
1003 /* fall through */
9ee02b5c 1004 {;}
a3a5b5b7 1005
6599da04
JM
1006 default:
1007 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1008 {
1009 /* Assume we have stumbled onto the first outermost function
1010 argument token, and start processing args. */
1011 func_done = 1;
1012 success = demangle_args (work, mangled, declp);
1013 }
1014 else
1015 {
1016 /* Non-GNU demanglers use a specific token to mark the start
1017 of the outermost function argument tokens. Typically 'F',
1018 for ARM-demangling, for example. So if we find something
1019 we are not prepared for, it must be an error. */
1020 success = 0;
1021 }
1022 break;
1023 }
1024 /*
1025 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1026 */
1027 {
1028 if (success && expect_func)
1029 {
1030 func_done = 1;
1031 success = demangle_args (work, mangled, declp);
a3a5b5b7
MM
1032 /* Since template include the mangling of their return types,
1033 we must set expect_func to 0 so that we don't try do
1034 demangle more arguments the next time we get here. */
1035 expect_func = 0;
6599da04
JM
1036 }
1037 }
1038 }
1039 if (success && !func_done)
1040 {
1041 if (AUTO_DEMANGLING || GNU_DEMANGLING)
1042 {
1043 /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1044 bar__3fooi is 'foo::bar(int)'. We get here when we find the
1045 first case, and need to ensure that the '(void)' gets added to
1046 the current declp. Note that with ARM, the first case
1047 represents the name of a static data member 'foo::bar',
1048 which is in the current declp, so we leave it alone. */
1049 success = demangle_args (work, mangled, declp);
1050 }
1051 }
1052 if (success && work -> static_type && PRINT_ARG_TYPES)
9923cc56 1053 string_append (declp, " static");
6599da04 1054 if (success && work -> const_type && PRINT_ARG_TYPES)
9923cc56
MM
1055 string_append (declp, " const");
1056 else if (success && work->volatile_type && PRINT_ARG_TYPES)
1057 string_append (declp, " volatile");
1058
6599da04
JM
1059 return (success);
1060}
1061
1062#if 0
1063
1064static int
1065demangle_method_args (work, mangled, declp)
1066 struct work_stuff *work;
1067 const char **mangled;
1068 string *declp;
1069{
1070 int success = 0;
1071
1072 if (work -> static_type)
1073 {
1074 string_append (declp, *mangled + 1);
1075 *mangled += strlen (*mangled);
1076 success = 1;
1077 }
1078 else
1079 {
1080 success = demangle_args (work, mangled, declp);
1081 }
1082 return (success);
1083}
1084
1085#endif
1086
9ee02b5c
JL
1087static int
1088demangle_template_template_parm (work, mangled, tname)
1089 struct work_stuff *work;
1090 const char **mangled;
1091 string *tname;
1092{
1093 int i;
1094 int r;
1095 int need_comma = 0;
1096 int success = 1;
1097 string temp;
1098
1099 string_append (tname, "template <");
1100 /* get size of template parameter list */
1101 if (get_count (mangled, &r))
1102 {
1103 for (i = 0; i < r; i++)
1104 {
1105 if (need_comma)
1106 {
1107 string_append (tname, ", ");
1108 }
1109
1110 /* Z for type parameters */
1111 if (**mangled == 'Z')
1112 {
1113 (*mangled)++;
1114 string_append (tname, "class");
1115 }
1116 /* z for template parameters */
1117 else if (**mangled == 'z')
1118 {
1119 (*mangled)++;
1120 success =
1121 demangle_template_template_parm (work, mangled, tname);
1122 if (!success)
1123 {
1124 break;
1125 }
1126 }
1127 else
1128 {
1129 /* temp is initialized in do_type */
1130 success = do_type (work, mangled, &temp);
1131 if (success)
1132 {
1133 string_appends (tname, &temp);
1134 }
1135 string_delete(&temp);
1136 if (!success)
1137 {
1138 break;
1139 }
1140 }
1141 need_comma = 1;
1142 }
1143
1144 }
1145 if (tname->p[-1] == '>')
1146 string_append (tname, " ");
1147 string_append (tname, "> class");
1148 return (success);
1149}
1150
f9c85454
MM
1151static int
1152demangle_integral_value (work, mangled, s)
1153 struct work_stuff *work;
1154 const char** mangled;
1155 string* s;
1156{
1157 int success;
1158
1159 if (**mangled == 'E')
1160 {
1161 int need_operator = 0;
1162
1163 success = 1;
1164 string_appendn (s, "(", 1);
1165 (*mangled)++;
1166 while (success && **mangled != 'W' && **mangled != '\0')
1167 {
1168 if (need_operator)
1169 {
1170 size_t i;
1171 size_t len;
1172
1173 success = 0;
1174
1175 len = strlen (*mangled);
1176
1177 for (i = 0;
1178 i < sizeof (optable) / sizeof (optable [0]);
1179 ++i)
1180 {
1181 size_t l = strlen (optable[i].in);
1182
1183 if (l <= len
1184 && memcmp (optable[i].in, *mangled, l) == 0)
1185 {
1186 string_appendn (s, " ", 1);
1187 string_append (s, optable[i].out);
1188 string_appendn (s, " ", 1);
1189 success = 1;
1190 (*mangled) += l;
1191 break;
1192 }
1193 }
1194
1195 if (!success)
1196 break;
1197 }
1198 else
1199 need_operator = 1;
1200
4d17a06f
MM
1201 success = demangle_template_value_parm (work, mangled, s,
1202 tk_integral);
f9c85454
MM
1203 }
1204
1205 if (**mangled != 'W')
1206 success = 0;
1207 else
1208 {
1209 string_appendn (s, ")", 1);
1210 (*mangled)++;
1211 }
1212 }
5e5199e8 1213 else if (**mangled == 'Q' || **mangled == 'K')
f9c85454
MM
1214 success = demangle_qualified (work, mangled, s, 0, 1);
1215 else
1216 {
1217 success = 0;
1218
1219 if (**mangled == 'm')
1220 {
1221 string_appendn (s, "-", 1);
1222 (*mangled)++;
1223 }
1224 while (isdigit (**mangled))
1225 {
1226 string_appendn (s, *mangled, 1);
1227 (*mangled)++;
1228 success = 1;
1229 }
1230 }
1231
1232 return success;
1233}
1234
1235static int
4d17a06f 1236demangle_template_value_parm (work, mangled, s, tk)
f9c85454
MM
1237 struct work_stuff *work;
1238 const char **mangled;
1239 string* s;
4d17a06f 1240 type_kind_t tk;
f9c85454 1241{
f9c85454
MM
1242 int success = 1;
1243
f9c85454
MM
1244 if (**mangled == 'Y')
1245 {
1246 /* The next argument is a template parameter. */
1247 int idx;
1248
1249 (*mangled)++;
1250 idx = consume_count_with_underscores (mangled);
1251 if (idx == -1
1252 || (work->tmpl_argvec && idx >= work->ntmpl_args)
1253 || consume_count_with_underscores (mangled) == -1)
1254 return -1;
1255 if (work->tmpl_argvec)
1256 string_append (s, work->tmpl_argvec[idx]);
1257 else
1258 {
1259 char buf[10];
1260 sprintf(buf, "T%d", idx);
1261 string_append (s, buf);
1262 }
1263 }
4d17a06f 1264 else if (tk == tk_integral)
f9c85454 1265 success = demangle_integral_value (work, mangled, s);
4d17a06f 1266 else if (tk == tk_char)
f9c85454
MM
1267 {
1268 char tmp[2];
1269 int val;
1270 if (**mangled == 'm')
1271 {
1272 string_appendn (s, "-", 1);
1273 (*mangled)++;
1274 }
1275 string_appendn (s, "'", 1);
1276 val = consume_count(mangled);
1277 if (val == 0)
1278 return -1;
1279 tmp[0] = (char)val;
1280 tmp[1] = '\0';
1281 string_appendn (s, &tmp[0], 1);
1282 string_appendn (s, "'", 1);
1283 }
4d17a06f 1284 else if (tk == tk_bool)
f9c85454
MM
1285 {
1286 int val = consume_count (mangled);
1287 if (val == 0)
1288 string_appendn (s, "false", 5);
1289 else if (val == 1)
1290 string_appendn (s, "true", 4);
1291 else
1292 success = 0;
1293 }
4d17a06f 1294 else if (tk == tk_real)
f9c85454
MM
1295 {
1296 if (**mangled == 'm')
1297 {
1298 string_appendn (s, "-", 1);
1299 (*mangled)++;
1300 }
1301 while (isdigit (**mangled))
1302 {
1303 string_appendn (s, *mangled, 1);
1304 (*mangled)++;
1305 }
1306 if (**mangled == '.') /* fraction */
1307 {
1308 string_appendn (s, ".", 1);
1309 (*mangled)++;
1310 while (isdigit (**mangled))
1311 {
1312 string_appendn (s, *mangled, 1);
1313 (*mangled)++;
1314 }
1315 }
1316 if (**mangled == 'e') /* exponent */
1317 {
1318 string_appendn (s, "e", 1);
1319 (*mangled)++;
1320 while (isdigit (**mangled))
1321 {
1322 string_appendn (s, *mangled, 1);
1323 (*mangled)++;
1324 }
1325 }
1326 }
4d17a06f 1327 else if (tk == tk_pointer)
f9c85454
MM
1328 {
1329 int symbol_len = consume_count (mangled);
1330 if (symbol_len == 0)
1331 return -1;
1332 if (symbol_len == 0)
1333 string_appendn (s, "0", 1);
1334 else
1335 {
1336 char *p = xmalloc (symbol_len + 1), *q;
1337 strncpy (p, *mangled, symbol_len);
1338 p [symbol_len] = '\0';
d6f4ec51 1339 q = internal_cplus_demangle (work, p);
f9c85454
MM
1340 string_appendn (s, "&", 1);
1341 if (q)
1342 {
1343 string_append (s, q);
1344 free (q);
1345 }
1346 else
1347 string_append (s, p);
1348 free (p);
1349 }
1350 *mangled += symbol_len;
1351 }
1352
1353 return success;
1354}
1355
9923cc56
MM
1356/* Demangle the template name in MANGLED. The full name of the
1357 template (e.g., S<int>) is placed in TNAME. The name without the
1358 template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
1359 non-NULL. If IS_TYPE is nonzero, this template is a type template,
1360 not a function template. If both IS_TYPE and REMEMBER are nonzero,
1361 the tmeplate is remembered in the list of back-referenceable
1362 types. */
1363
6599da04 1364static int
9923cc56 1365demangle_template (work, mangled, tname, trawname, is_type, remember)
6599da04
JM
1366 struct work_stuff *work;
1367 const char **mangled;
1368 string *tname;
1369 string *trawname;
a3a5b5b7 1370 int is_type;
9923cc56 1371 int remember;
6599da04
JM
1372{
1373 int i;
6599da04
JM
1374 int r;
1375 int need_comma = 0;
1376 int success = 0;
6599da04 1377 const char *start;
6599da04 1378 string temp;
9923cc56 1379 int bindex;
6599da04
JM
1380
1381 (*mangled)++;
a3a5b5b7 1382 if (is_type)
6599da04 1383 {
9923cc56
MM
1384 if (remember)
1385 bindex = register_Btype (work);
a3a5b5b7
MM
1386 start = *mangled;
1387 /* get template name */
9ee02b5c 1388 if (**mangled == 'z')
a3a5b5b7 1389 {
9ee02b5c
JL
1390 int idx;
1391 (*mangled)++;
1392 (*mangled)++;
1393
1394 idx = consume_count_with_underscores (mangled);
1395 if (idx == -1
1396 || (work->tmpl_argvec && idx >= work->ntmpl_args)
1397 || consume_count_with_underscores (mangled) == -1)
9923cc56
MM
1398 return (0);
1399
9ee02b5c
JL
1400 if (work->tmpl_argvec)
1401 {
1402 string_append (tname, work->tmpl_argvec[idx]);
1403 if (trawname)
1404 string_append (trawname, work->tmpl_argvec[idx]);
1405 }
1406 else
1407 {
1408 char buf[10];
1409 sprintf(buf, "T%d", idx);
1410 string_append (tname, buf);
1411 if (trawname)
9923cc56 1412 string_append (trawname, buf);
9ee02b5c 1413 }
a3a5b5b7 1414 }
9ee02b5c 1415 else
a3a5b5b7 1416 {
9ee02b5c
JL
1417 if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
1418 {
1419 return (0);
1420 }
9923cc56 1421 string_appendn (tname, *mangled, r);
9ee02b5c
JL
1422 if (trawname)
1423 string_appendn (trawname, *mangled, r);
9ee02b5c 1424 *mangled += r;
a3a5b5b7 1425 }
6599da04 1426 }
9923cc56 1427 string_append (tname, "<");
6599da04
JM
1428 /* get size of template parameter list */
1429 if (!get_count (mangled, &r))
1430 {
1431 return (0);
1432 }
a3a5b5b7
MM
1433 if (!is_type)
1434 {
1435 /* Create an array for saving the template argument values. */
1436 work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
1437 work->ntmpl_args = r;
1438 for (i = 0; i < r; i++)
1439 work->tmpl_argvec[i] = 0;
1440 }
6599da04
JM
1441 for (i = 0; i < r; i++)
1442 {
1443 if (need_comma)
1444 {
1445 string_append (tname, ", ");
1446 }
1447 /* Z for type parameters */
1448 if (**mangled == 'Z')
1449 {
1450 (*mangled)++;
1451 /* temp is initialized in do_type */
1452 success = do_type (work, mangled, &temp);
1453 if (success)
1454 {
1455 string_appends (tname, &temp);
a3a5b5b7
MM
1456
1457 if (!is_type)
1458 {
1459 /* Save the template argument. */
1460 int len = temp.p - temp.b;
1461 work->tmpl_argvec[i] = xmalloc (len + 1);
1462 memcpy (work->tmpl_argvec[i], temp.b, len);
1463 work->tmpl_argvec[i][len] = '\0';
1464 }
6599da04
JM
1465 }
1466 string_delete(&temp);
1467 if (!success)
1468 {
1469 break;
1470 }
1471 }
9ee02b5c
JL
1472 /* z for template parameters */
1473 else if (**mangled == 'z')
1474 {
1475 int r2;
1476 (*mangled)++;
1477 success = demangle_template_template_parm (work, mangled, tname);
1478
1479 if (success
1480 && (r2 = consume_count (mangled)) > 0 && strlen (*mangled) >= r2)
1481 {
1482 string_append (tname, " ");
1483 string_appendn (tname, *mangled, r2);
1484 if (!is_type)
1485 {
1486 /* Save the template argument. */
1487 int len = r2;
1488 work->tmpl_argvec[i] = xmalloc (len + 1);
1489 memcpy (work->tmpl_argvec[i], *mangled, len);
1490 work->tmpl_argvec[i][len] = '\0';
1491 }
1492 *mangled += r2;
1493 }
1494 if (!success)
1495 {
1496 break;
1497 }
1498 }
6599da04
JM
1499 else
1500 {
a3a5b5b7
MM
1501 string param;
1502 string* s;
4d17a06f 1503 const char* start_of_value_parm = *mangled;
a3a5b5b7 1504
6599da04 1505 /* otherwise, value parameter */
f9c85454 1506
6599da04
JM
1507 /* temp is initialized in do_type */
1508 success = do_type (work, mangled, &temp);
6599da04
JM
1509 string_delete(&temp);
1510 if (!success)
4d17a06f 1511 break;
a3a5b5b7
MM
1512
1513 if (!is_type)
1514 {
1515 s = &param;
1516 string_init (s);
1517 }
1518 else
1519 s = tname;
1520
4d17a06f
MM
1521 success = demangle_template_value_parm (work, mangled, s,
1522 (type_kind_t) success);
a3a5b5b7 1523
f9c85454 1524 if (!success)
6599da04 1525 {
f9c85454
MM
1526 if (!is_type)
1527 string_delete (s);
1528 success = 0;
1529 break;
6599da04 1530 }
f9c85454 1531
a3a5b5b7
MM
1532 if (!is_type)
1533 {
1534 int len = s->p - s->b;
1535 work->tmpl_argvec[i] = xmalloc (len + 1);
1536 memcpy (work->tmpl_argvec[i], s->b, len);
1537 work->tmpl_argvec[i][len] = '\0';
1538
1539 string_appends (tname, s);
1540 string_delete (s);
1541 }
6599da04
JM
1542 }
1543 need_comma = 1;
1544 }
4d59ab3f 1545 {
9923cc56
MM
1546 if (tname->p[-1] == '>')
1547 string_append (tname, " ");
1548 string_append (tname, ">");
4d59ab3f 1549 }
6599da04 1550
9923cc56
MM
1551 if (is_type && remember)
1552 remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
1553
6599da04
JM
1554 /*
1555 if (work -> static_type)
1556 {
1557 string_append (declp, *mangled + 1);
1558 *mangled += strlen (*mangled);
1559 success = 1;
1560 }
1561 else
1562 {
1563 success = demangle_args (work, mangled, declp);
1564 }
1565 }
1566 */
1567 return (success);
1568}
1569
1570static int
1571arm_pt (work, mangled, n, anchor, args)
1572 struct work_stuff *work;
1573 const char *mangled;
1574 int n;
1575 const char **anchor, **args;
1576{
1577 /* ARM template? */
1578 if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
1579 {
1580 int len;
1581 *args = *anchor + 6;
1582 len = consume_count (args);
1583 if (*args + len == mangled + n && **args == '_')
1584 {
1585 ++*args;
1586 return 1;
1587 }
1588 }
1589 return 0;
1590}
1591
1592static void
1593demangle_arm_pt (work, mangled, n, declp)
1594 struct work_stuff *work;
1595 const char **mangled;
1596 int n;
1597 string *declp;
1598{
1599 const char *p;
1600 const char *args;
1601 const char *e = *mangled + n;
1602
1603 /* ARM template? */
1604 if (arm_pt (work, *mangled, n, &p, &args))
1605 {
1606 string arg;
1607 string_init (&arg);
1608 string_appendn (declp, *mangled, p - *mangled);
1609 string_append (declp, "<");
1610 /* should do error checking here */
1611 while (args < e) {
1612 string_clear (&arg);
1613 do_type (work, &args, &arg);
1614 string_appends (declp, &arg);
1615 string_append (declp, ",");
1616 }
1617 string_delete (&arg);
1618 --declp->p;
1619 string_append (declp, ">");
1620 }
1621 else
1622 {
1623 string_appendn (declp, *mangled, n);
1624 }
1625 *mangled += n;
1626}
1627
1628static int
1629demangle_class_name (work, mangled, declp)
1630 struct work_stuff *work;
1631 const char **mangled;
1632 string *declp;
1633{
1634 int n;
1635 int success = 0;
1636
1637 n = consume_count (mangled);
1638 if (strlen (*mangled) >= n)
1639 {
1640 demangle_arm_pt (work, mangled, n, declp);
1641 success = 1;
1642 }
1643
1644 return (success);
1645}
1646
1647/*
1648
1649LOCAL FUNCTION
1650
1651 demangle_class -- demangle a mangled class sequence
1652
1653SYNOPSIS
1654
1655 static int
1656 demangle_class (struct work_stuff *work, const char **mangled,
1657 strint *declp)
1658
1659DESCRIPTION
1660
1661 DECLP points to the buffer into which demangling is being done.
1662
1663 *MANGLED points to the current token to be demangled. On input,
1664 it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
1665 On exit, it points to the next token after the mangled class on
1666 success, or the first unconsumed token on failure.
1667
1668 If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
1669 we are demangling a constructor or destructor. In this case
1670 we prepend "class::class" or "class::~class" to DECLP.
1671
1672 Otherwise, we prepend "class::" to the current DECLP.
1673
1674 Reset the constructor/destructor flags once they have been
1675 "consumed". This allows demangle_class to be called later during
1676 the same demangling, to do normal class demangling.
1677
1678 Returns 1 if demangling is successful, 0 otherwise.
1679
1680*/
1681
1682static int
1683demangle_class (work, mangled, declp)
1684 struct work_stuff *work;
1685 const char **mangled;
1686 string *declp;
1687{
1688 int success = 0;
5e5199e8 1689 int btype;
6599da04
JM
1690 string class_name;
1691
1692 string_init (&class_name);
5e5199e8 1693 btype = register_Btype (work);
6599da04
JM
1694 if (demangle_class_name (work, mangled, &class_name))
1695 {
1696 if ((work->constructor & 1) || (work->destructor & 1))
1697 {
1698 string_prepends (declp, &class_name);
1699 if (work -> destructor & 1)
1700 {
1701 string_prepend (declp, "~");
1702 work -> destructor -= 1;
1703 }
1704 else
1705 {
1706 work -> constructor -= 1;
1707 }
1708 }
5e5199e8
AM
1709 remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
1710 remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
9923cc56 1711 string_prepend (declp, SCOPE_STRING (work));
6599da04
JM
1712 string_prepends (declp, &class_name);
1713 success = 1;
1714 }
1715 string_delete (&class_name);
1716 return (success);
1717}
1718
1719/*
1720
1721LOCAL FUNCTION
1722
1723 demangle_prefix -- consume the mangled name prefix and find signature
1724
1725SYNOPSIS
1726
1727 static int
1728 demangle_prefix (struct work_stuff *work, const char **mangled,
1729 string *declp);
1730
1731DESCRIPTION
1732
1733 Consume and demangle the prefix of the mangled name.
1734
1735 DECLP points to the string buffer into which demangled output is
1736 placed. On entry, the buffer is empty. On exit it contains
1737 the root function name, the demangled operator name, or in some
1738 special cases either nothing or the completely demangled result.
1739
1740 MANGLED points to the current pointer into the mangled name. As each
1741 token of the mangled name is consumed, it is updated. Upon entry
1742 the current mangled name pointer points to the first character of
1743 the mangled name. Upon exit, it should point to the first character
1744 of the signature if demangling was successful, or to the first
1745 unconsumed character if demangling of the prefix was unsuccessful.
1746
1747 Returns 1 on success, 0 otherwise.
1748 */
1749
1750static int
1751demangle_prefix (work, mangled, declp)
1752 struct work_stuff *work;
1753 const char **mangled;
1754 string *declp;
1755{
1756 int success = 1;
1757 const char *scan;
1758 int i;
1759
1760 if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
1761 {
1762 char *marker = strchr (cplus_markers, (*mangled)[8]);
1763 if (marker != NULL && *marker == (*mangled)[10])
1764 {
1765 if ((*mangled)[9] == 'D')
1766 {
1767 /* it's a GNU global destructor to be executed at program exit */
1768 (*mangled) += 11;
1769 work->destructor = 2;
1770 if (gnu_special (work, mangled, declp))
1771 return success;
1772 }
1773 else if ((*mangled)[9] == 'I')
1774 {
1775 /* it's a GNU global constructor to be executed at program init */
1776 (*mangled) += 11;
1777 work->constructor = 2;
1778 if (gnu_special (work, mangled, declp))
1779 return success;
1780 }
1781 }
1782 }
1783 else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
1784 {
1785 /* it's a ARM global destructor to be executed at program exit */
1786 (*mangled) += 7;
1787 work->destructor = 2;
1788 }
1789 else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
1790 {
1791 /* it's a ARM global constructor to be executed at program initial */
1792 (*mangled) += 7;
1793 work->constructor = 2;
1794 }
1795
1796 /* This block of code is a reduction in strength time optimization
1797 of:
1798 scan = mystrstr (*mangled, "__"); */
1799
1800 {
1801 scan = *mangled;
1802
1803 do {
1804 scan = strchr (scan, '_');
1805 } while (scan != NULL && *++scan != '_');
1806
1807 if (scan != NULL) --scan;
1808 }
1809
1810 if (scan != NULL)
1811 {
1812 /* We found a sequence of two or more '_', ensure that we start at
1813 the last pair in the sequence. */
1814 i = strspn (scan, "_");
1815 if (i > 2)
1816 {
1817 scan += (i - 2);
1818 }
1819 }
1820
1821 if (scan == NULL)
1822 {
1823 success = 0;
1824 }
1825 else if (work -> static_type)
1826 {
1827 if (!isdigit (scan[0]) && (scan[0] != 't'))
1828 {
1829 success = 0;
1830 }
1831 }
1832 else if ((scan == *mangled)
19ddc834 1833 && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')
5e5199e8 1834 || (scan[2] == 'K') || (scan[2] == 'H')))
6599da04
JM
1835 {
1836 /* The ARM says nothing about the mangling of local variables.
1837 But cfront mangles local variables by prepending __<nesting_level>
1838 to them. As an extension to ARM demangling we handle this case. */
1839 if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
1840 {
1841 *mangled = scan + 2;
1842 consume_count (mangled);
1843 string_append (declp, *mangled);
1844 *mangled += strlen (*mangled);
1845 success = 1;
1846 }
1847 else
1848 {
1849 /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
1850 names like __Q2_3foo3bar for nested type names. So don't accept
19ddc834
JM
1851 this style of constructor for cfront demangling. A GNU
1852 style member-template constructor starts with 'H'. */
6599da04
JM
1853 if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
1854 work -> constructor += 1;
1855 *mangled = scan + 2;
1856 }
1857 }
1858 else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
1859 {
1860 /* Mangled name starts with "__". Skip over any leading '_' characters,
1861 then find the next "__" that separates the prefix from the signature.
1862 */
1863 if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
9ee02b5c 1864 || (arm_special (mangled, declp) == 0))
6599da04
JM
1865 {
1866 while (*scan == '_')
1867 {
1868 scan++;
1869 }
1870 if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
1871 {
1872 /* No separator (I.E. "__not_mangled"), or empty signature
1873 (I.E. "__not_mangled_either__") */
1874 success = 0;
1875 }
1876 else
1877 {
1878 demangle_function_name (work, mangled, declp, scan);
1879 }
1880 }
1881 }
1882 else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
1883 {
1884 /* Cfront-style parameterized type. Handled later as a signature. */
1885 success = 1;
1886
1887 /* ARM template? */
1888 demangle_arm_pt (work, mangled, strlen (*mangled), declp);
1889 }
1890 else if (*(scan + 2) != '\0')
1891 {
1892 /* Mangled name does not start with "__" but does have one somewhere
1893 in there with non empty stuff after it. Looks like a global
1894 function name. */
1895 demangle_function_name (work, mangled, declp, scan);
1896 }
1897 else
1898 {
1899 /* Doesn't look like a mangled name */
1900 success = 0;
1901 }
1902
1903 if (!success && (work->constructor == 2 || work->destructor == 2))
1904 {
1905 string_append (declp, *mangled);
1906 *mangled += strlen (*mangled);
1907 success = 1;
1908 }
1909 return (success);
1910}
1911
1912/*
1913
1914LOCAL FUNCTION
1915
1916 gnu_special -- special handling of gnu mangled strings
1917
1918SYNOPSIS
1919
1920 static int
1921 gnu_special (struct work_stuff *work, const char **mangled,
1922 string *declp);
1923
1924
1925DESCRIPTION
1926
1927 Process some special GNU style mangling forms that don't fit
1928 the normal pattern. For example:
1929
1930 _$_3foo (destructor for class foo)
1931 _vt$foo (foo virtual table)
1932 _vt$foo$bar (foo::bar virtual table)
1933 __vt_foo (foo virtual table, new style with thunks)
1934 _3foo$varname (static data member)
1935 _Q22rs2tu$vw (static data member)
1936 __t6vector1Zii (constructor with template)
1937 __thunk_4__$_7ostream (virtual function thunk)
1938 */
1939
1940static int
1941gnu_special (work, mangled, declp)
1942 struct work_stuff *work;
1943 const char **mangled;
1944 string *declp;
1945{
1946 int n;
1947 int success = 1;
1948 const char *p;
1949
1950 if ((*mangled)[0] == '_'
1951 && strchr (cplus_markers, (*mangled)[1]) != NULL
1952 && (*mangled)[2] == '_')
1953 {
1954 /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
1955 (*mangled) += 3;
1956 work -> destructor += 1;
1957 }
1958 else if ((*mangled)[0] == '_'
1959 && (((*mangled)[1] == '_'
1960 && (*mangled)[2] == 'v'
1961 && (*mangled)[3] == 't'
1962 && (*mangled)[4] == '_')
1963 || ((*mangled)[1] == 'v'
1964 && (*mangled)[2] == 't'
1965 && strchr (cplus_markers, (*mangled)[3]) != NULL)))
1966 {
1967 /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
1968 and create the decl. Note that we consume the entire mangled
1969 input string, which means that demangle_signature has no work
1970 to do. */
1971 if ((*mangled)[2] == 'v')
1972 (*mangled) += 5; /* New style, with thunks: "__vt_" */
1973 else
1974 (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
1975 while (**mangled != '\0')
1976 {
1977 p = strpbrk (*mangled, cplus_markers);
1978 switch (**mangled)
1979 {
1980 case 'Q':
5e5199e8 1981 case 'K':
6599da04
JM
1982 success = demangle_qualified (work, mangled, declp, 0, 1);
1983 break;
1984 case 't':
9923cc56
MM
1985 success = demangle_template (work, mangled, declp, 0, 1,
1986 1);
6599da04
JM
1987 break;
1988 default:
1989 if (isdigit(*mangled[0]))
1990 {
1991 n = consume_count(mangled);
5890bc92
JL
1992 /* We may be seeing a too-large size, or else a
1993 ".<digits>" indicating a static local symbol. In
1994 any case, declare victory and move on; *don't* try
1995 to use n to allocate. */
7bf40741 1996 if (n > strlen (*mangled))
5890bc92
JL
1997 {
1998 success = 1;
1999 break;
2000 }
6599da04
JM
2001 }
2002 else
2003 {
2004 n = strcspn (*mangled, cplus_markers);
2005 }
2006 string_appendn (declp, *mangled, n);
2007 (*mangled) += n;
2008 }
2009
2010 if (success && ((p == NULL) || (p == *mangled)))
2011 {
2012 if (p != NULL)
2013 {
9923cc56 2014 string_append (declp, SCOPE_STRING (work));
6599da04
JM
2015 (*mangled)++;
2016 }
2017 }
2018 else
2019 {
2020 success = 0;
2021 break;
2022 }
2023 }
2024 if (success)
2025 string_append (declp, " virtual table");
2026 }
2027 else if ((*mangled)[0] == '_'
2028 && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
2029 && (p = strpbrk (*mangled, cplus_markers)) != NULL)
2030 {
2031 /* static data member, "_3foo$varname" for example */
2032 (*mangled)++;
2033 switch (**mangled)
2034 {
2035 case 'Q':
5e5199e8 2036 case 'K':
6599da04
JM
2037 success = demangle_qualified (work, mangled, declp, 0, 1);
2038 break;
2039 case 't':
9923cc56 2040 success = demangle_template (work, mangled, declp, 0, 1, 1);
6599da04
JM
2041 break;
2042 default:
2043 n = consume_count (mangled);
2044 string_appendn (declp, *mangled, n);
2045 (*mangled) += n;
2046 }
2047 if (success && (p == *mangled))
2048 {
2049 /* Consumed everything up to the cplus_marker, append the
2050 variable name. */
2051 (*mangled)++;
9923cc56 2052 string_append (declp, SCOPE_STRING (work));
6599da04
JM
2053 n = strlen (*mangled);
2054 string_appendn (declp, *mangled, n);
2055 (*mangled) += n;
2056 }
2057 else
2058 {
2059 success = 0;
2060 }
2061 }
2062 else if (strncmp (*mangled, "__thunk_", 8) == 0)
2063 {
2064 int delta = ((*mangled) += 8, consume_count (mangled));
d6f4ec51 2065 char *method = internal_cplus_demangle (work, ++*mangled);
6599da04
JM
2066 if (method)
2067 {
2068 char buf[50];
2069 sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
2070 string_append (declp, buf);
2071 string_append (declp, method);
2072 free (method);
2073 n = strlen (*mangled);
2074 (*mangled) += n;
2075 }
2076 else
2077 {
2078 success = 0;
2079 }
2080 }
2081 else if (strncmp (*mangled, "__t", 3) == 0
2082 && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
2083 {
2084 p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
2085 (*mangled) += 4;
2086 switch (**mangled)
2087 {
2088 case 'Q':
5e5199e8 2089 case 'K':
6599da04
JM
2090 success = demangle_qualified (work, mangled, declp, 0, 1);
2091 break;
2092 case 't':
9923cc56 2093 success = demangle_template (work, mangled, declp, 0, 1, 1);
6599da04
JM
2094 break;
2095 default:
2096 success = demangle_fund_type (work, mangled, declp);
2097 break;
2098 }
2099 if (success && **mangled != '\0')
2100 success = 0;
2101 if (success)
2102 string_append (declp, p);
2103 }
2104 else
2105 {
2106 success = 0;
2107 }
2108 return (success);
2109}
2110
2111/*
2112
2113LOCAL FUNCTION
2114
2115 arm_special -- special handling of ARM/lucid mangled strings
2116
2117SYNOPSIS
2118
2119 static int
9ee02b5c
JL
2120 arm_special (const char **mangled,
2121 string *declp);
6599da04
JM
2122
2123
2124DESCRIPTION
2125
2126 Process some special ARM style mangling forms that don't fit
2127 the normal pattern. For example:
2128
2129 __vtbl__3foo (foo virtual table)
2130 __vtbl__3foo__3bar (bar::foo virtual table)
2131
2132 */
2133
2134static int
9ee02b5c 2135arm_special (mangled, declp)
6599da04
JM
2136 const char **mangled;
2137 string *declp;
2138{
2139 int n;
2140 int success = 1;
2141 const char *scan;
2142
2143 if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
2144 {
2145 /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
2146 and create the decl. Note that we consume the entire mangled
2147 input string, which means that demangle_signature has no work
2148 to do. */
2149 scan = *mangled + ARM_VTABLE_STRLEN;
2150 while (*scan != '\0') /* first check it can be demangled */
2151 {
2152 n = consume_count (&scan);
2153 if (n==0)
2154 {
2155 return (0); /* no good */
2156 }
2157 scan += n;
2158 if (scan[0] == '_' && scan[1] == '_')
2159 {
2160 scan += 2;
2161 }
2162 }
2163 (*mangled) += ARM_VTABLE_STRLEN;
2164 while (**mangled != '\0')
2165 {
2166 n = consume_count (mangled);
2167 string_prependn (declp, *mangled, n);
2168 (*mangled) += n;
2169 if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
2170 {
2171 string_prepend (declp, "::");
2172 (*mangled) += 2;
2173 }
2174 }
2175 string_append (declp, " virtual table");
2176 }
2177 else
2178 {
2179 success = 0;
2180 }
2181 return (success);
2182}
2183
2184/*
2185
2186LOCAL FUNCTION
2187
2188 demangle_qualified -- demangle 'Q' qualified name strings
2189
2190SYNOPSIS
2191
2192 static int
2193 demangle_qualified (struct work_stuff *, const char *mangled,
2194 string *result, int isfuncname, int append);
2195
2196DESCRIPTION
2197
2198 Demangle a qualified name, such as "Q25Outer5Inner" which is
2199 the mangled form of "Outer::Inner". The demangled output is
2200 prepended or appended to the result string according to the
2201 state of the append flag.
2202
2203 If isfuncname is nonzero, then the qualified name we are building
2204 is going to be used as a member function name, so if it is a
2205 constructor or destructor function, append an appropriate
2206 constructor or destructor name. I.E. for the above example,
2207 the result for use as a constructor is "Outer::Inner::Inner"
2208 and the result for use as a destructor is "Outer::Inner::~Inner".
2209
2210BUGS
2211
2212 Numeric conversion is ASCII dependent (FIXME).
2213
2214 */
2215
2216static int
2217demangle_qualified (work, mangled, result, isfuncname, append)
2218 struct work_stuff *work;
2219 const char **mangled;
2220 string *result;
2221 int isfuncname;
2222 int append;
2223{
5e5199e8 2224 int qualifiers = 0;
6599da04
JM
2225 int success = 1;
2226 const char *p;
2227 char num[2];
2228 string temp;
9923cc56
MM
2229 string last_name;
2230 int bindex = register_Btype (work);
2231
2232 /* We only make use of ISFUNCNAME if the entity is a constructor or
2233 destructor. */
2234 isfuncname = (isfuncname
2235 && ((work->constructor & 1) || (work->destructor & 1)));
6599da04
JM
2236
2237 string_init (&temp);
9923cc56 2238 string_init (&last_name);
5e5199e8
AM
2239
2240 if ((*mangled)[0] == 'K')
2241 {
2242 /* Squangling qualified name reuse */
2243 int idx;
2244 (*mangled)++;
2245 idx = consume_count_with_underscores (mangled);
2246 if (idx == -1 || idx > work -> numk)
2247 success = 0;
2248 else
2249 string_append (&temp, work -> ktypevec[idx]);
2250 }
2251 else
2252 switch ((*mangled)[1])
6599da04
JM
2253 {
2254 case '_':
2255 /* GNU mangled name with more than 9 classes. The count is preceded
2256 by an underscore (to distinguish it from the <= 9 case) and followed
2257 by an underscore. */
2258 p = *mangled + 2;
2259 qualifiers = atoi (p);
2260 if (!isdigit (*p) || *p == '0')
2261 success = 0;
2262
2263 /* Skip the digits. */
2264 while (isdigit (*p))
2265 ++p;
2266
2267 if (*p != '_')
2268 success = 0;
2269
2270 *mangled = p + 1;
2271 break;
2272
2273 case '1':
2274 case '2':
2275 case '3':
2276 case '4':
2277 case '5':
2278 case '6':
2279 case '7':
2280 case '8':
2281 case '9':
2282 /* The count is in a single digit. */
2283 num[0] = (*mangled)[1];
2284 num[1] = '\0';
2285 qualifiers = atoi (num);
2286
2287 /* If there is an underscore after the digit, skip it. This is
2288 said to be for ARM-qualified names, but the ARM makes no
2289 mention of such an underscore. Perhaps cfront uses one. */
2290 if ((*mangled)[2] == '_')
2291 {
2292 (*mangled)++;
2293 }
2294 (*mangled) += 2;
2295 break;
2296
2297 case '0':
2298 default:
2299 success = 0;
2300 }
2301
2302 if (!success)
2303 return success;
2304
2305 /* Pick off the names and collect them in the temp buffer in the order
2306 in which they are found, separated by '::'. */
2307
2308 while (qualifiers-- > 0)
2309 {
5e5199e8 2310 int remember_K = 1;
9923cc56
MM
2311 string_clear (&last_name);
2312
6599da04 2313 if (*mangled[0] == '_')
9923cc56
MM
2314 (*mangled)++;
2315
6599da04
JM
2316 if (*mangled[0] == 't')
2317 {
9923cc56
MM
2318 /* Here we always append to TEMP since we will want to use
2319 the template name without the template parameters as a
2320 constructor or destructor name. The appropriate
2321 (parameter-less) value is returned by demangle_template
2322 in LAST_NAME. We do not remember the template type here,
2323 in order to match the G++ mangling algorithm. */
2324 success = demangle_template(work, mangled, &temp,
2325 &last_name, 1, 0);
2326 if (!success)
2327 break;
2328 }
07623417 2329 else if (*mangled[0] == 'K')
5e5199e8
AM
2330 {
2331 int idx;
2332 (*mangled)++;
2333 idx = consume_count_with_underscores (mangled);
2334 if (idx == -1 || idx > work->numk)
2335 success = 0;
2336 else
2337 string_append (&temp, work->ktypevec[idx]);
2338 remember_K = 0;
2339
6599da04
JM
2340 if (!success) break;
2341 }
2342 else
9923cc56
MM
2343 {
2344 success = do_type (work, mangled, &last_name);
2345 if (!success)
2346 break;
2347 string_appends (&temp, &last_name);
6599da04 2348 }
5e5199e8
AM
2349
2350 if (remember_K)
9923cc56 2351 remember_Ktype (work, temp.b, LEN_STRING (&temp));
5e5199e8 2352
6599da04 2353 if (qualifiers > 0)
9923cc56 2354 string_append (&temp, SCOPE_STRING (work));
6599da04
JM
2355 }
2356
9923cc56
MM
2357 remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
2358
6599da04
JM
2359 /* If we are using the result as a function name, we need to append
2360 the appropriate '::' separated constructor or destructor name.
2361 We do this here because this is the most convenient place, where
2362 we already have a pointer to the name and the length of the name. */
2363
9923cc56 2364 if (isfuncname)
6599da04 2365 {
9923cc56 2366 string_append (&temp, SCOPE_STRING (work));
6599da04 2367 if (work -> destructor & 1)
9923cc56
MM
2368 string_append (&temp, "~");
2369 string_appends (&temp, &last_name);
6599da04
JM
2370 }
2371
2372 /* Now either prepend the temp buffer to the result, or append it,
2373 depending upon the state of the append flag. */
2374
2375 if (append)
9923cc56 2376 string_appends (result, &temp);
6599da04
JM
2377 else
2378 {
2379 if (!STRING_EMPTY (result))
9923cc56 2380 string_append (&temp, SCOPE_STRING (work));
6599da04
JM
2381 string_prepends (result, &temp);
2382 }
2383
9923cc56 2384 string_delete (&last_name);
6599da04
JM
2385 string_delete (&temp);
2386 return (success);
2387}
2388
2389/*
2390
2391LOCAL FUNCTION
2392
2393 get_count -- convert an ascii count to integer, consuming tokens
2394
2395SYNOPSIS
2396
2397 static int
2398 get_count (const char **type, int *count)
2399
2400DESCRIPTION
2401
2402 Return 0 if no conversion is performed, 1 if a string is converted.
2403*/
2404
2405static int
2406get_count (type, count)
2407 const char **type;
2408 int *count;
2409{
2410 const char *p;
2411 int n;
2412
2413 if (!isdigit (**type))
2414 {
2415 return (0);
2416 }
2417 else
2418 {
2419 *count = **type - '0';
2420 (*type)++;
2421 if (isdigit (**type))
2422 {
2423 p = *type;
2424 n = *count;
2425 do
2426 {
2427 n *= 10;
2428 n += *p - '0';
2429 p++;
2430 }
2431 while (isdigit (*p));
2432 if (*p == '_')
2433 {
2434 *type = p + 1;
2435 *count = n;
2436 }
2437 }
2438 }
2439 return (1);
2440}
2441
4d17a06f
MM
2442/* RESULT will be initialised here; it will be freed on failure. The
2443 value returned is really a type_kind_t. */
6599da04
JM
2444
2445static int
2446do_type (work, mangled, result)
2447 struct work_stuff *work;
2448 const char **mangled;
2449 string *result;
2450{
2451 int n;
2452 int done;
2453 int success;
2454 string decl;
2455 const char *remembered_type;
2456 int constp;
2457 int volatilep;
5e5199e8 2458 string btype;
4d17a06f 2459 type_kind_t tk = tk_none;
6599da04 2460
5e5199e8 2461 string_init (&btype);
6599da04
JM
2462 string_init (&decl);
2463 string_init (result);
2464
2465 done = 0;
2466 success = 1;
2467 while (success && !done)
2468 {
2469 int member;
2470 switch (**mangled)
2471 {
2472
2473 /* A pointer type */
2474 case 'P':
2475 case 'p':
2476 (*mangled)++;
9923cc56 2477 string_prepend (&decl, "*");
4d17a06f
MM
2478 if (tk == tk_none)
2479 tk = tk_pointer;
6599da04
JM
2480 break;
2481
2482 /* A reference type */
2483 case 'R':
2484 (*mangled)++;
2485 string_prepend (&decl, "&");
4d17a06f
MM
2486 if (tk == tk_none)
2487 tk = tk_pointer;
6599da04
JM
2488 break;
2489
2490 /* An array */
2491 case 'A':
2492 {
4d17a06f 2493 ++(*mangled);
09007174
JM
2494 if (!STRING_EMPTY (&decl)
2495 && (decl.b[0] == '*' || decl.b[0] == '&'))
5210f3d0
JM
2496 {
2497 string_prepend (&decl, "(");
2498 string_append (&decl, ")");
2499 }
2500 string_append (&decl, "[");
2501 if (**mangled != '_')
2502 success = demangle_template_value_parm (work, mangled, &decl,
2503 tk_integral);
6599da04 2504 if (**mangled == '_')
4d17a06f
MM
2505 ++(*mangled);
2506 string_append (&decl, "]");
6599da04
JM
2507 break;
2508 }
2509
2510 /* A back reference to a previously seen type */
2511 case 'T':
2512 (*mangled)++;
2513 if (!get_count (mangled, &n) || n >= work -> ntypes)
2514 {
2515 success = 0;
2516 }
2517 else
2518 {
2519 remembered_type = work -> typevec[n];
2520 mangled = &remembered_type;
2521 }
2522 break;
2523
2524 /* A function */
2525 case 'F':
2526 (*mangled)++;
09007174
JM
2527 if (!STRING_EMPTY (&decl)
2528 && (decl.b[0] == '*' || decl.b[0] == '&'))
6599da04
JM
2529 {
2530 string_prepend (&decl, "(");
2531 string_append (&decl, ")");
2532 }
2533 /* After picking off the function args, we expect to either find the
2534 function return type (preceded by an '_') or the end of the
2535 string. */
9923cc56 2536 if (!demangle_nested_args (work, mangled, &decl)
6599da04
JM
2537 || (**mangled != '_' && **mangled != '\0'))
2538 {
2539 success = 0;
9923cc56 2540 break;
6599da04
JM
2541 }
2542 if (success && (**mangled == '_'))
9923cc56 2543 (*mangled)++;
6599da04
JM
2544 break;
2545
2546 case 'M':
2547 case 'O':
2548 {
2549 constp = 0;
2550 volatilep = 0;
2551
2552 member = **mangled == 'M';
2553 (*mangled)++;
2554 if (!isdigit (**mangled) && **mangled != 't')
2555 {
2556 success = 0;
2557 break;
2558 }
2559
2560 string_append (&decl, ")");
9923cc56 2561 string_prepend (&decl, SCOPE_STRING (work));
6599da04
JM
2562 if (isdigit (**mangled))
2563 {
2564 n = consume_count (mangled);
2565 if (strlen (*mangled) < n)
2566 {
2567 success = 0;
2568 break;
2569 }
2570 string_prependn (&decl, *mangled, n);
2571 *mangled += n;
2572 }
2573 else
2574 {
2575 string temp;
2576 string_init (&temp);
9923cc56
MM
2577 success = demangle_template (work, mangled, &temp,
2578 NULL, 1, 1);
6599da04
JM
2579 if (success)
2580 {
2581 string_prependn (&decl, temp.b, temp.p - temp.b);
2582 string_clear (&temp);
2583 }
2584 else
2585 break;
2586 }
2587 string_prepend (&decl, "(");
2588 if (member)
2589 {
2590 if (**mangled == 'C')
2591 {
2592 (*mangled)++;
2593 constp = 1;
2594 }
2595 if (**mangled == 'V')
2596 {
2597 (*mangled)++;
2598 volatilep = 1;
2599 }
2600 if (*(*mangled)++ != 'F')
2601 {
2602 success = 0;
2603 break;
2604 }
2605 }
9923cc56 2606 if ((member && !demangle_nested_args (work, mangled, &decl))
6599da04
JM
2607 || **mangled != '_')
2608 {
2609 success = 0;
2610 break;
2611 }
2612 (*mangled)++;
2613 if (! PRINT_ANSI_QUALIFIERS)
2614 {
2615 break;
2616 }
2617 if (constp)
2618 {
2619 APPEND_BLANK (&decl);
2620 string_append (&decl, "const");
2621 }
2622 if (volatilep)
2623 {
2624 APPEND_BLANK (&decl);
2625 string_append (&decl, "volatile");
2626 }
2627 break;
2628 }
2629 case 'G':
2630 (*mangled)++;
2631 break;
2632
2633 case 'C':
1cc75298 2634 case 'V':
6599da04
JM
2635 /*
2636 if ((*mangled)[1] == 'P')
2637 {
2638 */
2639 if (PRINT_ANSI_QUALIFIERS)
2640 {
2641 if (!STRING_EMPTY (&decl))
2642 {
2643 string_prepend (&decl, " ");
2644 }
1cc75298
MM
2645 string_prepend (&decl,
2646 (**mangled) == 'C' ? "const" : "volatile");
6599da04 2647 }
1cc75298 2648 (*mangled)++;
6599da04
JM
2649 break;
2650 /*
2651 }
2652 */
2653
2654 /* fall through */
2655 default:
2656 done = 1;
2657 break;
2658 }
2659 }
2660
5210f3d0 2661 if (success) switch (**mangled)
6599da04
JM
2662 {
2663 /* A qualified name, such as "Outer::Inner". */
2664 case 'Q':
5e5199e8
AM
2665 case 'K':
2666 {
5e5199e8 2667 success = demangle_qualified (work, mangled, result, 0, 1);
5e5199e8
AM
2668 break;
2669 }
2670
2671 /* A back reference to a previously seen squangled type */
2672 case 'B':
2673 (*mangled)++;
2674 if (!get_count (mangled, &n) || n >= work -> numb)
5210f3d0 2675 success = 0;
5e5199e8 2676 else
4d17a06f 2677 string_append (result, work->btypevec[n]);
6599da04
JM
2678 break;
2679
19ddc834
JM
2680 case 'X':
2681 case 'Y':
2682 /* A template parm. We substitute the corresponding argument. */
2683 {
2684 int idx;
19ddc834
JM
2685
2686 (*mangled)++;
2687 idx = consume_count_with_underscores (mangled);
2688
2689 if (idx == -1
2690 || (work->tmpl_argvec && idx >= work->ntmpl_args)
2691 || consume_count_with_underscores (mangled) == -1)
2692 {
2693 success = 0;
2694 break;
2695 }
2696
2697 if (work->tmpl_argvec)
2698 string_append (result, work->tmpl_argvec[idx]);
2699 else
2700 {
2701 char buf[10];
2702 sprintf(buf, "T%d", idx);
2703 string_append (result, buf);
2704 }
2705
2706 success = 1;
2707 }
2708 break;
2709
6599da04
JM
2710 default:
2711 success = demangle_fund_type (work, mangled, result);
4d17a06f
MM
2712 if (tk == tk_none)
2713 tk = (type_kind_t) success;
6599da04
JM
2714 break;
2715 }
2716
2717 if (success)
2718 {
2719 if (!STRING_EMPTY (&decl))
2720 {
2721 string_append (result, " ");
2722 string_appends (result, &decl);
2723 }
2724 }
2725 else
4d17a06f 2726 string_delete (result);
6599da04 2727 string_delete (&decl);
4d17a06f
MM
2728
2729 if (success)
2730 /* Assume an integral type, if we're not sure. */
2731 return (int) ((tk == tk_none) ? tk_integral : tk);
2732 else
2733 return 0;
6599da04
JM
2734}
2735
2736/* Given a pointer to a type string that represents a fundamental type
2737 argument (int, long, unsigned int, etc) in TYPE, a pointer to the
2738 string in which the demangled output is being built in RESULT, and
2739 the WORK structure, decode the types and add them to the result.
2740
2741 For example:
2742
2743 "Ci" => "const int"
2744 "Sl" => "signed long"
2745 "CUs" => "const unsigned short"
2746
4d17a06f 2747 The value returned is really a type_kind_t. */
6599da04
JM
2748
2749static int
2750demangle_fund_type (work, mangled, result)
2751 struct work_stuff *work;
2752 const char **mangled;
2753 string *result;
2754{
2755 int done = 0;
2756 int success = 1;
5e5199e8 2757 string btype;
4d17a06f
MM
2758 type_kind_t tk = tk_integral;
2759
5e5199e8 2760 string_init (&btype);
6599da04
JM
2761
2762 /* First pick off any type qualifiers. There can be more than one. */
2763
2764 while (!done)
2765 {
2766 switch (**mangled)
2767 {
2768 case 'C':
2769 (*mangled)++;
2770 if (PRINT_ANSI_QUALIFIERS)
2771 {
2772 APPEND_BLANK (result);
2773 string_append (result, "const");
2774 }
2775 break;
2776 case 'U':
2777 (*mangled)++;
2778 APPEND_BLANK (result);
2779 string_append (result, "unsigned");
2780 break;
2781 case 'S': /* signed char only */
2782 (*mangled)++;
2783 APPEND_BLANK (result);
2784 string_append (result, "signed");
2785 break;
2786 case 'V':
2787 (*mangled)++;
2788 if (PRINT_ANSI_QUALIFIERS)
2789 {
2790 APPEND_BLANK (result);
2791 string_append (result, "volatile");
2792 }
2793 break;
2794 case 'J':
2795 (*mangled)++;
2796 APPEND_BLANK (result);
19ddc834 2797 string_append (result, "__complex");
6599da04
JM
2798 break;
2799 default:
2800 done = 1;
2801 break;
2802 }
2803 }
2804
2805 /* Now pick off the fundamental type. There can be only one. */
2806
2807 switch (**mangled)
2808 {
2809 case '\0':
2810 case '_':
2811 break;
2812 case 'v':
2813 (*mangled)++;
2814 APPEND_BLANK (result);
2815 string_append (result, "void");
2816 break;
2817 case 'x':
2818 (*mangled)++;
2819 APPEND_BLANK (result);
2820 string_append (result, "long long");
2821 break;
2822 case 'l':
2823 (*mangled)++;
2824 APPEND_BLANK (result);
2825 string_append (result, "long");
2826 break;
2827 case 'i':
2828 (*mangled)++;
2829 APPEND_BLANK (result);
2830 string_append (result, "int");
2831 break;
2832 case 's':
2833 (*mangled)++;
2834 APPEND_BLANK (result);
2835 string_append (result, "short");
2836 break;
2837 case 'b':
2838 (*mangled)++;
2839 APPEND_BLANK (result);
2840 string_append (result, "bool");
4d17a06f 2841 tk = tk_bool;
6599da04
JM
2842 break;
2843 case 'c':
2844 (*mangled)++;
2845 APPEND_BLANK (result);
2846 string_append (result, "char");
4d17a06f 2847 tk = tk_char;
6599da04
JM
2848 break;
2849 case 'w':
2850 (*mangled)++;
2851 APPEND_BLANK (result);
2852 string_append (result, "wchar_t");
4d17a06f 2853 tk = tk_char;
6599da04
JM
2854 break;
2855 case 'r':
2856 (*mangled)++;
2857 APPEND_BLANK (result);
2858 string_append (result, "long double");
4d17a06f 2859 tk = tk_real;
6599da04
JM
2860 break;
2861 case 'd':
2862 (*mangled)++;
2863 APPEND_BLANK (result);
2864 string_append (result, "double");
4d17a06f 2865 tk = tk_real;
6599da04
JM
2866 break;
2867 case 'f':
2868 (*mangled)++;
2869 APPEND_BLANK (result);
2870 string_append (result, "float");
4d17a06f 2871 tk = tk_real;
6599da04
JM
2872 break;
2873 case 'G':
2874 (*mangled)++;
2875 if (!isdigit (**mangled))
2876 {
2877 success = 0;
2878 break;
2879 }
2880 /* fall through */
2881 /* An explicit type, such as "6mytype" or "7integer" */
2882 case '0':
2883 case '1':
2884 case '2':
2885 case '3':
2886 case '4':
2887 case '5':
2888 case '6':
2889 case '7':
2890 case '8':
2891 case '9':
5e5199e8
AM
2892 {
2893 int bindex = register_Btype (work);
2894 string btype;
2895 string_init (&btype);
2896 if (demangle_class_name (work, mangled, &btype)) {
2897 remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
2898 APPEND_BLANK (result);
2899 string_appends (result, &btype);
2900 }
2901 else
2902 success = 0;
2903 string_delete (&btype);
2904 break;
6599da04 2905 }
6599da04 2906 case 't':
5e5199e8 2907 {
9923cc56 2908 success = demangle_template (work, mangled, &btype, 0, 1, 1);
5e5199e8
AM
2909 string_appends (result, &btype);
2910 break;
2911 }
6599da04
JM
2912 default:
2913 success = 0;
2914 break;
2915 }
2916
4d17a06f 2917 return success ? ((int) tk) : 0;
6599da04
JM
2918}
2919
9923cc56
MM
2920/* Demangle the next argument, given by MANGLED into RESULT, which
2921 *should be an uninitialized* string. It will be initialized here,
2922 and free'd should anything go wrong. */
6599da04
JM
2923
2924static int
2925do_arg (work, mangled, result)
2926 struct work_stuff *work;
2927 const char **mangled;
2928 string *result;
2929{
9923cc56
MM
2930 /* Remember where we started so that we can record the type, for
2931 non-squangling type remembering. */
6599da04
JM
2932 const char *start = *mangled;
2933
9923cc56
MM
2934 string_init (result);
2935
2936 if (work->nrepeats > 0)
6599da04 2937 {
9923cc56
MM
2938 --work->nrepeats;
2939
2940 if (work->previous_argument == 0)
2941 return 0;
2942
2943 /* We want to reissue the previous type in this argument list. */
2944 string_appends (result, work->previous_argument);
2945 return 1;
6599da04 2946 }
9923cc56
MM
2947
2948 if (**mangled == 'n')
2949 {
2950 /* A squangling-style repeat. */
2951 (*mangled)++;
2952 work->nrepeats = consume_count(mangled);
2953
2954 if (work->nrepeats == 0)
2955 /* This was not a repeat count after all. */
2956 return 0;
2957
2958 if (work->nrepeats > 9)
2959 {
2960 if (**mangled != '_')
2961 /* The repeat count should be followed by an '_' in this
2962 case. */
2963 return 0;
2964 else
2965 (*mangled)++;
2966 }
2967
2968 /* Now, the repeat is all set up. */
2969 return do_arg (work, mangled, result);
2970 }
2971
2972 /* Save the result in WORK->previous_argument so that we can find it
2973 if it's repeated. Note that saving START is not good enough: we
2974 do not want to add additional types to the back-referenceable
2975 type vector when processing a repeated type. */
2976 if (work->previous_argument)
2977 string_clear (work->previous_argument);
6599da04
JM
2978 else
2979 {
9923cc56
MM
2980 work->previous_argument = (string*) xmalloc (sizeof (string));
2981 string_init (work->previous_argument);
6599da04 2982 }
9923cc56
MM
2983
2984 if (!do_type (work, mangled, work->previous_argument))
2985 return 0;
2986
2987 string_appends (result, work->previous_argument);
2988
2989 remember_type (work, start, *mangled - start);
2990 return 1;
6599da04
JM
2991}
2992
2993static void
2994remember_type (work, start, len)
2995 struct work_stuff *work;
2996 const char *start;
2997 int len;
2998{
2999 char *tem;
3000
9923cc56
MM
3001 if (work->forgetting_types)
3002 return;
3003
6599da04
JM
3004 if (work -> ntypes >= work -> typevec_size)
3005 {
3006 if (work -> typevec_size == 0)
3007 {
3008 work -> typevec_size = 3;
3009 work -> typevec
3010 = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
3011 }
3012 else
3013 {
3014 work -> typevec_size *= 2;
3015 work -> typevec
3016 = (char **) xrealloc ((char *)work -> typevec,
3017 sizeof (char *) * work -> typevec_size);
3018 }
3019 }
3020 tem = xmalloc (len + 1);
3021 memcpy (tem, start, len);
3022 tem[len] = '\0';
3023 work -> typevec[work -> ntypes++] = tem;
3024}
3025
5e5199e8
AM
3026
3027/* Remember a K type class qualifier. */
3028static void
3029remember_Ktype (work, start, len)
3030 struct work_stuff *work;
3031 const char *start;
3032 int len;
3033{
3034 char *tem;
3035
3036 if (work -> numk >= work -> ksize)
3037 {
3038 if (work -> ksize == 0)
3039 {
3040 work -> ksize = 5;
3041 work -> ktypevec
3042 = (char **) xmalloc (sizeof (char *) * work -> ksize);
3043 }
3044 else
3045 {
3046 work -> ksize *= 2;
3047 work -> ktypevec
3048 = (char **) xrealloc ((char *)work -> ktypevec,
3049 sizeof (char *) * work -> ksize);
3050 }
3051 }
3052 tem = xmalloc (len + 1);
3053 memcpy (tem, start, len);
3054 tem[len] = '\0';
3055 work -> ktypevec[work -> numk++] = tem;
3056}
3057
3058/* Register a B code, and get an index for it. B codes are registered
3059 as they are seen, rather than as they are completed, so map<temp<char> >
3060 registers map<temp<char> > as B0, and temp<char> as B1 */
3061
3062static int
3063register_Btype (work)
3064 struct work_stuff *work;
3065{
3066 int ret;
3067
3068 if (work -> numb >= work -> bsize)
3069 {
3070 if (work -> bsize == 0)
3071 {
3072 work -> bsize = 5;
3073 work -> btypevec
3074 = (char **) xmalloc (sizeof (char *) * work -> bsize);
3075 }
3076 else
3077 {
3078 work -> bsize *= 2;
3079 work -> btypevec
3080 = (char **) xrealloc ((char *)work -> btypevec,
3081 sizeof (char *) * work -> bsize);
3082 }
3083 }
3084 ret = work -> numb++;
3085 work -> btypevec[ret] = NULL;
3086 return(ret);
3087}
3088
3089/* Store a value into a previously registered B code type. */
3090
3091static void
3092remember_Btype (work, start, len, index)
3093 struct work_stuff *work;
3094 const char *start;
3095 int len, index;
3096{
3097 char *tem;
3098
3099 tem = xmalloc (len + 1);
3100 memcpy (tem, start, len);
3101 tem[len] = '\0';
3102 work -> btypevec[index] = tem;
3103}
3104
3105/* Lose all the info related to B and K type codes. */
3106static void
3107forget_B_and_K_types (work)
3108 struct work_stuff *work;
3109{
3110 int i;
3111
3112 while (work -> numk > 0)
3113 {
3114 i = --(work -> numk);
3115 if (work -> ktypevec[i] != NULL)
3116 {
3117 free (work -> ktypevec[i]);
3118 work -> ktypevec[i] = NULL;
3119 }
3120 }
3121
3122 while (work -> numb > 0)
3123 {
3124 i = --(work -> numb);
3125 if (work -> btypevec[i] != NULL)
3126 {
3127 free (work -> btypevec[i]);
3128 work -> btypevec[i] = NULL;
3129 }
3130 }
3131}
6599da04
JM
3132/* Forget the remembered types, but not the type vector itself. */
3133
3134static void
3135forget_types (work)
3136 struct work_stuff *work;
3137{
3138 int i;
3139
3140 while (work -> ntypes > 0)
3141 {
3142 i = --(work -> ntypes);
3143 if (work -> typevec[i] != NULL)
3144 {
3145 free (work -> typevec[i]);
3146 work -> typevec[i] = NULL;
3147 }
3148 }
3149}
3150
3151/* Process the argument list part of the signature, after any class spec
3152 has been consumed, as well as the first 'F' character (if any). For
3153 example:
3154
3155 "__als__3fooRT0" => process "RT0"
3156 "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
3157
3158 DECLP must be already initialised, usually non-empty. It won't be freed
3159 on failure.
3160
3161 Note that g++ differs significantly from ARM and lucid style mangling
3162 with regards to references to previously seen types. For example, given
3163 the source fragment:
3164
3165 class foo {
3166 public:
3167 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
3168 };
3169
3170 foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3171 void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
3172
3173 g++ produces the names:
3174
3175 __3fooiRT0iT2iT2
3176 foo__FiR3fooiT1iT1
3177
3178 while lcc (and presumably other ARM style compilers as well) produces:
3179
3180 foo__FiR3fooT1T2T1T2
3181 __ct__3fooFiR3fooT1T2T1T2
3182
9923cc56
MM
3183 Note that g++ bases its type numbers starting at zero and counts all
3184 previously seen types, while lucid/ARM bases its type numbers starting
6599da04
JM
3185 at one and only considers types after it has seen the 'F' character
3186 indicating the start of the function args. For lucid/ARM style, we
3187 account for this difference by discarding any previously seen types when
3188 we see the 'F' character, and subtracting one from the type number
3189 reference.
3190
3191 */
3192
3193static int
3194demangle_args (work, mangled, declp)
3195 struct work_stuff *work;
3196 const char **mangled;
3197 string *declp;
3198{
3199 string arg;
3200 int need_comma = 0;
3201 int r;
3202 int t;
3203 const char *tem;
3204 char temptype;
3205
3206 if (PRINT_ARG_TYPES)
3207 {
3208 string_append (declp, "(");
3209 if (**mangled == '\0')
3210 {
3211 string_append (declp, "void");
3212 }
3213 }
3214
9923cc56
MM
3215 while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
3216 || work->nrepeats > 0)
6599da04
JM
3217 {
3218 if ((**mangled == 'N') || (**mangled == 'T'))
3219 {
3220 temptype = *(*mangled)++;
3221
3222 if (temptype == 'N')
3223 {
3224 if (!get_count (mangled, &r))
3225 {
3226 return (0);
3227 }
3228 }
3229 else
3230 {
3231 r = 1;
3232 }
3233 if (ARM_DEMANGLING && work -> ntypes >= 10)
3234 {
3235 /* If we have 10 or more types we might have more than a 1 digit
3236 index so we'll have to consume the whole count here. This
3237 will lose if the next thing is a type name preceded by a
3238 count but it's impossible to demangle that case properly
3239 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
3240 Pc, ...)" or "(..., type12, char *, ...)" */
3241 if ((t = consume_count(mangled)) == 0)
3242 {
3243 return (0);
3244 }
3245 }
3246 else
3247 {
3248 if (!get_count (mangled, &t))
3249 {
3250 return (0);
3251 }
3252 }
3253 if (LUCID_DEMANGLING || ARM_DEMANGLING)
3254 {
3255 t--;
3256 }
3257 /* Validate the type index. Protect against illegal indices from
3258 malformed type strings. */
3259 if ((t < 0) || (t >= work -> ntypes))
3260 {
3261 return (0);
3262 }
9923cc56 3263 while (work->nrepeats > 0 || --r >= 0)
6599da04
JM
3264 {
3265 tem = work -> typevec[t];
3266 if (need_comma && PRINT_ARG_TYPES)
3267 {
3268 string_append (declp, ", ");
3269 }
3270 if (!do_arg (work, &tem, &arg))
3271 {
3272 return (0);
3273 }
3274 if (PRINT_ARG_TYPES)
3275 {
3276 string_appends (declp, &arg);
3277 }
3278 string_delete (&arg);
3279 need_comma = 1;
3280 }
3281 }
3282 else
3283 {
9923cc56
MM
3284 if (need_comma && PRINT_ARG_TYPES)
3285 string_append (declp, ", ");
6599da04 3286 if (!do_arg (work, mangled, &arg))
9923cc56 3287 return (0);
6599da04 3288 if (PRINT_ARG_TYPES)
9923cc56 3289 string_appends (declp, &arg);
6599da04
JM
3290 string_delete (&arg);
3291 need_comma = 1;
3292 }
3293 }
3294
3295 if (**mangled == 'e')
3296 {
3297 (*mangled)++;
3298 if (PRINT_ARG_TYPES)
3299 {
3300 if (need_comma)
3301 {
3302 string_append (declp, ",");
3303 }
3304 string_append (declp, "...");
3305 }
3306 }
3307
3308 if (PRINT_ARG_TYPES)
3309 {
3310 string_append (declp, ")");
3311 }
3312 return (1);
3313}
3314
9923cc56
MM
3315/* Like demangle_args, but for demangling the argument lists of function
3316 and method pointers or references, not top-level declarations. */
3317
d94f5c58 3318static int
9923cc56
MM
3319demangle_nested_args (work, mangled, declp)
3320 struct work_stuff *work;
3321 const char **mangled;
3322 string *declp;
3323{
3324 string* saved_previous_argument;
3325 int result;
3326 int saved_nrepeats;
3327
3328 /* The G++ name-mangling algorithm does not remember types on nested
3329 argument lists, unless -fsquangling is used, and in that case the
3330 type vector updated by remember_type is not used. So, we turn
3331 off remembering of types here. */
3332 ++work->forgetting_types;
3333
3334 /* For the repeat codes used with -fsquangling, we must keep track of
3335 the last argument. */
3336 saved_previous_argument = work->previous_argument;
3337 saved_nrepeats = work->nrepeats;
3338 work->previous_argument = 0;
3339 work->nrepeats = 0;
3340
3341 /* Actually demangle the arguments. */
3342 result = demangle_args (work, mangled, declp);
3343
3344 /* Restore the previous_argument field. */
3345 if (work->previous_argument)
3346 string_delete (work->previous_argument);
3347 work->previous_argument = saved_previous_argument;
3348 work->nrepeats = saved_nrepeats;
3349
3350 return result;
3351}
3352
6599da04
JM
3353static void
3354demangle_function_name (work, mangled, declp, scan)
3355 struct work_stuff *work;
3356 const char **mangled;
3357 string *declp;
3358 const char *scan;
3359{
9ee02b5c 3360 size_t i;
6599da04
JM
3361 string type;
3362 const char *tem;
3363
3364 string_appendn (declp, (*mangled), scan - (*mangled));
3365 string_need (declp, 1);
3366 *(declp -> p) = '\0';
3367
3368 /* Consume the function name, including the "__" separating the name
3369 from the signature. We are guaranteed that SCAN points to the
3370 separator. */
3371
3372 (*mangled) = scan + 2;
3373
3374 if (LUCID_DEMANGLING || ARM_DEMANGLING)
3375 {
3376
3377 /* See if we have an ARM style constructor or destructor operator.
3378 If so, then just record it, clear the decl, and return.
3379 We can't build the actual constructor/destructor decl until later,
3380 when we recover the class name from the signature. */
3381
3382 if (strcmp (declp -> b, "__ct") == 0)
3383 {
3384 work -> constructor += 1;
3385 string_clear (declp);
3386 return;
3387 }
3388 else if (strcmp (declp -> b, "__dt") == 0)
3389 {
3390 work -> destructor += 1;
3391 string_clear (declp);
3392 return;
3393 }
3394 }
3395
3396 if (declp->p - declp->b >= 3
3397 && declp->b[0] == 'o'
3398 && declp->b[1] == 'p'
3399 && strchr (cplus_markers, declp->b[2]) != NULL)
3400 {
3401 /* see if it's an assignment expression */
3402 if (declp->p - declp->b >= 10 /* op$assign_ */
3403 && memcmp (declp->b + 3, "assign_", 7) == 0)
3404 {
3405 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3406 {
9ee02b5c 3407 int len = declp->p - declp->b - 10;
6599da04
JM
3408 if (strlen (optable[i].in) == len
3409 && memcmp (optable[i].in, declp->b + 10, len) == 0)
3410 {
3411 string_clear (declp);
3412 string_append (declp, "operator");
3413 string_append (declp, optable[i].out);
3414 string_append (declp, "=");
3415 break;
3416 }
3417 }
3418 }
3419 else
3420 {
3421 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3422 {
3423 int len = declp->p - declp->b - 3;
3424 if (strlen (optable[i].in) == len
3425 && memcmp (optable[i].in, declp->b + 3, len) == 0)
3426 {
3427 string_clear (declp);
3428 string_append (declp, "operator");
3429 string_append (declp, optable[i].out);
3430 break;
3431 }
3432 }
3433 }
3434 }
3435 else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
3436 && strchr (cplus_markers, declp->b[4]) != NULL)
3437 {
3438 /* type conversion operator */
3439 tem = declp->b + 5;
3440 if (do_type (work, &tem, &type))
3441 {
3442 string_clear (declp);
3443 string_append (declp, "operator ");
3444 string_appends (declp, &type);
3445 string_delete (&type);
3446 }
3447 }
3448 else if (declp->b[0] == '_' && declp->b[1] == '_'
3449 && declp->b[2] == 'o' && declp->b[3] == 'p')
3450 {
3451 /* ANSI. */
3452 /* type conversion operator. */
3453 tem = declp->b + 4;
3454 if (do_type (work, &tem, &type))
3455 {
3456 string_clear (declp);
3457 string_append (declp, "operator ");
3458 string_appends (declp, &type);
3459 string_delete (&type);
3460 }
3461 }
3462 else if (declp->b[0] == '_' && declp->b[1] == '_'
3463 && declp->b[2] >= 'a' && declp->b[2] <= 'z'
3464 && declp->b[3] >= 'a' && declp->b[3] <= 'z')
3465 {
3466 if (declp->b[4] == '\0')
3467 {
3468 /* Operator. */
3469 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3470 {
3471 if (strlen (optable[i].in) == 2
3472 && memcmp (optable[i].in, declp->b + 2, 2) == 0)
3473 {
3474 string_clear (declp);
3475 string_append (declp, "operator");
3476 string_append (declp, optable[i].out);
3477 break;
3478 }
3479 }
3480 }
3481 else
3482 {
3483 if (declp->b[2] == 'a' && declp->b[5] == '\0')
3484 {
3485 /* Assignment. */
3486 for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
3487 {
3488 if (strlen (optable[i].in) == 3
3489 && memcmp (optable[i].in, declp->b + 2, 3) == 0)
3490 {
3491 string_clear (declp);
3492 string_append (declp, "operator");
3493 string_append (declp, optable[i].out);
3494 break;
3495 }
3496 }
3497 }
3498 }
3499 }
3500}
3501
3502/* a mini string-handling package */
3503
3504static void
3505string_need (s, n)
3506 string *s;
3507 int n;
3508{
3509 int tem;
3510
3511 if (s->b == NULL)
3512 {
3513 if (n < 32)
3514 {
3515 n = 32;
3516 }
3517 s->p = s->b = xmalloc (n);
3518 s->e = s->b + n;
3519 }
3520 else if (s->e - s->p < n)
3521 {
3522 tem = s->p - s->b;
3523 n += tem;
3524 n *= 2;
3525 s->b = xrealloc (s->b, n);
3526 s->p = s->b + tem;
3527 s->e = s->b + n;
3528 }
3529}
3530
3531static void
3532string_delete (s)
3533 string *s;
3534{
3535 if (s->b != NULL)
3536 {
3537 free (s->b);
3538 s->b = s->e = s->p = NULL;
3539 }
3540}
3541
3542static void
3543string_init (s)
3544 string *s;
3545{
3546 s->b = s->p = s->e = NULL;
3547}
3548
3549static void
3550string_clear (s)
3551 string *s;
3552{
3553 s->p = s->b;
3554}
3555
3556#if 0
3557
3558static int
3559string_empty (s)
3560 string *s;
3561{
3562 return (s->b == s->p);
3563}
3564
3565#endif
3566
3567static void
3568string_append (p, s)
3569 string *p;
3570 const char *s;
3571{
3572 int n;
3573 if (s == NULL || *s == '\0')
3574 return;
3575 n = strlen (s);
3576 string_need (p, n);
3577 memcpy (p->p, s, n);
3578 p->p += n;
3579}
3580
3581static void
3582string_appends (p, s)
3583 string *p, *s;
3584{
3585 int n;
3586
3587 if (s->b != s->p)
3588 {
3589 n = s->p - s->b;
3590 string_need (p, n);
3591 memcpy (p->p, s->b, n);
3592 p->p += n;
3593 }
3594}
3595
3596static void
3597string_appendn (p, s, n)
3598 string *p;
3599 const char *s;
3600 int n;
3601{
3602 if (n != 0)
3603 {
3604 string_need (p, n);
3605 memcpy (p->p, s, n);
3606 p->p += n;
3607 }
3608}
3609
3610static void
3611string_prepend (p, s)
3612 string *p;
3613 const char *s;
3614{
3615 if (s != NULL && *s != '\0')
3616 {
3617 string_prependn (p, s, strlen (s));
3618 }
3619}
3620
3621static void
3622string_prepends (p, s)
3623 string *p, *s;
3624{
3625 if (s->b != s->p)
3626 {
3627 string_prependn (p, s->b, s->p - s->b);
3628 }
3629}
3630
3631static void
3632string_prependn (p, s, n)
3633 string *p;
3634 const char *s;
3635 int n;
3636{
3637 char *q;
3638
3639 if (n != 0)
3640 {
3641 string_need (p, n);
3642 for (q = p->p - 1; q >= p->b; q--)
3643 {
3644 q[n] = q[0];
3645 }
3646 memcpy (p->b, s, n);
3647 p->p += n;
3648 }
3649}
3650
3651/* To generate a standalone demangler program for testing purposes,
3652 just compile and link this file with -DMAIN and libiberty.a. When
3653 run, it demangles each command line arg, or each stdin string, and
3654 prints the result on stdout. */
3655
3656#ifdef MAIN
3657
3658#include "getopt.h"
3659
3660static char *program_name;
3661static char *program_version = VERSION;
3662static int flags = DMGL_PARAMS | DMGL_ANSI;
3663
3664static void demangle_it PARAMS ((char *));
3665static void usage PARAMS ((FILE *, int));
3666static void fatal PARAMS ((char *));
3667
3668static void
3669demangle_it (mangled_name)
3670 char *mangled_name;
3671{
3672 char *result;
3673
3674 result = cplus_demangle (mangled_name, flags);
3675 if (result == NULL)
3676 {
3677 printf ("%s\n", mangled_name);
3678 }
3679 else
3680 {
3681 printf ("%s\n", result);
3682 free (result);
3683 }
3684}
3685
3686static void
3687usage (stream, status)
3688 FILE *stream;
3689 int status;
3690{
3691 fprintf (stream, "\
3692Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
3693 [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
3694 [--help] [--version] [arg...]\n",
3695 program_name);
3696 exit (status);
3697}
3698
911c3b7d 3699#define MBUF_SIZE 32767
6599da04
JM
3700char mbuffer[MBUF_SIZE];
3701
3702/* Defined in the automatically-generated underscore.c. */
3703extern int prepends_underscore;
3704
3705int strip_underscore = 0;
3706
3707static struct option long_options[] = {
3708 {"strip-underscores", no_argument, 0, '_'},
3709 {"format", required_argument, 0, 's'},
3710 {"help", no_argument, 0, 'h'},
6599da04
JM
3711 {"no-strip-underscores", no_argument, 0, 'n'},
3712 {"version", no_argument, 0, 'v'},
3713 {0, no_argument, 0, 0}
3714};
3715
9ee02b5c
JL
3716/* More 'friendly' abort that prints the line and file.
3717 config.h can #define abort fancy_abort if you like that sort of thing. */
3718
3719void
3720fancy_abort ()
3721{
3722 fatal ("Internal gcc abort.");
3723}
3724
6599da04
JM
3725int
3726main (argc, argv)
3727 int argc;
3728 char **argv;
3729{
3730 char *result;
3731 int c;
3732
3733 program_name = argv[0];
3734
3735 strip_underscore = prepends_underscore;
3736
3737 while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
3738 {
3739 switch (c)
3740 {
3741 case '?':
3742 usage (stderr, 1);
3743 break;
3744 case 'h':
3745 usage (stdout, 0);
3746 case 'n':
3747 strip_underscore = 0;
3748 break;
3749 case 'v':
3750 printf ("GNU %s version %s\n", program_name, program_version);
3751 exit (0);
3752 case '_':
3753 strip_underscore = 1;
3754 break;
6599da04
JM
3755 case 's':
3756 if (strcmp (optarg, "gnu") == 0)
3757 {
3758 current_demangling_style = gnu_demangling;
3759 }
3760 else if (strcmp (optarg, "lucid") == 0)
3761 {
3762 current_demangling_style = lucid_demangling;
3763 }
3764 else if (strcmp (optarg, "arm") == 0)
3765 {
3766 current_demangling_style = arm_demangling;
3767 }
3768 else
3769 {
3770 fprintf (stderr, "%s: unknown demangling style `%s'\n",
3771 program_name, optarg);
3772 exit (1);
3773 }
3774 break;
3775 }
3776 }
3777
3778 if (optind < argc)
3779 {
3780 for ( ; optind < argc; optind++)
3781 {
3782 demangle_it (argv[optind]);
3783 }
3784 }
3785 else
3786 {
3787 for (;;)
3788 {
3789 int i = 0;
3790 c = getchar ();
3791 /* Try to read a label. */
3792 while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
3793 {
3794 if (i >= MBUF_SIZE-1)
3795 break;
3796 mbuffer[i++] = c;
3797 c = getchar ();
3798 }
3799 if (i > 0)
3800 {
3801 int skip_first = 0;
3802
3803 if (mbuffer[0] == '.')
3804 ++skip_first;
3805 if (strip_underscore && mbuffer[skip_first] == '_')
3806 ++skip_first;
3807
3808 if (skip_first > i)
3809 skip_first = i;
3810
3811 mbuffer[i] = 0;
3812
3813 result = cplus_demangle (mbuffer + skip_first, flags);
3814 if (result)
3815 {
3816 if (mbuffer[0] == '.')
3817 putc ('.', stdout);
3818 fputs (result, stdout);
3819 free (result);
3820 }
3821 else
3822 fputs (mbuffer, stdout);
3823
3824 fflush (stdout);
3825 }
3826 if (c == EOF)
3827 break;
3828 putchar (c);
3829 }
3830 }
3831
3832 exit (0);
3833}
3834
3835static void
3836fatal (str)
3837 char *str;
3838{
3839 fprintf (stderr, "%s: %s\n", program_name, str);
3840 exit (1);
3841}
3842
6599da04
JM
3843char *
3844xmalloc (size)
3845 unsigned size;
3846{
3847 register char *value = (char *) malloc (size);
3848 if (value == 0)
3849 fatal ("virtual memory exhausted");
3850 return value;
3851}
3852
3853char *
3854xrealloc (ptr, size)
3855 char *ptr;
3856 unsigned size;
3857{
3858 register char *value = (char *) realloc (ptr, size);
3859 if (value == 0)
3860 fatal ("virtual memory exhausted");
3861 return value;
3862}
3863#endif /* main */