xref: /dflybsd-src/contrib/binutils-2.27/libiberty/cplus-dem.c (revision e656dc90e3d65d744d534af2f5ea88cf8101ebcf)
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 = &param;
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