xref: /openbsd-src/gnu/lib/libiberty/src/cplus-dem.c (revision 150b7e42cfa21e6546d96ae514ca23e80d970ac7)
100bf4279Sespie /* Demangler for GNU C++
237c53322Sespie    Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
3*150b7e42Smiod    2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
400bf4279Sespie    Written by James Clark (jjc@jclark.uucp)
500bf4279Sespie    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
600bf4279Sespie    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
700bf4279Sespie 
800bf4279Sespie This file is part of the libiberty library.
900bf4279Sespie Libiberty is free software; you can redistribute it and/or
1000bf4279Sespie modify it under the terms of the GNU Library General Public
1100bf4279Sespie License as published by the Free Software Foundation; either
1200bf4279Sespie version 2 of the License, or (at your option) any later version.
1300bf4279Sespie 
1437c53322Sespie In addition to the permissions in the GNU Library General Public
1537c53322Sespie License, the Free Software Foundation gives you unlimited permission
1637c53322Sespie to link the compiled version of this file into combinations with other
1737c53322Sespie programs, and to distribute those combinations without any restriction
1837c53322Sespie coming from the use of this file.  (The Library Public License
1937c53322Sespie restrictions do apply in other respects; for example, they cover
2037c53322Sespie modification of the file, and distribution when not linked into a
2137c53322Sespie combined executable.)
2237c53322Sespie 
2300bf4279Sespie Libiberty is distributed in the hope that it will be useful,
2400bf4279Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
2500bf4279Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2600bf4279Sespie Library General Public License for more details.
2700bf4279Sespie 
2800bf4279Sespie You should have received a copy of the GNU Library General Public
2900bf4279Sespie License along with libiberty; see the file COPYING.LIB.  If
30*150b7e42Smiod not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
31*150b7e42Smiod Boston, MA 02110-1301, USA.  */
3200bf4279Sespie 
3300bf4279Sespie /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
3400bf4279Sespie 
3500bf4279Sespie    This file imports xmalloc and xrealloc, which are like malloc and
3600bf4279Sespie    realloc except that they generate a fatal error if there is no
3700bf4279Sespie    available memory.  */
3800bf4279Sespie 
3900bf4279Sespie /* This file lives in both GCC and libiberty.  When making changes, please
4000bf4279Sespie    try not to break either.  */
4100bf4279Sespie 
4200bf4279Sespie #ifdef HAVE_CONFIG_H
4300bf4279Sespie #include "config.h"
4400bf4279Sespie #endif
4500bf4279Sespie 
4637c53322Sespie #include "safe-ctype.h"
4737c53322Sespie 
4800bf4279Sespie #include <sys/types.h>
4900bf4279Sespie #include <string.h>
5000bf4279Sespie #include <stdio.h>
5100bf4279Sespie 
5200bf4279Sespie #ifdef HAVE_STDLIB_H
5300bf4279Sespie #include <stdlib.h>
5400bf4279Sespie #else
5500bf4279Sespie char * malloc ();
5600bf4279Sespie char * realloc ();
5700bf4279Sespie #endif
5800bf4279Sespie 
5900bf4279Sespie #include <demangle.h>
6000bf4279Sespie #undef CURRENT_DEMANGLING_STYLE
6100bf4279Sespie #define CURRENT_DEMANGLING_STYLE work->options
6200bf4279Sespie 
6300bf4279Sespie #include "libiberty.h"
6400bf4279Sespie 
65*150b7e42Smiod static char *ada_demangle (const char *, int);
6637c53322Sespie 
6700bf4279Sespie #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
6800bf4279Sespie 
6937c53322Sespie /* A value at least one greater than the maximum number of characters
7037c53322Sespie    that will be output when using the `%d' format with `printf'.  */
7137c53322Sespie #define INTBUF_SIZE 32
7200bf4279Sespie 
73*150b7e42Smiod extern void fancy_abort (void) ATTRIBUTE_NORETURN;
7400bf4279Sespie 
7500bf4279Sespie /* In order to allow a single demangler executable to demangle strings
7600bf4279Sespie    using various common values of CPLUS_MARKER, as well as any specific
7700bf4279Sespie    one set at compile time, we maintain a string containing all the
7800bf4279Sespie    commonly used ones, and check to see if the marker we are looking for
7900bf4279Sespie    is in that string.  CPLUS_MARKER is usually '$' on systems where the
8000bf4279Sespie    assembler can deal with that.  Where the assembler can't, it's usually
8100bf4279Sespie    '.' (but on many systems '.' is used for other things).  We put the
8200bf4279Sespie    current defined CPLUS_MARKER first (which defaults to '$'), followed
8300bf4279Sespie    by the next most common value, followed by an explicit '$' in case
8400bf4279Sespie    the value of CPLUS_MARKER is not '$'.
8500bf4279Sespie 
8600bf4279Sespie    We could avoid this if we could just get g++ to tell us what the actual
8700bf4279Sespie    cplus marker character is as part of the debug information, perhaps by
8800bf4279Sespie    ensuring that it is the character that terminates the gcc<n>_compiled
8900bf4279Sespie    marker symbol (FIXME).  */
9000bf4279Sespie 
9100bf4279Sespie #if !defined (CPLUS_MARKER)
9200bf4279Sespie #define CPLUS_MARKER '$'
9300bf4279Sespie #endif
9400bf4279Sespie 
9537c53322Sespie enum demangling_styles current_demangling_style = auto_demangling;
9600bf4279Sespie 
9700bf4279Sespie static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
9800bf4279Sespie 
9900bf4279Sespie static char char_str[2] = { '\000', '\000' };
10000bf4279Sespie 
10100bf4279Sespie void
set_cplus_marker_for_demangling(int ch)102*150b7e42Smiod set_cplus_marker_for_demangling (int ch)
10300bf4279Sespie {
10400bf4279Sespie   cplus_markers[0] = ch;
10500bf4279Sespie }
10600bf4279Sespie 
10700bf4279Sespie typedef struct string		/* Beware: these aren't required to be */
10800bf4279Sespie {				/*  '\0' terminated.  */
10900bf4279Sespie   char *b;			/* pointer to start of string */
11000bf4279Sespie   char *p;			/* pointer after last character */
11100bf4279Sespie   char *e;			/* pointer after end of allocated space */
11200bf4279Sespie } string;
11300bf4279Sespie 
11400bf4279Sespie /* Stuff that is shared between sub-routines.
11500bf4279Sespie    Using a shared structure allows cplus_demangle to be reentrant.  */
11600bf4279Sespie 
11700bf4279Sespie struct work_stuff
11800bf4279Sespie {
11900bf4279Sespie   int options;
12000bf4279Sespie   char **typevec;
12100bf4279Sespie   char **ktypevec;
12200bf4279Sespie   char **btypevec;
12300bf4279Sespie   int numk;
12400bf4279Sespie   int numb;
12500bf4279Sespie   int ksize;
12600bf4279Sespie   int bsize;
12700bf4279Sespie   int ntypes;
12800bf4279Sespie   int typevec_size;
12900bf4279Sespie   int constructor;
13000bf4279Sespie   int destructor;
13100bf4279Sespie   int static_type;	/* A static member function */
13200bf4279Sespie   int temp_start;       /* index in demangled to start of template args */
13300bf4279Sespie   int type_quals;       /* The type qualifiers.  */
13400bf4279Sespie   int dllimported;	/* Symbol imported from a PE DLL */
13500bf4279Sespie   char **tmpl_argvec;   /* Template function arguments. */
13600bf4279Sespie   int ntmpl_args;       /* The number of template function arguments. */
13700bf4279Sespie   int forgetting_types; /* Nonzero if we are not remembering the types
13800bf4279Sespie 			   we see.  */
13900bf4279Sespie   string* previous_argument; /* The last function argument demangled.  */
14000bf4279Sespie   int nrepeats;         /* The number of times to repeat the previous
14100bf4279Sespie 			   argument.  */
14200bf4279Sespie };
14300bf4279Sespie 
14400bf4279Sespie #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
14500bf4279Sespie #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
14600bf4279Sespie 
14700bf4279Sespie static const struct optable
14800bf4279Sespie {
14937c53322Sespie   const char *const in;
15037c53322Sespie   const char *const out;
15137c53322Sespie   const int flags;
15200bf4279Sespie } optable[] = {
15300bf4279Sespie   {"nw",	  " new",	DMGL_ANSI},	/* new (1.92,	 ansi) */
15400bf4279Sespie   {"dl",	  " delete",	DMGL_ANSI},	/* new (1.92,	 ansi) */
15500bf4279Sespie   {"new",	  " new",	0},		/* old (1.91,	 and 1.x) */
15600bf4279Sespie   {"delete",	  " delete",	0},		/* old (1.91,	 and 1.x) */
15700bf4279Sespie   {"vn",	  " new []",	DMGL_ANSI},	/* GNU, pending ansi */
15800bf4279Sespie   {"vd",	  " delete []",	DMGL_ANSI},	/* GNU, pending ansi */
15900bf4279Sespie   {"as",	  "=",		DMGL_ANSI},	/* ansi */
16000bf4279Sespie   {"ne",	  "!=",		DMGL_ANSI},	/* old, ansi */
16100bf4279Sespie   {"eq",	  "==",		DMGL_ANSI},	/* old,	ansi */
16200bf4279Sespie   {"ge",	  ">=",		DMGL_ANSI},	/* old,	ansi */
16300bf4279Sespie   {"gt",	  ">",		DMGL_ANSI},	/* old,	ansi */
16400bf4279Sespie   {"le",	  "<=",		DMGL_ANSI},	/* old,	ansi */
16500bf4279Sespie   {"lt",	  "<",		DMGL_ANSI},	/* old,	ansi */
16600bf4279Sespie   {"plus",	  "+",		0},		/* old */
16700bf4279Sespie   {"pl",	  "+",		DMGL_ANSI},	/* ansi */
16800bf4279Sespie   {"apl",	  "+=",		DMGL_ANSI},	/* ansi */
16900bf4279Sespie   {"minus",	  "-",		0},		/* old */
17000bf4279Sespie   {"mi",	  "-",		DMGL_ANSI},	/* ansi */
17100bf4279Sespie   {"ami",	  "-=",		DMGL_ANSI},	/* ansi */
17200bf4279Sespie   {"mult",	  "*",		0},		/* old */
17300bf4279Sespie   {"ml",	  "*",		DMGL_ANSI},	/* ansi */
17400bf4279Sespie   {"amu",	  "*=",		DMGL_ANSI},	/* ansi (ARM/Lucid) */
17500bf4279Sespie   {"aml",	  "*=",		DMGL_ANSI},	/* ansi (GNU/g++) */
17600bf4279Sespie   {"convert",	  "+",		0},		/* old (unary +) */
17700bf4279Sespie   {"negate",	  "-",		0},		/* old (unary -) */
17800bf4279Sespie   {"trunc_mod",	  "%",		0},		/* old */
17900bf4279Sespie   {"md",	  "%",		DMGL_ANSI},	/* ansi */
18000bf4279Sespie   {"amd",	  "%=",		DMGL_ANSI},	/* ansi */
18100bf4279Sespie   {"trunc_div",	  "/",		0},		/* old */
18200bf4279Sespie   {"dv",	  "/",		DMGL_ANSI},	/* ansi */
18300bf4279Sespie   {"adv",	  "/=",		DMGL_ANSI},	/* ansi */
18400bf4279Sespie   {"truth_andif", "&&",		0},		/* old */
18500bf4279Sespie   {"aa",	  "&&",		DMGL_ANSI},	/* ansi */
18600bf4279Sespie   {"truth_orif",  "||",		0},		/* old */
18700bf4279Sespie   {"oo",	  "||",		DMGL_ANSI},	/* ansi */
18800bf4279Sespie   {"truth_not",	  "!",		0},		/* old */
18900bf4279Sespie   {"nt",	  "!",		DMGL_ANSI},	/* ansi */
19000bf4279Sespie   {"postincrement","++",	0},		/* old */
19100bf4279Sespie   {"pp",	  "++",		DMGL_ANSI},	/* ansi */
19200bf4279Sespie   {"postdecrement","--",	0},		/* old */
19300bf4279Sespie   {"mm",	  "--",		DMGL_ANSI},	/* ansi */
19400bf4279Sespie   {"bit_ior",	  "|",		0},		/* old */
19500bf4279Sespie   {"or",	  "|",		DMGL_ANSI},	/* ansi */
19600bf4279Sespie   {"aor",	  "|=",		DMGL_ANSI},	/* ansi */
19700bf4279Sespie   {"bit_xor",	  "^",		0},		/* old */
19800bf4279Sespie   {"er",	  "^",		DMGL_ANSI},	/* ansi */
19900bf4279Sespie   {"aer",	  "^=",		DMGL_ANSI},	/* ansi */
20000bf4279Sespie   {"bit_and",	  "&",		0},		/* old */
20100bf4279Sespie   {"ad",	  "&",		DMGL_ANSI},	/* ansi */
20200bf4279Sespie   {"aad",	  "&=",		DMGL_ANSI},	/* ansi */
20300bf4279Sespie   {"bit_not",	  "~",		0},		/* old */
20400bf4279Sespie   {"co",	  "~",		DMGL_ANSI},	/* ansi */
20500bf4279Sespie   {"call",	  "()",		0},		/* old */
20600bf4279Sespie   {"cl",	  "()",		DMGL_ANSI},	/* ansi */
20700bf4279Sespie   {"alshift",	  "<<",		0},		/* old */
20800bf4279Sespie   {"ls",	  "<<",		DMGL_ANSI},	/* ansi */
20900bf4279Sespie   {"als",	  "<<=",	DMGL_ANSI},	/* ansi */
21000bf4279Sespie   {"arshift",	  ">>",		0},		/* old */
21100bf4279Sespie   {"rs",	  ">>",		DMGL_ANSI},	/* ansi */
21200bf4279Sespie   {"ars",	  ">>=",	DMGL_ANSI},	/* ansi */
21300bf4279Sespie   {"component",	  "->",		0},		/* old */
21400bf4279Sespie   {"pt",	  "->",		DMGL_ANSI},	/* ansi; Lucid C++ form */
21500bf4279Sespie   {"rf",	  "->",		DMGL_ANSI},	/* ansi; ARM/GNU form */
21600bf4279Sespie   {"indirect",	  "*",		0},		/* old */
21700bf4279Sespie   {"method_call",  "->()",	0},		/* old */
21800bf4279Sespie   {"addr",	  "&",		0},		/* old (unary &) */
21900bf4279Sespie   {"array",	  "[]",		0},		/* old */
22000bf4279Sespie   {"vc",	  "[]",		DMGL_ANSI},	/* ansi */
22100bf4279Sespie   {"compound",	  ", ",		0},		/* old */
22200bf4279Sespie   {"cm",	  ", ",		DMGL_ANSI},	/* ansi */
22300bf4279Sespie   {"cond",	  "?:",		0},		/* old */
22400bf4279Sespie   {"cn",	  "?:",		DMGL_ANSI},	/* pseudo-ansi */
22500bf4279Sespie   {"max",	  ">?",		0},		/* old */
22600bf4279Sespie   {"mx",	  ">?",		DMGL_ANSI},	/* pseudo-ansi */
22700bf4279Sespie   {"min",	  "<?",		0},		/* old */
22800bf4279Sespie   {"mn",	  "<?",		DMGL_ANSI},	/* pseudo-ansi */
22900bf4279Sespie   {"nop",	  "",		0},		/* old (for operator=) */
23000bf4279Sespie   {"rm",	  "->*",	DMGL_ANSI},	/* ansi */
23100bf4279Sespie   {"sz",          "sizeof ",    DMGL_ANSI}      /* pseudo-ansi */
23200bf4279Sespie };
23300bf4279Sespie 
23400bf4279Sespie /* These values are used to indicate the various type varieties.
23500bf4279Sespie    They are all non-zero so that they can be used as `success'
23600bf4279Sespie    values.  */
23700bf4279Sespie typedef enum type_kind_t
23800bf4279Sespie {
23900bf4279Sespie   tk_none,
24000bf4279Sespie   tk_pointer,
24100bf4279Sespie   tk_reference,
24200bf4279Sespie   tk_integral,
24300bf4279Sespie   tk_bool,
24400bf4279Sespie   tk_char,
24500bf4279Sespie   tk_real
24600bf4279Sespie } type_kind_t;
24700bf4279Sespie 
24837c53322Sespie const struct demangler_engine libiberty_demanglers[] =
2492e0724c7Sespie {
2502e0724c7Sespie   {
25137c53322Sespie     NO_DEMANGLING_STYLE_STRING,
25237c53322Sespie     no_demangling,
25337c53322Sespie     "Demangling disabled"
25437c53322Sespie   }
25537c53322Sespie   ,
25637c53322Sespie   {
2572e0724c7Sespie     AUTO_DEMANGLING_STYLE_STRING,
2582e0724c7Sespie       auto_demangling,
2592e0724c7Sespie       "Automatic selection based on executable"
2602e0724c7Sespie   }
2612e0724c7Sespie   ,
2622e0724c7Sespie   {
2632e0724c7Sespie     GNU_DEMANGLING_STYLE_STRING,
2642e0724c7Sespie       gnu_demangling,
2652e0724c7Sespie       "GNU (g++) style demangling"
2662e0724c7Sespie   }
2672e0724c7Sespie   ,
2682e0724c7Sespie   {
2692e0724c7Sespie     LUCID_DEMANGLING_STYLE_STRING,
2702e0724c7Sespie       lucid_demangling,
2712e0724c7Sespie       "Lucid (lcc) style demangling"
2722e0724c7Sespie   }
2732e0724c7Sespie   ,
2742e0724c7Sespie   {
2752e0724c7Sespie     ARM_DEMANGLING_STYLE_STRING,
2762e0724c7Sespie       arm_demangling,
2772e0724c7Sespie       "ARM style demangling"
2782e0724c7Sespie   }
2792e0724c7Sespie   ,
2802e0724c7Sespie   {
2812e0724c7Sespie     HP_DEMANGLING_STYLE_STRING,
2822e0724c7Sespie       hp_demangling,
2832e0724c7Sespie       "HP (aCC) style demangling"
2842e0724c7Sespie   }
2852e0724c7Sespie   ,
2862e0724c7Sespie   {
2872e0724c7Sespie     EDG_DEMANGLING_STYLE_STRING,
2882e0724c7Sespie       edg_demangling,
2892e0724c7Sespie       "EDG style demangling"
2902e0724c7Sespie   }
2912e0724c7Sespie   ,
2922e0724c7Sespie   {
29337c53322Sespie     GNU_V3_DEMANGLING_STYLE_STRING,
29437c53322Sespie     gnu_v3_demangling,
29537c53322Sespie     "GNU (g++) V3 ABI-style demangling"
29637c53322Sespie   }
29737c53322Sespie   ,
29837c53322Sespie   {
29937c53322Sespie     JAVA_DEMANGLING_STYLE_STRING,
30037c53322Sespie     java_demangling,
30137c53322Sespie     "Java style demangling"
30237c53322Sespie   }
30337c53322Sespie   ,
30437c53322Sespie   {
30537c53322Sespie     GNAT_DEMANGLING_STYLE_STRING,
30637c53322Sespie     gnat_demangling,
30737c53322Sespie     "GNAT style demangling"
30837c53322Sespie   }
30937c53322Sespie   ,
31037c53322Sespie   {
3112e0724c7Sespie     NULL, unknown_demangling, NULL
3122e0724c7Sespie   }
3132e0724c7Sespie };
3142e0724c7Sespie 
31500bf4279Sespie #define STRING_EMPTY(str)	((str) -> b == (str) -> p)
31600bf4279Sespie #define APPEND_BLANK(str)	{if (!STRING_EMPTY(str)) \
31700bf4279Sespie     string_append(str, " ");}
31800bf4279Sespie #define LEN_STRING(str)         ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
31900bf4279Sespie 
32000bf4279Sespie /* The scope separator appropriate for the language being demangled.  */
32100bf4279Sespie 
32200bf4279Sespie #define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
32300bf4279Sespie 
32400bf4279Sespie #define ARM_VTABLE_STRING "__vtbl__"	/* Lucid/ARM virtual table prefix */
32500bf4279Sespie #define ARM_VTABLE_STRLEN 8		/* strlen (ARM_VTABLE_STRING) */
32600bf4279Sespie 
32700bf4279Sespie /* Prototypes for local functions */
32800bf4279Sespie 
329*150b7e42Smiod static void delete_work_stuff (struct work_stuff *);
33037c53322Sespie 
331*150b7e42Smiod static void delete_non_B_K_work_stuff (struct work_stuff *);
33237c53322Sespie 
333*150b7e42Smiod static char *mop_up (struct work_stuff *, string *, int);
33400bf4279Sespie 
335*150b7e42Smiod static void squangle_mop_up (struct work_stuff *);
33600bf4279Sespie 
337*150b7e42Smiod static void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *);
33837c53322Sespie 
33900bf4279Sespie #if 0
34000bf4279Sespie static int
341*150b7e42Smiod demangle_method_args (struct work_stuff *, const char **, string *);
34200bf4279Sespie #endif
34300bf4279Sespie 
34400bf4279Sespie static char *
345*150b7e42Smiod internal_cplus_demangle (struct work_stuff *, const char *);
34600bf4279Sespie 
34700bf4279Sespie static int
348*150b7e42Smiod demangle_template_template_parm (struct work_stuff *work,
349*150b7e42Smiod                                  const char **, string *);
35000bf4279Sespie 
35100bf4279Sespie static int
352*150b7e42Smiod demangle_template (struct work_stuff *work, const char **, string *,
353*150b7e42Smiod                    string *, int, int);
35400bf4279Sespie 
35500bf4279Sespie static int
356*150b7e42Smiod arm_pt (struct work_stuff *, const char *, int, const char **,
357*150b7e42Smiod         const char **);
35800bf4279Sespie 
35900bf4279Sespie static int
360*150b7e42Smiod demangle_class_name (struct work_stuff *, const char **, string *);
36100bf4279Sespie 
36200bf4279Sespie static int
363*150b7e42Smiod demangle_qualified (struct work_stuff *, const char **, string *,
364*150b7e42Smiod                     int, int);
36500bf4279Sespie 
366*150b7e42Smiod static int demangle_class (struct work_stuff *, const char **, string *);
36700bf4279Sespie 
368*150b7e42Smiod static int demangle_fund_type (struct work_stuff *, const char **, string *);
36900bf4279Sespie 
370*150b7e42Smiod static int demangle_signature (struct work_stuff *, const char **, string *);
37100bf4279Sespie 
372*150b7e42Smiod static int demangle_prefix (struct work_stuff *, const char **, string *);
37300bf4279Sespie 
374*150b7e42Smiod static int gnu_special (struct work_stuff *, const char **, string *);
37500bf4279Sespie 
376*150b7e42Smiod static int arm_special (const char **, string *);
377*150b7e42Smiod 
378*150b7e42Smiod static void string_need (string *, int);
379*150b7e42Smiod 
380*150b7e42Smiod static void string_delete (string *);
38100bf4279Sespie 
38200bf4279Sespie static void
383*150b7e42Smiod string_init (string *);
38400bf4279Sespie 
385*150b7e42Smiod static void string_clear (string *);
38600bf4279Sespie 
38700bf4279Sespie #if 0
388*150b7e42Smiod static int string_empty (string *);
38900bf4279Sespie #endif
39000bf4279Sespie 
391*150b7e42Smiod static void string_append (string *, const char *);
392*150b7e42Smiod 
393*150b7e42Smiod static void string_appends (string *, string *);
394*150b7e42Smiod 
395*150b7e42Smiod static void string_appendn (string *, const char *, int);
396*150b7e42Smiod 
397*150b7e42Smiod static void string_prepend (string *, const char *);
398*150b7e42Smiod 
399*150b7e42Smiod static void string_prependn (string *, const char *, int);
400*150b7e42Smiod 
401*150b7e42Smiod static void string_append_template_idx (string *, int);
402*150b7e42Smiod 
403*150b7e42Smiod static int get_count (const char **, int *);
404*150b7e42Smiod 
405*150b7e42Smiod static int consume_count (const char **);
406*150b7e42Smiod 
407*150b7e42Smiod static int consume_count_with_underscores (const char**);
408*150b7e42Smiod 
409*150b7e42Smiod static int demangle_args (struct work_stuff *, const char **, string *);
410*150b7e42Smiod 
411*150b7e42Smiod static int demangle_nested_args (struct work_stuff*, const char**, string*);
412*150b7e42Smiod 
413*150b7e42Smiod static int do_type (struct work_stuff *, const char **, string *);
414*150b7e42Smiod 
415*150b7e42Smiod static int do_arg (struct work_stuff *, const char **, string *);
41600bf4279Sespie 
41700bf4279Sespie static void
418*150b7e42Smiod demangle_function_name (struct work_stuff *, const char **, string *,
419*150b7e42Smiod                         const char *);
42037c53322Sespie 
42100bf4279Sespie static int
422*150b7e42Smiod iterate_demangle_function (struct work_stuff *,
423*150b7e42Smiod                            const char **, string *, const char *);
424*150b7e42Smiod 
425*150b7e42Smiod static void remember_type (struct work_stuff *, const char *, int);
426*150b7e42Smiod 
427*150b7e42Smiod static void remember_Btype (struct work_stuff *, const char *, int, int);
428*150b7e42Smiod 
429*150b7e42Smiod static int register_Btype (struct work_stuff *);
430*150b7e42Smiod 
431*150b7e42Smiod static void remember_Ktype (struct work_stuff *, const char *, int);
432*150b7e42Smiod 
433*150b7e42Smiod static void forget_types (struct work_stuff *);
434*150b7e42Smiod 
435*150b7e42Smiod static void forget_B_and_K_types (struct work_stuff *);
436*150b7e42Smiod 
437*150b7e42Smiod static void string_prepends (string *, string *);
43800bf4279Sespie 
43900bf4279Sespie static int
440*150b7e42Smiod demangle_template_value_parm (struct work_stuff*, const char**,
441*150b7e42Smiod                               string*, type_kind_t);
44200bf4279Sespie 
44300bf4279Sespie static int
444*150b7e42Smiod do_hpacc_template_const_value (struct work_stuff *, const char **, string *);
44500bf4279Sespie 
44600bf4279Sespie static int
447*150b7e42Smiod do_hpacc_template_literal (struct work_stuff *, const char **, string *);
44800bf4279Sespie 
449*150b7e42Smiod static int snarf_numeric_literal (const char **, string *);
45000bf4279Sespie 
45100bf4279Sespie /* There is a TYPE_QUAL value for each type qualifier.  They can be
45200bf4279Sespie    combined by bitwise-or to form the complete set of qualifiers for a
45300bf4279Sespie    type.  */
45400bf4279Sespie 
45500bf4279Sespie #define TYPE_UNQUALIFIED   0x0
45600bf4279Sespie #define TYPE_QUAL_CONST    0x1
45700bf4279Sespie #define TYPE_QUAL_VOLATILE 0x2
45800bf4279Sespie #define TYPE_QUAL_RESTRICT 0x4
45900bf4279Sespie 
460*150b7e42Smiod static int code_for_qualifier (int);
46100bf4279Sespie 
462*150b7e42Smiod static const char* qualifier_string (int);
46300bf4279Sespie 
464*150b7e42Smiod static const char* demangle_qualifier (int);
465*150b7e42Smiod 
466*150b7e42Smiod static int demangle_expression (struct work_stuff *, const char **, string *,
467*150b7e42Smiod                                 type_kind_t);
46800bf4279Sespie 
46937c53322Sespie static int
470*150b7e42Smiod demangle_integral_value (struct work_stuff *, const char **, string *);
47137c53322Sespie 
47237c53322Sespie static int
473*150b7e42Smiod demangle_real_value (struct work_stuff *, const char **, string *);
47437c53322Sespie 
47537c53322Sespie static void
476*150b7e42Smiod demangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
47737c53322Sespie 
47837c53322Sespie static void
479*150b7e42Smiod recursively_demangle (struct work_stuff *, const char **, string *, int);
48037c53322Sespie 
481*150b7e42Smiod static void grow_vect (char **, size_t *, size_t, int);
48237c53322Sespie 
48300bf4279Sespie /* Translate count to integer, consuming tokens in the process.
48400bf4279Sespie    Conversion terminates on the first non-digit character.
48500bf4279Sespie 
48600bf4279Sespie    Trying to consume something that isn't a count results in no
48700bf4279Sespie    consumption of input and a return of -1.
48800bf4279Sespie 
48900bf4279Sespie    Overflow consumes the rest of the digits, and returns -1.  */
49000bf4279Sespie 
49100bf4279Sespie static int
consume_count(const char ** type)492*150b7e42Smiod consume_count (const char **type)
49300bf4279Sespie {
49400bf4279Sespie   int count = 0;
49500bf4279Sespie 
49637c53322Sespie   if (! ISDIGIT ((unsigned char)**type))
49700bf4279Sespie     return -1;
49800bf4279Sespie 
49937c53322Sespie   while (ISDIGIT ((unsigned char)**type))
50000bf4279Sespie     {
50100bf4279Sespie       count *= 10;
50200bf4279Sespie 
50300bf4279Sespie       /* Check for overflow.
50400bf4279Sespie 	 We assume that count is represented using two's-complement;
50500bf4279Sespie 	 no power of two is divisible by ten, so if an overflow occurs
50600bf4279Sespie 	 when multiplying by ten, the result will not be a multiple of
50700bf4279Sespie 	 ten.  */
50800bf4279Sespie       if ((count % 10) != 0)
50900bf4279Sespie 	{
51037c53322Sespie 	  while (ISDIGIT ((unsigned char) **type))
51100bf4279Sespie 	    (*type)++;
51200bf4279Sespie 	  return -1;
51300bf4279Sespie 	}
51400bf4279Sespie 
51500bf4279Sespie       count += **type - '0';
51600bf4279Sespie       (*type)++;
51700bf4279Sespie     }
51800bf4279Sespie 
51937c53322Sespie   if (count < 0)
52037c53322Sespie     count = -1;
52137c53322Sespie 
52200bf4279Sespie   return (count);
52300bf4279Sespie }
52400bf4279Sespie 
52500bf4279Sespie 
52600bf4279Sespie /* Like consume_count, but for counts that are preceded and followed
52700bf4279Sespie    by '_' if they are greater than 10.  Also, -1 is returned for
52800bf4279Sespie    failure, since 0 can be a valid value.  */
52900bf4279Sespie 
53000bf4279Sespie static int
consume_count_with_underscores(const char ** mangled)531*150b7e42Smiod consume_count_with_underscores (const char **mangled)
53200bf4279Sespie {
53300bf4279Sespie   int idx;
53400bf4279Sespie 
53500bf4279Sespie   if (**mangled == '_')
53600bf4279Sespie     {
53700bf4279Sespie       (*mangled)++;
53837c53322Sespie       if (!ISDIGIT ((unsigned char)**mangled))
53900bf4279Sespie 	return -1;
54000bf4279Sespie 
54100bf4279Sespie       idx = consume_count (mangled);
54200bf4279Sespie       if (**mangled != '_')
54300bf4279Sespie 	/* The trailing underscore was missing. */
54400bf4279Sespie 	return -1;
54500bf4279Sespie 
54600bf4279Sespie       (*mangled)++;
54700bf4279Sespie     }
54800bf4279Sespie   else
54900bf4279Sespie     {
55000bf4279Sespie       if (**mangled < '0' || **mangled > '9')
55100bf4279Sespie 	return -1;
55200bf4279Sespie 
55300bf4279Sespie       idx = **mangled - '0';
55400bf4279Sespie       (*mangled)++;
55500bf4279Sespie     }
55600bf4279Sespie 
55700bf4279Sespie   return idx;
55800bf4279Sespie }
55900bf4279Sespie 
56000bf4279Sespie /* C is the code for a type-qualifier.  Return the TYPE_QUAL
56100bf4279Sespie    corresponding to this qualifier.  */
56200bf4279Sespie 
56300bf4279Sespie static int
code_for_qualifier(int c)564*150b7e42Smiod code_for_qualifier (int c)
56500bf4279Sespie {
56600bf4279Sespie   switch (c)
56700bf4279Sespie     {
56800bf4279Sespie     case 'C':
56900bf4279Sespie       return TYPE_QUAL_CONST;
57000bf4279Sespie 
57100bf4279Sespie     case 'V':
57200bf4279Sespie       return TYPE_QUAL_VOLATILE;
57300bf4279Sespie 
57400bf4279Sespie     case 'u':
57500bf4279Sespie       return TYPE_QUAL_RESTRICT;
57600bf4279Sespie 
57700bf4279Sespie     default:
57800bf4279Sespie       break;
57900bf4279Sespie     }
58000bf4279Sespie 
58100bf4279Sespie   /* C was an invalid qualifier.  */
58200bf4279Sespie   abort ();
58300bf4279Sespie }
58400bf4279Sespie 
58500bf4279Sespie /* Return the string corresponding to the qualifiers given by
58600bf4279Sespie    TYPE_QUALS.  */
58700bf4279Sespie 
58800bf4279Sespie static const char*
qualifier_string(int type_quals)589*150b7e42Smiod qualifier_string (int type_quals)
59000bf4279Sespie {
59100bf4279Sespie   switch (type_quals)
59200bf4279Sespie     {
59300bf4279Sespie     case TYPE_UNQUALIFIED:
59400bf4279Sespie       return "";
59500bf4279Sespie 
59600bf4279Sespie     case TYPE_QUAL_CONST:
59700bf4279Sespie       return "const";
59800bf4279Sespie 
59900bf4279Sespie     case TYPE_QUAL_VOLATILE:
60000bf4279Sespie       return "volatile";
60100bf4279Sespie 
60200bf4279Sespie     case TYPE_QUAL_RESTRICT:
60300bf4279Sespie       return "__restrict";
60400bf4279Sespie 
60500bf4279Sespie     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
60600bf4279Sespie       return "const volatile";
60700bf4279Sespie 
60800bf4279Sespie     case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
60900bf4279Sespie       return "const __restrict";
61000bf4279Sespie 
61100bf4279Sespie     case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
61200bf4279Sespie       return "volatile __restrict";
61300bf4279Sespie 
61400bf4279Sespie     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
61500bf4279Sespie       return "const volatile __restrict";
61600bf4279Sespie 
61700bf4279Sespie     default:
61800bf4279Sespie       break;
61900bf4279Sespie     }
62000bf4279Sespie 
62100bf4279Sespie   /* TYPE_QUALS was an invalid qualifier set.  */
62200bf4279Sespie   abort ();
62300bf4279Sespie }
62400bf4279Sespie 
62500bf4279Sespie /* C is the code for a type-qualifier.  Return the string
62600bf4279Sespie    corresponding to this qualifier.  This function should only be
62700bf4279Sespie    called with a valid qualifier code.  */
62800bf4279Sespie 
62900bf4279Sespie static const char*
demangle_qualifier(int c)630*150b7e42Smiod demangle_qualifier (int c)
63100bf4279Sespie {
63200bf4279Sespie   return qualifier_string (code_for_qualifier (c));
63300bf4279Sespie }
63400bf4279Sespie 
63500bf4279Sespie int
cplus_demangle_opname(const char * opname,char * result,int options)636*150b7e42Smiod cplus_demangle_opname (const char *opname, char *result, int options)
63700bf4279Sespie {
63800bf4279Sespie   int len, len1, ret;
63900bf4279Sespie   string type;
64000bf4279Sespie   struct work_stuff work[1];
64100bf4279Sespie   const char *tem;
64200bf4279Sespie 
64300bf4279Sespie   len = strlen(opname);
64400bf4279Sespie   result[0] = '\0';
64500bf4279Sespie   ret = 0;
64600bf4279Sespie   memset ((char *) work, 0, sizeof (work));
64700bf4279Sespie   work->options = options;
64800bf4279Sespie 
64900bf4279Sespie   if (opname[0] == '_' && opname[1] == '_'
65000bf4279Sespie       && opname[2] == 'o' && opname[3] == 'p')
65100bf4279Sespie     {
65200bf4279Sespie       /* ANSI.  */
65300bf4279Sespie       /* type conversion operator.  */
65400bf4279Sespie       tem = opname + 4;
65500bf4279Sespie       if (do_type (work, &tem, &type))
65600bf4279Sespie 	{
65700bf4279Sespie 	  strcat (result, "operator ");
65800bf4279Sespie 	  strncat (result, type.b, type.p - type.b);
65900bf4279Sespie 	  string_delete (&type);
66000bf4279Sespie 	  ret = 1;
66100bf4279Sespie 	}
66200bf4279Sespie     }
66300bf4279Sespie   else if (opname[0] == '_' && opname[1] == '_'
66437c53322Sespie 	   && ISLOWER((unsigned char)opname[2])
66537c53322Sespie 	   && ISLOWER((unsigned char)opname[3]))
66600bf4279Sespie     {
66700bf4279Sespie       if (opname[4] == '\0')
66800bf4279Sespie 	{
66900bf4279Sespie 	  /* Operator.  */
67000bf4279Sespie 	  size_t i;
67137c53322Sespie 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
67200bf4279Sespie 	    {
67300bf4279Sespie 	      if (strlen (optable[i].in) == 2
67400bf4279Sespie 		  && memcmp (optable[i].in, opname + 2, 2) == 0)
67500bf4279Sespie 		{
67600bf4279Sespie 		  strcat (result, "operator");
67700bf4279Sespie 		  strcat (result, optable[i].out);
67800bf4279Sespie 		  ret = 1;
67900bf4279Sespie 		  break;
68000bf4279Sespie 		}
68100bf4279Sespie 	    }
68200bf4279Sespie 	}
68300bf4279Sespie       else
68400bf4279Sespie 	{
68500bf4279Sespie 	  if (opname[2] == 'a' && opname[5] == '\0')
68600bf4279Sespie 	    {
68700bf4279Sespie 	      /* Assignment.  */
68800bf4279Sespie 	      size_t i;
68937c53322Sespie 	      for (i = 0; i < ARRAY_SIZE (optable); i++)
69000bf4279Sespie 		{
69100bf4279Sespie 		  if (strlen (optable[i].in) == 3
69200bf4279Sespie 		      && memcmp (optable[i].in, opname + 2, 3) == 0)
69300bf4279Sespie 		    {
69400bf4279Sespie 		      strcat (result, "operator");
69500bf4279Sespie 		      strcat (result, optable[i].out);
69600bf4279Sespie 		      ret = 1;
69700bf4279Sespie 		      break;
69800bf4279Sespie 		    }
69900bf4279Sespie 		}
70000bf4279Sespie 	    }
70100bf4279Sespie 	}
70200bf4279Sespie     }
70300bf4279Sespie   else if (len >= 3
70400bf4279Sespie 	   && opname[0] == 'o'
70500bf4279Sespie 	   && opname[1] == 'p'
70600bf4279Sespie 	   && strchr (cplus_markers, opname[2]) != NULL)
70700bf4279Sespie     {
70800bf4279Sespie       /* see if it's an assignment expression */
70900bf4279Sespie       if (len >= 10 /* op$assign_ */
71000bf4279Sespie 	  && memcmp (opname + 3, "assign_", 7) == 0)
71100bf4279Sespie 	{
71200bf4279Sespie 	  size_t i;
71337c53322Sespie 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
71400bf4279Sespie 	    {
71500bf4279Sespie 	      len1 = len - 10;
71600bf4279Sespie 	      if ((int) strlen (optable[i].in) == len1
71700bf4279Sespie 		  && memcmp (optable[i].in, opname + 10, len1) == 0)
71800bf4279Sespie 		{
71900bf4279Sespie 		  strcat (result, "operator");
72000bf4279Sespie 		  strcat (result, optable[i].out);
72100bf4279Sespie 		  strcat (result, "=");
72200bf4279Sespie 		  ret = 1;
72300bf4279Sespie 		  break;
72400bf4279Sespie 		}
72500bf4279Sespie 	    }
72600bf4279Sespie 	}
72700bf4279Sespie       else
72800bf4279Sespie 	{
72900bf4279Sespie 	  size_t i;
73037c53322Sespie 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
73100bf4279Sespie 	    {
73200bf4279Sespie 	      len1 = len - 3;
73300bf4279Sespie 	      if ((int) strlen (optable[i].in) == len1
73400bf4279Sespie 		  && memcmp (optable[i].in, opname + 3, len1) == 0)
73500bf4279Sespie 		{
73600bf4279Sespie 		  strcat (result, "operator");
73700bf4279Sespie 		  strcat (result, optable[i].out);
73800bf4279Sespie 		  ret = 1;
73900bf4279Sespie 		  break;
74000bf4279Sespie 		}
74100bf4279Sespie 	    }
74200bf4279Sespie 	}
74300bf4279Sespie     }
74400bf4279Sespie   else if (len >= 5 && memcmp (opname, "type", 4) == 0
74500bf4279Sespie 	   && strchr (cplus_markers, opname[4]) != NULL)
74600bf4279Sespie     {
74700bf4279Sespie       /* type conversion operator */
74800bf4279Sespie       tem = opname + 5;
74900bf4279Sespie       if (do_type (work, &tem, &type))
75000bf4279Sespie 	{
75100bf4279Sespie 	  strcat (result, "operator ");
75200bf4279Sespie 	  strncat (result, type.b, type.p - type.b);
75300bf4279Sespie 	  string_delete (&type);
75400bf4279Sespie 	  ret = 1;
75500bf4279Sespie 	}
75600bf4279Sespie     }
75700bf4279Sespie   squangle_mop_up (work);
75800bf4279Sespie   return ret;
75900bf4279Sespie 
76000bf4279Sespie }
76137c53322Sespie 
76200bf4279Sespie /* Takes operator name as e.g. "++" and returns mangled
76300bf4279Sespie    operator name (e.g. "postincrement_expr"), or NULL if not found.
76400bf4279Sespie 
76500bf4279Sespie    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
76600bf4279Sespie    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
76700bf4279Sespie 
76800bf4279Sespie const char *
cplus_mangle_opname(const char * opname,int options)769*150b7e42Smiod cplus_mangle_opname (const char *opname, int options)
77000bf4279Sespie {
77100bf4279Sespie   size_t i;
77200bf4279Sespie   int len;
77300bf4279Sespie 
77400bf4279Sespie   len = strlen (opname);
77537c53322Sespie   for (i = 0; i < ARRAY_SIZE (optable); i++)
77600bf4279Sespie     {
77700bf4279Sespie       if ((int) strlen (optable[i].out) == len
77800bf4279Sespie 	  && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
77900bf4279Sespie 	  && memcmp (optable[i].out, opname, len) == 0)
78000bf4279Sespie 	return optable[i].in;
78100bf4279Sespie     }
78200bf4279Sespie   return (0);
78300bf4279Sespie }
78400bf4279Sespie 
7852e0724c7Sespie /* Add a routine to set the demangling style to be sure it is valid and
7862e0724c7Sespie    allow for any demangler initialization that maybe necessary. */
7872e0724c7Sespie 
7882e0724c7Sespie enum demangling_styles
cplus_demangle_set_style(enum demangling_styles style)789*150b7e42Smiod cplus_demangle_set_style (enum demangling_styles style)
7902e0724c7Sespie {
79137c53322Sespie   const struct demangler_engine *demangler = libiberty_demanglers;
7922e0724c7Sespie 
7932e0724c7Sespie   for (; demangler->demangling_style != unknown_demangling; ++demangler)
7942e0724c7Sespie     if (style == demangler->demangling_style)
7952e0724c7Sespie       {
7962e0724c7Sespie 	current_demangling_style = style;
7972e0724c7Sespie 	return current_demangling_style;
7982e0724c7Sespie       }
7992e0724c7Sespie 
8002e0724c7Sespie   return unknown_demangling;
8012e0724c7Sespie }
8022e0724c7Sespie 
8032e0724c7Sespie /* Do string name to style translation */
8042e0724c7Sespie 
8052e0724c7Sespie enum demangling_styles
cplus_demangle_name_to_style(const char * name)806*150b7e42Smiod cplus_demangle_name_to_style (const char *name)
8072e0724c7Sespie {
80837c53322Sespie   const struct demangler_engine *demangler = libiberty_demanglers;
8092e0724c7Sespie 
8102e0724c7Sespie   for (; demangler->demangling_style != unknown_demangling; ++demangler)
8112e0724c7Sespie     if (strcmp (name, demangler->demangling_style_name) == 0)
8122e0724c7Sespie       return demangler->demangling_style;
8132e0724c7Sespie 
8142e0724c7Sespie   return unknown_demangling;
8152e0724c7Sespie }
8162e0724c7Sespie 
81700bf4279Sespie /* char *cplus_demangle (const char *mangled, int options)
81800bf4279Sespie 
81900bf4279Sespie    If MANGLED is a mangled function name produced by GNU C++, then
82037c53322Sespie    a pointer to a @code{malloc}ed string giving a C++ representation
82100bf4279Sespie    of the name will be returned; otherwise NULL will be returned.
82200bf4279Sespie    It is the caller's responsibility to free the string which
82300bf4279Sespie    is returned.
82400bf4279Sespie 
82500bf4279Sespie    The OPTIONS arg may contain one or more of the following bits:
82600bf4279Sespie 
82700bf4279Sespie    	DMGL_ANSI	ANSI qualifiers such as `const' and `void' are
82800bf4279Sespie 			included.
82900bf4279Sespie 	DMGL_PARAMS	Function parameters are included.
83000bf4279Sespie 
83100bf4279Sespie    For example,
83200bf4279Sespie 
83300bf4279Sespie    cplus_demangle ("foo__1Ai", DMGL_PARAMS)		=> "A::foo(int)"
83400bf4279Sespie    cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI)	=> "A::foo(int)"
83500bf4279Sespie    cplus_demangle ("foo__1Ai", 0)			=> "A::foo"
83600bf4279Sespie 
83700bf4279Sespie    cplus_demangle ("foo__1Afe", DMGL_PARAMS)		=> "A::foo(float,...)"
83800bf4279Sespie    cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
83900bf4279Sespie    cplus_demangle ("foo__1Afe", 0)			=> "A::foo"
84000bf4279Sespie 
84100bf4279Sespie    Note that any leading underscores, or other such characters prepended by
84200bf4279Sespie    the compilation system, are presumed to have already been stripped from
84300bf4279Sespie    MANGLED.  */
84400bf4279Sespie 
84500bf4279Sespie char *
cplus_demangle(const char * mangled,int options)846*150b7e42Smiod cplus_demangle (const char *mangled, int options)
84700bf4279Sespie {
84800bf4279Sespie   char *ret;
84900bf4279Sespie   struct work_stuff work[1];
85037c53322Sespie 
85137c53322Sespie   if (current_demangling_style == no_demangling)
85237c53322Sespie     return xstrdup (mangled);
85337c53322Sespie 
85400bf4279Sespie   memset ((char *) work, 0, sizeof (work));
85500bf4279Sespie   work->options = options;
85600bf4279Sespie   if ((work->options & DMGL_STYLE_MASK) == 0)
85700bf4279Sespie     work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
85800bf4279Sespie 
85937c53322Sespie   /* The V3 ABI demangling is implemented elsewhere.  */
86037c53322Sespie   if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
86137c53322Sespie     {
86237c53322Sespie       ret = cplus_demangle_v3 (mangled, work->options);
86337c53322Sespie       if (ret || GNU_V3_DEMANGLING)
86437c53322Sespie 	return ret;
86537c53322Sespie     }
86637c53322Sespie 
86737c53322Sespie   if (JAVA_DEMANGLING)
86837c53322Sespie     {
86937c53322Sespie       ret = java_demangle_v3 (mangled);
87037c53322Sespie       if (ret)
87137c53322Sespie         return ret;
87237c53322Sespie     }
87337c53322Sespie 
87437c53322Sespie   if (GNAT_DEMANGLING)
87537c53322Sespie     return ada_demangle(mangled,options);
87637c53322Sespie 
87700bf4279Sespie   ret = internal_cplus_demangle (work, mangled);
87800bf4279Sespie   squangle_mop_up (work);
87900bf4279Sespie   return (ret);
88000bf4279Sespie }
88100bf4279Sespie 
88200bf4279Sespie 
88337c53322Sespie /* Assuming *OLD_VECT points to an array of *SIZE objects of size
88437c53322Sespie    ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
88537c53322Sespie    updating *OLD_VECT and *SIZE as necessary.  */
88637c53322Sespie 
88737c53322Sespie static void
grow_vect(char ** old_vect,size_t * size,size_t min_size,int element_size)888*150b7e42Smiod grow_vect (char **old_vect, size_t *size, size_t min_size, int element_size)
88937c53322Sespie {
89037c53322Sespie   if (*size < min_size)
89137c53322Sespie     {
89237c53322Sespie       *size *= 2;
89337c53322Sespie       if (*size < min_size)
89437c53322Sespie 	*size = min_size;
895*150b7e42Smiod       *old_vect = XRESIZEVAR (char, *old_vect, *size * element_size);
89637c53322Sespie     }
89737c53322Sespie }
89837c53322Sespie 
89937c53322Sespie /* Demangle ada names:
90037c53322Sespie    1. Discard final __{DIGIT}+ or ${DIGIT}+
90137c53322Sespie    2. Convert other instances of embedded "__" to `.'.
90237c53322Sespie    3. Discard leading _ada_.
90337c53322Sespie    4. Remove everything after first ___ if it is followed by 'X'.
90437c53322Sespie    5. Put symbols that should be suppressed in <...> brackets.
90537c53322Sespie    The resulting string is valid until the next call of ada_demangle.  */
90637c53322Sespie 
90737c53322Sespie static char *
ada_demangle(const char * mangled,int option ATTRIBUTE_UNUSED)908*150b7e42Smiod ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
90937c53322Sespie {
91037c53322Sespie   int i, j;
91137c53322Sespie   int len0;
91237c53322Sespie   const char* p;
91337c53322Sespie   char *demangled = NULL;
91437c53322Sespie   int changed;
91537c53322Sespie   size_t demangled_size = 0;
91637c53322Sespie 
91737c53322Sespie   changed = 0;
91837c53322Sespie 
91937c53322Sespie   if (strncmp (mangled, "_ada_", 5) == 0)
92037c53322Sespie     {
92137c53322Sespie       mangled += 5;
92237c53322Sespie       changed = 1;
92337c53322Sespie     }
92437c53322Sespie 
92537c53322Sespie   if (mangled[0] == '_' || mangled[0] == '<')
92637c53322Sespie     goto Suppress;
92737c53322Sespie 
92837c53322Sespie   p = strstr (mangled, "___");
92937c53322Sespie   if (p == NULL)
93037c53322Sespie     len0 = strlen (mangled);
93137c53322Sespie   else
93237c53322Sespie     {
93337c53322Sespie       if (p[3] == 'X')
93437c53322Sespie 	{
93537c53322Sespie 	  len0 = p - mangled;
93637c53322Sespie 	  changed = 1;
93737c53322Sespie 	}
93837c53322Sespie       else
93937c53322Sespie 	goto Suppress;
94037c53322Sespie     }
94137c53322Sespie 
94237c53322Sespie   /* Make demangled big enough for possible expansion by operator name.  */
94337c53322Sespie   grow_vect (&demangled,
94437c53322Sespie 	     &demangled_size,  2 * len0 + 1,
94537c53322Sespie 	     sizeof (char));
94637c53322Sespie 
94737c53322Sespie   if (ISDIGIT ((unsigned char) mangled[len0 - 1])) {
94837c53322Sespie     for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1)
94937c53322Sespie       ;
95037c53322Sespie     if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_')
95137c53322Sespie       {
95237c53322Sespie 	len0 = i - 1;
95337c53322Sespie 	changed = 1;
95437c53322Sespie       }
95537c53322Sespie     else if (mangled[i] == '$')
95637c53322Sespie       {
95737c53322Sespie 	len0 = i;
95837c53322Sespie 	changed = 1;
95937c53322Sespie       }
96037c53322Sespie   }
96137c53322Sespie 
96237c53322Sespie   for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
96337c53322Sespie        i += 1, j += 1)
96437c53322Sespie     demangled[j] = mangled[i];
96537c53322Sespie 
96637c53322Sespie   while (i < len0)
96737c53322Sespie     {
96837c53322Sespie       if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_')
96937c53322Sespie 	{
97037c53322Sespie 	  demangled[j] = '.';
971*150b7e42Smiod 	  changed = 1;
97237c53322Sespie 	  i += 2; j += 1;
97337c53322Sespie 	}
97437c53322Sespie       else
97537c53322Sespie 	{
97637c53322Sespie 	  demangled[j] = mangled[i];
97737c53322Sespie 	  i += 1;  j += 1;
97837c53322Sespie 	}
97937c53322Sespie     }
98037c53322Sespie   demangled[j] = '\000';
98137c53322Sespie 
98237c53322Sespie   for (i = 0; demangled[i] != '\0'; i += 1)
98337c53322Sespie     if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ')
98437c53322Sespie       goto Suppress;
98537c53322Sespie 
98637c53322Sespie   if (! changed)
98737c53322Sespie     return NULL;
98837c53322Sespie   else
98937c53322Sespie     return demangled;
99037c53322Sespie 
99137c53322Sespie  Suppress:
99237c53322Sespie   grow_vect (&demangled,
99337c53322Sespie 	     &demangled_size,  strlen (mangled) + 3,
99437c53322Sespie 	     sizeof (char));
99537c53322Sespie 
99637c53322Sespie   if (mangled[0] == '<')
99797490679Sespie     strlcpy (demangled, mangled, demangled_size);
99837c53322Sespie   else
99997490679Sespie     snprintf (demangled, demangled_size, "<%s>", mangled);
100037c53322Sespie 
100137c53322Sespie   return demangled;
100237c53322Sespie }
100337c53322Sespie 
100400bf4279Sespie /* This function performs most of what cplus_demangle use to do, but
100500bf4279Sespie    to be able to demangle a name with a B, K or n code, we need to
100600bf4279Sespie    have a longer term memory of what types have been seen. The original
1007707f648cSespie    now initializes and cleans up the squangle code info, while internal
100800bf4279Sespie    calls go directly to this routine to avoid resetting that info. */
100900bf4279Sespie 
101000bf4279Sespie static char *
internal_cplus_demangle(struct work_stuff * work,const char * mangled)1011*150b7e42Smiod internal_cplus_demangle (struct work_stuff *work, const char *mangled)
101200bf4279Sespie {
101300bf4279Sespie 
101400bf4279Sespie   string decl;
101500bf4279Sespie   int success = 0;
101600bf4279Sespie   char *demangled = NULL;
101700bf4279Sespie   int s1, s2, s3, s4;
101800bf4279Sespie   s1 = work->constructor;
101900bf4279Sespie   s2 = work->destructor;
102000bf4279Sespie   s3 = work->static_type;
102100bf4279Sespie   s4 = work->type_quals;
102200bf4279Sespie   work->constructor = work->destructor = 0;
102300bf4279Sespie   work->type_quals = TYPE_UNQUALIFIED;
102400bf4279Sespie   work->dllimported = 0;
102500bf4279Sespie 
102600bf4279Sespie   if ((mangled != NULL) && (*mangled != '\0'))
102700bf4279Sespie     {
102800bf4279Sespie       string_init (&decl);
102900bf4279Sespie 
103000bf4279Sespie       /* First check to see if gnu style demangling is active and if the
103100bf4279Sespie 	 string to be demangled contains a CPLUS_MARKER.  If so, attempt to
103200bf4279Sespie 	 recognize one of the gnu special forms rather than looking for a
103300bf4279Sespie 	 standard prefix.  In particular, don't worry about whether there
103400bf4279Sespie 	 is a "__" string in the mangled string.  Consider "_$_5__foo" for
103500bf4279Sespie 	 example.  */
103600bf4279Sespie 
103700bf4279Sespie       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
103800bf4279Sespie 	{
103900bf4279Sespie 	  success = gnu_special (work, &mangled, &decl);
104000bf4279Sespie 	}
104100bf4279Sespie       if (!success)
104200bf4279Sespie 	{
104300bf4279Sespie 	  success = demangle_prefix (work, &mangled, &decl);
104400bf4279Sespie 	}
104500bf4279Sespie       if (success && (*mangled != '\0'))
104600bf4279Sespie 	{
104700bf4279Sespie 	  success = demangle_signature (work, &mangled, &decl);
104800bf4279Sespie 	}
104900bf4279Sespie       if (work->constructor == 2)
105000bf4279Sespie         {
105100bf4279Sespie           string_prepend (&decl, "global constructors keyed to ");
105200bf4279Sespie           work->constructor = 0;
105300bf4279Sespie         }
105400bf4279Sespie       else if (work->destructor == 2)
105500bf4279Sespie         {
105600bf4279Sespie           string_prepend (&decl, "global destructors keyed to ");
105700bf4279Sespie           work->destructor = 0;
105800bf4279Sespie         }
105900bf4279Sespie       else if (work->dllimported == 1)
106000bf4279Sespie         {
106100bf4279Sespie           string_prepend (&decl, "import stub for ");
106200bf4279Sespie           work->dllimported = 0;
106300bf4279Sespie         }
106400bf4279Sespie       demangled = mop_up (work, &decl, success);
106500bf4279Sespie     }
106600bf4279Sespie   work->constructor = s1;
106700bf4279Sespie   work->destructor = s2;
106800bf4279Sespie   work->static_type = s3;
106900bf4279Sespie   work->type_quals = s4;
107037c53322Sespie   return demangled;
107100bf4279Sespie }
107200bf4279Sespie 
107300bf4279Sespie 
107400bf4279Sespie /* Clear out and squangling related storage */
107500bf4279Sespie static void
squangle_mop_up(struct work_stuff * work)1076*150b7e42Smiod squangle_mop_up (struct work_stuff *work)
107700bf4279Sespie {
107800bf4279Sespie   /* clean up the B and K type mangling types. */
107900bf4279Sespie   forget_B_and_K_types (work);
108000bf4279Sespie   if (work -> btypevec != NULL)
108100bf4279Sespie     {
108200bf4279Sespie       free ((char *) work -> btypevec);
108300bf4279Sespie     }
108400bf4279Sespie   if (work -> ktypevec != NULL)
108500bf4279Sespie     {
108600bf4279Sespie       free ((char *) work -> ktypevec);
108700bf4279Sespie     }
108800bf4279Sespie }
108900bf4279Sespie 
109000bf4279Sespie 
109137c53322Sespie /* Copy the work state and storage.  */
109237c53322Sespie 
109337c53322Sespie static void
work_stuff_copy_to_from(struct work_stuff * to,struct work_stuff * from)1094*150b7e42Smiod work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
10952e0724c7Sespie {
109637c53322Sespie   int i;
109701e9b57fSespie 
109837c53322Sespie   delete_work_stuff (to);
109937c53322Sespie 
110037c53322Sespie   /* Shallow-copy scalars.  */
110137c53322Sespie   memcpy (to, from, sizeof (*to));
110237c53322Sespie 
110337c53322Sespie   /* Deep-copy dynamic storage.  */
110437c53322Sespie   if (from->typevec_size)
1105*150b7e42Smiod     to->typevec = XNEWVEC (char *, from->typevec_size);
110637c53322Sespie 
110737c53322Sespie   for (i = 0; i < from->ntypes; i++)
110837c53322Sespie     {
110937c53322Sespie       int len = strlen (from->typevec[i]) + 1;
111037c53322Sespie 
1111*150b7e42Smiod       to->typevec[i] = XNEWVEC (char, len);
111237c53322Sespie       memcpy (to->typevec[i], from->typevec[i], len);
111337c53322Sespie     }
111437c53322Sespie 
111537c53322Sespie   if (from->ksize)
1116*150b7e42Smiod     to->ktypevec = XNEWVEC (char *, from->ksize);
111737c53322Sespie 
111837c53322Sespie   for (i = 0; i < from->numk; i++)
111937c53322Sespie     {
112037c53322Sespie       int len = strlen (from->ktypevec[i]) + 1;
112137c53322Sespie 
1122*150b7e42Smiod       to->ktypevec[i] = XNEWVEC (char, len);
112337c53322Sespie       memcpy (to->ktypevec[i], from->ktypevec[i], len);
112437c53322Sespie     }
112537c53322Sespie 
112637c53322Sespie   if (from->bsize)
1127*150b7e42Smiod     to->btypevec = XNEWVEC (char *, from->bsize);
112837c53322Sespie 
112937c53322Sespie   for (i = 0; i < from->numb; i++)
113037c53322Sespie     {
113137c53322Sespie       int len = strlen (from->btypevec[i]) + 1;
113237c53322Sespie 
1133*150b7e42Smiod       to->btypevec[i] = XNEWVEC (char , len);
113437c53322Sespie       memcpy (to->btypevec[i], from->btypevec[i], len);
113537c53322Sespie     }
113637c53322Sespie 
113737c53322Sespie   if (from->ntmpl_args)
1138*150b7e42Smiod     to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
113937c53322Sespie 
114037c53322Sespie   for (i = 0; i < from->ntmpl_args; i++)
114137c53322Sespie     {
114237c53322Sespie       int len = strlen (from->tmpl_argvec[i]) + 1;
114337c53322Sespie 
1144*150b7e42Smiod       to->tmpl_argvec[i] = XNEWVEC (char, len);
114537c53322Sespie       memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
114637c53322Sespie     }
114737c53322Sespie 
114837c53322Sespie   if (from->previous_argument)
114937c53322Sespie     {
1150*150b7e42Smiod       to->previous_argument = XNEW (string);
115137c53322Sespie       string_init (to->previous_argument);
115237c53322Sespie       string_appends (to->previous_argument, from->previous_argument);
115337c53322Sespie     }
115437c53322Sespie }
115537c53322Sespie 
115637c53322Sespie 
115737c53322Sespie /* Delete dynamic stuff in work_stuff that is not to be re-used.  */
115837c53322Sespie 
115937c53322Sespie static void
delete_non_B_K_work_stuff(struct work_stuff * work)1160*150b7e42Smiod delete_non_B_K_work_stuff (struct work_stuff *work)
116137c53322Sespie {
116200bf4279Sespie   /* Discard the remembered types, if any.  */
116300bf4279Sespie 
116400bf4279Sespie   forget_types (work);
116500bf4279Sespie   if (work -> typevec != NULL)
116600bf4279Sespie     {
116700bf4279Sespie       free ((char *) work -> typevec);
116800bf4279Sespie       work -> typevec = NULL;
116900bf4279Sespie       work -> typevec_size = 0;
117000bf4279Sespie     }
117100bf4279Sespie   if (work->tmpl_argvec)
117200bf4279Sespie     {
117300bf4279Sespie       int i;
117400bf4279Sespie 
117500bf4279Sespie       for (i = 0; i < work->ntmpl_args; i++)
117600bf4279Sespie 	if (work->tmpl_argvec[i])
117700bf4279Sespie 	  free ((char*) work->tmpl_argvec[i]);
117800bf4279Sespie 
117900bf4279Sespie       free ((char*) work->tmpl_argvec);
118000bf4279Sespie       work->tmpl_argvec = NULL;
118100bf4279Sespie     }
118200bf4279Sespie   if (work->previous_argument)
118300bf4279Sespie     {
118400bf4279Sespie       string_delete (work->previous_argument);
118500bf4279Sespie       free ((char*) work->previous_argument);
118600bf4279Sespie       work->previous_argument = NULL;
118700bf4279Sespie     }
118837c53322Sespie }
118937c53322Sespie 
119037c53322Sespie 
119137c53322Sespie /* Delete all dynamic storage in work_stuff.  */
119237c53322Sespie static void
delete_work_stuff(struct work_stuff * work)1193*150b7e42Smiod delete_work_stuff (struct work_stuff *work)
119437c53322Sespie {
119537c53322Sespie   delete_non_B_K_work_stuff (work);
119637c53322Sespie   squangle_mop_up (work);
119737c53322Sespie }
119837c53322Sespie 
119937c53322Sespie 
120037c53322Sespie /* Clear out any mangled storage */
120137c53322Sespie 
120237c53322Sespie static char *
mop_up(struct work_stuff * work,string * declp,int success)1203*150b7e42Smiod mop_up (struct work_stuff *work, string *declp, int success)
120437c53322Sespie {
120537c53322Sespie   char *demangled = NULL;
120637c53322Sespie 
120737c53322Sespie   delete_non_B_K_work_stuff (work);
120800bf4279Sespie 
120900bf4279Sespie   /* If demangling was successful, ensure that the demangled string is null
121000bf4279Sespie      terminated and return it.  Otherwise, free the demangling decl.  */
121100bf4279Sespie 
121200bf4279Sespie   if (!success)
121300bf4279Sespie     {
121400bf4279Sespie       string_delete (declp);
121500bf4279Sespie     }
121600bf4279Sespie   else
121700bf4279Sespie     {
121800bf4279Sespie       string_appendn (declp, "", 1);
121900bf4279Sespie       demangled = declp->b;
122000bf4279Sespie     }
122100bf4279Sespie   return (demangled);
122200bf4279Sespie }
122300bf4279Sespie 
122400bf4279Sespie /*
122500bf4279Sespie 
122600bf4279Sespie LOCAL FUNCTION
122700bf4279Sespie 
122800bf4279Sespie 	demangle_signature -- demangle the signature part of a mangled name
122900bf4279Sespie 
123000bf4279Sespie SYNOPSIS
123100bf4279Sespie 
123200bf4279Sespie 	static int
123300bf4279Sespie 	demangle_signature (struct work_stuff *work, const char **mangled,
123400bf4279Sespie 			    string *declp);
123500bf4279Sespie 
123600bf4279Sespie DESCRIPTION
123700bf4279Sespie 
123800bf4279Sespie 	Consume and demangle the signature portion of the mangled name.
123900bf4279Sespie 
124000bf4279Sespie 	DECLP is the string where demangled output is being built.  At
124100bf4279Sespie 	entry it contains the demangled root name from the mangled name
124200bf4279Sespie 	prefix.  I.E. either a demangled operator name or the root function
124300bf4279Sespie 	name.  In some special cases, it may contain nothing.
124400bf4279Sespie 
124500bf4279Sespie 	*MANGLED points to the current unconsumed location in the mangled
124600bf4279Sespie 	name.  As tokens are consumed and demangling is performed, the
124700bf4279Sespie 	pointer is updated to continuously point at the next token to
124800bf4279Sespie 	be consumed.
124900bf4279Sespie 
125000bf4279Sespie 	Demangling GNU style mangled names is nasty because there is no
125100bf4279Sespie 	explicit token that marks the start of the outermost function
125200bf4279Sespie 	argument list.  */
125300bf4279Sespie 
125400bf4279Sespie static int
demangle_signature(struct work_stuff * work,const char ** mangled,string * declp)1255*150b7e42Smiod demangle_signature (struct work_stuff *work,
1256*150b7e42Smiod                     const char **mangled, string *declp)
125700bf4279Sespie {
125800bf4279Sespie   int success = 1;
125900bf4279Sespie   int func_done = 0;
126000bf4279Sespie   int expect_func = 0;
126100bf4279Sespie   int expect_return_type = 0;
126200bf4279Sespie   const char *oldmangled = NULL;
126300bf4279Sespie   string trawname;
126400bf4279Sespie   string tname;
126500bf4279Sespie 
126600bf4279Sespie   while (success && (**mangled != '\0'))
126700bf4279Sespie     {
126800bf4279Sespie       switch (**mangled)
126900bf4279Sespie 	{
127000bf4279Sespie 	case 'Q':
127100bf4279Sespie 	  oldmangled = *mangled;
127200bf4279Sespie 	  success = demangle_qualified (work, mangled, declp, 1, 0);
127300bf4279Sespie 	  if (success)
127400bf4279Sespie 	    remember_type (work, oldmangled, *mangled - oldmangled);
127500bf4279Sespie 	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
127600bf4279Sespie 	    expect_func = 1;
127700bf4279Sespie 	  oldmangled = NULL;
127800bf4279Sespie 	  break;
127900bf4279Sespie 
128000bf4279Sespie         case 'K':
128100bf4279Sespie 	  oldmangled = *mangled;
128200bf4279Sespie 	  success = demangle_qualified (work, mangled, declp, 1, 0);
128300bf4279Sespie 	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
128400bf4279Sespie 	    {
128500bf4279Sespie 	      expect_func = 1;
128600bf4279Sespie 	    }
128700bf4279Sespie 	  oldmangled = NULL;
128800bf4279Sespie 	  break;
128900bf4279Sespie 
129000bf4279Sespie 	case 'S':
129100bf4279Sespie 	  /* Static member function */
129200bf4279Sespie 	  if (oldmangled == NULL)
129300bf4279Sespie 	    {
129400bf4279Sespie 	      oldmangled = *mangled;
129500bf4279Sespie 	    }
129600bf4279Sespie 	  (*mangled)++;
129700bf4279Sespie 	  work -> static_type = 1;
129800bf4279Sespie 	  break;
129900bf4279Sespie 
130000bf4279Sespie 	case 'C':
130100bf4279Sespie 	case 'V':
130200bf4279Sespie 	case 'u':
130300bf4279Sespie 	  work->type_quals |= code_for_qualifier (**mangled);
130400bf4279Sespie 
130500bf4279Sespie 	  /* a qualified member function */
130600bf4279Sespie 	  if (oldmangled == NULL)
130700bf4279Sespie 	    oldmangled = *mangled;
130800bf4279Sespie 	  (*mangled)++;
130900bf4279Sespie 	  break;
131000bf4279Sespie 
131100bf4279Sespie 	case 'L':
131200bf4279Sespie 	  /* Local class name follows after "Lnnn_" */
131300bf4279Sespie 	  if (HP_DEMANGLING)
131400bf4279Sespie 	    {
131500bf4279Sespie 	      while (**mangled && (**mangled != '_'))
131600bf4279Sespie 		(*mangled)++;
131700bf4279Sespie 	      if (!**mangled)
131800bf4279Sespie 		success = 0;
131900bf4279Sespie 	      else
132000bf4279Sespie 		(*mangled)++;
132100bf4279Sespie 	    }
132200bf4279Sespie 	  else
132300bf4279Sespie 	    success = 0;
132400bf4279Sespie 	  break;
132500bf4279Sespie 
132600bf4279Sespie 	case '0': case '1': case '2': case '3': case '4':
132700bf4279Sespie 	case '5': case '6': case '7': case '8': case '9':
132800bf4279Sespie 	  if (oldmangled == NULL)
132900bf4279Sespie 	    {
133000bf4279Sespie 	      oldmangled = *mangled;
133100bf4279Sespie 	    }
133200bf4279Sespie           work->temp_start = -1; /* uppermost call to demangle_class */
133300bf4279Sespie 	  success = demangle_class (work, mangled, declp);
133400bf4279Sespie 	  if (success)
133500bf4279Sespie 	    {
133600bf4279Sespie 	      remember_type (work, oldmangled, *mangled - oldmangled);
133700bf4279Sespie 	    }
133800bf4279Sespie 	  if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
133900bf4279Sespie 	    {
134000bf4279Sespie               /* EDG and others will have the "F", so we let the loop cycle
134100bf4279Sespie                  if we are looking at one. */
134200bf4279Sespie               if (**mangled != 'F')
134300bf4279Sespie                  expect_func = 1;
134400bf4279Sespie 	    }
134500bf4279Sespie 	  oldmangled = NULL;
134600bf4279Sespie 	  break;
134700bf4279Sespie 
134800bf4279Sespie 	case 'B':
134900bf4279Sespie 	  {
135000bf4279Sespie 	    string s;
135100bf4279Sespie 	    success = do_type (work, mangled, &s);
135200bf4279Sespie 	    if (success)
135300bf4279Sespie 	      {
135400bf4279Sespie 		string_append (&s, SCOPE_STRING (work));
135500bf4279Sespie 		string_prepends (declp, &s);
1356707f648cSespie 		string_delete (&s);
135700bf4279Sespie 	      }
135800bf4279Sespie 	    oldmangled = NULL;
135900bf4279Sespie 	    expect_func = 1;
136000bf4279Sespie 	  }
136100bf4279Sespie 	  break;
136200bf4279Sespie 
136300bf4279Sespie 	case 'F':
136400bf4279Sespie 	  /* Function */
136500bf4279Sespie 	  /* ARM/HP style demangling includes a specific 'F' character after
136600bf4279Sespie 	     the class name.  For GNU style, it is just implied.  So we can
136700bf4279Sespie 	     safely just consume any 'F' at this point and be compatible
136800bf4279Sespie 	     with either style.  */
136900bf4279Sespie 
137000bf4279Sespie 	  oldmangled = NULL;
137100bf4279Sespie 	  func_done = 1;
137200bf4279Sespie 	  (*mangled)++;
137300bf4279Sespie 
137400bf4279Sespie 	  /* For lucid/ARM/HP style we have to forget any types we might
137500bf4279Sespie 	     have remembered up to this point, since they were not argument
137600bf4279Sespie 	     types.  GNU style considers all types seen as available for
137700bf4279Sespie 	     back references.  See comment in demangle_args() */
137800bf4279Sespie 
137900bf4279Sespie 	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
138000bf4279Sespie 	    {
138100bf4279Sespie 	      forget_types (work);
138200bf4279Sespie 	    }
138300bf4279Sespie 	  success = demangle_args (work, mangled, declp);
138400bf4279Sespie 	  /* After picking off the function args, we expect to either
138500bf4279Sespie 	     find the function return type (preceded by an '_') or the
138600bf4279Sespie 	     end of the string. */
138700bf4279Sespie 	  if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
138800bf4279Sespie 	    {
138900bf4279Sespie 	      ++(*mangled);
139000bf4279Sespie               /* At this level, we do not care about the return type. */
139100bf4279Sespie               success = do_type (work, mangled, &tname);
139200bf4279Sespie               string_delete (&tname);
139300bf4279Sespie             }
139400bf4279Sespie 
139500bf4279Sespie 	  break;
139600bf4279Sespie 
139700bf4279Sespie 	case 't':
139800bf4279Sespie 	  /* G++ Template */
139900bf4279Sespie 	  string_init(&trawname);
140000bf4279Sespie 	  string_init(&tname);
140100bf4279Sespie 	  if (oldmangled == NULL)
140200bf4279Sespie 	    {
140300bf4279Sespie 	      oldmangled = *mangled;
140400bf4279Sespie 	    }
140500bf4279Sespie 	  success = demangle_template (work, mangled, &tname,
140600bf4279Sespie 				       &trawname, 1, 1);
140700bf4279Sespie 	  if (success)
140800bf4279Sespie 	    {
140900bf4279Sespie 	      remember_type (work, oldmangled, *mangled - oldmangled);
141000bf4279Sespie 	    }
141100bf4279Sespie 	  string_append (&tname, SCOPE_STRING (work));
141200bf4279Sespie 
141300bf4279Sespie 	  string_prepends(declp, &tname);
141400bf4279Sespie 	  if (work -> destructor & 1)
141500bf4279Sespie 	    {
141600bf4279Sespie 	      string_prepend (&trawname, "~");
141700bf4279Sespie 	      string_appends (declp, &trawname);
141800bf4279Sespie 	      work->destructor -= 1;
141900bf4279Sespie 	    }
142000bf4279Sespie 	  if ((work->constructor & 1) || (work->destructor & 1))
142100bf4279Sespie 	    {
142200bf4279Sespie 	      string_appends (declp, &trawname);
142300bf4279Sespie 	      work->constructor -= 1;
142400bf4279Sespie 	    }
142500bf4279Sespie 	  string_delete(&trawname);
142600bf4279Sespie 	  string_delete(&tname);
142700bf4279Sespie 	  oldmangled = NULL;
142800bf4279Sespie 	  expect_func = 1;
142900bf4279Sespie 	  break;
143000bf4279Sespie 
143100bf4279Sespie 	case '_':
143237c53322Sespie 	  if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
143300bf4279Sespie 	    {
143400bf4279Sespie 	      /* Read the return type. */
143500bf4279Sespie 	      string return_type;
143600bf4279Sespie 
143700bf4279Sespie 	      (*mangled)++;
143800bf4279Sespie 	      success = do_type (work, mangled, &return_type);
143900bf4279Sespie 	      APPEND_BLANK (&return_type);
144000bf4279Sespie 
144100bf4279Sespie 	      string_prepends (declp, &return_type);
144200bf4279Sespie 	      string_delete (&return_type);
144300bf4279Sespie 	      break;
144400bf4279Sespie 	    }
144500bf4279Sespie 	  else
144600bf4279Sespie 	    /* At the outermost level, we cannot have a return type specified,
144700bf4279Sespie 	       so if we run into another '_' at this point we are dealing with
144800bf4279Sespie 	       a mangled name that is either bogus, or has been mangled by
144900bf4279Sespie 	       some algorithm we don't know how to deal with.  So just
145000bf4279Sespie 	       reject the entire demangling.  */
145100bf4279Sespie             /* However, "_nnn" is an expected suffix for alternate entry point
145200bf4279Sespie                numbered nnn for a function, with HP aCC, so skip over that
145300bf4279Sespie                without reporting failure. pai/1997-09-04 */
145400bf4279Sespie             if (HP_DEMANGLING)
145500bf4279Sespie               {
145600bf4279Sespie                 (*mangled)++;
145737c53322Sespie                 while (**mangled && ISDIGIT ((unsigned char)**mangled))
145800bf4279Sespie                   (*mangled)++;
145900bf4279Sespie               }
146000bf4279Sespie             else
146100bf4279Sespie 	      success = 0;
146200bf4279Sespie 	  break;
146300bf4279Sespie 
146400bf4279Sespie 	case 'H':
146537c53322Sespie 	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
146600bf4279Sespie 	    {
146700bf4279Sespie 	      /* A G++ template function.  Read the template arguments. */
146800bf4279Sespie 	      success = demangle_template (work, mangled, declp, 0, 0,
146900bf4279Sespie 					   0);
147000bf4279Sespie 	      if (!(work->constructor & 1))
147100bf4279Sespie 		expect_return_type = 1;
147200bf4279Sespie 	      (*mangled)++;
147300bf4279Sespie 	      break;
147400bf4279Sespie 	    }
147500bf4279Sespie 	  else
147600bf4279Sespie 	    /* fall through */
147700bf4279Sespie 	    {;}
147800bf4279Sespie 
147900bf4279Sespie 	default:
148000bf4279Sespie 	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
148100bf4279Sespie 	    {
148200bf4279Sespie 	      /* Assume we have stumbled onto the first outermost function
148300bf4279Sespie 		 argument token, and start processing args.  */
148400bf4279Sespie 	      func_done = 1;
148500bf4279Sespie 	      success = demangle_args (work, mangled, declp);
148600bf4279Sespie 	    }
148700bf4279Sespie 	  else
148800bf4279Sespie 	    {
148900bf4279Sespie 	      /* Non-GNU demanglers use a specific token to mark the start
149000bf4279Sespie 		 of the outermost function argument tokens.  Typically 'F',
149100bf4279Sespie 		 for ARM/HP-demangling, for example.  So if we find something
149200bf4279Sespie 		 we are not prepared for, it must be an error.  */
149300bf4279Sespie 	      success = 0;
149400bf4279Sespie 	    }
149500bf4279Sespie 	  break;
149600bf4279Sespie 	}
149700bf4279Sespie       /*
149800bf4279Sespie 	if (AUTO_DEMANGLING || GNU_DEMANGLING)
149900bf4279Sespie 	*/
150000bf4279Sespie       {
150100bf4279Sespie 	if (success && expect_func)
150200bf4279Sespie 	  {
150300bf4279Sespie 	    func_done = 1;
150400bf4279Sespie               if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
150500bf4279Sespie                 {
150600bf4279Sespie                   forget_types (work);
150700bf4279Sespie                 }
150800bf4279Sespie 	    success = demangle_args (work, mangled, declp);
150900bf4279Sespie 	    /* Since template include the mangling of their return types,
151000bf4279Sespie 	       we must set expect_func to 0 so that we don't try do
151100bf4279Sespie 	       demangle more arguments the next time we get here.  */
151200bf4279Sespie 	    expect_func = 0;
151300bf4279Sespie 	  }
151400bf4279Sespie       }
151500bf4279Sespie     }
151600bf4279Sespie   if (success && !func_done)
151700bf4279Sespie     {
151800bf4279Sespie       if (AUTO_DEMANGLING || GNU_DEMANGLING)
151900bf4279Sespie 	{
152000bf4279Sespie 	  /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
152100bf4279Sespie 	     bar__3fooi is 'foo::bar(int)'.  We get here when we find the
152200bf4279Sespie 	     first case, and need to ensure that the '(void)' gets added to
152300bf4279Sespie 	     the current declp.  Note that with ARM/HP, the first case
152400bf4279Sespie 	     represents the name of a static data member 'foo::bar',
152500bf4279Sespie 	     which is in the current declp, so we leave it alone.  */
152600bf4279Sespie 	  success = demangle_args (work, mangled, declp);
152700bf4279Sespie 	}
152800bf4279Sespie     }
152900bf4279Sespie   if (success && PRINT_ARG_TYPES)
153000bf4279Sespie     {
153100bf4279Sespie       if (work->static_type)
153200bf4279Sespie 	string_append (declp, " static");
153300bf4279Sespie       if (work->type_quals != TYPE_UNQUALIFIED)
153400bf4279Sespie 	{
153500bf4279Sespie 	  APPEND_BLANK (declp);
153600bf4279Sespie 	  string_append (declp, qualifier_string (work->type_quals));
153700bf4279Sespie 	}
153800bf4279Sespie     }
153900bf4279Sespie 
154000bf4279Sespie   return (success);
154100bf4279Sespie }
154200bf4279Sespie 
154300bf4279Sespie #if 0
154400bf4279Sespie 
154500bf4279Sespie static int
1546*150b7e42Smiod demangle_method_args (struct work_stuff *work, const char **mangled,
1547*150b7e42Smiod                       string *declp)
154800bf4279Sespie {
154900bf4279Sespie   int success = 0;
155000bf4279Sespie 
155100bf4279Sespie   if (work -> static_type)
155200bf4279Sespie     {
155300bf4279Sespie       string_append (declp, *mangled + 1);
155400bf4279Sespie       *mangled += strlen (*mangled);
155500bf4279Sespie       success = 1;
155600bf4279Sespie     }
155700bf4279Sespie   else
155800bf4279Sespie     {
155900bf4279Sespie       success = demangle_args (work, mangled, declp);
156000bf4279Sespie     }
156100bf4279Sespie   return (success);
156200bf4279Sespie }
156300bf4279Sespie 
156400bf4279Sespie #endif
156500bf4279Sespie 
156600bf4279Sespie static int
demangle_template_template_parm(struct work_stuff * work,const char ** mangled,string * tname)1567*150b7e42Smiod demangle_template_template_parm (struct work_stuff *work,
1568*150b7e42Smiod                                  const char **mangled, string *tname)
156900bf4279Sespie {
157000bf4279Sespie   int i;
157100bf4279Sespie   int r;
157200bf4279Sespie   int need_comma = 0;
157300bf4279Sespie   int success = 1;
157400bf4279Sespie   string temp;
157500bf4279Sespie 
157600bf4279Sespie   string_append (tname, "template <");
157700bf4279Sespie   /* get size of template parameter list */
157800bf4279Sespie   if (get_count (mangled, &r))
157900bf4279Sespie     {
158000bf4279Sespie       for (i = 0; i < r; i++)
158100bf4279Sespie 	{
158200bf4279Sespie 	  if (need_comma)
158300bf4279Sespie 	    {
158400bf4279Sespie 	      string_append (tname, ", ");
158500bf4279Sespie 	    }
158600bf4279Sespie 
158700bf4279Sespie 	    /* Z for type parameters */
158800bf4279Sespie 	    if (**mangled == 'Z')
158900bf4279Sespie 	      {
159000bf4279Sespie 		(*mangled)++;
159100bf4279Sespie 		string_append (tname, "class");
159200bf4279Sespie 	      }
159300bf4279Sespie 	      /* z for template parameters */
159400bf4279Sespie 	    else if (**mangled == 'z')
159500bf4279Sespie 	      {
159600bf4279Sespie 		(*mangled)++;
159700bf4279Sespie 		success =
159800bf4279Sespie 		  demangle_template_template_parm (work, mangled, tname);
159900bf4279Sespie 		if (!success)
160000bf4279Sespie 		  {
160100bf4279Sespie 		    break;
160200bf4279Sespie 		  }
160300bf4279Sespie 	      }
160400bf4279Sespie 	    else
160500bf4279Sespie 	      {
160600bf4279Sespie 		/* temp is initialized in do_type */
160700bf4279Sespie 		success = do_type (work, mangled, &temp);
160800bf4279Sespie 		if (success)
160900bf4279Sespie 		  {
161000bf4279Sespie 		    string_appends (tname, &temp);
161100bf4279Sespie 		  }
161200bf4279Sespie 		string_delete(&temp);
161300bf4279Sespie 		if (!success)
161400bf4279Sespie 		  {
161500bf4279Sespie 		    break;
161600bf4279Sespie 		  }
161700bf4279Sespie 	      }
161800bf4279Sespie 	  need_comma = 1;
161900bf4279Sespie 	}
162000bf4279Sespie 
162100bf4279Sespie     }
162200bf4279Sespie   if (tname->p[-1] == '>')
162300bf4279Sespie     string_append (tname, " ");
162400bf4279Sespie   string_append (tname, "> class");
162500bf4279Sespie   return (success);
162600bf4279Sespie }
162700bf4279Sespie 
162800bf4279Sespie static int
demangle_expression(struct work_stuff * work,const char ** mangled,string * s,type_kind_t tk)1629*150b7e42Smiod demangle_expression (struct work_stuff *work, const char **mangled,
1630*150b7e42Smiod                      string *s, type_kind_t tk)
163100bf4279Sespie {
163200bf4279Sespie   int need_operator = 0;
163337c53322Sespie   int success;
163400bf4279Sespie 
163500bf4279Sespie   success = 1;
163600bf4279Sespie   string_appendn (s, "(", 1);
163700bf4279Sespie   (*mangled)++;
163800bf4279Sespie   while (success && **mangled != 'W' && **mangled != '\0')
163900bf4279Sespie     {
164000bf4279Sespie       if (need_operator)
164100bf4279Sespie 	{
164200bf4279Sespie 	  size_t i;
164300bf4279Sespie 	  size_t len;
164400bf4279Sespie 
164500bf4279Sespie 	  success = 0;
164600bf4279Sespie 
164700bf4279Sespie 	  len = strlen (*mangled);
164800bf4279Sespie 
164937c53322Sespie 	  for (i = 0; i < ARRAY_SIZE (optable); ++i)
165000bf4279Sespie 	    {
165100bf4279Sespie 	      size_t l = strlen (optable[i].in);
165200bf4279Sespie 
165300bf4279Sespie 	      if (l <= len
165400bf4279Sespie 		  && memcmp (optable[i].in, *mangled, l) == 0)
165500bf4279Sespie 		{
165600bf4279Sespie 		  string_appendn (s, " ", 1);
165700bf4279Sespie 		  string_append (s, optable[i].out);
165800bf4279Sespie 		  string_appendn (s, " ", 1);
165900bf4279Sespie 		  success = 1;
166000bf4279Sespie 		  (*mangled) += l;
166100bf4279Sespie 		  break;
166200bf4279Sespie 		}
166300bf4279Sespie 	    }
166400bf4279Sespie 
166500bf4279Sespie 	  if (!success)
166600bf4279Sespie 	    break;
166700bf4279Sespie 	}
166800bf4279Sespie       else
166900bf4279Sespie 	need_operator = 1;
167000bf4279Sespie 
167137c53322Sespie       success = demangle_template_value_parm (work, mangled, s, tk);
167200bf4279Sespie     }
167300bf4279Sespie 
167400bf4279Sespie   if (**mangled != 'W')
167500bf4279Sespie     success = 0;
167600bf4279Sespie   else
167700bf4279Sespie     {
167800bf4279Sespie       string_appendn (s, ")", 1);
167900bf4279Sespie       (*mangled)++;
168000bf4279Sespie     }
168137c53322Sespie 
168237c53322Sespie   return success;
168300bf4279Sespie }
168437c53322Sespie 
168537c53322Sespie static int
demangle_integral_value(struct work_stuff * work,const char ** mangled,string * s)1686*150b7e42Smiod demangle_integral_value (struct work_stuff *work,
1687*150b7e42Smiod                          const char **mangled, string *s)
168837c53322Sespie {
168937c53322Sespie   int success;
169037c53322Sespie 
169137c53322Sespie   if (**mangled == 'E')
169237c53322Sespie     success = demangle_expression (work, mangled, s, tk_integral);
169300bf4279Sespie   else if (**mangled == 'Q' || **mangled == 'K')
169400bf4279Sespie     success = demangle_qualified (work, mangled, s, 0, 1);
169500bf4279Sespie   else
169600bf4279Sespie     {
169737c53322Sespie       int value;
169837c53322Sespie 
169937c53322Sespie       /* By default, we let the number decide whether we shall consume an
170037c53322Sespie 	 underscore.  */
170137c53322Sespie       int multidigit_without_leading_underscore = 0;
170237c53322Sespie       int leave_following_underscore = 0;
170337c53322Sespie 
170400bf4279Sespie       success = 0;
170500bf4279Sespie 
1706707f648cSespie       if (**mangled == '_')
170737c53322Sespie         {
1708707f648cSespie 	  if (mangled[0][1] == 'm')
170937c53322Sespie 	    {
171037c53322Sespie 	      /* Since consume_count_with_underscores does not handle the
171137c53322Sespie 		 `m'-prefix we must do it here, using consume_count and
171237c53322Sespie 		 adjusting underscores: we have to consume the underscore
171337c53322Sespie 		 matching the prepended one.  */
171437c53322Sespie 	      multidigit_without_leading_underscore = 1;
171537c53322Sespie 	      string_appendn (s, "-", 1);
171637c53322Sespie 	      (*mangled) += 2;
171737c53322Sespie 	    }
1718707f648cSespie 	  else
171937c53322Sespie 	    {
172037c53322Sespie 	      /* Do not consume a following underscore;
1721707f648cSespie 	         consume_count_with_underscores will consume what
1722707f648cSespie 	         should be consumed.  */
172337c53322Sespie 	      leave_following_underscore = 1;
172437c53322Sespie 	    }
1725707f648cSespie 	}
172637c53322Sespie       else
172737c53322Sespie 	{
1728707f648cSespie 	  /* Negative numbers are indicated with a leading `m'.  */
1729707f648cSespie 	  if (**mangled == 'm')
1730707f648cSespie 	  {
1731707f648cSespie 	    string_appendn (s, "-", 1);
1732707f648cSespie 	    (*mangled)++;
1733707f648cSespie 	  }
173437c53322Sespie 	  /* Since consume_count_with_underscores does not handle
173537c53322Sespie 	     multi-digit numbers that do not start with an underscore,
173637c53322Sespie 	     and this number can be an integer template parameter,
173737c53322Sespie 	     we have to call consume_count. */
173837c53322Sespie 	  multidigit_without_leading_underscore = 1;
173937c53322Sespie 	  /* These multi-digit numbers never end on an underscore,
174037c53322Sespie 	     so if there is one then don't eat it. */
174137c53322Sespie 	  leave_following_underscore = 1;
174237c53322Sespie 	}
174337c53322Sespie 
174437c53322Sespie       /* We must call consume_count if we expect to remove a trailing
174537c53322Sespie 	 underscore, since consume_count_with_underscores expects
174637c53322Sespie 	 the leading underscore (that we consumed) if it is to handle
174737c53322Sespie 	 multi-digit numbers.  */
174837c53322Sespie       if (multidigit_without_leading_underscore)
174937c53322Sespie 	value = consume_count (mangled);
175037c53322Sespie       else
175137c53322Sespie 	value = consume_count_with_underscores (mangled);
175237c53322Sespie 
175337c53322Sespie       if (value != -1)
175437c53322Sespie 	{
175537c53322Sespie 	  char buf[INTBUF_SIZE];
175697490679Sespie 	  snprintf (buf, sizeof buf, "%d", value);
175737c53322Sespie 	  string_append (s, buf);
175837c53322Sespie 
175937c53322Sespie 	  /* Numbers not otherwise delimited, might have an underscore
176037c53322Sespie 	     appended as a delimeter, which we should skip.
176137c53322Sespie 
176237c53322Sespie 	     ??? This used to always remove a following underscore, which
176337c53322Sespie 	     is wrong.  If other (arbitrary) cases are followed by an
176437c53322Sespie 	     underscore, we need to do something more radical.  */
176537c53322Sespie 
176637c53322Sespie 	  if ((value > 9 || multidigit_without_leading_underscore)
176737c53322Sespie 	      && ! leave_following_underscore
176837c53322Sespie 	      && **mangled == '_')
176937c53322Sespie 	    (*mangled)++;
177037c53322Sespie 
177137c53322Sespie 	  /* All is well.  */
177237c53322Sespie 	  success = 1;
177337c53322Sespie 	}
177437c53322Sespie       }
177537c53322Sespie 
177637c53322Sespie   return success;
177737c53322Sespie }
177837c53322Sespie 
177937c53322Sespie /* Demangle the real value in MANGLED.  */
178037c53322Sespie 
178137c53322Sespie static int
demangle_real_value(struct work_stuff * work,const char ** mangled,string * s)1782*150b7e42Smiod demangle_real_value (struct work_stuff *work,
1783*150b7e42Smiod                      const char **mangled, string *s)
178437c53322Sespie {
178537c53322Sespie   if (**mangled == 'E')
178637c53322Sespie     return demangle_expression (work, mangled, s, tk_real);
178737c53322Sespie 
178800bf4279Sespie   if (**mangled == 'm')
178900bf4279Sespie     {
179000bf4279Sespie       string_appendn (s, "-", 1);
179100bf4279Sespie       (*mangled)++;
179200bf4279Sespie     }
179337c53322Sespie   while (ISDIGIT ((unsigned char)**mangled))
17942e0724c7Sespie     {
179501e9b57fSespie       string_appendn (s, *mangled, 1);
179600bf4279Sespie       (*mangled)++;
179737c53322Sespie     }
179837c53322Sespie   if (**mangled == '.') /* fraction */
179937c53322Sespie     {
180037c53322Sespie       string_appendn (s, ".", 1);
180137c53322Sespie       (*mangled)++;
180237c53322Sespie       while (ISDIGIT ((unsigned char)**mangled))
180337c53322Sespie 	{
180437c53322Sespie 	  string_appendn (s, *mangled, 1);
180537c53322Sespie 	  (*mangled)++;
180637c53322Sespie 	}
180737c53322Sespie     }
180837c53322Sespie   if (**mangled == 'e') /* exponent */
180937c53322Sespie     {
181037c53322Sespie       string_appendn (s, "e", 1);
181137c53322Sespie       (*mangled)++;
181237c53322Sespie       while (ISDIGIT ((unsigned char)**mangled))
181337c53322Sespie 	{
181437c53322Sespie 	  string_appendn (s, *mangled, 1);
181537c53322Sespie 	  (*mangled)++;
181600bf4279Sespie 	}
181700bf4279Sespie     }
181800bf4279Sespie 
181937c53322Sespie   return 1;
182000bf4279Sespie }
182100bf4279Sespie 
182200bf4279Sespie static int
demangle_template_value_parm(struct work_stuff * work,const char ** mangled,string * s,type_kind_t tk)1823*150b7e42Smiod demangle_template_value_parm (struct work_stuff *work, const char **mangled,
1824*150b7e42Smiod                               string *s, type_kind_t tk)
182500bf4279Sespie {
182600bf4279Sespie   int success = 1;
182700bf4279Sespie 
182800bf4279Sespie   if (**mangled == 'Y')
182900bf4279Sespie     {
183000bf4279Sespie       /* The next argument is a template parameter. */
183100bf4279Sespie       int idx;
183200bf4279Sespie 
183300bf4279Sespie       (*mangled)++;
183400bf4279Sespie       idx = consume_count_with_underscores (mangled);
183500bf4279Sespie       if (idx == -1
183600bf4279Sespie 	  || (work->tmpl_argvec && idx >= work->ntmpl_args)
183700bf4279Sespie 	  || consume_count_with_underscores (mangled) == -1)
183800bf4279Sespie 	return -1;
183900bf4279Sespie       if (work->tmpl_argvec)
184000bf4279Sespie 	string_append (s, work->tmpl_argvec[idx]);
184100bf4279Sespie       else
184237c53322Sespie 	string_append_template_idx (s, idx);
184300bf4279Sespie     }
184400bf4279Sespie   else if (tk == tk_integral)
184500bf4279Sespie     success = demangle_integral_value (work, mangled, s);
184600bf4279Sespie   else if (tk == tk_char)
184700bf4279Sespie     {
184800bf4279Sespie       char tmp[2];
184900bf4279Sespie       int val;
185000bf4279Sespie       if (**mangled == 'm')
185100bf4279Sespie 	{
185200bf4279Sespie 	  string_appendn (s, "-", 1);
185300bf4279Sespie 	  (*mangled)++;
185400bf4279Sespie 	}
185500bf4279Sespie       string_appendn (s, "'", 1);
185600bf4279Sespie       val = consume_count(mangled);
185700bf4279Sespie       if (val <= 0)
185800bf4279Sespie 	success = 0;
185900bf4279Sespie       else
186000bf4279Sespie 	{
186100bf4279Sespie 	  tmp[0] = (char)val;
186200bf4279Sespie 	  tmp[1] = '\0';
186300bf4279Sespie 	  string_appendn (s, &tmp[0], 1);
186400bf4279Sespie 	  string_appendn (s, "'", 1);
186500bf4279Sespie 	}
186600bf4279Sespie     }
186700bf4279Sespie   else if (tk == tk_bool)
186800bf4279Sespie     {
186900bf4279Sespie       int val = consume_count (mangled);
187000bf4279Sespie       if (val == 0)
187100bf4279Sespie 	string_appendn (s, "false", 5);
187200bf4279Sespie       else if (val == 1)
187300bf4279Sespie 	string_appendn (s, "true", 4);
187400bf4279Sespie       else
187500bf4279Sespie 	success = 0;
187600bf4279Sespie     }
187700bf4279Sespie   else if (tk == tk_real)
187837c53322Sespie     success = demangle_real_value (work, mangled, s);
187900bf4279Sespie   else if (tk == tk_pointer || tk == tk_reference)
188000bf4279Sespie     {
188100bf4279Sespie       if (**mangled == 'Q')
188200bf4279Sespie 	success = demangle_qualified (work, mangled, s,
188300bf4279Sespie 				      /*isfuncname=*/0,
188400bf4279Sespie 				      /*append=*/1);
188500bf4279Sespie       else
188600bf4279Sespie 	{
188700bf4279Sespie 	  int symbol_len  = consume_count (mangled);
188800bf4279Sespie 	  if (symbol_len == -1)
188900bf4279Sespie 	    return -1;
189000bf4279Sespie 	  if (symbol_len == 0)
189100bf4279Sespie 	    string_appendn (s, "0", 1);
189200bf4279Sespie 	  else
189300bf4279Sespie 	    {
1894*150b7e42Smiod 	      char *p = XNEWVEC (char, symbol_len + 1), *q;
189500bf4279Sespie 	      strncpy (p, *mangled, symbol_len);
189600bf4279Sespie 	      p [symbol_len] = '\0';
189700bf4279Sespie 	      /* We use cplus_demangle here, rather than
189800bf4279Sespie 		 internal_cplus_demangle, because the name of the entity
189900bf4279Sespie 		 mangled here does not make use of any of the squangling
190000bf4279Sespie 		 or type-code information we have built up thus far; it is
190100bf4279Sespie 		 mangled independently.  */
190200bf4279Sespie 	      q = cplus_demangle (p, work->options);
190300bf4279Sespie 	      if (tk == tk_pointer)
190400bf4279Sespie 		string_appendn (s, "&", 1);
190500bf4279Sespie 	      /* FIXME: Pointer-to-member constants should get a
190600bf4279Sespie 		 qualifying class name here.  */
190700bf4279Sespie 	      if (q)
190800bf4279Sespie 		{
190900bf4279Sespie 		  string_append (s, q);
191000bf4279Sespie 		  free (q);
191100bf4279Sespie 		}
191200bf4279Sespie 	      else
191300bf4279Sespie 		string_append (s, p);
191400bf4279Sespie 	      free (p);
191500bf4279Sespie 	    }
191600bf4279Sespie 	  *mangled += symbol_len;
191700bf4279Sespie 	}
191800bf4279Sespie     }
191900bf4279Sespie 
192000bf4279Sespie   return success;
192100bf4279Sespie }
192200bf4279Sespie 
192300bf4279Sespie /* Demangle the template name in MANGLED.  The full name of the
192400bf4279Sespie    template (e.g., S<int>) is placed in TNAME.  The name without the
192500bf4279Sespie    template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
192600bf4279Sespie    non-NULL.  If IS_TYPE is nonzero, this template is a type template,
192700bf4279Sespie    not a function template.  If both IS_TYPE and REMEMBER are nonzero,
192837c53322Sespie    the template is remembered in the list of back-referenceable
192900bf4279Sespie    types.  */
193000bf4279Sespie 
193100bf4279Sespie static int
demangle_template(struct work_stuff * work,const char ** mangled,string * tname,string * trawname,int is_type,int remember)1932*150b7e42Smiod demangle_template (struct work_stuff *work, const char **mangled,
1933*150b7e42Smiod                    string *tname, string *trawname,
1934*150b7e42Smiod                    int is_type, int remember)
193500bf4279Sespie {
193600bf4279Sespie   int i;
193700bf4279Sespie   int r;
193800bf4279Sespie   int need_comma = 0;
193900bf4279Sespie   int success = 0;
194000bf4279Sespie   int is_java_array = 0;
194100bf4279Sespie   string temp;
194200bf4279Sespie 
194300bf4279Sespie   (*mangled)++;
194400bf4279Sespie   if (is_type)
194500bf4279Sespie     {
194600bf4279Sespie       /* get template name */
194700bf4279Sespie       if (**mangled == 'z')
194800bf4279Sespie 	{
194900bf4279Sespie 	  int idx;
195000bf4279Sespie 	  (*mangled)++;
195100bf4279Sespie 	  (*mangled)++;
195200bf4279Sespie 
195300bf4279Sespie 	  idx = consume_count_with_underscores (mangled);
195400bf4279Sespie 	  if (idx == -1
195500bf4279Sespie 	      || (work->tmpl_argvec && idx >= work->ntmpl_args)
195600bf4279Sespie 	      || consume_count_with_underscores (mangled) == -1)
195700bf4279Sespie 	    return (0);
195800bf4279Sespie 
195900bf4279Sespie 	  if (work->tmpl_argvec)
196000bf4279Sespie 	    {
196100bf4279Sespie 	      string_append (tname, work->tmpl_argvec[idx]);
196200bf4279Sespie 	      if (trawname)
196300bf4279Sespie 		string_append (trawname, work->tmpl_argvec[idx]);
196400bf4279Sespie 	    }
196500bf4279Sespie 	  else
196600bf4279Sespie 	    {
196737c53322Sespie 	      string_append_template_idx (tname, idx);
196800bf4279Sespie 	      if (trawname)
196937c53322Sespie 		string_append_template_idx (trawname, idx);
197000bf4279Sespie 	    }
197100bf4279Sespie 	}
197200bf4279Sespie       else
197300bf4279Sespie 	{
197400bf4279Sespie 	  if ((r = consume_count (mangled)) <= 0
197500bf4279Sespie 	      || (int) strlen (*mangled) < r)
197600bf4279Sespie 	    {
197700bf4279Sespie 	      return (0);
197800bf4279Sespie 	    }
197900bf4279Sespie 	  is_java_array = (work -> options & DMGL_JAVA)
198000bf4279Sespie 	    && strncmp (*mangled, "JArray1Z", 8) == 0;
198100bf4279Sespie 	  if (! is_java_array)
198200bf4279Sespie 	    {
198300bf4279Sespie 	      string_appendn (tname, *mangled, r);
198400bf4279Sespie 	    }
198500bf4279Sespie 	  if (trawname)
198600bf4279Sespie 	    string_appendn (trawname, *mangled, r);
198700bf4279Sespie 	  *mangled += r;
198800bf4279Sespie 	}
198900bf4279Sespie     }
199000bf4279Sespie   if (!is_java_array)
199100bf4279Sespie     string_append (tname, "<");
199200bf4279Sespie   /* get size of template parameter list */
199300bf4279Sespie   if (!get_count (mangled, &r))
199400bf4279Sespie     {
199500bf4279Sespie       return (0);
199600bf4279Sespie     }
199700bf4279Sespie   if (!is_type)
199800bf4279Sespie     {
199900bf4279Sespie       /* Create an array for saving the template argument values. */
2000*150b7e42Smiod       work->tmpl_argvec = XNEWVEC (char *, r);
200100bf4279Sespie       work->ntmpl_args = r;
200200bf4279Sespie       for (i = 0; i < r; i++)
200300bf4279Sespie 	work->tmpl_argvec[i] = 0;
200400bf4279Sespie     }
200500bf4279Sespie   for (i = 0; i < r; i++)
200600bf4279Sespie     {
200700bf4279Sespie       if (need_comma)
200800bf4279Sespie 	{
200900bf4279Sespie 	  string_append (tname, ", ");
201000bf4279Sespie 	}
201100bf4279Sespie       /* Z for type parameters */
201200bf4279Sespie       if (**mangled == 'Z')
201300bf4279Sespie 	{
201400bf4279Sespie 	  (*mangled)++;
201500bf4279Sespie 	  /* temp is initialized in do_type */
201600bf4279Sespie 	  success = do_type (work, mangled, &temp);
201700bf4279Sespie 	  if (success)
201800bf4279Sespie 	    {
201900bf4279Sespie 	      string_appends (tname, &temp);
202000bf4279Sespie 
202100bf4279Sespie 	      if (!is_type)
202200bf4279Sespie 		{
202300bf4279Sespie 		  /* Save the template argument. */
202400bf4279Sespie 		  int len = temp.p - temp.b;
2025*150b7e42Smiod 		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
202600bf4279Sespie 		  memcpy (work->tmpl_argvec[i], temp.b, len);
202700bf4279Sespie 		  work->tmpl_argvec[i][len] = '\0';
202800bf4279Sespie 		}
202900bf4279Sespie 	    }
203000bf4279Sespie 	  string_delete(&temp);
203100bf4279Sespie 	  if (!success)
203200bf4279Sespie 	    {
203300bf4279Sespie 	      break;
203400bf4279Sespie 	    }
203500bf4279Sespie 	}
203600bf4279Sespie       /* z for template parameters */
203700bf4279Sespie       else if (**mangled == 'z')
203800bf4279Sespie 	{
203900bf4279Sespie 	  int r2;
204000bf4279Sespie 	  (*mangled)++;
204100bf4279Sespie 	  success = demangle_template_template_parm (work, mangled, tname);
204200bf4279Sespie 
204300bf4279Sespie 	  if (success
204400bf4279Sespie 	      && (r2 = consume_count (mangled)) > 0
204500bf4279Sespie 	      && (int) strlen (*mangled) >= r2)
204600bf4279Sespie 	    {
204700bf4279Sespie 	      string_append (tname, " ");
204800bf4279Sespie 	      string_appendn (tname, *mangled, r2);
204900bf4279Sespie 	      if (!is_type)
205000bf4279Sespie 		{
205100bf4279Sespie 		  /* Save the template argument. */
205200bf4279Sespie 		  int len = r2;
2053*150b7e42Smiod 		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
205400bf4279Sespie 		  memcpy (work->tmpl_argvec[i], *mangled, len);
205500bf4279Sespie 		  work->tmpl_argvec[i][len] = '\0';
205600bf4279Sespie 		}
205700bf4279Sespie 	      *mangled += r2;
205800bf4279Sespie 	    }
205900bf4279Sespie 	  if (!success)
206000bf4279Sespie 	    {
206100bf4279Sespie 	      break;
206200bf4279Sespie 	    }
206300bf4279Sespie 	}
206400bf4279Sespie       else
206500bf4279Sespie 	{
206600bf4279Sespie 	  string  param;
206700bf4279Sespie 	  string* s;
206800bf4279Sespie 
206900bf4279Sespie 	  /* otherwise, value parameter */
207000bf4279Sespie 
207100bf4279Sespie 	  /* temp is initialized in do_type */
207200bf4279Sespie 	  success = do_type (work, mangled, &temp);
207300bf4279Sespie 	  string_delete(&temp);
207400bf4279Sespie 	  if (!success)
207500bf4279Sespie 	    break;
207600bf4279Sespie 
207700bf4279Sespie 	  if (!is_type)
207800bf4279Sespie 	    {
207900bf4279Sespie 	      s = &param;
208000bf4279Sespie 	      string_init (s);
208100bf4279Sespie 	    }
208200bf4279Sespie 	  else
208300bf4279Sespie 	    s = tname;
208400bf4279Sespie 
208500bf4279Sespie 	  success = demangle_template_value_parm (work, mangled, s,
208600bf4279Sespie 						  (type_kind_t) success);
208700bf4279Sespie 
208800bf4279Sespie 	  if (!success)
208900bf4279Sespie 	    {
209000bf4279Sespie 	      if (!is_type)
209100bf4279Sespie 		string_delete (s);
209200bf4279Sespie 	      success = 0;
209300bf4279Sespie 	      break;
209400bf4279Sespie 	    }
209500bf4279Sespie 
209600bf4279Sespie 	  if (!is_type)
209700bf4279Sespie 	    {
209800bf4279Sespie 	      int len = s->p - s->b;
2099*150b7e42Smiod 	      work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
210000bf4279Sespie 	      memcpy (work->tmpl_argvec[i], s->b, len);
210100bf4279Sespie 	      work->tmpl_argvec[i][len] = '\0';
210200bf4279Sespie 
210300bf4279Sespie 	      string_appends (tname, s);
210400bf4279Sespie 	      string_delete (s);
210500bf4279Sespie 	    }
210600bf4279Sespie 	}
210700bf4279Sespie       need_comma = 1;
210800bf4279Sespie     }
210900bf4279Sespie   if (is_java_array)
211000bf4279Sespie     {
211100bf4279Sespie       string_append (tname, "[]");
211200bf4279Sespie     }
211300bf4279Sespie   else
211400bf4279Sespie     {
211500bf4279Sespie       if (tname->p[-1] == '>')
211600bf4279Sespie 	string_append (tname, " ");
211700bf4279Sespie       string_append (tname, ">");
211800bf4279Sespie     }
211900bf4279Sespie 
212000bf4279Sespie   if (is_type && remember)
2121*150b7e42Smiod     {
2122*150b7e42Smiod       const int bindex = register_Btype (work);
212300bf4279Sespie       remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
2124*150b7e42Smiod     }
212500bf4279Sespie 
212600bf4279Sespie   /*
212700bf4279Sespie     if (work -> static_type)
212800bf4279Sespie     {
212900bf4279Sespie     string_append (declp, *mangled + 1);
213000bf4279Sespie     *mangled += strlen (*mangled);
213100bf4279Sespie     success = 1;
213200bf4279Sespie     }
213300bf4279Sespie     else
213400bf4279Sespie     {
213500bf4279Sespie     success = demangle_args (work, mangled, declp);
213600bf4279Sespie     }
213700bf4279Sespie     }
213800bf4279Sespie     */
213900bf4279Sespie   return (success);
214000bf4279Sespie }
214100bf4279Sespie 
214200bf4279Sespie static int
arm_pt(struct work_stuff * work,const char * mangled,int n,const char ** anchor,const char ** args)2143*150b7e42Smiod arm_pt (struct work_stuff *work, const char *mangled,
2144*150b7e42Smiod         int n, const char **anchor, const char **args)
214500bf4279Sespie {
214600bf4279Sespie   /* Check if ARM template with "__pt__" in it ("parameterized type") */
214700bf4279Sespie   /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
214837c53322Sespie   if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
214900bf4279Sespie     {
215000bf4279Sespie       int len;
215100bf4279Sespie       *args = *anchor + 6;
215200bf4279Sespie       len = consume_count (args);
215300bf4279Sespie       if (len == -1)
215400bf4279Sespie 	return 0;
215500bf4279Sespie       if (*args + len == mangled + n && **args == '_')
215600bf4279Sespie 	{
215700bf4279Sespie 	  ++*args;
215800bf4279Sespie 	  return 1;
215900bf4279Sespie 	}
216000bf4279Sespie     }
216100bf4279Sespie   if (AUTO_DEMANGLING || EDG_DEMANGLING)
216200bf4279Sespie     {
216337c53322Sespie       if ((*anchor = strstr (mangled, "__tm__"))
216437c53322Sespie           || (*anchor = strstr (mangled, "__ps__"))
216537c53322Sespie           || (*anchor = strstr (mangled, "__pt__")))
216600bf4279Sespie         {
216700bf4279Sespie           int len;
216800bf4279Sespie           *args = *anchor + 6;
216900bf4279Sespie           len = consume_count (args);
217000bf4279Sespie 	  if (len == -1)
217100bf4279Sespie 	    return 0;
217200bf4279Sespie           if (*args + len == mangled + n && **args == '_')
217300bf4279Sespie             {
217400bf4279Sespie               ++*args;
217500bf4279Sespie               return 1;
217600bf4279Sespie             }
217700bf4279Sespie         }
217837c53322Sespie       else if ((*anchor = strstr (mangled, "__S")))
217900bf4279Sespie         {
218000bf4279Sespie  	  int len;
218100bf4279Sespie  	  *args = *anchor + 3;
218200bf4279Sespie  	  len = consume_count (args);
218300bf4279Sespie 	  if (len == -1)
218400bf4279Sespie 	    return 0;
218500bf4279Sespie  	  if (*args + len == mangled + n && **args == '_')
218600bf4279Sespie             {
218700bf4279Sespie               ++*args;
218800bf4279Sespie  	      return 1;
218900bf4279Sespie             }
219000bf4279Sespie         }
219100bf4279Sespie     }
219200bf4279Sespie 
219300bf4279Sespie   return 0;
219400bf4279Sespie }
219500bf4279Sespie 
219600bf4279Sespie static void
demangle_arm_hp_template(struct work_stuff * work,const char ** mangled,int n,string * declp)2197*150b7e42Smiod demangle_arm_hp_template (struct work_stuff *work, const char **mangled,
2198*150b7e42Smiod                           int n, string *declp)
219900bf4279Sespie {
220000bf4279Sespie   const char *p;
220100bf4279Sespie   const char *args;
220200bf4279Sespie   const char *e = *mangled + n;
220300bf4279Sespie   string arg;
220400bf4279Sespie 
220500bf4279Sespie   /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
220600bf4279Sespie      template args */
220700bf4279Sespie   if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
220800bf4279Sespie     {
220900bf4279Sespie       char *start_spec_args = NULL;
2210*150b7e42Smiod       int hold_options;
221100bf4279Sespie 
221200bf4279Sespie       /* First check for and omit template specialization pseudo-arguments,
221300bf4279Sespie          such as in "Spec<#1,#1.*>" */
221400bf4279Sespie       start_spec_args = strchr (*mangled, '<');
221500bf4279Sespie       if (start_spec_args && (start_spec_args - *mangled < n))
221600bf4279Sespie         string_appendn (declp, *mangled, start_spec_args - *mangled);
221700bf4279Sespie       else
221800bf4279Sespie         string_appendn (declp, *mangled, n);
221900bf4279Sespie       (*mangled) += n + 1;
222000bf4279Sespie       string_init (&arg);
222100bf4279Sespie       if (work->temp_start == -1) /* non-recursive call */
222200bf4279Sespie         work->temp_start = declp->p - declp->b;
2223*150b7e42Smiod 
2224*150b7e42Smiod       /* We want to unconditionally demangle parameter types in
2225*150b7e42Smiod 	 template parameters.  */
2226*150b7e42Smiod       hold_options = work->options;
2227*150b7e42Smiod       work->options |= DMGL_PARAMS;
2228*150b7e42Smiod 
222900bf4279Sespie       string_append (declp, "<");
223000bf4279Sespie       while (1)
223100bf4279Sespie         {
2232707f648cSespie           string_delete (&arg);
223300bf4279Sespie           switch (**mangled)
223400bf4279Sespie             {
223500bf4279Sespie               case 'T':
223600bf4279Sespie                 /* 'T' signals a type parameter */
223700bf4279Sespie                 (*mangled)++;
223800bf4279Sespie                 if (!do_type (work, mangled, &arg))
223900bf4279Sespie                   goto hpacc_template_args_done;
224000bf4279Sespie                 break;
224100bf4279Sespie 
224200bf4279Sespie               case 'U':
224300bf4279Sespie               case 'S':
224400bf4279Sespie                 /* 'U' or 'S' signals an integral value */
224500bf4279Sespie                 if (!do_hpacc_template_const_value (work, mangled, &arg))
224600bf4279Sespie                   goto hpacc_template_args_done;
224700bf4279Sespie                 break;
224800bf4279Sespie 
224900bf4279Sespie               case 'A':
225000bf4279Sespie                 /* 'A' signals a named constant expression (literal) */
225100bf4279Sespie                 if (!do_hpacc_template_literal (work, mangled, &arg))
225200bf4279Sespie                   goto hpacc_template_args_done;
225300bf4279Sespie                 break;
225400bf4279Sespie 
225500bf4279Sespie               default:
225600bf4279Sespie                 /* Today, 1997-09-03, we have only the above types
225700bf4279Sespie                    of template parameters */
225800bf4279Sespie                 /* FIXME: maybe this should fail and return null */
225900bf4279Sespie                 goto hpacc_template_args_done;
226000bf4279Sespie             }
226100bf4279Sespie           string_appends (declp, &arg);
226200bf4279Sespie          /* Check if we're at the end of template args.
226300bf4279Sespie              0 if at end of static member of template class,
226400bf4279Sespie              _ if done with template args for a function */
226500bf4279Sespie           if ((**mangled == '\000') || (**mangled == '_'))
226600bf4279Sespie             break;
226700bf4279Sespie           else
226800bf4279Sespie             string_append (declp, ",");
226900bf4279Sespie         }
227000bf4279Sespie     hpacc_template_args_done:
227100bf4279Sespie       string_append (declp, ">");
227200bf4279Sespie       string_delete (&arg);
227300bf4279Sespie       if (**mangled == '_')
227400bf4279Sespie         (*mangled)++;
2275*150b7e42Smiod       work->options = hold_options;
227600bf4279Sespie       return;
227700bf4279Sespie     }
227800bf4279Sespie   /* ARM template? (Also handles HP cfront extensions) */
227900bf4279Sespie   else if (arm_pt (work, *mangled, n, &p, &args))
228000bf4279Sespie     {
2281*150b7e42Smiod       int hold_options;
228200bf4279Sespie       string type_str;
228300bf4279Sespie 
228400bf4279Sespie       string_init (&arg);
228500bf4279Sespie       string_appendn (declp, *mangled, p - *mangled);
228600bf4279Sespie       if (work->temp_start == -1)  /* non-recursive call */
228700bf4279Sespie 	work->temp_start = declp->p - declp->b;
2288*150b7e42Smiod 
2289*150b7e42Smiod       /* We want to unconditionally demangle parameter types in
2290*150b7e42Smiod 	 template parameters.  */
2291*150b7e42Smiod       hold_options = work->options;
2292*150b7e42Smiod       work->options |= DMGL_PARAMS;
2293*150b7e42Smiod 
229400bf4279Sespie       string_append (declp, "<");
229500bf4279Sespie       /* should do error checking here */
229600bf4279Sespie       while (args < e) {
2297707f648cSespie 	string_delete (&arg);
229800bf4279Sespie 
229900bf4279Sespie 	/* Check for type or literal here */
230000bf4279Sespie 	switch (*args)
230100bf4279Sespie 	  {
230200bf4279Sespie 	    /* HP cfront extensions to ARM for template args */
230300bf4279Sespie 	    /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
230400bf4279Sespie 	    /* FIXME: We handle only numeric literals for HP cfront */
230500bf4279Sespie           case 'X':
230600bf4279Sespie             /* A typed constant value follows */
230700bf4279Sespie             args++;
230800bf4279Sespie             if (!do_type (work, &args, &type_str))
230900bf4279Sespie 	      goto cfront_template_args_done;
231000bf4279Sespie             string_append (&arg, "(");
231100bf4279Sespie             string_appends (&arg, &type_str);
2312707f648cSespie             string_delete (&type_str);
231300bf4279Sespie             string_append (&arg, ")");
231400bf4279Sespie             if (*args != 'L')
231500bf4279Sespie               goto cfront_template_args_done;
231600bf4279Sespie             args++;
231700bf4279Sespie             /* Now snarf a literal value following 'L' */
231800bf4279Sespie             if (!snarf_numeric_literal (&args, &arg))
231900bf4279Sespie 	      goto cfront_template_args_done;
232000bf4279Sespie             break;
232100bf4279Sespie 
232200bf4279Sespie           case 'L':
232300bf4279Sespie             /* Snarf a literal following 'L' */
232400bf4279Sespie             args++;
232500bf4279Sespie             if (!snarf_numeric_literal (&args, &arg))
232600bf4279Sespie 	      goto cfront_template_args_done;
232700bf4279Sespie             break;
232800bf4279Sespie           default:
232900bf4279Sespie             /* Not handling other HP cfront stuff */
233037c53322Sespie             {
233137c53322Sespie               const char* old_args = args;
233200bf4279Sespie               if (!do_type (work, &args, &arg))
233300bf4279Sespie                 goto cfront_template_args_done;
233437c53322Sespie 
233537c53322Sespie               /* Fail if we didn't make any progress: prevent infinite loop. */
233637c53322Sespie               if (args == old_args)
2337*150b7e42Smiod 		{
2338*150b7e42Smiod 		  work->options = hold_options;
233937c53322Sespie 		  return;
234037c53322Sespie 		}
234100bf4279Sespie             }
2342*150b7e42Smiod 	  }
234300bf4279Sespie 	string_appends (declp, &arg);
234400bf4279Sespie 	string_append (declp, ",");
234500bf4279Sespie       }
234600bf4279Sespie     cfront_template_args_done:
234700bf4279Sespie       string_delete (&arg);
234800bf4279Sespie       if (args >= e)
234900bf4279Sespie 	--declp->p; /* remove extra comma */
235000bf4279Sespie       string_append (declp, ">");
2351*150b7e42Smiod       work->options = hold_options;
235200bf4279Sespie     }
235300bf4279Sespie   else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
235400bf4279Sespie 	   && (*mangled)[9] == 'N'
235500bf4279Sespie 	   && (*mangled)[8] == (*mangled)[10]
235600bf4279Sespie 	   && strchr (cplus_markers, (*mangled)[8]))
235700bf4279Sespie     {
235800bf4279Sespie       /* A member of the anonymous namespace.  */
235900bf4279Sespie       string_append (declp, "{anonymous}");
236000bf4279Sespie     }
236100bf4279Sespie   else
236200bf4279Sespie     {
236300bf4279Sespie       if (work->temp_start == -1) /* non-recursive call only */
236400bf4279Sespie 	work->temp_start = 0;     /* disable in recursive calls */
236500bf4279Sespie       string_appendn (declp, *mangled, n);
236600bf4279Sespie     }
236700bf4279Sespie   *mangled += n;
236800bf4279Sespie }
236900bf4279Sespie 
237000bf4279Sespie /* Extract a class name, possibly a template with arguments, from the
237100bf4279Sespie    mangled string; qualifiers, local class indicators, etc. have
237200bf4279Sespie    already been dealt with */
237300bf4279Sespie 
237400bf4279Sespie static int
demangle_class_name(struct work_stuff * work,const char ** mangled,string * declp)2375*150b7e42Smiod demangle_class_name (struct work_stuff *work, const char **mangled,
2376*150b7e42Smiod                      string *declp)
237700bf4279Sespie {
237800bf4279Sespie   int n;
237900bf4279Sespie   int success = 0;
238000bf4279Sespie 
238100bf4279Sespie   n = consume_count (mangled);
238200bf4279Sespie   if (n == -1)
238300bf4279Sespie     return 0;
238400bf4279Sespie   if ((int) strlen (*mangled) >= n)
238500bf4279Sespie     {
238600bf4279Sespie       demangle_arm_hp_template (work, mangled, n, declp);
238700bf4279Sespie       success = 1;
238800bf4279Sespie     }
238900bf4279Sespie 
239000bf4279Sespie   return (success);
239100bf4279Sespie }
239200bf4279Sespie 
239300bf4279Sespie /*
239400bf4279Sespie 
239500bf4279Sespie LOCAL FUNCTION
239600bf4279Sespie 
239700bf4279Sespie 	demangle_class -- demangle a mangled class sequence
239800bf4279Sespie 
239900bf4279Sespie SYNOPSIS
240000bf4279Sespie 
240100bf4279Sespie 	static int
240200bf4279Sespie 	demangle_class (struct work_stuff *work, const char **mangled,
240300bf4279Sespie 			strint *declp)
240400bf4279Sespie 
240500bf4279Sespie DESCRIPTION
240600bf4279Sespie 
240700bf4279Sespie 	DECLP points to the buffer into which demangling is being done.
240800bf4279Sespie 
240900bf4279Sespie 	*MANGLED points to the current token to be demangled.  On input,
241000bf4279Sespie 	it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
241100bf4279Sespie 	On exit, it points to the next token after the mangled class on
241200bf4279Sespie 	success, or the first unconsumed token on failure.
241300bf4279Sespie 
241400bf4279Sespie 	If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
241500bf4279Sespie 	we are demangling a constructor or destructor.  In this case
241600bf4279Sespie 	we prepend "class::class" or "class::~class" to DECLP.
241700bf4279Sespie 
241800bf4279Sespie 	Otherwise, we prepend "class::" to the current DECLP.
241900bf4279Sespie 
242000bf4279Sespie 	Reset the constructor/destructor flags once they have been
242100bf4279Sespie 	"consumed".  This allows demangle_class to be called later during
242200bf4279Sespie 	the same demangling, to do normal class demangling.
242300bf4279Sespie 
242400bf4279Sespie 	Returns 1 if demangling is successful, 0 otherwise.
242500bf4279Sespie 
242600bf4279Sespie */
242700bf4279Sespie 
242800bf4279Sespie static int
demangle_class(struct work_stuff * work,const char ** mangled,string * declp)2429*150b7e42Smiod demangle_class (struct work_stuff *work, const char **mangled, string *declp)
243000bf4279Sespie {
243100bf4279Sespie   int success = 0;
243200bf4279Sespie   int btype;
243300bf4279Sespie   string class_name;
243400bf4279Sespie   char *save_class_name_end = 0;
243500bf4279Sespie 
243600bf4279Sespie   string_init (&class_name);
243700bf4279Sespie   btype = register_Btype (work);
243800bf4279Sespie   if (demangle_class_name (work, mangled, &class_name))
243900bf4279Sespie     {
244000bf4279Sespie       save_class_name_end = class_name.p;
244100bf4279Sespie       if ((work->constructor & 1) || (work->destructor & 1))
244200bf4279Sespie 	{
244300bf4279Sespie           /* adjust so we don't include template args */
244400bf4279Sespie           if (work->temp_start && (work->temp_start != -1))
244500bf4279Sespie             {
244600bf4279Sespie               class_name.p = class_name.b + work->temp_start;
244700bf4279Sespie             }
244800bf4279Sespie 	  string_prepends (declp, &class_name);
244900bf4279Sespie 	  if (work -> destructor & 1)
245000bf4279Sespie 	    {
245100bf4279Sespie 	      string_prepend (declp, "~");
245200bf4279Sespie               work -> destructor -= 1;
245300bf4279Sespie 	    }
245400bf4279Sespie 	  else
245500bf4279Sespie 	    {
245600bf4279Sespie 	      work -> constructor -= 1;
245700bf4279Sespie 	    }
245800bf4279Sespie 	}
245900bf4279Sespie       class_name.p = save_class_name_end;
246000bf4279Sespie       remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
246100bf4279Sespie       remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
246200bf4279Sespie       string_prepend (declp, SCOPE_STRING (work));
246300bf4279Sespie       string_prepends (declp, &class_name);
246400bf4279Sespie       success = 1;
246500bf4279Sespie     }
246600bf4279Sespie   string_delete (&class_name);
246700bf4279Sespie   return (success);
246800bf4279Sespie }
246900bf4279Sespie 
247037c53322Sespie 
247137c53322Sespie /* Called when there's a "__" in the mangled name, with `scan' pointing to
247237c53322Sespie    the rightmost guess.
247337c53322Sespie 
247437c53322Sespie    Find the correct "__"-sequence where the function name ends and the
247537c53322Sespie    signature starts, which is ambiguous with GNU mangling.
247637c53322Sespie    Call demangle_signature here, so we can make sure we found the right
247737c53322Sespie    one; *mangled will be consumed so caller will not make further calls to
247837c53322Sespie    demangle_signature.  */
247937c53322Sespie 
248037c53322Sespie static int
iterate_demangle_function(struct work_stuff * work,const char ** mangled,string * declp,const char * scan)2481*150b7e42Smiod iterate_demangle_function (struct work_stuff *work, const char **mangled,
2482*150b7e42Smiod                            string *declp, const char *scan)
248337c53322Sespie {
248437c53322Sespie   const char *mangle_init = *mangled;
248537c53322Sespie   int success = 0;
248637c53322Sespie   string decl_init;
248737c53322Sespie   struct work_stuff work_init;
248837c53322Sespie 
248937c53322Sespie   if (*(scan + 2) == '\0')
249037c53322Sespie     return 0;
249137c53322Sespie 
249237c53322Sespie   /* Do not iterate for some demangling modes, or if there's only one
249337c53322Sespie      "__"-sequence.  This is the normal case.  */
249437c53322Sespie   if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
249537c53322Sespie       || strstr (scan + 2, "__") == NULL)
249637c53322Sespie     {
249737c53322Sespie       demangle_function_name (work, mangled, declp, scan);
249837c53322Sespie       return 1;
249937c53322Sespie     }
250037c53322Sespie 
250137c53322Sespie   /* Save state so we can restart if the guess at the correct "__" was
250237c53322Sespie      wrong.  */
250337c53322Sespie   string_init (&decl_init);
250437c53322Sespie   string_appends (&decl_init, declp);
250537c53322Sespie   memset (&work_init, 0, sizeof work_init);
250637c53322Sespie   work_stuff_copy_to_from (&work_init, work);
250737c53322Sespie 
250837c53322Sespie   /* Iterate over occurrences of __, allowing names and types to have a
250937c53322Sespie      "__" sequence in them.  We must start with the first (not the last)
251037c53322Sespie      occurrence, since "__" most often occur between independent mangled
251137c53322Sespie      parts, hence starting at the last occurence inside a signature
251237c53322Sespie      might get us a "successful" demangling of the signature.  */
251337c53322Sespie 
251437c53322Sespie   while (scan[2])
251537c53322Sespie     {
251637c53322Sespie       demangle_function_name (work, mangled, declp, scan);
251737c53322Sespie       success = demangle_signature (work, mangled, declp);
251837c53322Sespie       if (success)
251937c53322Sespie 	break;
252037c53322Sespie 
252137c53322Sespie       /* Reset demangle state for the next round.  */
252237c53322Sespie       *mangled = mangle_init;
252337c53322Sespie       string_clear (declp);
252437c53322Sespie       string_appends (declp, &decl_init);
252537c53322Sespie       work_stuff_copy_to_from (work, &work_init);
252637c53322Sespie 
252737c53322Sespie       /* Leave this underscore-sequence.  */
252837c53322Sespie       scan += 2;
252937c53322Sespie 
253037c53322Sespie       /* Scan for the next "__" sequence.  */
253137c53322Sespie       while (*scan && (scan[0] != '_' || scan[1] != '_'))
253237c53322Sespie 	scan++;
253337c53322Sespie 
253437c53322Sespie       /* Move to last "__" in this sequence.  */
253537c53322Sespie       while (*scan && *scan == '_')
253637c53322Sespie 	scan++;
253737c53322Sespie       scan -= 2;
253837c53322Sespie     }
253937c53322Sespie 
254037c53322Sespie   /* Delete saved state.  */
254137c53322Sespie   delete_work_stuff (&work_init);
254237c53322Sespie   string_delete (&decl_init);
254337c53322Sespie 
254437c53322Sespie   return success;
254537c53322Sespie }
254637c53322Sespie 
254700bf4279Sespie /*
254800bf4279Sespie 
254900bf4279Sespie LOCAL FUNCTION
255000bf4279Sespie 
255100bf4279Sespie 	demangle_prefix -- consume the mangled name prefix and find signature
255200bf4279Sespie 
255300bf4279Sespie SYNOPSIS
255400bf4279Sespie 
255500bf4279Sespie 	static int
255600bf4279Sespie 	demangle_prefix (struct work_stuff *work, const char **mangled,
255700bf4279Sespie 			 string *declp);
255800bf4279Sespie 
255900bf4279Sespie DESCRIPTION
256000bf4279Sespie 
256100bf4279Sespie 	Consume and demangle the prefix of the mangled name.
256237c53322Sespie 	While processing the function name root, arrange to call
256337c53322Sespie 	demangle_signature if the root is ambiguous.
256400bf4279Sespie 
256500bf4279Sespie 	DECLP points to the string buffer into which demangled output is
256600bf4279Sespie 	placed.  On entry, the buffer is empty.  On exit it contains
256700bf4279Sespie 	the root function name, the demangled operator name, or in some
256800bf4279Sespie 	special cases either nothing or the completely demangled result.
256900bf4279Sespie 
257000bf4279Sespie 	MANGLED points to the current pointer into the mangled name.  As each
257100bf4279Sespie 	token of the mangled name is consumed, it is updated.  Upon entry
257200bf4279Sespie 	the current mangled name pointer points to the first character of
257300bf4279Sespie 	the mangled name.  Upon exit, it should point to the first character
257400bf4279Sespie 	of the signature if demangling was successful, or to the first
257500bf4279Sespie 	unconsumed character if demangling of the prefix was unsuccessful.
257600bf4279Sespie 
257700bf4279Sespie 	Returns 1 on success, 0 otherwise.
257800bf4279Sespie  */
257900bf4279Sespie 
258000bf4279Sespie static int
demangle_prefix(struct work_stuff * work,const char ** mangled,string * declp)2581*150b7e42Smiod demangle_prefix (struct work_stuff *work, const char **mangled,
2582*150b7e42Smiod                  string *declp)
258300bf4279Sespie {
258400bf4279Sespie   int success = 1;
258500bf4279Sespie   const char *scan;
258600bf4279Sespie   int i;
258700bf4279Sespie 
258800bf4279Sespie   if (strlen(*mangled) > 6
258900bf4279Sespie       && (strncmp(*mangled, "_imp__", 6) == 0
259000bf4279Sespie           || strncmp(*mangled, "__imp_", 6) == 0))
259100bf4279Sespie     {
259200bf4279Sespie       /* it's a symbol imported from a PE dynamic library. Check for both
259300bf4279Sespie          new style prefix _imp__ and legacy __imp_ used by older versions
259400bf4279Sespie 	 of dlltool. */
259500bf4279Sespie       (*mangled) += 6;
259600bf4279Sespie       work->dllimported = 1;
259700bf4279Sespie     }
259800bf4279Sespie   else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
259900bf4279Sespie     {
260000bf4279Sespie       char *marker = strchr (cplus_markers, (*mangled)[8]);
260100bf4279Sespie       if (marker != NULL && *marker == (*mangled)[10])
260200bf4279Sespie 	{
260300bf4279Sespie 	  if ((*mangled)[9] == 'D')
260400bf4279Sespie 	    {
260500bf4279Sespie 	      /* it's a GNU global destructor to be executed at program exit */
260600bf4279Sespie 	      (*mangled) += 11;
260700bf4279Sespie 	      work->destructor = 2;
260800bf4279Sespie 	      if (gnu_special (work, mangled, declp))
260900bf4279Sespie 		return success;
261000bf4279Sespie 	    }
261100bf4279Sespie 	  else if ((*mangled)[9] == 'I')
261200bf4279Sespie 	    {
261300bf4279Sespie 	      /* it's a GNU global constructor to be executed at program init */
261400bf4279Sespie 	      (*mangled) += 11;
261500bf4279Sespie 	      work->constructor = 2;
261600bf4279Sespie 	      if (gnu_special (work, mangled, declp))
261700bf4279Sespie 		return success;
261800bf4279Sespie 	    }
261900bf4279Sespie 	}
262000bf4279Sespie     }
262100bf4279Sespie   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
262200bf4279Sespie     {
262300bf4279Sespie       /* it's a ARM global destructor to be executed at program exit */
262400bf4279Sespie       (*mangled) += 7;
262500bf4279Sespie       work->destructor = 2;
262600bf4279Sespie     }
262700bf4279Sespie   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
262800bf4279Sespie     {
262900bf4279Sespie       /* it's a ARM global constructor to be executed at program initial */
263000bf4279Sespie       (*mangled) += 7;
263100bf4279Sespie       work->constructor = 2;
263200bf4279Sespie     }
263300bf4279Sespie 
263400bf4279Sespie   /*  This block of code is a reduction in strength time optimization
263500bf4279Sespie       of:
263637c53322Sespie       scan = strstr (*mangled, "__"); */
263700bf4279Sespie 
263800bf4279Sespie   {
263900bf4279Sespie     scan = *mangled;
264000bf4279Sespie 
264100bf4279Sespie     do {
264200bf4279Sespie       scan = strchr (scan, '_');
264300bf4279Sespie     } while (scan != NULL && *++scan != '_');
264400bf4279Sespie 
264500bf4279Sespie     if (scan != NULL) --scan;
264600bf4279Sespie   }
264700bf4279Sespie 
264800bf4279Sespie   if (scan != NULL)
264900bf4279Sespie     {
265000bf4279Sespie       /* We found a sequence of two or more '_', ensure that we start at
265100bf4279Sespie 	 the last pair in the sequence.  */
265200bf4279Sespie       i = strspn (scan, "_");
265300bf4279Sespie       if (i > 2)
265400bf4279Sespie 	{
265500bf4279Sespie 	  scan += (i - 2);
265600bf4279Sespie 	}
265700bf4279Sespie     }
265800bf4279Sespie 
265900bf4279Sespie   if (scan == NULL)
266000bf4279Sespie     {
266100bf4279Sespie       success = 0;
266200bf4279Sespie     }
266300bf4279Sespie   else if (work -> static_type)
266400bf4279Sespie     {
266537c53322Sespie       if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
266600bf4279Sespie 	{
266700bf4279Sespie 	  success = 0;
266800bf4279Sespie 	}
266900bf4279Sespie     }
267000bf4279Sespie   else if ((scan == *mangled)
267137c53322Sespie 	   && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
267200bf4279Sespie 	       || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
267300bf4279Sespie     {
267400bf4279Sespie       /* The ARM says nothing about the mangling of local variables.
267500bf4279Sespie 	 But cfront mangles local variables by prepending __<nesting_level>
267600bf4279Sespie 	 to them. As an extension to ARM demangling we handle this case.  */
267700bf4279Sespie       if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
267837c53322Sespie 	  && ISDIGIT ((unsigned char)scan[2]))
267900bf4279Sespie 	{
268000bf4279Sespie 	  *mangled = scan + 2;
268100bf4279Sespie 	  consume_count (mangled);
268200bf4279Sespie 	  string_append (declp, *mangled);
268300bf4279Sespie 	  *mangled += strlen (*mangled);
268400bf4279Sespie 	  success = 1;
268500bf4279Sespie 	}
268600bf4279Sespie       else
268700bf4279Sespie 	{
268800bf4279Sespie 	  /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
268900bf4279Sespie 	     names like __Q2_3foo3bar for nested type names.  So don't accept
269000bf4279Sespie 	     this style of constructor for cfront demangling.  A GNU
269100bf4279Sespie 	     style member-template constructor starts with 'H'. */
269200bf4279Sespie 	  if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
269300bf4279Sespie 	    work -> constructor += 1;
269400bf4279Sespie 	  *mangled = scan + 2;
269500bf4279Sespie 	}
269600bf4279Sespie     }
269700bf4279Sespie   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
269800bf4279Sespie     {
269900bf4279Sespie       /* Cfront-style parameterized type.  Handled later as a signature. */
270000bf4279Sespie       success = 1;
270100bf4279Sespie 
270200bf4279Sespie       /* ARM template? */
270300bf4279Sespie       demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
270400bf4279Sespie     }
270500bf4279Sespie   else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
270600bf4279Sespie                               || (scan[2] == 'p' && scan[3] == 's')
270700bf4279Sespie                               || (scan[2] == 'p' && scan[3] == 't')))
270800bf4279Sespie     {
270900bf4279Sespie       /* EDG-style parameterized type.  Handled later as a signature. */
271000bf4279Sespie       success = 1;
271100bf4279Sespie 
271200bf4279Sespie       /* EDG template? */
271300bf4279Sespie       demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
271400bf4279Sespie     }
271537c53322Sespie   else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
271600bf4279Sespie 	   && (scan[2] != 't'))
271700bf4279Sespie     {
271800bf4279Sespie       /* Mangled name starts with "__".  Skip over any leading '_' characters,
271900bf4279Sespie 	 then find the next "__" that separates the prefix from the signature.
272000bf4279Sespie 	 */
272100bf4279Sespie       if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
272200bf4279Sespie 	  || (arm_special (mangled, declp) == 0))
272300bf4279Sespie 	{
272400bf4279Sespie 	  while (*scan == '_')
272500bf4279Sespie 	    {
272600bf4279Sespie 	      scan++;
272700bf4279Sespie 	    }
272837c53322Sespie 	  if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
272900bf4279Sespie 	    {
273000bf4279Sespie 	      /* No separator (I.E. "__not_mangled"), or empty signature
273100bf4279Sespie 		 (I.E. "__not_mangled_either__") */
273200bf4279Sespie 	      success = 0;
273300bf4279Sespie 	    }
273400bf4279Sespie 	  else
273537c53322Sespie 	    return iterate_demangle_function (work, mangled, declp, scan);
273600bf4279Sespie 	}
273700bf4279Sespie     }
273800bf4279Sespie   else if (*(scan + 2) != '\0')
273900bf4279Sespie     {
274000bf4279Sespie       /* Mangled name does not start with "__" but does have one somewhere
274100bf4279Sespie 	 in there with non empty stuff after it.  Looks like a global
274237c53322Sespie 	 function name.  Iterate over all "__":s until the right
274337c53322Sespie 	 one is found.  */
274437c53322Sespie       return iterate_demangle_function (work, mangled, declp, scan);
274500bf4279Sespie     }
274600bf4279Sespie   else
274700bf4279Sespie     {
274800bf4279Sespie       /* Doesn't look like a mangled name */
274900bf4279Sespie       success = 0;
275000bf4279Sespie     }
275100bf4279Sespie 
275200bf4279Sespie   if (!success && (work->constructor == 2 || work->destructor == 2))
275300bf4279Sespie     {
275400bf4279Sespie       string_append (declp, *mangled);
275500bf4279Sespie       *mangled += strlen (*mangled);
275600bf4279Sespie       success = 1;
275700bf4279Sespie     }
275800bf4279Sespie   return (success);
275900bf4279Sespie }
276000bf4279Sespie 
276100bf4279Sespie /*
276200bf4279Sespie 
276300bf4279Sespie LOCAL FUNCTION
276400bf4279Sespie 
276500bf4279Sespie 	gnu_special -- special handling of gnu mangled strings
276600bf4279Sespie 
276700bf4279Sespie SYNOPSIS
276800bf4279Sespie 
276900bf4279Sespie 	static int
277000bf4279Sespie 	gnu_special (struct work_stuff *work, const char **mangled,
277100bf4279Sespie 		     string *declp);
277200bf4279Sespie 
277300bf4279Sespie 
277400bf4279Sespie DESCRIPTION
277500bf4279Sespie 
277600bf4279Sespie 	Process some special GNU style mangling forms that don't fit
277700bf4279Sespie 	the normal pattern.  For example:
277800bf4279Sespie 
277900bf4279Sespie 		_$_3foo		(destructor for class foo)
278000bf4279Sespie 		_vt$foo		(foo virtual table)
278100bf4279Sespie 		_vt$foo$bar	(foo::bar virtual table)
278200bf4279Sespie 		__vt_foo	(foo virtual table, new style with thunks)
278300bf4279Sespie 		_3foo$varname	(static data member)
278400bf4279Sespie 		_Q22rs2tu$vw	(static data member)
278500bf4279Sespie 		__t6vector1Zii	(constructor with template)
278600bf4279Sespie 		__thunk_4__$_7ostream (virtual function thunk)
278700bf4279Sespie  */
278800bf4279Sespie 
278900bf4279Sespie static int
gnu_special(struct work_stuff * work,const char ** mangled,string * declp)2790*150b7e42Smiod gnu_special (struct work_stuff *work, const char **mangled, string *declp)
279100bf4279Sespie {
279200bf4279Sespie   int n;
279300bf4279Sespie   int success = 1;
279400bf4279Sespie   const char *p;
279500bf4279Sespie 
279600bf4279Sespie   if ((*mangled)[0] == '_'
279700bf4279Sespie       && strchr (cplus_markers, (*mangled)[1]) != NULL
279800bf4279Sespie       && (*mangled)[2] == '_')
279900bf4279Sespie     {
280000bf4279Sespie       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
280100bf4279Sespie       (*mangled) += 3;
280200bf4279Sespie       work -> destructor += 1;
280300bf4279Sespie     }
280400bf4279Sespie   else if ((*mangled)[0] == '_'
280500bf4279Sespie 	   && (((*mangled)[1] == '_'
280600bf4279Sespie 		&& (*mangled)[2] == 'v'
280700bf4279Sespie 		&& (*mangled)[3] == 't'
280800bf4279Sespie 		&& (*mangled)[4] == '_')
280900bf4279Sespie 	       || ((*mangled)[1] == 'v'
281000bf4279Sespie 		   && (*mangled)[2] == 't'
281100bf4279Sespie 		   && strchr (cplus_markers, (*mangled)[3]) != NULL)))
281200bf4279Sespie     {
281300bf4279Sespie       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
281400bf4279Sespie          and create the decl.  Note that we consume the entire mangled
281500bf4279Sespie 	 input string, which means that demangle_signature has no work
281600bf4279Sespie 	 to do.  */
281700bf4279Sespie       if ((*mangled)[2] == 'v')
281800bf4279Sespie 	(*mangled) += 5; /* New style, with thunks: "__vt_" */
281900bf4279Sespie       else
282000bf4279Sespie 	(*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
282100bf4279Sespie       while (**mangled != '\0')
282200bf4279Sespie 	{
282300bf4279Sespie 	  switch (**mangled)
282400bf4279Sespie 	    {
282500bf4279Sespie 	    case 'Q':
282600bf4279Sespie 	    case 'K':
282700bf4279Sespie 	      success = demangle_qualified (work, mangled, declp, 0, 1);
282800bf4279Sespie 	      break;
282900bf4279Sespie 	    case 't':
283000bf4279Sespie 	      success = demangle_template (work, mangled, declp, 0, 1,
283100bf4279Sespie 					   1);
283200bf4279Sespie 	      break;
283300bf4279Sespie 	    default:
283437c53322Sespie 	      if (ISDIGIT((unsigned char)*mangled[0]))
283500bf4279Sespie 		{
283600bf4279Sespie 		  n = consume_count(mangled);
283700bf4279Sespie 		  /* We may be seeing a too-large size, or else a
283800bf4279Sespie 		     ".<digits>" indicating a static local symbol.  In
283900bf4279Sespie 		     any case, declare victory and move on; *don't* try
284000bf4279Sespie 		     to use n to allocate.  */
284100bf4279Sespie 		  if (n > (int) strlen (*mangled))
284200bf4279Sespie 		    {
284300bf4279Sespie 		      success = 1;
284400bf4279Sespie 		      break;
284500bf4279Sespie 		    }
284600bf4279Sespie 		}
284700bf4279Sespie 	      else
284800bf4279Sespie 		{
284900bf4279Sespie 		  n = strcspn (*mangled, cplus_markers);
285000bf4279Sespie 		}
285100bf4279Sespie 	      string_appendn (declp, *mangled, n);
285200bf4279Sespie 	      (*mangled) += n;
285300bf4279Sespie 	    }
285400bf4279Sespie 
285500bf4279Sespie 	  p = strpbrk (*mangled, cplus_markers);
285600bf4279Sespie 	  if (success && ((p == NULL) || (p == *mangled)))
285700bf4279Sespie 	    {
285800bf4279Sespie 	      if (p != NULL)
285900bf4279Sespie 		{
286000bf4279Sespie 		  string_append (declp, SCOPE_STRING (work));
286100bf4279Sespie 		  (*mangled)++;
286200bf4279Sespie 		}
286300bf4279Sespie 	    }
286400bf4279Sespie 	  else
286500bf4279Sespie 	    {
286600bf4279Sespie 	      success = 0;
286700bf4279Sespie 	      break;
286800bf4279Sespie 	    }
286900bf4279Sespie 	}
287000bf4279Sespie       if (success)
287100bf4279Sespie 	string_append (declp, " virtual table");
287200bf4279Sespie     }
287300bf4279Sespie   else if ((*mangled)[0] == '_'
287400bf4279Sespie 	   && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
287500bf4279Sespie 	   && (p = strpbrk (*mangled, cplus_markers)) != NULL)
287600bf4279Sespie     {
287700bf4279Sespie       /* static data member, "_3foo$varname" for example */
287800bf4279Sespie       (*mangled)++;
287900bf4279Sespie       switch (**mangled)
288000bf4279Sespie 	{
288100bf4279Sespie 	case 'Q':
288200bf4279Sespie 	case 'K':
288300bf4279Sespie 	  success = demangle_qualified (work, mangled, declp, 0, 1);
288400bf4279Sespie 	  break;
288500bf4279Sespie 	case 't':
288600bf4279Sespie 	  success = demangle_template (work, mangled, declp, 0, 1, 1);
288700bf4279Sespie 	  break;
288800bf4279Sespie 	default:
288900bf4279Sespie 	  n = consume_count (mangled);
289037c53322Sespie 	  if (n < 0 || n > (long) strlen (*mangled))
289100bf4279Sespie 	    {
289200bf4279Sespie 	      success = 0;
289300bf4279Sespie 	      break;
289400bf4279Sespie 	    }
289537c53322Sespie 
289637c53322Sespie 	  if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
289737c53322Sespie 	      && (*mangled)[9] == 'N'
289837c53322Sespie 	      && (*mangled)[8] == (*mangled)[10]
289937c53322Sespie 	      && strchr (cplus_markers, (*mangled)[8]))
290037c53322Sespie 	    {
290137c53322Sespie 	      /* A member of the anonymous namespace.  There's information
290237c53322Sespie 		 about what identifier or filename it was keyed to, but
290337c53322Sespie 		 it's just there to make the mangled name unique; we just
290437c53322Sespie 		 step over it.  */
290537c53322Sespie 	      string_append (declp, "{anonymous}");
290637c53322Sespie 	      (*mangled) += n;
290737c53322Sespie 
290837c53322Sespie 	      /* Now p points to the marker before the N, so we need to
290937c53322Sespie 		 update it to the first marker after what we consumed.  */
291037c53322Sespie 	      p = strpbrk (*mangled, cplus_markers);
291137c53322Sespie 	      break;
291237c53322Sespie 	    }
291337c53322Sespie 
291400bf4279Sespie 	  string_appendn (declp, *mangled, n);
291500bf4279Sespie 	  (*mangled) += n;
291600bf4279Sespie 	}
291700bf4279Sespie       if (success && (p == *mangled))
291800bf4279Sespie 	{
291900bf4279Sespie 	  /* Consumed everything up to the cplus_marker, append the
292000bf4279Sespie 	     variable name.  */
292100bf4279Sespie 	  (*mangled)++;
292200bf4279Sespie 	  string_append (declp, SCOPE_STRING (work));
292300bf4279Sespie 	  n = strlen (*mangled);
292400bf4279Sespie 	  string_appendn (declp, *mangled, n);
292500bf4279Sespie 	  (*mangled) += n;
292600bf4279Sespie 	}
292700bf4279Sespie       else
292800bf4279Sespie 	{
292900bf4279Sespie 	  success = 0;
293000bf4279Sespie 	}
293100bf4279Sespie     }
293200bf4279Sespie   else if (strncmp (*mangled, "__thunk_", 8) == 0)
293300bf4279Sespie     {
293400bf4279Sespie       int delta;
293500bf4279Sespie 
293600bf4279Sespie       (*mangled) += 8;
293700bf4279Sespie       delta = consume_count (mangled);
293800bf4279Sespie       if (delta == -1)
293900bf4279Sespie 	success = 0;
294000bf4279Sespie       else
294100bf4279Sespie 	{
294200bf4279Sespie 	  char *method = internal_cplus_demangle (work, ++*mangled);
294300bf4279Sespie 
294400bf4279Sespie 	  if (method)
294500bf4279Sespie 	    {
294600bf4279Sespie 	      char buf[50];
2947*150b7e42Smiod 	      snprintf (buf, sizeof buf, "virtual function thunk (delta:%d) for ", -delta);
294800bf4279Sespie 	      string_append (declp, buf);
294900bf4279Sespie 	      string_append (declp, method);
295000bf4279Sespie 	      free (method);
295100bf4279Sespie 	      n = strlen (*mangled);
295200bf4279Sespie 	      (*mangled) += n;
295300bf4279Sespie 	    }
295400bf4279Sespie 	  else
295500bf4279Sespie 	    {
295600bf4279Sespie 	      success = 0;
295700bf4279Sespie 	    }
295800bf4279Sespie 	}
295900bf4279Sespie     }
296000bf4279Sespie   else if (strncmp (*mangled, "__t", 3) == 0
296100bf4279Sespie 	   && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
296200bf4279Sespie     {
296300bf4279Sespie       p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
296400bf4279Sespie       (*mangled) += 4;
296500bf4279Sespie       switch (**mangled)
296600bf4279Sespie 	{
296700bf4279Sespie 	case 'Q':
296800bf4279Sespie 	case 'K':
296900bf4279Sespie 	  success = demangle_qualified (work, mangled, declp, 0, 1);
297000bf4279Sespie 	  break;
297100bf4279Sespie 	case 't':
297200bf4279Sespie 	  success = demangle_template (work, mangled, declp, 0, 1, 1);
297300bf4279Sespie 	  break;
297400bf4279Sespie 	default:
297537c53322Sespie 	  success = do_type (work, mangled, declp);
297600bf4279Sespie 	  break;
297700bf4279Sespie 	}
297800bf4279Sespie       if (success && **mangled != '\0')
297900bf4279Sespie 	success = 0;
298000bf4279Sespie       if (success)
298100bf4279Sespie 	string_append (declp, p);
298200bf4279Sespie     }
298300bf4279Sespie   else
298400bf4279Sespie     {
298500bf4279Sespie       success = 0;
298600bf4279Sespie     }
298700bf4279Sespie   return (success);
298800bf4279Sespie }
298900bf4279Sespie 
299000bf4279Sespie static void
recursively_demangle(struct work_stuff * work,const char ** mangled,string * result,int namelength)2991*150b7e42Smiod recursively_demangle(struct work_stuff *work, const char **mangled,
2992*150b7e42Smiod                      string *result, int namelength)
299300bf4279Sespie {
299400bf4279Sespie   char * recurse = (char *)NULL;
299500bf4279Sespie   char * recurse_dem = (char *)NULL;
299600bf4279Sespie 
2997*150b7e42Smiod   recurse = XNEWVEC (char, namelength + 1);
299800bf4279Sespie   memcpy (recurse, *mangled, namelength);
299900bf4279Sespie   recurse[namelength] = '\000';
300000bf4279Sespie 
300100bf4279Sespie   recurse_dem = cplus_demangle (recurse, work->options);
300200bf4279Sespie 
300300bf4279Sespie   if (recurse_dem)
300400bf4279Sespie     {
300500bf4279Sespie       string_append (result, recurse_dem);
300600bf4279Sespie       free (recurse_dem);
300700bf4279Sespie     }
300800bf4279Sespie   else
300900bf4279Sespie     {
301000bf4279Sespie       string_appendn (result, *mangled, namelength);
301100bf4279Sespie     }
301200bf4279Sespie   free (recurse);
301300bf4279Sespie   *mangled += namelength;
301400bf4279Sespie }
301500bf4279Sespie 
301600bf4279Sespie /*
301700bf4279Sespie 
301800bf4279Sespie LOCAL FUNCTION
301900bf4279Sespie 
302000bf4279Sespie 	arm_special -- special handling of ARM/lucid mangled strings
302100bf4279Sespie 
302200bf4279Sespie SYNOPSIS
302300bf4279Sespie 
302400bf4279Sespie 	static int
302500bf4279Sespie 	arm_special (const char **mangled,
302600bf4279Sespie 		     string *declp);
302700bf4279Sespie 
302800bf4279Sespie 
302900bf4279Sespie DESCRIPTION
303000bf4279Sespie 
303100bf4279Sespie 	Process some special ARM style mangling forms that don't fit
303200bf4279Sespie 	the normal pattern.  For example:
303300bf4279Sespie 
303400bf4279Sespie 		__vtbl__3foo		(foo virtual table)
303500bf4279Sespie 		__vtbl__3foo__3bar	(bar::foo virtual table)
303600bf4279Sespie 
303700bf4279Sespie  */
303800bf4279Sespie 
303900bf4279Sespie static int
arm_special(const char ** mangled,string * declp)3040*150b7e42Smiod arm_special (const char **mangled, string *declp)
304100bf4279Sespie {
304200bf4279Sespie   int n;
304300bf4279Sespie   int success = 1;
304400bf4279Sespie   const char *scan;
304500bf4279Sespie 
304600bf4279Sespie   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
304700bf4279Sespie     {
304800bf4279Sespie       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
304900bf4279Sespie          and create the decl.  Note that we consume the entire mangled
305000bf4279Sespie 	 input string, which means that demangle_signature has no work
305100bf4279Sespie 	 to do.  */
305200bf4279Sespie       scan = *mangled + ARM_VTABLE_STRLEN;
305300bf4279Sespie       while (*scan != '\0')        /* first check it can be demangled */
305400bf4279Sespie         {
305500bf4279Sespie           n = consume_count (&scan);
305600bf4279Sespie           if (n == -1)
305700bf4279Sespie 	    {
305800bf4279Sespie 	      return (0);           /* no good */
305900bf4279Sespie 	    }
306000bf4279Sespie           scan += n;
306100bf4279Sespie           if (scan[0] == '_' && scan[1] == '_')
306200bf4279Sespie 	    {
306300bf4279Sespie 	      scan += 2;
306400bf4279Sespie 	    }
306500bf4279Sespie         }
306600bf4279Sespie       (*mangled) += ARM_VTABLE_STRLEN;
306700bf4279Sespie       while (**mangled != '\0')
306800bf4279Sespie 	{
306900bf4279Sespie 	  n = consume_count (mangled);
307000bf4279Sespie           if (n == -1
307137c53322Sespie 	      || n > (long) strlen (*mangled))
307200bf4279Sespie 	    return 0;
307300bf4279Sespie 	  string_prependn (declp, *mangled, n);
307400bf4279Sespie 	  (*mangled) += n;
307500bf4279Sespie 	  if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
307600bf4279Sespie 	    {
307700bf4279Sespie 	      string_prepend (declp, "::");
307800bf4279Sespie 	      (*mangled) += 2;
307900bf4279Sespie 	    }
308000bf4279Sespie 	}
308100bf4279Sespie       string_append (declp, " virtual table");
308200bf4279Sespie     }
308300bf4279Sespie   else
308400bf4279Sespie     {
308500bf4279Sespie       success = 0;
308600bf4279Sespie     }
308700bf4279Sespie   return (success);
308800bf4279Sespie }
308900bf4279Sespie 
309000bf4279Sespie /*
309100bf4279Sespie 
309200bf4279Sespie LOCAL FUNCTION
309300bf4279Sespie 
309400bf4279Sespie 	demangle_qualified -- demangle 'Q' qualified name strings
309500bf4279Sespie 
309600bf4279Sespie SYNOPSIS
309700bf4279Sespie 
309800bf4279Sespie 	static int
309900bf4279Sespie 	demangle_qualified (struct work_stuff *, const char *mangled,
310000bf4279Sespie 			    string *result, int isfuncname, int append);
310100bf4279Sespie 
310200bf4279Sespie DESCRIPTION
310300bf4279Sespie 
310400bf4279Sespie 	Demangle a qualified name, such as "Q25Outer5Inner" which is
310500bf4279Sespie 	the mangled form of "Outer::Inner".  The demangled output is
310600bf4279Sespie 	prepended or appended to the result string according to the
310700bf4279Sespie 	state of the append flag.
310800bf4279Sespie 
310900bf4279Sespie 	If isfuncname is nonzero, then the qualified name we are building
311000bf4279Sespie 	is going to be used as a member function name, so if it is a
311100bf4279Sespie 	constructor or destructor function, append an appropriate
311200bf4279Sespie 	constructor or destructor name.  I.E. for the above example,
311300bf4279Sespie 	the result for use as a constructor is "Outer::Inner::Inner"
311400bf4279Sespie 	and the result for use as a destructor is "Outer::Inner::~Inner".
311500bf4279Sespie 
311600bf4279Sespie BUGS
311700bf4279Sespie 
311800bf4279Sespie 	Numeric conversion is ASCII dependent (FIXME).
311900bf4279Sespie 
312000bf4279Sespie  */
312100bf4279Sespie 
312200bf4279Sespie static int
demangle_qualified(struct work_stuff * work,const char ** mangled,string * result,int isfuncname,int append)3123*150b7e42Smiod demangle_qualified (struct work_stuff *work, const char **mangled,
3124*150b7e42Smiod                     string *result, int isfuncname, int append)
312500bf4279Sespie {
312600bf4279Sespie   int qualifiers = 0;
312700bf4279Sespie   int success = 1;
312800bf4279Sespie   char num[2];
312900bf4279Sespie   string temp;
313000bf4279Sespie   string last_name;
313100bf4279Sespie   int bindex = register_Btype (work);
313200bf4279Sespie 
313300bf4279Sespie   /* We only make use of ISFUNCNAME if the entity is a constructor or
313400bf4279Sespie      destructor.  */
313500bf4279Sespie   isfuncname = (isfuncname
313600bf4279Sespie 		&& ((work->constructor & 1) || (work->destructor & 1)));
313700bf4279Sespie 
313800bf4279Sespie   string_init (&temp);
313900bf4279Sespie   string_init (&last_name);
314000bf4279Sespie 
314100bf4279Sespie   if ((*mangled)[0] == 'K')
314200bf4279Sespie     {
314300bf4279Sespie     /* Squangling qualified name reuse */
314400bf4279Sespie       int idx;
314500bf4279Sespie       (*mangled)++;
314600bf4279Sespie       idx = consume_count_with_underscores (mangled);
314700bf4279Sespie       if (idx == -1 || idx >= work -> numk)
314800bf4279Sespie         success = 0;
314900bf4279Sespie       else
315000bf4279Sespie         string_append (&temp, work -> ktypevec[idx]);
315100bf4279Sespie     }
315200bf4279Sespie   else
315300bf4279Sespie     switch ((*mangled)[1])
315400bf4279Sespie     {
315500bf4279Sespie     case '_':
315600bf4279Sespie       /* GNU mangled name with more than 9 classes.  The count is preceded
315700bf4279Sespie 	 by an underscore (to distinguish it from the <= 9 case) and followed
315800bf4279Sespie 	 by an underscore.  */
315937c53322Sespie       (*mangled)++;
316037c53322Sespie       qualifiers = consume_count_with_underscores (mangled);
316137c53322Sespie       if (qualifiers == -1)
316200bf4279Sespie 	success = 0;
316300bf4279Sespie       break;
316400bf4279Sespie 
316500bf4279Sespie     case '1':
316600bf4279Sespie     case '2':
316700bf4279Sespie     case '3':
316800bf4279Sespie     case '4':
316900bf4279Sespie     case '5':
317000bf4279Sespie     case '6':
317100bf4279Sespie     case '7':
317200bf4279Sespie     case '8':
317300bf4279Sespie     case '9':
317400bf4279Sespie       /* The count is in a single digit.  */
317500bf4279Sespie       num[0] = (*mangled)[1];
317600bf4279Sespie       num[1] = '\0';
317700bf4279Sespie       qualifiers = atoi (num);
317800bf4279Sespie 
317900bf4279Sespie       /* If there is an underscore after the digit, skip it.  This is
318000bf4279Sespie 	 said to be for ARM-qualified names, but the ARM makes no
318100bf4279Sespie 	 mention of such an underscore.  Perhaps cfront uses one.  */
318200bf4279Sespie       if ((*mangled)[2] == '_')
318300bf4279Sespie 	{
318400bf4279Sespie 	  (*mangled)++;
318500bf4279Sespie 	}
318600bf4279Sespie       (*mangled) += 2;
318700bf4279Sespie       break;
318800bf4279Sespie 
318900bf4279Sespie     case '0':
319000bf4279Sespie     default:
319100bf4279Sespie       success = 0;
319200bf4279Sespie     }
319300bf4279Sespie 
319400bf4279Sespie   if (!success)
319500bf4279Sespie     return success;
319600bf4279Sespie 
319700bf4279Sespie   /* Pick off the names and collect them in the temp buffer in the order
319800bf4279Sespie      in which they are found, separated by '::'.  */
319900bf4279Sespie 
320000bf4279Sespie   while (qualifiers-- > 0)
320100bf4279Sespie     {
320200bf4279Sespie       int remember_K = 1;
320300bf4279Sespie       string_clear (&last_name);
320400bf4279Sespie 
320500bf4279Sespie       if (*mangled[0] == '_')
320600bf4279Sespie 	(*mangled)++;
320700bf4279Sespie 
320800bf4279Sespie       if (*mangled[0] == 't')
320900bf4279Sespie 	{
321000bf4279Sespie 	  /* Here we always append to TEMP since we will want to use
321100bf4279Sespie 	     the template name without the template parameters as a
321200bf4279Sespie 	     constructor or destructor name.  The appropriate
321300bf4279Sespie 	     (parameter-less) value is returned by demangle_template
321400bf4279Sespie 	     in LAST_NAME.  We do not remember the template type here,
321500bf4279Sespie 	     in order to match the G++ mangling algorithm.  */
321600bf4279Sespie 	  success = demangle_template(work, mangled, &temp,
321700bf4279Sespie 				      &last_name, 1, 0);
321800bf4279Sespie 	  if (!success)
321900bf4279Sespie 	    break;
322000bf4279Sespie 	}
322100bf4279Sespie       else if (*mangled[0] == 'K')
322200bf4279Sespie 	{
322300bf4279Sespie           int idx;
322400bf4279Sespie           (*mangled)++;
322500bf4279Sespie           idx = consume_count_with_underscores (mangled);
322600bf4279Sespie           if (idx == -1 || idx >= work->numk)
322700bf4279Sespie             success = 0;
322800bf4279Sespie           else
322900bf4279Sespie             string_append (&temp, work->ktypevec[idx]);
323000bf4279Sespie           remember_K = 0;
323100bf4279Sespie 
323200bf4279Sespie 	  if (!success) break;
323300bf4279Sespie 	}
323400bf4279Sespie       else
323500bf4279Sespie 	{
323600bf4279Sespie 	  if (EDG_DEMANGLING)
323700bf4279Sespie             {
323800bf4279Sespie 	      int namelength;
323900bf4279Sespie  	      /* Now recursively demangle the qualifier
324000bf4279Sespie  	       * This is necessary to deal with templates in
324100bf4279Sespie  	       * mangling styles like EDG */
324200bf4279Sespie 	      namelength = consume_count (mangled);
324300bf4279Sespie 	      if (namelength == -1)
324400bf4279Sespie 		{
324500bf4279Sespie 		  success = 0;
324600bf4279Sespie 		  break;
324700bf4279Sespie 		}
324800bf4279Sespie  	      recursively_demangle(work, mangled, &temp, namelength);
324900bf4279Sespie             }
325000bf4279Sespie           else
325100bf4279Sespie             {
3252707f648cSespie               string_delete (&last_name);
325300bf4279Sespie               success = do_type (work, mangled, &last_name);
325400bf4279Sespie               if (!success)
325500bf4279Sespie                 break;
325600bf4279Sespie               string_appends (&temp, &last_name);
325700bf4279Sespie             }
325800bf4279Sespie 	}
325900bf4279Sespie 
326000bf4279Sespie       if (remember_K)
326100bf4279Sespie 	remember_Ktype (work, temp.b, LEN_STRING (&temp));
326200bf4279Sespie 
326300bf4279Sespie       if (qualifiers > 0)
326400bf4279Sespie 	string_append (&temp, SCOPE_STRING (work));
326500bf4279Sespie     }
326600bf4279Sespie 
326700bf4279Sespie   remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
326800bf4279Sespie 
326900bf4279Sespie   /* If we are using the result as a function name, we need to append
327000bf4279Sespie      the appropriate '::' separated constructor or destructor name.
327100bf4279Sespie      We do this here because this is the most convenient place, where
327200bf4279Sespie      we already have a pointer to the name and the length of the name.  */
327300bf4279Sespie 
327400bf4279Sespie   if (isfuncname)
327500bf4279Sespie     {
327600bf4279Sespie       string_append (&temp, SCOPE_STRING (work));
327700bf4279Sespie       if (work -> destructor & 1)
327800bf4279Sespie 	string_append (&temp, "~");
327900bf4279Sespie       string_appends (&temp, &last_name);
328000bf4279Sespie     }
328100bf4279Sespie 
328200bf4279Sespie   /* Now either prepend the temp buffer to the result, or append it,
328300bf4279Sespie      depending upon the state of the append flag.  */
328400bf4279Sespie 
328500bf4279Sespie   if (append)
328600bf4279Sespie     string_appends (result, &temp);
328700bf4279Sespie   else
328800bf4279Sespie     {
328900bf4279Sespie       if (!STRING_EMPTY (result))
329000bf4279Sespie 	string_append (&temp, SCOPE_STRING (work));
329100bf4279Sespie       string_prepends (result, &temp);
329200bf4279Sespie     }
329300bf4279Sespie 
329400bf4279Sespie   string_delete (&last_name);
329500bf4279Sespie   string_delete (&temp);
329600bf4279Sespie   return (success);
329700bf4279Sespie }
329800bf4279Sespie 
329900bf4279Sespie /*
330000bf4279Sespie 
330100bf4279Sespie LOCAL FUNCTION
330200bf4279Sespie 
330300bf4279Sespie 	get_count -- convert an ascii count to integer, consuming tokens
330400bf4279Sespie 
330500bf4279Sespie SYNOPSIS
330600bf4279Sespie 
330700bf4279Sespie 	static int
330800bf4279Sespie 	get_count (const char **type, int *count)
330900bf4279Sespie 
331000bf4279Sespie DESCRIPTION
331100bf4279Sespie 
331200bf4279Sespie 	Assume that *type points at a count in a mangled name; set
331300bf4279Sespie 	*count to its value, and set *type to the next character after
331400bf4279Sespie 	the count.  There are some weird rules in effect here.
331500bf4279Sespie 
331600bf4279Sespie 	If *type does not point at a string of digits, return zero.
331700bf4279Sespie 
331800bf4279Sespie 	If *type points at a string of digits followed by an
331900bf4279Sespie 	underscore, set *count to their value as an integer, advance
332000bf4279Sespie 	*type to point *after the underscore, and return 1.
332100bf4279Sespie 
332200bf4279Sespie 	If *type points at a string of digits not followed by an
332300bf4279Sespie 	underscore, consume only the first digit.  Set *count to its
332400bf4279Sespie 	value as an integer, leave *type pointing after that digit,
332500bf4279Sespie 	and return 1.
332600bf4279Sespie 
332700bf4279Sespie         The excuse for this odd behavior: in the ARM and HP demangling
332800bf4279Sespie         styles, a type can be followed by a repeat count of the form
332900bf4279Sespie         `Nxy', where:
333000bf4279Sespie 
333100bf4279Sespie         `x' is a single digit specifying how many additional copies
333200bf4279Sespie             of the type to append to the argument list, and
333300bf4279Sespie 
333400bf4279Sespie         `y' is one or more digits, specifying the zero-based index of
333500bf4279Sespie             the first repeated argument in the list.  Yes, as you're
333600bf4279Sespie             unmangling the name you can figure this out yourself, but
333700bf4279Sespie             it's there anyway.
333800bf4279Sespie 
333900bf4279Sespie         So, for example, in `bar__3fooFPiN51', the first argument is a
334000bf4279Sespie         pointer to an integer (`Pi'), and then the next five arguments
334100bf4279Sespie         are the same (`N5'), and the first repeat is the function's
334200bf4279Sespie         second argument (`1').
334300bf4279Sespie */
334400bf4279Sespie 
334500bf4279Sespie static int
get_count(const char ** type,int * count)3346*150b7e42Smiod get_count (const char **type, int *count)
334700bf4279Sespie {
334800bf4279Sespie   const char *p;
334900bf4279Sespie   int n;
335000bf4279Sespie 
335137c53322Sespie   if (!ISDIGIT ((unsigned char)**type))
335200bf4279Sespie     return (0);
335300bf4279Sespie   else
335400bf4279Sespie     {
335500bf4279Sespie       *count = **type - '0';
335600bf4279Sespie       (*type)++;
335737c53322Sespie       if (ISDIGIT ((unsigned char)**type))
335800bf4279Sespie 	{
335900bf4279Sespie 	  p = *type;
336000bf4279Sespie 	  n = *count;
336100bf4279Sespie 	  do
336200bf4279Sespie 	    {
336300bf4279Sespie 	      n *= 10;
336400bf4279Sespie 	      n += *p - '0';
336500bf4279Sespie 	      p++;
336600bf4279Sespie 	    }
336737c53322Sespie 	  while (ISDIGIT ((unsigned char)*p));
336800bf4279Sespie 	  if (*p == '_')
336900bf4279Sespie 	    {
337000bf4279Sespie 	      *type = p + 1;
337100bf4279Sespie 	      *count = n;
337200bf4279Sespie 	    }
337300bf4279Sespie 	}
337400bf4279Sespie     }
337500bf4279Sespie   return (1);
337600bf4279Sespie }
337700bf4279Sespie 
337800bf4279Sespie /* RESULT will be initialised here; it will be freed on failure.  The
337900bf4279Sespie    value returned is really a type_kind_t.  */
338000bf4279Sespie 
338100bf4279Sespie static int
do_type(struct work_stuff * work,const char ** mangled,string * result)3382*150b7e42Smiod do_type (struct work_stuff *work, const char **mangled, string *result)
338300bf4279Sespie {
338400bf4279Sespie   int n;
338500bf4279Sespie   int done;
338600bf4279Sespie   int success;
338700bf4279Sespie   string decl;
338800bf4279Sespie   const char *remembered_type;
338900bf4279Sespie   int type_quals;
339000bf4279Sespie   type_kind_t tk = tk_none;
339100bf4279Sespie 
339200bf4279Sespie   string_init (&decl);
339300bf4279Sespie   string_init (result);
339400bf4279Sespie 
339500bf4279Sespie   done = 0;
339600bf4279Sespie   success = 1;
339700bf4279Sespie   while (success && !done)
339800bf4279Sespie     {
339900bf4279Sespie       int member;
340000bf4279Sespie       switch (**mangled)
340100bf4279Sespie 	{
340200bf4279Sespie 
340300bf4279Sespie 	  /* A pointer type */
340400bf4279Sespie 	case 'P':
340500bf4279Sespie 	case 'p':
340600bf4279Sespie 	  (*mangled)++;
340700bf4279Sespie 	  if (! (work -> options & DMGL_JAVA))
340800bf4279Sespie 	    string_prepend (&decl, "*");
340900bf4279Sespie 	  if (tk == tk_none)
341000bf4279Sespie 	    tk = tk_pointer;
341100bf4279Sespie 	  break;
341200bf4279Sespie 
341300bf4279Sespie 	  /* A reference type */
341400bf4279Sespie 	case 'R':
341500bf4279Sespie 	  (*mangled)++;
341600bf4279Sespie 	  string_prepend (&decl, "&");
341700bf4279Sespie 	  if (tk == tk_none)
341800bf4279Sespie 	    tk = tk_reference;
341900bf4279Sespie 	  break;
342000bf4279Sespie 
342100bf4279Sespie 	  /* An array */
342200bf4279Sespie 	case 'A':
342300bf4279Sespie 	  {
342400bf4279Sespie 	    ++(*mangled);
342500bf4279Sespie 	    if (!STRING_EMPTY (&decl)
342600bf4279Sespie 		&& (decl.b[0] == '*' || decl.b[0] == '&'))
342700bf4279Sespie 	      {
342800bf4279Sespie 		string_prepend (&decl, "(");
342900bf4279Sespie 		string_append (&decl, ")");
343000bf4279Sespie 	      }
343100bf4279Sespie 	    string_append (&decl, "[");
343200bf4279Sespie 	    if (**mangled != '_')
343300bf4279Sespie 	      success = demangle_template_value_parm (work, mangled, &decl,
343400bf4279Sespie 						      tk_integral);
343500bf4279Sespie 	    if (**mangled == '_')
343600bf4279Sespie 	      ++(*mangled);
343700bf4279Sespie 	    string_append (&decl, "]");
343800bf4279Sespie 	    break;
343900bf4279Sespie 	  }
344000bf4279Sespie 
344100bf4279Sespie 	/* A back reference to a previously seen type */
344200bf4279Sespie 	case 'T':
344300bf4279Sespie 	  (*mangled)++;
344400bf4279Sespie 	  if (!get_count (mangled, &n) || n >= work -> ntypes)
344500bf4279Sespie 	    {
344600bf4279Sespie 	      success = 0;
344700bf4279Sespie 	    }
344800bf4279Sespie 	  else
344900bf4279Sespie 	    {
345000bf4279Sespie 	      remembered_type = work -> typevec[n];
345100bf4279Sespie 	      mangled = &remembered_type;
345200bf4279Sespie 	    }
345300bf4279Sespie 	  break;
345400bf4279Sespie 
345500bf4279Sespie 	  /* A function */
345600bf4279Sespie 	case 'F':
345700bf4279Sespie 	  (*mangled)++;
345800bf4279Sespie 	    if (!STRING_EMPTY (&decl)
345900bf4279Sespie 		&& (decl.b[0] == '*' || decl.b[0] == '&'))
346000bf4279Sespie 	    {
346100bf4279Sespie 	      string_prepend (&decl, "(");
346200bf4279Sespie 	      string_append (&decl, ")");
346300bf4279Sespie 	    }
346400bf4279Sespie 	  /* After picking off the function args, we expect to either find the
346500bf4279Sespie 	     function return type (preceded by an '_') or the end of the
346600bf4279Sespie 	     string.  */
346700bf4279Sespie 	  if (!demangle_nested_args (work, mangled, &decl)
346800bf4279Sespie 	      || (**mangled != '_' && **mangled != '\0'))
346900bf4279Sespie 	    {
347000bf4279Sespie 	      success = 0;
347100bf4279Sespie 	      break;
347200bf4279Sespie 	    }
347300bf4279Sespie 	  if (success && (**mangled == '_'))
347400bf4279Sespie 	    (*mangled)++;
347500bf4279Sespie 	  break;
347600bf4279Sespie 
347700bf4279Sespie 	case 'M':
347800bf4279Sespie 	case 'O':
347900bf4279Sespie 	  {
348000bf4279Sespie 	    type_quals = TYPE_UNQUALIFIED;
348100bf4279Sespie 
348200bf4279Sespie 	    member = **mangled == 'M';
348300bf4279Sespie 	    (*mangled)++;
348400bf4279Sespie 
348500bf4279Sespie 	    string_append (&decl, ")");
348637c53322Sespie 
348737c53322Sespie 	    /* We don't need to prepend `::' for a qualified name;
348837c53322Sespie 	       demangle_qualified will do that for us.  */
348937c53322Sespie 	    if (**mangled != 'Q')
349000bf4279Sespie 	      string_prepend (&decl, SCOPE_STRING (work));
349137c53322Sespie 
349237c53322Sespie 	    if (ISDIGIT ((unsigned char)**mangled))
349300bf4279Sespie 	      {
349400bf4279Sespie 		n = consume_count (mangled);
349500bf4279Sespie 		if (n == -1
349600bf4279Sespie 		    || (int) strlen (*mangled) < n)
349700bf4279Sespie 		  {
349800bf4279Sespie 		    success = 0;
349900bf4279Sespie 		    break;
350000bf4279Sespie 		  }
350100bf4279Sespie 		string_prependn (&decl, *mangled, n);
350200bf4279Sespie 		*mangled += n;
350300bf4279Sespie 	      }
350400bf4279Sespie 	    else if (**mangled == 'X' || **mangled == 'Y')
350500bf4279Sespie 	      {
350600bf4279Sespie 		string temp;
350700bf4279Sespie 		do_type (work, mangled, &temp);
350800bf4279Sespie 		string_prepends (&decl, &temp);
3509707f648cSespie 		string_delete (&temp);
351000bf4279Sespie 	      }
351100bf4279Sespie 	    else if (**mangled == 't')
351200bf4279Sespie 	      {
351300bf4279Sespie 		string temp;
351400bf4279Sespie 		string_init (&temp);
351500bf4279Sespie 		success = demangle_template (work, mangled, &temp,
351600bf4279Sespie 					     NULL, 1, 1);
351700bf4279Sespie 		if (success)
351800bf4279Sespie 		  {
351900bf4279Sespie 		    string_prependn (&decl, temp.b, temp.p - temp.b);
3520707f648cSespie 		    string_delete (&temp);
352100bf4279Sespie 		  }
352200bf4279Sespie 		else
352300bf4279Sespie 		  break;
352400bf4279Sespie 	      }
352537c53322Sespie 	    else if (**mangled == 'Q')
352637c53322Sespie 	      {
352737c53322Sespie 		success = demangle_qualified (work, mangled, &decl,
352837c53322Sespie 					      /*isfuncnam=*/0,
352937c53322Sespie 					      /*append=*/0);
353037c53322Sespie 		if (!success)
353137c53322Sespie 		  break;
353237c53322Sespie 	      }
353300bf4279Sespie 	    else
353400bf4279Sespie 	      {
353500bf4279Sespie 		success = 0;
353600bf4279Sespie 		break;
353700bf4279Sespie 	      }
353800bf4279Sespie 
353900bf4279Sespie 	    string_prepend (&decl, "(");
354000bf4279Sespie 	    if (member)
354100bf4279Sespie 	      {
354200bf4279Sespie 		switch (**mangled)
354300bf4279Sespie 		  {
354400bf4279Sespie 		  case 'C':
354500bf4279Sespie 		  case 'V':
354600bf4279Sespie 		  case 'u':
354700bf4279Sespie 		    type_quals |= code_for_qualifier (**mangled);
354800bf4279Sespie 		    (*mangled)++;
354900bf4279Sespie 		    break;
355000bf4279Sespie 
355100bf4279Sespie 		  default:
355200bf4279Sespie 		    break;
355300bf4279Sespie 		  }
355400bf4279Sespie 
355500bf4279Sespie 		if (*(*mangled)++ != 'F')
355600bf4279Sespie 		  {
355700bf4279Sespie 		    success = 0;
355800bf4279Sespie 		    break;
355900bf4279Sespie 		  }
356000bf4279Sespie 	      }
356100bf4279Sespie 	    if ((member && !demangle_nested_args (work, mangled, &decl))
356200bf4279Sespie 		|| **mangled != '_')
356300bf4279Sespie 	      {
356400bf4279Sespie 		success = 0;
356500bf4279Sespie 		break;
356600bf4279Sespie 	      }
356700bf4279Sespie 	    (*mangled)++;
356800bf4279Sespie 	    if (! PRINT_ANSI_QUALIFIERS)
356900bf4279Sespie 	      {
357000bf4279Sespie 		break;
357100bf4279Sespie 	      }
357200bf4279Sespie 	    if (type_quals != TYPE_UNQUALIFIED)
357300bf4279Sespie 	      {
357400bf4279Sespie 		APPEND_BLANK (&decl);
357500bf4279Sespie 		string_append (&decl, qualifier_string (type_quals));
357600bf4279Sespie 	      }
357700bf4279Sespie 	    break;
357800bf4279Sespie 	  }
357900bf4279Sespie         case 'G':
358000bf4279Sespie 	  (*mangled)++;
358100bf4279Sespie 	  break;
358200bf4279Sespie 
358300bf4279Sespie 	case 'C':
358400bf4279Sespie 	case 'V':
358500bf4279Sespie 	case 'u':
358600bf4279Sespie 	  if (PRINT_ANSI_QUALIFIERS)
358700bf4279Sespie 	    {
358800bf4279Sespie 	      if (!STRING_EMPTY (&decl))
358900bf4279Sespie 		string_prepend (&decl, " ");
359000bf4279Sespie 
359100bf4279Sespie 	      string_prepend (&decl, demangle_qualifier (**mangled));
359200bf4279Sespie 	    }
359300bf4279Sespie 	  (*mangled)++;
359400bf4279Sespie 	  break;
359500bf4279Sespie 	  /*
359600bf4279Sespie 	    }
359700bf4279Sespie 	    */
359800bf4279Sespie 
359900bf4279Sespie 	  /* fall through */
360000bf4279Sespie 	default:
360100bf4279Sespie 	  done = 1;
360200bf4279Sespie 	  break;
360300bf4279Sespie 	}
360400bf4279Sespie     }
360500bf4279Sespie 
360600bf4279Sespie   if (success) switch (**mangled)
360700bf4279Sespie     {
360800bf4279Sespie       /* A qualified name, such as "Outer::Inner".  */
360900bf4279Sespie     case 'Q':
361000bf4279Sespie     case 'K':
361100bf4279Sespie       {
361200bf4279Sespie         success = demangle_qualified (work, mangled, result, 0, 1);
361300bf4279Sespie         break;
361400bf4279Sespie       }
361500bf4279Sespie 
361600bf4279Sespie     /* A back reference to a previously seen squangled type */
361700bf4279Sespie     case 'B':
361800bf4279Sespie       (*mangled)++;
361900bf4279Sespie       if (!get_count (mangled, &n) || n >= work -> numb)
362000bf4279Sespie 	success = 0;
362100bf4279Sespie       else
362200bf4279Sespie 	string_append (result, work->btypevec[n]);
362300bf4279Sespie       break;
362400bf4279Sespie 
362500bf4279Sespie     case 'X':
362600bf4279Sespie     case 'Y':
362700bf4279Sespie       /* A template parm.  We substitute the corresponding argument. */
362800bf4279Sespie       {
362900bf4279Sespie 	int idx;
363000bf4279Sespie 
363100bf4279Sespie 	(*mangled)++;
363200bf4279Sespie 	idx = consume_count_with_underscores (mangled);
363300bf4279Sespie 
363400bf4279Sespie 	if (idx == -1
363500bf4279Sespie 	    || (work->tmpl_argvec && idx >= work->ntmpl_args)
363600bf4279Sespie 	    || consume_count_with_underscores (mangled) == -1)
363700bf4279Sespie 	  {
363800bf4279Sespie 	    success = 0;
363900bf4279Sespie 	    break;
364000bf4279Sespie 	  }
364100bf4279Sespie 
364200bf4279Sespie 	if (work->tmpl_argvec)
364300bf4279Sespie 	  string_append (result, work->tmpl_argvec[idx]);
364400bf4279Sespie 	else
364537c53322Sespie 	  string_append_template_idx (result, idx);
364600bf4279Sespie 
364700bf4279Sespie 	success = 1;
364800bf4279Sespie       }
364900bf4279Sespie     break;
365000bf4279Sespie 
365100bf4279Sespie     default:
365200bf4279Sespie       success = demangle_fund_type (work, mangled, result);
365300bf4279Sespie       if (tk == tk_none)
365400bf4279Sespie 	tk = (type_kind_t) success;
365500bf4279Sespie       break;
365600bf4279Sespie     }
365700bf4279Sespie 
365800bf4279Sespie   if (success)
365900bf4279Sespie     {
366000bf4279Sespie       if (!STRING_EMPTY (&decl))
366100bf4279Sespie 	{
366200bf4279Sespie 	  string_append (result, " ");
366300bf4279Sespie 	  string_appends (result, &decl);
366400bf4279Sespie 	}
366500bf4279Sespie     }
366600bf4279Sespie   else
366700bf4279Sespie     string_delete (result);
366800bf4279Sespie   string_delete (&decl);
366900bf4279Sespie 
367000bf4279Sespie   if (success)
367100bf4279Sespie     /* Assume an integral type, if we're not sure.  */
367200bf4279Sespie     return (int) ((tk == tk_none) ? tk_integral : tk);
367300bf4279Sespie   else
367400bf4279Sespie     return 0;
367500bf4279Sespie }
367600bf4279Sespie 
367700bf4279Sespie /* Given a pointer to a type string that represents a fundamental type
367800bf4279Sespie    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
367900bf4279Sespie    string in which the demangled output is being built in RESULT, and
368000bf4279Sespie    the WORK structure, decode the types and add them to the result.
368100bf4279Sespie 
368200bf4279Sespie    For example:
368300bf4279Sespie 
368400bf4279Sespie    	"Ci"	=>	"const int"
368500bf4279Sespie 	"Sl"	=>	"signed long"
368600bf4279Sespie 	"CUs"	=>	"const unsigned short"
368700bf4279Sespie 
368800bf4279Sespie    The value returned is really a type_kind_t.  */
368900bf4279Sespie 
369000bf4279Sespie static int
demangle_fund_type(struct work_stuff * work,const char ** mangled,string * result)3691*150b7e42Smiod demangle_fund_type (struct work_stuff *work,
3692*150b7e42Smiod                     const char **mangled, string *result)
369300bf4279Sespie {
369400bf4279Sespie   int done = 0;
369500bf4279Sespie   int success = 1;
369600bf4279Sespie   char buf[10];
369737c53322Sespie   unsigned int dec = 0;
369800bf4279Sespie   type_kind_t tk = tk_integral;
369900bf4279Sespie 
370000bf4279Sespie   /* First pick off any type qualifiers.  There can be more than one.  */
370100bf4279Sespie 
370200bf4279Sespie   while (!done)
370300bf4279Sespie     {
370400bf4279Sespie       switch (**mangled)
370500bf4279Sespie 	{
370600bf4279Sespie 	case 'C':
370700bf4279Sespie 	case 'V':
370800bf4279Sespie 	case 'u':
370900bf4279Sespie 	  if (PRINT_ANSI_QUALIFIERS)
371000bf4279Sespie 	    {
371100bf4279Sespie               if (!STRING_EMPTY (result))
371200bf4279Sespie                 string_prepend (result, " ");
371300bf4279Sespie 	      string_prepend (result, demangle_qualifier (**mangled));
371400bf4279Sespie 	    }
371500bf4279Sespie 	  (*mangled)++;
371600bf4279Sespie 	  break;
371700bf4279Sespie 	case 'U':
371800bf4279Sespie 	  (*mangled)++;
371900bf4279Sespie 	  APPEND_BLANK (result);
372000bf4279Sespie 	  string_append (result, "unsigned");
372100bf4279Sespie 	  break;
372200bf4279Sespie 	case 'S': /* signed char only */
372300bf4279Sespie 	  (*mangled)++;
372400bf4279Sespie 	  APPEND_BLANK (result);
372500bf4279Sespie 	  string_append (result, "signed");
372600bf4279Sespie 	  break;
372700bf4279Sespie 	case 'J':
372800bf4279Sespie 	  (*mangled)++;
372900bf4279Sespie 	  APPEND_BLANK (result);
373000bf4279Sespie 	  string_append (result, "__complex");
373100bf4279Sespie 	  break;
373200bf4279Sespie 	default:
373300bf4279Sespie 	  done = 1;
373400bf4279Sespie 	  break;
373500bf4279Sespie 	}
373600bf4279Sespie     }
373700bf4279Sespie 
373800bf4279Sespie   /* Now pick off the fundamental type.  There can be only one.  */
373900bf4279Sespie 
374000bf4279Sespie   switch (**mangled)
374100bf4279Sespie     {
374200bf4279Sespie     case '\0':
374300bf4279Sespie     case '_':
374400bf4279Sespie       break;
374500bf4279Sespie     case 'v':
374600bf4279Sespie       (*mangled)++;
374700bf4279Sespie       APPEND_BLANK (result);
374800bf4279Sespie       string_append (result, "void");
374900bf4279Sespie       break;
375000bf4279Sespie     case 'x':
375100bf4279Sespie       (*mangled)++;
375200bf4279Sespie       APPEND_BLANK (result);
375300bf4279Sespie       string_append (result, "long long");
375400bf4279Sespie       break;
375500bf4279Sespie     case 'l':
375600bf4279Sespie       (*mangled)++;
375700bf4279Sespie       APPEND_BLANK (result);
375800bf4279Sespie       string_append (result, "long");
375900bf4279Sespie       break;
376000bf4279Sespie     case 'i':
376100bf4279Sespie       (*mangled)++;
376200bf4279Sespie       APPEND_BLANK (result);
376300bf4279Sespie       string_append (result, "int");
376400bf4279Sespie       break;
376500bf4279Sespie     case 's':
376600bf4279Sespie       (*mangled)++;
376700bf4279Sespie       APPEND_BLANK (result);
376800bf4279Sespie       string_append (result, "short");
376900bf4279Sespie       break;
377000bf4279Sespie     case 'b':
377100bf4279Sespie       (*mangled)++;
377200bf4279Sespie       APPEND_BLANK (result);
377300bf4279Sespie       string_append (result, "bool");
377400bf4279Sespie       tk = tk_bool;
377500bf4279Sespie       break;
377600bf4279Sespie     case 'c':
377700bf4279Sespie       (*mangled)++;
377800bf4279Sespie       APPEND_BLANK (result);
377900bf4279Sespie       string_append (result, "char");
378000bf4279Sespie       tk = tk_char;
378100bf4279Sespie       break;
378200bf4279Sespie     case 'w':
378300bf4279Sespie       (*mangled)++;
378400bf4279Sespie       APPEND_BLANK (result);
378500bf4279Sespie       string_append (result, "wchar_t");
378600bf4279Sespie       tk = tk_char;
378700bf4279Sespie       break;
378800bf4279Sespie     case 'r':
378900bf4279Sespie       (*mangled)++;
379000bf4279Sespie       APPEND_BLANK (result);
379100bf4279Sespie       string_append (result, "long double");
379200bf4279Sespie       tk = tk_real;
379300bf4279Sespie       break;
379400bf4279Sespie     case 'd':
379500bf4279Sespie       (*mangled)++;
379600bf4279Sespie       APPEND_BLANK (result);
379700bf4279Sespie       string_append (result, "double");
379800bf4279Sespie       tk = tk_real;
379900bf4279Sespie       break;
380000bf4279Sespie     case 'f':
380100bf4279Sespie       (*mangled)++;
380200bf4279Sespie       APPEND_BLANK (result);
380300bf4279Sespie       string_append (result, "float");
380400bf4279Sespie       tk = tk_real;
380500bf4279Sespie       break;
380600bf4279Sespie     case 'G':
380700bf4279Sespie       (*mangled)++;
380837c53322Sespie       if (!ISDIGIT ((unsigned char)**mangled))
380900bf4279Sespie 	{
381000bf4279Sespie 	  success = 0;
381100bf4279Sespie 	  break;
381200bf4279Sespie 	}
381300bf4279Sespie     case 'I':
381400bf4279Sespie       (*mangled)++;
381500bf4279Sespie       if (**mangled == '_')
381600bf4279Sespie 	{
381700bf4279Sespie 	  int i;
381800bf4279Sespie 	  (*mangled)++;
381900bf4279Sespie 	  for (i = 0;
382037c53322Sespie 	       i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
382100bf4279Sespie 	       (*mangled)++, i++)
382200bf4279Sespie 	    buf[i] = **mangled;
382300bf4279Sespie 	  if (**mangled != '_')
382400bf4279Sespie 	    {
382500bf4279Sespie 	      success = 0;
382600bf4279Sespie 	      break;
382700bf4279Sespie 	    }
382800bf4279Sespie 	  buf[i] = '\0';
382900bf4279Sespie 	  (*mangled)++;
383000bf4279Sespie 	}
383100bf4279Sespie       else
383200bf4279Sespie 	{
383300bf4279Sespie 	  strncpy (buf, *mangled, 2);
383400bf4279Sespie 	  buf[2] = '\0';
383500bf4279Sespie 	  *mangled += min (strlen (*mangled), 2);
383600bf4279Sespie 	}
383700bf4279Sespie       sscanf (buf, "%x", &dec);
383897490679Sespie       snprintf (buf, sizeof buf, "int%u_t", dec);
383900bf4279Sespie       APPEND_BLANK (result);
384000bf4279Sespie       string_append (result, buf);
384100bf4279Sespie       break;
384200bf4279Sespie 
384300bf4279Sespie       /* fall through */
384400bf4279Sespie       /* An explicit type, such as "6mytype" or "7integer" */
384500bf4279Sespie     case '0':
384600bf4279Sespie     case '1':
384700bf4279Sespie     case '2':
384800bf4279Sespie     case '3':
384900bf4279Sespie     case '4':
385000bf4279Sespie     case '5':
385100bf4279Sespie     case '6':
385200bf4279Sespie     case '7':
385300bf4279Sespie     case '8':
385400bf4279Sespie     case '9':
385500bf4279Sespie       {
385600bf4279Sespie         int bindex = register_Btype (work);
385700bf4279Sespie         string btype;
385800bf4279Sespie         string_init (&btype);
385900bf4279Sespie         if (demangle_class_name (work, mangled, &btype)) {
386000bf4279Sespie           remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
386100bf4279Sespie           APPEND_BLANK (result);
386200bf4279Sespie           string_appends (result, &btype);
386300bf4279Sespie         }
386400bf4279Sespie         else
386500bf4279Sespie           success = 0;
386600bf4279Sespie         string_delete (&btype);
386700bf4279Sespie         break;
386800bf4279Sespie       }
386900bf4279Sespie     case 't':
387000bf4279Sespie       {
3871707f648cSespie         string btype;
3872707f648cSespie         string_init (&btype);
387300bf4279Sespie         success = demangle_template (work, mangled, &btype, 0, 1, 1);
387400bf4279Sespie         string_appends (result, &btype);
3875707f648cSespie         string_delete (&btype);
387600bf4279Sespie         break;
387700bf4279Sespie       }
387800bf4279Sespie     default:
387900bf4279Sespie       success = 0;
388000bf4279Sespie       break;
388100bf4279Sespie     }
388200bf4279Sespie 
388300bf4279Sespie   return success ? ((int) tk) : 0;
388400bf4279Sespie }
388500bf4279Sespie 
388600bf4279Sespie 
388700bf4279Sespie /* Handle a template's value parameter for HP aCC (extension from ARM)
388800bf4279Sespie    **mangled points to 'S' or 'U' */
388900bf4279Sespie 
389000bf4279Sespie static int
do_hpacc_template_const_value(struct work_stuff * work ATTRIBUTE_UNUSED,const char ** mangled,string * result)3891*150b7e42Smiod do_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED,
3892*150b7e42Smiod                                const char **mangled, string *result)
389300bf4279Sespie {
389400bf4279Sespie   int unsigned_const;
389500bf4279Sespie 
389600bf4279Sespie   if (**mangled != 'U' && **mangled != 'S')
389700bf4279Sespie     return 0;
389800bf4279Sespie 
389900bf4279Sespie   unsigned_const = (**mangled == 'U');
390000bf4279Sespie 
390100bf4279Sespie   (*mangled)++;
390200bf4279Sespie 
390300bf4279Sespie   switch (**mangled)
390400bf4279Sespie     {
390500bf4279Sespie       case 'N':
390600bf4279Sespie         string_append (result, "-");
390700bf4279Sespie         /* fall through */
390800bf4279Sespie       case 'P':
390900bf4279Sespie         (*mangled)++;
391000bf4279Sespie         break;
391100bf4279Sespie       case 'M':
391200bf4279Sespie         /* special case for -2^31 */
391300bf4279Sespie         string_append (result, "-2147483648");
391400bf4279Sespie         (*mangled)++;
391500bf4279Sespie         return 1;
391600bf4279Sespie       default:
391700bf4279Sespie         return 0;
391800bf4279Sespie     }
391900bf4279Sespie 
392000bf4279Sespie   /* We have to be looking at an integer now */
392137c53322Sespie   if (!(ISDIGIT ((unsigned char)**mangled)))
392200bf4279Sespie     return 0;
392300bf4279Sespie 
392400bf4279Sespie   /* We only deal with integral values for template
392500bf4279Sespie      parameters -- so it's OK to look only for digits */
392637c53322Sespie   while (ISDIGIT ((unsigned char)**mangled))
392700bf4279Sespie     {
392800bf4279Sespie       char_str[0] = **mangled;
392900bf4279Sespie       string_append (result, char_str);
393000bf4279Sespie       (*mangled)++;
393100bf4279Sespie     }
393200bf4279Sespie 
393300bf4279Sespie   if (unsigned_const)
393400bf4279Sespie     string_append (result, "U");
393500bf4279Sespie 
393600bf4279Sespie   /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
393700bf4279Sespie      with L or LL suffixes. pai/1997-09-03 */
393800bf4279Sespie 
393900bf4279Sespie   return 1; /* success */
394000bf4279Sespie }
394100bf4279Sespie 
394200bf4279Sespie /* Handle a template's literal parameter for HP aCC (extension from ARM)
394300bf4279Sespie    **mangled is pointing to the 'A' */
394400bf4279Sespie 
394500bf4279Sespie static int
do_hpacc_template_literal(struct work_stuff * work,const char ** mangled,string * result)3946*150b7e42Smiod do_hpacc_template_literal (struct work_stuff *work, const char **mangled,
3947*150b7e42Smiod                            string *result)
394800bf4279Sespie {
394900bf4279Sespie   int literal_len = 0;
395000bf4279Sespie   char * recurse;
395100bf4279Sespie   char * recurse_dem;
395200bf4279Sespie 
395300bf4279Sespie   if (**mangled != 'A')
395400bf4279Sespie     return 0;
395500bf4279Sespie 
395600bf4279Sespie   (*mangled)++;
395700bf4279Sespie 
395800bf4279Sespie   literal_len = consume_count (mangled);
395900bf4279Sespie 
396000bf4279Sespie   if (literal_len <= 0)
396100bf4279Sespie     return 0;
396200bf4279Sespie 
396300bf4279Sespie   /* Literal parameters are names of arrays, functions, etc.  and the
396400bf4279Sespie      canonical representation uses the address operator */
396500bf4279Sespie   string_append (result, "&");
396600bf4279Sespie 
396700bf4279Sespie   /* Now recursively demangle the literal name */
3968*150b7e42Smiod   recurse = XNEWVEC (char, literal_len + 1);
396900bf4279Sespie   memcpy (recurse, *mangled, literal_len);
397000bf4279Sespie   recurse[literal_len] = '\000';
397100bf4279Sespie 
397200bf4279Sespie   recurse_dem = cplus_demangle (recurse, work->options);
397300bf4279Sespie 
397400bf4279Sespie   if (recurse_dem)
397500bf4279Sespie     {
397600bf4279Sespie       string_append (result, recurse_dem);
397700bf4279Sespie       free (recurse_dem);
397800bf4279Sespie     }
397900bf4279Sespie   else
398000bf4279Sespie     {
398100bf4279Sespie       string_appendn (result, *mangled, literal_len);
398200bf4279Sespie     }
398300bf4279Sespie   (*mangled) += literal_len;
398400bf4279Sespie   free (recurse);
398500bf4279Sespie 
398600bf4279Sespie   return 1;
398700bf4279Sespie }
398800bf4279Sespie 
398900bf4279Sespie static int
snarf_numeric_literal(const char ** args,string * arg)3990*150b7e42Smiod snarf_numeric_literal (const char **args, string *arg)
399100bf4279Sespie {
399200bf4279Sespie   if (**args == '-')
399300bf4279Sespie     {
399400bf4279Sespie       char_str[0] = '-';
399500bf4279Sespie       string_append (arg, char_str);
399600bf4279Sespie       (*args)++;
399700bf4279Sespie     }
399800bf4279Sespie   else if (**args == '+')
399900bf4279Sespie     (*args)++;
400000bf4279Sespie 
400137c53322Sespie   if (!ISDIGIT ((unsigned char)**args))
400200bf4279Sespie     return 0;
400300bf4279Sespie 
400437c53322Sespie   while (ISDIGIT ((unsigned char)**args))
400500bf4279Sespie     {
400600bf4279Sespie       char_str[0] = **args;
400700bf4279Sespie       string_append (arg, char_str);
400800bf4279Sespie       (*args)++;
400900bf4279Sespie     }
401000bf4279Sespie 
401100bf4279Sespie   return 1;
401200bf4279Sespie }
401300bf4279Sespie 
401400bf4279Sespie /* Demangle the next argument, given by MANGLED into RESULT, which
401500bf4279Sespie    *should be an uninitialized* string.  It will be initialized here,
401600bf4279Sespie    and free'd should anything go wrong.  */
401700bf4279Sespie 
401800bf4279Sespie static int
do_arg(struct work_stuff * work,const char ** mangled,string * result)4019*150b7e42Smiod do_arg (struct work_stuff *work, const char **mangled, string *result)
402000bf4279Sespie {
402100bf4279Sespie   /* Remember where we started so that we can record the type, for
402200bf4279Sespie      non-squangling type remembering.  */
402300bf4279Sespie   const char *start = *mangled;
402400bf4279Sespie 
402500bf4279Sespie   string_init (result);
402600bf4279Sespie 
402700bf4279Sespie   if (work->nrepeats > 0)
402800bf4279Sespie     {
402900bf4279Sespie       --work->nrepeats;
403000bf4279Sespie 
403100bf4279Sespie       if (work->previous_argument == 0)
403200bf4279Sespie 	return 0;
403300bf4279Sespie 
403400bf4279Sespie       /* We want to reissue the previous type in this argument list.  */
403500bf4279Sespie       string_appends (result, work->previous_argument);
403600bf4279Sespie       return 1;
403700bf4279Sespie     }
403800bf4279Sespie 
403900bf4279Sespie   if (**mangled == 'n')
404000bf4279Sespie     {
404100bf4279Sespie       /* A squangling-style repeat.  */
404200bf4279Sespie       (*mangled)++;
404300bf4279Sespie       work->nrepeats = consume_count(mangled);
404400bf4279Sespie 
404500bf4279Sespie       if (work->nrepeats <= 0)
404600bf4279Sespie 	/* This was not a repeat count after all.  */
404700bf4279Sespie 	return 0;
404800bf4279Sespie 
404900bf4279Sespie       if (work->nrepeats > 9)
405000bf4279Sespie 	{
405100bf4279Sespie 	  if (**mangled != '_')
405200bf4279Sespie 	    /* The repeat count should be followed by an '_' in this
405300bf4279Sespie 	       case.  */
405400bf4279Sespie 	    return 0;
405500bf4279Sespie 	  else
405600bf4279Sespie 	    (*mangled)++;
405700bf4279Sespie 	}
405800bf4279Sespie 
405900bf4279Sespie       /* Now, the repeat is all set up.  */
406000bf4279Sespie       return do_arg (work, mangled, result);
406100bf4279Sespie     }
406200bf4279Sespie 
406300bf4279Sespie   /* Save the result in WORK->previous_argument so that we can find it
406400bf4279Sespie      if it's repeated.  Note that saving START is not good enough: we
406500bf4279Sespie      do not want to add additional types to the back-referenceable
406600bf4279Sespie      type vector when processing a repeated type.  */
406700bf4279Sespie   if (work->previous_argument)
4068707f648cSespie     string_delete (work->previous_argument);
406900bf4279Sespie   else
4070*150b7e42Smiod     work->previous_argument = XNEW (string);
407100bf4279Sespie 
407200bf4279Sespie   if (!do_type (work, mangled, work->previous_argument))
407300bf4279Sespie     return 0;
407400bf4279Sespie 
407500bf4279Sespie   string_appends (result, work->previous_argument);
407600bf4279Sespie 
407700bf4279Sespie   remember_type (work, start, *mangled - start);
407800bf4279Sespie   return 1;
407900bf4279Sespie }
408000bf4279Sespie 
408100bf4279Sespie static void
remember_type(struct work_stuff * work,const char * start,int len)4082*150b7e42Smiod remember_type (struct work_stuff *work, const char *start, int len)
408300bf4279Sespie {
408400bf4279Sespie   char *tem;
408500bf4279Sespie 
408600bf4279Sespie   if (work->forgetting_types)
408700bf4279Sespie     return;
408800bf4279Sespie 
408900bf4279Sespie   if (work -> ntypes >= work -> typevec_size)
409000bf4279Sespie     {
409100bf4279Sespie       if (work -> typevec_size == 0)
409200bf4279Sespie 	{
409300bf4279Sespie 	  work -> typevec_size = 3;
4094*150b7e42Smiod 	  work -> typevec = XNEWVEC (char *, work->typevec_size);
409500bf4279Sespie 	}
409600bf4279Sespie       else
409700bf4279Sespie 	{
409800bf4279Sespie 	  work -> typevec_size *= 2;
409900bf4279Sespie 	  work -> typevec
4100*150b7e42Smiod 	    = XRESIZEVEC (char *, work->typevec, work->typevec_size);
410100bf4279Sespie 	}
410200bf4279Sespie     }
4103*150b7e42Smiod   tem = XNEWVEC (char, len + 1);
410400bf4279Sespie   memcpy (tem, start, len);
410500bf4279Sespie   tem[len] = '\0';
410600bf4279Sespie   work -> typevec[work -> ntypes++] = tem;
410700bf4279Sespie }
410800bf4279Sespie 
410900bf4279Sespie 
411000bf4279Sespie /* Remember a K type class qualifier. */
411100bf4279Sespie static void
remember_Ktype(struct work_stuff * work,const char * start,int len)4112*150b7e42Smiod remember_Ktype (struct work_stuff *work, const char *start, int len)
411300bf4279Sespie {
411400bf4279Sespie   char *tem;
411500bf4279Sespie 
411600bf4279Sespie   if (work -> numk >= work -> ksize)
411700bf4279Sespie     {
411800bf4279Sespie       if (work -> ksize == 0)
411900bf4279Sespie 	{
412000bf4279Sespie 	  work -> ksize = 5;
4121*150b7e42Smiod 	  work -> ktypevec = XNEWVEC (char *, work->ksize);
412200bf4279Sespie 	}
412300bf4279Sespie       else
412400bf4279Sespie 	{
412500bf4279Sespie 	  work -> ksize *= 2;
412600bf4279Sespie 	  work -> ktypevec
4127*150b7e42Smiod 	    = XRESIZEVEC (char *, work->ktypevec, work->ksize);
412800bf4279Sespie 	}
412900bf4279Sespie     }
4130*150b7e42Smiod   tem = XNEWVEC (char, len + 1);
413100bf4279Sespie   memcpy (tem, start, len);
413200bf4279Sespie   tem[len] = '\0';
413300bf4279Sespie   work -> ktypevec[work -> numk++] = tem;
413400bf4279Sespie }
413500bf4279Sespie 
413600bf4279Sespie /* Register a B code, and get an index for it. B codes are registered
413700bf4279Sespie    as they are seen, rather than as they are completed, so map<temp<char> >
413800bf4279Sespie    registers map<temp<char> > as B0, and temp<char> as B1 */
413900bf4279Sespie 
414000bf4279Sespie static int
register_Btype(struct work_stuff * work)4141*150b7e42Smiod register_Btype (struct work_stuff *work)
414200bf4279Sespie {
414300bf4279Sespie   int ret;
414400bf4279Sespie 
414500bf4279Sespie   if (work -> numb >= work -> bsize)
414600bf4279Sespie     {
414700bf4279Sespie       if (work -> bsize == 0)
414800bf4279Sespie 	{
414900bf4279Sespie 	  work -> bsize = 5;
4150*150b7e42Smiod 	  work -> btypevec = XNEWVEC (char *, work->bsize);
415100bf4279Sespie 	}
415200bf4279Sespie       else
415300bf4279Sespie 	{
415400bf4279Sespie 	  work -> bsize *= 2;
415500bf4279Sespie 	  work -> btypevec
4156*150b7e42Smiod 	    = XRESIZEVEC (char *, work->btypevec, work->bsize);
415700bf4279Sespie 	}
415800bf4279Sespie     }
415900bf4279Sespie   ret = work -> numb++;
416000bf4279Sespie   work -> btypevec[ret] = NULL;
416100bf4279Sespie   return(ret);
416200bf4279Sespie }
416300bf4279Sespie 
416400bf4279Sespie /* Store a value into a previously registered B code type. */
416500bf4279Sespie 
416600bf4279Sespie static void
remember_Btype(struct work_stuff * work,const char * start,int len,int index)4167*150b7e42Smiod remember_Btype (struct work_stuff *work, const char *start,
4168*150b7e42Smiod                 int len, int index)
416900bf4279Sespie {
417000bf4279Sespie   char *tem;
417100bf4279Sespie 
4172*150b7e42Smiod   tem = XNEWVEC (char, len + 1);
417300bf4279Sespie   memcpy (tem, start, len);
417400bf4279Sespie   tem[len] = '\0';
417500bf4279Sespie   work -> btypevec[index] = tem;
417600bf4279Sespie }
417700bf4279Sespie 
417800bf4279Sespie /* Lose all the info related to B and K type codes. */
417900bf4279Sespie static void
forget_B_and_K_types(struct work_stuff * work)4180*150b7e42Smiod forget_B_and_K_types (struct work_stuff *work)
418100bf4279Sespie {
418200bf4279Sespie   int i;
418300bf4279Sespie 
418400bf4279Sespie   while (work -> numk > 0)
418500bf4279Sespie     {
418600bf4279Sespie       i = --(work -> numk);
418700bf4279Sespie       if (work -> ktypevec[i] != NULL)
418800bf4279Sespie 	{
418900bf4279Sespie 	  free (work -> ktypevec[i]);
419000bf4279Sespie 	  work -> ktypevec[i] = NULL;
419100bf4279Sespie 	}
419200bf4279Sespie     }
419300bf4279Sespie 
419400bf4279Sespie   while (work -> numb > 0)
419500bf4279Sespie     {
419600bf4279Sespie       i = --(work -> numb);
419700bf4279Sespie       if (work -> btypevec[i] != NULL)
419800bf4279Sespie 	{
419900bf4279Sespie 	  free (work -> btypevec[i]);
420000bf4279Sespie 	  work -> btypevec[i] = NULL;
420100bf4279Sespie 	}
420200bf4279Sespie     }
420300bf4279Sespie }
420400bf4279Sespie /* Forget the remembered types, but not the type vector itself.  */
420500bf4279Sespie 
420600bf4279Sespie static void
forget_types(struct work_stuff * work)4207*150b7e42Smiod forget_types (struct work_stuff *work)
420800bf4279Sespie {
420900bf4279Sespie   int i;
421000bf4279Sespie 
421100bf4279Sespie   while (work -> ntypes > 0)
421200bf4279Sespie     {
421300bf4279Sespie       i = --(work -> ntypes);
421400bf4279Sespie       if (work -> typevec[i] != NULL)
421500bf4279Sespie 	{
421600bf4279Sespie 	  free (work -> typevec[i]);
421700bf4279Sespie 	  work -> typevec[i] = NULL;
421800bf4279Sespie 	}
421900bf4279Sespie     }
422000bf4279Sespie }
422100bf4279Sespie 
422200bf4279Sespie /* Process the argument list part of the signature, after any class spec
422300bf4279Sespie    has been consumed, as well as the first 'F' character (if any).  For
422400bf4279Sespie    example:
422500bf4279Sespie 
422600bf4279Sespie    "__als__3fooRT0"		=>	process "RT0"
422700bf4279Sespie    "complexfunc5__FPFPc_PFl_i"	=>	process "PFPc_PFl_i"
422800bf4279Sespie 
422900bf4279Sespie    DECLP must be already initialised, usually non-empty.  It won't be freed
423000bf4279Sespie    on failure.
423100bf4279Sespie 
423200bf4279Sespie    Note that g++ differs significantly from ARM and lucid style mangling
423300bf4279Sespie    with regards to references to previously seen types.  For example, given
423400bf4279Sespie    the source fragment:
423500bf4279Sespie 
423600bf4279Sespie      class foo {
423700bf4279Sespie        public:
423800bf4279Sespie        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
423900bf4279Sespie      };
424000bf4279Sespie 
424100bf4279Sespie      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
424200bf4279Sespie      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
424300bf4279Sespie 
424400bf4279Sespie    g++ produces the names:
424500bf4279Sespie 
424600bf4279Sespie      __3fooiRT0iT2iT2
424700bf4279Sespie      foo__FiR3fooiT1iT1
424800bf4279Sespie 
424900bf4279Sespie    while lcc (and presumably other ARM style compilers as well) produces:
425000bf4279Sespie 
425100bf4279Sespie      foo__FiR3fooT1T2T1T2
425200bf4279Sespie      __ct__3fooFiR3fooT1T2T1T2
425300bf4279Sespie 
425400bf4279Sespie    Note that g++ bases its type numbers starting at zero and counts all
425500bf4279Sespie    previously seen types, while lucid/ARM bases its type numbers starting
425600bf4279Sespie    at one and only considers types after it has seen the 'F' character
425700bf4279Sespie    indicating the start of the function args.  For lucid/ARM style, we
425800bf4279Sespie    account for this difference by discarding any previously seen types when
425900bf4279Sespie    we see the 'F' character, and subtracting one from the type number
426000bf4279Sespie    reference.
426100bf4279Sespie 
426200bf4279Sespie  */
426300bf4279Sespie 
426400bf4279Sespie static int
demangle_args(struct work_stuff * work,const char ** mangled,string * declp)4265*150b7e42Smiod demangle_args (struct work_stuff *work, const char **mangled,
4266*150b7e42Smiod                string *declp)
426700bf4279Sespie {
426800bf4279Sespie   string arg;
426900bf4279Sespie   int need_comma = 0;
427000bf4279Sespie   int r;
427100bf4279Sespie   int t;
427200bf4279Sespie   const char *tem;
427300bf4279Sespie   char temptype;
427400bf4279Sespie 
427500bf4279Sespie   if (PRINT_ARG_TYPES)
427600bf4279Sespie     {
427700bf4279Sespie       string_append (declp, "(");
427800bf4279Sespie       if (**mangled == '\0')
427900bf4279Sespie 	{
428000bf4279Sespie 	  string_append (declp, "void");
428100bf4279Sespie 	}
428200bf4279Sespie     }
428300bf4279Sespie 
428400bf4279Sespie   while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
428500bf4279Sespie 	 || work->nrepeats > 0)
428600bf4279Sespie     {
428700bf4279Sespie       if ((**mangled == 'N') || (**mangled == 'T'))
428800bf4279Sespie 	{
428900bf4279Sespie 	  temptype = *(*mangled)++;
429000bf4279Sespie 
429100bf4279Sespie 	  if (temptype == 'N')
429200bf4279Sespie 	    {
429300bf4279Sespie 	      if (!get_count (mangled, &r))
429400bf4279Sespie 		{
429500bf4279Sespie 		  return (0);
429600bf4279Sespie 		}
429700bf4279Sespie 	    }
429800bf4279Sespie 	  else
429900bf4279Sespie 	    {
430000bf4279Sespie 	      r = 1;
430100bf4279Sespie 	    }
430200bf4279Sespie           if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
430300bf4279Sespie             {
430400bf4279Sespie               /* If we have 10 or more types we might have more than a 1 digit
430500bf4279Sespie                  index so we'll have to consume the whole count here. This
430600bf4279Sespie                  will lose if the next thing is a type name preceded by a
430700bf4279Sespie                  count but it's impossible to demangle that case properly
430800bf4279Sespie                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
430900bf4279Sespie                  Pc, ...)"  or "(..., type12, char *, ...)" */
431000bf4279Sespie               if ((t = consume_count(mangled)) <= 0)
431100bf4279Sespie                 {
431200bf4279Sespie                   return (0);
431300bf4279Sespie                 }
431400bf4279Sespie             }
431500bf4279Sespie           else
431600bf4279Sespie 	    {
431700bf4279Sespie 	      if (!get_count (mangled, &t))
431800bf4279Sespie 	    	{
431900bf4279Sespie 	          return (0);
432000bf4279Sespie 	    	}
432100bf4279Sespie 	    }
432200bf4279Sespie 	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
432300bf4279Sespie 	    {
432400bf4279Sespie 	      t--;
432500bf4279Sespie 	    }
432600bf4279Sespie 	  /* Validate the type index.  Protect against illegal indices from
432700bf4279Sespie 	     malformed type strings.  */
432800bf4279Sespie 	  if ((t < 0) || (t >= work -> ntypes))
432900bf4279Sespie 	    {
433000bf4279Sespie 	      return (0);
433100bf4279Sespie 	    }
433200bf4279Sespie 	  while (work->nrepeats > 0 || --r >= 0)
433300bf4279Sespie 	    {
433400bf4279Sespie 	      tem = work -> typevec[t];
433500bf4279Sespie 	      if (need_comma && PRINT_ARG_TYPES)
433600bf4279Sespie 		{
433700bf4279Sespie 		  string_append (declp, ", ");
433800bf4279Sespie 		}
433900bf4279Sespie 	      if (!do_arg (work, &tem, &arg))
434000bf4279Sespie 		{
434100bf4279Sespie 		  return (0);
434200bf4279Sespie 		}
434300bf4279Sespie 	      if (PRINT_ARG_TYPES)
434400bf4279Sespie 		{
434500bf4279Sespie 		  string_appends (declp, &arg);
434600bf4279Sespie 		}
434700bf4279Sespie 	      string_delete (&arg);
434800bf4279Sespie 	      need_comma = 1;
434900bf4279Sespie 	    }
435000bf4279Sespie 	}
435100bf4279Sespie       else
435200bf4279Sespie 	{
435300bf4279Sespie 	  if (need_comma && PRINT_ARG_TYPES)
435400bf4279Sespie 	    string_append (declp, ", ");
435500bf4279Sespie 	  if (!do_arg (work, mangled, &arg))
435600bf4279Sespie 	    return (0);
435700bf4279Sespie 	  if (PRINT_ARG_TYPES)
435800bf4279Sespie 	    string_appends (declp, &arg);
435900bf4279Sespie 	  string_delete (&arg);
436000bf4279Sespie 	  need_comma = 1;
436100bf4279Sespie 	}
436200bf4279Sespie     }
436300bf4279Sespie 
436400bf4279Sespie   if (**mangled == 'e')
436500bf4279Sespie     {
436600bf4279Sespie       (*mangled)++;
436700bf4279Sespie       if (PRINT_ARG_TYPES)
436800bf4279Sespie 	{
436900bf4279Sespie 	  if (need_comma)
437000bf4279Sespie 	    {
437100bf4279Sespie 	      string_append (declp, ",");
437200bf4279Sespie 	    }
437300bf4279Sespie 	  string_append (declp, "...");
437400bf4279Sespie 	}
437500bf4279Sespie     }
437600bf4279Sespie 
437700bf4279Sespie   if (PRINT_ARG_TYPES)
437800bf4279Sespie     {
437900bf4279Sespie       string_append (declp, ")");
438000bf4279Sespie     }
438100bf4279Sespie   return (1);
438200bf4279Sespie }
438300bf4279Sespie 
438400bf4279Sespie /* Like demangle_args, but for demangling the argument lists of function
438500bf4279Sespie    and method pointers or references, not top-level declarations.  */
438600bf4279Sespie 
438700bf4279Sespie static int
demangle_nested_args(struct work_stuff * work,const char ** mangled,string * declp)4388*150b7e42Smiod demangle_nested_args (struct work_stuff *work, const char **mangled,
4389*150b7e42Smiod                       string *declp)
439000bf4279Sespie {
439100bf4279Sespie   string* saved_previous_argument;
439200bf4279Sespie   int result;
439300bf4279Sespie   int saved_nrepeats;
439400bf4279Sespie 
439500bf4279Sespie   /* The G++ name-mangling algorithm does not remember types on nested
439600bf4279Sespie      argument lists, unless -fsquangling is used, and in that case the
439700bf4279Sespie      type vector updated by remember_type is not used.  So, we turn
439800bf4279Sespie      off remembering of types here.  */
439900bf4279Sespie   ++work->forgetting_types;
440000bf4279Sespie 
440100bf4279Sespie   /* For the repeat codes used with -fsquangling, we must keep track of
440200bf4279Sespie      the last argument.  */
440300bf4279Sespie   saved_previous_argument = work->previous_argument;
440400bf4279Sespie   saved_nrepeats = work->nrepeats;
440500bf4279Sespie   work->previous_argument = 0;
440600bf4279Sespie   work->nrepeats = 0;
440700bf4279Sespie 
440800bf4279Sespie   /* Actually demangle the arguments.  */
440900bf4279Sespie   result = demangle_args (work, mangled, declp);
441000bf4279Sespie 
441100bf4279Sespie   /* Restore the previous_argument field.  */
441200bf4279Sespie   if (work->previous_argument)
4413707f648cSespie     {
441400bf4279Sespie       string_delete (work->previous_argument);
4415707f648cSespie       free ((char *) work->previous_argument);
4416707f648cSespie     }
441700bf4279Sespie   work->previous_argument = saved_previous_argument;
441800bf4279Sespie   --work->forgetting_types;
441900bf4279Sespie   work->nrepeats = saved_nrepeats;
442000bf4279Sespie 
442100bf4279Sespie   return result;
442200bf4279Sespie }
442300bf4279Sespie 
442400bf4279Sespie static void
demangle_function_name(struct work_stuff * work,const char ** mangled,string * declp,const char * scan)4425*150b7e42Smiod demangle_function_name (struct work_stuff *work, const char **mangled,
4426*150b7e42Smiod                         string *declp, const char *scan)
442700bf4279Sespie {
442800bf4279Sespie   size_t i;
442900bf4279Sespie   string type;
443000bf4279Sespie   const char *tem;
443100bf4279Sespie 
443200bf4279Sespie   string_appendn (declp, (*mangled), scan - (*mangled));
443300bf4279Sespie   string_need (declp, 1);
443400bf4279Sespie   *(declp -> p) = '\0';
443500bf4279Sespie 
443600bf4279Sespie   /* Consume the function name, including the "__" separating the name
443700bf4279Sespie      from the signature.  We are guaranteed that SCAN points to the
443800bf4279Sespie      separator.  */
443900bf4279Sespie 
444000bf4279Sespie   (*mangled) = scan + 2;
444100bf4279Sespie   /* We may be looking at an instantiation of a template function:
444200bf4279Sespie      foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
444300bf4279Sespie      following _F marks the start of the function arguments.  Handle
444400bf4279Sespie      the template arguments first. */
444500bf4279Sespie 
444600bf4279Sespie   if (HP_DEMANGLING && (**mangled == 'X'))
444700bf4279Sespie     {
444800bf4279Sespie       demangle_arm_hp_template (work, mangled, 0, declp);
444900bf4279Sespie       /* This leaves MANGLED pointing to the 'F' marking func args */
445000bf4279Sespie     }
445100bf4279Sespie 
445200bf4279Sespie   if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
445300bf4279Sespie     {
445400bf4279Sespie 
445500bf4279Sespie       /* See if we have an ARM style constructor or destructor operator.
445600bf4279Sespie 	 If so, then just record it, clear the decl, and return.
445700bf4279Sespie 	 We can't build the actual constructor/destructor decl until later,
445800bf4279Sespie 	 when we recover the class name from the signature.  */
445900bf4279Sespie 
446000bf4279Sespie       if (strcmp (declp -> b, "__ct") == 0)
446100bf4279Sespie 	{
446200bf4279Sespie 	  work -> constructor += 1;
446300bf4279Sespie 	  string_clear (declp);
446400bf4279Sespie 	  return;
446500bf4279Sespie 	}
446600bf4279Sespie       else if (strcmp (declp -> b, "__dt") == 0)
446700bf4279Sespie 	{
446800bf4279Sespie 	  work -> destructor += 1;
446900bf4279Sespie 	  string_clear (declp);
447000bf4279Sespie 	  return;
447100bf4279Sespie 	}
447200bf4279Sespie     }
447300bf4279Sespie 
447400bf4279Sespie   if (declp->p - declp->b >= 3
447500bf4279Sespie       && declp->b[0] == 'o'
447600bf4279Sespie       && declp->b[1] == 'p'
447700bf4279Sespie       && strchr (cplus_markers, declp->b[2]) != NULL)
447800bf4279Sespie     {
447900bf4279Sespie       /* see if it's an assignment expression */
448000bf4279Sespie       if (declp->p - declp->b >= 10 /* op$assign_ */
448100bf4279Sespie 	  && memcmp (declp->b + 3, "assign_", 7) == 0)
448200bf4279Sespie 	{
448337c53322Sespie 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
448400bf4279Sespie 	    {
448500bf4279Sespie 	      int len = declp->p - declp->b - 10;
448600bf4279Sespie 	      if ((int) strlen (optable[i].in) == len
448700bf4279Sespie 		  && memcmp (optable[i].in, declp->b + 10, len) == 0)
448800bf4279Sespie 		{
448900bf4279Sespie 		  string_clear (declp);
449000bf4279Sespie 		  string_append (declp, "operator");
449100bf4279Sespie 		  string_append (declp, optable[i].out);
449200bf4279Sespie 		  string_append (declp, "=");
449300bf4279Sespie 		  break;
449400bf4279Sespie 		}
449500bf4279Sespie 	    }
449600bf4279Sespie 	}
449700bf4279Sespie       else
449800bf4279Sespie 	{
449937c53322Sespie 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
450000bf4279Sespie 	    {
450100bf4279Sespie 	      int len = declp->p - declp->b - 3;
450200bf4279Sespie 	      if ((int) strlen (optable[i].in) == len
450300bf4279Sespie 		  && memcmp (optable[i].in, declp->b + 3, len) == 0)
450400bf4279Sespie 		{
450500bf4279Sespie 		  string_clear (declp);
450600bf4279Sespie 		  string_append (declp, "operator");
450700bf4279Sespie 		  string_append (declp, optable[i].out);
450800bf4279Sespie 		  break;
450900bf4279Sespie 		}
451000bf4279Sespie 	    }
451100bf4279Sespie 	}
451200bf4279Sespie     }
451300bf4279Sespie   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
451400bf4279Sespie 	   && strchr (cplus_markers, declp->b[4]) != NULL)
451500bf4279Sespie     {
451600bf4279Sespie       /* type conversion operator */
451700bf4279Sespie       tem = declp->b + 5;
451800bf4279Sespie       if (do_type (work, &tem, &type))
451900bf4279Sespie 	{
452000bf4279Sespie 	  string_clear (declp);
452100bf4279Sespie 	  string_append (declp, "operator ");
452200bf4279Sespie 	  string_appends (declp, &type);
452300bf4279Sespie 	  string_delete (&type);
452400bf4279Sespie 	}
452500bf4279Sespie     }
452600bf4279Sespie   else if (declp->b[0] == '_' && declp->b[1] == '_'
452700bf4279Sespie 	   && declp->b[2] == 'o' && declp->b[3] == 'p')
452800bf4279Sespie     {
452900bf4279Sespie       /* ANSI.  */
453000bf4279Sespie       /* type conversion operator.  */
453100bf4279Sespie       tem = declp->b + 4;
453200bf4279Sespie       if (do_type (work, &tem, &type))
453300bf4279Sespie 	{
453400bf4279Sespie 	  string_clear (declp);
453500bf4279Sespie 	  string_append (declp, "operator ");
453600bf4279Sespie 	  string_appends (declp, &type);
453700bf4279Sespie 	  string_delete (&type);
453800bf4279Sespie 	}
453900bf4279Sespie     }
454000bf4279Sespie   else if (declp->b[0] == '_' && declp->b[1] == '_'
454137c53322Sespie 	   && ISLOWER((unsigned char)declp->b[2])
454237c53322Sespie 	   && ISLOWER((unsigned char)declp->b[3]))
454300bf4279Sespie     {
454400bf4279Sespie       if (declp->b[4] == '\0')
454500bf4279Sespie 	{
454600bf4279Sespie 	  /* Operator.  */
454737c53322Sespie 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
454800bf4279Sespie 	    {
454900bf4279Sespie 	      if (strlen (optable[i].in) == 2
455000bf4279Sespie 		  && memcmp (optable[i].in, declp->b + 2, 2) == 0)
455100bf4279Sespie 		{
455200bf4279Sespie 		  string_clear (declp);
455300bf4279Sespie 		  string_append (declp, "operator");
455400bf4279Sespie 		  string_append (declp, optable[i].out);
455500bf4279Sespie 		  break;
455600bf4279Sespie 		}
455700bf4279Sespie 	    }
455800bf4279Sespie 	}
455900bf4279Sespie       else
456000bf4279Sespie 	{
456100bf4279Sespie 	  if (declp->b[2] == 'a' && declp->b[5] == '\0')
456200bf4279Sespie 	    {
456300bf4279Sespie 	      /* Assignment.  */
456437c53322Sespie 	      for (i = 0; i < ARRAY_SIZE (optable); i++)
456500bf4279Sespie 		{
456600bf4279Sespie 		  if (strlen (optable[i].in) == 3
456700bf4279Sespie 		      && memcmp (optable[i].in, declp->b + 2, 3) == 0)
456800bf4279Sespie 		    {
456900bf4279Sespie 		      string_clear (declp);
457000bf4279Sespie 		      string_append (declp, "operator");
457100bf4279Sespie 		      string_append (declp, optable[i].out);
457200bf4279Sespie 		      break;
457300bf4279Sespie 		    }
457400bf4279Sespie 		}
457500bf4279Sespie 	    }
457600bf4279Sespie 	}
457700bf4279Sespie     }
457800bf4279Sespie }
457900bf4279Sespie 
458000bf4279Sespie /* a mini string-handling package */
458100bf4279Sespie 
458200bf4279Sespie static void
string_need(string * s,int n)4583*150b7e42Smiod string_need (string *s, int n)
458400bf4279Sespie {
458500bf4279Sespie   int tem;
458600bf4279Sespie 
458700bf4279Sespie   if (s->b == NULL)
458800bf4279Sespie     {
458900bf4279Sespie       if (n < 32)
459000bf4279Sespie 	{
459100bf4279Sespie 	  n = 32;
459200bf4279Sespie 	}
4593*150b7e42Smiod       s->p = s->b = XNEWVEC (char, n);
459400bf4279Sespie       s->e = s->b + n;
459500bf4279Sespie     }
459600bf4279Sespie   else if (s->e - s->p < n)
459700bf4279Sespie     {
459800bf4279Sespie       tem = s->p - s->b;
459900bf4279Sespie       n += tem;
460000bf4279Sespie       n *= 2;
4601*150b7e42Smiod       s->b = XRESIZEVEC (char, s->b, n);
460200bf4279Sespie       s->p = s->b + tem;
460300bf4279Sespie       s->e = s->b + n;
460400bf4279Sespie     }
460500bf4279Sespie }
460600bf4279Sespie 
460700bf4279Sespie static void
string_delete(string * s)4608*150b7e42Smiod string_delete (string *s)
460900bf4279Sespie {
461000bf4279Sespie   if (s->b != NULL)
461100bf4279Sespie     {
461200bf4279Sespie       free (s->b);
461300bf4279Sespie       s->b = s->e = s->p = NULL;
461400bf4279Sespie     }
461500bf4279Sespie }
461600bf4279Sespie 
461700bf4279Sespie static void
string_init(string * s)4618*150b7e42Smiod string_init (string *s)
461900bf4279Sespie {
462000bf4279Sespie   s->b = s->p = s->e = NULL;
462100bf4279Sespie }
462200bf4279Sespie 
462300bf4279Sespie static void
string_clear(string * s)4624*150b7e42Smiod string_clear (string *s)
462500bf4279Sespie {
462600bf4279Sespie   s->p = s->b;
462700bf4279Sespie }
462800bf4279Sespie 
462900bf4279Sespie #if 0
463000bf4279Sespie 
463100bf4279Sespie static int
4632*150b7e42Smiod string_empty (string *s)
463300bf4279Sespie {
463400bf4279Sespie   return (s->b == s->p);
463500bf4279Sespie }
463600bf4279Sespie 
463700bf4279Sespie #endif
463800bf4279Sespie 
463900bf4279Sespie static void
string_append(string * p,const char * s)4640*150b7e42Smiod string_append (string *p, const char *s)
464100bf4279Sespie {
464200bf4279Sespie   int n;
464300bf4279Sespie   if (s == NULL || *s == '\0')
464400bf4279Sespie     return;
464500bf4279Sespie   n = strlen (s);
464600bf4279Sespie   string_need (p, n);
464700bf4279Sespie   memcpy (p->p, s, n);
464800bf4279Sespie   p->p += n;
464900bf4279Sespie }
465000bf4279Sespie 
465100bf4279Sespie static void
string_appends(string * p,string * s)4652*150b7e42Smiod string_appends (string *p, string *s)
465300bf4279Sespie {
465400bf4279Sespie   int n;
465500bf4279Sespie 
465600bf4279Sespie   if (s->b != s->p)
465700bf4279Sespie     {
465800bf4279Sespie       n = s->p - s->b;
465900bf4279Sespie       string_need (p, n);
466000bf4279Sespie       memcpy (p->p, s->b, n);
466100bf4279Sespie       p->p += n;
466200bf4279Sespie     }
466300bf4279Sespie }
466400bf4279Sespie 
466500bf4279Sespie static void
string_appendn(string * p,const char * s,int n)4666*150b7e42Smiod string_appendn (string *p, const char *s, int n)
466700bf4279Sespie {
466800bf4279Sespie   if (n != 0)
466900bf4279Sespie     {
467000bf4279Sespie       string_need (p, n);
467100bf4279Sespie       memcpy (p->p, s, n);
467200bf4279Sespie       p->p += n;
467300bf4279Sespie     }
467400bf4279Sespie }
467500bf4279Sespie 
467600bf4279Sespie static void
string_prepend(string * p,const char * s)4677*150b7e42Smiod string_prepend (string *p, const char *s)
467800bf4279Sespie {
467900bf4279Sespie   if (s != NULL && *s != '\0')
468000bf4279Sespie     {
468100bf4279Sespie       string_prependn (p, s, strlen (s));
468200bf4279Sespie     }
468300bf4279Sespie }
468400bf4279Sespie 
468500bf4279Sespie static void
string_prepends(string * p,string * s)4686*150b7e42Smiod string_prepends (string *p, string *s)
468700bf4279Sespie {
468800bf4279Sespie   if (s->b != s->p)
468900bf4279Sespie     {
469000bf4279Sespie       string_prependn (p, s->b, s->p - s->b);
469100bf4279Sespie     }
469200bf4279Sespie }
469300bf4279Sespie 
469400bf4279Sespie static void
string_prependn(string * p,const char * s,int n)4695*150b7e42Smiod string_prependn (string *p, const char *s, int n)
469600bf4279Sespie {
469700bf4279Sespie   char *q;
469800bf4279Sespie 
469900bf4279Sespie   if (n != 0)
470000bf4279Sespie     {
470100bf4279Sespie       string_need (p, n);
470200bf4279Sespie       for (q = p->p - 1; q >= p->b; q--)
470300bf4279Sespie 	{
470400bf4279Sespie 	  q[n] = q[0];
470500bf4279Sespie 	}
470600bf4279Sespie       memcpy (p->b, s, n);
470700bf4279Sespie       p->p += n;
470800bf4279Sespie     }
470900bf4279Sespie }
471000bf4279Sespie 
471100bf4279Sespie static void
string_append_template_idx(string * s,int idx)4712*150b7e42Smiod string_append_template_idx (string *s, int idx)
471300bf4279Sespie {
471437c53322Sespie   char buf[INTBUF_SIZE + 1 /* 'T' */];
471597490679Sespie   snprintf(buf, sizeof buf, "T%d", idx);
471637c53322Sespie   string_append (s, buf);
471700bf4279Sespie }
4718