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