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