1169695Skan/* Demangler for GNU C++
2169695Skan   Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
3169695Skan   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4169695Skan   Written by James Clark (jjc@jclark.uucp)
5169695Skan   Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
6169695Skan   Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
7169695Skan
8169695SkanThis file is part of the libiberty library.
9169695SkanLibiberty is free software; you can redistribute it and/or
10169695Skanmodify it under the terms of the GNU Library General Public
11169695SkanLicense as published by the Free Software Foundation; either
12169695Skanversion 2 of the License, or (at your option) any later version.
13169695Skan
14169695SkanIn addition to the permissions in the GNU Library General Public
15169695SkanLicense, the Free Software Foundation gives you unlimited permission
16169695Skanto link the compiled version of this file into combinations with other
17169695Skanprograms, and to distribute those combinations without any restriction
18169695Skancoming from the use of this file.  (The Library Public License
19169695Skanrestrictions do apply in other respects; for example, they cover
20169695Skanmodification of the file, and distribution when not linked into a
21169695Skancombined executable.)
22169695Skan
23169695SkanLibiberty is distributed in the hope that it will be useful,
24169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of
25169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26169695SkanLibrary General Public License for more details.
27169695Skan
28169695SkanYou should have received a copy of the GNU Library General Public
29169695SkanLicense along with libiberty; see the file COPYING.LIB.  If
30169695Skannot, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
31169695SkanBoston, MA 02110-1301, USA.  */
32169695Skan
33169695Skan/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
34169695Skan
35169695Skan   This file imports xmalloc and xrealloc, which are like malloc and
36169695Skan   realloc except that they generate a fatal error if there is no
37169695Skan   available memory.  */
38169695Skan
39169695Skan/* This file lives in both GCC and libiberty.  When making changes, please
40169695Skan   try not to break either.  */
41169695Skan
42169695Skan#ifdef HAVE_CONFIG_H
43169695Skan#include "config.h"
44169695Skan#endif
45169695Skan
46169695Skan#include "safe-ctype.h"
47169695Skan
48169695Skan#include <sys/types.h>
49169695Skan#include <string.h>
50169695Skan#include <stdio.h>
51169695Skan
52169695Skan#ifdef HAVE_STDLIB_H
53169695Skan#include <stdlib.h>
54169695Skan#else
55169695Skanchar * malloc ();
56169695Skanchar * realloc ();
57169695Skan#endif
58169695Skan
59169695Skan#include <demangle.h>
60169695Skan#undef CURRENT_DEMANGLING_STYLE
61169695Skan#define CURRENT_DEMANGLING_STYLE work->options
62169695Skan
63169695Skan#include "libiberty.h"
64169695Skan
65169695Skanstatic char *ada_demangle (const char *, int);
66169695Skan
67169695Skan#define min(X,Y) (((X) < (Y)) ? (X) : (Y))
68169695Skan
69169695Skan/* A value at least one greater than the maximum number of characters
70169695Skan   that will be output when using the `%d' format with `printf'.  */
71169695Skan#define INTBUF_SIZE 32
72169695Skan
73169695Skanextern void fancy_abort (void) ATTRIBUTE_NORETURN;
74169695Skan
75169695Skan/* In order to allow a single demangler executable to demangle strings
76169695Skan   using various common values of CPLUS_MARKER, as well as any specific
77169695Skan   one set at compile time, we maintain a string containing all the
78169695Skan   commonly used ones, and check to see if the marker we are looking for
79169695Skan   is in that string.  CPLUS_MARKER is usually '$' on systems where the
80169695Skan   assembler can deal with that.  Where the assembler can't, it's usually
81169695Skan   '.' (but on many systems '.' is used for other things).  We put the
82169695Skan   current defined CPLUS_MARKER first (which defaults to '$'), followed
83169695Skan   by the next most common value, followed by an explicit '$' in case
84169695Skan   the value of CPLUS_MARKER is not '$'.
85169695Skan
86169695Skan   We could avoid this if we could just get g++ to tell us what the actual
87169695Skan   cplus marker character is as part of the debug information, perhaps by
88169695Skan   ensuring that it is the character that terminates the gcc<n>_compiled
89169695Skan   marker symbol (FIXME).  */
90169695Skan
91169695Skan#if !defined (CPLUS_MARKER)
92169695Skan#define CPLUS_MARKER '$'
93169695Skan#endif
94169695Skan
95169695Skanenum demangling_styles current_demangling_style = auto_demangling;
96169695Skan
97169695Skanstatic char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
98169695Skan
99169695Skanstatic char char_str[2] = { '\000', '\000' };
100169695Skan
101169695Skanvoid
102169695Skanset_cplus_marker_for_demangling (int ch)
103169695Skan{
104169695Skan  cplus_markers[0] = ch;
105169695Skan}
106169695Skan
107169695Skantypedef struct string		/* Beware: these aren't required to be */
108169695Skan{				/*  '\0' terminated.  */
109169695Skan  char *b;			/* pointer to start of string */
110169695Skan  char *p;			/* pointer after last character */
111169695Skan  char *e;			/* pointer after end of allocated space */
112169695Skan} string;
113169695Skan
114169695Skan/* Stuff that is shared between sub-routines.
115169695Skan   Using a shared structure allows cplus_demangle to be reentrant.  */
116169695Skan
117169695Skanstruct work_stuff
118169695Skan{
119169695Skan  int options;
120169695Skan  char **typevec;
121169695Skan  char **ktypevec;
122169695Skan  char **btypevec;
123169695Skan  int numk;
124169695Skan  int numb;
125169695Skan  int ksize;
126169695Skan  int bsize;
127169695Skan  int ntypes;
128169695Skan  int typevec_size;
129169695Skan  int constructor;
130169695Skan  int destructor;
131169695Skan  int static_type;	/* A static member function */
132169695Skan  int temp_start;       /* index in demangled to start of template args */
133169695Skan  int type_quals;       /* The type qualifiers.  */
134169695Skan  int dllimported;	/* Symbol imported from a PE DLL */
135169695Skan  char **tmpl_argvec;   /* Template function arguments. */
136169695Skan  int ntmpl_args;       /* The number of template function arguments. */
137169695Skan  int forgetting_types; /* Nonzero if we are not remembering the types
138169695Skan			   we see.  */
139169695Skan  string* previous_argument; /* The last function argument demangled.  */
140169695Skan  int nrepeats;         /* The number of times to repeat the previous
141169695Skan			   argument.  */
142169695Skan};
143169695Skan
144169695Skan#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
145169695Skan#define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
146169695Skan
147169695Skanstatic const struct optable
148169695Skan{
149169695Skan  const char *const in;
150169695Skan  const char *const out;
151169695Skan  const int flags;
152169695Skan} optable[] = {
153169695Skan  {"nw",	  " new",	DMGL_ANSI},	/* new (1.92,	 ansi) */
154169695Skan  {"dl",	  " delete",	DMGL_ANSI},	/* new (1.92,	 ansi) */
155169695Skan  {"new",	  " new",	0},		/* old (1.91,	 and 1.x) */
156169695Skan  {"delete",	  " delete",	0},		/* old (1.91,	 and 1.x) */
157169695Skan  {"vn",	  " new []",	DMGL_ANSI},	/* GNU, pending ansi */
158169695Skan  {"vd",	  " delete []",	DMGL_ANSI},	/* GNU, pending ansi */
159169695Skan  {"as",	  "=",		DMGL_ANSI},	/* ansi */
160169695Skan  {"ne",	  "!=",		DMGL_ANSI},	/* old, ansi */
161169695Skan  {"eq",	  "==",		DMGL_ANSI},	/* old,	ansi */
162169695Skan  {"ge",	  ">=",		DMGL_ANSI},	/* old,	ansi */
163169695Skan  {"gt",	  ">",		DMGL_ANSI},	/* old,	ansi */
164169695Skan  {"le",	  "<=",		DMGL_ANSI},	/* old,	ansi */
165169695Skan  {"lt",	  "<",		DMGL_ANSI},	/* old,	ansi */
166169695Skan  {"plus",	  "+",		0},		/* old */
167169695Skan  {"pl",	  "+",		DMGL_ANSI},	/* ansi */
168169695Skan  {"apl",	  "+=",		DMGL_ANSI},	/* ansi */
169169695Skan  {"minus",	  "-",		0},		/* old */
170169695Skan  {"mi",	  "-",		DMGL_ANSI},	/* ansi */
171169695Skan  {"ami",	  "-=",		DMGL_ANSI},	/* ansi */
172169695Skan  {"mult",	  "*",		0},		/* old */
173169695Skan  {"ml",	  "*",		DMGL_ANSI},	/* ansi */
174169695Skan  {"amu",	  "*=",		DMGL_ANSI},	/* ansi (ARM/Lucid) */
175169695Skan  {"aml",	  "*=",		DMGL_ANSI},	/* ansi (GNU/g++) */
176169695Skan  {"convert",	  "+",		0},		/* old (unary +) */
177169695Skan  {"negate",	  "-",		0},		/* old (unary -) */
178169695Skan  {"trunc_mod",	  "%",		0},		/* old */
179169695Skan  {"md",	  "%",		DMGL_ANSI},	/* ansi */
180169695Skan  {"amd",	  "%=",		DMGL_ANSI},	/* ansi */
181169695Skan  {"trunc_div",	  "/",		0},		/* old */
182169695Skan  {"dv",	  "/",		DMGL_ANSI},	/* ansi */
183169695Skan  {"adv",	  "/=",		DMGL_ANSI},	/* ansi */
184169695Skan  {"truth_andif", "&&",		0},		/* old */
185169695Skan  {"aa",	  "&&",		DMGL_ANSI},	/* ansi */
186169695Skan  {"truth_orif",  "||",		0},		/* old */
187169695Skan  {"oo",	  "||",		DMGL_ANSI},	/* ansi */
188169695Skan  {"truth_not",	  "!",		0},		/* old */
189169695Skan  {"nt",	  "!",		DMGL_ANSI},	/* ansi */
190169695Skan  {"postincrement","++",	0},		/* old */
191169695Skan  {"pp",	  "++",		DMGL_ANSI},	/* ansi */
192169695Skan  {"postdecrement","--",	0},		/* old */
193169695Skan  {"mm",	  "--",		DMGL_ANSI},	/* ansi */
194169695Skan  {"bit_ior",	  "|",		0},		/* old */
195169695Skan  {"or",	  "|",		DMGL_ANSI},	/* ansi */
196169695Skan  {"aor",	  "|=",		DMGL_ANSI},	/* ansi */
197169695Skan  {"bit_xor",	  "^",		0},		/* old */
198169695Skan  {"er",	  "^",		DMGL_ANSI},	/* ansi */
199169695Skan  {"aer",	  "^=",		DMGL_ANSI},	/* ansi */
200169695Skan  {"bit_and",	  "&",		0},		/* old */
201169695Skan  {"ad",	  "&",		DMGL_ANSI},	/* ansi */
202169695Skan  {"aad",	  "&=",		DMGL_ANSI},	/* ansi */
203169695Skan  {"bit_not",	  "~",		0},		/* old */
204169695Skan  {"co",	  "~",		DMGL_ANSI},	/* ansi */
205169695Skan  {"call",	  "()",		0},		/* old */
206169695Skan  {"cl",	  "()",		DMGL_ANSI},	/* ansi */
207169695Skan  {"alshift",	  "<<",		0},		/* old */
208169695Skan  {"ls",	  "<<",		DMGL_ANSI},	/* ansi */
209169695Skan  {"als",	  "<<=",	DMGL_ANSI},	/* ansi */
210169695Skan  {"arshift",	  ">>",		0},		/* old */
211169695Skan  {"rs",	  ">>",		DMGL_ANSI},	/* ansi */
212169695Skan  {"ars",	  ">>=",	DMGL_ANSI},	/* ansi */
213169695Skan  {"component",	  "->",		0},		/* old */
214169695Skan  {"pt",	  "->",		DMGL_ANSI},	/* ansi; Lucid C++ form */
215169695Skan  {"rf",	  "->",		DMGL_ANSI},	/* ansi; ARM/GNU form */
216169695Skan  {"indirect",	  "*",		0},		/* old */
217169695Skan  {"method_call",  "->()",	0},		/* old */
218169695Skan  {"addr",	  "&",		0},		/* old (unary &) */
219169695Skan  {"array",	  "[]",		0},		/* old */
220169695Skan  {"vc",	  "[]",		DMGL_ANSI},	/* ansi */
221169695Skan  {"compound",	  ", ",		0},		/* old */
222169695Skan  {"cm",	  ", ",		DMGL_ANSI},	/* ansi */
223169695Skan  {"cond",	  "?:",		0},		/* old */
224169695Skan  {"cn",	  "?:",		DMGL_ANSI},	/* pseudo-ansi */
225169695Skan  {"max",	  ">?",		0},		/* old */
226169695Skan  {"mx",	  ">?",		DMGL_ANSI},	/* pseudo-ansi */
227169695Skan  {"min",	  "<?",		0},		/* old */
228169695Skan  {"mn",	  "<?",		DMGL_ANSI},	/* pseudo-ansi */
229169695Skan  {"nop",	  "",		0},		/* old (for operator=) */
230169695Skan  {"rm",	  "->*",	DMGL_ANSI},	/* ansi */
231169695Skan  {"sz",          "sizeof ",    DMGL_ANSI}      /* pseudo-ansi */
232169695Skan};
233169695Skan
234169695Skan/* These values are used to indicate the various type varieties.
235169695Skan   They are all non-zero so that they can be used as `success'
236169695Skan   values.  */
237169695Skantypedef enum type_kind_t
238169695Skan{
239169695Skan  tk_none,
240169695Skan  tk_pointer,
241169695Skan  tk_reference,
242169695Skan  tk_integral,
243169695Skan  tk_bool,
244169695Skan  tk_char,
245169695Skan  tk_real
246169695Skan} type_kind_t;
247169695Skan
248169695Skanconst struct demangler_engine libiberty_demanglers[] =
249169695Skan{
250169695Skan  {
251169695Skan    NO_DEMANGLING_STYLE_STRING,
252169695Skan    no_demangling,
253169695Skan    "Demangling disabled"
254169695Skan  }
255169695Skan  ,
256169695Skan  {
257169695Skan    AUTO_DEMANGLING_STYLE_STRING,
258169695Skan      auto_demangling,
259169695Skan      "Automatic selection based on executable"
260169695Skan  }
261169695Skan  ,
262169695Skan  {
263169695Skan    GNU_DEMANGLING_STYLE_STRING,
264169695Skan      gnu_demangling,
265169695Skan      "GNU (g++) style demangling"
266169695Skan  }
267169695Skan  ,
268169695Skan  {
269169695Skan    LUCID_DEMANGLING_STYLE_STRING,
270169695Skan      lucid_demangling,
271169695Skan      "Lucid (lcc) style demangling"
272169695Skan  }
273169695Skan  ,
274169695Skan  {
275169695Skan    ARM_DEMANGLING_STYLE_STRING,
276169695Skan      arm_demangling,
277169695Skan      "ARM style demangling"
278169695Skan  }
279169695Skan  ,
280169695Skan  {
281169695Skan    HP_DEMANGLING_STYLE_STRING,
282169695Skan      hp_demangling,
283169695Skan      "HP (aCC) style demangling"
284169695Skan  }
285169695Skan  ,
286169695Skan  {
287169695Skan    EDG_DEMANGLING_STYLE_STRING,
288169695Skan      edg_demangling,
289169695Skan      "EDG style demangling"
290169695Skan  }
291169695Skan  ,
292169695Skan  {
293169695Skan    GNU_V3_DEMANGLING_STYLE_STRING,
294169695Skan    gnu_v3_demangling,
295169695Skan    "GNU (g++) V3 ABI-style demangling"
296169695Skan  }
297169695Skan  ,
298169695Skan  {
299169695Skan    JAVA_DEMANGLING_STYLE_STRING,
300169695Skan    java_demangling,
301169695Skan    "Java style demangling"
302169695Skan  }
303169695Skan  ,
304169695Skan  {
305169695Skan    GNAT_DEMANGLING_STYLE_STRING,
306169695Skan    gnat_demangling,
307169695Skan    "GNAT style demangling"
308169695Skan  }
309169695Skan  ,
310169695Skan  {
311169695Skan    NULL, unknown_demangling, NULL
312169695Skan  }
313169695Skan};
314169695Skan
315169695Skan#define STRING_EMPTY(str)	((str) -> b == (str) -> p)
316169695Skan#define APPEND_BLANK(str)	{if (!STRING_EMPTY(str)) \
317169695Skan    string_append(str, " ");}
318169695Skan#define LEN_STRING(str)         ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
319169695Skan
320169695Skan/* The scope separator appropriate for the language being demangled.  */
321169695Skan
322169695Skan#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
323169695Skan
324169695Skan#define ARM_VTABLE_STRING "__vtbl__"	/* Lucid/ARM virtual table prefix */
325169695Skan#define ARM_VTABLE_STRLEN 8		/* strlen (ARM_VTABLE_STRING) */
326169695Skan
327169695Skan/* Prototypes for local functions */
328169695Skan
329169695Skanstatic void delete_work_stuff (struct work_stuff *);
330169695Skan
331169695Skanstatic void delete_non_B_K_work_stuff (struct work_stuff *);
332169695Skan
333169695Skanstatic char *mop_up (struct work_stuff *, string *, int);
334169695Skan
335169695Skanstatic void squangle_mop_up (struct work_stuff *);
336169695Skan
337169695Skanstatic void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *);
338169695Skan
339169695Skan#if 0
340169695Skanstatic int
341169695Skandemangle_method_args (struct work_stuff *, const char **, string *);
342169695Skan#endif
343169695Skan
344169695Skanstatic char *
345169695Skaninternal_cplus_demangle (struct work_stuff *, const char *);
346169695Skan
347169695Skanstatic int
348169695Skandemangle_template_template_parm (struct work_stuff *work,
349169695Skan                                 const char **, string *);
350169695Skan
351169695Skanstatic int
352169695Skandemangle_template (struct work_stuff *work, const char **, string *,
353169695Skan                   string *, int, int);
354169695Skan
355169695Skanstatic int
356169695Skanarm_pt (struct work_stuff *, const char *, int, const char **,
357169695Skan        const char **);
358169695Skan
359169695Skanstatic int
360169695Skandemangle_class_name (struct work_stuff *, const char **, string *);
361169695Skan
362169695Skanstatic int
363169695Skandemangle_qualified (struct work_stuff *, const char **, string *,
364169695Skan                    int, int);
365169695Skan
366169695Skanstatic int demangle_class (struct work_stuff *, const char **, string *);
367169695Skan
368169695Skanstatic int demangle_fund_type (struct work_stuff *, const char **, string *);
369169695Skan
370169695Skanstatic int demangle_signature (struct work_stuff *, const char **, string *);
371169695Skan
372169695Skanstatic int demangle_prefix (struct work_stuff *, const char **, string *);
373169695Skan
374169695Skanstatic int gnu_special (struct work_stuff *, const char **, string *);
375169695Skan
376169695Skanstatic int arm_special (const char **, string *);
377169695Skan
378169695Skanstatic void string_need (string *, int);
379169695Skan
380169695Skanstatic void string_delete (string *);
381169695Skan
382169695Skanstatic void
383169695Skanstring_init (string *);
384169695Skan
385169695Skanstatic void string_clear (string *);
386169695Skan
387169695Skan#if 0
388169695Skanstatic int string_empty (string *);
389169695Skan#endif
390169695Skan
391169695Skanstatic void string_append (string *, const char *);
392169695Skan
393169695Skanstatic void string_appends (string *, string *);
394169695Skan
395169695Skanstatic void string_appendn (string *, const char *, int);
396169695Skan
397169695Skanstatic void string_prepend (string *, const char *);
398169695Skan
399169695Skanstatic void string_prependn (string *, const char *, int);
400169695Skan
401169695Skanstatic void string_append_template_idx (string *, int);
402169695Skan
403169695Skanstatic int get_count (const char **, int *);
404169695Skan
405169695Skanstatic int consume_count (const char **);
406169695Skan
407169695Skanstatic int consume_count_with_underscores (const char**);
408169695Skan
409169695Skanstatic int demangle_args (struct work_stuff *, const char **, string *);
410169695Skan
411169695Skanstatic int demangle_nested_args (struct work_stuff*, const char**, string*);
412169695Skan
413169695Skanstatic int do_type (struct work_stuff *, const char **, string *);
414169695Skan
415169695Skanstatic int do_arg (struct work_stuff *, const char **, string *);
416169695Skan
417169695Skanstatic void
418169695Skandemangle_function_name (struct work_stuff *, const char **, string *,
419169695Skan                        const char *);
420169695Skan
421169695Skanstatic int
422169695Skaniterate_demangle_function (struct work_stuff *,
423169695Skan                           const char **, string *, const char *);
424169695Skan
425169695Skanstatic void remember_type (struct work_stuff *, const char *, int);
426169695Skan
427169695Skanstatic void remember_Btype (struct work_stuff *, const char *, int, int);
428169695Skan
429169695Skanstatic int register_Btype (struct work_stuff *);
430169695Skan
431169695Skanstatic void remember_Ktype (struct work_stuff *, const char *, int);
432169695Skan
433169695Skanstatic void forget_types (struct work_stuff *);
434169695Skan
435169695Skanstatic void forget_B_and_K_types (struct work_stuff *);
436169695Skan
437169695Skanstatic void string_prepends (string *, string *);
438169695Skan
439169695Skanstatic int
440169695Skandemangle_template_value_parm (struct work_stuff*, const char**,
441169695Skan                              string*, type_kind_t);
442169695Skan
443169695Skanstatic int
444169695Skando_hpacc_template_const_value (struct work_stuff *, const char **, string *);
445169695Skan
446169695Skanstatic int
447169695Skando_hpacc_template_literal (struct work_stuff *, const char **, string *);
448169695Skan
449169695Skanstatic int snarf_numeric_literal (const char **, string *);
450169695Skan
451169695Skan/* There is a TYPE_QUAL value for each type qualifier.  They can be
452169695Skan   combined by bitwise-or to form the complete set of qualifiers for a
453169695Skan   type.  */
454169695Skan
455169695Skan#define TYPE_UNQUALIFIED   0x0
456169695Skan#define TYPE_QUAL_CONST    0x1
457169695Skan#define TYPE_QUAL_VOLATILE 0x2
458169695Skan#define TYPE_QUAL_RESTRICT 0x4
459169695Skan
460169695Skanstatic int code_for_qualifier (int);
461169695Skan
462169695Skanstatic const char* qualifier_string (int);
463169695Skan
464169695Skanstatic const char* demangle_qualifier (int);
465169695Skan
466169695Skanstatic int demangle_expression (struct work_stuff *, const char **, string *,
467169695Skan                                type_kind_t);
468169695Skan
469169695Skanstatic int
470169695Skandemangle_integral_value (struct work_stuff *, const char **, string *);
471169695Skan
472169695Skanstatic int
473169695Skandemangle_real_value (struct work_stuff *, const char **, string *);
474169695Skan
475169695Skanstatic void
476169695Skandemangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
477169695Skan
478169695Skanstatic void
479169695Skanrecursively_demangle (struct work_stuff *, const char **, string *, int);
480169695Skan
481169695Skanstatic void grow_vect (char **, size_t *, size_t, int);
482169695Skan
483169695Skan/* Translate count to integer, consuming tokens in the process.
484169695Skan   Conversion terminates on the first non-digit character.
485169695Skan
486169695Skan   Trying to consume something that isn't a count results in no
487169695Skan   consumption of input and a return of -1.
488169695Skan
489169695Skan   Overflow consumes the rest of the digits, and returns -1.  */
490169695Skan
491169695Skanstatic int
492169695Skanconsume_count (const char **type)
493169695Skan{
494169695Skan  int count = 0;
495169695Skan
496169695Skan  if (! ISDIGIT ((unsigned char)**type))
497169695Skan    return -1;
498169695Skan
499169695Skan  while (ISDIGIT ((unsigned char)**type))
500169695Skan    {
501169695Skan      count *= 10;
502169695Skan
503169695Skan      /* Check for overflow.
504169695Skan	 We assume that count is represented using two's-complement;
505169695Skan	 no power of two is divisible by ten, so if an overflow occurs
506169695Skan	 when multiplying by ten, the result will not be a multiple of
507169695Skan	 ten.  */
508169695Skan      if ((count % 10) != 0)
509169695Skan	{
510169695Skan	  while (ISDIGIT ((unsigned char) **type))
511169695Skan	    (*type)++;
512169695Skan	  return -1;
513169695Skan	}
514169695Skan
515169695Skan      count += **type - '0';
516169695Skan      (*type)++;
517169695Skan    }
518169695Skan
519169695Skan  if (count < 0)
520169695Skan    count = -1;
521169695Skan
522169695Skan  return (count);
523169695Skan}
524169695Skan
525169695Skan
526169695Skan/* Like consume_count, but for counts that are preceded and followed
527169695Skan   by '_' if they are greater than 10.  Also, -1 is returned for
528169695Skan   failure, since 0 can be a valid value.  */
529169695Skan
530169695Skanstatic int
531169695Skanconsume_count_with_underscores (const char **mangled)
532169695Skan{
533169695Skan  int idx;
534169695Skan
535169695Skan  if (**mangled == '_')
536169695Skan    {
537169695Skan      (*mangled)++;
538169695Skan      if (!ISDIGIT ((unsigned char)**mangled))
539169695Skan	return -1;
540169695Skan
541169695Skan      idx = consume_count (mangled);
542169695Skan      if (**mangled != '_')
543169695Skan	/* The trailing underscore was missing. */
544169695Skan	return -1;
545169695Skan
546169695Skan      (*mangled)++;
547169695Skan    }
548169695Skan  else
549169695Skan    {
550169695Skan      if (**mangled < '0' || **mangled > '9')
551169695Skan	return -1;
552169695Skan
553169695Skan      idx = **mangled - '0';
554169695Skan      (*mangled)++;
555169695Skan    }
556169695Skan
557169695Skan  return idx;
558169695Skan}
559169695Skan
560169695Skan/* C is the code for a type-qualifier.  Return the TYPE_QUAL
561169695Skan   corresponding to this qualifier.  */
562169695Skan
563169695Skanstatic int
564169695Skancode_for_qualifier (int c)
565169695Skan{
566169695Skan  switch (c)
567169695Skan    {
568169695Skan    case 'C':
569169695Skan      return TYPE_QUAL_CONST;
570169695Skan
571169695Skan    case 'V':
572169695Skan      return TYPE_QUAL_VOLATILE;
573169695Skan
574169695Skan    case 'u':
575169695Skan      return TYPE_QUAL_RESTRICT;
576169695Skan
577169695Skan    default:
578169695Skan      break;
579169695Skan    }
580169695Skan
581169695Skan  /* C was an invalid qualifier.  */
582169695Skan  abort ();
583169695Skan}
584169695Skan
585169695Skan/* Return the string corresponding to the qualifiers given by
586169695Skan   TYPE_QUALS.  */
587169695Skan
588169695Skanstatic const char*
589169695Skanqualifier_string (int type_quals)
590169695Skan{
591169695Skan  switch (type_quals)
592169695Skan    {
593169695Skan    case TYPE_UNQUALIFIED:
594169695Skan      return "";
595169695Skan
596169695Skan    case TYPE_QUAL_CONST:
597169695Skan      return "const";
598169695Skan
599169695Skan    case TYPE_QUAL_VOLATILE:
600169695Skan      return "volatile";
601169695Skan
602169695Skan    case TYPE_QUAL_RESTRICT:
603169695Skan      return "__restrict";
604169695Skan
605169695Skan    case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
606169695Skan      return "const volatile";
607169695Skan
608169695Skan    case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
609169695Skan      return "const __restrict";
610169695Skan
611169695Skan    case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
612169695Skan      return "volatile __restrict";
613169695Skan
614169695Skan    case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
615169695Skan      return "const volatile __restrict";
616169695Skan
617169695Skan    default:
618169695Skan      break;
619169695Skan    }
620169695Skan
621169695Skan  /* TYPE_QUALS was an invalid qualifier set.  */
622169695Skan  abort ();
623169695Skan}
624169695Skan
625169695Skan/* C is the code for a type-qualifier.  Return the string
626169695Skan   corresponding to this qualifier.  This function should only be
627169695Skan   called with a valid qualifier code.  */
628169695Skan
629169695Skanstatic const char*
630169695Skandemangle_qualifier (int c)
631169695Skan{
632169695Skan  return qualifier_string (code_for_qualifier (c));
633169695Skan}
634169695Skan
635169695Skanint
636169695Skancplus_demangle_opname (const char *opname, char *result, int options)
637169695Skan{
638169695Skan  int len, len1, ret;
639169695Skan  string type;
640169695Skan  struct work_stuff work[1];
641169695Skan  const char *tem;
642169695Skan
643169695Skan  len = strlen(opname);
644169695Skan  result[0] = '\0';
645169695Skan  ret = 0;
646169695Skan  memset ((char *) work, 0, sizeof (work));
647169695Skan  work->options = options;
648169695Skan
649169695Skan  if (opname[0] == '_' && opname[1] == '_'
650169695Skan      && opname[2] == 'o' && opname[3] == 'p')
651169695Skan    {
652169695Skan      /* ANSI.  */
653169695Skan      /* type conversion operator.  */
654169695Skan      tem = opname + 4;
655169695Skan      if (do_type (work, &tem, &type))
656169695Skan	{
657169695Skan	  strcat (result, "operator ");
658169695Skan	  strncat (result, type.b, type.p - type.b);
659169695Skan	  string_delete (&type);
660169695Skan	  ret = 1;
661169695Skan	}
662169695Skan    }
663169695Skan  else if (opname[0] == '_' && opname[1] == '_'
664169695Skan	   && ISLOWER((unsigned char)opname[2])
665169695Skan	   && ISLOWER((unsigned char)opname[3]))
666169695Skan    {
667169695Skan      if (opname[4] == '\0')
668169695Skan	{
669169695Skan	  /* Operator.  */
670169695Skan	  size_t i;
671169695Skan	  for (i = 0; i < ARRAY_SIZE (optable); i++)
672169695Skan	    {
673169695Skan	      if (strlen (optable[i].in) == 2
674169695Skan		  && memcmp (optable[i].in, opname + 2, 2) == 0)
675169695Skan		{
676169695Skan		  strcat (result, "operator");
677169695Skan		  strcat (result, optable[i].out);
678169695Skan		  ret = 1;
679169695Skan		  break;
680169695Skan		}
681169695Skan	    }
682169695Skan	}
683169695Skan      else
684169695Skan	{
685169695Skan	  if (opname[2] == 'a' && opname[5] == '\0')
686169695Skan	    {
687169695Skan	      /* Assignment.  */
688169695Skan	      size_t i;
689169695Skan	      for (i = 0; i < ARRAY_SIZE (optable); i++)
690169695Skan		{
691169695Skan		  if (strlen (optable[i].in) == 3
692169695Skan		      && memcmp (optable[i].in, opname + 2, 3) == 0)
693169695Skan		    {
694169695Skan		      strcat (result, "operator");
695169695Skan		      strcat (result, optable[i].out);
696169695Skan		      ret = 1;
697169695Skan		      break;
698169695Skan		    }
699169695Skan		}
700169695Skan	    }
701169695Skan	}
702169695Skan    }
703169695Skan  else if (len >= 3
704169695Skan	   && opname[0] == 'o'
705169695Skan	   && opname[1] == 'p'
706169695Skan	   && strchr (cplus_markers, opname[2]) != NULL)
707169695Skan    {
708169695Skan      /* see if it's an assignment expression */
709169695Skan      if (len >= 10 /* op$assign_ */
710169695Skan	  && memcmp (opname + 3, "assign_", 7) == 0)
711169695Skan	{
712169695Skan	  size_t i;
713169695Skan	  for (i = 0; i < ARRAY_SIZE (optable); i++)
714169695Skan	    {
715169695Skan	      len1 = len - 10;
716169695Skan	      if ((int) strlen (optable[i].in) == len1
717169695Skan		  && memcmp (optable[i].in, opname + 10, len1) == 0)
718169695Skan		{
719169695Skan		  strcat (result, "operator");
720169695Skan		  strcat (result, optable[i].out);
721169695Skan		  strcat (result, "=");
722169695Skan		  ret = 1;
723169695Skan		  break;
724169695Skan		}
725169695Skan	    }
726169695Skan	}
727169695Skan      else
728169695Skan	{
729169695Skan	  size_t i;
730169695Skan	  for (i = 0; i < ARRAY_SIZE (optable); i++)
731169695Skan	    {
732169695Skan	      len1 = len - 3;
733169695Skan	      if ((int) strlen (optable[i].in) == len1
734169695Skan		  && memcmp (optable[i].in, opname + 3, len1) == 0)
735169695Skan		{
736169695Skan		  strcat (result, "operator");
737169695Skan		  strcat (result, optable[i].out);
738169695Skan		  ret = 1;
739169695Skan		  break;
740169695Skan		}
741169695Skan	    }
742169695Skan	}
743169695Skan    }
744169695Skan  else if (len >= 5 && memcmp (opname, "type", 4) == 0
745169695Skan	   && strchr (cplus_markers, opname[4]) != NULL)
746169695Skan    {
747169695Skan      /* type conversion operator */
748169695Skan      tem = opname + 5;
749169695Skan      if (do_type (work, &tem, &type))
750169695Skan	{
751169695Skan	  strcat (result, "operator ");
752169695Skan	  strncat (result, type.b, type.p - type.b);
753169695Skan	  string_delete (&type);
754169695Skan	  ret = 1;
755169695Skan	}
756169695Skan    }
757169695Skan  squangle_mop_up (work);
758169695Skan  return ret;
759169695Skan
760169695Skan}
761169695Skan
762169695Skan/* Takes operator name as e.g. "++" and returns mangled
763169695Skan   operator name (e.g. "postincrement_expr"), or NULL if not found.
764169695Skan
765169695Skan   If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
766169695Skan   if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
767169695Skan
768169695Skanconst char *
769169695Skancplus_mangle_opname (const char *opname, int options)
770169695Skan{
771169695Skan  size_t i;
772169695Skan  int len;
773169695Skan
774169695Skan  len = strlen (opname);
775169695Skan  for (i = 0; i < ARRAY_SIZE (optable); i++)
776169695Skan    {
777169695Skan      if ((int) strlen (optable[i].out) == len
778169695Skan	  && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
779169695Skan	  && memcmp (optable[i].out, opname, len) == 0)
780169695Skan	return optable[i].in;
781169695Skan    }
782169695Skan  return (0);
783169695Skan}
784169695Skan
785169695Skan/* Add a routine to set the demangling style to be sure it is valid and
786169695Skan   allow for any demangler initialization that maybe necessary. */
787169695Skan
788169695Skanenum demangling_styles
789169695Skancplus_demangle_set_style (enum demangling_styles style)
790169695Skan{
791169695Skan  const struct demangler_engine *demangler = libiberty_demanglers;
792169695Skan
793169695Skan  for (; demangler->demangling_style != unknown_demangling; ++demangler)
794169695Skan    if (style == demangler->demangling_style)
795169695Skan      {
796169695Skan	current_demangling_style = style;
797169695Skan	return current_demangling_style;
798169695Skan      }
799169695Skan
800169695Skan  return unknown_demangling;
801169695Skan}
802169695Skan
803169695Skan/* Do string name to style translation */
804169695Skan
805169695Skanenum demangling_styles
806169695Skancplus_demangle_name_to_style (const char *name)
807169695Skan{
808169695Skan  const struct demangler_engine *demangler = libiberty_demanglers;
809169695Skan
810169695Skan  for (; demangler->demangling_style != unknown_demangling; ++demangler)
811169695Skan    if (strcmp (name, demangler->demangling_style_name) == 0)
812169695Skan      return demangler->demangling_style;
813169695Skan
814169695Skan  return unknown_demangling;
815169695Skan}
816169695Skan
817169695Skan/* char *cplus_demangle (const char *mangled, int options)
818169695Skan
819169695Skan   If MANGLED is a mangled function name produced by GNU C++, then
820169695Skan   a pointer to a @code{malloc}ed string giving a C++ representation
821169695Skan   of the name will be returned; otherwise NULL will be returned.
822169695Skan   It is the caller's responsibility to free the string which
823169695Skan   is returned.
824169695Skan
825169695Skan   The OPTIONS arg may contain one or more of the following bits:
826169695Skan
827169695Skan   	DMGL_ANSI	ANSI qualifiers such as `const' and `void' are
828169695Skan			included.
829169695Skan	DMGL_PARAMS	Function parameters are included.
830169695Skan
831169695Skan   For example,
832169695Skan
833169695Skan   cplus_demangle ("foo__1Ai", DMGL_PARAMS)		=> "A::foo(int)"
834169695Skan   cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI)	=> "A::foo(int)"
835169695Skan   cplus_demangle ("foo__1Ai", 0)			=> "A::foo"
836169695Skan
837169695Skan   cplus_demangle ("foo__1Afe", DMGL_PARAMS)		=> "A::foo(float,...)"
838169695Skan   cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
839169695Skan   cplus_demangle ("foo__1Afe", 0)			=> "A::foo"
840169695Skan
841169695Skan   Note that any leading underscores, or other such characters prepended by
842169695Skan   the compilation system, are presumed to have already been stripped from
843169695Skan   MANGLED.  */
844169695Skan
845169695Skanchar *
846169695Skancplus_demangle (const char *mangled, int options)
847169695Skan{
848169695Skan  char *ret;
849169695Skan  struct work_stuff work[1];
850169695Skan
851169695Skan  if (current_demangling_style == no_demangling)
852169695Skan    return xstrdup (mangled);
853169695Skan
854169695Skan  memset ((char *) work, 0, sizeof (work));
855169695Skan  work->options = options;
856169695Skan  if ((work->options & DMGL_STYLE_MASK) == 0)
857169695Skan    work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
858169695Skan
859169695Skan  /* The V3 ABI demangling is implemented elsewhere.  */
860169695Skan  if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
861169695Skan    {
862169695Skan      ret = cplus_demangle_v3 (mangled, work->options);
863169695Skan      if (ret || GNU_V3_DEMANGLING)
864169695Skan	return ret;
865169695Skan    }
866169695Skan
867169695Skan  if (JAVA_DEMANGLING)
868169695Skan    {
869169695Skan      ret = java_demangle_v3 (mangled);
870169695Skan      if (ret)
871169695Skan        return ret;
872169695Skan    }
873169695Skan
874169695Skan  if (GNAT_DEMANGLING)
875169695Skan    return ada_demangle(mangled,options);
876169695Skan
877169695Skan  ret = internal_cplus_demangle (work, mangled);
878169695Skan  squangle_mop_up (work);
879169695Skan  return (ret);
880169695Skan}
881169695Skan
882169695Skan
883169695Skan/* Assuming *OLD_VECT points to an array of *SIZE objects of size
884169695Skan   ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
885169695Skan   updating *OLD_VECT and *SIZE as necessary.  */
886169695Skan
887169695Skanstatic void
888169695Skangrow_vect (char **old_vect, size_t *size, size_t min_size, int element_size)
889169695Skan{
890169695Skan  if (*size < min_size)
891169695Skan    {
892169695Skan      *size *= 2;
893169695Skan      if (*size < min_size)
894169695Skan	*size = min_size;
895169695Skan      *old_vect = XRESIZEVAR (char, *old_vect, *size * element_size);
896169695Skan    }
897169695Skan}
898169695Skan
899169695Skan/* Demangle ada names:
900169695Skan   1. Discard final __{DIGIT}+ or ${DIGIT}+
901169695Skan   2. Convert other instances of embedded "__" to `.'.
902169695Skan   3. Discard leading _ada_.
903169695Skan   4. Remove everything after first ___ if it is followed by 'X'.
904169695Skan   5. Put symbols that should be suppressed in <...> brackets.
905169695Skan   The resulting string is valid until the next call of ada_demangle.  */
906169695Skan
907169695Skanstatic char *
908169695Skanada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
909169695Skan{
910169695Skan  int i, j;
911169695Skan  int len0;
912169695Skan  const char* p;
913169695Skan  char *demangled = NULL;
914169695Skan  int changed;
915169695Skan  size_t demangled_size = 0;
916169695Skan
917169695Skan  changed = 0;
918169695Skan
919169695Skan  if (strncmp (mangled, "_ada_", 5) == 0)
920169695Skan    {
921169695Skan      mangled += 5;
922169695Skan      changed = 1;
923169695Skan    }
924169695Skan
925169695Skan  if (mangled[0] == '_' || mangled[0] == '<')
926169695Skan    goto Suppress;
927169695Skan
928169695Skan  p = strstr (mangled, "___");
929169695Skan  if (p == NULL)
930169695Skan    len0 = strlen (mangled);
931169695Skan  else
932169695Skan    {
933169695Skan      if (p[3] == 'X')
934169695Skan	{
935169695Skan	  len0 = p - mangled;
936169695Skan	  changed = 1;
937169695Skan	}
938169695Skan      else
939169695Skan	goto Suppress;
940169695Skan    }
941169695Skan
942169695Skan  /* Make demangled big enough for possible expansion by operator name.  */
943169695Skan  grow_vect (&demangled,
944169695Skan	     &demangled_size,  2 * len0 + 1,
945169695Skan	     sizeof (char));
946169695Skan
947169695Skan  if (ISDIGIT ((unsigned char) mangled[len0 - 1])) {
948169695Skan    for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1)
949169695Skan      ;
950169695Skan    if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_')
951169695Skan      {
952169695Skan	len0 = i - 1;
953169695Skan	changed = 1;
954169695Skan      }
955169695Skan    else if (mangled[i] == '$')
956169695Skan      {
957169695Skan	len0 = i;
958169695Skan	changed = 1;
959169695Skan      }
960169695Skan  }
961169695Skan
962169695Skan  for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
963169695Skan       i += 1, j += 1)
964169695Skan    demangled[j] = mangled[i];
965169695Skan
966169695Skan  while (i < len0)
967169695Skan    {
968169695Skan      if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_')
969169695Skan	{
970169695Skan	  demangled[j] = '.';
971169695Skan	  changed = 1;
972169695Skan	  i += 2; j += 1;
973169695Skan	}
974169695Skan      else
975169695Skan	{
976169695Skan	  demangled[j] = mangled[i];
977169695Skan	  i += 1;  j += 1;
978169695Skan	}
979169695Skan    }
980169695Skan  demangled[j] = '\000';
981169695Skan
982169695Skan  for (i = 0; demangled[i] != '\0'; i += 1)
983169695Skan    if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ')
984169695Skan      goto Suppress;
985169695Skan
986169695Skan  if (! changed)
987169695Skan    return NULL;
988169695Skan  else
989169695Skan    return demangled;
990169695Skan
991169695Skan Suppress:
992169695Skan  grow_vect (&demangled,
993169695Skan	     &demangled_size,  strlen (mangled) + 3,
994169695Skan	     sizeof (char));
995169695Skan
996169695Skan  if (mangled[0] == '<')
997169695Skan     strcpy (demangled, mangled);
998169695Skan  else
999169695Skan    sprintf (demangled, "<%s>", mangled);
1000169695Skan
1001169695Skan  return demangled;
1002169695Skan}
1003169695Skan
1004169695Skan/* This function performs most of what cplus_demangle use to do, but
1005169695Skan   to be able to demangle a name with a B, K or n code, we need to
1006169695Skan   have a longer term memory of what types have been seen. The original
1007169695Skan   now initializes and cleans up the squangle code info, while internal
1008169695Skan   calls go directly to this routine to avoid resetting that info. */
1009169695Skan
1010169695Skanstatic char *
1011169695Skaninternal_cplus_demangle (struct work_stuff *work, const char *mangled)
1012169695Skan{
1013169695Skan
1014169695Skan  string decl;
1015169695Skan  int success = 0;
1016169695Skan  char *demangled = NULL;
1017169695Skan  int s1, s2, s3, s4;
1018169695Skan  s1 = work->constructor;
1019169695Skan  s2 = work->destructor;
1020169695Skan  s3 = work->static_type;
1021169695Skan  s4 = work->type_quals;
1022169695Skan  work->constructor = work->destructor = 0;
1023169695Skan  work->type_quals = TYPE_UNQUALIFIED;
1024169695Skan  work->dllimported = 0;
1025169695Skan
1026169695Skan  if ((mangled != NULL) && (*mangled != '\0'))
1027169695Skan    {
1028169695Skan      string_init (&decl);
1029169695Skan
1030169695Skan      /* First check to see if gnu style demangling is active and if the
1031169695Skan	 string to be demangled contains a CPLUS_MARKER.  If so, attempt to
1032169695Skan	 recognize one of the gnu special forms rather than looking for a
1033169695Skan	 standard prefix.  In particular, don't worry about whether there
1034169695Skan	 is a "__" string in the mangled string.  Consider "_$_5__foo" for
1035169695Skan	 example.  */
1036169695Skan
1037169695Skan      if ((AUTO_DEMANGLING || GNU_DEMANGLING))
1038169695Skan	{
1039169695Skan	  success = gnu_special (work, &mangled, &decl);
1040169695Skan	}
1041169695Skan      if (!success)
1042169695Skan	{
1043169695Skan	  success = demangle_prefix (work, &mangled, &decl);
1044169695Skan	}
1045169695Skan      if (success && (*mangled != '\0'))
1046169695Skan	{
1047169695Skan	  success = demangle_signature (work, &mangled, &decl);
1048169695Skan	}
1049169695Skan      if (work->constructor == 2)
1050169695Skan        {
1051169695Skan          string_prepend (&decl, "global constructors keyed to ");
1052169695Skan          work->constructor = 0;
1053169695Skan        }
1054169695Skan      else if (work->destructor == 2)
1055169695Skan        {
1056169695Skan          string_prepend (&decl, "global destructors keyed to ");
1057169695Skan          work->destructor = 0;
1058169695Skan        }
1059169695Skan      else if (work->dllimported == 1)
1060169695Skan        {
1061169695Skan          string_prepend (&decl, "import stub for ");
1062169695Skan          work->dllimported = 0;
1063169695Skan        }
1064169695Skan      demangled = mop_up (work, &decl, success);
1065169695Skan    }
1066169695Skan  work->constructor = s1;
1067169695Skan  work->destructor = s2;
1068169695Skan  work->static_type = s3;
1069169695Skan  work->type_quals = s4;
1070169695Skan  return demangled;
1071169695Skan}
1072169695Skan
1073169695Skan
1074169695Skan/* Clear out and squangling related storage */
1075169695Skanstatic void
1076169695Skansquangle_mop_up (struct work_stuff *work)
1077169695Skan{
1078169695Skan  /* clean up the B and K type mangling types. */
1079169695Skan  forget_B_and_K_types (work);
1080169695Skan  if (work -> btypevec != NULL)
1081169695Skan    {
1082169695Skan      free ((char *) work -> btypevec);
1083169695Skan    }
1084169695Skan  if (work -> ktypevec != NULL)
1085169695Skan    {
1086169695Skan      free ((char *) work -> ktypevec);
1087169695Skan    }
1088169695Skan}
1089169695Skan
1090169695Skan
1091169695Skan/* Copy the work state and storage.  */
1092169695Skan
1093169695Skanstatic void
1094169695Skanwork_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
1095169695Skan{
1096169695Skan  int i;
1097169695Skan
1098169695Skan  delete_work_stuff (to);
1099169695Skan
1100169695Skan  /* Shallow-copy scalars.  */
1101169695Skan  memcpy (to, from, sizeof (*to));
1102169695Skan
1103169695Skan  /* Deep-copy dynamic storage.  */
1104169695Skan  if (from->typevec_size)
1105169695Skan    to->typevec = XNEWVEC (char *, from->typevec_size);
1106169695Skan
1107169695Skan  for (i = 0; i < from->ntypes; i++)
1108169695Skan    {
1109169695Skan      int len = strlen (from->typevec[i]) + 1;
1110169695Skan
1111169695Skan      to->typevec[i] = XNEWVEC (char, len);
1112169695Skan      memcpy (to->typevec[i], from->typevec[i], len);
1113169695Skan    }
1114169695Skan
1115169695Skan  if (from->ksize)
1116169695Skan    to->ktypevec = XNEWVEC (char *, from->ksize);
1117169695Skan
1118169695Skan  for (i = 0; i < from->numk; i++)
1119169695Skan    {
1120169695Skan      int len = strlen (from->ktypevec[i]) + 1;
1121169695Skan
1122169695Skan      to->ktypevec[i] = XNEWVEC (char, len);
1123169695Skan      memcpy (to->ktypevec[i], from->ktypevec[i], len);
1124169695Skan    }
1125169695Skan
1126169695Skan  if (from->bsize)
1127169695Skan    to->btypevec = XNEWVEC (char *, from->bsize);
1128169695Skan
1129169695Skan  for (i = 0; i < from->numb; i++)
1130169695Skan    {
1131169695Skan      int len = strlen (from->btypevec[i]) + 1;
1132169695Skan
1133169695Skan      to->btypevec[i] = XNEWVEC (char , len);
1134169695Skan      memcpy (to->btypevec[i], from->btypevec[i], len);
1135169695Skan    }
1136169695Skan
1137169695Skan  if (from->ntmpl_args)
1138169695Skan    to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
1139169695Skan
1140169695Skan  for (i = 0; i < from->ntmpl_args; i++)
1141169695Skan    {
1142169695Skan      int len = strlen (from->tmpl_argvec[i]) + 1;
1143169695Skan
1144169695Skan      to->tmpl_argvec[i] = XNEWVEC (char, len);
1145169695Skan      memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
1146169695Skan    }
1147169695Skan
1148169695Skan  if (from->previous_argument)
1149169695Skan    {
1150169695Skan      to->previous_argument = XNEW (string);
1151169695Skan      string_init (to->previous_argument);
1152169695Skan      string_appends (to->previous_argument, from->previous_argument);
1153169695Skan    }
1154169695Skan}
1155169695Skan
1156169695Skan
1157169695Skan/* Delete dynamic stuff in work_stuff that is not to be re-used.  */
1158169695Skan
1159169695Skanstatic void
1160169695Skandelete_non_B_K_work_stuff (struct work_stuff *work)
1161169695Skan{
1162169695Skan  /* Discard the remembered types, if any.  */
1163169695Skan
1164169695Skan  forget_types (work);
1165169695Skan  if (work -> typevec != NULL)
1166169695Skan    {
1167169695Skan      free ((char *) work -> typevec);
1168169695Skan      work -> typevec = NULL;
1169169695Skan      work -> typevec_size = 0;
1170169695Skan    }
1171169695Skan  if (work->tmpl_argvec)
1172169695Skan    {
1173169695Skan      int i;
1174169695Skan
1175169695Skan      for (i = 0; i < work->ntmpl_args; i++)
1176169695Skan	if (work->tmpl_argvec[i])
1177169695Skan	  free ((char*) work->tmpl_argvec[i]);
1178169695Skan
1179169695Skan      free ((char*) work->tmpl_argvec);
1180169695Skan      work->tmpl_argvec = NULL;
1181169695Skan    }
1182169695Skan  if (work->previous_argument)
1183169695Skan    {
1184169695Skan      string_delete (work->previous_argument);
1185169695Skan      free ((char*) work->previous_argument);
1186169695Skan      work->previous_argument = NULL;
1187169695Skan    }
1188169695Skan}
1189169695Skan
1190169695Skan
1191169695Skan/* Delete all dynamic storage in work_stuff.  */
1192169695Skanstatic void
1193169695Skandelete_work_stuff (struct work_stuff *work)
1194169695Skan{
1195169695Skan  delete_non_B_K_work_stuff (work);
1196169695Skan  squangle_mop_up (work);
1197169695Skan}
1198169695Skan
1199169695Skan
1200169695Skan/* Clear out any mangled storage */
1201169695Skan
1202169695Skanstatic char *
1203169695Skanmop_up (struct work_stuff *work, string *declp, int success)
1204169695Skan{
1205169695Skan  char *demangled = NULL;
1206169695Skan
1207169695Skan  delete_non_B_K_work_stuff (work);
1208169695Skan
1209169695Skan  /* If demangling was successful, ensure that the demangled string is null
1210169695Skan     terminated and return it.  Otherwise, free the demangling decl.  */
1211169695Skan
1212169695Skan  if (!success)
1213169695Skan    {
1214169695Skan      string_delete (declp);
1215169695Skan    }
1216169695Skan  else
1217169695Skan    {
1218169695Skan      string_appendn (declp, "", 1);
1219169695Skan      demangled = declp->b;
1220169695Skan    }
1221169695Skan  return (demangled);
1222169695Skan}
1223169695Skan
1224169695Skan/*
1225169695Skan
1226169695SkanLOCAL FUNCTION
1227169695Skan
1228169695Skan	demangle_signature -- demangle the signature part of a mangled name
1229169695Skan
1230169695SkanSYNOPSIS
1231169695Skan
1232169695Skan	static int
1233169695Skan	demangle_signature (struct work_stuff *work, const char **mangled,
1234169695Skan			    string *declp);
1235169695Skan
1236169695SkanDESCRIPTION
1237169695Skan
1238169695Skan	Consume and demangle the signature portion of the mangled name.
1239169695Skan
1240169695Skan	DECLP is the string where demangled output is being built.  At
1241169695Skan	entry it contains the demangled root name from the mangled name
1242169695Skan	prefix.  I.E. either a demangled operator name or the root function
1243169695Skan	name.  In some special cases, it may contain nothing.
1244169695Skan
1245169695Skan	*MANGLED points to the current unconsumed location in the mangled
1246169695Skan	name.  As tokens are consumed and demangling is performed, the
1247169695Skan	pointer is updated to continuously point at the next token to
1248169695Skan	be consumed.
1249169695Skan
1250169695Skan	Demangling GNU style mangled names is nasty because there is no
1251169695Skan	explicit token that marks the start of the outermost function
1252169695Skan	argument list.  */
1253169695Skan
1254169695Skanstatic int
1255169695Skandemangle_signature (struct work_stuff *work,
1256169695Skan                    const char **mangled, string *declp)
1257169695Skan{
1258169695Skan  int success = 1;
1259169695Skan  int func_done = 0;
1260169695Skan  int expect_func = 0;
1261169695Skan  int expect_return_type = 0;
1262169695Skan  const char *oldmangled = NULL;
1263169695Skan  string trawname;
1264169695Skan  string tname;
1265169695Skan
1266169695Skan  while (success && (**mangled != '\0'))
1267169695Skan    {
1268169695Skan      switch (**mangled)
1269169695Skan	{
1270169695Skan	case 'Q':
1271169695Skan	  oldmangled = *mangled;
1272169695Skan	  success = demangle_qualified (work, mangled, declp, 1, 0);
1273169695Skan	  if (success)
1274169695Skan	    remember_type (work, oldmangled, *mangled - oldmangled);
1275169695Skan	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
1276169695Skan	    expect_func = 1;
1277169695Skan	  oldmangled = NULL;
1278169695Skan	  break;
1279169695Skan
1280169695Skan        case 'K':
1281169695Skan	  oldmangled = *mangled;
1282169695Skan	  success = demangle_qualified (work, mangled, declp, 1, 0);
1283169695Skan	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
1284169695Skan	    {
1285169695Skan	      expect_func = 1;
1286169695Skan	    }
1287169695Skan	  oldmangled = NULL;
1288169695Skan	  break;
1289169695Skan
1290169695Skan	case 'S':
1291169695Skan	  /* Static member function */
1292169695Skan	  if (oldmangled == NULL)
1293169695Skan	    {
1294169695Skan	      oldmangled = *mangled;
1295169695Skan	    }
1296169695Skan	  (*mangled)++;
1297169695Skan	  work -> static_type = 1;
1298169695Skan	  break;
1299169695Skan
1300169695Skan	case 'C':
1301169695Skan	case 'V':
1302169695Skan	case 'u':
1303169695Skan	  work->type_quals |= code_for_qualifier (**mangled);
1304169695Skan
1305169695Skan	  /* a qualified member function */
1306169695Skan	  if (oldmangled == NULL)
1307169695Skan	    oldmangled = *mangled;
1308169695Skan	  (*mangled)++;
1309169695Skan	  break;
1310169695Skan
1311169695Skan	case 'L':
1312169695Skan	  /* Local class name follows after "Lnnn_" */
1313169695Skan	  if (HP_DEMANGLING)
1314169695Skan	    {
1315169695Skan	      while (**mangled && (**mangled != '_'))
1316169695Skan		(*mangled)++;
1317169695Skan	      if (!**mangled)
1318169695Skan		success = 0;
1319169695Skan	      else
1320169695Skan		(*mangled)++;
1321169695Skan	    }
1322169695Skan	  else
1323169695Skan	    success = 0;
1324169695Skan	  break;
1325169695Skan
1326169695Skan	case '0': case '1': case '2': case '3': case '4':
1327169695Skan	case '5': case '6': case '7': case '8': case '9':
1328169695Skan	  if (oldmangled == NULL)
1329169695Skan	    {
1330169695Skan	      oldmangled = *mangled;
1331169695Skan	    }
1332169695Skan          work->temp_start = -1; /* uppermost call to demangle_class */
1333169695Skan	  success = demangle_class (work, mangled, declp);
1334169695Skan	  if (success)
1335169695Skan	    {
1336169695Skan	      remember_type (work, oldmangled, *mangled - oldmangled);
1337169695Skan	    }
1338169695Skan	  if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
1339169695Skan	    {
1340169695Skan              /* EDG and others will have the "F", so we let the loop cycle
1341169695Skan                 if we are looking at one. */
1342169695Skan              if (**mangled != 'F')
1343169695Skan                 expect_func = 1;
1344169695Skan	    }
1345169695Skan	  oldmangled = NULL;
1346169695Skan	  break;
1347169695Skan
1348169695Skan	case 'B':
1349169695Skan	  {
1350169695Skan	    string s;
1351169695Skan	    success = do_type (work, mangled, &s);
1352169695Skan	    if (success)
1353169695Skan	      {
1354169695Skan		string_append (&s, SCOPE_STRING (work));
1355169695Skan		string_prepends (declp, &s);
1356169695Skan		string_delete (&s);
1357169695Skan	      }
1358169695Skan	    oldmangled = NULL;
1359169695Skan	    expect_func = 1;
1360169695Skan	  }
1361169695Skan	  break;
1362169695Skan
1363169695Skan	case 'F':
1364169695Skan	  /* Function */
1365169695Skan	  /* ARM/HP style demangling includes a specific 'F' character after
1366169695Skan	     the class name.  For GNU style, it is just implied.  So we can
1367169695Skan	     safely just consume any 'F' at this point and be compatible
1368169695Skan	     with either style.  */
1369169695Skan
1370169695Skan	  oldmangled = NULL;
1371169695Skan	  func_done = 1;
1372169695Skan	  (*mangled)++;
1373169695Skan
1374169695Skan	  /* For lucid/ARM/HP style we have to forget any types we might
1375169695Skan	     have remembered up to this point, since they were not argument
1376169695Skan	     types.  GNU style considers all types seen as available for
1377169695Skan	     back references.  See comment in demangle_args() */
1378169695Skan
1379169695Skan	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
1380169695Skan	    {
1381169695Skan	      forget_types (work);
1382169695Skan	    }
1383169695Skan	  success = demangle_args (work, mangled, declp);
1384169695Skan	  /* After picking off the function args, we expect to either
1385169695Skan	     find the function return type (preceded by an '_') or the
1386169695Skan	     end of the string. */
1387169695Skan	  if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
1388169695Skan	    {
1389169695Skan	      ++(*mangled);
1390169695Skan              /* At this level, we do not care about the return type. */
1391169695Skan              success = do_type (work, mangled, &tname);
1392169695Skan              string_delete (&tname);
1393169695Skan            }
1394169695Skan
1395169695Skan	  break;
1396169695Skan
1397169695Skan	case 't':
1398169695Skan	  /* G++ Template */
1399169695Skan	  string_init(&trawname);
1400169695Skan	  string_init(&tname);
1401169695Skan	  if (oldmangled == NULL)
1402169695Skan	    {
1403169695Skan	      oldmangled = *mangled;
1404169695Skan	    }
1405169695Skan	  success = demangle_template (work, mangled, &tname,
1406169695Skan				       &trawname, 1, 1);
1407169695Skan	  if (success)
1408169695Skan	    {
1409169695Skan	      remember_type (work, oldmangled, *mangled - oldmangled);
1410169695Skan	    }
1411169695Skan	  string_append (&tname, SCOPE_STRING (work));
1412169695Skan
1413169695Skan	  string_prepends(declp, &tname);
1414169695Skan	  if (work -> destructor & 1)
1415169695Skan	    {
1416169695Skan	      string_prepend (&trawname, "~");
1417169695Skan	      string_appends (declp, &trawname);
1418169695Skan	      work->destructor -= 1;
1419169695Skan	    }
1420169695Skan	  if ((work->constructor & 1) || (work->destructor & 1))
1421169695Skan	    {
1422169695Skan	      string_appends (declp, &trawname);
1423169695Skan	      work->constructor -= 1;
1424169695Skan	    }
1425169695Skan	  string_delete(&trawname);
1426169695Skan	  string_delete(&tname);
1427169695Skan	  oldmangled = NULL;
1428169695Skan	  expect_func = 1;
1429169695Skan	  break;
1430169695Skan
1431169695Skan	case '_':
1432169695Skan	  if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
1433169695Skan	    {
1434169695Skan	      /* Read the return type. */
1435169695Skan	      string return_type;
1436169695Skan
1437169695Skan	      (*mangled)++;
1438169695Skan	      success = do_type (work, mangled, &return_type);
1439169695Skan	      APPEND_BLANK (&return_type);
1440169695Skan
1441169695Skan	      string_prepends (declp, &return_type);
1442169695Skan	      string_delete (&return_type);
1443169695Skan	      break;
1444169695Skan	    }
1445169695Skan	  else
1446169695Skan	    /* At the outermost level, we cannot have a return type specified,
1447169695Skan	       so if we run into another '_' at this point we are dealing with
1448169695Skan	       a mangled name that is either bogus, or has been mangled by
1449169695Skan	       some algorithm we don't know how to deal with.  So just
1450169695Skan	       reject the entire demangling.  */
1451169695Skan            /* However, "_nnn" is an expected suffix for alternate entry point
1452169695Skan               numbered nnn for a function, with HP aCC, so skip over that
1453169695Skan               without reporting failure. pai/1997-09-04 */
1454169695Skan            if (HP_DEMANGLING)
1455169695Skan              {
1456169695Skan                (*mangled)++;
1457169695Skan                while (**mangled && ISDIGIT ((unsigned char)**mangled))
1458169695Skan                  (*mangled)++;
1459169695Skan              }
1460169695Skan            else
1461169695Skan	      success = 0;
1462169695Skan	  break;
1463169695Skan
1464169695Skan	case 'H':
1465169695Skan	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
1466169695Skan	    {
1467169695Skan	      /* A G++ template function.  Read the template arguments. */
1468169695Skan	      success = demangle_template (work, mangled, declp, 0, 0,
1469169695Skan					   0);
1470169695Skan	      if (!(work->constructor & 1))
1471169695Skan		expect_return_type = 1;
1472169695Skan	      (*mangled)++;
1473169695Skan	      break;
1474169695Skan	    }
1475169695Skan	  else
1476169695Skan	    /* fall through */
1477169695Skan	    {;}
1478169695Skan
1479169695Skan	default:
1480169695Skan	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
1481169695Skan	    {
1482169695Skan	      /* Assume we have stumbled onto the first outermost function
1483169695Skan		 argument token, and start processing args.  */
1484169695Skan	      func_done = 1;
1485169695Skan	      success = demangle_args (work, mangled, declp);
1486169695Skan	    }
1487169695Skan	  else
1488169695Skan	    {
1489169695Skan	      /* Non-GNU demanglers use a specific token to mark the start
1490169695Skan		 of the outermost function argument tokens.  Typically 'F',
1491169695Skan		 for ARM/HP-demangling, for example.  So if we find something
1492169695Skan		 we are not prepared for, it must be an error.  */
1493169695Skan	      success = 0;
1494169695Skan	    }
1495169695Skan	  break;
1496169695Skan	}
1497169695Skan      /*
1498169695Skan	if (AUTO_DEMANGLING || GNU_DEMANGLING)
1499169695Skan	*/
1500169695Skan      {
1501169695Skan	if (success && expect_func)
1502169695Skan	  {
1503169695Skan	    func_done = 1;
1504169695Skan              if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
1505169695Skan                {
1506169695Skan                  forget_types (work);
1507169695Skan                }
1508169695Skan	    success = demangle_args (work, mangled, declp);
1509169695Skan	    /* Since template include the mangling of their return types,
1510169695Skan	       we must set expect_func to 0 so that we don't try do
1511169695Skan	       demangle more arguments the next time we get here.  */
1512169695Skan	    expect_func = 0;
1513169695Skan	  }
1514169695Skan      }
1515169695Skan    }
1516169695Skan  if (success && !func_done)
1517169695Skan    {
1518169695Skan      if (AUTO_DEMANGLING || GNU_DEMANGLING)
1519169695Skan	{
1520169695Skan	  /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
1521169695Skan	     bar__3fooi is 'foo::bar(int)'.  We get here when we find the
1522169695Skan	     first case, and need to ensure that the '(void)' gets added to
1523169695Skan	     the current declp.  Note that with ARM/HP, the first case
1524169695Skan	     represents the name of a static data member 'foo::bar',
1525169695Skan	     which is in the current declp, so we leave it alone.  */
1526169695Skan	  success = demangle_args (work, mangled, declp);
1527169695Skan	}
1528169695Skan    }
1529169695Skan  if (success && PRINT_ARG_TYPES)
1530169695Skan    {
1531169695Skan      if (work->static_type)
1532169695Skan	string_append (declp, " static");
1533169695Skan      if (work->type_quals != TYPE_UNQUALIFIED)
1534169695Skan	{
1535169695Skan	  APPEND_BLANK (declp);
1536169695Skan	  string_append (declp, qualifier_string (work->type_quals));
1537169695Skan	}
1538169695Skan    }
1539169695Skan
1540169695Skan  return (success);
1541169695Skan}
1542169695Skan
1543169695Skan#if 0
1544169695Skan
1545169695Skanstatic int
1546169695Skandemangle_method_args (struct work_stuff *work, const char **mangled,
1547169695Skan                      string *declp)
1548169695Skan{
1549169695Skan  int success = 0;
1550169695Skan
1551169695Skan  if (work -> static_type)
1552169695Skan    {
1553169695Skan      string_append (declp, *mangled + 1);
1554169695Skan      *mangled += strlen (*mangled);
1555169695Skan      success = 1;
1556169695Skan    }
1557169695Skan  else
1558169695Skan    {
1559169695Skan      success = demangle_args (work, mangled, declp);
1560169695Skan    }
1561169695Skan  return (success);
1562169695Skan}
1563169695Skan
1564169695Skan#endif
1565169695Skan
1566169695Skanstatic int
1567169695Skandemangle_template_template_parm (struct work_stuff *work,
1568169695Skan                                 const char **mangled, string *tname)
1569169695Skan{
1570169695Skan  int i;
1571169695Skan  int r;
1572169695Skan  int need_comma = 0;
1573169695Skan  int success = 1;
1574169695Skan  string temp;
1575169695Skan
1576169695Skan  string_append (tname, "template <");
1577169695Skan  /* get size of template parameter list */
1578169695Skan  if (get_count (mangled, &r))
1579169695Skan    {
1580169695Skan      for (i = 0; i < r; i++)
1581169695Skan	{
1582169695Skan	  if (need_comma)
1583169695Skan	    {
1584169695Skan	      string_append (tname, ", ");
1585169695Skan	    }
1586169695Skan
1587169695Skan	    /* Z for type parameters */
1588169695Skan	    if (**mangled == 'Z')
1589169695Skan	      {
1590169695Skan		(*mangled)++;
1591169695Skan		string_append (tname, "class");
1592169695Skan	      }
1593169695Skan	      /* z for template parameters */
1594169695Skan	    else if (**mangled == 'z')
1595169695Skan	      {
1596169695Skan		(*mangled)++;
1597169695Skan		success =
1598169695Skan		  demangle_template_template_parm (work, mangled, tname);
1599169695Skan		if (!success)
1600169695Skan		  {
1601169695Skan		    break;
1602169695Skan		  }
1603169695Skan	      }
1604169695Skan	    else
1605169695Skan	      {
1606169695Skan		/* temp is initialized in do_type */
1607169695Skan		success = do_type (work, mangled, &temp);
1608169695Skan		if (success)
1609169695Skan		  {
1610169695Skan		    string_appends (tname, &temp);
1611169695Skan		  }
1612169695Skan		string_delete(&temp);
1613169695Skan		if (!success)
1614169695Skan		  {
1615169695Skan		    break;
1616169695Skan		  }
1617169695Skan	      }
1618169695Skan	  need_comma = 1;
1619169695Skan	}
1620169695Skan
1621169695Skan    }
1622169695Skan  if (tname->p[-1] == '>')
1623169695Skan    string_append (tname, " ");
1624169695Skan  string_append (tname, "> class");
1625169695Skan  return (success);
1626169695Skan}
1627169695Skan
1628169695Skanstatic int
1629169695Skandemangle_expression (struct work_stuff *work, const char **mangled,
1630169695Skan                     string *s, type_kind_t tk)
1631169695Skan{
1632169695Skan  int need_operator = 0;
1633169695Skan  int success;
1634169695Skan
1635169695Skan  success = 1;
1636169695Skan  string_appendn (s, "(", 1);
1637169695Skan  (*mangled)++;
1638169695Skan  while (success && **mangled != 'W' && **mangled != '\0')
1639169695Skan    {
1640169695Skan      if (need_operator)
1641169695Skan	{
1642169695Skan	  size_t i;
1643169695Skan	  size_t len;
1644169695Skan
1645169695Skan	  success = 0;
1646169695Skan
1647169695Skan	  len = strlen (*mangled);
1648169695Skan
1649169695Skan	  for (i = 0; i < ARRAY_SIZE (optable); ++i)
1650169695Skan	    {
1651169695Skan	      size_t l = strlen (optable[i].in);
1652169695Skan
1653169695Skan	      if (l <= len
1654169695Skan		  && memcmp (optable[i].in, *mangled, l) == 0)
1655169695Skan		{
1656169695Skan		  string_appendn (s, " ", 1);
1657169695Skan		  string_append (s, optable[i].out);
1658169695Skan		  string_appendn (s, " ", 1);
1659169695Skan		  success = 1;
1660169695Skan		  (*mangled) += l;
1661169695Skan		  break;
1662169695Skan		}
1663169695Skan	    }
1664169695Skan
1665169695Skan	  if (!success)
1666169695Skan	    break;
1667169695Skan	}
1668169695Skan      else
1669169695Skan	need_operator = 1;
1670169695Skan
1671169695Skan      success = demangle_template_value_parm (work, mangled, s, tk);
1672169695Skan    }
1673169695Skan
1674169695Skan  if (**mangled != 'W')
1675169695Skan    success = 0;
1676169695Skan  else
1677169695Skan    {
1678169695Skan      string_appendn (s, ")", 1);
1679169695Skan      (*mangled)++;
1680169695Skan    }
1681169695Skan
1682169695Skan  return success;
1683169695Skan}
1684169695Skan
1685169695Skanstatic int
1686169695Skandemangle_integral_value (struct work_stuff *work,
1687169695Skan                         const char **mangled, string *s)
1688169695Skan{
1689169695Skan  int success;
1690169695Skan
1691169695Skan  if (**mangled == 'E')
1692169695Skan    success = demangle_expression (work, mangled, s, tk_integral);
1693169695Skan  else if (**mangled == 'Q' || **mangled == 'K')
1694169695Skan    success = demangle_qualified (work, mangled, s, 0, 1);
1695169695Skan  else
1696169695Skan    {
1697169695Skan      int value;
1698169695Skan
1699169695Skan      /* By default, we let the number decide whether we shall consume an
1700169695Skan	 underscore.  */
1701169695Skan      int multidigit_without_leading_underscore = 0;
1702169695Skan      int leave_following_underscore = 0;
1703169695Skan
1704169695Skan      success = 0;
1705169695Skan
1706169695Skan      if (**mangled == '_')
1707169695Skan        {
1708169695Skan	  if (mangled[0][1] == 'm')
1709169695Skan	    {
1710169695Skan	      /* Since consume_count_with_underscores does not handle the
1711169695Skan		 `m'-prefix we must do it here, using consume_count and
1712169695Skan		 adjusting underscores: we have to consume the underscore
1713169695Skan		 matching the prepended one.  */
1714169695Skan	      multidigit_without_leading_underscore = 1;
1715169695Skan	      string_appendn (s, "-", 1);
1716169695Skan	      (*mangled) += 2;
1717169695Skan	    }
1718169695Skan	  else
1719169695Skan	    {
1720169695Skan	      /* Do not consume a following underscore;
1721169695Skan	         consume_count_with_underscores will consume what
1722169695Skan	         should be consumed.  */
1723169695Skan	      leave_following_underscore = 1;
1724169695Skan	    }
1725169695Skan	}
1726169695Skan      else
1727169695Skan	{
1728169695Skan	  /* Negative numbers are indicated with a leading `m'.  */
1729169695Skan	  if (**mangled == 'm')
1730169695Skan	  {
1731169695Skan	    string_appendn (s, "-", 1);
1732169695Skan	    (*mangled)++;
1733169695Skan	  }
1734169695Skan	  /* Since consume_count_with_underscores does not handle
1735169695Skan	     multi-digit numbers that do not start with an underscore,
1736169695Skan	     and this number can be an integer template parameter,
1737169695Skan	     we have to call consume_count. */
1738169695Skan	  multidigit_without_leading_underscore = 1;
1739169695Skan	  /* These multi-digit numbers never end on an underscore,
1740169695Skan	     so if there is one then don't eat it. */
1741169695Skan	  leave_following_underscore = 1;
1742169695Skan	}
1743169695Skan
1744169695Skan      /* We must call consume_count if we expect to remove a trailing
1745169695Skan	 underscore, since consume_count_with_underscores expects
1746169695Skan	 the leading underscore (that we consumed) if it is to handle
1747169695Skan	 multi-digit numbers.  */
1748169695Skan      if (multidigit_without_leading_underscore)
1749169695Skan	value = consume_count (mangled);
1750169695Skan      else
1751169695Skan	value = consume_count_with_underscores (mangled);
1752169695Skan
1753169695Skan      if (value != -1)
1754169695Skan	{
1755169695Skan	  char buf[INTBUF_SIZE];
1756169695Skan	  sprintf (buf, "%d", value);
1757169695Skan	  string_append (s, buf);
1758169695Skan
1759169695Skan	  /* Numbers not otherwise delimited, might have an underscore
1760169695Skan	     appended as a delimeter, which we should skip.
1761169695Skan
1762169695Skan	     ??? This used to always remove a following underscore, which
1763169695Skan	     is wrong.  If other (arbitrary) cases are followed by an
1764169695Skan	     underscore, we need to do something more radical.  */
1765169695Skan
1766169695Skan	  if ((value > 9 || multidigit_without_leading_underscore)
1767169695Skan	      && ! leave_following_underscore
1768169695Skan	      && **mangled == '_')
1769169695Skan	    (*mangled)++;
1770169695Skan
1771169695Skan	  /* All is well.  */
1772169695Skan	  success = 1;
1773169695Skan	}
1774169695Skan      }
1775169695Skan
1776169695Skan  return success;
1777169695Skan}
1778169695Skan
1779169695Skan/* Demangle the real value in MANGLED.  */
1780169695Skan
1781169695Skanstatic int
1782169695Skandemangle_real_value (struct work_stuff *work,
1783169695Skan                     const char **mangled, string *s)
1784169695Skan{
1785169695Skan  if (**mangled == 'E')
1786169695Skan    return demangle_expression (work, mangled, s, tk_real);
1787169695Skan
1788169695Skan  if (**mangled == 'm')
1789169695Skan    {
1790169695Skan      string_appendn (s, "-", 1);
1791169695Skan      (*mangled)++;
1792169695Skan    }
1793169695Skan  while (ISDIGIT ((unsigned char)**mangled))
1794169695Skan    {
1795169695Skan      string_appendn (s, *mangled, 1);
1796169695Skan      (*mangled)++;
1797169695Skan    }
1798169695Skan  if (**mangled == '.') /* fraction */
1799169695Skan    {
1800169695Skan      string_appendn (s, ".", 1);
1801169695Skan      (*mangled)++;
1802169695Skan      while (ISDIGIT ((unsigned char)**mangled))
1803169695Skan	{
1804169695Skan	  string_appendn (s, *mangled, 1);
1805169695Skan	  (*mangled)++;
1806169695Skan	}
1807169695Skan    }
1808169695Skan  if (**mangled == 'e') /* exponent */
1809169695Skan    {
1810169695Skan      string_appendn (s, "e", 1);
1811169695Skan      (*mangled)++;
1812169695Skan      while (ISDIGIT ((unsigned char)**mangled))
1813169695Skan	{
1814169695Skan	  string_appendn (s, *mangled, 1);
1815169695Skan	  (*mangled)++;
1816169695Skan	}
1817169695Skan    }
1818169695Skan
1819169695Skan  return 1;
1820169695Skan}
1821169695Skan
1822169695Skanstatic int
1823169695Skandemangle_template_value_parm (struct work_stuff *work, const char **mangled,
1824169695Skan                              string *s, type_kind_t tk)
1825169695Skan{
1826169695Skan  int success = 1;
1827169695Skan
1828169695Skan  if (**mangled == 'Y')
1829169695Skan    {
1830169695Skan      /* The next argument is a template parameter. */
1831169695Skan      int idx;
1832169695Skan
1833169695Skan      (*mangled)++;
1834169695Skan      idx = consume_count_with_underscores (mangled);
1835169695Skan      if (idx == -1
1836169695Skan	  || (work->tmpl_argvec && idx >= work->ntmpl_args)
1837169695Skan	  || consume_count_with_underscores (mangled) == -1)
1838169695Skan	return -1;
1839169695Skan      if (work->tmpl_argvec)
1840169695Skan	string_append (s, work->tmpl_argvec[idx]);
1841169695Skan      else
1842169695Skan	string_append_template_idx (s, idx);
1843169695Skan    }
1844169695Skan  else if (tk == tk_integral)
1845169695Skan    success = demangle_integral_value (work, mangled, s);
1846169695Skan  else if (tk == tk_char)
1847169695Skan    {
1848169695Skan      char tmp[2];
1849169695Skan      int val;
1850169695Skan      if (**mangled == 'm')
1851169695Skan	{
1852169695Skan	  string_appendn (s, "-", 1);
1853169695Skan	  (*mangled)++;
1854169695Skan	}
1855169695Skan      string_appendn (s, "'", 1);
1856169695Skan      val = consume_count(mangled);
1857169695Skan      if (val <= 0)
1858169695Skan	success = 0;
1859169695Skan      else
1860169695Skan	{
1861169695Skan	  tmp[0] = (char)val;
1862169695Skan	  tmp[1] = '\0';
1863169695Skan	  string_appendn (s, &tmp[0], 1);
1864169695Skan	  string_appendn (s, "'", 1);
1865169695Skan	}
1866169695Skan    }
1867169695Skan  else if (tk == tk_bool)
1868169695Skan    {
1869169695Skan      int val = consume_count (mangled);
1870169695Skan      if (val == 0)
1871169695Skan	string_appendn (s, "false", 5);
1872169695Skan      else if (val == 1)
1873169695Skan	string_appendn (s, "true", 4);
1874169695Skan      else
1875169695Skan	success = 0;
1876169695Skan    }
1877169695Skan  else if (tk == tk_real)
1878169695Skan    success = demangle_real_value (work, mangled, s);
1879169695Skan  else if (tk == tk_pointer || tk == tk_reference)
1880169695Skan    {
1881169695Skan      if (**mangled == 'Q')
1882169695Skan	success = demangle_qualified (work, mangled, s,
1883169695Skan				      /*isfuncname=*/0,
1884169695Skan				      /*append=*/1);
1885169695Skan      else
1886169695Skan	{
1887169695Skan	  int symbol_len  = consume_count (mangled);
1888169695Skan	  if (symbol_len == -1)
1889169695Skan	    return -1;
1890169695Skan	  if (symbol_len == 0)
1891169695Skan	    string_appendn (s, "0", 1);
1892169695Skan	  else
1893169695Skan	    {
1894169695Skan	      char *p = XNEWVEC (char, symbol_len + 1), *q;
1895169695Skan	      strncpy (p, *mangled, symbol_len);
1896169695Skan	      p [symbol_len] = '\0';
1897169695Skan	      /* We use cplus_demangle here, rather than
1898169695Skan		 internal_cplus_demangle, because the name of the entity
1899169695Skan		 mangled here does not make use of any of the squangling
1900169695Skan		 or type-code information we have built up thus far; it is
1901169695Skan		 mangled independently.  */
1902169695Skan	      q = cplus_demangle (p, work->options);
1903169695Skan	      if (tk == tk_pointer)
1904169695Skan		string_appendn (s, "&", 1);
1905169695Skan	      /* FIXME: Pointer-to-member constants should get a
1906169695Skan		 qualifying class name here.  */
1907169695Skan	      if (q)
1908169695Skan		{
1909169695Skan		  string_append (s, q);
1910169695Skan		  free (q);
1911169695Skan		}
1912169695Skan	      else
1913169695Skan		string_append (s, p);
1914169695Skan	      free (p);
1915169695Skan	    }
1916169695Skan	  *mangled += symbol_len;
1917169695Skan	}
1918169695Skan    }
1919169695Skan
1920169695Skan  return success;
1921169695Skan}
1922169695Skan
1923169695Skan/* Demangle the template name in MANGLED.  The full name of the
1924169695Skan   template (e.g., S<int>) is placed in TNAME.  The name without the
1925169695Skan   template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
1926169695Skan   non-NULL.  If IS_TYPE is nonzero, this template is a type template,
1927169695Skan   not a function template.  If both IS_TYPE and REMEMBER are nonzero,
1928169695Skan   the template is remembered in the list of back-referenceable
1929169695Skan   types.  */
1930169695Skan
1931169695Skanstatic int
1932169695Skandemangle_template (struct work_stuff *work, const char **mangled,
1933169695Skan                   string *tname, string *trawname,
1934169695Skan                   int is_type, int remember)
1935169695Skan{
1936169695Skan  int i;
1937169695Skan  int r;
1938169695Skan  int need_comma = 0;
1939169695Skan  int success = 0;
1940169695Skan  int is_java_array = 0;
1941169695Skan  string temp;
1942169695Skan
1943169695Skan  (*mangled)++;
1944169695Skan  if (is_type)
1945169695Skan    {
1946169695Skan      /* get template name */
1947169695Skan      if (**mangled == 'z')
1948169695Skan	{
1949169695Skan	  int idx;
1950169695Skan	  (*mangled)++;
1951169695Skan	  (*mangled)++;
1952169695Skan
1953169695Skan	  idx = consume_count_with_underscores (mangled);
1954169695Skan	  if (idx == -1
1955169695Skan	      || (work->tmpl_argvec && idx >= work->ntmpl_args)
1956169695Skan	      || consume_count_with_underscores (mangled) == -1)
1957169695Skan	    return (0);
1958169695Skan
1959169695Skan	  if (work->tmpl_argvec)
1960169695Skan	    {
1961169695Skan	      string_append (tname, work->tmpl_argvec[idx]);
1962169695Skan	      if (trawname)
1963169695Skan		string_append (trawname, work->tmpl_argvec[idx]);
1964169695Skan	    }
1965169695Skan	  else
1966169695Skan	    {
1967169695Skan	      string_append_template_idx (tname, idx);
1968169695Skan	      if (trawname)
1969169695Skan		string_append_template_idx (trawname, idx);
1970169695Skan	    }
1971169695Skan	}
1972169695Skan      else
1973169695Skan	{
1974169695Skan	  if ((r = consume_count (mangled)) <= 0
1975169695Skan	      || (int) strlen (*mangled) < r)
1976169695Skan	    {
1977169695Skan	      return (0);
1978169695Skan	    }
1979169695Skan	  is_java_array = (work -> options & DMGL_JAVA)
1980169695Skan	    && strncmp (*mangled, "JArray1Z", 8) == 0;
1981169695Skan	  if (! is_java_array)
1982169695Skan	    {
1983169695Skan	      string_appendn (tname, *mangled, r);
1984169695Skan	    }
1985169695Skan	  if (trawname)
1986169695Skan	    string_appendn (trawname, *mangled, r);
1987169695Skan	  *mangled += r;
1988169695Skan	}
1989169695Skan    }
1990169695Skan  if (!is_java_array)
1991169695Skan    string_append (tname, "<");
1992169695Skan  /* get size of template parameter list */
1993169695Skan  if (!get_count (mangled, &r))
1994169695Skan    {
1995169695Skan      return (0);
1996169695Skan    }
1997169695Skan  if (!is_type)
1998169695Skan    {
1999169695Skan      /* Create an array for saving the template argument values. */
2000169695Skan      work->tmpl_argvec = XNEWVEC (char *, r);
2001169695Skan      work->ntmpl_args = r;
2002169695Skan      for (i = 0; i < r; i++)
2003169695Skan	work->tmpl_argvec[i] = 0;
2004169695Skan    }
2005169695Skan  for (i = 0; i < r; i++)
2006169695Skan    {
2007169695Skan      if (need_comma)
2008169695Skan	{
2009169695Skan	  string_append (tname, ", ");
2010169695Skan	}
2011169695Skan      /* Z for type parameters */
2012169695Skan      if (**mangled == 'Z')
2013169695Skan	{
2014169695Skan	  (*mangled)++;
2015169695Skan	  /* temp is initialized in do_type */
2016169695Skan	  success = do_type (work, mangled, &temp);
2017169695Skan	  if (success)
2018169695Skan	    {
2019169695Skan	      string_appends (tname, &temp);
2020169695Skan
2021169695Skan	      if (!is_type)
2022169695Skan		{
2023169695Skan		  /* Save the template argument. */
2024169695Skan		  int len = temp.p - temp.b;
2025169695Skan		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
2026169695Skan		  memcpy (work->tmpl_argvec[i], temp.b, len);
2027169695Skan		  work->tmpl_argvec[i][len] = '\0';
2028169695Skan		}
2029169695Skan	    }
2030169695Skan	  string_delete(&temp);
2031169695Skan	  if (!success)
2032169695Skan	    {
2033169695Skan	      break;
2034169695Skan	    }
2035169695Skan	}
2036169695Skan      /* z for template parameters */
2037169695Skan      else if (**mangled == 'z')
2038169695Skan	{
2039169695Skan	  int r2;
2040169695Skan	  (*mangled)++;
2041169695Skan	  success = demangle_template_template_parm (work, mangled, tname);
2042169695Skan
2043169695Skan	  if (success
2044169695Skan	      && (r2 = consume_count (mangled)) > 0
2045169695Skan	      && (int) strlen (*mangled) >= r2)
2046169695Skan	    {
2047169695Skan	      string_append (tname, " ");
2048169695Skan	      string_appendn (tname, *mangled, r2);
2049169695Skan	      if (!is_type)
2050169695Skan		{
2051169695Skan		  /* Save the template argument. */
2052169695Skan		  int len = r2;
2053169695Skan		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
2054169695Skan		  memcpy (work->tmpl_argvec[i], *mangled, len);
2055169695Skan		  work->tmpl_argvec[i][len] = '\0';
2056169695Skan		}
2057169695Skan	      *mangled += r2;
2058169695Skan	    }
2059169695Skan	  if (!success)
2060169695Skan	    {
2061169695Skan	      break;
2062169695Skan	    }
2063169695Skan	}
2064169695Skan      else
2065169695Skan	{
2066169695Skan	  string  param;
2067169695Skan	  string* s;
2068169695Skan
2069169695Skan	  /* otherwise, value parameter */
2070169695Skan
2071169695Skan	  /* temp is initialized in do_type */
2072169695Skan	  success = do_type (work, mangled, &temp);
2073169695Skan	  string_delete(&temp);
2074169695Skan	  if (!success)
2075169695Skan	    break;
2076169695Skan
2077169695Skan	  if (!is_type)
2078169695Skan	    {
2079169695Skan	      s = &param;
2080169695Skan	      string_init (s);
2081169695Skan	    }
2082169695Skan	  else
2083169695Skan	    s = tname;
2084169695Skan
2085169695Skan	  success = demangle_template_value_parm (work, mangled, s,
2086169695Skan						  (type_kind_t) success);
2087169695Skan
2088169695Skan	  if (!success)
2089169695Skan	    {
2090169695Skan	      if (!is_type)
2091169695Skan		string_delete (s);
2092169695Skan	      success = 0;
2093169695Skan	      break;
2094169695Skan	    }
2095169695Skan
2096169695Skan	  if (!is_type)
2097169695Skan	    {
2098169695Skan	      int len = s->p - s->b;
2099169695Skan	      work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
2100169695Skan	      memcpy (work->tmpl_argvec[i], s->b, len);
2101169695Skan	      work->tmpl_argvec[i][len] = '\0';
2102169695Skan
2103169695Skan	      string_appends (tname, s);
2104169695Skan	      string_delete (s);
2105169695Skan	    }
2106169695Skan	}
2107169695Skan      need_comma = 1;
2108169695Skan    }
2109169695Skan  if (is_java_array)
2110169695Skan    {
2111169695Skan      string_append (tname, "[]");
2112169695Skan    }
2113169695Skan  else
2114169695Skan    {
2115169695Skan      if (tname->p[-1] == '>')
2116169695Skan	string_append (tname, " ");
2117169695Skan      string_append (tname, ">");
2118169695Skan    }
2119169695Skan
2120169695Skan  if (is_type && remember)
2121169695Skan    {
2122169695Skan      const int bindex = register_Btype (work);
2123169695Skan      remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
2124169695Skan    }
2125169695Skan
2126169695Skan  /*
2127169695Skan    if (work -> static_type)
2128169695Skan    {
2129169695Skan    string_append (declp, *mangled + 1);
2130169695Skan    *mangled += strlen (*mangled);
2131169695Skan    success = 1;
2132169695Skan    }
2133169695Skan    else
2134169695Skan    {
2135169695Skan    success = demangle_args (work, mangled, declp);
2136169695Skan    }
2137169695Skan    }
2138169695Skan    */
2139169695Skan  return (success);
2140169695Skan}
2141169695Skan
2142169695Skanstatic int
2143169695Skanarm_pt (struct work_stuff *work, const char *mangled,
2144169695Skan        int n, const char **anchor, const char **args)
2145169695Skan{
2146169695Skan  /* Check if ARM template with "__pt__" in it ("parameterized type") */
2147169695Skan  /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
2148169695Skan  if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
2149169695Skan    {
2150169695Skan      int len;
2151169695Skan      *args = *anchor + 6;
2152169695Skan      len = consume_count (args);
2153169695Skan      if (len == -1)
2154169695Skan	return 0;
2155169695Skan      if (*args + len == mangled + n && **args == '_')
2156169695Skan	{
2157169695Skan	  ++*args;
2158169695Skan	  return 1;
2159169695Skan	}
2160169695Skan    }
2161169695Skan  if (AUTO_DEMANGLING || EDG_DEMANGLING)
2162169695Skan    {
2163169695Skan      if ((*anchor = strstr (mangled, "__tm__"))
2164169695Skan          || (*anchor = strstr (mangled, "__ps__"))
2165169695Skan          || (*anchor = strstr (mangled, "__pt__")))
2166169695Skan        {
2167169695Skan          int len;
2168169695Skan          *args = *anchor + 6;
2169169695Skan          len = consume_count (args);
2170169695Skan	  if (len == -1)
2171169695Skan	    return 0;
2172169695Skan          if (*args + len == mangled + n && **args == '_')
2173169695Skan            {
2174169695Skan              ++*args;
2175169695Skan              return 1;
2176169695Skan            }
2177169695Skan        }
2178169695Skan      else if ((*anchor = strstr (mangled, "__S")))
2179169695Skan        {
2180169695Skan 	  int len;
2181169695Skan 	  *args = *anchor + 3;
2182169695Skan 	  len = consume_count (args);
2183169695Skan	  if (len == -1)
2184169695Skan	    return 0;
2185169695Skan 	  if (*args + len == mangled + n && **args == '_')
2186169695Skan            {
2187169695Skan              ++*args;
2188169695Skan 	      return 1;
2189169695Skan            }
2190169695Skan        }
2191169695Skan    }
2192169695Skan
2193169695Skan  return 0;
2194169695Skan}
2195169695Skan
2196169695Skanstatic void
2197169695Skandemangle_arm_hp_template (struct work_stuff *work, const char **mangled,
2198169695Skan                          int n, string *declp)
2199169695Skan{
2200169695Skan  const char *p;
2201169695Skan  const char *args;
2202169695Skan  const char *e = *mangled + n;
2203169695Skan  string arg;
2204169695Skan
2205169695Skan  /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
2206169695Skan     template args */
2207169695Skan  if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
2208169695Skan    {
2209169695Skan      char *start_spec_args = NULL;
2210169695Skan      int hold_options;
2211169695Skan
2212169695Skan      /* First check for and omit template specialization pseudo-arguments,
2213169695Skan         such as in "Spec<#1,#1.*>" */
2214169695Skan      start_spec_args = strchr (*mangled, '<');
2215169695Skan      if (start_spec_args && (start_spec_args - *mangled < n))
2216169695Skan        string_appendn (declp, *mangled, start_spec_args - *mangled);
2217169695Skan      else
2218169695Skan        string_appendn (declp, *mangled, n);
2219169695Skan      (*mangled) += n + 1;
2220169695Skan      string_init (&arg);
2221169695Skan      if (work->temp_start == -1) /* non-recursive call */
2222169695Skan        work->temp_start = declp->p - declp->b;
2223169695Skan
2224169695Skan      /* We want to unconditionally demangle parameter types in
2225169695Skan	 template parameters.  */
2226169695Skan      hold_options = work->options;
2227169695Skan      work->options |= DMGL_PARAMS;
2228169695Skan
2229169695Skan      string_append (declp, "<");
2230169695Skan      while (1)
2231169695Skan        {
2232169695Skan          string_delete (&arg);
2233169695Skan          switch (**mangled)
2234169695Skan            {
2235169695Skan              case 'T':
2236169695Skan                /* 'T' signals a type parameter */
2237169695Skan                (*mangled)++;
2238169695Skan                if (!do_type (work, mangled, &arg))
2239169695Skan                  goto hpacc_template_args_done;
2240169695Skan                break;
2241169695Skan
2242169695Skan              case 'U':
2243169695Skan              case 'S':
2244169695Skan                /* 'U' or 'S' signals an integral value */
2245169695Skan                if (!do_hpacc_template_const_value (work, mangled, &arg))
2246169695Skan                  goto hpacc_template_args_done;
2247169695Skan                break;
2248169695Skan
2249169695Skan              case 'A':
2250169695Skan                /* 'A' signals a named constant expression (literal) */
2251169695Skan                if (!do_hpacc_template_literal (work, mangled, &arg))
2252169695Skan                  goto hpacc_template_args_done;
2253169695Skan                break;
2254169695Skan
2255169695Skan              default:
2256169695Skan                /* Today, 1997-09-03, we have only the above types
2257169695Skan                   of template parameters */
2258169695Skan                /* FIXME: maybe this should fail and return null */
2259169695Skan                goto hpacc_template_args_done;
2260169695Skan            }
2261169695Skan          string_appends (declp, &arg);
2262169695Skan         /* Check if we're at the end of template args.
2263169695Skan             0 if at end of static member of template class,
2264169695Skan             _ if done with template args for a function */
2265169695Skan          if ((**mangled == '\000') || (**mangled == '_'))
2266169695Skan            break;
2267169695Skan          else
2268169695Skan            string_append (declp, ",");
2269169695Skan        }
2270169695Skan    hpacc_template_args_done:
2271169695Skan      string_append (declp, ">");
2272169695Skan      string_delete (&arg);
2273169695Skan      if (**mangled == '_')
2274169695Skan        (*mangled)++;
2275169695Skan      work->options = hold_options;
2276169695Skan      return;
2277169695Skan    }
2278169695Skan  /* ARM template? (Also handles HP cfront extensions) */
2279169695Skan  else if (arm_pt (work, *mangled, n, &p, &args))
2280169695Skan    {
2281169695Skan      int hold_options;
2282169695Skan      string type_str;
2283169695Skan
2284169695Skan      string_init (&arg);
2285169695Skan      string_appendn (declp, *mangled, p - *mangled);
2286169695Skan      if (work->temp_start == -1)  /* non-recursive call */
2287169695Skan	work->temp_start = declp->p - declp->b;
2288169695Skan
2289169695Skan      /* We want to unconditionally demangle parameter types in
2290169695Skan	 template parameters.  */
2291169695Skan      hold_options = work->options;
2292169695Skan      work->options |= DMGL_PARAMS;
2293169695Skan
2294169695Skan      string_append (declp, "<");
2295169695Skan      /* should do error checking here */
2296169695Skan      while (args < e) {
2297169695Skan	string_delete (&arg);
2298169695Skan
2299169695Skan	/* Check for type or literal here */
2300169695Skan	switch (*args)
2301169695Skan	  {
2302169695Skan	    /* HP cfront extensions to ARM for template args */
2303169695Skan	    /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
2304169695Skan	    /* FIXME: We handle only numeric literals for HP cfront */
2305169695Skan          case 'X':
2306169695Skan            /* A typed constant value follows */
2307169695Skan            args++;
2308169695Skan            if (!do_type (work, &args, &type_str))
2309169695Skan	      goto cfront_template_args_done;
2310169695Skan            string_append (&arg, "(");
2311169695Skan            string_appends (&arg, &type_str);
2312169695Skan            string_delete (&type_str);
2313169695Skan            string_append (&arg, ")");
2314169695Skan            if (*args != 'L')
2315169695Skan              goto cfront_template_args_done;
2316169695Skan            args++;
2317169695Skan            /* Now snarf a literal value following 'L' */
2318169695Skan            if (!snarf_numeric_literal (&args, &arg))
2319169695Skan	      goto cfront_template_args_done;
2320169695Skan            break;
2321169695Skan
2322169695Skan          case 'L':
2323169695Skan            /* Snarf a literal following 'L' */
2324169695Skan            args++;
2325169695Skan            if (!snarf_numeric_literal (&args, &arg))
2326169695Skan	      goto cfront_template_args_done;
2327169695Skan            break;
2328169695Skan          default:
2329169695Skan            /* Not handling other HP cfront stuff */
2330169695Skan            {
2331169695Skan              const char* old_args = args;
2332169695Skan              if (!do_type (work, &args, &arg))
2333169695Skan                goto cfront_template_args_done;
2334169695Skan
2335169695Skan              /* Fail if we didn't make any progress: prevent infinite loop. */
2336169695Skan              if (args == old_args)
2337169695Skan		{
2338169695Skan		  work->options = hold_options;
2339169695Skan		  return;
2340169695Skan		}
2341169695Skan            }
2342169695Skan	  }
2343169695Skan	string_appends (declp, &arg);
2344169695Skan	string_append (declp, ",");
2345169695Skan      }
2346169695Skan    cfront_template_args_done:
2347169695Skan      string_delete (&arg);
2348169695Skan      if (args >= e)
2349169695Skan	--declp->p; /* remove extra comma */
2350169695Skan      string_append (declp, ">");
2351169695Skan      work->options = hold_options;
2352169695Skan    }
2353169695Skan  else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
2354169695Skan	   && (*mangled)[9] == 'N'
2355169695Skan	   && (*mangled)[8] == (*mangled)[10]
2356169695Skan	   && strchr (cplus_markers, (*mangled)[8]))
2357169695Skan    {
2358169695Skan      /* A member of the anonymous namespace.  */
2359169695Skan      string_append (declp, "{anonymous}");
2360169695Skan    }
2361169695Skan  else
2362169695Skan    {
2363169695Skan      if (work->temp_start == -1) /* non-recursive call only */
2364169695Skan	work->temp_start = 0;     /* disable in recursive calls */
2365169695Skan      string_appendn (declp, *mangled, n);
2366169695Skan    }
2367169695Skan  *mangled += n;
2368169695Skan}
2369169695Skan
2370169695Skan/* Extract a class name, possibly a template with arguments, from the
2371169695Skan   mangled string; qualifiers, local class indicators, etc. have
2372169695Skan   already been dealt with */
2373169695Skan
2374169695Skanstatic int
2375169695Skandemangle_class_name (struct work_stuff *work, const char **mangled,
2376169695Skan                     string *declp)
2377169695Skan{
2378169695Skan  int n;
2379169695Skan  int success = 0;
2380169695Skan
2381169695Skan  n = consume_count (mangled);
2382169695Skan  if (n == -1)
2383169695Skan    return 0;
2384169695Skan  if ((int) strlen (*mangled) >= n)
2385169695Skan    {
2386169695Skan      demangle_arm_hp_template (work, mangled, n, declp);
2387169695Skan      success = 1;
2388169695Skan    }
2389169695Skan
2390169695Skan  return (success);
2391169695Skan}
2392169695Skan
2393169695Skan/*
2394169695Skan
2395169695SkanLOCAL FUNCTION
2396169695Skan
2397169695Skan	demangle_class -- demangle a mangled class sequence
2398169695Skan
2399169695SkanSYNOPSIS
2400169695Skan
2401169695Skan	static int
2402169695Skan	demangle_class (struct work_stuff *work, const char **mangled,
2403169695Skan			strint *declp)
2404169695Skan
2405169695SkanDESCRIPTION
2406169695Skan
2407169695Skan	DECLP points to the buffer into which demangling is being done.
2408169695Skan
2409169695Skan	*MANGLED points to the current token to be demangled.  On input,
2410169695Skan	it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
2411169695Skan	On exit, it points to the next token after the mangled class on
2412169695Skan	success, or the first unconsumed token on failure.
2413169695Skan
2414169695Skan	If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
2415169695Skan	we are demangling a constructor or destructor.  In this case
2416169695Skan	we prepend "class::class" or "class::~class" to DECLP.
2417169695Skan
2418169695Skan	Otherwise, we prepend "class::" to the current DECLP.
2419169695Skan
2420169695Skan	Reset the constructor/destructor flags once they have been
2421169695Skan	"consumed".  This allows demangle_class to be called later during
2422169695Skan	the same demangling, to do normal class demangling.
2423169695Skan
2424169695Skan	Returns 1 if demangling is successful, 0 otherwise.
2425169695Skan
2426169695Skan*/
2427169695Skan
2428169695Skanstatic int
2429169695Skandemangle_class (struct work_stuff *work, const char **mangled, string *declp)
2430169695Skan{
2431169695Skan  int success = 0;
2432169695Skan  int btype;
2433169695Skan  string class_name;
2434169695Skan  char *save_class_name_end = 0;
2435169695Skan
2436169695Skan  string_init (&class_name);
2437169695Skan  btype = register_Btype (work);
2438169695Skan  if (demangle_class_name (work, mangled, &class_name))
2439169695Skan    {
2440169695Skan      save_class_name_end = class_name.p;
2441169695Skan      if ((work->constructor & 1) || (work->destructor & 1))
2442169695Skan	{
2443169695Skan          /* adjust so we don't include template args */
2444169695Skan          if (work->temp_start && (work->temp_start != -1))
2445169695Skan            {
2446169695Skan              class_name.p = class_name.b + work->temp_start;
2447169695Skan            }
2448169695Skan	  string_prepends (declp, &class_name);
2449169695Skan	  if (work -> destructor & 1)
2450169695Skan	    {
2451169695Skan	      string_prepend (declp, "~");
2452169695Skan              work -> destructor -= 1;
2453169695Skan	    }
2454169695Skan	  else
2455169695Skan	    {
2456169695Skan	      work -> constructor -= 1;
2457169695Skan	    }
2458169695Skan	}
2459169695Skan      class_name.p = save_class_name_end;
2460169695Skan      remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
2461169695Skan      remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
2462169695Skan      string_prepend (declp, SCOPE_STRING (work));
2463169695Skan      string_prepends (declp, &class_name);
2464169695Skan      success = 1;
2465169695Skan    }
2466169695Skan  string_delete (&class_name);
2467169695Skan  return (success);
2468169695Skan}
2469169695Skan
2470169695Skan
2471169695Skan/* Called when there's a "__" in the mangled name, with `scan' pointing to
2472169695Skan   the rightmost guess.
2473169695Skan
2474169695Skan   Find the correct "__"-sequence where the function name ends and the
2475169695Skan   signature starts, which is ambiguous with GNU mangling.
2476169695Skan   Call demangle_signature here, so we can make sure we found the right
2477169695Skan   one; *mangled will be consumed so caller will not make further calls to
2478169695Skan   demangle_signature.  */
2479169695Skan
2480169695Skanstatic int
2481169695Skaniterate_demangle_function (struct work_stuff *work, const char **mangled,
2482169695Skan                           string *declp, const char *scan)
2483169695Skan{
2484169695Skan  const char *mangle_init = *mangled;
2485169695Skan  int success = 0;
2486169695Skan  string decl_init;
2487169695Skan  struct work_stuff work_init;
2488169695Skan
2489169695Skan  if (*(scan + 2) == '\0')
2490169695Skan    return 0;
2491169695Skan
2492169695Skan  /* Do not iterate for some demangling modes, or if there's only one
2493169695Skan     "__"-sequence.  This is the normal case.  */
2494169695Skan  if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
2495169695Skan      || strstr (scan + 2, "__") == NULL)
2496169695Skan    {
2497169695Skan      demangle_function_name (work, mangled, declp, scan);
2498169695Skan      return 1;
2499169695Skan    }
2500169695Skan
2501169695Skan  /* Save state so we can restart if the guess at the correct "__" was
2502169695Skan     wrong.  */
2503169695Skan  string_init (&decl_init);
2504169695Skan  string_appends (&decl_init, declp);
2505169695Skan  memset (&work_init, 0, sizeof work_init);
2506169695Skan  work_stuff_copy_to_from (&work_init, work);
2507169695Skan
2508169695Skan  /* Iterate over occurrences of __, allowing names and types to have a
2509169695Skan     "__" sequence in them.  We must start with the first (not the last)
2510169695Skan     occurrence, since "__" most often occur between independent mangled
2511169695Skan     parts, hence starting at the last occurence inside a signature
2512169695Skan     might get us a "successful" demangling of the signature.  */
2513169695Skan
2514169695Skan  while (scan[2])
2515169695Skan    {
2516169695Skan      demangle_function_name (work, mangled, declp, scan);
2517169695Skan      success = demangle_signature (work, mangled, declp);
2518169695Skan      if (success)
2519169695Skan	break;
2520169695Skan
2521169695Skan      /* Reset demangle state for the next round.  */
2522169695Skan      *mangled = mangle_init;
2523169695Skan      string_clear (declp);
2524169695Skan      string_appends (declp, &decl_init);
2525169695Skan      work_stuff_copy_to_from (work, &work_init);
2526169695Skan
2527169695Skan      /* Leave this underscore-sequence.  */
2528169695Skan      scan += 2;
2529169695Skan
2530169695Skan      /* Scan for the next "__" sequence.  */
2531169695Skan      while (*scan && (scan[0] != '_' || scan[1] != '_'))
2532169695Skan	scan++;
2533169695Skan
2534169695Skan      /* Move to last "__" in this sequence.  */
2535169695Skan      while (*scan && *scan == '_')
2536169695Skan	scan++;
2537169695Skan      scan -= 2;
2538169695Skan    }
2539169695Skan
2540169695Skan  /* Delete saved state.  */
2541169695Skan  delete_work_stuff (&work_init);
2542169695Skan  string_delete (&decl_init);
2543169695Skan
2544169695Skan  return success;
2545169695Skan}
2546169695Skan
2547169695Skan/*
2548169695Skan
2549169695SkanLOCAL FUNCTION
2550169695Skan
2551169695Skan	demangle_prefix -- consume the mangled name prefix and find signature
2552169695Skan
2553169695SkanSYNOPSIS
2554169695Skan
2555169695Skan	static int
2556169695Skan	demangle_prefix (struct work_stuff *work, const char **mangled,
2557169695Skan			 string *declp);
2558169695Skan
2559169695SkanDESCRIPTION
2560169695Skan
2561169695Skan	Consume and demangle the prefix of the mangled name.
2562169695Skan	While processing the function name root, arrange to call
2563169695Skan	demangle_signature if the root is ambiguous.
2564169695Skan
2565169695Skan	DECLP points to the string buffer into which demangled output is
2566169695Skan	placed.  On entry, the buffer is empty.  On exit it contains
2567169695Skan	the root function name, the demangled operator name, or in some
2568169695Skan	special cases either nothing or the completely demangled result.
2569169695Skan
2570169695Skan	MANGLED points to the current pointer into the mangled name.  As each
2571169695Skan	token of the mangled name is consumed, it is updated.  Upon entry
2572169695Skan	the current mangled name pointer points to the first character of
2573169695Skan	the mangled name.  Upon exit, it should point to the first character
2574169695Skan	of the signature if demangling was successful, or to the first
2575169695Skan	unconsumed character if demangling of the prefix was unsuccessful.
2576169695Skan
2577169695Skan	Returns 1 on success, 0 otherwise.
2578169695Skan */
2579169695Skan
2580169695Skanstatic int
2581169695Skandemangle_prefix (struct work_stuff *work, const char **mangled,
2582169695Skan                 string *declp)
2583169695Skan{
2584169695Skan  int success = 1;
2585169695Skan  const char *scan;
2586169695Skan  int i;
2587169695Skan
2588169695Skan  if (strlen(*mangled) > 6
2589169695Skan      && (strncmp(*mangled, "_imp__", 6) == 0
2590169695Skan          || strncmp(*mangled, "__imp_", 6) == 0))
2591169695Skan    {
2592169695Skan      /* it's a symbol imported from a PE dynamic library. Check for both
2593169695Skan         new style prefix _imp__ and legacy __imp_ used by older versions
2594169695Skan	 of dlltool. */
2595169695Skan      (*mangled) += 6;
2596169695Skan      work->dllimported = 1;
2597169695Skan    }
2598169695Skan  else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
2599169695Skan    {
2600169695Skan      char *marker = strchr (cplus_markers, (*mangled)[8]);
2601169695Skan      if (marker != NULL && *marker == (*mangled)[10])
2602169695Skan	{
2603169695Skan	  if ((*mangled)[9] == 'D')
2604169695Skan	    {
2605169695Skan	      /* it's a GNU global destructor to be executed at program exit */
2606169695Skan	      (*mangled) += 11;
2607169695Skan	      work->destructor = 2;
2608169695Skan	      if (gnu_special (work, mangled, declp))
2609169695Skan		return success;
2610169695Skan	    }
2611169695Skan	  else if ((*mangled)[9] == 'I')
2612169695Skan	    {
2613169695Skan	      /* it's a GNU global constructor to be executed at program init */
2614169695Skan	      (*mangled) += 11;
2615169695Skan	      work->constructor = 2;
2616169695Skan	      if (gnu_special (work, mangled, declp))
2617169695Skan		return success;
2618169695Skan	    }
2619169695Skan	}
2620169695Skan    }
2621169695Skan  else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
2622169695Skan    {
2623169695Skan      /* it's a ARM global destructor to be executed at program exit */
2624169695Skan      (*mangled) += 7;
2625169695Skan      work->destructor = 2;
2626169695Skan    }
2627169695Skan  else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
2628169695Skan    {
2629169695Skan      /* it's a ARM global constructor to be executed at program initial */
2630169695Skan      (*mangled) += 7;
2631169695Skan      work->constructor = 2;
2632169695Skan    }
2633169695Skan
2634169695Skan  /*  This block of code is a reduction in strength time optimization
2635169695Skan      of:
2636169695Skan      scan = strstr (*mangled, "__"); */
2637169695Skan
2638169695Skan  {
2639169695Skan    scan = *mangled;
2640169695Skan
2641169695Skan    do {
2642169695Skan      scan = strchr (scan, '_');
2643169695Skan    } while (scan != NULL && *++scan != '_');
2644169695Skan
2645169695Skan    if (scan != NULL) --scan;
2646169695Skan  }
2647169695Skan
2648169695Skan  if (scan != NULL)
2649169695Skan    {
2650169695Skan      /* We found a sequence of two or more '_', ensure that we start at
2651169695Skan	 the last pair in the sequence.  */
2652169695Skan      i = strspn (scan, "_");
2653169695Skan      if (i > 2)
2654169695Skan	{
2655169695Skan	  scan += (i - 2);
2656169695Skan	}
2657169695Skan    }
2658169695Skan
2659169695Skan  if (scan == NULL)
2660169695Skan    {
2661169695Skan      success = 0;
2662169695Skan    }
2663169695Skan  else if (work -> static_type)
2664169695Skan    {
2665169695Skan      if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
2666169695Skan	{
2667169695Skan	  success = 0;
2668169695Skan	}
2669169695Skan    }
2670169695Skan  else if ((scan == *mangled)
2671169695Skan	   && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
2672169695Skan	       || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
2673169695Skan    {
2674169695Skan      /* The ARM says nothing about the mangling of local variables.
2675169695Skan	 But cfront mangles local variables by prepending __<nesting_level>
2676169695Skan	 to them. As an extension to ARM demangling we handle this case.  */
2677169695Skan      if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
2678169695Skan	  && ISDIGIT ((unsigned char)scan[2]))
2679169695Skan	{
2680169695Skan	  *mangled = scan + 2;
2681169695Skan	  consume_count (mangled);
2682169695Skan	  string_append (declp, *mangled);
2683169695Skan	  *mangled += strlen (*mangled);
2684169695Skan	  success = 1;
2685169695Skan	}
2686169695Skan      else
2687169695Skan	{
2688169695Skan	  /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
2689169695Skan	     names like __Q2_3foo3bar for nested type names.  So don't accept
2690169695Skan	     this style of constructor for cfront demangling.  A GNU
2691169695Skan	     style member-template constructor starts with 'H'. */
2692169695Skan	  if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
2693169695Skan	    work -> constructor += 1;
2694169695Skan	  *mangled = scan + 2;
2695169695Skan	}
2696169695Skan    }
2697169695Skan  else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
2698169695Skan    {
2699169695Skan      /* Cfront-style parameterized type.  Handled later as a signature. */
2700169695Skan      success = 1;
2701169695Skan
2702169695Skan      /* ARM template? */
2703169695Skan      demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
2704169695Skan    }
2705169695Skan  else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
2706169695Skan                              || (scan[2] == 'p' && scan[3] == 's')
2707169695Skan                              || (scan[2] == 'p' && scan[3] == 't')))
2708169695Skan    {
2709169695Skan      /* EDG-style parameterized type.  Handled later as a signature. */
2710169695Skan      success = 1;
2711169695Skan
2712169695Skan      /* EDG template? */
2713169695Skan      demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
2714169695Skan    }
2715169695Skan  else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
2716169695Skan	   && (scan[2] != 't'))
2717169695Skan    {
2718169695Skan      /* Mangled name starts with "__".  Skip over any leading '_' characters,
2719169695Skan	 then find the next "__" that separates the prefix from the signature.
2720169695Skan	 */
2721169695Skan      if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
2722169695Skan	  || (arm_special (mangled, declp) == 0))
2723169695Skan	{
2724169695Skan	  while (*scan == '_')
2725169695Skan	    {
2726169695Skan	      scan++;
2727169695Skan	    }
2728169695Skan	  if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
2729169695Skan	    {
2730169695Skan	      /* No separator (I.E. "__not_mangled"), or empty signature
2731169695Skan		 (I.E. "__not_mangled_either__") */
2732169695Skan	      success = 0;
2733169695Skan	    }
2734169695Skan	  else
2735169695Skan	    return iterate_demangle_function (work, mangled, declp, scan);
2736169695Skan	}
2737169695Skan    }
2738169695Skan  else if (*(scan + 2) != '\0')
2739169695Skan    {
2740169695Skan      /* Mangled name does not start with "__" but does have one somewhere
2741169695Skan	 in there with non empty stuff after it.  Looks like a global
2742169695Skan	 function name.  Iterate over all "__":s until the right
2743169695Skan	 one is found.  */
2744169695Skan      return iterate_demangle_function (work, mangled, declp, scan);
2745169695Skan    }
2746169695Skan  else
2747169695Skan    {
2748169695Skan      /* Doesn't look like a mangled name */
2749169695Skan      success = 0;
2750169695Skan    }
2751169695Skan
2752169695Skan  if (!success && (work->constructor == 2 || work->destructor == 2))
2753169695Skan    {
2754169695Skan      string_append (declp, *mangled);
2755169695Skan      *mangled += strlen (*mangled);
2756169695Skan      success = 1;
2757169695Skan    }
2758169695Skan  return (success);
2759169695Skan}
2760169695Skan
2761169695Skan/*
2762169695Skan
2763169695SkanLOCAL FUNCTION
2764169695Skan
2765169695Skan	gnu_special -- special handling of gnu mangled strings
2766169695Skan
2767169695SkanSYNOPSIS
2768169695Skan
2769169695Skan	static int
2770169695Skan	gnu_special (struct work_stuff *work, const char **mangled,
2771169695Skan		     string *declp);
2772169695Skan
2773169695Skan
2774169695SkanDESCRIPTION
2775169695Skan
2776169695Skan	Process some special GNU style mangling forms that don't fit
2777169695Skan	the normal pattern.  For example:
2778169695Skan
2779169695Skan		_$_3foo		(destructor for class foo)
2780169695Skan		_vt$foo		(foo virtual table)
2781169695Skan		_vt$foo$bar	(foo::bar virtual table)
2782169695Skan		__vt_foo	(foo virtual table, new style with thunks)
2783169695Skan		_3foo$varname	(static data member)
2784169695Skan		_Q22rs2tu$vw	(static data member)
2785169695Skan		__t6vector1Zii	(constructor with template)
2786169695Skan		__thunk_4__$_7ostream (virtual function thunk)
2787169695Skan */
2788169695Skan
2789169695Skanstatic int
2790169695Skangnu_special (struct work_stuff *work, const char **mangled, string *declp)
2791169695Skan{
2792169695Skan  int n;
2793169695Skan  int success = 1;
2794169695Skan  const char *p;
2795169695Skan
2796169695Skan  if ((*mangled)[0] == '_'
2797169695Skan      && strchr (cplus_markers, (*mangled)[1]) != NULL
2798169695Skan      && (*mangled)[2] == '_')
2799169695Skan    {
2800169695Skan      /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
2801169695Skan      (*mangled) += 3;
2802169695Skan      work -> destructor += 1;
2803169695Skan    }
2804169695Skan  else if ((*mangled)[0] == '_'
2805169695Skan	   && (((*mangled)[1] == '_'
2806169695Skan		&& (*mangled)[2] == 'v'
2807169695Skan		&& (*mangled)[3] == 't'
2808169695Skan		&& (*mangled)[4] == '_')
2809169695Skan	       || ((*mangled)[1] == 'v'
2810169695Skan		   && (*mangled)[2] == 't'
2811169695Skan		   && strchr (cplus_markers, (*mangled)[3]) != NULL)))
2812169695Skan    {
2813169695Skan      /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
2814169695Skan         and create the decl.  Note that we consume the entire mangled
2815169695Skan	 input string, which means that demangle_signature has no work
2816169695Skan	 to do.  */
2817169695Skan      if ((*mangled)[2] == 'v')
2818169695Skan	(*mangled) += 5; /* New style, with thunks: "__vt_" */
2819169695Skan      else
2820169695Skan	(*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
2821169695Skan      while (**mangled != '\0')
2822169695Skan	{
2823169695Skan	  switch (**mangled)
2824169695Skan	    {
2825169695Skan	    case 'Q':
2826169695Skan	    case 'K':
2827169695Skan	      success = demangle_qualified (work, mangled, declp, 0, 1);
2828169695Skan	      break;
2829169695Skan	    case 't':
2830169695Skan	      success = demangle_template (work, mangled, declp, 0, 1,
2831169695Skan					   1);
2832169695Skan	      break;
2833169695Skan	    default:
2834169695Skan	      if (ISDIGIT((unsigned char)*mangled[0]))
2835169695Skan		{
2836169695Skan		  n = consume_count(mangled);
2837169695Skan		  /* We may be seeing a too-large size, or else a
2838169695Skan		     ".<digits>" indicating a static local symbol.  In
2839169695Skan		     any case, declare victory and move on; *don't* try
2840169695Skan		     to use n to allocate.  */
2841169695Skan		  if (n > (int) strlen (*mangled))
2842169695Skan		    {
2843169695Skan		      success = 1;
2844169695Skan		      break;
2845169695Skan		    }
2846169695Skan		}
2847169695Skan	      else
2848169695Skan		{
2849169695Skan		  n = strcspn (*mangled, cplus_markers);
2850169695Skan		}
2851169695Skan	      string_appendn (declp, *mangled, n);
2852169695Skan	      (*mangled) += n;
2853169695Skan	    }
2854169695Skan
2855169695Skan	  p = strpbrk (*mangled, cplus_markers);
2856169695Skan	  if (success && ((p == NULL) || (p == *mangled)))
2857169695Skan	    {
2858169695Skan	      if (p != NULL)
2859169695Skan		{
2860169695Skan		  string_append (declp, SCOPE_STRING (work));
2861169695Skan		  (*mangled)++;
2862169695Skan		}
2863169695Skan	    }
2864169695Skan	  else
2865169695Skan	    {
2866169695Skan	      success = 0;
2867169695Skan	      break;
2868169695Skan	    }
2869169695Skan	}
2870169695Skan      if (success)
2871169695Skan	string_append (declp, " virtual table");
2872169695Skan    }
2873169695Skan  else if ((*mangled)[0] == '_'
2874169695Skan	   && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
2875169695Skan	   && (p = strpbrk (*mangled, cplus_markers)) != NULL)
2876169695Skan    {
2877169695Skan      /* static data member, "_3foo$varname" for example */
2878169695Skan      (*mangled)++;
2879169695Skan      switch (**mangled)
2880169695Skan	{
2881169695Skan	case 'Q':
2882169695Skan	case 'K':
2883169695Skan	  success = demangle_qualified (work, mangled, declp, 0, 1);
2884169695Skan	  break;
2885169695Skan	case 't':
2886169695Skan	  success = demangle_template (work, mangled, declp, 0, 1, 1);
2887169695Skan	  break;
2888169695Skan	default:
2889169695Skan	  n = consume_count (mangled);
2890169695Skan	  if (n < 0 || n > (long) strlen (*mangled))
2891169695Skan	    {
2892169695Skan	      success = 0;
2893169695Skan	      break;
2894169695Skan	    }
2895169695Skan
2896169695Skan	  if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
2897169695Skan	      && (*mangled)[9] == 'N'
2898169695Skan	      && (*mangled)[8] == (*mangled)[10]
2899169695Skan	      && strchr (cplus_markers, (*mangled)[8]))
2900169695Skan	    {
2901169695Skan	      /* A member of the anonymous namespace.  There's information
2902169695Skan		 about what identifier or filename it was keyed to, but
2903169695Skan		 it's just there to make the mangled name unique; we just
2904169695Skan		 step over it.  */
2905169695Skan	      string_append (declp, "{anonymous}");
2906169695Skan	      (*mangled) += n;
2907169695Skan
2908169695Skan	      /* Now p points to the marker before the N, so we need to
2909169695Skan		 update it to the first marker after what we consumed.  */
2910169695Skan	      p = strpbrk (*mangled, cplus_markers);
2911169695Skan	      break;
2912169695Skan	    }
2913169695Skan
2914169695Skan	  string_appendn (declp, *mangled, n);
2915169695Skan	  (*mangled) += n;
2916169695Skan	}
2917169695Skan      if (success && (p == *mangled))
2918169695Skan	{
2919169695Skan	  /* Consumed everything up to the cplus_marker, append the
2920169695Skan	     variable name.  */
2921169695Skan	  (*mangled)++;
2922169695Skan	  string_append (declp, SCOPE_STRING (work));
2923169695Skan	  n = strlen (*mangled);
2924169695Skan	  string_appendn (declp, *mangled, n);
2925169695Skan	  (*mangled) += n;
2926169695Skan	}
2927169695Skan      else
2928169695Skan	{
2929169695Skan	  success = 0;
2930169695Skan	}
2931169695Skan    }
2932169695Skan  else if (strncmp (*mangled, "__thunk_", 8) == 0)
2933169695Skan    {
2934169695Skan      int delta;
2935169695Skan
2936169695Skan      (*mangled) += 8;
2937169695Skan      delta = consume_count (mangled);
2938169695Skan      if (delta == -1)
2939169695Skan	success = 0;
2940169695Skan      else
2941169695Skan	{
2942169695Skan	  char *method = internal_cplus_demangle (work, ++*mangled);
2943169695Skan
2944169695Skan	  if (method)
2945169695Skan	    {
2946169695Skan	      char buf[50];
2947169695Skan	      sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
2948169695Skan	      string_append (declp, buf);
2949169695Skan	      string_append (declp, method);
2950169695Skan	      free (method);
2951169695Skan	      n = strlen (*mangled);
2952169695Skan	      (*mangled) += n;
2953169695Skan	    }
2954169695Skan	  else
2955169695Skan	    {
2956169695Skan	      success = 0;
2957169695Skan	    }
2958169695Skan	}
2959169695Skan    }
2960169695Skan  else if (strncmp (*mangled, "__t", 3) == 0
2961169695Skan	   && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
2962169695Skan    {
2963169695Skan      p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
2964169695Skan      (*mangled) += 4;
2965169695Skan      switch (**mangled)
2966169695Skan	{
2967169695Skan	case 'Q':
2968169695Skan	case 'K':
2969169695Skan	  success = demangle_qualified (work, mangled, declp, 0, 1);
2970169695Skan	  break;
2971169695Skan	case 't':
2972169695Skan	  success = demangle_template (work, mangled, declp, 0, 1, 1);
2973169695Skan	  break;
2974169695Skan	default:
2975169695Skan	  success = do_type (work, mangled, declp);
2976169695Skan	  break;
2977169695Skan	}
2978169695Skan      if (success && **mangled != '\0')
2979169695Skan	success = 0;
2980169695Skan      if (success)
2981169695Skan	string_append (declp, p);
2982169695Skan    }
2983169695Skan  else
2984169695Skan    {
2985169695Skan      success = 0;
2986169695Skan    }
2987169695Skan  return (success);
2988169695Skan}
2989169695Skan
2990169695Skanstatic void
2991169695Skanrecursively_demangle(struct work_stuff *work, const char **mangled,
2992169695Skan                     string *result, int namelength)
2993169695Skan{
2994169695Skan  char * recurse = (char *)NULL;
2995169695Skan  char * recurse_dem = (char *)NULL;
2996169695Skan
2997169695Skan  recurse = XNEWVEC (char, namelength + 1);
2998169695Skan  memcpy (recurse, *mangled, namelength);
2999169695Skan  recurse[namelength] = '\000';
3000169695Skan
3001169695Skan  recurse_dem = cplus_demangle (recurse, work->options);
3002169695Skan
3003169695Skan  if (recurse_dem)
3004169695Skan    {
3005169695Skan      string_append (result, recurse_dem);
3006169695Skan      free (recurse_dem);
3007169695Skan    }
3008169695Skan  else
3009169695Skan    {
3010169695Skan      string_appendn (result, *mangled, namelength);
3011169695Skan    }
3012169695Skan  free (recurse);
3013169695Skan  *mangled += namelength;
3014169695Skan}
3015169695Skan
3016169695Skan/*
3017169695Skan
3018169695SkanLOCAL FUNCTION
3019169695Skan
3020169695Skan	arm_special -- special handling of ARM/lucid mangled strings
3021169695Skan
3022169695SkanSYNOPSIS
3023169695Skan
3024169695Skan	static int
3025169695Skan	arm_special (const char **mangled,
3026169695Skan		     string *declp);
3027169695Skan
3028169695Skan
3029169695SkanDESCRIPTION
3030169695Skan
3031169695Skan	Process some special ARM style mangling forms that don't fit
3032169695Skan	the normal pattern.  For example:
3033169695Skan
3034169695Skan		__vtbl__3foo		(foo virtual table)
3035169695Skan		__vtbl__3foo__3bar	(bar::foo virtual table)
3036169695Skan
3037169695Skan */
3038169695Skan
3039169695Skanstatic int
3040169695Skanarm_special (const char **mangled, string *declp)
3041169695Skan{
3042169695Skan  int n;
3043169695Skan  int success = 1;
3044169695Skan  const char *scan;
3045169695Skan
3046169695Skan  if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
3047169695Skan    {
3048169695Skan      /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
3049169695Skan         and create the decl.  Note that we consume the entire mangled
3050169695Skan	 input string, which means that demangle_signature has no work
3051169695Skan	 to do.  */
3052169695Skan      scan = *mangled + ARM_VTABLE_STRLEN;
3053169695Skan      while (*scan != '\0')        /* first check it can be demangled */
3054169695Skan        {
3055169695Skan          n = consume_count (&scan);
3056169695Skan          if (n == -1)
3057169695Skan	    {
3058169695Skan	      return (0);           /* no good */
3059169695Skan	    }
3060169695Skan          scan += n;
3061169695Skan          if (scan[0] == '_' && scan[1] == '_')
3062169695Skan	    {
3063169695Skan	      scan += 2;
3064169695Skan	    }
3065169695Skan        }
3066169695Skan      (*mangled) += ARM_VTABLE_STRLEN;
3067169695Skan      while (**mangled != '\0')
3068169695Skan	{
3069169695Skan	  n = consume_count (mangled);
3070169695Skan          if (n == -1
3071169695Skan	      || n > (long) strlen (*mangled))
3072169695Skan	    return 0;
3073169695Skan	  string_prependn (declp, *mangled, n);
3074169695Skan	  (*mangled) += n;
3075169695Skan	  if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
3076169695Skan	    {
3077169695Skan	      string_prepend (declp, "::");
3078169695Skan	      (*mangled) += 2;
3079169695Skan	    }
3080169695Skan	}
3081169695Skan      string_append (declp, " virtual table");
3082169695Skan    }
3083169695Skan  else
3084169695Skan    {
3085169695Skan      success = 0;
3086169695Skan    }
3087169695Skan  return (success);
3088169695Skan}
3089169695Skan
3090169695Skan/*
3091169695Skan
3092169695SkanLOCAL FUNCTION
3093169695Skan
3094169695Skan	demangle_qualified -- demangle 'Q' qualified name strings
3095169695Skan
3096169695SkanSYNOPSIS
3097169695Skan
3098169695Skan	static int
3099169695Skan	demangle_qualified (struct work_stuff *, const char *mangled,
3100169695Skan			    string *result, int isfuncname, int append);
3101169695Skan
3102169695SkanDESCRIPTION
3103169695Skan
3104169695Skan	Demangle a qualified name, such as "Q25Outer5Inner" which is
3105169695Skan	the mangled form of "Outer::Inner".  The demangled output is
3106169695Skan	prepended or appended to the result string according to the
3107169695Skan	state of the append flag.
3108169695Skan
3109169695Skan	If isfuncname is nonzero, then the qualified name we are building
3110169695Skan	is going to be used as a member function name, so if it is a
3111169695Skan	constructor or destructor function, append an appropriate
3112169695Skan	constructor or destructor name.  I.E. for the above example,
3113169695Skan	the result for use as a constructor is "Outer::Inner::Inner"
3114169695Skan	and the result for use as a destructor is "Outer::Inner::~Inner".
3115169695Skan
3116169695SkanBUGS
3117169695Skan
3118169695Skan	Numeric conversion is ASCII dependent (FIXME).
3119169695Skan
3120169695Skan */
3121169695Skan
3122169695Skanstatic int
3123169695Skandemangle_qualified (struct work_stuff *work, const char **mangled,
3124169695Skan                    string *result, int isfuncname, int append)
3125169695Skan{
3126169695Skan  int qualifiers = 0;
3127169695Skan  int success = 1;
3128169695Skan  char num[2];
3129169695Skan  string temp;
3130169695Skan  string last_name;
3131169695Skan  int bindex = register_Btype (work);
3132169695Skan
3133169695Skan  /* We only make use of ISFUNCNAME if the entity is a constructor or
3134169695Skan     destructor.  */
3135169695Skan  isfuncname = (isfuncname
3136169695Skan		&& ((work->constructor & 1) || (work->destructor & 1)));
3137169695Skan
3138169695Skan  string_init (&temp);
3139169695Skan  string_init (&last_name);
3140169695Skan
3141169695Skan  if ((*mangled)[0] == 'K')
3142169695Skan    {
3143169695Skan    /* Squangling qualified name reuse */
3144169695Skan      int idx;
3145169695Skan      (*mangled)++;
3146169695Skan      idx = consume_count_with_underscores (mangled);
3147169695Skan      if (idx == -1 || idx >= work -> numk)
3148169695Skan        success = 0;
3149169695Skan      else
3150169695Skan        string_append (&temp, work -> ktypevec[idx]);
3151169695Skan    }
3152169695Skan  else
3153169695Skan    switch ((*mangled)[1])
3154169695Skan    {
3155169695Skan    case '_':
3156169695Skan      /* GNU mangled name with more than 9 classes.  The count is preceded
3157169695Skan	 by an underscore (to distinguish it from the <= 9 case) and followed
3158169695Skan	 by an underscore.  */
3159169695Skan      (*mangled)++;
3160169695Skan      qualifiers = consume_count_with_underscores (mangled);
3161169695Skan      if (qualifiers == -1)
3162169695Skan	success = 0;
3163169695Skan      break;
3164169695Skan
3165169695Skan    case '1':
3166169695Skan    case '2':
3167169695Skan    case '3':
3168169695Skan    case '4':
3169169695Skan    case '5':
3170169695Skan    case '6':
3171169695Skan    case '7':
3172169695Skan    case '8':
3173169695Skan    case '9':
3174169695Skan      /* The count is in a single digit.  */
3175169695Skan      num[0] = (*mangled)[1];
3176169695Skan      num[1] = '\0';
3177169695Skan      qualifiers = atoi (num);
3178169695Skan
3179169695Skan      /* If there is an underscore after the digit, skip it.  This is
3180169695Skan	 said to be for ARM-qualified names, but the ARM makes no
3181169695Skan	 mention of such an underscore.  Perhaps cfront uses one.  */
3182169695Skan      if ((*mangled)[2] == '_')
3183169695Skan	{
3184169695Skan	  (*mangled)++;
3185169695Skan	}
3186169695Skan      (*mangled) += 2;
3187169695Skan      break;
3188169695Skan
3189169695Skan    case '0':
3190169695Skan    default:
3191169695Skan      success = 0;
3192169695Skan    }
3193169695Skan
3194169695Skan  if (!success)
3195169695Skan    return success;
3196169695Skan
3197169695Skan  /* Pick off the names and collect them in the temp buffer in the order
3198169695Skan     in which they are found, separated by '::'.  */
3199169695Skan
3200169695Skan  while (qualifiers-- > 0)
3201169695Skan    {
3202169695Skan      int remember_K = 1;
3203169695Skan      string_clear (&last_name);
3204169695Skan
3205169695Skan      if (*mangled[0] == '_')
3206169695Skan	(*mangled)++;
3207169695Skan
3208169695Skan      if (*mangled[0] == 't')
3209169695Skan	{
3210169695Skan	  /* Here we always append to TEMP since we will want to use
3211169695Skan	     the template name without the template parameters as a
3212169695Skan	     constructor or destructor name.  The appropriate
3213169695Skan	     (parameter-less) value is returned by demangle_template
3214169695Skan	     in LAST_NAME.  We do not remember the template type here,
3215169695Skan	     in order to match the G++ mangling algorithm.  */
3216169695Skan	  success = demangle_template(work, mangled, &temp,
3217169695Skan				      &last_name, 1, 0);
3218169695Skan	  if (!success)
3219169695Skan	    break;
3220169695Skan	}
3221169695Skan      else if (*mangled[0] == 'K')
3222169695Skan	{
3223169695Skan          int idx;
3224169695Skan          (*mangled)++;
3225169695Skan          idx = consume_count_with_underscores (mangled);
3226169695Skan          if (idx == -1 || idx >= work->numk)
3227169695Skan            success = 0;
3228169695Skan          else
3229169695Skan            string_append (&temp, work->ktypevec[idx]);
3230169695Skan          remember_K = 0;
3231169695Skan
3232169695Skan	  if (!success) break;
3233169695Skan	}
3234169695Skan      else
3235169695Skan	{
3236169695Skan	  if (EDG_DEMANGLING)
3237169695Skan            {
3238169695Skan	      int namelength;
3239169695Skan 	      /* Now recursively demangle the qualifier
3240169695Skan 	       * This is necessary to deal with templates in
3241169695Skan 	       * mangling styles like EDG */
3242169695Skan	      namelength = consume_count (mangled);
3243169695Skan	      if (namelength == -1)
3244169695Skan		{
3245169695Skan		  success = 0;
3246169695Skan		  break;
3247169695Skan		}
3248169695Skan 	      recursively_demangle(work, mangled, &temp, namelength);
3249169695Skan            }
3250169695Skan          else
3251169695Skan            {
3252169695Skan              string_delete (&last_name);
3253169695Skan              success = do_type (work, mangled, &last_name);
3254169695Skan              if (!success)
3255169695Skan                break;
3256169695Skan              string_appends (&temp, &last_name);
3257169695Skan            }
3258169695Skan	}
3259169695Skan
3260169695Skan      if (remember_K)
3261169695Skan	remember_Ktype (work, temp.b, LEN_STRING (&temp));
3262169695Skan
3263169695Skan      if (qualifiers > 0)
3264169695Skan	string_append (&temp, SCOPE_STRING (work));
3265169695Skan    }
3266169695Skan
3267169695Skan  remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
3268169695Skan
3269169695Skan  /* If we are using the result as a function name, we need to append
3270169695Skan     the appropriate '::' separated constructor or destructor name.
3271169695Skan     We do this here because this is the most convenient place, where
3272169695Skan     we already have a pointer to the name and the length of the name.  */
3273169695Skan
3274169695Skan  if (isfuncname)
3275169695Skan    {
3276169695Skan      string_append (&temp, SCOPE_STRING (work));
3277169695Skan      if (work -> destructor & 1)
3278169695Skan	string_append (&temp, "~");
3279169695Skan      string_appends (&temp, &last_name);
3280169695Skan    }
3281169695Skan
3282169695Skan  /* Now either prepend the temp buffer to the result, or append it,
3283169695Skan     depending upon the state of the append flag.  */
3284169695Skan
3285169695Skan  if (append)
3286169695Skan    string_appends (result, &temp);
3287169695Skan  else
3288169695Skan    {
3289169695Skan      if (!STRING_EMPTY (result))
3290169695Skan	string_append (&temp, SCOPE_STRING (work));
3291169695Skan      string_prepends (result, &temp);
3292169695Skan    }
3293169695Skan
3294169695Skan  string_delete (&last_name);
3295169695Skan  string_delete (&temp);
3296169695Skan  return (success);
3297169695Skan}
3298169695Skan
3299169695Skan/*
3300169695Skan
3301169695SkanLOCAL FUNCTION
3302169695Skan
3303169695Skan	get_count -- convert an ascii count to integer, consuming tokens
3304169695Skan
3305169695SkanSYNOPSIS
3306169695Skan
3307169695Skan	static int
3308169695Skan	get_count (const char **type, int *count)
3309169695Skan
3310169695SkanDESCRIPTION
3311169695Skan
3312169695Skan	Assume that *type points at a count in a mangled name; set
3313169695Skan	*count to its value, and set *type to the next character after
3314169695Skan	the count.  There are some weird rules in effect here.
3315169695Skan
3316169695Skan	If *type does not point at a string of digits, return zero.
3317169695Skan
3318169695Skan	If *type points at a string of digits followed by an
3319169695Skan	underscore, set *count to their value as an integer, advance
3320169695Skan	*type to point *after the underscore, and return 1.
3321169695Skan
3322169695Skan	If *type points at a string of digits not followed by an
3323169695Skan	underscore, consume only the first digit.  Set *count to its
3324169695Skan	value as an integer, leave *type pointing after that digit,
3325169695Skan	and return 1.
3326169695Skan
3327169695Skan        The excuse for this odd behavior: in the ARM and HP demangling
3328169695Skan        styles, a type can be followed by a repeat count of the form
3329169695Skan        `Nxy', where:
3330169695Skan
3331169695Skan        `x' is a single digit specifying how many additional copies
3332169695Skan            of the type to append to the argument list, and
3333169695Skan
3334169695Skan        `y' is one or more digits, specifying the zero-based index of
3335169695Skan            the first repeated argument in the list.  Yes, as you're
3336169695Skan            unmangling the name you can figure this out yourself, but
3337169695Skan            it's there anyway.
3338169695Skan
3339169695Skan        So, for example, in `bar__3fooFPiN51', the first argument is a
3340169695Skan        pointer to an integer (`Pi'), and then the next five arguments
3341169695Skan        are the same (`N5'), and the first repeat is the function's
3342169695Skan        second argument (`1').
3343169695Skan*/
3344169695Skan
3345169695Skanstatic int
3346169695Skanget_count (const char **type, int *count)
3347169695Skan{
3348169695Skan  const char *p;
3349169695Skan  int n;
3350169695Skan
3351169695Skan  if (!ISDIGIT ((unsigned char)**type))
3352169695Skan    return (0);
3353169695Skan  else
3354169695Skan    {
3355169695Skan      *count = **type - '0';
3356169695Skan      (*type)++;
3357169695Skan      if (ISDIGIT ((unsigned char)**type))
3358169695Skan	{
3359169695Skan	  p = *type;
3360169695Skan	  n = *count;
3361169695Skan	  do
3362169695Skan	    {
3363169695Skan	      n *= 10;
3364169695Skan	      n += *p - '0';
3365169695Skan	      p++;
3366169695Skan	    }
3367169695Skan	  while (ISDIGIT ((unsigned char)*p));
3368169695Skan	  if (*p == '_')
3369169695Skan	    {
3370169695Skan	      *type = p + 1;
3371169695Skan	      *count = n;
3372169695Skan	    }
3373169695Skan	}
3374169695Skan    }
3375169695Skan  return (1);
3376169695Skan}
3377169695Skan
3378169695Skan/* RESULT will be initialised here; it will be freed on failure.  The
3379169695Skan   value returned is really a type_kind_t.  */
3380169695Skan
3381169695Skanstatic int
3382169695Skando_type (struct work_stuff *work, const char **mangled, string *result)
3383169695Skan{
3384169695Skan  int n;
3385169695Skan  int done;
3386169695Skan  int success;
3387169695Skan  string decl;
3388169695Skan  const char *remembered_type;
3389169695Skan  int type_quals;
3390169695Skan  type_kind_t tk = tk_none;
3391169695Skan
3392169695Skan  string_init (&decl);
3393169695Skan  string_init (result);
3394169695Skan
3395169695Skan  done = 0;
3396169695Skan  success = 1;
3397169695Skan  while (success && !done)
3398169695Skan    {
3399169695Skan      int member;
3400169695Skan      switch (**mangled)
3401169695Skan	{
3402169695Skan
3403169695Skan	  /* A pointer type */
3404169695Skan	case 'P':
3405169695Skan	case 'p':
3406169695Skan	  (*mangled)++;
3407169695Skan	  if (! (work -> options & DMGL_JAVA))
3408169695Skan	    string_prepend (&decl, "*");
3409169695Skan	  if (tk == tk_none)
3410169695Skan	    tk = tk_pointer;
3411169695Skan	  break;
3412169695Skan
3413169695Skan	  /* A reference type */
3414169695Skan	case 'R':
3415169695Skan	  (*mangled)++;
3416169695Skan	  string_prepend (&decl, "&");
3417169695Skan	  if (tk == tk_none)
3418169695Skan	    tk = tk_reference;
3419169695Skan	  break;
3420169695Skan
3421169695Skan	  /* An array */
3422169695Skan	case 'A':
3423169695Skan	  {
3424169695Skan	    ++(*mangled);
3425169695Skan	    if (!STRING_EMPTY (&decl)
3426169695Skan		&& (decl.b[0] == '*' || decl.b[0] == '&'))
3427169695Skan	      {
3428169695Skan		string_prepend (&decl, "(");
3429169695Skan		string_append (&decl, ")");
3430169695Skan	      }
3431169695Skan	    string_append (&decl, "[");
3432169695Skan	    if (**mangled != '_')
3433169695Skan	      success = demangle_template_value_parm (work, mangled, &decl,
3434169695Skan						      tk_integral);
3435169695Skan	    if (**mangled == '_')
3436169695Skan	      ++(*mangled);
3437169695Skan	    string_append (&decl, "]");
3438169695Skan	    break;
3439169695Skan	  }
3440169695Skan
3441169695Skan	/* A back reference to a previously seen type */
3442169695Skan	case 'T':
3443169695Skan	  (*mangled)++;
3444169695Skan	  if (!get_count (mangled, &n) || n >= work -> ntypes)
3445169695Skan	    {
3446169695Skan	      success = 0;
3447169695Skan	    }
3448169695Skan	  else
3449169695Skan	    {
3450169695Skan	      remembered_type = work -> typevec[n];
3451169695Skan	      mangled = &remembered_type;
3452169695Skan	    }
3453169695Skan	  break;
3454169695Skan
3455169695Skan	  /* A function */
3456169695Skan	case 'F':
3457169695Skan	  (*mangled)++;
3458169695Skan	    if (!STRING_EMPTY (&decl)
3459169695Skan		&& (decl.b[0] == '*' || decl.b[0] == '&'))
3460169695Skan	    {
3461169695Skan	      string_prepend (&decl, "(");
3462169695Skan	      string_append (&decl, ")");
3463169695Skan	    }
3464169695Skan	  /* After picking off the function args, we expect to either find the
3465169695Skan	     function return type (preceded by an '_') or the end of the
3466169695Skan	     string.  */
3467169695Skan	  if (!demangle_nested_args (work, mangled, &decl)
3468169695Skan	      || (**mangled != '_' && **mangled != '\0'))
3469169695Skan	    {
3470169695Skan	      success = 0;
3471169695Skan	      break;
3472169695Skan	    }
3473169695Skan	  if (success && (**mangled == '_'))
3474169695Skan	    (*mangled)++;
3475169695Skan	  break;
3476169695Skan
3477169695Skan	case 'M':
3478169695Skan	case 'O':
3479169695Skan	  {
3480169695Skan	    type_quals = TYPE_UNQUALIFIED;
3481169695Skan
3482169695Skan	    member = **mangled == 'M';
3483169695Skan	    (*mangled)++;
3484169695Skan
3485169695Skan	    string_append (&decl, ")");
3486169695Skan
3487169695Skan	    /* We don't need to prepend `::' for a qualified name;
3488169695Skan	       demangle_qualified will do that for us.  */
3489169695Skan	    if (**mangled != 'Q')
3490169695Skan	      string_prepend (&decl, SCOPE_STRING (work));
3491169695Skan
3492169695Skan	    if (ISDIGIT ((unsigned char)**mangled))
3493169695Skan	      {
3494169695Skan		n = consume_count (mangled);
3495169695Skan		if (n == -1
3496169695Skan		    || (int) strlen (*mangled) < n)
3497169695Skan		  {
3498169695Skan		    success = 0;
3499169695Skan		    break;
3500169695Skan		  }
3501169695Skan		string_prependn (&decl, *mangled, n);
3502169695Skan		*mangled += n;
3503169695Skan	      }
3504169695Skan	    else if (**mangled == 'X' || **mangled == 'Y')
3505169695Skan	      {
3506169695Skan		string temp;
3507169695Skan		do_type (work, mangled, &temp);
3508169695Skan		string_prepends (&decl, &temp);
3509169695Skan		string_delete (&temp);
3510169695Skan	      }
3511169695Skan	    else if (**mangled == 't')
3512169695Skan	      {
3513169695Skan		string temp;
3514169695Skan		string_init (&temp);
3515169695Skan		success = demangle_template (work, mangled, &temp,
3516169695Skan					     NULL, 1, 1);
3517169695Skan		if (success)
3518169695Skan		  {
3519169695Skan		    string_prependn (&decl, temp.b, temp.p - temp.b);
3520169695Skan		    string_delete (&temp);
3521169695Skan		  }
3522169695Skan		else
3523169695Skan		  break;
3524169695Skan	      }
3525169695Skan	    else if (**mangled == 'Q')
3526169695Skan	      {
3527169695Skan		success = demangle_qualified (work, mangled, &decl,
3528169695Skan					      /*isfuncnam=*/0,
3529169695Skan					      /*append=*/0);
3530169695Skan		if (!success)
3531169695Skan		  break;
3532169695Skan	      }
3533169695Skan	    else
3534169695Skan	      {
3535169695Skan		success = 0;
3536169695Skan		break;
3537169695Skan	      }
3538169695Skan
3539169695Skan	    string_prepend (&decl, "(");
3540169695Skan	    if (member)
3541169695Skan	      {
3542169695Skan		switch (**mangled)
3543169695Skan		  {
3544169695Skan		  case 'C':
3545169695Skan		  case 'V':
3546169695Skan		  case 'u':
3547169695Skan		    type_quals |= code_for_qualifier (**mangled);
3548169695Skan		    (*mangled)++;
3549169695Skan		    break;
3550169695Skan
3551169695Skan		  default:
3552169695Skan		    break;
3553169695Skan		  }
3554169695Skan
3555169695Skan		if (*(*mangled)++ != 'F')
3556169695Skan		  {
3557169695Skan		    success = 0;
3558169695Skan		    break;
3559169695Skan		  }
3560169695Skan	      }
3561169695Skan	    if ((member && !demangle_nested_args (work, mangled, &decl))
3562169695Skan		|| **mangled != '_')
3563169695Skan	      {
3564169695Skan		success = 0;
3565169695Skan		break;
3566169695Skan	      }
3567169695Skan	    (*mangled)++;
3568169695Skan	    if (! PRINT_ANSI_QUALIFIERS)
3569169695Skan	      {
3570169695Skan		break;
3571169695Skan	      }
3572169695Skan	    if (type_quals != TYPE_UNQUALIFIED)
3573169695Skan	      {
3574169695Skan		APPEND_BLANK (&decl);
3575169695Skan		string_append (&decl, qualifier_string (type_quals));
3576169695Skan	      }
3577169695Skan	    break;
3578169695Skan	  }
3579169695Skan        case 'G':
3580169695Skan	  (*mangled)++;
3581169695Skan	  break;
3582169695Skan
3583169695Skan	case 'C':
3584169695Skan	case 'V':
3585169695Skan	case 'u':
3586169695Skan	  if (PRINT_ANSI_QUALIFIERS)
3587169695Skan	    {
3588169695Skan	      if (!STRING_EMPTY (&decl))
3589169695Skan		string_prepend (&decl, " ");
3590169695Skan
3591169695Skan	      string_prepend (&decl, demangle_qualifier (**mangled));
3592169695Skan	    }
3593169695Skan	  (*mangled)++;
3594169695Skan	  break;
3595169695Skan	  /*
3596169695Skan	    }
3597169695Skan	    */
3598169695Skan
3599169695Skan	  /* fall through */
3600169695Skan	default:
3601169695Skan	  done = 1;
3602169695Skan	  break;
3603169695Skan	}
3604169695Skan    }
3605169695Skan
3606169695Skan  if (success) switch (**mangled)
3607169695Skan    {
3608169695Skan      /* A qualified name, such as "Outer::Inner".  */
3609169695Skan    case 'Q':
3610169695Skan    case 'K':
3611169695Skan      {
3612169695Skan        success = demangle_qualified (work, mangled, result, 0, 1);
3613169695Skan        break;
3614169695Skan      }
3615169695Skan
3616169695Skan    /* A back reference to a previously seen squangled type */
3617169695Skan    case 'B':
3618169695Skan      (*mangled)++;
3619169695Skan      if (!get_count (mangled, &n) || n >= work -> numb)
3620169695Skan	success = 0;
3621169695Skan      else
3622169695Skan	string_append (result, work->btypevec[n]);
3623169695Skan      break;
3624169695Skan
3625169695Skan    case 'X':
3626169695Skan    case 'Y':
3627169695Skan      /* A template parm.  We substitute the corresponding argument. */
3628169695Skan      {
3629169695Skan	int idx;
3630169695Skan
3631169695Skan	(*mangled)++;
3632169695Skan	idx = consume_count_with_underscores (mangled);
3633169695Skan
3634169695Skan	if (idx == -1
3635169695Skan	    || (work->tmpl_argvec && idx >= work->ntmpl_args)
3636169695Skan	    || consume_count_with_underscores (mangled) == -1)
3637169695Skan	  {
3638169695Skan	    success = 0;
3639169695Skan	    break;
3640169695Skan	  }
3641169695Skan
3642169695Skan	if (work->tmpl_argvec)
3643169695Skan	  string_append (result, work->tmpl_argvec[idx]);
3644169695Skan	else
3645169695Skan	  string_append_template_idx (result, idx);
3646169695Skan
3647169695Skan	success = 1;
3648169695Skan      }
3649169695Skan    break;
3650169695Skan
3651169695Skan    default:
3652169695Skan      success = demangle_fund_type (work, mangled, result);
3653169695Skan      if (tk == tk_none)
3654169695Skan	tk = (type_kind_t) success;
3655169695Skan      break;
3656169695Skan    }
3657169695Skan
3658169695Skan  if (success)
3659169695Skan    {
3660169695Skan      if (!STRING_EMPTY (&decl))
3661169695Skan	{
3662169695Skan	  string_append (result, " ");
3663169695Skan	  string_appends (result, &decl);
3664169695Skan	}
3665169695Skan    }
3666169695Skan  else
3667169695Skan    string_delete (result);
3668169695Skan  string_delete (&decl);
3669169695Skan
3670169695Skan  if (success)
3671169695Skan    /* Assume an integral type, if we're not sure.  */
3672169695Skan    return (int) ((tk == tk_none) ? tk_integral : tk);
3673169695Skan  else
3674169695Skan    return 0;
3675169695Skan}
3676169695Skan
3677169695Skan/* Given a pointer to a type string that represents a fundamental type
3678169695Skan   argument (int, long, unsigned int, etc) in TYPE, a pointer to the
3679169695Skan   string in which the demangled output is being built in RESULT, and
3680169695Skan   the WORK structure, decode the types and add them to the result.
3681169695Skan
3682169695Skan   For example:
3683169695Skan
3684169695Skan   	"Ci"	=>	"const int"
3685169695Skan	"Sl"	=>	"signed long"
3686169695Skan	"CUs"	=>	"const unsigned short"
3687169695Skan
3688169695Skan   The value returned is really a type_kind_t.  */
3689169695Skan
3690169695Skanstatic int
3691169695Skandemangle_fund_type (struct work_stuff *work,
3692169695Skan                    const char **mangled, string *result)
3693169695Skan{
3694169695Skan  int done = 0;
3695169695Skan  int success = 1;
3696169695Skan  char buf[INTBUF_SIZE + 5 /* 'int%u_t' */];
3697169695Skan  unsigned int dec = 0;
3698169695Skan  type_kind_t tk = tk_integral;
3699169695Skan
3700169695Skan  /* First pick off any type qualifiers.  There can be more than one.  */
3701169695Skan
3702169695Skan  while (!done)
3703169695Skan    {
3704169695Skan      switch (**mangled)
3705169695Skan	{
3706169695Skan	case 'C':
3707169695Skan	case 'V':
3708169695Skan	case 'u':
3709169695Skan	  if (PRINT_ANSI_QUALIFIERS)
3710169695Skan	    {
3711169695Skan              if (!STRING_EMPTY (result))
3712169695Skan                string_prepend (result, " ");
3713169695Skan	      string_prepend (result, demangle_qualifier (**mangled));
3714169695Skan	    }
3715169695Skan	  (*mangled)++;
3716169695Skan	  break;
3717169695Skan	case 'U':
3718169695Skan	  (*mangled)++;
3719169695Skan	  APPEND_BLANK (result);
3720169695Skan	  string_append (result, "unsigned");
3721169695Skan	  break;
3722169695Skan	case 'S': /* signed char only */
3723169695Skan	  (*mangled)++;
3724169695Skan	  APPEND_BLANK (result);
3725169695Skan	  string_append (result, "signed");
3726169695Skan	  break;
3727169695Skan	case 'J':
3728169695Skan	  (*mangled)++;
3729169695Skan	  APPEND_BLANK (result);
3730169695Skan	  string_append (result, "__complex");
3731169695Skan	  break;
3732169695Skan	default:
3733169695Skan	  done = 1;
3734169695Skan	  break;
3735169695Skan	}
3736169695Skan    }
3737169695Skan
3738169695Skan  /* Now pick off the fundamental type.  There can be only one.  */
3739169695Skan
3740169695Skan  switch (**mangled)
3741169695Skan    {
3742169695Skan    case '\0':
3743169695Skan    case '_':
3744169695Skan      break;
3745169695Skan    case 'v':
3746169695Skan      (*mangled)++;
3747169695Skan      APPEND_BLANK (result);
3748169695Skan      string_append (result, "void");
3749169695Skan      break;
3750169695Skan    case 'x':
3751169695Skan      (*mangled)++;
3752169695Skan      APPEND_BLANK (result);
3753169695Skan      string_append (result, "long long");
3754169695Skan      break;
3755169695Skan    case 'l':
3756169695Skan      (*mangled)++;
3757169695Skan      APPEND_BLANK (result);
3758169695Skan      string_append (result, "long");
3759169695Skan      break;
3760169695Skan    case 'i':
3761169695Skan      (*mangled)++;
3762169695Skan      APPEND_BLANK (result);
3763169695Skan      string_append (result, "int");
3764169695Skan      break;
3765169695Skan    case 's':
3766169695Skan      (*mangled)++;
3767169695Skan      APPEND_BLANK (result);
3768169695Skan      string_append (result, "short");
3769169695Skan      break;
3770169695Skan    case 'b':
3771169695Skan      (*mangled)++;
3772169695Skan      APPEND_BLANK (result);
3773169695Skan      string_append (result, "bool");
3774169695Skan      tk = tk_bool;
3775169695Skan      break;
3776169695Skan    case 'c':
3777169695Skan      (*mangled)++;
3778169695Skan      APPEND_BLANK (result);
3779169695Skan      string_append (result, "char");
3780169695Skan      tk = tk_char;
3781169695Skan      break;
3782169695Skan    case 'w':
3783169695Skan      (*mangled)++;
3784169695Skan      APPEND_BLANK (result);
3785169695Skan      string_append (result, "wchar_t");
3786169695Skan      tk = tk_char;
3787169695Skan      break;
3788169695Skan    case 'r':
3789169695Skan      (*mangled)++;
3790169695Skan      APPEND_BLANK (result);
3791169695Skan      string_append (result, "long double");
3792169695Skan      tk = tk_real;
3793169695Skan      break;
3794169695Skan    case 'd':
3795169695Skan      (*mangled)++;
3796169695Skan      APPEND_BLANK (result);
3797169695Skan      string_append (result, "double");
3798169695Skan      tk = tk_real;
3799169695Skan      break;
3800169695Skan    case 'f':
3801169695Skan      (*mangled)++;
3802169695Skan      APPEND_BLANK (result);
3803169695Skan      string_append (result, "float");
3804169695Skan      tk = tk_real;
3805169695Skan      break;
3806169695Skan    case 'G':
3807169695Skan      (*mangled)++;
3808169695Skan      if (!ISDIGIT ((unsigned char)**mangled))
3809169695Skan	{
3810169695Skan	  success = 0;
3811169695Skan	  break;
3812169695Skan	}
3813169695Skan    case 'I':
3814169695Skan      (*mangled)++;
3815169695Skan      if (**mangled == '_')
3816169695Skan	{
3817169695Skan	  int i;
3818169695Skan	  (*mangled)++;
3819169695Skan	  for (i = 0;
3820169695Skan	       i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
3821169695Skan	       (*mangled)++, i++)
3822169695Skan	    buf[i] = **mangled;
3823169695Skan	  if (**mangled != '_')
3824169695Skan	    {
3825169695Skan	      success = 0;
3826169695Skan	      break;
3827169695Skan	    }
3828169695Skan	  buf[i] = '\0';
3829169695Skan	  (*mangled)++;
3830169695Skan	}
3831169695Skan      else
3832169695Skan	{
3833169695Skan	  strncpy (buf, *mangled, 2);
3834169695Skan	  buf[2] = '\0';
3835169695Skan	  *mangled += min (strlen (*mangled), 2);
3836169695Skan	}
3837169695Skan      sscanf (buf, "%x", &dec);
3838169695Skan      sprintf (buf, "int%u_t", dec);
3839169695Skan      APPEND_BLANK (result);
3840169695Skan      string_append (result, buf);
3841169695Skan      break;
3842169695Skan
3843169695Skan      /* fall through */
3844169695Skan      /* An explicit type, such as "6mytype" or "7integer" */
3845169695Skan    case '0':
3846169695Skan    case '1':
3847169695Skan    case '2':
3848169695Skan    case '3':
3849169695Skan    case '4':
3850169695Skan    case '5':
3851169695Skan    case '6':
3852169695Skan    case '7':
3853169695Skan    case '8':
3854169695Skan    case '9':
3855169695Skan      {
3856169695Skan        int bindex = register_Btype (work);
3857169695Skan        string btype;
3858169695Skan        string_init (&btype);
3859169695Skan        if (demangle_class_name (work, mangled, &btype)) {
3860169695Skan          remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
3861169695Skan          APPEND_BLANK (result);
3862169695Skan          string_appends (result, &btype);
3863169695Skan        }
3864169695Skan        else
3865169695Skan          success = 0;
3866169695Skan        string_delete (&btype);
3867169695Skan        break;
3868169695Skan      }
3869169695Skan    case 't':
3870169695Skan      {
3871169695Skan        string btype;
3872169695Skan        string_init (&btype);
3873169695Skan        success = demangle_template (work, mangled, &btype, 0, 1, 1);
3874169695Skan        string_appends (result, &btype);
3875169695Skan        string_delete (&btype);
3876169695Skan        break;
3877169695Skan      }
3878169695Skan    default:
3879169695Skan      success = 0;
3880169695Skan      break;
3881169695Skan    }
3882169695Skan
3883169695Skan  return success ? ((int) tk) : 0;
3884169695Skan}
3885169695Skan
3886169695Skan
3887169695Skan/* Handle a template's value parameter for HP aCC (extension from ARM)
3888169695Skan   **mangled points to 'S' or 'U' */
3889169695Skan
3890169695Skanstatic int
3891169695Skando_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED,
3892169695Skan                               const char **mangled, string *result)
3893169695Skan{
3894169695Skan  int unsigned_const;
3895169695Skan
3896169695Skan  if (**mangled != 'U' && **mangled != 'S')
3897169695Skan    return 0;
3898169695Skan
3899169695Skan  unsigned_const = (**mangled == 'U');
3900169695Skan
3901169695Skan  (*mangled)++;
3902169695Skan
3903169695Skan  switch (**mangled)
3904169695Skan    {
3905169695Skan      case 'N':
3906169695Skan        string_append (result, "-");
3907169695Skan        /* fall through */
3908169695Skan      case 'P':
3909169695Skan        (*mangled)++;
3910169695Skan        break;
3911169695Skan      case 'M':
3912169695Skan        /* special case for -2^31 */
3913169695Skan        string_append (result, "-2147483648");
3914169695Skan        (*mangled)++;
3915169695Skan        return 1;
3916169695Skan      default:
3917169695Skan        return 0;
3918169695Skan    }
3919169695Skan
3920169695Skan  /* We have to be looking at an integer now */
3921169695Skan  if (!(ISDIGIT ((unsigned char)**mangled)))
3922169695Skan    return 0;
3923169695Skan
3924169695Skan  /* We only deal with integral values for template
3925169695Skan     parameters -- so it's OK to look only for digits */
3926169695Skan  while (ISDIGIT ((unsigned char)**mangled))
3927169695Skan    {
3928169695Skan      char_str[0] = **mangled;
3929169695Skan      string_append (result, char_str);
3930169695Skan      (*mangled)++;
3931169695Skan    }
3932169695Skan
3933169695Skan  if (unsigned_const)
3934169695Skan    string_append (result, "U");
3935169695Skan
3936169695Skan  /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
3937169695Skan     with L or LL suffixes. pai/1997-09-03 */
3938169695Skan
3939169695Skan  return 1; /* success */
3940169695Skan}
3941169695Skan
3942169695Skan/* Handle a template's literal parameter for HP aCC (extension from ARM)
3943169695Skan   **mangled is pointing to the 'A' */
3944169695Skan
3945169695Skanstatic int
3946169695Skando_hpacc_template_literal (struct work_stuff *work, const char **mangled,
3947169695Skan                           string *result)
3948169695Skan{
3949169695Skan  int literal_len = 0;
3950169695Skan  char * recurse;
3951169695Skan  char * recurse_dem;
3952169695Skan
3953169695Skan  if (**mangled != 'A')
3954169695Skan    return 0;
3955169695Skan
3956169695Skan  (*mangled)++;
3957169695Skan
3958169695Skan  literal_len = consume_count (mangled);
3959169695Skan
3960169695Skan  if (literal_len <= 0)
3961169695Skan    return 0;
3962169695Skan
3963169695Skan  /* Literal parameters are names of arrays, functions, etc.  and the
3964169695Skan     canonical representation uses the address operator */
3965169695Skan  string_append (result, "&");
3966169695Skan
3967169695Skan  /* Now recursively demangle the literal name */
3968169695Skan  recurse = XNEWVEC (char, literal_len + 1);
3969169695Skan  memcpy (recurse, *mangled, literal_len);
3970169695Skan  recurse[literal_len] = '\000';
3971169695Skan
3972169695Skan  recurse_dem = cplus_demangle (recurse, work->options);
3973169695Skan
3974169695Skan  if (recurse_dem)
3975169695Skan    {
3976169695Skan      string_append (result, recurse_dem);
3977169695Skan      free (recurse_dem);
3978169695Skan    }
3979169695Skan  else
3980169695Skan    {
3981169695Skan      string_appendn (result, *mangled, literal_len);
3982169695Skan    }
3983169695Skan  (*mangled) += literal_len;
3984169695Skan  free (recurse);
3985169695Skan
3986169695Skan  return 1;
3987169695Skan}
3988169695Skan
3989169695Skanstatic int
3990169695Skansnarf_numeric_literal (const char **args, string *arg)
3991169695Skan{
3992169695Skan  if (**args == '-')
3993169695Skan    {
3994169695Skan      char_str[0] = '-';
3995169695Skan      string_append (arg, char_str);
3996169695Skan      (*args)++;
3997169695Skan    }
3998169695Skan  else if (**args == '+')
3999169695Skan    (*args)++;
4000169695Skan
4001169695Skan  if (!ISDIGIT ((unsigned char)**args))
4002169695Skan    return 0;
4003169695Skan
4004169695Skan  while (ISDIGIT ((unsigned char)**args))
4005169695Skan    {
4006169695Skan      char_str[0] = **args;
4007169695Skan      string_append (arg, char_str);
4008169695Skan      (*args)++;
4009169695Skan    }
4010169695Skan
4011169695Skan  return 1;
4012169695Skan}
4013169695Skan
4014169695Skan/* Demangle the next argument, given by MANGLED into RESULT, which
4015169695Skan   *should be an uninitialized* string.  It will be initialized here,
4016169695Skan   and free'd should anything go wrong.  */
4017169695Skan
4018169695Skanstatic int
4019169695Skando_arg (struct work_stuff *work, const char **mangled, string *result)
4020169695Skan{
4021169695Skan  /* Remember where we started so that we can record the type, for
4022169695Skan     non-squangling type remembering.  */
4023169695Skan  const char *start = *mangled;
4024169695Skan
4025169695Skan  string_init (result);
4026169695Skan
4027169695Skan  if (work->nrepeats > 0)
4028169695Skan    {
4029169695Skan      --work->nrepeats;
4030169695Skan
4031169695Skan      if (work->previous_argument == 0)
4032169695Skan	return 0;
4033169695Skan
4034169695Skan      /* We want to reissue the previous type in this argument list.  */
4035169695Skan      string_appends (result, work->previous_argument);
4036169695Skan      return 1;
4037169695Skan    }
4038169695Skan
4039169695Skan  if (**mangled == 'n')
4040169695Skan    {
4041169695Skan      /* A squangling-style repeat.  */
4042169695Skan      (*mangled)++;
4043169695Skan      work->nrepeats = consume_count(mangled);
4044169695Skan
4045169695Skan      if (work->nrepeats <= 0)
4046169695Skan	/* This was not a repeat count after all.  */
4047169695Skan	return 0;
4048169695Skan
4049169695Skan      if (work->nrepeats > 9)
4050169695Skan	{
4051169695Skan	  if (**mangled != '_')
4052169695Skan	    /* The repeat count should be followed by an '_' in this
4053169695Skan	       case.  */
4054169695Skan	    return 0;
4055169695Skan	  else
4056169695Skan	    (*mangled)++;
4057169695Skan	}
4058169695Skan
4059169695Skan      /* Now, the repeat is all set up.  */
4060169695Skan      return do_arg (work, mangled, result);
4061169695Skan    }
4062169695Skan
4063169695Skan  /* Save the result in WORK->previous_argument so that we can find it
4064169695Skan     if it's repeated.  Note that saving START is not good enough: we
4065169695Skan     do not want to add additional types to the back-referenceable
4066169695Skan     type vector when processing a repeated type.  */
4067169695Skan  if (work->previous_argument)
4068169695Skan    string_delete (work->previous_argument);
4069169695Skan  else
4070169695Skan    work->previous_argument = XNEW (string);
4071169695Skan
4072169695Skan  if (!do_type (work, mangled, work->previous_argument))
4073169695Skan    return 0;
4074169695Skan
4075169695Skan  string_appends (result, work->previous_argument);
4076169695Skan
4077169695Skan  remember_type (work, start, *mangled - start);
4078169695Skan  return 1;
4079169695Skan}
4080169695Skan
4081169695Skanstatic void
4082169695Skanremember_type (struct work_stuff *work, const char *start, int len)
4083169695Skan{
4084169695Skan  char *tem;
4085169695Skan
4086169695Skan  if (work->forgetting_types)
4087169695Skan    return;
4088169695Skan
4089169695Skan  if (work -> ntypes >= work -> typevec_size)
4090169695Skan    {
4091169695Skan      if (work -> typevec_size == 0)
4092169695Skan	{
4093169695Skan	  work -> typevec_size = 3;
4094169695Skan	  work -> typevec = XNEWVEC (char *, work->typevec_size);
4095169695Skan	}
4096169695Skan      else
4097169695Skan	{
4098169695Skan	  work -> typevec_size *= 2;
4099169695Skan	  work -> typevec
4100169695Skan	    = XRESIZEVEC (char *, work->typevec, work->typevec_size);
4101169695Skan	}
4102169695Skan    }
4103169695Skan  tem = XNEWVEC (char, len + 1);
4104169695Skan  memcpy (tem, start, len);
4105169695Skan  tem[len] = '\0';
4106169695Skan  work -> typevec[work -> ntypes++] = tem;
4107169695Skan}
4108169695Skan
4109169695Skan
4110169695Skan/* Remember a K type class qualifier. */
4111169695Skanstatic void
4112169695Skanremember_Ktype (struct work_stuff *work, const char *start, int len)
4113169695Skan{
4114169695Skan  char *tem;
4115169695Skan
4116169695Skan  if (work -> numk >= work -> ksize)
4117169695Skan    {
4118169695Skan      if (work -> ksize == 0)
4119169695Skan	{
4120169695Skan	  work -> ksize = 5;
4121169695Skan	  work -> ktypevec = XNEWVEC (char *, work->ksize);
4122169695Skan	}
4123169695Skan      else
4124169695Skan	{
4125169695Skan	  work -> ksize *= 2;
4126169695Skan	  work -> ktypevec
4127169695Skan	    = XRESIZEVEC (char *, work->ktypevec, work->ksize);
4128169695Skan	}
4129169695Skan    }
4130169695Skan  tem = XNEWVEC (char, len + 1);
4131169695Skan  memcpy (tem, start, len);
4132169695Skan  tem[len] = '\0';
4133169695Skan  work -> ktypevec[work -> numk++] = tem;
4134169695Skan}
4135169695Skan
4136169695Skan/* Register a B code, and get an index for it. B codes are registered
4137169695Skan   as they are seen, rather than as they are completed, so map<temp<char> >
4138169695Skan   registers map<temp<char> > as B0, and temp<char> as B1 */
4139169695Skan
4140169695Skanstatic int
4141169695Skanregister_Btype (struct work_stuff *work)
4142169695Skan{
4143169695Skan  int ret;
4144169695Skan
4145169695Skan  if (work -> numb >= work -> bsize)
4146169695Skan    {
4147169695Skan      if (work -> bsize == 0)
4148169695Skan	{
4149169695Skan	  work -> bsize = 5;
4150169695Skan	  work -> btypevec = XNEWVEC (char *, work->bsize);
4151169695Skan	}
4152169695Skan      else
4153169695Skan	{
4154169695Skan	  work -> bsize *= 2;
4155169695Skan	  work -> btypevec
4156169695Skan	    = XRESIZEVEC (char *, work->btypevec, work->bsize);
4157169695Skan	}
4158169695Skan    }
4159169695Skan  ret = work -> numb++;
4160169695Skan  work -> btypevec[ret] = NULL;
4161169695Skan  return(ret);
4162169695Skan}
4163169695Skan
4164169695Skan/* Store a value into a previously registered B code type. */
4165169695Skan
4166169695Skanstatic void
4167169695Skanremember_Btype (struct work_stuff *work, const char *start,
4168169695Skan                int len, int index)
4169169695Skan{
4170169695Skan  char *tem;
4171169695Skan
4172169695Skan  tem = XNEWVEC (char, len + 1);
4173169695Skan  memcpy (tem, start, len);
4174169695Skan  tem[len] = '\0';
4175169695Skan  work -> btypevec[index] = tem;
4176169695Skan}
4177169695Skan
4178169695Skan/* Lose all the info related to B and K type codes. */
4179169695Skanstatic void
4180169695Skanforget_B_and_K_types (struct work_stuff *work)
4181169695Skan{
4182169695Skan  int i;
4183169695Skan
4184169695Skan  while (work -> numk > 0)
4185169695Skan    {
4186169695Skan      i = --(work -> numk);
4187169695Skan      if (work -> ktypevec[i] != NULL)
4188169695Skan	{
4189169695Skan	  free (work -> ktypevec[i]);
4190169695Skan	  work -> ktypevec[i] = NULL;
4191169695Skan	}
4192169695Skan    }
4193169695Skan
4194169695Skan  while (work -> numb > 0)
4195169695Skan    {
4196169695Skan      i = --(work -> numb);
4197169695Skan      if (work -> btypevec[i] != NULL)
4198169695Skan	{
4199169695Skan	  free (work -> btypevec[i]);
4200169695Skan	  work -> btypevec[i] = NULL;
4201169695Skan	}
4202169695Skan    }
4203169695Skan}
4204169695Skan/* Forget the remembered types, but not the type vector itself.  */
4205169695Skan
4206169695Skanstatic void
4207169695Skanforget_types (struct work_stuff *work)
4208169695Skan{
4209169695Skan  int i;
4210169695Skan
4211169695Skan  while (work -> ntypes > 0)
4212169695Skan    {
4213169695Skan      i = --(work -> ntypes);
4214169695Skan      if (work -> typevec[i] != NULL)
4215169695Skan	{
4216169695Skan	  free (work -> typevec[i]);
4217169695Skan	  work -> typevec[i] = NULL;
4218169695Skan	}
4219169695Skan    }
4220169695Skan}
4221169695Skan
4222169695Skan/* Process the argument list part of the signature, after any class spec
4223169695Skan   has been consumed, as well as the first 'F' character (if any).  For
4224169695Skan   example:
4225169695Skan
4226169695Skan   "__als__3fooRT0"		=>	process "RT0"
4227169695Skan   "complexfunc5__FPFPc_PFl_i"	=>	process "PFPc_PFl_i"
4228169695Skan
4229169695Skan   DECLP must be already initialised, usually non-empty.  It won't be freed
4230169695Skan   on failure.
4231169695Skan
4232169695Skan   Note that g++ differs significantly from ARM and lucid style mangling
4233169695Skan   with regards to references to previously seen types.  For example, given
4234169695Skan   the source fragment:
4235169695Skan
4236169695Skan     class foo {
4237169695Skan       public:
4238169695Skan       foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
4239169695Skan     };
4240169695Skan
4241169695Skan     foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
4242169695Skan     void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
4243169695Skan
4244169695Skan   g++ produces the names:
4245169695Skan
4246169695Skan     __3fooiRT0iT2iT2
4247169695Skan     foo__FiR3fooiT1iT1
4248169695Skan
4249169695Skan   while lcc (and presumably other ARM style compilers as well) produces:
4250169695Skan
4251169695Skan     foo__FiR3fooT1T2T1T2
4252169695Skan     __ct__3fooFiR3fooT1T2T1T2
4253169695Skan
4254169695Skan   Note that g++ bases its type numbers starting at zero and counts all
4255169695Skan   previously seen types, while lucid/ARM bases its type numbers starting
4256169695Skan   at one and only considers types after it has seen the 'F' character
4257169695Skan   indicating the start of the function args.  For lucid/ARM style, we
4258169695Skan   account for this difference by discarding any previously seen types when
4259169695Skan   we see the 'F' character, and subtracting one from the type number
4260169695Skan   reference.
4261169695Skan
4262169695Skan */
4263169695Skan
4264169695Skanstatic int
4265169695Skandemangle_args (struct work_stuff *work, const char **mangled,
4266169695Skan               string *declp)
4267169695Skan{
4268169695Skan  string arg;
4269169695Skan  int need_comma = 0;
4270169695Skan  int r;
4271169695Skan  int t;
4272169695Skan  const char *tem;
4273169695Skan  char temptype;
4274169695Skan
4275169695Skan  if (PRINT_ARG_TYPES)
4276169695Skan    {
4277169695Skan      string_append (declp, "(");
4278169695Skan      if (**mangled == '\0')
4279169695Skan	{
4280169695Skan	  string_append (declp, "void");
4281169695Skan	}
4282169695Skan    }
4283169695Skan
4284169695Skan  while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
4285169695Skan	 || work->nrepeats > 0)
4286169695Skan    {
4287169695Skan      if ((**mangled == 'N') || (**mangled == 'T'))
4288169695Skan	{
4289169695Skan	  temptype = *(*mangled)++;
4290169695Skan
4291169695Skan	  if (temptype == 'N')
4292169695Skan	    {
4293169695Skan	      if (!get_count (mangled, &r))
4294169695Skan		{
4295169695Skan		  return (0);
4296169695Skan		}
4297169695Skan	    }
4298169695Skan	  else
4299169695Skan	    {
4300169695Skan	      r = 1;
4301169695Skan	    }
4302169695Skan          if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
4303169695Skan            {
4304169695Skan              /* If we have 10 or more types we might have more than a 1 digit
4305169695Skan                 index so we'll have to consume the whole count here. This
4306169695Skan                 will lose if the next thing is a type name preceded by a
4307169695Skan                 count but it's impossible to demangle that case properly
4308169695Skan                 anyway. Eg if we already have 12 types is T12Pc "(..., type1,
4309169695Skan                 Pc, ...)"  or "(..., type12, char *, ...)" */
4310169695Skan              if ((t = consume_count(mangled)) <= 0)
4311169695Skan                {
4312169695Skan                  return (0);
4313169695Skan                }
4314169695Skan            }
4315169695Skan          else
4316169695Skan	    {
4317169695Skan	      if (!get_count (mangled, &t))
4318169695Skan	    	{
4319169695Skan	          return (0);
4320169695Skan	    	}
4321169695Skan	    }
4322169695Skan	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
4323169695Skan	    {
4324169695Skan	      t--;
4325169695Skan	    }
4326169695Skan	  /* Validate the type index.  Protect against illegal indices from
4327169695Skan	     malformed type strings.  */
4328169695Skan	  if ((t < 0) || (t >= work -> ntypes))
4329169695Skan	    {
4330169695Skan	      return (0);
4331169695Skan	    }
4332169695Skan	  while (work->nrepeats > 0 || --r >= 0)
4333169695Skan	    {
4334169695Skan	      tem = work -> typevec[t];
4335169695Skan	      if (need_comma && PRINT_ARG_TYPES)
4336169695Skan		{
4337169695Skan		  string_append (declp, ", ");
4338169695Skan		}
4339169695Skan	      if (!do_arg (work, &tem, &arg))
4340169695Skan		{
4341169695Skan		  return (0);
4342169695Skan		}
4343169695Skan	      if (PRINT_ARG_TYPES)
4344169695Skan		{
4345169695Skan		  string_appends (declp, &arg);
4346169695Skan		}
4347169695Skan	      string_delete (&arg);
4348169695Skan	      need_comma = 1;
4349169695Skan	    }
4350169695Skan	}
4351169695Skan      else
4352169695Skan	{
4353169695Skan	  if (need_comma && PRINT_ARG_TYPES)
4354169695Skan	    string_append (declp, ", ");
4355169695Skan	  if (!do_arg (work, mangled, &arg))
4356169695Skan	    return (0);
4357169695Skan	  if (PRINT_ARG_TYPES)
4358169695Skan	    string_appends (declp, &arg);
4359169695Skan	  string_delete (&arg);
4360169695Skan	  need_comma = 1;
4361169695Skan	}
4362169695Skan    }
4363169695Skan
4364169695Skan  if (**mangled == 'e')
4365169695Skan    {
4366169695Skan      (*mangled)++;
4367169695Skan      if (PRINT_ARG_TYPES)
4368169695Skan	{
4369169695Skan	  if (need_comma)
4370169695Skan	    {
4371169695Skan	      string_append (declp, ",");
4372169695Skan	    }
4373169695Skan	  string_append (declp, "...");
4374169695Skan	}
4375169695Skan    }
4376169695Skan
4377169695Skan  if (PRINT_ARG_TYPES)
4378169695Skan    {
4379169695Skan      string_append (declp, ")");
4380169695Skan    }
4381169695Skan  return (1);
4382169695Skan}
4383169695Skan
4384169695Skan/* Like demangle_args, but for demangling the argument lists of function
4385169695Skan   and method pointers or references, not top-level declarations.  */
4386169695Skan
4387169695Skanstatic int
4388169695Skandemangle_nested_args (struct work_stuff *work, const char **mangled,
4389169695Skan                      string *declp)
4390169695Skan{
4391169695Skan  string* saved_previous_argument;
4392169695Skan  int result;
4393169695Skan  int saved_nrepeats;
4394169695Skan
4395169695Skan  /* The G++ name-mangling algorithm does not remember types on nested
4396169695Skan     argument lists, unless -fsquangling is used, and in that case the
4397169695Skan     type vector updated by remember_type is not used.  So, we turn
4398169695Skan     off remembering of types here.  */
4399169695Skan  ++work->forgetting_types;
4400169695Skan
4401169695Skan  /* For the repeat codes used with -fsquangling, we must keep track of
4402169695Skan     the last argument.  */
4403169695Skan  saved_previous_argument = work->previous_argument;
4404169695Skan  saved_nrepeats = work->nrepeats;
4405169695Skan  work->previous_argument = 0;
4406169695Skan  work->nrepeats = 0;
4407169695Skan
4408169695Skan  /* Actually demangle the arguments.  */
4409169695Skan  result = demangle_args (work, mangled, declp);
4410169695Skan
4411169695Skan  /* Restore the previous_argument field.  */
4412169695Skan  if (work->previous_argument)
4413169695Skan    {
4414169695Skan      string_delete (work->previous_argument);
4415169695Skan      free ((char *) work->previous_argument);
4416169695Skan    }
4417169695Skan  work->previous_argument = saved_previous_argument;
4418169695Skan  --work->forgetting_types;
4419169695Skan  work->nrepeats = saved_nrepeats;
4420169695Skan
4421169695Skan  return result;
4422169695Skan}
4423169695Skan
4424169695Skanstatic void
4425169695Skandemangle_function_name (struct work_stuff *work, const char **mangled,
4426169695Skan                        string *declp, const char *scan)
4427169695Skan{
4428169695Skan  size_t i;
4429169695Skan  string type;
4430169695Skan  const char *tem;
4431169695Skan
4432169695Skan  string_appendn (declp, (*mangled), scan - (*mangled));
4433169695Skan  string_need (declp, 1);
4434169695Skan  *(declp -> p) = '\0';
4435169695Skan
4436169695Skan  /* Consume the function name, including the "__" separating the name
4437169695Skan     from the signature.  We are guaranteed that SCAN points to the
4438169695Skan     separator.  */
4439169695Skan
4440169695Skan  (*mangled) = scan + 2;
4441169695Skan  /* We may be looking at an instantiation of a template function:
4442169695Skan     foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
4443169695Skan     following _F marks the start of the function arguments.  Handle
4444169695Skan     the template arguments first. */
4445169695Skan
4446169695Skan  if (HP_DEMANGLING && (**mangled == 'X'))
4447169695Skan    {
4448169695Skan      demangle_arm_hp_template (work, mangled, 0, declp);
4449169695Skan      /* This leaves MANGLED pointing to the 'F' marking func args */
4450169695Skan    }
4451169695Skan
4452169695Skan  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
4453169695Skan    {
4454169695Skan
4455169695Skan      /* See if we have an ARM style constructor or destructor operator.
4456169695Skan	 If so, then just record it, clear the decl, and return.
4457169695Skan	 We can't build the actual constructor/destructor decl until later,
4458169695Skan	 when we recover the class name from the signature.  */
4459169695Skan
4460169695Skan      if (strcmp (declp -> b, "__ct") == 0)
4461169695Skan	{
4462169695Skan	  work -> constructor += 1;
4463169695Skan	  string_clear (declp);
4464169695Skan	  return;
4465169695Skan	}
4466169695Skan      else if (strcmp (declp -> b, "__dt") == 0)
4467169695Skan	{
4468169695Skan	  work -> destructor += 1;
4469169695Skan	  string_clear (declp);
4470169695Skan	  return;
4471169695Skan	}
4472169695Skan    }
4473169695Skan
4474169695Skan  if (declp->p - declp->b >= 3
4475169695Skan      && declp->b[0] == 'o'
4476169695Skan      && declp->b[1] == 'p'
4477169695Skan      && strchr (cplus_markers, declp->b[2]) != NULL)
4478169695Skan    {
4479169695Skan      /* see if it's an assignment expression */
4480169695Skan      if (declp->p - declp->b >= 10 /* op$assign_ */
4481169695Skan	  && memcmp (declp->b + 3, "assign_", 7) == 0)
4482169695Skan	{
4483169695Skan	  for (i = 0; i < ARRAY_SIZE (optable); i++)
4484169695Skan	    {
4485169695Skan	      int len = declp->p - declp->b - 10;
4486169695Skan	      if ((int) strlen (optable[i].in) == len
4487169695Skan		  && memcmp (optable[i].in, declp->b + 10, len) == 0)
4488169695Skan		{
4489169695Skan		  string_clear (declp);
4490169695Skan		  string_append (declp, "operator");
4491169695Skan		  string_append (declp, optable[i].out);
4492169695Skan		  string_append (declp, "=");
4493169695Skan		  break;
4494169695Skan		}
4495169695Skan	    }
4496169695Skan	}
4497169695Skan      else
4498169695Skan	{
4499169695Skan	  for (i = 0; i < ARRAY_SIZE (optable); i++)
4500169695Skan	    {
4501169695Skan	      int len = declp->p - declp->b - 3;
4502169695Skan	      if ((int) strlen (optable[i].in) == len
4503169695Skan		  && memcmp (optable[i].in, declp->b + 3, len) == 0)
4504169695Skan		{
4505169695Skan		  string_clear (declp);
4506169695Skan		  string_append (declp, "operator");
4507169695Skan		  string_append (declp, optable[i].out);
4508169695Skan		  break;
4509169695Skan		}
4510169695Skan	    }
4511169695Skan	}
4512169695Skan    }
4513169695Skan  else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
4514169695Skan	   && strchr (cplus_markers, declp->b[4]) != NULL)
4515169695Skan    {
4516169695Skan      /* type conversion operator */
4517169695Skan      tem = declp->b + 5;
4518169695Skan      if (do_type (work, &tem, &type))
4519169695Skan	{
4520169695Skan	  string_clear (declp);
4521169695Skan	  string_append (declp, "operator ");
4522169695Skan	  string_appends (declp, &type);
4523169695Skan	  string_delete (&type);
4524169695Skan	}
4525169695Skan    }
4526169695Skan  else if (declp->b[0] == '_' && declp->b[1] == '_'
4527169695Skan	   && declp->b[2] == 'o' && declp->b[3] == 'p')
4528169695Skan    {
4529169695Skan      /* ANSI.  */
4530169695Skan      /* type conversion operator.  */
4531169695Skan      tem = declp->b + 4;
4532169695Skan      if (do_type (work, &tem, &type))
4533169695Skan	{
4534169695Skan	  string_clear (declp);
4535169695Skan	  string_append (declp, "operator ");
4536169695Skan	  string_appends (declp, &type);
4537169695Skan	  string_delete (&type);
4538169695Skan	}
4539169695Skan    }
4540169695Skan  else if (declp->b[0] == '_' && declp->b[1] == '_'
4541169695Skan	   && ISLOWER((unsigned char)declp->b[2])
4542169695Skan	   && ISLOWER((unsigned char)declp->b[3]))
4543169695Skan    {
4544169695Skan      if (declp->b[4] == '\0')
4545169695Skan	{
4546169695Skan	  /* Operator.  */
4547169695Skan	  for (i = 0; i < ARRAY_SIZE (optable); i++)
4548169695Skan	    {
4549169695Skan	      if (strlen (optable[i].in) == 2
4550169695Skan		  && memcmp (optable[i].in, declp->b + 2, 2) == 0)
4551169695Skan		{
4552169695Skan		  string_clear (declp);
4553169695Skan		  string_append (declp, "operator");
4554169695Skan		  string_append (declp, optable[i].out);
4555169695Skan		  break;
4556169695Skan		}
4557169695Skan	    }
4558169695Skan	}
4559169695Skan      else
4560169695Skan	{
4561169695Skan	  if (declp->b[2] == 'a' && declp->b[5] == '\0')
4562169695Skan	    {
4563169695Skan	      /* Assignment.  */
4564169695Skan	      for (i = 0; i < ARRAY_SIZE (optable); i++)
4565169695Skan		{
4566169695Skan		  if (strlen (optable[i].in) == 3
4567169695Skan		      && memcmp (optable[i].in, declp->b + 2, 3) == 0)
4568169695Skan		    {
4569169695Skan		      string_clear (declp);
4570169695Skan		      string_append (declp, "operator");
4571169695Skan		      string_append (declp, optable[i].out);
4572169695Skan		      break;
4573169695Skan		    }
4574169695Skan		}
4575169695Skan	    }
4576169695Skan	}
4577169695Skan    }
4578169695Skan}
4579169695Skan
4580169695Skan/* a mini string-handling package */
4581169695Skan
4582169695Skanstatic void
4583169695Skanstring_need (string *s, int n)
4584169695Skan{
4585169695Skan  int tem;
4586169695Skan
4587169695Skan  if (s->b == NULL)
4588169695Skan    {
4589169695Skan      if (n < 32)
4590169695Skan	{
4591169695Skan	  n = 32;
4592169695Skan	}
4593169695Skan      s->p = s->b = XNEWVEC (char, n);
4594169695Skan      s->e = s->b + n;
4595169695Skan    }
4596169695Skan  else if (s->e - s->p < n)
4597169695Skan    {
4598169695Skan      tem = s->p - s->b;
4599169695Skan      n += tem;
4600169695Skan      n *= 2;
4601169695Skan      s->b = XRESIZEVEC (char, s->b, n);
4602169695Skan      s->p = s->b + tem;
4603169695Skan      s->e = s->b + n;
4604169695Skan    }
4605169695Skan}
4606169695Skan
4607169695Skanstatic void
4608169695Skanstring_delete (string *s)
4609169695Skan{
4610169695Skan  if (s->b != NULL)
4611169695Skan    {
4612169695Skan      free (s->b);
4613169695Skan      s->b = s->e = s->p = NULL;
4614169695Skan    }
4615169695Skan}
4616169695Skan
4617169695Skanstatic void
4618169695Skanstring_init (string *s)
4619169695Skan{
4620169695Skan  s->b = s->p = s->e = NULL;
4621169695Skan}
4622169695Skan
4623169695Skanstatic void
4624169695Skanstring_clear (string *s)
4625169695Skan{
4626169695Skan  s->p = s->b;
4627169695Skan}
4628169695Skan
4629169695Skan#if 0
4630169695Skan
4631169695Skanstatic int
4632169695Skanstring_empty (string *s)
4633169695Skan{
4634169695Skan  return (s->b == s->p);
4635169695Skan}
4636169695Skan
4637169695Skan#endif
4638169695Skan
4639169695Skanstatic void
4640169695Skanstring_append (string *p, const char *s)
4641169695Skan{
4642169695Skan  int n;
4643169695Skan  if (s == NULL || *s == '\0')
4644169695Skan    return;
4645169695Skan  n = strlen (s);
4646169695Skan  string_need (p, n);
4647169695Skan  memcpy (p->p, s, n);
4648169695Skan  p->p += n;
4649169695Skan}
4650169695Skan
4651169695Skanstatic void
4652169695Skanstring_appends (string *p, string *s)
4653169695Skan{
4654169695Skan  int n;
4655169695Skan
4656169695Skan  if (s->b != s->p)
4657169695Skan    {
4658169695Skan      n = s->p - s->b;
4659169695Skan      string_need (p, n);
4660169695Skan      memcpy (p->p, s->b, n);
4661169695Skan      p->p += n;
4662169695Skan    }
4663169695Skan}
4664169695Skan
4665169695Skanstatic void
4666169695Skanstring_appendn (string *p, const char *s, int n)
4667169695Skan{
4668169695Skan  if (n != 0)
4669169695Skan    {
4670169695Skan      string_need (p, n);
4671169695Skan      memcpy (p->p, s, n);
4672169695Skan      p->p += n;
4673169695Skan    }
4674169695Skan}
4675169695Skan
4676169695Skanstatic void
4677169695Skanstring_prepend (string *p, const char *s)
4678169695Skan{
4679169695Skan  if (s != NULL && *s != '\0')
4680169695Skan    {
4681169695Skan      string_prependn (p, s, strlen (s));
4682169695Skan    }
4683169695Skan}
4684169695Skan
4685169695Skanstatic void
4686169695Skanstring_prepends (string *p, string *s)
4687169695Skan{
4688169695Skan  if (s->b != s->p)
4689169695Skan    {
4690169695Skan      string_prependn (p, s->b, s->p - s->b);
4691169695Skan    }
4692169695Skan}
4693169695Skan
4694169695Skanstatic void
4695169695Skanstring_prependn (string *p, const char *s, int n)
4696169695Skan{
4697169695Skan  char *q;
4698169695Skan
4699169695Skan  if (n != 0)
4700169695Skan    {
4701169695Skan      string_need (p, n);
4702169695Skan      for (q = p->p - 1; q >= p->b; q--)
4703169695Skan	{
4704169695Skan	  q[n] = q[0];
4705169695Skan	}
4706169695Skan      memcpy (p->b, s, n);
4707169695Skan      p->p += n;
4708169695Skan    }
4709169695Skan}
4710169695Skan
4711169695Skanstatic void
4712169695Skanstring_append_template_idx (string *s, int idx)
4713169695Skan{
4714169695Skan  char buf[INTBUF_SIZE + 1 /* 'T' */];
4715169695Skan  sprintf(buf, "T%d", idx);
4716169695Skan  string_append (s, buf);
4717169695Skan}
4718