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