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