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