15796c8dcSSimon Schubert /* Demangler for GNU C++
25796c8dcSSimon Schubert    Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
3*c50c785cSJohn Marino    2000, 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
45796c8dcSSimon Schubert    Written by James Clark (jjc@jclark.uucp)
55796c8dcSSimon Schubert    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
65796c8dcSSimon Schubert    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
75796c8dcSSimon Schubert 
85796c8dcSSimon Schubert This file is part of the libiberty library.
95796c8dcSSimon Schubert Libiberty is free software; you can redistribute it and/or
105796c8dcSSimon Schubert modify it under the terms of the GNU Library General Public
115796c8dcSSimon Schubert License as published by the Free Software Foundation; either
125796c8dcSSimon Schubert version 2 of the License, or (at your option) any later version.
135796c8dcSSimon Schubert 
145796c8dcSSimon Schubert In addition to the permissions in the GNU Library General Public
155796c8dcSSimon Schubert License, the Free Software Foundation gives you unlimited permission
165796c8dcSSimon Schubert to link the compiled version of this file into combinations with other
175796c8dcSSimon Schubert programs, and to distribute those combinations without any restriction
185796c8dcSSimon Schubert coming from the use of this file.  (The Library Public License
195796c8dcSSimon Schubert restrictions do apply in other respects; for example, they cover
205796c8dcSSimon Schubert modification of the file, and distribution when not linked into a
215796c8dcSSimon Schubert combined executable.)
225796c8dcSSimon Schubert 
235796c8dcSSimon Schubert Libiberty is distributed in the hope that it will be useful,
245796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
255796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
265796c8dcSSimon Schubert Library General Public License for more details.
275796c8dcSSimon Schubert 
285796c8dcSSimon Schubert You should have received a copy of the GNU Library General Public
295796c8dcSSimon Schubert License along with libiberty; see the file COPYING.LIB.  If
305796c8dcSSimon Schubert not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
315796c8dcSSimon Schubert Boston, MA 02110-1301, USA.  */
325796c8dcSSimon Schubert 
335796c8dcSSimon Schubert /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
345796c8dcSSimon Schubert 
355796c8dcSSimon Schubert    This file imports xmalloc and xrealloc, which are like malloc and
365796c8dcSSimon Schubert    realloc except that they generate a fatal error if there is no
375796c8dcSSimon Schubert    available memory.  */
385796c8dcSSimon Schubert 
395796c8dcSSimon Schubert /* This file lives in both GCC and libiberty.  When making changes, please
405796c8dcSSimon Schubert    try not to break either.  */
415796c8dcSSimon Schubert 
425796c8dcSSimon Schubert #ifdef HAVE_CONFIG_H
435796c8dcSSimon Schubert #include "config.h"
445796c8dcSSimon Schubert #endif
455796c8dcSSimon Schubert 
465796c8dcSSimon Schubert #include "safe-ctype.h"
475796c8dcSSimon Schubert 
485796c8dcSSimon Schubert #include <sys/types.h>
495796c8dcSSimon Schubert #include <string.h>
505796c8dcSSimon Schubert #include <stdio.h>
515796c8dcSSimon Schubert 
525796c8dcSSimon Schubert #ifdef HAVE_STDLIB_H
535796c8dcSSimon Schubert #include <stdlib.h>
545796c8dcSSimon Schubert #else
555796c8dcSSimon Schubert void * malloc ();
565796c8dcSSimon Schubert void * realloc ();
575796c8dcSSimon Schubert #endif
585796c8dcSSimon Schubert 
595796c8dcSSimon Schubert #include <demangle.h>
605796c8dcSSimon Schubert #undef CURRENT_DEMANGLING_STYLE
615796c8dcSSimon Schubert #define CURRENT_DEMANGLING_STYLE work->options
625796c8dcSSimon Schubert 
635796c8dcSSimon Schubert #include "libiberty.h"
645796c8dcSSimon Schubert 
655796c8dcSSimon Schubert #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
665796c8dcSSimon Schubert 
675796c8dcSSimon Schubert /* A value at least one greater than the maximum number of characters
685796c8dcSSimon Schubert    that will be output when using the `%d' format with `printf'.  */
695796c8dcSSimon Schubert #define INTBUF_SIZE 32
705796c8dcSSimon Schubert 
715796c8dcSSimon Schubert extern void fancy_abort (void) ATTRIBUTE_NORETURN;
725796c8dcSSimon Schubert 
735796c8dcSSimon Schubert /* In order to allow a single demangler executable to demangle strings
745796c8dcSSimon Schubert    using various common values of CPLUS_MARKER, as well as any specific
755796c8dcSSimon Schubert    one set at compile time, we maintain a string containing all the
765796c8dcSSimon Schubert    commonly used ones, and check to see if the marker we are looking for
775796c8dcSSimon Schubert    is in that string.  CPLUS_MARKER is usually '$' on systems where the
785796c8dcSSimon Schubert    assembler can deal with that.  Where the assembler can't, it's usually
795796c8dcSSimon Schubert    '.' (but on many systems '.' is used for other things).  We put the
805796c8dcSSimon Schubert    current defined CPLUS_MARKER first (which defaults to '$'), followed
815796c8dcSSimon Schubert    by the next most common value, followed by an explicit '$' in case
825796c8dcSSimon Schubert    the value of CPLUS_MARKER is not '$'.
835796c8dcSSimon Schubert 
845796c8dcSSimon Schubert    We could avoid this if we could just get g++ to tell us what the actual
855796c8dcSSimon Schubert    cplus marker character is as part of the debug information, perhaps by
865796c8dcSSimon Schubert    ensuring that it is the character that terminates the gcc<n>_compiled
875796c8dcSSimon Schubert    marker symbol (FIXME).  */
885796c8dcSSimon Schubert 
895796c8dcSSimon Schubert #if !defined (CPLUS_MARKER)
905796c8dcSSimon Schubert #define CPLUS_MARKER '$'
915796c8dcSSimon Schubert #endif
925796c8dcSSimon Schubert 
935796c8dcSSimon Schubert enum demangling_styles current_demangling_style = auto_demangling;
945796c8dcSSimon Schubert 
955796c8dcSSimon Schubert static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
965796c8dcSSimon Schubert 
975796c8dcSSimon Schubert static char char_str[2] = { '\000', '\000' };
985796c8dcSSimon Schubert 
995796c8dcSSimon Schubert void
set_cplus_marker_for_demangling(int ch)1005796c8dcSSimon Schubert set_cplus_marker_for_demangling (int ch)
1015796c8dcSSimon Schubert {
1025796c8dcSSimon Schubert   cplus_markers[0] = ch;
1035796c8dcSSimon Schubert }
1045796c8dcSSimon Schubert 
1055796c8dcSSimon Schubert typedef struct string		/* Beware: these aren't required to be */
1065796c8dcSSimon Schubert {				/*  '\0' terminated.  */
1075796c8dcSSimon Schubert   char *b;			/* pointer to start of string */
1085796c8dcSSimon Schubert   char *p;			/* pointer after last character */
1095796c8dcSSimon Schubert   char *e;			/* pointer after end of allocated space */
1105796c8dcSSimon Schubert } string;
1115796c8dcSSimon Schubert 
1125796c8dcSSimon Schubert /* Stuff that is shared between sub-routines.
1135796c8dcSSimon Schubert    Using a shared structure allows cplus_demangle to be reentrant.  */
1145796c8dcSSimon Schubert 
1155796c8dcSSimon Schubert struct work_stuff
1165796c8dcSSimon Schubert {
1175796c8dcSSimon Schubert   int options;
1185796c8dcSSimon Schubert   char **typevec;
1195796c8dcSSimon Schubert   char **ktypevec;
1205796c8dcSSimon Schubert   char **btypevec;
1215796c8dcSSimon Schubert   int numk;
1225796c8dcSSimon Schubert   int numb;
1235796c8dcSSimon Schubert   int ksize;
1245796c8dcSSimon Schubert   int bsize;
1255796c8dcSSimon Schubert   int ntypes;
1265796c8dcSSimon Schubert   int typevec_size;
1275796c8dcSSimon Schubert   int constructor;
1285796c8dcSSimon Schubert   int destructor;
1295796c8dcSSimon Schubert   int static_type;	/* A static member function */
1305796c8dcSSimon Schubert   int temp_start;       /* index in demangled to start of template args */
1315796c8dcSSimon Schubert   int type_quals;       /* The type qualifiers.  */
1325796c8dcSSimon Schubert   int dllimported;	/* Symbol imported from a PE DLL */
1335796c8dcSSimon Schubert   char **tmpl_argvec;   /* Template function arguments. */
1345796c8dcSSimon Schubert   int ntmpl_args;       /* The number of template function arguments. */
1355796c8dcSSimon Schubert   int forgetting_types; /* Nonzero if we are not remembering the types
1365796c8dcSSimon Schubert 			   we see.  */
1375796c8dcSSimon Schubert   string* previous_argument; /* The last function argument demangled.  */
1385796c8dcSSimon Schubert   int nrepeats;         /* The number of times to repeat the previous
1395796c8dcSSimon Schubert 			   argument.  */
1405796c8dcSSimon Schubert };
1415796c8dcSSimon Schubert 
1425796c8dcSSimon Schubert #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
1435796c8dcSSimon Schubert #define PRINT_ARG_TYPES       (work -> options & DMGL_PARAMS)
1445796c8dcSSimon Schubert 
1455796c8dcSSimon Schubert static const struct optable
1465796c8dcSSimon Schubert {
1475796c8dcSSimon Schubert   const char *const in;
1485796c8dcSSimon Schubert   const char *const out;
1495796c8dcSSimon Schubert   const int flags;
1505796c8dcSSimon Schubert } optable[] = {
1515796c8dcSSimon Schubert   {"nw",	  " new",	DMGL_ANSI},	/* new (1.92,	 ansi) */
1525796c8dcSSimon Schubert   {"dl",	  " delete",	DMGL_ANSI},	/* new (1.92,	 ansi) */
1535796c8dcSSimon Schubert   {"new",	  " new",	0},		/* old (1.91,	 and 1.x) */
1545796c8dcSSimon Schubert   {"delete",	  " delete",	0},		/* old (1.91,	 and 1.x) */
1555796c8dcSSimon Schubert   {"vn",	  " new []",	DMGL_ANSI},	/* GNU, pending ansi */
1565796c8dcSSimon Schubert   {"vd",	  " delete []",	DMGL_ANSI},	/* GNU, pending ansi */
1575796c8dcSSimon Schubert   {"as",	  "=",		DMGL_ANSI},	/* ansi */
1585796c8dcSSimon Schubert   {"ne",	  "!=",		DMGL_ANSI},	/* old, ansi */
1595796c8dcSSimon Schubert   {"eq",	  "==",		DMGL_ANSI},	/* old,	ansi */
1605796c8dcSSimon Schubert   {"ge",	  ">=",		DMGL_ANSI},	/* old,	ansi */
1615796c8dcSSimon Schubert   {"gt",	  ">",		DMGL_ANSI},	/* old,	ansi */
1625796c8dcSSimon Schubert   {"le",	  "<=",		DMGL_ANSI},	/* old,	ansi */
1635796c8dcSSimon Schubert   {"lt",	  "<",		DMGL_ANSI},	/* old,	ansi */
1645796c8dcSSimon Schubert   {"plus",	  "+",		0},		/* old */
1655796c8dcSSimon Schubert   {"pl",	  "+",		DMGL_ANSI},	/* ansi */
1665796c8dcSSimon Schubert   {"apl",	  "+=",		DMGL_ANSI},	/* ansi */
1675796c8dcSSimon Schubert   {"minus",	  "-",		0},		/* old */
1685796c8dcSSimon Schubert   {"mi",	  "-",		DMGL_ANSI},	/* ansi */
1695796c8dcSSimon Schubert   {"ami",	  "-=",		DMGL_ANSI},	/* ansi */
1705796c8dcSSimon Schubert   {"mult",	  "*",		0},		/* old */
1715796c8dcSSimon Schubert   {"ml",	  "*",		DMGL_ANSI},	/* ansi */
1725796c8dcSSimon Schubert   {"amu",	  "*=",		DMGL_ANSI},	/* ansi (ARM/Lucid) */
1735796c8dcSSimon Schubert   {"aml",	  "*=",		DMGL_ANSI},	/* ansi (GNU/g++) */
1745796c8dcSSimon Schubert   {"convert",	  "+",		0},		/* old (unary +) */
1755796c8dcSSimon Schubert   {"negate",	  "-",		0},		/* old (unary -) */
1765796c8dcSSimon Schubert   {"trunc_mod",	  "%",		0},		/* old */
1775796c8dcSSimon Schubert   {"md",	  "%",		DMGL_ANSI},	/* ansi */
1785796c8dcSSimon Schubert   {"amd",	  "%=",		DMGL_ANSI},	/* ansi */
1795796c8dcSSimon Schubert   {"trunc_div",	  "/",		0},		/* old */
1805796c8dcSSimon Schubert   {"dv",	  "/",		DMGL_ANSI},	/* ansi */
1815796c8dcSSimon Schubert   {"adv",	  "/=",		DMGL_ANSI},	/* ansi */
1825796c8dcSSimon Schubert   {"truth_andif", "&&",		0},		/* old */
1835796c8dcSSimon Schubert   {"aa",	  "&&",		DMGL_ANSI},	/* ansi */
1845796c8dcSSimon Schubert   {"truth_orif",  "||",		0},		/* old */
1855796c8dcSSimon Schubert   {"oo",	  "||",		DMGL_ANSI},	/* ansi */
1865796c8dcSSimon Schubert   {"truth_not",	  "!",		0},		/* old */
1875796c8dcSSimon Schubert   {"nt",	  "!",		DMGL_ANSI},	/* ansi */
1885796c8dcSSimon Schubert   {"postincrement","++",	0},		/* old */
1895796c8dcSSimon Schubert   {"pp",	  "++",		DMGL_ANSI},	/* ansi */
1905796c8dcSSimon Schubert   {"postdecrement","--",	0},		/* old */
1915796c8dcSSimon Schubert   {"mm",	  "--",		DMGL_ANSI},	/* ansi */
1925796c8dcSSimon Schubert   {"bit_ior",	  "|",		0},		/* old */
1935796c8dcSSimon Schubert   {"or",	  "|",		DMGL_ANSI},	/* ansi */
1945796c8dcSSimon Schubert   {"aor",	  "|=",		DMGL_ANSI},	/* ansi */
1955796c8dcSSimon Schubert   {"bit_xor",	  "^",		0},		/* old */
1965796c8dcSSimon Schubert   {"er",	  "^",		DMGL_ANSI},	/* ansi */
1975796c8dcSSimon Schubert   {"aer",	  "^=",		DMGL_ANSI},	/* ansi */
1985796c8dcSSimon Schubert   {"bit_and",	  "&",		0},		/* old */
1995796c8dcSSimon Schubert   {"ad",	  "&",		DMGL_ANSI},	/* ansi */
2005796c8dcSSimon Schubert   {"aad",	  "&=",		DMGL_ANSI},	/* ansi */
2015796c8dcSSimon Schubert   {"bit_not",	  "~",		0},		/* old */
2025796c8dcSSimon Schubert   {"co",	  "~",		DMGL_ANSI},	/* ansi */
2035796c8dcSSimon Schubert   {"call",	  "()",		0},		/* old */
2045796c8dcSSimon Schubert   {"cl",	  "()",		DMGL_ANSI},	/* ansi */
2055796c8dcSSimon Schubert   {"alshift",	  "<<",		0},		/* old */
2065796c8dcSSimon Schubert   {"ls",	  "<<",		DMGL_ANSI},	/* ansi */
2075796c8dcSSimon Schubert   {"als",	  "<<=",	DMGL_ANSI},	/* ansi */
2085796c8dcSSimon Schubert   {"arshift",	  ">>",		0},		/* old */
2095796c8dcSSimon Schubert   {"rs",	  ">>",		DMGL_ANSI},	/* ansi */
2105796c8dcSSimon Schubert   {"ars",	  ">>=",	DMGL_ANSI},	/* ansi */
2115796c8dcSSimon Schubert   {"component",	  "->",		0},		/* old */
2125796c8dcSSimon Schubert   {"pt",	  "->",		DMGL_ANSI},	/* ansi; Lucid C++ form */
2135796c8dcSSimon Schubert   {"rf",	  "->",		DMGL_ANSI},	/* ansi; ARM/GNU form */
2145796c8dcSSimon Schubert   {"indirect",	  "*",		0},		/* old */
2155796c8dcSSimon Schubert   {"method_call",  "->()",	0},		/* old */
2165796c8dcSSimon Schubert   {"addr",	  "&",		0},		/* old (unary &) */
2175796c8dcSSimon Schubert   {"array",	  "[]",		0},		/* old */
2185796c8dcSSimon Schubert   {"vc",	  "[]",		DMGL_ANSI},	/* ansi */
2195796c8dcSSimon Schubert   {"compound",	  ", ",		0},		/* old */
2205796c8dcSSimon Schubert   {"cm",	  ", ",		DMGL_ANSI},	/* ansi */
2215796c8dcSSimon Schubert   {"cond",	  "?:",		0},		/* old */
2225796c8dcSSimon Schubert   {"cn",	  "?:",		DMGL_ANSI},	/* pseudo-ansi */
2235796c8dcSSimon Schubert   {"max",	  ">?",		0},		/* old */
2245796c8dcSSimon Schubert   {"mx",	  ">?",		DMGL_ANSI},	/* pseudo-ansi */
2255796c8dcSSimon Schubert   {"min",	  "<?",		0},		/* old */
2265796c8dcSSimon Schubert   {"mn",	  "<?",		DMGL_ANSI},	/* pseudo-ansi */
2275796c8dcSSimon Schubert   {"nop",	  "",		0},		/* old (for operator=) */
2285796c8dcSSimon Schubert   {"rm",	  "->*",	DMGL_ANSI},	/* ansi */
2295796c8dcSSimon Schubert   {"sz",          "sizeof ",    DMGL_ANSI}      /* pseudo-ansi */
2305796c8dcSSimon Schubert };
2315796c8dcSSimon Schubert 
2325796c8dcSSimon Schubert /* These values are used to indicate the various type varieties.
2335796c8dcSSimon Schubert    They are all non-zero so that they can be used as `success'
2345796c8dcSSimon Schubert    values.  */
2355796c8dcSSimon Schubert typedef enum type_kind_t
2365796c8dcSSimon Schubert {
2375796c8dcSSimon Schubert   tk_none,
2385796c8dcSSimon Schubert   tk_pointer,
2395796c8dcSSimon Schubert   tk_reference,
2405796c8dcSSimon Schubert   tk_integral,
2415796c8dcSSimon Schubert   tk_bool,
2425796c8dcSSimon Schubert   tk_char,
2435796c8dcSSimon Schubert   tk_real
2445796c8dcSSimon Schubert } type_kind_t;
2455796c8dcSSimon Schubert 
2465796c8dcSSimon Schubert const struct demangler_engine libiberty_demanglers[] =
2475796c8dcSSimon Schubert {
2485796c8dcSSimon Schubert   {
2495796c8dcSSimon Schubert     NO_DEMANGLING_STYLE_STRING,
2505796c8dcSSimon Schubert     no_demangling,
2515796c8dcSSimon Schubert     "Demangling disabled"
2525796c8dcSSimon Schubert   }
2535796c8dcSSimon Schubert   ,
2545796c8dcSSimon Schubert   {
2555796c8dcSSimon Schubert     AUTO_DEMANGLING_STYLE_STRING,
2565796c8dcSSimon Schubert       auto_demangling,
2575796c8dcSSimon Schubert       "Automatic selection based on executable"
2585796c8dcSSimon Schubert   }
2595796c8dcSSimon Schubert   ,
2605796c8dcSSimon Schubert   {
2615796c8dcSSimon Schubert     GNU_DEMANGLING_STYLE_STRING,
2625796c8dcSSimon Schubert       gnu_demangling,
2635796c8dcSSimon Schubert       "GNU (g++) style demangling"
2645796c8dcSSimon Schubert   }
2655796c8dcSSimon Schubert   ,
2665796c8dcSSimon Schubert   {
2675796c8dcSSimon Schubert     LUCID_DEMANGLING_STYLE_STRING,
2685796c8dcSSimon Schubert       lucid_demangling,
2695796c8dcSSimon Schubert       "Lucid (lcc) style demangling"
2705796c8dcSSimon Schubert   }
2715796c8dcSSimon Schubert   ,
2725796c8dcSSimon Schubert   {
2735796c8dcSSimon Schubert     ARM_DEMANGLING_STYLE_STRING,
2745796c8dcSSimon Schubert       arm_demangling,
2755796c8dcSSimon Schubert       "ARM style demangling"
2765796c8dcSSimon Schubert   }
2775796c8dcSSimon Schubert   ,
2785796c8dcSSimon Schubert   {
2795796c8dcSSimon Schubert     HP_DEMANGLING_STYLE_STRING,
2805796c8dcSSimon Schubert       hp_demangling,
2815796c8dcSSimon Schubert       "HP (aCC) style demangling"
2825796c8dcSSimon Schubert   }
2835796c8dcSSimon Schubert   ,
2845796c8dcSSimon Schubert   {
2855796c8dcSSimon Schubert     EDG_DEMANGLING_STYLE_STRING,
2865796c8dcSSimon Schubert       edg_demangling,
2875796c8dcSSimon Schubert       "EDG style demangling"
2885796c8dcSSimon Schubert   }
2895796c8dcSSimon Schubert   ,
2905796c8dcSSimon Schubert   {
2915796c8dcSSimon Schubert     GNU_V3_DEMANGLING_STYLE_STRING,
2925796c8dcSSimon Schubert     gnu_v3_demangling,
2935796c8dcSSimon Schubert     "GNU (g++) V3 ABI-style demangling"
2945796c8dcSSimon Schubert   }
2955796c8dcSSimon Schubert   ,
2965796c8dcSSimon Schubert   {
2975796c8dcSSimon Schubert     JAVA_DEMANGLING_STYLE_STRING,
2985796c8dcSSimon Schubert     java_demangling,
2995796c8dcSSimon Schubert     "Java style demangling"
3005796c8dcSSimon Schubert   }
3015796c8dcSSimon Schubert   ,
3025796c8dcSSimon Schubert   {
3035796c8dcSSimon Schubert     GNAT_DEMANGLING_STYLE_STRING,
3045796c8dcSSimon Schubert     gnat_demangling,
3055796c8dcSSimon Schubert     "GNAT style demangling"
3065796c8dcSSimon Schubert   }
3075796c8dcSSimon Schubert   ,
3085796c8dcSSimon Schubert   {
3095796c8dcSSimon Schubert     NULL, unknown_demangling, NULL
3105796c8dcSSimon Schubert   }
3115796c8dcSSimon Schubert };
3125796c8dcSSimon Schubert 
3135796c8dcSSimon Schubert #define STRING_EMPTY(str)	((str) -> b == (str) -> p)
3145796c8dcSSimon Schubert #define APPEND_BLANK(str)	{if (!STRING_EMPTY(str)) \
3155796c8dcSSimon Schubert     string_append(str, " ");}
3165796c8dcSSimon Schubert #define LEN_STRING(str)         ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
3175796c8dcSSimon Schubert 
3185796c8dcSSimon Schubert /* The scope separator appropriate for the language being demangled.  */
3195796c8dcSSimon Schubert 
3205796c8dcSSimon Schubert #define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
3215796c8dcSSimon Schubert 
3225796c8dcSSimon Schubert #define ARM_VTABLE_STRING "__vtbl__"	/* Lucid/ARM virtual table prefix */
3235796c8dcSSimon Schubert #define ARM_VTABLE_STRLEN 8		/* strlen (ARM_VTABLE_STRING) */
3245796c8dcSSimon Schubert 
3255796c8dcSSimon Schubert /* Prototypes for local functions */
3265796c8dcSSimon Schubert 
3275796c8dcSSimon Schubert static void delete_work_stuff (struct work_stuff *);
3285796c8dcSSimon Schubert 
3295796c8dcSSimon Schubert static void delete_non_B_K_work_stuff (struct work_stuff *);
3305796c8dcSSimon Schubert 
3315796c8dcSSimon Schubert static char *mop_up (struct work_stuff *, string *, int);
3325796c8dcSSimon Schubert 
3335796c8dcSSimon Schubert static void squangle_mop_up (struct work_stuff *);
3345796c8dcSSimon Schubert 
3355796c8dcSSimon Schubert static void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *);
3365796c8dcSSimon Schubert 
3375796c8dcSSimon Schubert #if 0
3385796c8dcSSimon Schubert static int
3395796c8dcSSimon Schubert demangle_method_args (struct work_stuff *, const char **, string *);
3405796c8dcSSimon Schubert #endif
3415796c8dcSSimon Schubert 
3425796c8dcSSimon Schubert static char *
3435796c8dcSSimon Schubert internal_cplus_demangle (struct work_stuff *, const char *);
3445796c8dcSSimon Schubert 
3455796c8dcSSimon Schubert static int
3465796c8dcSSimon Schubert demangle_template_template_parm (struct work_stuff *work,
3475796c8dcSSimon Schubert                                  const char **, string *);
3485796c8dcSSimon Schubert 
3495796c8dcSSimon Schubert static int
3505796c8dcSSimon Schubert demangle_template (struct work_stuff *work, const char **, string *,
3515796c8dcSSimon Schubert                    string *, int, int);
3525796c8dcSSimon Schubert 
3535796c8dcSSimon Schubert static int
3545796c8dcSSimon Schubert arm_pt (struct work_stuff *, const char *, int, const char **,
3555796c8dcSSimon Schubert         const char **);
3565796c8dcSSimon Schubert 
3575796c8dcSSimon Schubert static int
3585796c8dcSSimon Schubert demangle_class_name (struct work_stuff *, const char **, string *);
3595796c8dcSSimon Schubert 
3605796c8dcSSimon Schubert static int
3615796c8dcSSimon Schubert demangle_qualified (struct work_stuff *, const char **, string *,
3625796c8dcSSimon Schubert                     int, int);
3635796c8dcSSimon Schubert 
3645796c8dcSSimon Schubert static int demangle_class (struct work_stuff *, const char **, string *);
3655796c8dcSSimon Schubert 
3665796c8dcSSimon Schubert static int demangle_fund_type (struct work_stuff *, const char **, string *);
3675796c8dcSSimon Schubert 
3685796c8dcSSimon Schubert static int demangle_signature (struct work_stuff *, const char **, string *);
3695796c8dcSSimon Schubert 
3705796c8dcSSimon Schubert static int demangle_prefix (struct work_stuff *, const char **, string *);
3715796c8dcSSimon Schubert 
3725796c8dcSSimon Schubert static int gnu_special (struct work_stuff *, const char **, string *);
3735796c8dcSSimon Schubert 
3745796c8dcSSimon Schubert static int arm_special (const char **, string *);
3755796c8dcSSimon Schubert 
3765796c8dcSSimon Schubert static void string_need (string *, int);
3775796c8dcSSimon Schubert 
3785796c8dcSSimon Schubert static void string_delete (string *);
3795796c8dcSSimon Schubert 
3805796c8dcSSimon Schubert static void
3815796c8dcSSimon Schubert string_init (string *);
3825796c8dcSSimon Schubert 
3835796c8dcSSimon Schubert static void string_clear (string *);
3845796c8dcSSimon Schubert 
3855796c8dcSSimon Schubert #if 0
3865796c8dcSSimon Schubert static int string_empty (string *);
3875796c8dcSSimon Schubert #endif
3885796c8dcSSimon Schubert 
3895796c8dcSSimon Schubert static void string_append (string *, const char *);
3905796c8dcSSimon Schubert 
3915796c8dcSSimon Schubert static void string_appends (string *, string *);
3925796c8dcSSimon Schubert 
3935796c8dcSSimon Schubert static void string_appendn (string *, const char *, int);
3945796c8dcSSimon Schubert 
3955796c8dcSSimon Schubert static void string_prepend (string *, const char *);
3965796c8dcSSimon Schubert 
3975796c8dcSSimon Schubert static void string_prependn (string *, const char *, int);
3985796c8dcSSimon Schubert 
3995796c8dcSSimon Schubert static void string_append_template_idx (string *, int);
4005796c8dcSSimon Schubert 
4015796c8dcSSimon Schubert static int get_count (const char **, int *);
4025796c8dcSSimon Schubert 
4035796c8dcSSimon Schubert static int consume_count (const char **);
4045796c8dcSSimon Schubert 
4055796c8dcSSimon Schubert static int consume_count_with_underscores (const char**);
4065796c8dcSSimon Schubert 
4075796c8dcSSimon Schubert static int demangle_args (struct work_stuff *, const char **, string *);
4085796c8dcSSimon Schubert 
4095796c8dcSSimon Schubert static int demangle_nested_args (struct work_stuff*, const char**, string*);
4105796c8dcSSimon Schubert 
4115796c8dcSSimon Schubert static int do_type (struct work_stuff *, const char **, string *);
4125796c8dcSSimon Schubert 
4135796c8dcSSimon Schubert static int do_arg (struct work_stuff *, const char **, string *);
4145796c8dcSSimon Schubert 
4155796c8dcSSimon Schubert static int
4165796c8dcSSimon Schubert demangle_function_name (struct work_stuff *, const char **, string *,
4175796c8dcSSimon Schubert                         const char *);
4185796c8dcSSimon Schubert 
4195796c8dcSSimon Schubert static int
4205796c8dcSSimon Schubert iterate_demangle_function (struct work_stuff *,
4215796c8dcSSimon Schubert                            const char **, string *, const char *);
4225796c8dcSSimon Schubert 
4235796c8dcSSimon Schubert static void remember_type (struct work_stuff *, const char *, int);
4245796c8dcSSimon Schubert 
4255796c8dcSSimon Schubert static void remember_Btype (struct work_stuff *, const char *, int, int);
4265796c8dcSSimon Schubert 
4275796c8dcSSimon Schubert static int register_Btype (struct work_stuff *);
4285796c8dcSSimon Schubert 
4295796c8dcSSimon Schubert static void remember_Ktype (struct work_stuff *, const char *, int);
4305796c8dcSSimon Schubert 
4315796c8dcSSimon Schubert static void forget_types (struct work_stuff *);
4325796c8dcSSimon Schubert 
4335796c8dcSSimon Schubert static void forget_B_and_K_types (struct work_stuff *);
4345796c8dcSSimon Schubert 
4355796c8dcSSimon Schubert static void string_prepends (string *, string *);
4365796c8dcSSimon Schubert 
4375796c8dcSSimon Schubert static int
4385796c8dcSSimon Schubert demangle_template_value_parm (struct work_stuff*, const char**,
4395796c8dcSSimon Schubert                               string*, type_kind_t);
4405796c8dcSSimon Schubert 
4415796c8dcSSimon Schubert static int
4425796c8dcSSimon Schubert do_hpacc_template_const_value (struct work_stuff *, const char **, string *);
4435796c8dcSSimon Schubert 
4445796c8dcSSimon Schubert static int
4455796c8dcSSimon Schubert do_hpacc_template_literal (struct work_stuff *, const char **, string *);
4465796c8dcSSimon Schubert 
4475796c8dcSSimon Schubert static int snarf_numeric_literal (const char **, string *);
4485796c8dcSSimon Schubert 
4495796c8dcSSimon Schubert /* There is a TYPE_QUAL value for each type qualifier.  They can be
4505796c8dcSSimon Schubert    combined by bitwise-or to form the complete set of qualifiers for a
4515796c8dcSSimon Schubert    type.  */
4525796c8dcSSimon Schubert 
4535796c8dcSSimon Schubert #define TYPE_UNQUALIFIED   0x0
4545796c8dcSSimon Schubert #define TYPE_QUAL_CONST    0x1
4555796c8dcSSimon Schubert #define TYPE_QUAL_VOLATILE 0x2
4565796c8dcSSimon Schubert #define TYPE_QUAL_RESTRICT 0x4
4575796c8dcSSimon Schubert 
4585796c8dcSSimon Schubert static int code_for_qualifier (int);
4595796c8dcSSimon Schubert 
4605796c8dcSSimon Schubert static const char* qualifier_string (int);
4615796c8dcSSimon Schubert 
4625796c8dcSSimon Schubert static const char* demangle_qualifier (int);
4635796c8dcSSimon Schubert 
4645796c8dcSSimon Schubert static int demangle_expression (struct work_stuff *, const char **, string *,
4655796c8dcSSimon Schubert                                 type_kind_t);
4665796c8dcSSimon Schubert 
4675796c8dcSSimon Schubert static int
4685796c8dcSSimon Schubert demangle_integral_value (struct work_stuff *, const char **, string *);
4695796c8dcSSimon Schubert 
4705796c8dcSSimon Schubert static int
4715796c8dcSSimon Schubert demangle_real_value (struct work_stuff *, const char **, string *);
4725796c8dcSSimon Schubert 
4735796c8dcSSimon Schubert static void
4745796c8dcSSimon Schubert demangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
4755796c8dcSSimon Schubert 
4765796c8dcSSimon Schubert static void
4775796c8dcSSimon Schubert recursively_demangle (struct work_stuff *, const char **, string *, int);
4785796c8dcSSimon Schubert 
4795796c8dcSSimon Schubert /* Translate count to integer, consuming tokens in the process.
4805796c8dcSSimon Schubert    Conversion terminates on the first non-digit character.
4815796c8dcSSimon Schubert 
4825796c8dcSSimon Schubert    Trying to consume something that isn't a count results in no
4835796c8dcSSimon Schubert    consumption of input and a return of -1.
4845796c8dcSSimon Schubert 
4855796c8dcSSimon Schubert    Overflow consumes the rest of the digits, and returns -1.  */
4865796c8dcSSimon Schubert 
4875796c8dcSSimon Schubert static int
consume_count(const char ** type)4885796c8dcSSimon Schubert consume_count (const char **type)
4895796c8dcSSimon Schubert {
4905796c8dcSSimon Schubert   int count = 0;
4915796c8dcSSimon Schubert 
4925796c8dcSSimon Schubert   if (! ISDIGIT ((unsigned char)**type))
4935796c8dcSSimon Schubert     return -1;
4945796c8dcSSimon Schubert 
4955796c8dcSSimon Schubert   while (ISDIGIT ((unsigned char)**type))
4965796c8dcSSimon Schubert     {
4975796c8dcSSimon Schubert       count *= 10;
4985796c8dcSSimon Schubert 
4995796c8dcSSimon Schubert       /* Check for overflow.
5005796c8dcSSimon Schubert 	 We assume that count is represented using two's-complement;
5015796c8dcSSimon Schubert 	 no power of two is divisible by ten, so if an overflow occurs
5025796c8dcSSimon Schubert 	 when multiplying by ten, the result will not be a multiple of
5035796c8dcSSimon Schubert 	 ten.  */
5045796c8dcSSimon Schubert       if ((count % 10) != 0)
5055796c8dcSSimon Schubert 	{
5065796c8dcSSimon Schubert 	  while (ISDIGIT ((unsigned char) **type))
5075796c8dcSSimon Schubert 	    (*type)++;
5085796c8dcSSimon Schubert 	  return -1;
5095796c8dcSSimon Schubert 	}
5105796c8dcSSimon Schubert 
5115796c8dcSSimon Schubert       count += **type - '0';
5125796c8dcSSimon Schubert       (*type)++;
5135796c8dcSSimon Schubert     }
5145796c8dcSSimon Schubert 
5155796c8dcSSimon Schubert   if (count < 0)
5165796c8dcSSimon Schubert     count = -1;
5175796c8dcSSimon Schubert 
5185796c8dcSSimon Schubert   return (count);
5195796c8dcSSimon Schubert }
5205796c8dcSSimon Schubert 
5215796c8dcSSimon Schubert 
5225796c8dcSSimon Schubert /* Like consume_count, but for counts that are preceded and followed
5235796c8dcSSimon Schubert    by '_' if they are greater than 10.  Also, -1 is returned for
5245796c8dcSSimon Schubert    failure, since 0 can be a valid value.  */
5255796c8dcSSimon Schubert 
5265796c8dcSSimon Schubert static int
consume_count_with_underscores(const char ** mangled)5275796c8dcSSimon Schubert consume_count_with_underscores (const char **mangled)
5285796c8dcSSimon Schubert {
5295796c8dcSSimon Schubert   int idx;
5305796c8dcSSimon Schubert 
5315796c8dcSSimon Schubert   if (**mangled == '_')
5325796c8dcSSimon Schubert     {
5335796c8dcSSimon Schubert       (*mangled)++;
5345796c8dcSSimon Schubert       if (!ISDIGIT ((unsigned char)**mangled))
5355796c8dcSSimon Schubert 	return -1;
5365796c8dcSSimon Schubert 
5375796c8dcSSimon Schubert       idx = consume_count (mangled);
5385796c8dcSSimon Schubert       if (**mangled != '_')
5395796c8dcSSimon Schubert 	/* The trailing underscore was missing. */
5405796c8dcSSimon Schubert 	return -1;
5415796c8dcSSimon Schubert 
5425796c8dcSSimon Schubert       (*mangled)++;
5435796c8dcSSimon Schubert     }
5445796c8dcSSimon Schubert   else
5455796c8dcSSimon Schubert     {
5465796c8dcSSimon Schubert       if (**mangled < '0' || **mangled > '9')
5475796c8dcSSimon Schubert 	return -1;
5485796c8dcSSimon Schubert 
5495796c8dcSSimon Schubert       idx = **mangled - '0';
5505796c8dcSSimon Schubert       (*mangled)++;
5515796c8dcSSimon Schubert     }
5525796c8dcSSimon Schubert 
5535796c8dcSSimon Schubert   return idx;
5545796c8dcSSimon Schubert }
5555796c8dcSSimon Schubert 
5565796c8dcSSimon Schubert /* C is the code for a type-qualifier.  Return the TYPE_QUAL
5575796c8dcSSimon Schubert    corresponding to this qualifier.  */
5585796c8dcSSimon Schubert 
5595796c8dcSSimon Schubert static int
code_for_qualifier(int c)5605796c8dcSSimon Schubert code_for_qualifier (int c)
5615796c8dcSSimon Schubert {
5625796c8dcSSimon Schubert   switch (c)
5635796c8dcSSimon Schubert     {
5645796c8dcSSimon Schubert     case 'C':
5655796c8dcSSimon Schubert       return TYPE_QUAL_CONST;
5665796c8dcSSimon Schubert 
5675796c8dcSSimon Schubert     case 'V':
5685796c8dcSSimon Schubert       return TYPE_QUAL_VOLATILE;
5695796c8dcSSimon Schubert 
5705796c8dcSSimon Schubert     case 'u':
5715796c8dcSSimon Schubert       return TYPE_QUAL_RESTRICT;
5725796c8dcSSimon Schubert 
5735796c8dcSSimon Schubert     default:
5745796c8dcSSimon Schubert       break;
5755796c8dcSSimon Schubert     }
5765796c8dcSSimon Schubert 
5775796c8dcSSimon Schubert   /* C was an invalid qualifier.  */
5785796c8dcSSimon Schubert   abort ();
5795796c8dcSSimon Schubert }
5805796c8dcSSimon Schubert 
5815796c8dcSSimon Schubert /* Return the string corresponding to the qualifiers given by
5825796c8dcSSimon Schubert    TYPE_QUALS.  */
5835796c8dcSSimon Schubert 
5845796c8dcSSimon Schubert static const char*
qualifier_string(int type_quals)5855796c8dcSSimon Schubert qualifier_string (int type_quals)
5865796c8dcSSimon Schubert {
5875796c8dcSSimon Schubert   switch (type_quals)
5885796c8dcSSimon Schubert     {
5895796c8dcSSimon Schubert     case TYPE_UNQUALIFIED:
5905796c8dcSSimon Schubert       return "";
5915796c8dcSSimon Schubert 
5925796c8dcSSimon Schubert     case TYPE_QUAL_CONST:
5935796c8dcSSimon Schubert       return "const";
5945796c8dcSSimon Schubert 
5955796c8dcSSimon Schubert     case TYPE_QUAL_VOLATILE:
5965796c8dcSSimon Schubert       return "volatile";
5975796c8dcSSimon Schubert 
5985796c8dcSSimon Schubert     case TYPE_QUAL_RESTRICT:
5995796c8dcSSimon Schubert       return "__restrict";
6005796c8dcSSimon Schubert 
6015796c8dcSSimon Schubert     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
6025796c8dcSSimon Schubert       return "const volatile";
6035796c8dcSSimon Schubert 
6045796c8dcSSimon Schubert     case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
6055796c8dcSSimon Schubert       return "const __restrict";
6065796c8dcSSimon Schubert 
6075796c8dcSSimon Schubert     case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
6085796c8dcSSimon Schubert       return "volatile __restrict";
6095796c8dcSSimon Schubert 
6105796c8dcSSimon Schubert     case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
6115796c8dcSSimon Schubert       return "const volatile __restrict";
6125796c8dcSSimon Schubert 
6135796c8dcSSimon Schubert     default:
6145796c8dcSSimon Schubert       break;
6155796c8dcSSimon Schubert     }
6165796c8dcSSimon Schubert 
6175796c8dcSSimon Schubert   /* TYPE_QUALS was an invalid qualifier set.  */
6185796c8dcSSimon Schubert   abort ();
6195796c8dcSSimon Schubert }
6205796c8dcSSimon Schubert 
6215796c8dcSSimon Schubert /* C is the code for a type-qualifier.  Return the string
6225796c8dcSSimon Schubert    corresponding to this qualifier.  This function should only be
6235796c8dcSSimon Schubert    called with a valid qualifier code.  */
6245796c8dcSSimon Schubert 
6255796c8dcSSimon Schubert static const char*
demangle_qualifier(int c)6265796c8dcSSimon Schubert demangle_qualifier (int c)
6275796c8dcSSimon Schubert {
6285796c8dcSSimon Schubert   return qualifier_string (code_for_qualifier (c));
6295796c8dcSSimon Schubert }
6305796c8dcSSimon Schubert 
6315796c8dcSSimon Schubert int
cplus_demangle_opname(const char * opname,char * result,int options)6325796c8dcSSimon Schubert cplus_demangle_opname (const char *opname, char *result, int options)
6335796c8dcSSimon Schubert {
6345796c8dcSSimon Schubert   int len, len1, ret;
6355796c8dcSSimon Schubert   string type;
6365796c8dcSSimon Schubert   struct work_stuff work[1];
6375796c8dcSSimon Schubert   const char *tem;
6385796c8dcSSimon Schubert 
6395796c8dcSSimon Schubert   len = strlen(opname);
6405796c8dcSSimon Schubert   result[0] = '\0';
6415796c8dcSSimon Schubert   ret = 0;
6425796c8dcSSimon Schubert   memset ((char *) work, 0, sizeof (work));
6435796c8dcSSimon Schubert   work->options = options;
6445796c8dcSSimon Schubert 
6455796c8dcSSimon Schubert   if (opname[0] == '_' && opname[1] == '_'
6465796c8dcSSimon Schubert       && opname[2] == 'o' && opname[3] == 'p')
6475796c8dcSSimon Schubert     {
6485796c8dcSSimon Schubert       /* ANSI.  */
6495796c8dcSSimon Schubert       /* type conversion operator.  */
6505796c8dcSSimon Schubert       tem = opname + 4;
6515796c8dcSSimon Schubert       if (do_type (work, &tem, &type))
6525796c8dcSSimon Schubert 	{
6535796c8dcSSimon Schubert 	  strcat (result, "operator ");
6545796c8dcSSimon Schubert 	  strncat (result, type.b, type.p - type.b);
6555796c8dcSSimon Schubert 	  string_delete (&type);
6565796c8dcSSimon Schubert 	  ret = 1;
6575796c8dcSSimon Schubert 	}
6585796c8dcSSimon Schubert     }
6595796c8dcSSimon Schubert   else if (opname[0] == '_' && opname[1] == '_'
6605796c8dcSSimon Schubert 	   && ISLOWER((unsigned char)opname[2])
6615796c8dcSSimon Schubert 	   && ISLOWER((unsigned char)opname[3]))
6625796c8dcSSimon Schubert     {
6635796c8dcSSimon Schubert       if (opname[4] == '\0')
6645796c8dcSSimon Schubert 	{
6655796c8dcSSimon Schubert 	  /* Operator.  */
6665796c8dcSSimon Schubert 	  size_t i;
6675796c8dcSSimon Schubert 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
6685796c8dcSSimon Schubert 	    {
6695796c8dcSSimon Schubert 	      if (strlen (optable[i].in) == 2
6705796c8dcSSimon Schubert 		  && memcmp (optable[i].in, opname + 2, 2) == 0)
6715796c8dcSSimon Schubert 		{
6725796c8dcSSimon Schubert 		  strcat (result, "operator");
6735796c8dcSSimon Schubert 		  strcat (result, optable[i].out);
6745796c8dcSSimon Schubert 		  ret = 1;
6755796c8dcSSimon Schubert 		  break;
6765796c8dcSSimon Schubert 		}
6775796c8dcSSimon Schubert 	    }
6785796c8dcSSimon Schubert 	}
6795796c8dcSSimon Schubert       else
6805796c8dcSSimon Schubert 	{
6815796c8dcSSimon Schubert 	  if (opname[2] == 'a' && opname[5] == '\0')
6825796c8dcSSimon Schubert 	    {
6835796c8dcSSimon Schubert 	      /* Assignment.  */
6845796c8dcSSimon Schubert 	      size_t i;
6855796c8dcSSimon Schubert 	      for (i = 0; i < ARRAY_SIZE (optable); i++)
6865796c8dcSSimon Schubert 		{
6875796c8dcSSimon Schubert 		  if (strlen (optable[i].in) == 3
6885796c8dcSSimon Schubert 		      && memcmp (optable[i].in, opname + 2, 3) == 0)
6895796c8dcSSimon Schubert 		    {
6905796c8dcSSimon Schubert 		      strcat (result, "operator");
6915796c8dcSSimon Schubert 		      strcat (result, optable[i].out);
6925796c8dcSSimon Schubert 		      ret = 1;
6935796c8dcSSimon Schubert 		      break;
6945796c8dcSSimon Schubert 		    }
6955796c8dcSSimon Schubert 		}
6965796c8dcSSimon Schubert 	    }
6975796c8dcSSimon Schubert 	}
6985796c8dcSSimon Schubert     }
6995796c8dcSSimon Schubert   else if (len >= 3
7005796c8dcSSimon Schubert 	   && opname[0] == 'o'
7015796c8dcSSimon Schubert 	   && opname[1] == 'p'
7025796c8dcSSimon Schubert 	   && strchr (cplus_markers, opname[2]) != NULL)
7035796c8dcSSimon Schubert     {
7045796c8dcSSimon Schubert       /* see if it's an assignment expression */
7055796c8dcSSimon Schubert       if (len >= 10 /* op$assign_ */
7065796c8dcSSimon Schubert 	  && memcmp (opname + 3, "assign_", 7) == 0)
7075796c8dcSSimon Schubert 	{
7085796c8dcSSimon Schubert 	  size_t i;
7095796c8dcSSimon Schubert 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
7105796c8dcSSimon Schubert 	    {
7115796c8dcSSimon Schubert 	      len1 = len - 10;
7125796c8dcSSimon Schubert 	      if ((int) strlen (optable[i].in) == len1
7135796c8dcSSimon Schubert 		  && memcmp (optable[i].in, opname + 10, len1) == 0)
7145796c8dcSSimon Schubert 		{
7155796c8dcSSimon Schubert 		  strcat (result, "operator");
7165796c8dcSSimon Schubert 		  strcat (result, optable[i].out);
7175796c8dcSSimon Schubert 		  strcat (result, "=");
7185796c8dcSSimon Schubert 		  ret = 1;
7195796c8dcSSimon Schubert 		  break;
7205796c8dcSSimon Schubert 		}
7215796c8dcSSimon Schubert 	    }
7225796c8dcSSimon Schubert 	}
7235796c8dcSSimon Schubert       else
7245796c8dcSSimon Schubert 	{
7255796c8dcSSimon Schubert 	  size_t i;
7265796c8dcSSimon Schubert 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
7275796c8dcSSimon Schubert 	    {
7285796c8dcSSimon Schubert 	      len1 = len - 3;
7295796c8dcSSimon Schubert 	      if ((int) strlen (optable[i].in) == len1
7305796c8dcSSimon Schubert 		  && memcmp (optable[i].in, opname + 3, len1) == 0)
7315796c8dcSSimon Schubert 		{
7325796c8dcSSimon Schubert 		  strcat (result, "operator");
7335796c8dcSSimon Schubert 		  strcat (result, optable[i].out);
7345796c8dcSSimon Schubert 		  ret = 1;
7355796c8dcSSimon Schubert 		  break;
7365796c8dcSSimon Schubert 		}
7375796c8dcSSimon Schubert 	    }
7385796c8dcSSimon Schubert 	}
7395796c8dcSSimon Schubert     }
7405796c8dcSSimon Schubert   else if (len >= 5 && memcmp (opname, "type", 4) == 0
7415796c8dcSSimon Schubert 	   && strchr (cplus_markers, opname[4]) != NULL)
7425796c8dcSSimon Schubert     {
7435796c8dcSSimon Schubert       /* type conversion operator */
7445796c8dcSSimon Schubert       tem = opname + 5;
7455796c8dcSSimon Schubert       if (do_type (work, &tem, &type))
7465796c8dcSSimon Schubert 	{
7475796c8dcSSimon Schubert 	  strcat (result, "operator ");
7485796c8dcSSimon Schubert 	  strncat (result, type.b, type.p - type.b);
7495796c8dcSSimon Schubert 	  string_delete (&type);
7505796c8dcSSimon Schubert 	  ret = 1;
7515796c8dcSSimon Schubert 	}
7525796c8dcSSimon Schubert     }
7535796c8dcSSimon Schubert   squangle_mop_up (work);
7545796c8dcSSimon Schubert   return ret;
7555796c8dcSSimon Schubert 
7565796c8dcSSimon Schubert }
7575796c8dcSSimon Schubert 
7585796c8dcSSimon Schubert /* Takes operator name as e.g. "++" and returns mangled
7595796c8dcSSimon Schubert    operator name (e.g. "postincrement_expr"), or NULL if not found.
7605796c8dcSSimon Schubert 
7615796c8dcSSimon Schubert    If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
7625796c8dcSSimon Schubert    if OPTIONS & DMGL_ANSI == 0, return the old GNU name.  */
7635796c8dcSSimon Schubert 
7645796c8dcSSimon Schubert const char *
cplus_mangle_opname(const char * opname,int options)7655796c8dcSSimon Schubert cplus_mangle_opname (const char *opname, int options)
7665796c8dcSSimon Schubert {
7675796c8dcSSimon Schubert   size_t i;
7685796c8dcSSimon Schubert   int len;
7695796c8dcSSimon Schubert 
7705796c8dcSSimon Schubert   len = strlen (opname);
7715796c8dcSSimon Schubert   for (i = 0; i < ARRAY_SIZE (optable); i++)
7725796c8dcSSimon Schubert     {
7735796c8dcSSimon Schubert       if ((int) strlen (optable[i].out) == len
7745796c8dcSSimon Schubert 	  && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
7755796c8dcSSimon Schubert 	  && memcmp (optable[i].out, opname, len) == 0)
7765796c8dcSSimon Schubert 	return optable[i].in;
7775796c8dcSSimon Schubert     }
7785796c8dcSSimon Schubert   return (0);
7795796c8dcSSimon Schubert }
7805796c8dcSSimon Schubert 
7815796c8dcSSimon Schubert /* Add a routine to set the demangling style to be sure it is valid and
7825796c8dcSSimon Schubert    allow for any demangler initialization that maybe necessary. */
7835796c8dcSSimon Schubert 
7845796c8dcSSimon Schubert enum demangling_styles
cplus_demangle_set_style(enum demangling_styles style)7855796c8dcSSimon Schubert cplus_demangle_set_style (enum demangling_styles style)
7865796c8dcSSimon Schubert {
7875796c8dcSSimon Schubert   const struct demangler_engine *demangler = libiberty_demanglers;
7885796c8dcSSimon Schubert 
7895796c8dcSSimon Schubert   for (; demangler->demangling_style != unknown_demangling; ++demangler)
7905796c8dcSSimon Schubert     if (style == demangler->demangling_style)
7915796c8dcSSimon Schubert       {
7925796c8dcSSimon Schubert 	current_demangling_style = style;
7935796c8dcSSimon Schubert 	return current_demangling_style;
7945796c8dcSSimon Schubert       }
7955796c8dcSSimon Schubert 
7965796c8dcSSimon Schubert   return unknown_demangling;
7975796c8dcSSimon Schubert }
7985796c8dcSSimon Schubert 
7995796c8dcSSimon Schubert /* Do string name to style translation */
8005796c8dcSSimon Schubert 
8015796c8dcSSimon Schubert enum demangling_styles
cplus_demangle_name_to_style(const char * name)8025796c8dcSSimon Schubert cplus_demangle_name_to_style (const char *name)
8035796c8dcSSimon Schubert {
8045796c8dcSSimon Schubert   const struct demangler_engine *demangler = libiberty_demanglers;
8055796c8dcSSimon Schubert 
8065796c8dcSSimon Schubert   for (; demangler->demangling_style != unknown_demangling; ++demangler)
8075796c8dcSSimon Schubert     if (strcmp (name, demangler->demangling_style_name) == 0)
8085796c8dcSSimon Schubert       return demangler->demangling_style;
8095796c8dcSSimon Schubert 
8105796c8dcSSimon Schubert   return unknown_demangling;
8115796c8dcSSimon Schubert }
8125796c8dcSSimon Schubert 
8135796c8dcSSimon Schubert /* char *cplus_demangle (const char *mangled, int options)
8145796c8dcSSimon Schubert 
8155796c8dcSSimon Schubert    If MANGLED is a mangled function name produced by GNU C++, then
8165796c8dcSSimon Schubert    a pointer to a @code{malloc}ed string giving a C++ representation
8175796c8dcSSimon Schubert    of the name will be returned; otherwise NULL will be returned.
8185796c8dcSSimon Schubert    It is the caller's responsibility to free the string which
8195796c8dcSSimon Schubert    is returned.
8205796c8dcSSimon Schubert 
8215796c8dcSSimon Schubert    The OPTIONS arg may contain one or more of the following bits:
8225796c8dcSSimon Schubert 
8235796c8dcSSimon Schubert    	DMGL_ANSI	ANSI qualifiers such as `const' and `void' are
8245796c8dcSSimon Schubert 			included.
8255796c8dcSSimon Schubert 	DMGL_PARAMS	Function parameters are included.
8265796c8dcSSimon Schubert 
8275796c8dcSSimon Schubert    For example,
8285796c8dcSSimon Schubert 
8295796c8dcSSimon Schubert    cplus_demangle ("foo__1Ai", DMGL_PARAMS)		=> "A::foo(int)"
8305796c8dcSSimon Schubert    cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI)	=> "A::foo(int)"
8315796c8dcSSimon Schubert    cplus_demangle ("foo__1Ai", 0)			=> "A::foo"
8325796c8dcSSimon Schubert 
8335796c8dcSSimon Schubert    cplus_demangle ("foo__1Afe", DMGL_PARAMS)		=> "A::foo(float,...)"
8345796c8dcSSimon Schubert    cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
8355796c8dcSSimon Schubert    cplus_demangle ("foo__1Afe", 0)			=> "A::foo"
8365796c8dcSSimon Schubert 
8375796c8dcSSimon Schubert    Note that any leading underscores, or other such characters prepended by
8385796c8dcSSimon Schubert    the compilation system, are presumed to have already been stripped from
8395796c8dcSSimon Schubert    MANGLED.  */
8405796c8dcSSimon Schubert 
8415796c8dcSSimon Schubert char *
cplus_demangle(const char * mangled,int options)8425796c8dcSSimon Schubert cplus_demangle (const char *mangled, int options)
8435796c8dcSSimon Schubert {
8445796c8dcSSimon Schubert   char *ret;
8455796c8dcSSimon Schubert   struct work_stuff work[1];
8465796c8dcSSimon Schubert 
8475796c8dcSSimon Schubert   if (current_demangling_style == no_demangling)
8485796c8dcSSimon Schubert     return xstrdup (mangled);
8495796c8dcSSimon Schubert 
8505796c8dcSSimon Schubert   memset ((char *) work, 0, sizeof (work));
8515796c8dcSSimon Schubert   work->options = options;
8525796c8dcSSimon Schubert   if ((work->options & DMGL_STYLE_MASK) == 0)
8535796c8dcSSimon Schubert     work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
8545796c8dcSSimon Schubert 
8555796c8dcSSimon Schubert   /* The V3 ABI demangling is implemented elsewhere.  */
8565796c8dcSSimon Schubert   if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
8575796c8dcSSimon Schubert     {
8585796c8dcSSimon Schubert       ret = cplus_demangle_v3 (mangled, work->options);
8595796c8dcSSimon Schubert       if (ret || GNU_V3_DEMANGLING)
8605796c8dcSSimon Schubert 	return ret;
8615796c8dcSSimon Schubert     }
8625796c8dcSSimon Schubert 
8635796c8dcSSimon Schubert   if (JAVA_DEMANGLING)
8645796c8dcSSimon Schubert     {
8655796c8dcSSimon Schubert       ret = java_demangle_v3 (mangled);
8665796c8dcSSimon Schubert       if (ret)
8675796c8dcSSimon Schubert         return ret;
8685796c8dcSSimon Schubert     }
8695796c8dcSSimon Schubert 
8705796c8dcSSimon Schubert   if (GNAT_DEMANGLING)
8715796c8dcSSimon Schubert     return ada_demangle (mangled, options);
8725796c8dcSSimon Schubert 
8735796c8dcSSimon Schubert   ret = internal_cplus_demangle (work, mangled);
8745796c8dcSSimon Schubert   squangle_mop_up (work);
8755796c8dcSSimon Schubert   return (ret);
8765796c8dcSSimon Schubert }
8775796c8dcSSimon Schubert 
878cf7f2e2dSJohn Marino /* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */
8795796c8dcSSimon Schubert 
880cf7f2e2dSJohn Marino char *
ada_demangle(const char * mangled,int option ATTRIBUTE_UNUSED)8815796c8dcSSimon Schubert ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
8825796c8dcSSimon Schubert {
8835796c8dcSSimon Schubert   int len0;
8845796c8dcSSimon Schubert   const char* p;
885cf7f2e2dSJohn Marino   char *d;
886cf7f2e2dSJohn Marino   char *demangled;
8875796c8dcSSimon Schubert 
888cf7f2e2dSJohn Marino   /* Discard leading _ada_, which is used for library level subprograms.  */
8895796c8dcSSimon Schubert   if (strncmp (mangled, "_ada_", 5) == 0)
8905796c8dcSSimon Schubert     mangled += 5;
8915796c8dcSSimon Schubert 
892cf7f2e2dSJohn Marino   /* All ada unit names are lower-case.  */
893cf7f2e2dSJohn Marino   if (!ISLOWER (mangled[0]))
894cf7f2e2dSJohn Marino     goto unknown;
8955796c8dcSSimon Schubert 
896cf7f2e2dSJohn Marino   /* Most of the demangling will trivially remove chars.  Operator names
897cf7f2e2dSJohn Marino      may add one char but because they are always preceeded by '__' which is
898*c50c785cSJohn Marino      replaced by '.', they eventually never expand the size.
899*c50c785cSJohn Marino      A few special names such as '___elabs' add a few chars (at most 7), but
900*c50c785cSJohn Marino      they occur only once.  */
901*c50c785cSJohn Marino   len0 = strlen (mangled) + 7 + 1;
902cf7f2e2dSJohn Marino   demangled = XNEWVEC (char, len0);
9035796c8dcSSimon Schubert 
904cf7f2e2dSJohn Marino   d = demangled;
905cf7f2e2dSJohn Marino   p = mangled;
906cf7f2e2dSJohn Marino   while (1)
9075796c8dcSSimon Schubert     {
908*c50c785cSJohn Marino       /* An entity names is expected.  */
909cf7f2e2dSJohn Marino       if (ISLOWER (*p))
910cf7f2e2dSJohn Marino         {
911*c50c785cSJohn Marino           /* An identifier, which is always lower case.  */
912cf7f2e2dSJohn Marino           do
913cf7f2e2dSJohn Marino             *d++ = *p++;
914cf7f2e2dSJohn Marino           while (ISLOWER(*p) || ISDIGIT (*p)
915cf7f2e2dSJohn Marino                  || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
9165796c8dcSSimon Schubert         }
917cf7f2e2dSJohn Marino       else if (p[0] == 'O')
9185796c8dcSSimon Schubert         {
919*c50c785cSJohn Marino           /* An operator name.  */
920cf7f2e2dSJohn Marino           static const char * const operators[][2] =
921cf7f2e2dSJohn Marino             {{"Oabs", "abs"},  {"Oand", "and"},    {"Omod", "mod"},
922cf7f2e2dSJohn Marino              {"Onot", "not"},  {"Oor", "or"},      {"Orem", "rem"},
923cf7f2e2dSJohn Marino              {"Oxor", "xor"},  {"Oeq", "="},       {"One", "/="},
924cf7f2e2dSJohn Marino              {"Olt", "<"},     {"Ole", "<="},      {"Ogt", ">"},
925cf7f2e2dSJohn Marino              {"Oge", ">="},    {"Oadd", "+"},      {"Osubtract", "-"},
926cf7f2e2dSJohn Marino              {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
927cf7f2e2dSJohn Marino              {"Oexpon", "**"}, {NULL, NULL}};
928cf7f2e2dSJohn Marino           int k;
929cf7f2e2dSJohn Marino 
930*c50c785cSJohn Marino           for (k = 0; operators[k][0] != NULL; k++)
931cf7f2e2dSJohn Marino             {
932*c50c785cSJohn Marino               size_t slen = strlen (operators[k][0]);
933*c50c785cSJohn Marino               if (strncmp (p, operators[k][0], slen) == 0)
934cf7f2e2dSJohn Marino                 {
935*c50c785cSJohn Marino                   p += slen;
936*c50c785cSJohn Marino                   slen = strlen (operators[k][1]);
937cf7f2e2dSJohn Marino                   *d++ = '"';
938*c50c785cSJohn Marino                   memcpy (d, operators[k][1], slen);
939*c50c785cSJohn Marino                   d += slen;
940cf7f2e2dSJohn Marino                   *d++ = '"';
941cf7f2e2dSJohn Marino                   break;
9425796c8dcSSimon Schubert                 }
9435796c8dcSSimon Schubert             }
944cf7f2e2dSJohn Marino           /* Operator not found.  */
945*c50c785cSJohn Marino           if (operators[k][0] == NULL)
946cf7f2e2dSJohn Marino             goto unknown;
9475796c8dcSSimon Schubert         }
9485796c8dcSSimon Schubert       else
9495796c8dcSSimon Schubert         {
950cf7f2e2dSJohn Marino           /* Not a GNAT encoding.  */
951cf7f2e2dSJohn Marino           goto unknown;
9525796c8dcSSimon Schubert         }
953cf7f2e2dSJohn Marino 
954*c50c785cSJohn Marino       /* The name can be directly followed by some uppercase letters.  */
955*c50c785cSJohn Marino       if (p[0] == 'T' && p[1] == 'K')
956*c50c785cSJohn Marino         {
957*c50c785cSJohn Marino           /* Task stuff.  */
958*c50c785cSJohn Marino           if (p[2] == 'B' && p[3] == 0)
959*c50c785cSJohn Marino             {
960*c50c785cSJohn Marino               /* Subprogram for task body.  */
961*c50c785cSJohn Marino               break;
962*c50c785cSJohn Marino             }
963*c50c785cSJohn Marino           else if (p[2] == '_' && p[3] == '_')
964*c50c785cSJohn Marino             {
965*c50c785cSJohn Marino               /* Inner declarations in a task.  */
966*c50c785cSJohn Marino               p += 4;
967*c50c785cSJohn Marino               *d++ = '.';
968*c50c785cSJohn Marino               continue;
969*c50c785cSJohn Marino             }
970*c50c785cSJohn Marino           else
971*c50c785cSJohn Marino             goto unknown;
972*c50c785cSJohn Marino         }
973*c50c785cSJohn Marino       if (p[0] == 'E' && p[1] == 0)
974*c50c785cSJohn Marino         {
975*c50c785cSJohn Marino           /* Exception name.  */
976*c50c785cSJohn Marino           goto unknown;
977*c50c785cSJohn Marino         }
978*c50c785cSJohn Marino       if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
979*c50c785cSJohn Marino         {
980*c50c785cSJohn Marino           /* Protected type subprogram.  */
981*c50c785cSJohn Marino           break;
982*c50c785cSJohn Marino         }
983*c50c785cSJohn Marino       if ((*p == 'N' || *p == 'S') && p[1] == 0)
984*c50c785cSJohn Marino         {
985*c50c785cSJohn Marino           /* Enumerated type name table.  */
986*c50c785cSJohn Marino           goto unknown;
987*c50c785cSJohn Marino         }
988*c50c785cSJohn Marino       if (p[0] == 'X')
989*c50c785cSJohn Marino         {
990*c50c785cSJohn Marino           /* Body nested.  */
991*c50c785cSJohn Marino           p++;
992*c50c785cSJohn Marino           while (p[0] == 'n' || p[0] == 'b')
993*c50c785cSJohn Marino             p++;
994*c50c785cSJohn Marino         }
995*c50c785cSJohn Marino       if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
996*c50c785cSJohn Marino         {
997*c50c785cSJohn Marino           /* Stream operations.  */
998*c50c785cSJohn Marino           const char *name;
999*c50c785cSJohn Marino           switch (p[1])
1000*c50c785cSJohn Marino             {
1001*c50c785cSJohn Marino             case 'R':
1002*c50c785cSJohn Marino               name = "'Read";
1003*c50c785cSJohn Marino               break;
1004*c50c785cSJohn Marino             case 'W':
1005*c50c785cSJohn Marino               name = "'Write";
1006*c50c785cSJohn Marino               break;
1007*c50c785cSJohn Marino             case 'I':
1008*c50c785cSJohn Marino               name = "'Input";
1009*c50c785cSJohn Marino               break;
1010*c50c785cSJohn Marino             case 'O':
1011*c50c785cSJohn Marino               name = "'Output";
1012*c50c785cSJohn Marino               break;
1013*c50c785cSJohn Marino             default:
1014*c50c785cSJohn Marino               goto unknown;
1015*c50c785cSJohn Marino             }
1016*c50c785cSJohn Marino           p += 2;
1017*c50c785cSJohn Marino           strcpy (d, name);
1018*c50c785cSJohn Marino           d += strlen (name);
1019*c50c785cSJohn Marino         }
1020*c50c785cSJohn Marino       else if (p[0] == 'D')
1021*c50c785cSJohn Marino         {
1022*c50c785cSJohn Marino           /* Controlled type operation.  */
1023*c50c785cSJohn Marino           const char *name;
1024*c50c785cSJohn Marino           switch (p[1])
1025*c50c785cSJohn Marino             {
1026*c50c785cSJohn Marino             case 'F':
1027*c50c785cSJohn Marino               name = ".Finalize";
1028*c50c785cSJohn Marino               break;
1029*c50c785cSJohn Marino             case 'A':
1030*c50c785cSJohn Marino               name = ".Adjust";
1031*c50c785cSJohn Marino               break;
1032*c50c785cSJohn Marino             default:
1033*c50c785cSJohn Marino               goto unknown;
1034*c50c785cSJohn Marino             }
1035*c50c785cSJohn Marino           strcpy (d, name);
1036*c50c785cSJohn Marino           d += strlen (name);
1037*c50c785cSJohn Marino           break;
1038*c50c785cSJohn Marino         }
1039*c50c785cSJohn Marino 
1040cf7f2e2dSJohn Marino       if (p[0] == '_')
1041cf7f2e2dSJohn Marino         {
1042cf7f2e2dSJohn Marino           /* Separator.  */
1043cf7f2e2dSJohn Marino           if (p[1] == '_')
1044cf7f2e2dSJohn Marino             {
1045cf7f2e2dSJohn Marino               /* Standard separator.  Handled first.  */
1046cf7f2e2dSJohn Marino               p += 2;
1047*c50c785cSJohn Marino 
1048cf7f2e2dSJohn Marino               if (ISDIGIT (*p))
1049cf7f2e2dSJohn Marino                 {
1050*c50c785cSJohn Marino                   /* Overloading number.  */
1051cf7f2e2dSJohn Marino                   do
1052cf7f2e2dSJohn Marino                     p++;
1053cf7f2e2dSJohn Marino                   while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
1054*c50c785cSJohn Marino                   if (*p == 'X')
1055cf7f2e2dSJohn Marino                     {
1056*c50c785cSJohn Marino                       p++;
1057*c50c785cSJohn Marino                       while (p[0] == 'n' || p[0] == 'b')
1058*c50c785cSJohn Marino                         p++;
1059*c50c785cSJohn Marino                     }
1060*c50c785cSJohn Marino                 }
1061*c50c785cSJohn Marino               else if (p[0] == '_' && p[1] != '_')
1062*c50c785cSJohn Marino                 {
1063*c50c785cSJohn Marino                   /* Special names.  */
1064*c50c785cSJohn Marino                   static const char * const special[][2] = {
1065*c50c785cSJohn Marino                     { "_elabb", "'Elab_Body" },
1066*c50c785cSJohn Marino                     { "_elabs", "'Elab_Spec" },
1067*c50c785cSJohn Marino                     { "_size", "'Size" },
1068*c50c785cSJohn Marino                     { "_alignment", "'Alignment" },
1069*c50c785cSJohn Marino                     { "_assign", ".\":=\"" },
1070*c50c785cSJohn Marino                     { NULL, NULL }
1071*c50c785cSJohn Marino                   };
1072*c50c785cSJohn Marino                   int k;
1073*c50c785cSJohn Marino 
1074*c50c785cSJohn Marino                   for (k = 0; special[k][0] != NULL; k++)
1075*c50c785cSJohn Marino                     {
1076*c50c785cSJohn Marino                       size_t slen = strlen (special[k][0]);
1077*c50c785cSJohn Marino                       if (strncmp (p, special[k][0], slen) == 0)
1078*c50c785cSJohn Marino                         {
1079*c50c785cSJohn Marino                           p += slen;
1080*c50c785cSJohn Marino                           slen = strlen (special[k][1]);
1081*c50c785cSJohn Marino                           memcpy (d, special[k][1], slen);
1082*c50c785cSJohn Marino                           d += slen;
1083cf7f2e2dSJohn Marino                           break;
1084cf7f2e2dSJohn Marino                         }
1085*c50c785cSJohn Marino                     }
1086*c50c785cSJohn Marino                   if (special[k][0] != NULL)
1087cf7f2e2dSJohn Marino                     break;
1088*c50c785cSJohn Marino                   else
1089*c50c785cSJohn Marino                     goto unknown;
1090cf7f2e2dSJohn Marino                 }
10915796c8dcSSimon Schubert               else
1092cf7f2e2dSJohn Marino                 {
1093cf7f2e2dSJohn Marino                   *d++ = '.';
1094cf7f2e2dSJohn Marino                   continue;
1095cf7f2e2dSJohn Marino                 }
1096cf7f2e2dSJohn Marino             }
1097cf7f2e2dSJohn Marino           else if (p[1] == 'B' || p[1] == 'E')
1098cf7f2e2dSJohn Marino             {
1099cf7f2e2dSJohn Marino               /* Entry Body or barrier Evaluation.  */
1100cf7f2e2dSJohn Marino               p += 2;
1101cf7f2e2dSJohn Marino               while (ISDIGIT (*p))
1102cf7f2e2dSJohn Marino                 p++;
1103cf7f2e2dSJohn Marino               if (p[0] == 's' && p[1] == 0)
1104cf7f2e2dSJohn Marino                 break;
1105cf7f2e2dSJohn Marino               else
1106cf7f2e2dSJohn Marino                 goto unknown;
1107cf7f2e2dSJohn Marino             }
1108cf7f2e2dSJohn Marino           else
1109cf7f2e2dSJohn Marino             goto unknown;
1110cf7f2e2dSJohn Marino         }
1111cf7f2e2dSJohn Marino 
1112cf7f2e2dSJohn Marino       if (p[0] == '.' && ISDIGIT (p[1]))
1113cf7f2e2dSJohn Marino         {
1114cf7f2e2dSJohn Marino           /* Nested subprogram.  */
1115cf7f2e2dSJohn Marino           p += 2;
1116cf7f2e2dSJohn Marino           while (ISDIGIT (*p))
1117cf7f2e2dSJohn Marino             p++;
1118cf7f2e2dSJohn Marino         }
1119cf7f2e2dSJohn Marino       if (*p == 0)
1120cf7f2e2dSJohn Marino         {
1121cf7f2e2dSJohn Marino           /* End of mangled name.  */
1122cf7f2e2dSJohn Marino           break;
1123cf7f2e2dSJohn Marino         }
1124cf7f2e2dSJohn Marino       else
1125cf7f2e2dSJohn Marino         goto unknown;
1126cf7f2e2dSJohn Marino     }
1127cf7f2e2dSJohn Marino   *d = 0;
11285796c8dcSSimon Schubert   return demangled;
11295796c8dcSSimon Schubert 
1130cf7f2e2dSJohn Marino  unknown:
1131cf7f2e2dSJohn Marino   len0 = strlen (mangled);
1132cf7f2e2dSJohn Marino   demangled = XNEWVEC (char, len0 + 3);
11335796c8dcSSimon Schubert 
11345796c8dcSSimon Schubert   if (mangled[0] == '<')
11355796c8dcSSimon Schubert      strcpy (demangled, mangled);
11365796c8dcSSimon Schubert   else
11375796c8dcSSimon Schubert     sprintf (demangled, "<%s>", mangled);
11385796c8dcSSimon Schubert 
11395796c8dcSSimon Schubert   return demangled;
11405796c8dcSSimon Schubert }
11415796c8dcSSimon Schubert 
11425796c8dcSSimon Schubert /* This function performs most of what cplus_demangle use to do, but
11435796c8dcSSimon Schubert    to be able to demangle a name with a B, K or n code, we need to
11445796c8dcSSimon Schubert    have a longer term memory of what types have been seen. The original
11455796c8dcSSimon Schubert    now initializes and cleans up the squangle code info, while internal
11465796c8dcSSimon Schubert    calls go directly to this routine to avoid resetting that info. */
11475796c8dcSSimon Schubert 
11485796c8dcSSimon Schubert static char *
internal_cplus_demangle(struct work_stuff * work,const char * mangled)11495796c8dcSSimon Schubert internal_cplus_demangle (struct work_stuff *work, const char *mangled)
11505796c8dcSSimon Schubert {
11515796c8dcSSimon Schubert 
11525796c8dcSSimon Schubert   string decl;
11535796c8dcSSimon Schubert   int success = 0;
11545796c8dcSSimon Schubert   char *demangled = NULL;
11555796c8dcSSimon Schubert   int s1, s2, s3, s4;
11565796c8dcSSimon Schubert   s1 = work->constructor;
11575796c8dcSSimon Schubert   s2 = work->destructor;
11585796c8dcSSimon Schubert   s3 = work->static_type;
11595796c8dcSSimon Schubert   s4 = work->type_quals;
11605796c8dcSSimon Schubert   work->constructor = work->destructor = 0;
11615796c8dcSSimon Schubert   work->type_quals = TYPE_UNQUALIFIED;
11625796c8dcSSimon Schubert   work->dllimported = 0;
11635796c8dcSSimon Schubert 
11645796c8dcSSimon Schubert   if ((mangled != NULL) && (*mangled != '\0'))
11655796c8dcSSimon Schubert     {
11665796c8dcSSimon Schubert       string_init (&decl);
11675796c8dcSSimon Schubert 
11685796c8dcSSimon Schubert       /* First check to see if gnu style demangling is active and if the
11695796c8dcSSimon Schubert 	 string to be demangled contains a CPLUS_MARKER.  If so, attempt to
11705796c8dcSSimon Schubert 	 recognize one of the gnu special forms rather than looking for a
11715796c8dcSSimon Schubert 	 standard prefix.  In particular, don't worry about whether there
11725796c8dcSSimon Schubert 	 is a "__" string in the mangled string.  Consider "_$_5__foo" for
11735796c8dcSSimon Schubert 	 example.  */
11745796c8dcSSimon Schubert 
11755796c8dcSSimon Schubert       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
11765796c8dcSSimon Schubert 	{
11775796c8dcSSimon Schubert 	  success = gnu_special (work, &mangled, &decl);
11785796c8dcSSimon Schubert 	}
11795796c8dcSSimon Schubert       if (!success)
11805796c8dcSSimon Schubert 	{
11815796c8dcSSimon Schubert 	  success = demangle_prefix (work, &mangled, &decl);
11825796c8dcSSimon Schubert 	}
11835796c8dcSSimon Schubert       if (success && (*mangled != '\0'))
11845796c8dcSSimon Schubert 	{
11855796c8dcSSimon Schubert 	  success = demangle_signature (work, &mangled, &decl);
11865796c8dcSSimon Schubert 	}
11875796c8dcSSimon Schubert       if (work->constructor == 2)
11885796c8dcSSimon Schubert         {
11895796c8dcSSimon Schubert           string_prepend (&decl, "global constructors keyed to ");
11905796c8dcSSimon Schubert           work->constructor = 0;
11915796c8dcSSimon Schubert         }
11925796c8dcSSimon Schubert       else if (work->destructor == 2)
11935796c8dcSSimon Schubert         {
11945796c8dcSSimon Schubert           string_prepend (&decl, "global destructors keyed to ");
11955796c8dcSSimon Schubert           work->destructor = 0;
11965796c8dcSSimon Schubert         }
11975796c8dcSSimon Schubert       else if (work->dllimported == 1)
11985796c8dcSSimon Schubert         {
11995796c8dcSSimon Schubert           string_prepend (&decl, "import stub for ");
12005796c8dcSSimon Schubert           work->dllimported = 0;
12015796c8dcSSimon Schubert         }
12025796c8dcSSimon Schubert       demangled = mop_up (work, &decl, success);
12035796c8dcSSimon Schubert     }
12045796c8dcSSimon Schubert   work->constructor = s1;
12055796c8dcSSimon Schubert   work->destructor = s2;
12065796c8dcSSimon Schubert   work->static_type = s3;
12075796c8dcSSimon Schubert   work->type_quals = s4;
12085796c8dcSSimon Schubert   return demangled;
12095796c8dcSSimon Schubert }
12105796c8dcSSimon Schubert 
12115796c8dcSSimon Schubert 
12125796c8dcSSimon Schubert /* Clear out and squangling related storage */
12135796c8dcSSimon Schubert static void
squangle_mop_up(struct work_stuff * work)12145796c8dcSSimon Schubert squangle_mop_up (struct work_stuff *work)
12155796c8dcSSimon Schubert {
12165796c8dcSSimon Schubert   /* clean up the B and K type mangling types. */
12175796c8dcSSimon Schubert   forget_B_and_K_types (work);
12185796c8dcSSimon Schubert   if (work -> btypevec != NULL)
12195796c8dcSSimon Schubert     {
12205796c8dcSSimon Schubert       free ((char *) work -> btypevec);
12215796c8dcSSimon Schubert     }
12225796c8dcSSimon Schubert   if (work -> ktypevec != NULL)
12235796c8dcSSimon Schubert     {
12245796c8dcSSimon Schubert       free ((char *) work -> ktypevec);
12255796c8dcSSimon Schubert     }
12265796c8dcSSimon Schubert }
12275796c8dcSSimon Schubert 
12285796c8dcSSimon Schubert 
12295796c8dcSSimon Schubert /* Copy the work state and storage.  */
12305796c8dcSSimon Schubert 
12315796c8dcSSimon Schubert static void
work_stuff_copy_to_from(struct work_stuff * to,struct work_stuff * from)12325796c8dcSSimon Schubert work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
12335796c8dcSSimon Schubert {
12345796c8dcSSimon Schubert   int i;
12355796c8dcSSimon Schubert 
12365796c8dcSSimon Schubert   delete_work_stuff (to);
12375796c8dcSSimon Schubert 
12385796c8dcSSimon Schubert   /* Shallow-copy scalars.  */
12395796c8dcSSimon Schubert   memcpy (to, from, sizeof (*to));
12405796c8dcSSimon Schubert 
12415796c8dcSSimon Schubert   /* Deep-copy dynamic storage.  */
12425796c8dcSSimon Schubert   if (from->typevec_size)
12435796c8dcSSimon Schubert     to->typevec = XNEWVEC (char *, from->typevec_size);
12445796c8dcSSimon Schubert 
12455796c8dcSSimon Schubert   for (i = 0; i < from->ntypes; i++)
12465796c8dcSSimon Schubert     {
12475796c8dcSSimon Schubert       int len = strlen (from->typevec[i]) + 1;
12485796c8dcSSimon Schubert 
12495796c8dcSSimon Schubert       to->typevec[i] = XNEWVEC (char, len);
12505796c8dcSSimon Schubert       memcpy (to->typevec[i], from->typevec[i], len);
12515796c8dcSSimon Schubert     }
12525796c8dcSSimon Schubert 
12535796c8dcSSimon Schubert   if (from->ksize)
12545796c8dcSSimon Schubert     to->ktypevec = XNEWVEC (char *, from->ksize);
12555796c8dcSSimon Schubert 
12565796c8dcSSimon Schubert   for (i = 0; i < from->numk; i++)
12575796c8dcSSimon Schubert     {
12585796c8dcSSimon Schubert       int len = strlen (from->ktypevec[i]) + 1;
12595796c8dcSSimon Schubert 
12605796c8dcSSimon Schubert       to->ktypevec[i] = XNEWVEC (char, len);
12615796c8dcSSimon Schubert       memcpy (to->ktypevec[i], from->ktypevec[i], len);
12625796c8dcSSimon Schubert     }
12635796c8dcSSimon Schubert 
12645796c8dcSSimon Schubert   if (from->bsize)
12655796c8dcSSimon Schubert     to->btypevec = XNEWVEC (char *, from->bsize);
12665796c8dcSSimon Schubert 
12675796c8dcSSimon Schubert   for (i = 0; i < from->numb; i++)
12685796c8dcSSimon Schubert     {
12695796c8dcSSimon Schubert       int len = strlen (from->btypevec[i]) + 1;
12705796c8dcSSimon Schubert 
12715796c8dcSSimon Schubert       to->btypevec[i] = XNEWVEC (char , len);
12725796c8dcSSimon Schubert       memcpy (to->btypevec[i], from->btypevec[i], len);
12735796c8dcSSimon Schubert     }
12745796c8dcSSimon Schubert 
12755796c8dcSSimon Schubert   if (from->ntmpl_args)
12765796c8dcSSimon Schubert     to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
12775796c8dcSSimon Schubert 
12785796c8dcSSimon Schubert   for (i = 0; i < from->ntmpl_args; i++)
12795796c8dcSSimon Schubert     {
12805796c8dcSSimon Schubert       int len = strlen (from->tmpl_argvec[i]) + 1;
12815796c8dcSSimon Schubert 
12825796c8dcSSimon Schubert       to->tmpl_argvec[i] = XNEWVEC (char, len);
12835796c8dcSSimon Schubert       memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
12845796c8dcSSimon Schubert     }
12855796c8dcSSimon Schubert 
12865796c8dcSSimon Schubert   if (from->previous_argument)
12875796c8dcSSimon Schubert     {
12885796c8dcSSimon Schubert       to->previous_argument = XNEW (string);
12895796c8dcSSimon Schubert       string_init (to->previous_argument);
12905796c8dcSSimon Schubert       string_appends (to->previous_argument, from->previous_argument);
12915796c8dcSSimon Schubert     }
12925796c8dcSSimon Schubert }
12935796c8dcSSimon Schubert 
12945796c8dcSSimon Schubert 
12955796c8dcSSimon Schubert /* Delete dynamic stuff in work_stuff that is not to be re-used.  */
12965796c8dcSSimon Schubert 
12975796c8dcSSimon Schubert static void
delete_non_B_K_work_stuff(struct work_stuff * work)12985796c8dcSSimon Schubert delete_non_B_K_work_stuff (struct work_stuff *work)
12995796c8dcSSimon Schubert {
13005796c8dcSSimon Schubert   /* Discard the remembered types, if any.  */
13015796c8dcSSimon Schubert 
13025796c8dcSSimon Schubert   forget_types (work);
13035796c8dcSSimon Schubert   if (work -> typevec != NULL)
13045796c8dcSSimon Schubert     {
13055796c8dcSSimon Schubert       free ((char *) work -> typevec);
13065796c8dcSSimon Schubert       work -> typevec = NULL;
13075796c8dcSSimon Schubert       work -> typevec_size = 0;
13085796c8dcSSimon Schubert     }
13095796c8dcSSimon Schubert   if (work->tmpl_argvec)
13105796c8dcSSimon Schubert     {
13115796c8dcSSimon Schubert       int i;
13125796c8dcSSimon Schubert 
13135796c8dcSSimon Schubert       for (i = 0; i < work->ntmpl_args; i++)
13145796c8dcSSimon Schubert 	free ((char*) work->tmpl_argvec[i]);
13155796c8dcSSimon Schubert 
13165796c8dcSSimon Schubert       free ((char*) work->tmpl_argvec);
13175796c8dcSSimon Schubert       work->tmpl_argvec = NULL;
13185796c8dcSSimon Schubert     }
13195796c8dcSSimon Schubert   if (work->previous_argument)
13205796c8dcSSimon Schubert     {
13215796c8dcSSimon Schubert       string_delete (work->previous_argument);
13225796c8dcSSimon Schubert       free ((char*) work->previous_argument);
13235796c8dcSSimon Schubert       work->previous_argument = NULL;
13245796c8dcSSimon Schubert     }
13255796c8dcSSimon Schubert }
13265796c8dcSSimon Schubert 
13275796c8dcSSimon Schubert 
13285796c8dcSSimon Schubert /* Delete all dynamic storage in work_stuff.  */
13295796c8dcSSimon Schubert static void
delete_work_stuff(struct work_stuff * work)13305796c8dcSSimon Schubert delete_work_stuff (struct work_stuff *work)
13315796c8dcSSimon Schubert {
13325796c8dcSSimon Schubert   delete_non_B_K_work_stuff (work);
13335796c8dcSSimon Schubert   squangle_mop_up (work);
13345796c8dcSSimon Schubert }
13355796c8dcSSimon Schubert 
13365796c8dcSSimon Schubert 
13375796c8dcSSimon Schubert /* Clear out any mangled storage */
13385796c8dcSSimon Schubert 
13395796c8dcSSimon Schubert static char *
mop_up(struct work_stuff * work,string * declp,int success)13405796c8dcSSimon Schubert mop_up (struct work_stuff *work, string *declp, int success)
13415796c8dcSSimon Schubert {
13425796c8dcSSimon Schubert   char *demangled = NULL;
13435796c8dcSSimon Schubert 
13445796c8dcSSimon Schubert   delete_non_B_K_work_stuff (work);
13455796c8dcSSimon Schubert 
13465796c8dcSSimon Schubert   /* If demangling was successful, ensure that the demangled string is null
13475796c8dcSSimon Schubert      terminated and return it.  Otherwise, free the demangling decl.  */
13485796c8dcSSimon Schubert 
13495796c8dcSSimon Schubert   if (!success)
13505796c8dcSSimon Schubert     {
13515796c8dcSSimon Schubert       string_delete (declp);
13525796c8dcSSimon Schubert     }
13535796c8dcSSimon Schubert   else
13545796c8dcSSimon Schubert     {
13555796c8dcSSimon Schubert       string_appendn (declp, "", 1);
13565796c8dcSSimon Schubert       demangled = declp->b;
13575796c8dcSSimon Schubert     }
13585796c8dcSSimon Schubert   return (demangled);
13595796c8dcSSimon Schubert }
13605796c8dcSSimon Schubert 
13615796c8dcSSimon Schubert /*
13625796c8dcSSimon Schubert 
13635796c8dcSSimon Schubert LOCAL FUNCTION
13645796c8dcSSimon Schubert 
13655796c8dcSSimon Schubert 	demangle_signature -- demangle the signature part of a mangled name
13665796c8dcSSimon Schubert 
13675796c8dcSSimon Schubert SYNOPSIS
13685796c8dcSSimon Schubert 
13695796c8dcSSimon Schubert 	static int
13705796c8dcSSimon Schubert 	demangle_signature (struct work_stuff *work, const char **mangled,
13715796c8dcSSimon Schubert 			    string *declp);
13725796c8dcSSimon Schubert 
13735796c8dcSSimon Schubert DESCRIPTION
13745796c8dcSSimon Schubert 
13755796c8dcSSimon Schubert 	Consume and demangle the signature portion of the mangled name.
13765796c8dcSSimon Schubert 
13775796c8dcSSimon Schubert 	DECLP is the string where demangled output is being built.  At
13785796c8dcSSimon Schubert 	entry it contains the demangled root name from the mangled name
13795796c8dcSSimon Schubert 	prefix.  I.E. either a demangled operator name or the root function
13805796c8dcSSimon Schubert 	name.  In some special cases, it may contain nothing.
13815796c8dcSSimon Schubert 
13825796c8dcSSimon Schubert 	*MANGLED points to the current unconsumed location in the mangled
13835796c8dcSSimon Schubert 	name.  As tokens are consumed and demangling is performed, the
13845796c8dcSSimon Schubert 	pointer is updated to continuously point at the next token to
13855796c8dcSSimon Schubert 	be consumed.
13865796c8dcSSimon Schubert 
13875796c8dcSSimon Schubert 	Demangling GNU style mangled names is nasty because there is no
13885796c8dcSSimon Schubert 	explicit token that marks the start of the outermost function
13895796c8dcSSimon Schubert 	argument list.  */
13905796c8dcSSimon Schubert 
13915796c8dcSSimon Schubert static int
demangle_signature(struct work_stuff * work,const char ** mangled,string * declp)13925796c8dcSSimon Schubert demangle_signature (struct work_stuff *work,
13935796c8dcSSimon Schubert                     const char **mangled, string *declp)
13945796c8dcSSimon Schubert {
13955796c8dcSSimon Schubert   int success = 1;
13965796c8dcSSimon Schubert   int func_done = 0;
13975796c8dcSSimon Schubert   int expect_func = 0;
13985796c8dcSSimon Schubert   int expect_return_type = 0;
13995796c8dcSSimon Schubert   const char *oldmangled = NULL;
14005796c8dcSSimon Schubert   string trawname;
14015796c8dcSSimon Schubert   string tname;
14025796c8dcSSimon Schubert 
14035796c8dcSSimon Schubert   while (success && (**mangled != '\0'))
14045796c8dcSSimon Schubert     {
14055796c8dcSSimon Schubert       switch (**mangled)
14065796c8dcSSimon Schubert 	{
14075796c8dcSSimon Schubert 	case 'Q':
14085796c8dcSSimon Schubert 	  oldmangled = *mangled;
14095796c8dcSSimon Schubert 	  success = demangle_qualified (work, mangled, declp, 1, 0);
14105796c8dcSSimon Schubert 	  if (success)
14115796c8dcSSimon Schubert 	    remember_type (work, oldmangled, *mangled - oldmangled);
14125796c8dcSSimon Schubert 	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
14135796c8dcSSimon Schubert 	    expect_func = 1;
14145796c8dcSSimon Schubert 	  oldmangled = NULL;
14155796c8dcSSimon Schubert 	  break;
14165796c8dcSSimon Schubert 
14175796c8dcSSimon Schubert         case 'K':
14185796c8dcSSimon Schubert 	  oldmangled = *mangled;
14195796c8dcSSimon Schubert 	  success = demangle_qualified (work, mangled, declp, 1, 0);
14205796c8dcSSimon Schubert 	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
14215796c8dcSSimon Schubert 	    {
14225796c8dcSSimon Schubert 	      expect_func = 1;
14235796c8dcSSimon Schubert 	    }
14245796c8dcSSimon Schubert 	  oldmangled = NULL;
14255796c8dcSSimon Schubert 	  break;
14265796c8dcSSimon Schubert 
14275796c8dcSSimon Schubert 	case 'S':
14285796c8dcSSimon Schubert 	  /* Static member function */
14295796c8dcSSimon Schubert 	  if (oldmangled == NULL)
14305796c8dcSSimon Schubert 	    {
14315796c8dcSSimon Schubert 	      oldmangled = *mangled;
14325796c8dcSSimon Schubert 	    }
14335796c8dcSSimon Schubert 	  (*mangled)++;
14345796c8dcSSimon Schubert 	  work -> static_type = 1;
14355796c8dcSSimon Schubert 	  break;
14365796c8dcSSimon Schubert 
14375796c8dcSSimon Schubert 	case 'C':
14385796c8dcSSimon Schubert 	case 'V':
14395796c8dcSSimon Schubert 	case 'u':
14405796c8dcSSimon Schubert 	  work->type_quals |= code_for_qualifier (**mangled);
14415796c8dcSSimon Schubert 
14425796c8dcSSimon Schubert 	  /* a qualified member function */
14435796c8dcSSimon Schubert 	  if (oldmangled == NULL)
14445796c8dcSSimon Schubert 	    oldmangled = *mangled;
14455796c8dcSSimon Schubert 	  (*mangled)++;
14465796c8dcSSimon Schubert 	  break;
14475796c8dcSSimon Schubert 
14485796c8dcSSimon Schubert 	case 'L':
14495796c8dcSSimon Schubert 	  /* Local class name follows after "Lnnn_" */
14505796c8dcSSimon Schubert 	  if (HP_DEMANGLING)
14515796c8dcSSimon Schubert 	    {
14525796c8dcSSimon Schubert 	      while (**mangled && (**mangled != '_'))
14535796c8dcSSimon Schubert 		(*mangled)++;
14545796c8dcSSimon Schubert 	      if (!**mangled)
14555796c8dcSSimon Schubert 		success = 0;
14565796c8dcSSimon Schubert 	      else
14575796c8dcSSimon Schubert 		(*mangled)++;
14585796c8dcSSimon Schubert 	    }
14595796c8dcSSimon Schubert 	  else
14605796c8dcSSimon Schubert 	    success = 0;
14615796c8dcSSimon Schubert 	  break;
14625796c8dcSSimon Schubert 
14635796c8dcSSimon Schubert 	case '0': case '1': case '2': case '3': case '4':
14645796c8dcSSimon Schubert 	case '5': case '6': case '7': case '8': case '9':
14655796c8dcSSimon Schubert 	  if (oldmangled == NULL)
14665796c8dcSSimon Schubert 	    {
14675796c8dcSSimon Schubert 	      oldmangled = *mangled;
14685796c8dcSSimon Schubert 	    }
14695796c8dcSSimon Schubert           work->temp_start = -1; /* uppermost call to demangle_class */
14705796c8dcSSimon Schubert 	  success = demangle_class (work, mangled, declp);
14715796c8dcSSimon Schubert 	  if (success)
14725796c8dcSSimon Schubert 	    {
14735796c8dcSSimon Schubert 	      remember_type (work, oldmangled, *mangled - oldmangled);
14745796c8dcSSimon Schubert 	    }
14755796c8dcSSimon Schubert 	  if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
14765796c8dcSSimon Schubert 	    {
14775796c8dcSSimon Schubert               /* EDG and others will have the "F", so we let the loop cycle
14785796c8dcSSimon Schubert                  if we are looking at one. */
14795796c8dcSSimon Schubert               if (**mangled != 'F')
14805796c8dcSSimon Schubert                  expect_func = 1;
14815796c8dcSSimon Schubert 	    }
14825796c8dcSSimon Schubert 	  oldmangled = NULL;
14835796c8dcSSimon Schubert 	  break;
14845796c8dcSSimon Schubert 
14855796c8dcSSimon Schubert 	case 'B':
14865796c8dcSSimon Schubert 	  {
14875796c8dcSSimon Schubert 	    string s;
14885796c8dcSSimon Schubert 	    success = do_type (work, mangled, &s);
14895796c8dcSSimon Schubert 	    if (success)
14905796c8dcSSimon Schubert 	      {
14915796c8dcSSimon Schubert 		string_append (&s, SCOPE_STRING (work));
14925796c8dcSSimon Schubert 		string_prepends (declp, &s);
14935796c8dcSSimon Schubert 		string_delete (&s);
14945796c8dcSSimon Schubert 	      }
14955796c8dcSSimon Schubert 	    oldmangled = NULL;
14965796c8dcSSimon Schubert 	    expect_func = 1;
14975796c8dcSSimon Schubert 	  }
14985796c8dcSSimon Schubert 	  break;
14995796c8dcSSimon Schubert 
15005796c8dcSSimon Schubert 	case 'F':
15015796c8dcSSimon Schubert 	  /* Function */
15025796c8dcSSimon Schubert 	  /* ARM/HP style demangling includes a specific 'F' character after
15035796c8dcSSimon Schubert 	     the class name.  For GNU style, it is just implied.  So we can
15045796c8dcSSimon Schubert 	     safely just consume any 'F' at this point and be compatible
15055796c8dcSSimon Schubert 	     with either style.  */
15065796c8dcSSimon Schubert 
15075796c8dcSSimon Schubert 	  oldmangled = NULL;
15085796c8dcSSimon Schubert 	  func_done = 1;
15095796c8dcSSimon Schubert 	  (*mangled)++;
15105796c8dcSSimon Schubert 
15115796c8dcSSimon Schubert 	  /* For lucid/ARM/HP style we have to forget any types we might
15125796c8dcSSimon Schubert 	     have remembered up to this point, since they were not argument
15135796c8dcSSimon Schubert 	     types.  GNU style considers all types seen as available for
15145796c8dcSSimon Schubert 	     back references.  See comment in demangle_args() */
15155796c8dcSSimon Schubert 
15165796c8dcSSimon Schubert 	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
15175796c8dcSSimon Schubert 	    {
15185796c8dcSSimon Schubert 	      forget_types (work);
15195796c8dcSSimon Schubert 	    }
15205796c8dcSSimon Schubert 	  success = demangle_args (work, mangled, declp);
15215796c8dcSSimon Schubert 	  /* After picking off the function args, we expect to either
15225796c8dcSSimon Schubert 	     find the function return type (preceded by an '_') or the
15235796c8dcSSimon Schubert 	     end of the string. */
15245796c8dcSSimon Schubert 	  if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
15255796c8dcSSimon Schubert 	    {
15265796c8dcSSimon Schubert 	      ++(*mangled);
15275796c8dcSSimon Schubert               /* At this level, we do not care about the return type. */
15285796c8dcSSimon Schubert               success = do_type (work, mangled, &tname);
15295796c8dcSSimon Schubert               string_delete (&tname);
15305796c8dcSSimon Schubert             }
15315796c8dcSSimon Schubert 
15325796c8dcSSimon Schubert 	  break;
15335796c8dcSSimon Schubert 
15345796c8dcSSimon Schubert 	case 't':
15355796c8dcSSimon Schubert 	  /* G++ Template */
15365796c8dcSSimon Schubert 	  string_init(&trawname);
15375796c8dcSSimon Schubert 	  string_init(&tname);
15385796c8dcSSimon Schubert 	  if (oldmangled == NULL)
15395796c8dcSSimon Schubert 	    {
15405796c8dcSSimon Schubert 	      oldmangled = *mangled;
15415796c8dcSSimon Schubert 	    }
15425796c8dcSSimon Schubert 	  success = demangle_template (work, mangled, &tname,
15435796c8dcSSimon Schubert 				       &trawname, 1, 1);
15445796c8dcSSimon Schubert 	  if (success)
15455796c8dcSSimon Schubert 	    {
15465796c8dcSSimon Schubert 	      remember_type (work, oldmangled, *mangled - oldmangled);
15475796c8dcSSimon Schubert 	    }
15485796c8dcSSimon Schubert 	  string_append (&tname, SCOPE_STRING (work));
15495796c8dcSSimon Schubert 
15505796c8dcSSimon Schubert 	  string_prepends(declp, &tname);
15515796c8dcSSimon Schubert 	  if (work -> destructor & 1)
15525796c8dcSSimon Schubert 	    {
15535796c8dcSSimon Schubert 	      string_prepend (&trawname, "~");
15545796c8dcSSimon Schubert 	      string_appends (declp, &trawname);
15555796c8dcSSimon Schubert 	      work->destructor -= 1;
15565796c8dcSSimon Schubert 	    }
15575796c8dcSSimon Schubert 	  if ((work->constructor & 1) || (work->destructor & 1))
15585796c8dcSSimon Schubert 	    {
15595796c8dcSSimon Schubert 	      string_appends (declp, &trawname);
15605796c8dcSSimon Schubert 	      work->constructor -= 1;
15615796c8dcSSimon Schubert 	    }
15625796c8dcSSimon Schubert 	  string_delete(&trawname);
15635796c8dcSSimon Schubert 	  string_delete(&tname);
15645796c8dcSSimon Schubert 	  oldmangled = NULL;
15655796c8dcSSimon Schubert 	  expect_func = 1;
15665796c8dcSSimon Schubert 	  break;
15675796c8dcSSimon Schubert 
15685796c8dcSSimon Schubert 	case '_':
15695796c8dcSSimon Schubert 	  if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
15705796c8dcSSimon Schubert 	    {
15715796c8dcSSimon Schubert 	      /* Read the return type. */
15725796c8dcSSimon Schubert 	      string return_type;
15735796c8dcSSimon Schubert 
15745796c8dcSSimon Schubert 	      (*mangled)++;
15755796c8dcSSimon Schubert 	      success = do_type (work, mangled, &return_type);
15765796c8dcSSimon Schubert 	      APPEND_BLANK (&return_type);
15775796c8dcSSimon Schubert 
15785796c8dcSSimon Schubert 	      string_prepends (declp, &return_type);
15795796c8dcSSimon Schubert 	      string_delete (&return_type);
15805796c8dcSSimon Schubert 	      break;
15815796c8dcSSimon Schubert 	    }
15825796c8dcSSimon Schubert 	  else
15835796c8dcSSimon Schubert 	    /* At the outermost level, we cannot have a return type specified,
15845796c8dcSSimon Schubert 	       so if we run into another '_' at this point we are dealing with
15855796c8dcSSimon Schubert 	       a mangled name that is either bogus, or has been mangled by
15865796c8dcSSimon Schubert 	       some algorithm we don't know how to deal with.  So just
15875796c8dcSSimon Schubert 	       reject the entire demangling.  */
15885796c8dcSSimon Schubert             /* However, "_nnn" is an expected suffix for alternate entry point
15895796c8dcSSimon Schubert                numbered nnn for a function, with HP aCC, so skip over that
15905796c8dcSSimon Schubert                without reporting failure. pai/1997-09-04 */
15915796c8dcSSimon Schubert             if (HP_DEMANGLING)
15925796c8dcSSimon Schubert               {
15935796c8dcSSimon Schubert                 (*mangled)++;
15945796c8dcSSimon Schubert                 while (**mangled && ISDIGIT ((unsigned char)**mangled))
15955796c8dcSSimon Schubert                   (*mangled)++;
15965796c8dcSSimon Schubert               }
15975796c8dcSSimon Schubert             else
15985796c8dcSSimon Schubert 	      success = 0;
15995796c8dcSSimon Schubert 	  break;
16005796c8dcSSimon Schubert 
16015796c8dcSSimon Schubert 	case 'H':
16025796c8dcSSimon Schubert 	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
16035796c8dcSSimon Schubert 	    {
16045796c8dcSSimon Schubert 	      /* A G++ template function.  Read the template arguments. */
16055796c8dcSSimon Schubert 	      success = demangle_template (work, mangled, declp, 0, 0,
16065796c8dcSSimon Schubert 					   0);
16075796c8dcSSimon Schubert 	      if (!(work->constructor & 1))
16085796c8dcSSimon Schubert 		expect_return_type = 1;
16095796c8dcSSimon Schubert 	      (*mangled)++;
16105796c8dcSSimon Schubert 	      break;
16115796c8dcSSimon Schubert 	    }
16125796c8dcSSimon Schubert 	  else
16135796c8dcSSimon Schubert 	    /* fall through */
16145796c8dcSSimon Schubert 	    {;}
16155796c8dcSSimon Schubert 
16165796c8dcSSimon Schubert 	default:
16175796c8dcSSimon Schubert 	  if (AUTO_DEMANGLING || GNU_DEMANGLING)
16185796c8dcSSimon Schubert 	    {
16195796c8dcSSimon Schubert 	      /* Assume we have stumbled onto the first outermost function
16205796c8dcSSimon Schubert 		 argument token, and start processing args.  */
16215796c8dcSSimon Schubert 	      func_done = 1;
16225796c8dcSSimon Schubert 	      success = demangle_args (work, mangled, declp);
16235796c8dcSSimon Schubert 	    }
16245796c8dcSSimon Schubert 	  else
16255796c8dcSSimon Schubert 	    {
16265796c8dcSSimon Schubert 	      /* Non-GNU demanglers use a specific token to mark the start
16275796c8dcSSimon Schubert 		 of the outermost function argument tokens.  Typically 'F',
16285796c8dcSSimon Schubert 		 for ARM/HP-demangling, for example.  So if we find something
16295796c8dcSSimon Schubert 		 we are not prepared for, it must be an error.  */
16305796c8dcSSimon Schubert 	      success = 0;
16315796c8dcSSimon Schubert 	    }
16325796c8dcSSimon Schubert 	  break;
16335796c8dcSSimon Schubert 	}
16345796c8dcSSimon Schubert       /*
16355796c8dcSSimon Schubert 	if (AUTO_DEMANGLING || GNU_DEMANGLING)
16365796c8dcSSimon Schubert 	*/
16375796c8dcSSimon Schubert       {
16385796c8dcSSimon Schubert 	if (success && expect_func)
16395796c8dcSSimon Schubert 	  {
16405796c8dcSSimon Schubert 	    func_done = 1;
16415796c8dcSSimon Schubert               if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
16425796c8dcSSimon Schubert                 {
16435796c8dcSSimon Schubert                   forget_types (work);
16445796c8dcSSimon Schubert                 }
16455796c8dcSSimon Schubert 	    success = demangle_args (work, mangled, declp);
16465796c8dcSSimon Schubert 	    /* Since template include the mangling of their return types,
16475796c8dcSSimon Schubert 	       we must set expect_func to 0 so that we don't try do
16485796c8dcSSimon Schubert 	       demangle more arguments the next time we get here.  */
16495796c8dcSSimon Schubert 	    expect_func = 0;
16505796c8dcSSimon Schubert 	  }
16515796c8dcSSimon Schubert       }
16525796c8dcSSimon Schubert     }
16535796c8dcSSimon Schubert   if (success && !func_done)
16545796c8dcSSimon Schubert     {
16555796c8dcSSimon Schubert       if (AUTO_DEMANGLING || GNU_DEMANGLING)
16565796c8dcSSimon Schubert 	{
16575796c8dcSSimon Schubert 	  /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
16585796c8dcSSimon Schubert 	     bar__3fooi is 'foo::bar(int)'.  We get here when we find the
16595796c8dcSSimon Schubert 	     first case, and need to ensure that the '(void)' gets added to
16605796c8dcSSimon Schubert 	     the current declp.  Note that with ARM/HP, the first case
16615796c8dcSSimon Schubert 	     represents the name of a static data member 'foo::bar',
16625796c8dcSSimon Schubert 	     which is in the current declp, so we leave it alone.  */
16635796c8dcSSimon Schubert 	  success = demangle_args (work, mangled, declp);
16645796c8dcSSimon Schubert 	}
16655796c8dcSSimon Schubert     }
16665796c8dcSSimon Schubert   if (success && PRINT_ARG_TYPES)
16675796c8dcSSimon Schubert     {
16685796c8dcSSimon Schubert       if (work->static_type)
16695796c8dcSSimon Schubert 	string_append (declp, " static");
16705796c8dcSSimon Schubert       if (work->type_quals != TYPE_UNQUALIFIED)
16715796c8dcSSimon Schubert 	{
16725796c8dcSSimon Schubert 	  APPEND_BLANK (declp);
16735796c8dcSSimon Schubert 	  string_append (declp, qualifier_string (work->type_quals));
16745796c8dcSSimon Schubert 	}
16755796c8dcSSimon Schubert     }
16765796c8dcSSimon Schubert 
16775796c8dcSSimon Schubert   return (success);
16785796c8dcSSimon Schubert }
16795796c8dcSSimon Schubert 
16805796c8dcSSimon Schubert #if 0
16815796c8dcSSimon Schubert 
16825796c8dcSSimon Schubert static int
16835796c8dcSSimon Schubert demangle_method_args (struct work_stuff *work, const char **mangled,
16845796c8dcSSimon Schubert                       string *declp)
16855796c8dcSSimon Schubert {
16865796c8dcSSimon Schubert   int success = 0;
16875796c8dcSSimon Schubert 
16885796c8dcSSimon Schubert   if (work -> static_type)
16895796c8dcSSimon Schubert     {
16905796c8dcSSimon Schubert       string_append (declp, *mangled + 1);
16915796c8dcSSimon Schubert       *mangled += strlen (*mangled);
16925796c8dcSSimon Schubert       success = 1;
16935796c8dcSSimon Schubert     }
16945796c8dcSSimon Schubert   else
16955796c8dcSSimon Schubert     {
16965796c8dcSSimon Schubert       success = demangle_args (work, mangled, declp);
16975796c8dcSSimon Schubert     }
16985796c8dcSSimon Schubert   return (success);
16995796c8dcSSimon Schubert }
17005796c8dcSSimon Schubert 
17015796c8dcSSimon Schubert #endif
17025796c8dcSSimon Schubert 
17035796c8dcSSimon Schubert static int
demangle_template_template_parm(struct work_stuff * work,const char ** mangled,string * tname)17045796c8dcSSimon Schubert demangle_template_template_parm (struct work_stuff *work,
17055796c8dcSSimon Schubert                                  const char **mangled, string *tname)
17065796c8dcSSimon Schubert {
17075796c8dcSSimon Schubert   int i;
17085796c8dcSSimon Schubert   int r;
17095796c8dcSSimon Schubert   int need_comma = 0;
17105796c8dcSSimon Schubert   int success = 1;
17115796c8dcSSimon Schubert   string temp;
17125796c8dcSSimon Schubert 
17135796c8dcSSimon Schubert   string_append (tname, "template <");
17145796c8dcSSimon Schubert   /* get size of template parameter list */
17155796c8dcSSimon Schubert   if (get_count (mangled, &r))
17165796c8dcSSimon Schubert     {
17175796c8dcSSimon Schubert       for (i = 0; i < r; i++)
17185796c8dcSSimon Schubert 	{
17195796c8dcSSimon Schubert 	  if (need_comma)
17205796c8dcSSimon Schubert 	    {
17215796c8dcSSimon Schubert 	      string_append (tname, ", ");
17225796c8dcSSimon Schubert 	    }
17235796c8dcSSimon Schubert 
17245796c8dcSSimon Schubert 	    /* Z for type parameters */
17255796c8dcSSimon Schubert 	    if (**mangled == 'Z')
17265796c8dcSSimon Schubert 	      {
17275796c8dcSSimon Schubert 		(*mangled)++;
17285796c8dcSSimon Schubert 		string_append (tname, "class");
17295796c8dcSSimon Schubert 	      }
17305796c8dcSSimon Schubert 	      /* z for template parameters */
17315796c8dcSSimon Schubert 	    else if (**mangled == 'z')
17325796c8dcSSimon Schubert 	      {
17335796c8dcSSimon Schubert 		(*mangled)++;
17345796c8dcSSimon Schubert 		success =
17355796c8dcSSimon Schubert 		  demangle_template_template_parm (work, mangled, tname);
17365796c8dcSSimon Schubert 		if (!success)
17375796c8dcSSimon Schubert 		  {
17385796c8dcSSimon Schubert 		    break;
17395796c8dcSSimon Schubert 		  }
17405796c8dcSSimon Schubert 	      }
17415796c8dcSSimon Schubert 	    else
17425796c8dcSSimon Schubert 	      {
17435796c8dcSSimon Schubert 		/* temp is initialized in do_type */
17445796c8dcSSimon Schubert 		success = do_type (work, mangled, &temp);
17455796c8dcSSimon Schubert 		if (success)
17465796c8dcSSimon Schubert 		  {
17475796c8dcSSimon Schubert 		    string_appends (tname, &temp);
17485796c8dcSSimon Schubert 		  }
17495796c8dcSSimon Schubert 		string_delete(&temp);
17505796c8dcSSimon Schubert 		if (!success)
17515796c8dcSSimon Schubert 		  {
17525796c8dcSSimon Schubert 		    break;
17535796c8dcSSimon Schubert 		  }
17545796c8dcSSimon Schubert 	      }
17555796c8dcSSimon Schubert 	  need_comma = 1;
17565796c8dcSSimon Schubert 	}
17575796c8dcSSimon Schubert 
17585796c8dcSSimon Schubert     }
17595796c8dcSSimon Schubert   if (tname->p[-1] == '>')
17605796c8dcSSimon Schubert     string_append (tname, " ");
17615796c8dcSSimon Schubert   string_append (tname, "> class");
17625796c8dcSSimon Schubert   return (success);
17635796c8dcSSimon Schubert }
17645796c8dcSSimon Schubert 
17655796c8dcSSimon Schubert static int
demangle_expression(struct work_stuff * work,const char ** mangled,string * s,type_kind_t tk)17665796c8dcSSimon Schubert demangle_expression (struct work_stuff *work, const char **mangled,
17675796c8dcSSimon Schubert                      string *s, type_kind_t tk)
17685796c8dcSSimon Schubert {
17695796c8dcSSimon Schubert   int need_operator = 0;
17705796c8dcSSimon Schubert   int success;
17715796c8dcSSimon Schubert 
17725796c8dcSSimon Schubert   success = 1;
17735796c8dcSSimon Schubert   string_appendn (s, "(", 1);
17745796c8dcSSimon Schubert   (*mangled)++;
17755796c8dcSSimon Schubert   while (success && **mangled != 'W' && **mangled != '\0')
17765796c8dcSSimon Schubert     {
17775796c8dcSSimon Schubert       if (need_operator)
17785796c8dcSSimon Schubert 	{
17795796c8dcSSimon Schubert 	  size_t i;
17805796c8dcSSimon Schubert 	  size_t len;
17815796c8dcSSimon Schubert 
17825796c8dcSSimon Schubert 	  success = 0;
17835796c8dcSSimon Schubert 
17845796c8dcSSimon Schubert 	  len = strlen (*mangled);
17855796c8dcSSimon Schubert 
17865796c8dcSSimon Schubert 	  for (i = 0; i < ARRAY_SIZE (optable); ++i)
17875796c8dcSSimon Schubert 	    {
17885796c8dcSSimon Schubert 	      size_t l = strlen (optable[i].in);
17895796c8dcSSimon Schubert 
17905796c8dcSSimon Schubert 	      if (l <= len
17915796c8dcSSimon Schubert 		  && memcmp (optable[i].in, *mangled, l) == 0)
17925796c8dcSSimon Schubert 		{
17935796c8dcSSimon Schubert 		  string_appendn (s, " ", 1);
17945796c8dcSSimon Schubert 		  string_append (s, optable[i].out);
17955796c8dcSSimon Schubert 		  string_appendn (s, " ", 1);
17965796c8dcSSimon Schubert 		  success = 1;
17975796c8dcSSimon Schubert 		  (*mangled) += l;
17985796c8dcSSimon Schubert 		  break;
17995796c8dcSSimon Schubert 		}
18005796c8dcSSimon Schubert 	    }
18015796c8dcSSimon Schubert 
18025796c8dcSSimon Schubert 	  if (!success)
18035796c8dcSSimon Schubert 	    break;
18045796c8dcSSimon Schubert 	}
18055796c8dcSSimon Schubert       else
18065796c8dcSSimon Schubert 	need_operator = 1;
18075796c8dcSSimon Schubert 
18085796c8dcSSimon Schubert       success = demangle_template_value_parm (work, mangled, s, tk);
18095796c8dcSSimon Schubert     }
18105796c8dcSSimon Schubert 
18115796c8dcSSimon Schubert   if (**mangled != 'W')
18125796c8dcSSimon Schubert     success = 0;
18135796c8dcSSimon Schubert   else
18145796c8dcSSimon Schubert     {
18155796c8dcSSimon Schubert       string_appendn (s, ")", 1);
18165796c8dcSSimon Schubert       (*mangled)++;
18175796c8dcSSimon Schubert     }
18185796c8dcSSimon Schubert 
18195796c8dcSSimon Schubert   return success;
18205796c8dcSSimon Schubert }
18215796c8dcSSimon Schubert 
18225796c8dcSSimon Schubert static int
demangle_integral_value(struct work_stuff * work,const char ** mangled,string * s)18235796c8dcSSimon Schubert demangle_integral_value (struct work_stuff *work,
18245796c8dcSSimon Schubert                          const char **mangled, string *s)
18255796c8dcSSimon Schubert {
18265796c8dcSSimon Schubert   int success;
18275796c8dcSSimon Schubert 
18285796c8dcSSimon Schubert   if (**mangled == 'E')
18295796c8dcSSimon Schubert     success = demangle_expression (work, mangled, s, tk_integral);
18305796c8dcSSimon Schubert   else if (**mangled == 'Q' || **mangled == 'K')
18315796c8dcSSimon Schubert     success = demangle_qualified (work, mangled, s, 0, 1);
18325796c8dcSSimon Schubert   else
18335796c8dcSSimon Schubert     {
18345796c8dcSSimon Schubert       int value;
18355796c8dcSSimon Schubert 
18365796c8dcSSimon Schubert       /* By default, we let the number decide whether we shall consume an
18375796c8dcSSimon Schubert 	 underscore.  */
18385796c8dcSSimon Schubert       int multidigit_without_leading_underscore = 0;
18395796c8dcSSimon Schubert       int leave_following_underscore = 0;
18405796c8dcSSimon Schubert 
18415796c8dcSSimon Schubert       success = 0;
18425796c8dcSSimon Schubert 
18435796c8dcSSimon Schubert       if (**mangled == '_')
18445796c8dcSSimon Schubert         {
18455796c8dcSSimon Schubert 	  if (mangled[0][1] == 'm')
18465796c8dcSSimon Schubert 	    {
18475796c8dcSSimon Schubert 	      /* Since consume_count_with_underscores does not handle the
18485796c8dcSSimon Schubert 		 `m'-prefix we must do it here, using consume_count and
18495796c8dcSSimon Schubert 		 adjusting underscores: we have to consume the underscore
18505796c8dcSSimon Schubert 		 matching the prepended one.  */
18515796c8dcSSimon Schubert 	      multidigit_without_leading_underscore = 1;
18525796c8dcSSimon Schubert 	      string_appendn (s, "-", 1);
18535796c8dcSSimon Schubert 	      (*mangled) += 2;
18545796c8dcSSimon Schubert 	    }
18555796c8dcSSimon Schubert 	  else
18565796c8dcSSimon Schubert 	    {
18575796c8dcSSimon Schubert 	      /* Do not consume a following underscore;
18585796c8dcSSimon Schubert 	         consume_count_with_underscores will consume what
18595796c8dcSSimon Schubert 	         should be consumed.  */
18605796c8dcSSimon Schubert 	      leave_following_underscore = 1;
18615796c8dcSSimon Schubert 	    }
18625796c8dcSSimon Schubert 	}
18635796c8dcSSimon Schubert       else
18645796c8dcSSimon Schubert 	{
18655796c8dcSSimon Schubert 	  /* Negative numbers are indicated with a leading `m'.  */
18665796c8dcSSimon Schubert 	  if (**mangled == 'm')
18675796c8dcSSimon Schubert 	  {
18685796c8dcSSimon Schubert 	    string_appendn (s, "-", 1);
18695796c8dcSSimon Schubert 	    (*mangled)++;
18705796c8dcSSimon Schubert 	  }
18715796c8dcSSimon Schubert 	  /* Since consume_count_with_underscores does not handle
18725796c8dcSSimon Schubert 	     multi-digit numbers that do not start with an underscore,
18735796c8dcSSimon Schubert 	     and this number can be an integer template parameter,
18745796c8dcSSimon Schubert 	     we have to call consume_count. */
18755796c8dcSSimon Schubert 	  multidigit_without_leading_underscore = 1;
18765796c8dcSSimon Schubert 	  /* These multi-digit numbers never end on an underscore,
18775796c8dcSSimon Schubert 	     so if there is one then don't eat it. */
18785796c8dcSSimon Schubert 	  leave_following_underscore = 1;
18795796c8dcSSimon Schubert 	}
18805796c8dcSSimon Schubert 
18815796c8dcSSimon Schubert       /* We must call consume_count if we expect to remove a trailing
18825796c8dcSSimon Schubert 	 underscore, since consume_count_with_underscores expects
18835796c8dcSSimon Schubert 	 the leading underscore (that we consumed) if it is to handle
18845796c8dcSSimon Schubert 	 multi-digit numbers.  */
18855796c8dcSSimon Schubert       if (multidigit_without_leading_underscore)
18865796c8dcSSimon Schubert 	value = consume_count (mangled);
18875796c8dcSSimon Schubert       else
18885796c8dcSSimon Schubert 	value = consume_count_with_underscores (mangled);
18895796c8dcSSimon Schubert 
18905796c8dcSSimon Schubert       if (value != -1)
18915796c8dcSSimon Schubert 	{
18925796c8dcSSimon Schubert 	  char buf[INTBUF_SIZE];
18935796c8dcSSimon Schubert 	  sprintf (buf, "%d", value);
18945796c8dcSSimon Schubert 	  string_append (s, buf);
18955796c8dcSSimon Schubert 
18965796c8dcSSimon Schubert 	  /* Numbers not otherwise delimited, might have an underscore
18975796c8dcSSimon Schubert 	     appended as a delimeter, which we should skip.
18985796c8dcSSimon Schubert 
18995796c8dcSSimon Schubert 	     ??? This used to always remove a following underscore, which
19005796c8dcSSimon Schubert 	     is wrong.  If other (arbitrary) cases are followed by an
19015796c8dcSSimon Schubert 	     underscore, we need to do something more radical.  */
19025796c8dcSSimon Schubert 
19035796c8dcSSimon Schubert 	  if ((value > 9 || multidigit_without_leading_underscore)
19045796c8dcSSimon Schubert 	      && ! leave_following_underscore
19055796c8dcSSimon Schubert 	      && **mangled == '_')
19065796c8dcSSimon Schubert 	    (*mangled)++;
19075796c8dcSSimon Schubert 
19085796c8dcSSimon Schubert 	  /* All is well.  */
19095796c8dcSSimon Schubert 	  success = 1;
19105796c8dcSSimon Schubert 	}
19115796c8dcSSimon Schubert       }
19125796c8dcSSimon Schubert 
19135796c8dcSSimon Schubert   return success;
19145796c8dcSSimon Schubert }
19155796c8dcSSimon Schubert 
19165796c8dcSSimon Schubert /* Demangle the real value in MANGLED.  */
19175796c8dcSSimon Schubert 
19185796c8dcSSimon Schubert static int
demangle_real_value(struct work_stuff * work,const char ** mangled,string * s)19195796c8dcSSimon Schubert demangle_real_value (struct work_stuff *work,
19205796c8dcSSimon Schubert                      const char **mangled, string *s)
19215796c8dcSSimon Schubert {
19225796c8dcSSimon Schubert   if (**mangled == 'E')
19235796c8dcSSimon Schubert     return demangle_expression (work, mangled, s, tk_real);
19245796c8dcSSimon Schubert 
19255796c8dcSSimon Schubert   if (**mangled == 'm')
19265796c8dcSSimon Schubert     {
19275796c8dcSSimon Schubert       string_appendn (s, "-", 1);
19285796c8dcSSimon Schubert       (*mangled)++;
19295796c8dcSSimon Schubert     }
19305796c8dcSSimon Schubert   while (ISDIGIT ((unsigned char)**mangled))
19315796c8dcSSimon Schubert     {
19325796c8dcSSimon Schubert       string_appendn (s, *mangled, 1);
19335796c8dcSSimon Schubert       (*mangled)++;
19345796c8dcSSimon Schubert     }
19355796c8dcSSimon Schubert   if (**mangled == '.') /* fraction */
19365796c8dcSSimon Schubert     {
19375796c8dcSSimon Schubert       string_appendn (s, ".", 1);
19385796c8dcSSimon Schubert       (*mangled)++;
19395796c8dcSSimon Schubert       while (ISDIGIT ((unsigned char)**mangled))
19405796c8dcSSimon Schubert 	{
19415796c8dcSSimon Schubert 	  string_appendn (s, *mangled, 1);
19425796c8dcSSimon Schubert 	  (*mangled)++;
19435796c8dcSSimon Schubert 	}
19445796c8dcSSimon Schubert     }
19455796c8dcSSimon Schubert   if (**mangled == 'e') /* exponent */
19465796c8dcSSimon Schubert     {
19475796c8dcSSimon Schubert       string_appendn (s, "e", 1);
19485796c8dcSSimon Schubert       (*mangled)++;
19495796c8dcSSimon Schubert       while (ISDIGIT ((unsigned char)**mangled))
19505796c8dcSSimon Schubert 	{
19515796c8dcSSimon Schubert 	  string_appendn (s, *mangled, 1);
19525796c8dcSSimon Schubert 	  (*mangled)++;
19535796c8dcSSimon Schubert 	}
19545796c8dcSSimon Schubert     }
19555796c8dcSSimon Schubert 
19565796c8dcSSimon Schubert   return 1;
19575796c8dcSSimon Schubert }
19585796c8dcSSimon Schubert 
19595796c8dcSSimon Schubert static int
demangle_template_value_parm(struct work_stuff * work,const char ** mangled,string * s,type_kind_t tk)19605796c8dcSSimon Schubert demangle_template_value_parm (struct work_stuff *work, const char **mangled,
19615796c8dcSSimon Schubert                               string *s, type_kind_t tk)
19625796c8dcSSimon Schubert {
19635796c8dcSSimon Schubert   int success = 1;
19645796c8dcSSimon Schubert 
19655796c8dcSSimon Schubert   if (**mangled == 'Y')
19665796c8dcSSimon Schubert     {
19675796c8dcSSimon Schubert       /* The next argument is a template parameter. */
19685796c8dcSSimon Schubert       int idx;
19695796c8dcSSimon Schubert 
19705796c8dcSSimon Schubert       (*mangled)++;
19715796c8dcSSimon Schubert       idx = consume_count_with_underscores (mangled);
19725796c8dcSSimon Schubert       if (idx == -1
19735796c8dcSSimon Schubert 	  || (work->tmpl_argvec && idx >= work->ntmpl_args)
19745796c8dcSSimon Schubert 	  || consume_count_with_underscores (mangled) == -1)
19755796c8dcSSimon Schubert 	return -1;
19765796c8dcSSimon Schubert       if (work->tmpl_argvec)
19775796c8dcSSimon Schubert 	string_append (s, work->tmpl_argvec[idx]);
19785796c8dcSSimon Schubert       else
19795796c8dcSSimon Schubert 	string_append_template_idx (s, idx);
19805796c8dcSSimon Schubert     }
19815796c8dcSSimon Schubert   else if (tk == tk_integral)
19825796c8dcSSimon Schubert     success = demangle_integral_value (work, mangled, s);
19835796c8dcSSimon Schubert   else if (tk == tk_char)
19845796c8dcSSimon Schubert     {
19855796c8dcSSimon Schubert       char tmp[2];
19865796c8dcSSimon Schubert       int val;
19875796c8dcSSimon Schubert       if (**mangled == 'm')
19885796c8dcSSimon Schubert 	{
19895796c8dcSSimon Schubert 	  string_appendn (s, "-", 1);
19905796c8dcSSimon Schubert 	  (*mangled)++;
19915796c8dcSSimon Schubert 	}
19925796c8dcSSimon Schubert       string_appendn (s, "'", 1);
19935796c8dcSSimon Schubert       val = consume_count(mangled);
19945796c8dcSSimon Schubert       if (val <= 0)
19955796c8dcSSimon Schubert 	success = 0;
19965796c8dcSSimon Schubert       else
19975796c8dcSSimon Schubert 	{
19985796c8dcSSimon Schubert 	  tmp[0] = (char)val;
19995796c8dcSSimon Schubert 	  tmp[1] = '\0';
20005796c8dcSSimon Schubert 	  string_appendn (s, &tmp[0], 1);
20015796c8dcSSimon Schubert 	  string_appendn (s, "'", 1);
20025796c8dcSSimon Schubert 	}
20035796c8dcSSimon Schubert     }
20045796c8dcSSimon Schubert   else if (tk == tk_bool)
20055796c8dcSSimon Schubert     {
20065796c8dcSSimon Schubert       int val = consume_count (mangled);
20075796c8dcSSimon Schubert       if (val == 0)
20085796c8dcSSimon Schubert 	string_appendn (s, "false", 5);
20095796c8dcSSimon Schubert       else if (val == 1)
20105796c8dcSSimon Schubert 	string_appendn (s, "true", 4);
20115796c8dcSSimon Schubert       else
20125796c8dcSSimon Schubert 	success = 0;
20135796c8dcSSimon Schubert     }
20145796c8dcSSimon Schubert   else if (tk == tk_real)
20155796c8dcSSimon Schubert     success = demangle_real_value (work, mangled, s);
20165796c8dcSSimon Schubert   else if (tk == tk_pointer || tk == tk_reference)
20175796c8dcSSimon Schubert     {
20185796c8dcSSimon Schubert       if (**mangled == 'Q')
20195796c8dcSSimon Schubert 	success = demangle_qualified (work, mangled, s,
20205796c8dcSSimon Schubert 				      /*isfuncname=*/0,
20215796c8dcSSimon Schubert 				      /*append=*/1);
20225796c8dcSSimon Schubert       else
20235796c8dcSSimon Schubert 	{
20245796c8dcSSimon Schubert 	  int symbol_len  = consume_count (mangled);
20255796c8dcSSimon Schubert 	  if (symbol_len == -1)
20265796c8dcSSimon Schubert 	    return -1;
20275796c8dcSSimon Schubert 	  if (symbol_len == 0)
20285796c8dcSSimon Schubert 	    string_appendn (s, "0", 1);
20295796c8dcSSimon Schubert 	  else
20305796c8dcSSimon Schubert 	    {
20315796c8dcSSimon Schubert 	      char *p = XNEWVEC (char, symbol_len + 1), *q;
20325796c8dcSSimon Schubert 	      strncpy (p, *mangled, symbol_len);
20335796c8dcSSimon Schubert 	      p [symbol_len] = '\0';
20345796c8dcSSimon Schubert 	      /* We use cplus_demangle here, rather than
20355796c8dcSSimon Schubert 		 internal_cplus_demangle, because the name of the entity
20365796c8dcSSimon Schubert 		 mangled here does not make use of any of the squangling
20375796c8dcSSimon Schubert 		 or type-code information we have built up thus far; it is
20385796c8dcSSimon Schubert 		 mangled independently.  */
20395796c8dcSSimon Schubert 	      q = cplus_demangle (p, work->options);
20405796c8dcSSimon Schubert 	      if (tk == tk_pointer)
20415796c8dcSSimon Schubert 		string_appendn (s, "&", 1);
20425796c8dcSSimon Schubert 	      /* FIXME: Pointer-to-member constants should get a
20435796c8dcSSimon Schubert 		 qualifying class name here.  */
20445796c8dcSSimon Schubert 	      if (q)
20455796c8dcSSimon Schubert 		{
20465796c8dcSSimon Schubert 		  string_append (s, q);
20475796c8dcSSimon Schubert 		  free (q);
20485796c8dcSSimon Schubert 		}
20495796c8dcSSimon Schubert 	      else
20505796c8dcSSimon Schubert 		string_append (s, p);
20515796c8dcSSimon Schubert 	      free (p);
20525796c8dcSSimon Schubert 	    }
20535796c8dcSSimon Schubert 	  *mangled += symbol_len;
20545796c8dcSSimon Schubert 	}
20555796c8dcSSimon Schubert     }
20565796c8dcSSimon Schubert 
20575796c8dcSSimon Schubert   return success;
20585796c8dcSSimon Schubert }
20595796c8dcSSimon Schubert 
20605796c8dcSSimon Schubert /* Demangle the template name in MANGLED.  The full name of the
20615796c8dcSSimon Schubert    template (e.g., S<int>) is placed in TNAME.  The name without the
20625796c8dcSSimon Schubert    template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
20635796c8dcSSimon Schubert    non-NULL.  If IS_TYPE is nonzero, this template is a type template,
20645796c8dcSSimon Schubert    not a function template.  If both IS_TYPE and REMEMBER are nonzero,
20655796c8dcSSimon Schubert    the template is remembered in the list of back-referenceable
20665796c8dcSSimon Schubert    types.  */
20675796c8dcSSimon Schubert 
20685796c8dcSSimon Schubert static int
demangle_template(struct work_stuff * work,const char ** mangled,string * tname,string * trawname,int is_type,int remember)20695796c8dcSSimon Schubert demangle_template (struct work_stuff *work, const char **mangled,
20705796c8dcSSimon Schubert                    string *tname, string *trawname,
20715796c8dcSSimon Schubert                    int is_type, int remember)
20725796c8dcSSimon Schubert {
20735796c8dcSSimon Schubert   int i;
20745796c8dcSSimon Schubert   int r;
20755796c8dcSSimon Schubert   int need_comma = 0;
20765796c8dcSSimon Schubert   int success = 0;
20775796c8dcSSimon Schubert   int is_java_array = 0;
20785796c8dcSSimon Schubert   string temp;
20795796c8dcSSimon Schubert 
20805796c8dcSSimon Schubert   (*mangled)++;
20815796c8dcSSimon Schubert   if (is_type)
20825796c8dcSSimon Schubert     {
20835796c8dcSSimon Schubert       /* get template name */
20845796c8dcSSimon Schubert       if (**mangled == 'z')
20855796c8dcSSimon Schubert 	{
20865796c8dcSSimon Schubert 	  int idx;
20875796c8dcSSimon Schubert 	  (*mangled)++;
20885796c8dcSSimon Schubert 	  (*mangled)++;
20895796c8dcSSimon Schubert 
20905796c8dcSSimon Schubert 	  idx = consume_count_with_underscores (mangled);
20915796c8dcSSimon Schubert 	  if (idx == -1
20925796c8dcSSimon Schubert 	      || (work->tmpl_argvec && idx >= work->ntmpl_args)
20935796c8dcSSimon Schubert 	      || consume_count_with_underscores (mangled) == -1)
20945796c8dcSSimon Schubert 	    return (0);
20955796c8dcSSimon Schubert 
20965796c8dcSSimon Schubert 	  if (work->tmpl_argvec)
20975796c8dcSSimon Schubert 	    {
20985796c8dcSSimon Schubert 	      string_append (tname, work->tmpl_argvec[idx]);
20995796c8dcSSimon Schubert 	      if (trawname)
21005796c8dcSSimon Schubert 		string_append (trawname, work->tmpl_argvec[idx]);
21015796c8dcSSimon Schubert 	    }
21025796c8dcSSimon Schubert 	  else
21035796c8dcSSimon Schubert 	    {
21045796c8dcSSimon Schubert 	      string_append_template_idx (tname, idx);
21055796c8dcSSimon Schubert 	      if (trawname)
21065796c8dcSSimon Schubert 		string_append_template_idx (trawname, idx);
21075796c8dcSSimon Schubert 	    }
21085796c8dcSSimon Schubert 	}
21095796c8dcSSimon Schubert       else
21105796c8dcSSimon Schubert 	{
21115796c8dcSSimon Schubert 	  if ((r = consume_count (mangled)) <= 0
21125796c8dcSSimon Schubert 	      || (int) strlen (*mangled) < r)
21135796c8dcSSimon Schubert 	    {
21145796c8dcSSimon Schubert 	      return (0);
21155796c8dcSSimon Schubert 	    }
21165796c8dcSSimon Schubert 	  is_java_array = (work -> options & DMGL_JAVA)
21175796c8dcSSimon Schubert 	    && strncmp (*mangled, "JArray1Z", 8) == 0;
21185796c8dcSSimon Schubert 	  if (! is_java_array)
21195796c8dcSSimon Schubert 	    {
21205796c8dcSSimon Schubert 	      string_appendn (tname, *mangled, r);
21215796c8dcSSimon Schubert 	    }
21225796c8dcSSimon Schubert 	  if (trawname)
21235796c8dcSSimon Schubert 	    string_appendn (trawname, *mangled, r);
21245796c8dcSSimon Schubert 	  *mangled += r;
21255796c8dcSSimon Schubert 	}
21265796c8dcSSimon Schubert     }
21275796c8dcSSimon Schubert   if (!is_java_array)
21285796c8dcSSimon Schubert     string_append (tname, "<");
21295796c8dcSSimon Schubert   /* get size of template parameter list */
21305796c8dcSSimon Schubert   if (!get_count (mangled, &r))
21315796c8dcSSimon Schubert     {
21325796c8dcSSimon Schubert       return (0);
21335796c8dcSSimon Schubert     }
21345796c8dcSSimon Schubert   if (!is_type)
21355796c8dcSSimon Schubert     {
21365796c8dcSSimon Schubert       /* Create an array for saving the template argument values. */
21375796c8dcSSimon Schubert       work->tmpl_argvec = XNEWVEC (char *, r);
21385796c8dcSSimon Schubert       work->ntmpl_args = r;
21395796c8dcSSimon Schubert       for (i = 0; i < r; i++)
21405796c8dcSSimon Schubert 	work->tmpl_argvec[i] = 0;
21415796c8dcSSimon Schubert     }
21425796c8dcSSimon Schubert   for (i = 0; i < r; i++)
21435796c8dcSSimon Schubert     {
21445796c8dcSSimon Schubert       if (need_comma)
21455796c8dcSSimon Schubert 	{
21465796c8dcSSimon Schubert 	  string_append (tname, ", ");
21475796c8dcSSimon Schubert 	}
21485796c8dcSSimon Schubert       /* Z for type parameters */
21495796c8dcSSimon Schubert       if (**mangled == 'Z')
21505796c8dcSSimon Schubert 	{
21515796c8dcSSimon Schubert 	  (*mangled)++;
21525796c8dcSSimon Schubert 	  /* temp is initialized in do_type */
21535796c8dcSSimon Schubert 	  success = do_type (work, mangled, &temp);
21545796c8dcSSimon Schubert 	  if (success)
21555796c8dcSSimon Schubert 	    {
21565796c8dcSSimon Schubert 	      string_appends (tname, &temp);
21575796c8dcSSimon Schubert 
21585796c8dcSSimon Schubert 	      if (!is_type)
21595796c8dcSSimon Schubert 		{
21605796c8dcSSimon Schubert 		  /* Save the template argument. */
21615796c8dcSSimon Schubert 		  int len = temp.p - temp.b;
21625796c8dcSSimon Schubert 		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
21635796c8dcSSimon Schubert 		  memcpy (work->tmpl_argvec[i], temp.b, len);
21645796c8dcSSimon Schubert 		  work->tmpl_argvec[i][len] = '\0';
21655796c8dcSSimon Schubert 		}
21665796c8dcSSimon Schubert 	    }
21675796c8dcSSimon Schubert 	  string_delete(&temp);
21685796c8dcSSimon Schubert 	  if (!success)
21695796c8dcSSimon Schubert 	    {
21705796c8dcSSimon Schubert 	      break;
21715796c8dcSSimon Schubert 	    }
21725796c8dcSSimon Schubert 	}
21735796c8dcSSimon Schubert       /* z for template parameters */
21745796c8dcSSimon Schubert       else if (**mangled == 'z')
21755796c8dcSSimon Schubert 	{
21765796c8dcSSimon Schubert 	  int r2;
21775796c8dcSSimon Schubert 	  (*mangled)++;
21785796c8dcSSimon Schubert 	  success = demangle_template_template_parm (work, mangled, tname);
21795796c8dcSSimon Schubert 
21805796c8dcSSimon Schubert 	  if (success
21815796c8dcSSimon Schubert 	      && (r2 = consume_count (mangled)) > 0
21825796c8dcSSimon Schubert 	      && (int) strlen (*mangled) >= r2)
21835796c8dcSSimon Schubert 	    {
21845796c8dcSSimon Schubert 	      string_append (tname, " ");
21855796c8dcSSimon Schubert 	      string_appendn (tname, *mangled, r2);
21865796c8dcSSimon Schubert 	      if (!is_type)
21875796c8dcSSimon Schubert 		{
21885796c8dcSSimon Schubert 		  /* Save the template argument. */
21895796c8dcSSimon Schubert 		  int len = r2;
21905796c8dcSSimon Schubert 		  work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
21915796c8dcSSimon Schubert 		  memcpy (work->tmpl_argvec[i], *mangled, len);
21925796c8dcSSimon Schubert 		  work->tmpl_argvec[i][len] = '\0';
21935796c8dcSSimon Schubert 		}
21945796c8dcSSimon Schubert 	      *mangled += r2;
21955796c8dcSSimon Schubert 	    }
21965796c8dcSSimon Schubert 	  if (!success)
21975796c8dcSSimon Schubert 	    {
21985796c8dcSSimon Schubert 	      break;
21995796c8dcSSimon Schubert 	    }
22005796c8dcSSimon Schubert 	}
22015796c8dcSSimon Schubert       else
22025796c8dcSSimon Schubert 	{
22035796c8dcSSimon Schubert 	  string  param;
22045796c8dcSSimon Schubert 	  string* s;
22055796c8dcSSimon Schubert 
22065796c8dcSSimon Schubert 	  /* otherwise, value parameter */
22075796c8dcSSimon Schubert 
22085796c8dcSSimon Schubert 	  /* temp is initialized in do_type */
22095796c8dcSSimon Schubert 	  success = do_type (work, mangled, &temp);
22105796c8dcSSimon Schubert 	  string_delete(&temp);
22115796c8dcSSimon Schubert 	  if (!success)
22125796c8dcSSimon Schubert 	    break;
22135796c8dcSSimon Schubert 
22145796c8dcSSimon Schubert 	  if (!is_type)
22155796c8dcSSimon Schubert 	    {
22165796c8dcSSimon Schubert 	      s = &param;
22175796c8dcSSimon Schubert 	      string_init (s);
22185796c8dcSSimon Schubert 	    }
22195796c8dcSSimon Schubert 	  else
22205796c8dcSSimon Schubert 	    s = tname;
22215796c8dcSSimon Schubert 
22225796c8dcSSimon Schubert 	  success = demangle_template_value_parm (work, mangled, s,
22235796c8dcSSimon Schubert 						  (type_kind_t) success);
22245796c8dcSSimon Schubert 
22255796c8dcSSimon Schubert 	  if (!success)
22265796c8dcSSimon Schubert 	    {
22275796c8dcSSimon Schubert 	      if (!is_type)
22285796c8dcSSimon Schubert 		string_delete (s);
22295796c8dcSSimon Schubert 	      success = 0;
22305796c8dcSSimon Schubert 	      break;
22315796c8dcSSimon Schubert 	    }
22325796c8dcSSimon Schubert 
22335796c8dcSSimon Schubert 	  if (!is_type)
22345796c8dcSSimon Schubert 	    {
22355796c8dcSSimon Schubert 	      int len = s->p - s->b;
22365796c8dcSSimon Schubert 	      work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
22375796c8dcSSimon Schubert 	      memcpy (work->tmpl_argvec[i], s->b, len);
22385796c8dcSSimon Schubert 	      work->tmpl_argvec[i][len] = '\0';
22395796c8dcSSimon Schubert 
22405796c8dcSSimon Schubert 	      string_appends (tname, s);
22415796c8dcSSimon Schubert 	      string_delete (s);
22425796c8dcSSimon Schubert 	    }
22435796c8dcSSimon Schubert 	}
22445796c8dcSSimon Schubert       need_comma = 1;
22455796c8dcSSimon Schubert     }
22465796c8dcSSimon Schubert   if (is_java_array)
22475796c8dcSSimon Schubert     {
22485796c8dcSSimon Schubert       string_append (tname, "[]");
22495796c8dcSSimon Schubert     }
22505796c8dcSSimon Schubert   else
22515796c8dcSSimon Schubert     {
22525796c8dcSSimon Schubert       if (tname->p[-1] == '>')
22535796c8dcSSimon Schubert 	string_append (tname, " ");
22545796c8dcSSimon Schubert       string_append (tname, ">");
22555796c8dcSSimon Schubert     }
22565796c8dcSSimon Schubert 
22575796c8dcSSimon Schubert   if (is_type && remember)
22585796c8dcSSimon Schubert     {
22595796c8dcSSimon Schubert       const int bindex = register_Btype (work);
22605796c8dcSSimon Schubert       remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
22615796c8dcSSimon Schubert     }
22625796c8dcSSimon Schubert 
22635796c8dcSSimon Schubert   /*
22645796c8dcSSimon Schubert     if (work -> static_type)
22655796c8dcSSimon Schubert     {
22665796c8dcSSimon Schubert     string_append (declp, *mangled + 1);
22675796c8dcSSimon Schubert     *mangled += strlen (*mangled);
22685796c8dcSSimon Schubert     success = 1;
22695796c8dcSSimon Schubert     }
22705796c8dcSSimon Schubert     else
22715796c8dcSSimon Schubert     {
22725796c8dcSSimon Schubert     success = demangle_args (work, mangled, declp);
22735796c8dcSSimon Schubert     }
22745796c8dcSSimon Schubert     }
22755796c8dcSSimon Schubert     */
22765796c8dcSSimon Schubert   return (success);
22775796c8dcSSimon Schubert }
22785796c8dcSSimon Schubert 
22795796c8dcSSimon Schubert static int
arm_pt(struct work_stuff * work,const char * mangled,int n,const char ** anchor,const char ** args)22805796c8dcSSimon Schubert arm_pt (struct work_stuff *work, const char *mangled,
22815796c8dcSSimon Schubert         int n, const char **anchor, const char **args)
22825796c8dcSSimon Schubert {
22835796c8dcSSimon Schubert   /* Check if ARM template with "__pt__" in it ("parameterized type") */
22845796c8dcSSimon Schubert   /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
22855796c8dcSSimon Schubert   if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
22865796c8dcSSimon Schubert     {
22875796c8dcSSimon Schubert       int len;
22885796c8dcSSimon Schubert       *args = *anchor + 6;
22895796c8dcSSimon Schubert       len = consume_count (args);
22905796c8dcSSimon Schubert       if (len == -1)
22915796c8dcSSimon Schubert 	return 0;
22925796c8dcSSimon Schubert       if (*args + len == mangled + n && **args == '_')
22935796c8dcSSimon Schubert 	{
22945796c8dcSSimon Schubert 	  ++*args;
22955796c8dcSSimon Schubert 	  return 1;
22965796c8dcSSimon Schubert 	}
22975796c8dcSSimon Schubert     }
22985796c8dcSSimon Schubert   if (AUTO_DEMANGLING || EDG_DEMANGLING)
22995796c8dcSSimon Schubert     {
23005796c8dcSSimon Schubert       if ((*anchor = strstr (mangled, "__tm__"))
23015796c8dcSSimon Schubert           || (*anchor = strstr (mangled, "__ps__"))
23025796c8dcSSimon Schubert           || (*anchor = strstr (mangled, "__pt__")))
23035796c8dcSSimon Schubert         {
23045796c8dcSSimon Schubert           int len;
23055796c8dcSSimon Schubert           *args = *anchor + 6;
23065796c8dcSSimon Schubert           len = consume_count (args);
23075796c8dcSSimon Schubert 	  if (len == -1)
23085796c8dcSSimon Schubert 	    return 0;
23095796c8dcSSimon Schubert           if (*args + len == mangled + n && **args == '_')
23105796c8dcSSimon Schubert             {
23115796c8dcSSimon Schubert               ++*args;
23125796c8dcSSimon Schubert               return 1;
23135796c8dcSSimon Schubert             }
23145796c8dcSSimon Schubert         }
23155796c8dcSSimon Schubert       else if ((*anchor = strstr (mangled, "__S")))
23165796c8dcSSimon Schubert         {
23175796c8dcSSimon Schubert  	  int len;
23185796c8dcSSimon Schubert  	  *args = *anchor + 3;
23195796c8dcSSimon Schubert  	  len = consume_count (args);
23205796c8dcSSimon Schubert 	  if (len == -1)
23215796c8dcSSimon Schubert 	    return 0;
23225796c8dcSSimon Schubert  	  if (*args + len == mangled + n && **args == '_')
23235796c8dcSSimon Schubert             {
23245796c8dcSSimon Schubert               ++*args;
23255796c8dcSSimon Schubert  	      return 1;
23265796c8dcSSimon Schubert             }
23275796c8dcSSimon Schubert         }
23285796c8dcSSimon Schubert     }
23295796c8dcSSimon Schubert 
23305796c8dcSSimon Schubert   return 0;
23315796c8dcSSimon Schubert }
23325796c8dcSSimon Schubert 
23335796c8dcSSimon Schubert static void
demangle_arm_hp_template(struct work_stuff * work,const char ** mangled,int n,string * declp)23345796c8dcSSimon Schubert demangle_arm_hp_template (struct work_stuff *work, const char **mangled,
23355796c8dcSSimon Schubert                           int n, string *declp)
23365796c8dcSSimon Schubert {
23375796c8dcSSimon Schubert   const char *p;
23385796c8dcSSimon Schubert   const char *args;
23395796c8dcSSimon Schubert   const char *e = *mangled + n;
23405796c8dcSSimon Schubert   string arg;
23415796c8dcSSimon Schubert 
23425796c8dcSSimon Schubert   /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
23435796c8dcSSimon Schubert      template args */
23445796c8dcSSimon Schubert   if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
23455796c8dcSSimon Schubert     {
23465796c8dcSSimon Schubert       char *start_spec_args = NULL;
23475796c8dcSSimon Schubert       int hold_options;
23485796c8dcSSimon Schubert 
23495796c8dcSSimon Schubert       /* First check for and omit template specialization pseudo-arguments,
23505796c8dcSSimon Schubert          such as in "Spec<#1,#1.*>" */
23515796c8dcSSimon Schubert       start_spec_args = strchr (*mangled, '<');
23525796c8dcSSimon Schubert       if (start_spec_args && (start_spec_args - *mangled < n))
23535796c8dcSSimon Schubert         string_appendn (declp, *mangled, start_spec_args - *mangled);
23545796c8dcSSimon Schubert       else
23555796c8dcSSimon Schubert         string_appendn (declp, *mangled, n);
23565796c8dcSSimon Schubert       (*mangled) += n + 1;
23575796c8dcSSimon Schubert       string_init (&arg);
23585796c8dcSSimon Schubert       if (work->temp_start == -1) /* non-recursive call */
23595796c8dcSSimon Schubert         work->temp_start = declp->p - declp->b;
23605796c8dcSSimon Schubert 
23615796c8dcSSimon Schubert       /* We want to unconditionally demangle parameter types in
23625796c8dcSSimon Schubert 	 template parameters.  */
23635796c8dcSSimon Schubert       hold_options = work->options;
23645796c8dcSSimon Schubert       work->options |= DMGL_PARAMS;
23655796c8dcSSimon Schubert 
23665796c8dcSSimon Schubert       string_append (declp, "<");
23675796c8dcSSimon Schubert       while (1)
23685796c8dcSSimon Schubert         {
23695796c8dcSSimon Schubert           string_delete (&arg);
23705796c8dcSSimon Schubert           switch (**mangled)
23715796c8dcSSimon Schubert             {
23725796c8dcSSimon Schubert               case 'T':
23735796c8dcSSimon Schubert                 /* 'T' signals a type parameter */
23745796c8dcSSimon Schubert                 (*mangled)++;
23755796c8dcSSimon Schubert                 if (!do_type (work, mangled, &arg))
23765796c8dcSSimon Schubert                   goto hpacc_template_args_done;
23775796c8dcSSimon Schubert                 break;
23785796c8dcSSimon Schubert 
23795796c8dcSSimon Schubert               case 'U':
23805796c8dcSSimon Schubert               case 'S':
23815796c8dcSSimon Schubert                 /* 'U' or 'S' signals an integral value */
23825796c8dcSSimon Schubert                 if (!do_hpacc_template_const_value (work, mangled, &arg))
23835796c8dcSSimon Schubert                   goto hpacc_template_args_done;
23845796c8dcSSimon Schubert                 break;
23855796c8dcSSimon Schubert 
23865796c8dcSSimon Schubert               case 'A':
23875796c8dcSSimon Schubert                 /* 'A' signals a named constant expression (literal) */
23885796c8dcSSimon Schubert                 if (!do_hpacc_template_literal (work, mangled, &arg))
23895796c8dcSSimon Schubert                   goto hpacc_template_args_done;
23905796c8dcSSimon Schubert                 break;
23915796c8dcSSimon Schubert 
23925796c8dcSSimon Schubert               default:
23935796c8dcSSimon Schubert                 /* Today, 1997-09-03, we have only the above types
23945796c8dcSSimon Schubert                    of template parameters */
23955796c8dcSSimon Schubert                 /* FIXME: maybe this should fail and return null */
23965796c8dcSSimon Schubert                 goto hpacc_template_args_done;
23975796c8dcSSimon Schubert             }
23985796c8dcSSimon Schubert           string_appends (declp, &arg);
23995796c8dcSSimon Schubert          /* Check if we're at the end of template args.
24005796c8dcSSimon Schubert              0 if at end of static member of template class,
24015796c8dcSSimon Schubert              _ if done with template args for a function */
24025796c8dcSSimon Schubert           if ((**mangled == '\000') || (**mangled == '_'))
24035796c8dcSSimon Schubert             break;
24045796c8dcSSimon Schubert           else
24055796c8dcSSimon Schubert             string_append (declp, ",");
24065796c8dcSSimon Schubert         }
24075796c8dcSSimon Schubert     hpacc_template_args_done:
24085796c8dcSSimon Schubert       string_append (declp, ">");
24095796c8dcSSimon Schubert       string_delete (&arg);
24105796c8dcSSimon Schubert       if (**mangled == '_')
24115796c8dcSSimon Schubert         (*mangled)++;
24125796c8dcSSimon Schubert       work->options = hold_options;
24135796c8dcSSimon Schubert       return;
24145796c8dcSSimon Schubert     }
24155796c8dcSSimon Schubert   /* ARM template? (Also handles HP cfront extensions) */
24165796c8dcSSimon Schubert   else if (arm_pt (work, *mangled, n, &p, &args))
24175796c8dcSSimon Schubert     {
24185796c8dcSSimon Schubert       int hold_options;
24195796c8dcSSimon Schubert       string type_str;
24205796c8dcSSimon Schubert 
24215796c8dcSSimon Schubert       string_init (&arg);
24225796c8dcSSimon Schubert       string_appendn (declp, *mangled, p - *mangled);
24235796c8dcSSimon Schubert       if (work->temp_start == -1)  /* non-recursive call */
24245796c8dcSSimon Schubert 	work->temp_start = declp->p - declp->b;
24255796c8dcSSimon Schubert 
24265796c8dcSSimon Schubert       /* We want to unconditionally demangle parameter types in
24275796c8dcSSimon Schubert 	 template parameters.  */
24285796c8dcSSimon Schubert       hold_options = work->options;
24295796c8dcSSimon Schubert       work->options |= DMGL_PARAMS;
24305796c8dcSSimon Schubert 
24315796c8dcSSimon Schubert       string_append (declp, "<");
24325796c8dcSSimon Schubert       /* should do error checking here */
24335796c8dcSSimon Schubert       while (args < e) {
24345796c8dcSSimon Schubert 	string_delete (&arg);
24355796c8dcSSimon Schubert 
24365796c8dcSSimon Schubert 	/* Check for type or literal here */
24375796c8dcSSimon Schubert 	switch (*args)
24385796c8dcSSimon Schubert 	  {
24395796c8dcSSimon Schubert 	    /* HP cfront extensions to ARM for template args */
24405796c8dcSSimon Schubert 	    /* spec: Xt1Lv1 where t1 is a type, v1 is a literal value */
24415796c8dcSSimon Schubert 	    /* FIXME: We handle only numeric literals for HP cfront */
24425796c8dcSSimon Schubert           case 'X':
24435796c8dcSSimon Schubert             /* A typed constant value follows */
24445796c8dcSSimon Schubert             args++;
24455796c8dcSSimon Schubert             if (!do_type (work, &args, &type_str))
24465796c8dcSSimon Schubert 	      goto cfront_template_args_done;
24475796c8dcSSimon Schubert             string_append (&arg, "(");
24485796c8dcSSimon Schubert             string_appends (&arg, &type_str);
24495796c8dcSSimon Schubert             string_delete (&type_str);
24505796c8dcSSimon Schubert             string_append (&arg, ")");
24515796c8dcSSimon Schubert             if (*args != 'L')
24525796c8dcSSimon Schubert               goto cfront_template_args_done;
24535796c8dcSSimon Schubert             args++;
24545796c8dcSSimon Schubert             /* Now snarf a literal value following 'L' */
24555796c8dcSSimon Schubert             if (!snarf_numeric_literal (&args, &arg))
24565796c8dcSSimon Schubert 	      goto cfront_template_args_done;
24575796c8dcSSimon Schubert             break;
24585796c8dcSSimon Schubert 
24595796c8dcSSimon Schubert           case 'L':
24605796c8dcSSimon Schubert             /* Snarf a literal following 'L' */
24615796c8dcSSimon Schubert             args++;
24625796c8dcSSimon Schubert             if (!snarf_numeric_literal (&args, &arg))
24635796c8dcSSimon Schubert 	      goto cfront_template_args_done;
24645796c8dcSSimon Schubert             break;
24655796c8dcSSimon Schubert           default:
24665796c8dcSSimon Schubert             /* Not handling other HP cfront stuff */
24675796c8dcSSimon Schubert             {
24685796c8dcSSimon Schubert               const char* old_args = args;
24695796c8dcSSimon Schubert               if (!do_type (work, &args, &arg))
24705796c8dcSSimon Schubert                 goto cfront_template_args_done;
24715796c8dcSSimon Schubert 
24725796c8dcSSimon Schubert               /* Fail if we didn't make any progress: prevent infinite loop. */
24735796c8dcSSimon Schubert               if (args == old_args)
24745796c8dcSSimon Schubert 		{
24755796c8dcSSimon Schubert 		  work->options = hold_options;
24765796c8dcSSimon Schubert 		  return;
24775796c8dcSSimon Schubert 		}
24785796c8dcSSimon Schubert             }
24795796c8dcSSimon Schubert 	  }
24805796c8dcSSimon Schubert 	string_appends (declp, &arg);
24815796c8dcSSimon Schubert 	string_append (declp, ",");
24825796c8dcSSimon Schubert       }
24835796c8dcSSimon Schubert     cfront_template_args_done:
24845796c8dcSSimon Schubert       string_delete (&arg);
24855796c8dcSSimon Schubert       if (args >= e)
24865796c8dcSSimon Schubert 	--declp->p; /* remove extra comma */
24875796c8dcSSimon Schubert       string_append (declp, ">");
24885796c8dcSSimon Schubert       work->options = hold_options;
24895796c8dcSSimon Schubert     }
24905796c8dcSSimon Schubert   else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
24915796c8dcSSimon Schubert 	   && (*mangled)[9] == 'N'
24925796c8dcSSimon Schubert 	   && (*mangled)[8] == (*mangled)[10]
24935796c8dcSSimon Schubert 	   && strchr (cplus_markers, (*mangled)[8]))
24945796c8dcSSimon Schubert     {
24955796c8dcSSimon Schubert       /* A member of the anonymous namespace.  */
24965796c8dcSSimon Schubert       string_append (declp, "{anonymous}");
24975796c8dcSSimon Schubert     }
24985796c8dcSSimon Schubert   else
24995796c8dcSSimon Schubert     {
25005796c8dcSSimon Schubert       if (work->temp_start == -1) /* non-recursive call only */
25015796c8dcSSimon Schubert 	work->temp_start = 0;     /* disable in recursive calls */
25025796c8dcSSimon Schubert       string_appendn (declp, *mangled, n);
25035796c8dcSSimon Schubert     }
25045796c8dcSSimon Schubert   *mangled += n;
25055796c8dcSSimon Schubert }
25065796c8dcSSimon Schubert 
25075796c8dcSSimon Schubert /* Extract a class name, possibly a template with arguments, from the
25085796c8dcSSimon Schubert    mangled string; qualifiers, local class indicators, etc. have
25095796c8dcSSimon Schubert    already been dealt with */
25105796c8dcSSimon Schubert 
25115796c8dcSSimon Schubert static int
demangle_class_name(struct work_stuff * work,const char ** mangled,string * declp)25125796c8dcSSimon Schubert demangle_class_name (struct work_stuff *work, const char **mangled,
25135796c8dcSSimon Schubert                      string *declp)
25145796c8dcSSimon Schubert {
25155796c8dcSSimon Schubert   int n;
25165796c8dcSSimon Schubert   int success = 0;
25175796c8dcSSimon Schubert 
25185796c8dcSSimon Schubert   n = consume_count (mangled);
25195796c8dcSSimon Schubert   if (n == -1)
25205796c8dcSSimon Schubert     return 0;
25215796c8dcSSimon Schubert   if ((int) strlen (*mangled) >= n)
25225796c8dcSSimon Schubert     {
25235796c8dcSSimon Schubert       demangle_arm_hp_template (work, mangled, n, declp);
25245796c8dcSSimon Schubert       success = 1;
25255796c8dcSSimon Schubert     }
25265796c8dcSSimon Schubert 
25275796c8dcSSimon Schubert   return (success);
25285796c8dcSSimon Schubert }
25295796c8dcSSimon Schubert 
25305796c8dcSSimon Schubert /*
25315796c8dcSSimon Schubert 
25325796c8dcSSimon Schubert LOCAL FUNCTION
25335796c8dcSSimon Schubert 
25345796c8dcSSimon Schubert 	demangle_class -- demangle a mangled class sequence
25355796c8dcSSimon Schubert 
25365796c8dcSSimon Schubert SYNOPSIS
25375796c8dcSSimon Schubert 
25385796c8dcSSimon Schubert 	static int
25395796c8dcSSimon Schubert 	demangle_class (struct work_stuff *work, const char **mangled,
25405796c8dcSSimon Schubert 			strint *declp)
25415796c8dcSSimon Schubert 
25425796c8dcSSimon Schubert DESCRIPTION
25435796c8dcSSimon Schubert 
25445796c8dcSSimon Schubert 	DECLP points to the buffer into which demangling is being done.
25455796c8dcSSimon Schubert 
25465796c8dcSSimon Schubert 	*MANGLED points to the current token to be demangled.  On input,
25475796c8dcSSimon Schubert 	it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
25485796c8dcSSimon Schubert 	On exit, it points to the next token after the mangled class on
25495796c8dcSSimon Schubert 	success, or the first unconsumed token on failure.
25505796c8dcSSimon Schubert 
25515796c8dcSSimon Schubert 	If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
25525796c8dcSSimon Schubert 	we are demangling a constructor or destructor.  In this case
25535796c8dcSSimon Schubert 	we prepend "class::class" or "class::~class" to DECLP.
25545796c8dcSSimon Schubert 
25555796c8dcSSimon Schubert 	Otherwise, we prepend "class::" to the current DECLP.
25565796c8dcSSimon Schubert 
25575796c8dcSSimon Schubert 	Reset the constructor/destructor flags once they have been
25585796c8dcSSimon Schubert 	"consumed".  This allows demangle_class to be called later during
25595796c8dcSSimon Schubert 	the same demangling, to do normal class demangling.
25605796c8dcSSimon Schubert 
25615796c8dcSSimon Schubert 	Returns 1 if demangling is successful, 0 otherwise.
25625796c8dcSSimon Schubert 
25635796c8dcSSimon Schubert */
25645796c8dcSSimon Schubert 
25655796c8dcSSimon Schubert static int
demangle_class(struct work_stuff * work,const char ** mangled,string * declp)25665796c8dcSSimon Schubert demangle_class (struct work_stuff *work, const char **mangled, string *declp)
25675796c8dcSSimon Schubert {
25685796c8dcSSimon Schubert   int success = 0;
25695796c8dcSSimon Schubert   int btype;
25705796c8dcSSimon Schubert   string class_name;
25715796c8dcSSimon Schubert   char *save_class_name_end = 0;
25725796c8dcSSimon Schubert 
25735796c8dcSSimon Schubert   string_init (&class_name);
25745796c8dcSSimon Schubert   btype = register_Btype (work);
25755796c8dcSSimon Schubert   if (demangle_class_name (work, mangled, &class_name))
25765796c8dcSSimon Schubert     {
25775796c8dcSSimon Schubert       save_class_name_end = class_name.p;
25785796c8dcSSimon Schubert       if ((work->constructor & 1) || (work->destructor & 1))
25795796c8dcSSimon Schubert 	{
25805796c8dcSSimon Schubert           /* adjust so we don't include template args */
25815796c8dcSSimon Schubert           if (work->temp_start && (work->temp_start != -1))
25825796c8dcSSimon Schubert             {
25835796c8dcSSimon Schubert               class_name.p = class_name.b + work->temp_start;
25845796c8dcSSimon Schubert             }
25855796c8dcSSimon Schubert 	  string_prepends (declp, &class_name);
25865796c8dcSSimon Schubert 	  if (work -> destructor & 1)
25875796c8dcSSimon Schubert 	    {
25885796c8dcSSimon Schubert 	      string_prepend (declp, "~");
25895796c8dcSSimon Schubert               work -> destructor -= 1;
25905796c8dcSSimon Schubert 	    }
25915796c8dcSSimon Schubert 	  else
25925796c8dcSSimon Schubert 	    {
25935796c8dcSSimon Schubert 	      work -> constructor -= 1;
25945796c8dcSSimon Schubert 	    }
25955796c8dcSSimon Schubert 	}
25965796c8dcSSimon Schubert       class_name.p = save_class_name_end;
25975796c8dcSSimon Schubert       remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
25985796c8dcSSimon Schubert       remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
25995796c8dcSSimon Schubert       string_prepend (declp, SCOPE_STRING (work));
26005796c8dcSSimon Schubert       string_prepends (declp, &class_name);
26015796c8dcSSimon Schubert       success = 1;
26025796c8dcSSimon Schubert     }
26035796c8dcSSimon Schubert   string_delete (&class_name);
26045796c8dcSSimon Schubert   return (success);
26055796c8dcSSimon Schubert }
26065796c8dcSSimon Schubert 
26075796c8dcSSimon Schubert 
26085796c8dcSSimon Schubert /* Called when there's a "__" in the mangled name, with `scan' pointing to
26095796c8dcSSimon Schubert    the rightmost guess.
26105796c8dcSSimon Schubert 
26115796c8dcSSimon Schubert    Find the correct "__"-sequence where the function name ends and the
26125796c8dcSSimon Schubert    signature starts, which is ambiguous with GNU mangling.
26135796c8dcSSimon Schubert    Call demangle_signature here, so we can make sure we found the right
26145796c8dcSSimon Schubert    one; *mangled will be consumed so caller will not make further calls to
26155796c8dcSSimon Schubert    demangle_signature.  */
26165796c8dcSSimon Schubert 
26175796c8dcSSimon Schubert static int
iterate_demangle_function(struct work_stuff * work,const char ** mangled,string * declp,const char * scan)26185796c8dcSSimon Schubert iterate_demangle_function (struct work_stuff *work, const char **mangled,
26195796c8dcSSimon Schubert                            string *declp, const char *scan)
26205796c8dcSSimon Schubert {
26215796c8dcSSimon Schubert   const char *mangle_init = *mangled;
26225796c8dcSSimon Schubert   int success = 0;
26235796c8dcSSimon Schubert   string decl_init;
26245796c8dcSSimon Schubert   struct work_stuff work_init;
26255796c8dcSSimon Schubert 
26265796c8dcSSimon Schubert   if (*(scan + 2) == '\0')
26275796c8dcSSimon Schubert     return 0;
26285796c8dcSSimon Schubert 
26295796c8dcSSimon Schubert   /* Do not iterate for some demangling modes, or if there's only one
26305796c8dcSSimon Schubert      "__"-sequence.  This is the normal case.  */
26315796c8dcSSimon Schubert   if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
26325796c8dcSSimon Schubert       || strstr (scan + 2, "__") == NULL)
26335796c8dcSSimon Schubert     return demangle_function_name (work, mangled, declp, scan);
26345796c8dcSSimon Schubert 
26355796c8dcSSimon Schubert   /* Save state so we can restart if the guess at the correct "__" was
26365796c8dcSSimon Schubert      wrong.  */
26375796c8dcSSimon Schubert   string_init (&decl_init);
26385796c8dcSSimon Schubert   string_appends (&decl_init, declp);
26395796c8dcSSimon Schubert   memset (&work_init, 0, sizeof work_init);
26405796c8dcSSimon Schubert   work_stuff_copy_to_from (&work_init, work);
26415796c8dcSSimon Schubert 
26425796c8dcSSimon Schubert   /* Iterate over occurrences of __, allowing names and types to have a
26435796c8dcSSimon Schubert      "__" sequence in them.  We must start with the first (not the last)
26445796c8dcSSimon Schubert      occurrence, since "__" most often occur between independent mangled
26455796c8dcSSimon Schubert      parts, hence starting at the last occurence inside a signature
26465796c8dcSSimon Schubert      might get us a "successful" demangling of the signature.  */
26475796c8dcSSimon Schubert 
26485796c8dcSSimon Schubert   while (scan[2])
26495796c8dcSSimon Schubert     {
26505796c8dcSSimon Schubert       if (demangle_function_name (work, mangled, declp, scan))
26515796c8dcSSimon Schubert 	{
26525796c8dcSSimon Schubert 	  success = demangle_signature (work, mangled, declp);
26535796c8dcSSimon Schubert 	  if (success)
26545796c8dcSSimon Schubert 	    break;
26555796c8dcSSimon Schubert 	}
26565796c8dcSSimon Schubert 
26575796c8dcSSimon Schubert       /* Reset demangle state for the next round.  */
26585796c8dcSSimon Schubert       *mangled = mangle_init;
26595796c8dcSSimon Schubert       string_clear (declp);
26605796c8dcSSimon Schubert       string_appends (declp, &decl_init);
26615796c8dcSSimon Schubert       work_stuff_copy_to_from (work, &work_init);
26625796c8dcSSimon Schubert 
26635796c8dcSSimon Schubert       /* Leave this underscore-sequence.  */
26645796c8dcSSimon Schubert       scan += 2;
26655796c8dcSSimon Schubert 
26665796c8dcSSimon Schubert       /* Scan for the next "__" sequence.  */
26675796c8dcSSimon Schubert       while (*scan && (scan[0] != '_' || scan[1] != '_'))
26685796c8dcSSimon Schubert 	scan++;
26695796c8dcSSimon Schubert 
26705796c8dcSSimon Schubert       /* Move to last "__" in this sequence.  */
26715796c8dcSSimon Schubert       while (*scan && *scan == '_')
26725796c8dcSSimon Schubert 	scan++;
26735796c8dcSSimon Schubert       scan -= 2;
26745796c8dcSSimon Schubert     }
26755796c8dcSSimon Schubert 
26765796c8dcSSimon Schubert   /* Delete saved state.  */
26775796c8dcSSimon Schubert   delete_work_stuff (&work_init);
26785796c8dcSSimon Schubert   string_delete (&decl_init);
26795796c8dcSSimon Schubert 
26805796c8dcSSimon Schubert   return success;
26815796c8dcSSimon Schubert }
26825796c8dcSSimon Schubert 
26835796c8dcSSimon Schubert /*
26845796c8dcSSimon Schubert 
26855796c8dcSSimon Schubert LOCAL FUNCTION
26865796c8dcSSimon Schubert 
26875796c8dcSSimon Schubert 	demangle_prefix -- consume the mangled name prefix and find signature
26885796c8dcSSimon Schubert 
26895796c8dcSSimon Schubert SYNOPSIS
26905796c8dcSSimon Schubert 
26915796c8dcSSimon Schubert 	static int
26925796c8dcSSimon Schubert 	demangle_prefix (struct work_stuff *work, const char **mangled,
26935796c8dcSSimon Schubert 			 string *declp);
26945796c8dcSSimon Schubert 
26955796c8dcSSimon Schubert DESCRIPTION
26965796c8dcSSimon Schubert 
26975796c8dcSSimon Schubert 	Consume and demangle the prefix of the mangled name.
26985796c8dcSSimon Schubert 	While processing the function name root, arrange to call
26995796c8dcSSimon Schubert 	demangle_signature if the root is ambiguous.
27005796c8dcSSimon Schubert 
27015796c8dcSSimon Schubert 	DECLP points to the string buffer into which demangled output is
27025796c8dcSSimon Schubert 	placed.  On entry, the buffer is empty.  On exit it contains
27035796c8dcSSimon Schubert 	the root function name, the demangled operator name, or in some
27045796c8dcSSimon Schubert 	special cases either nothing or the completely demangled result.
27055796c8dcSSimon Schubert 
27065796c8dcSSimon Schubert 	MANGLED points to the current pointer into the mangled name.  As each
27075796c8dcSSimon Schubert 	token of the mangled name is consumed, it is updated.  Upon entry
27085796c8dcSSimon Schubert 	the current mangled name pointer points to the first character of
27095796c8dcSSimon Schubert 	the mangled name.  Upon exit, it should point to the first character
27105796c8dcSSimon Schubert 	of the signature if demangling was successful, or to the first
27115796c8dcSSimon Schubert 	unconsumed character if demangling of the prefix was unsuccessful.
27125796c8dcSSimon Schubert 
27135796c8dcSSimon Schubert 	Returns 1 on success, 0 otherwise.
27145796c8dcSSimon Schubert  */
27155796c8dcSSimon Schubert 
27165796c8dcSSimon Schubert static int
demangle_prefix(struct work_stuff * work,const char ** mangled,string * declp)27175796c8dcSSimon Schubert demangle_prefix (struct work_stuff *work, const char **mangled,
27185796c8dcSSimon Schubert                  string *declp)
27195796c8dcSSimon Schubert {
27205796c8dcSSimon Schubert   int success = 1;
27215796c8dcSSimon Schubert   const char *scan;
27225796c8dcSSimon Schubert   int i;
27235796c8dcSSimon Schubert 
27245796c8dcSSimon Schubert   if (strlen(*mangled) > 6
27255796c8dcSSimon Schubert       && (strncmp(*mangled, "_imp__", 6) == 0
27265796c8dcSSimon Schubert           || strncmp(*mangled, "__imp_", 6) == 0))
27275796c8dcSSimon Schubert     {
27285796c8dcSSimon Schubert       /* it's a symbol imported from a PE dynamic library. Check for both
27295796c8dcSSimon Schubert          new style prefix _imp__ and legacy __imp_ used by older versions
27305796c8dcSSimon Schubert 	 of dlltool. */
27315796c8dcSSimon Schubert       (*mangled) += 6;
27325796c8dcSSimon Schubert       work->dllimported = 1;
27335796c8dcSSimon Schubert     }
27345796c8dcSSimon Schubert   else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
27355796c8dcSSimon Schubert     {
27365796c8dcSSimon Schubert       char *marker = strchr (cplus_markers, (*mangled)[8]);
27375796c8dcSSimon Schubert       if (marker != NULL && *marker == (*mangled)[10])
27385796c8dcSSimon Schubert 	{
27395796c8dcSSimon Schubert 	  if ((*mangled)[9] == 'D')
27405796c8dcSSimon Schubert 	    {
27415796c8dcSSimon Schubert 	      /* it's a GNU global destructor to be executed at program exit */
27425796c8dcSSimon Schubert 	      (*mangled) += 11;
27435796c8dcSSimon Schubert 	      work->destructor = 2;
27445796c8dcSSimon Schubert 	      if (gnu_special (work, mangled, declp))
27455796c8dcSSimon Schubert 		return success;
27465796c8dcSSimon Schubert 	    }
27475796c8dcSSimon Schubert 	  else if ((*mangled)[9] == 'I')
27485796c8dcSSimon Schubert 	    {
27495796c8dcSSimon Schubert 	      /* it's a GNU global constructor to be executed at program init */
27505796c8dcSSimon Schubert 	      (*mangled) += 11;
27515796c8dcSSimon Schubert 	      work->constructor = 2;
27525796c8dcSSimon Schubert 	      if (gnu_special (work, mangled, declp))
27535796c8dcSSimon Schubert 		return success;
27545796c8dcSSimon Schubert 	    }
27555796c8dcSSimon Schubert 	}
27565796c8dcSSimon Schubert     }
27575796c8dcSSimon Schubert   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
27585796c8dcSSimon Schubert     {
27595796c8dcSSimon Schubert       /* it's a ARM global destructor to be executed at program exit */
27605796c8dcSSimon Schubert       (*mangled) += 7;
27615796c8dcSSimon Schubert       work->destructor = 2;
27625796c8dcSSimon Schubert     }
27635796c8dcSSimon Schubert   else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
27645796c8dcSSimon Schubert     {
27655796c8dcSSimon Schubert       /* it's a ARM global constructor to be executed at program initial */
27665796c8dcSSimon Schubert       (*mangled) += 7;
27675796c8dcSSimon Schubert       work->constructor = 2;
27685796c8dcSSimon Schubert     }
27695796c8dcSSimon Schubert 
27705796c8dcSSimon Schubert   /*  This block of code is a reduction in strength time optimization
27715796c8dcSSimon Schubert       of:
27725796c8dcSSimon Schubert       scan = strstr (*mangled, "__"); */
27735796c8dcSSimon Schubert 
27745796c8dcSSimon Schubert   {
27755796c8dcSSimon Schubert     scan = *mangled;
27765796c8dcSSimon Schubert 
27775796c8dcSSimon Schubert     do {
27785796c8dcSSimon Schubert       scan = strchr (scan, '_');
27795796c8dcSSimon Schubert     } while (scan != NULL && *++scan != '_');
27805796c8dcSSimon Schubert 
27815796c8dcSSimon Schubert     if (scan != NULL) --scan;
27825796c8dcSSimon Schubert   }
27835796c8dcSSimon Schubert 
27845796c8dcSSimon Schubert   if (scan != NULL)
27855796c8dcSSimon Schubert     {
27865796c8dcSSimon Schubert       /* We found a sequence of two or more '_', ensure that we start at
27875796c8dcSSimon Schubert 	 the last pair in the sequence.  */
27885796c8dcSSimon Schubert       i = strspn (scan, "_");
27895796c8dcSSimon Schubert       if (i > 2)
27905796c8dcSSimon Schubert 	{
27915796c8dcSSimon Schubert 	  scan += (i - 2);
27925796c8dcSSimon Schubert 	}
27935796c8dcSSimon Schubert     }
27945796c8dcSSimon Schubert 
27955796c8dcSSimon Schubert   if (scan == NULL)
27965796c8dcSSimon Schubert     {
27975796c8dcSSimon Schubert       success = 0;
27985796c8dcSSimon Schubert     }
27995796c8dcSSimon Schubert   else if (work -> static_type)
28005796c8dcSSimon Schubert     {
28015796c8dcSSimon Schubert       if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
28025796c8dcSSimon Schubert 	{
28035796c8dcSSimon Schubert 	  success = 0;
28045796c8dcSSimon Schubert 	}
28055796c8dcSSimon Schubert     }
28065796c8dcSSimon Schubert   else if ((scan == *mangled)
28075796c8dcSSimon Schubert 	   && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
28085796c8dcSSimon Schubert 	       || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
28095796c8dcSSimon Schubert     {
28105796c8dcSSimon Schubert       /* The ARM says nothing about the mangling of local variables.
28115796c8dcSSimon Schubert 	 But cfront mangles local variables by prepending __<nesting_level>
28125796c8dcSSimon Schubert 	 to them. As an extension to ARM demangling we handle this case.  */
28135796c8dcSSimon Schubert       if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
28145796c8dcSSimon Schubert 	  && ISDIGIT ((unsigned char)scan[2]))
28155796c8dcSSimon Schubert 	{
28165796c8dcSSimon Schubert 	  *mangled = scan + 2;
28175796c8dcSSimon Schubert 	  consume_count (mangled);
28185796c8dcSSimon Schubert 	  string_append (declp, *mangled);
28195796c8dcSSimon Schubert 	  *mangled += strlen (*mangled);
28205796c8dcSSimon Schubert 	  success = 1;
28215796c8dcSSimon Schubert 	}
28225796c8dcSSimon Schubert       else
28235796c8dcSSimon Schubert 	{
28245796c8dcSSimon Schubert 	  /* A GNU style constructor starts with __[0-9Qt].  But cfront uses
28255796c8dcSSimon Schubert 	     names like __Q2_3foo3bar for nested type names.  So don't accept
28265796c8dcSSimon Schubert 	     this style of constructor for cfront demangling.  A GNU
28275796c8dcSSimon Schubert 	     style member-template constructor starts with 'H'. */
28285796c8dcSSimon Schubert 	  if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
28295796c8dcSSimon Schubert 	    work -> constructor += 1;
28305796c8dcSSimon Schubert 	  *mangled = scan + 2;
28315796c8dcSSimon Schubert 	}
28325796c8dcSSimon Schubert     }
28335796c8dcSSimon Schubert   else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
28345796c8dcSSimon Schubert     {
28355796c8dcSSimon Schubert       /* Cfront-style parameterized type.  Handled later as a signature. */
28365796c8dcSSimon Schubert       success = 1;
28375796c8dcSSimon Schubert 
28385796c8dcSSimon Schubert       /* ARM template? */
28395796c8dcSSimon Schubert       demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
28405796c8dcSSimon Schubert     }
28415796c8dcSSimon Schubert   else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
28425796c8dcSSimon Schubert                               || (scan[2] == 'p' && scan[3] == 's')
28435796c8dcSSimon Schubert                               || (scan[2] == 'p' && scan[3] == 't')))
28445796c8dcSSimon Schubert     {
28455796c8dcSSimon Schubert       /* EDG-style parameterized type.  Handled later as a signature. */
28465796c8dcSSimon Schubert       success = 1;
28475796c8dcSSimon Schubert 
28485796c8dcSSimon Schubert       /* EDG template? */
28495796c8dcSSimon Schubert       demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
28505796c8dcSSimon Schubert     }
28515796c8dcSSimon Schubert   else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
28525796c8dcSSimon Schubert 	   && (scan[2] != 't'))
28535796c8dcSSimon Schubert     {
28545796c8dcSSimon Schubert       /* Mangled name starts with "__".  Skip over any leading '_' characters,
28555796c8dcSSimon Schubert 	 then find the next "__" that separates the prefix from the signature.
28565796c8dcSSimon Schubert 	 */
28575796c8dcSSimon Schubert       if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
28585796c8dcSSimon Schubert 	  || (arm_special (mangled, declp) == 0))
28595796c8dcSSimon Schubert 	{
28605796c8dcSSimon Schubert 	  while (*scan == '_')
28615796c8dcSSimon Schubert 	    {
28625796c8dcSSimon Schubert 	      scan++;
28635796c8dcSSimon Schubert 	    }
28645796c8dcSSimon Schubert 	  if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
28655796c8dcSSimon Schubert 	    {
28665796c8dcSSimon Schubert 	      /* No separator (I.E. "__not_mangled"), or empty signature
28675796c8dcSSimon Schubert 		 (I.E. "__not_mangled_either__") */
28685796c8dcSSimon Schubert 	      success = 0;
28695796c8dcSSimon Schubert 	    }
28705796c8dcSSimon Schubert 	  else
28715796c8dcSSimon Schubert 	    return iterate_demangle_function (work, mangled, declp, scan);
28725796c8dcSSimon Schubert 	}
28735796c8dcSSimon Schubert     }
28745796c8dcSSimon Schubert   else if (*(scan + 2) != '\0')
28755796c8dcSSimon Schubert     {
28765796c8dcSSimon Schubert       /* Mangled name does not start with "__" but does have one somewhere
28775796c8dcSSimon Schubert 	 in there with non empty stuff after it.  Looks like a global
28785796c8dcSSimon Schubert 	 function name.  Iterate over all "__":s until the right
28795796c8dcSSimon Schubert 	 one is found.  */
28805796c8dcSSimon Schubert       return iterate_demangle_function (work, mangled, declp, scan);
28815796c8dcSSimon Schubert     }
28825796c8dcSSimon Schubert   else
28835796c8dcSSimon Schubert     {
28845796c8dcSSimon Schubert       /* Doesn't look like a mangled name */
28855796c8dcSSimon Schubert       success = 0;
28865796c8dcSSimon Schubert     }
28875796c8dcSSimon Schubert 
28885796c8dcSSimon Schubert   if (!success && (work->constructor == 2 || work->destructor == 2))
28895796c8dcSSimon Schubert     {
28905796c8dcSSimon Schubert       string_append (declp, *mangled);
28915796c8dcSSimon Schubert       *mangled += strlen (*mangled);
28925796c8dcSSimon Schubert       success = 1;
28935796c8dcSSimon Schubert     }
28945796c8dcSSimon Schubert   return (success);
28955796c8dcSSimon Schubert }
28965796c8dcSSimon Schubert 
28975796c8dcSSimon Schubert /*
28985796c8dcSSimon Schubert 
28995796c8dcSSimon Schubert LOCAL FUNCTION
29005796c8dcSSimon Schubert 
29015796c8dcSSimon Schubert 	gnu_special -- special handling of gnu mangled strings
29025796c8dcSSimon Schubert 
29035796c8dcSSimon Schubert SYNOPSIS
29045796c8dcSSimon Schubert 
29055796c8dcSSimon Schubert 	static int
29065796c8dcSSimon Schubert 	gnu_special (struct work_stuff *work, const char **mangled,
29075796c8dcSSimon Schubert 		     string *declp);
29085796c8dcSSimon Schubert 
29095796c8dcSSimon Schubert 
29105796c8dcSSimon Schubert DESCRIPTION
29115796c8dcSSimon Schubert 
29125796c8dcSSimon Schubert 	Process some special GNU style mangling forms that don't fit
29135796c8dcSSimon Schubert 	the normal pattern.  For example:
29145796c8dcSSimon Schubert 
29155796c8dcSSimon Schubert 		_$_3foo		(destructor for class foo)
29165796c8dcSSimon Schubert 		_vt$foo		(foo virtual table)
29175796c8dcSSimon Schubert 		_vt$foo$bar	(foo::bar virtual table)
29185796c8dcSSimon Schubert 		__vt_foo	(foo virtual table, new style with thunks)
29195796c8dcSSimon Schubert 		_3foo$varname	(static data member)
29205796c8dcSSimon Schubert 		_Q22rs2tu$vw	(static data member)
29215796c8dcSSimon Schubert 		__t6vector1Zii	(constructor with template)
29225796c8dcSSimon Schubert 		__thunk_4__$_7ostream (virtual function thunk)
29235796c8dcSSimon Schubert  */
29245796c8dcSSimon Schubert 
29255796c8dcSSimon Schubert static int
gnu_special(struct work_stuff * work,const char ** mangled,string * declp)29265796c8dcSSimon Schubert gnu_special (struct work_stuff *work, const char **mangled, string *declp)
29275796c8dcSSimon Schubert {
29285796c8dcSSimon Schubert   int n;
29295796c8dcSSimon Schubert   int success = 1;
29305796c8dcSSimon Schubert   const char *p;
29315796c8dcSSimon Schubert 
29325796c8dcSSimon Schubert   if ((*mangled)[0] == '_'
29335796c8dcSSimon Schubert       && strchr (cplus_markers, (*mangled)[1]) != NULL
29345796c8dcSSimon Schubert       && (*mangled)[2] == '_')
29355796c8dcSSimon Schubert     {
29365796c8dcSSimon Schubert       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
29375796c8dcSSimon Schubert       (*mangled) += 3;
29385796c8dcSSimon Schubert       work -> destructor += 1;
29395796c8dcSSimon Schubert     }
29405796c8dcSSimon Schubert   else if ((*mangled)[0] == '_'
29415796c8dcSSimon Schubert 	   && (((*mangled)[1] == '_'
29425796c8dcSSimon Schubert 		&& (*mangled)[2] == 'v'
29435796c8dcSSimon Schubert 		&& (*mangled)[3] == 't'
29445796c8dcSSimon Schubert 		&& (*mangled)[4] == '_')
29455796c8dcSSimon Schubert 	       || ((*mangled)[1] == 'v'
29465796c8dcSSimon Schubert 		   && (*mangled)[2] == 't'
29475796c8dcSSimon Schubert 		   && strchr (cplus_markers, (*mangled)[3]) != NULL)))
29485796c8dcSSimon Schubert     {
29495796c8dcSSimon Schubert       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
29505796c8dcSSimon Schubert          and create the decl.  Note that we consume the entire mangled
29515796c8dcSSimon Schubert 	 input string, which means that demangle_signature has no work
29525796c8dcSSimon Schubert 	 to do.  */
29535796c8dcSSimon Schubert       if ((*mangled)[2] == 'v')
29545796c8dcSSimon Schubert 	(*mangled) += 5; /* New style, with thunks: "__vt_" */
29555796c8dcSSimon Schubert       else
29565796c8dcSSimon Schubert 	(*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
29575796c8dcSSimon Schubert       while (**mangled != '\0')
29585796c8dcSSimon Schubert 	{
29595796c8dcSSimon Schubert 	  switch (**mangled)
29605796c8dcSSimon Schubert 	    {
29615796c8dcSSimon Schubert 	    case 'Q':
29625796c8dcSSimon Schubert 	    case 'K':
29635796c8dcSSimon Schubert 	      success = demangle_qualified (work, mangled, declp, 0, 1);
29645796c8dcSSimon Schubert 	      break;
29655796c8dcSSimon Schubert 	    case 't':
29665796c8dcSSimon Schubert 	      success = demangle_template (work, mangled, declp, 0, 1,
29675796c8dcSSimon Schubert 					   1);
29685796c8dcSSimon Schubert 	      break;
29695796c8dcSSimon Schubert 	    default:
29705796c8dcSSimon Schubert 	      if (ISDIGIT((unsigned char)*mangled[0]))
29715796c8dcSSimon Schubert 		{
29725796c8dcSSimon Schubert 		  n = consume_count(mangled);
29735796c8dcSSimon Schubert 		  /* We may be seeing a too-large size, or else a
29745796c8dcSSimon Schubert 		     ".<digits>" indicating a static local symbol.  In
29755796c8dcSSimon Schubert 		     any case, declare victory and move on; *don't* try
29765796c8dcSSimon Schubert 		     to use n to allocate.  */
29775796c8dcSSimon Schubert 		  if (n > (int) strlen (*mangled))
29785796c8dcSSimon Schubert 		    {
29795796c8dcSSimon Schubert 		      success = 1;
29805796c8dcSSimon Schubert 		      break;
29815796c8dcSSimon Schubert 		    }
29825796c8dcSSimon Schubert 		}
29835796c8dcSSimon Schubert 	      else
29845796c8dcSSimon Schubert 		{
29855796c8dcSSimon Schubert 		  n = strcspn (*mangled, cplus_markers);
29865796c8dcSSimon Schubert 		}
29875796c8dcSSimon Schubert 	      string_appendn (declp, *mangled, n);
29885796c8dcSSimon Schubert 	      (*mangled) += n;
29895796c8dcSSimon Schubert 	    }
29905796c8dcSSimon Schubert 
29915796c8dcSSimon Schubert 	  p = strpbrk (*mangled, cplus_markers);
29925796c8dcSSimon Schubert 	  if (success && ((p == NULL) || (p == *mangled)))
29935796c8dcSSimon Schubert 	    {
29945796c8dcSSimon Schubert 	      if (p != NULL)
29955796c8dcSSimon Schubert 		{
29965796c8dcSSimon Schubert 		  string_append (declp, SCOPE_STRING (work));
29975796c8dcSSimon Schubert 		  (*mangled)++;
29985796c8dcSSimon Schubert 		}
29995796c8dcSSimon Schubert 	    }
30005796c8dcSSimon Schubert 	  else
30015796c8dcSSimon Schubert 	    {
30025796c8dcSSimon Schubert 	      success = 0;
30035796c8dcSSimon Schubert 	      break;
30045796c8dcSSimon Schubert 	    }
30055796c8dcSSimon Schubert 	}
30065796c8dcSSimon Schubert       if (success)
30075796c8dcSSimon Schubert 	string_append (declp, " virtual table");
30085796c8dcSSimon Schubert     }
30095796c8dcSSimon Schubert   else if ((*mangled)[0] == '_'
30105796c8dcSSimon Schubert 	   && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
30115796c8dcSSimon Schubert 	   && (p = strpbrk (*mangled, cplus_markers)) != NULL)
30125796c8dcSSimon Schubert     {
30135796c8dcSSimon Schubert       /* static data member, "_3foo$varname" for example */
30145796c8dcSSimon Schubert       (*mangled)++;
30155796c8dcSSimon Schubert       switch (**mangled)
30165796c8dcSSimon Schubert 	{
30175796c8dcSSimon Schubert 	case 'Q':
30185796c8dcSSimon Schubert 	case 'K':
30195796c8dcSSimon Schubert 	  success = demangle_qualified (work, mangled, declp, 0, 1);
30205796c8dcSSimon Schubert 	  break;
30215796c8dcSSimon Schubert 	case 't':
30225796c8dcSSimon Schubert 	  success = demangle_template (work, mangled, declp, 0, 1, 1);
30235796c8dcSSimon Schubert 	  break;
30245796c8dcSSimon Schubert 	default:
30255796c8dcSSimon Schubert 	  n = consume_count (mangled);
30265796c8dcSSimon Schubert 	  if (n < 0 || n > (long) strlen (*mangled))
30275796c8dcSSimon Schubert 	    {
30285796c8dcSSimon Schubert 	      success = 0;
30295796c8dcSSimon Schubert 	      break;
30305796c8dcSSimon Schubert 	    }
30315796c8dcSSimon Schubert 
30325796c8dcSSimon Schubert 	  if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
30335796c8dcSSimon Schubert 	      && (*mangled)[9] == 'N'
30345796c8dcSSimon Schubert 	      && (*mangled)[8] == (*mangled)[10]
30355796c8dcSSimon Schubert 	      && strchr (cplus_markers, (*mangled)[8]))
30365796c8dcSSimon Schubert 	    {
30375796c8dcSSimon Schubert 	      /* A member of the anonymous namespace.  There's information
30385796c8dcSSimon Schubert 		 about what identifier or filename it was keyed to, but
30395796c8dcSSimon Schubert 		 it's just there to make the mangled name unique; we just
30405796c8dcSSimon Schubert 		 step over it.  */
30415796c8dcSSimon Schubert 	      string_append (declp, "{anonymous}");
30425796c8dcSSimon Schubert 	      (*mangled) += n;
30435796c8dcSSimon Schubert 
30445796c8dcSSimon Schubert 	      /* Now p points to the marker before the N, so we need to
30455796c8dcSSimon Schubert 		 update it to the first marker after what we consumed.  */
30465796c8dcSSimon Schubert 	      p = strpbrk (*mangled, cplus_markers);
30475796c8dcSSimon Schubert 	      break;
30485796c8dcSSimon Schubert 	    }
30495796c8dcSSimon Schubert 
30505796c8dcSSimon Schubert 	  string_appendn (declp, *mangled, n);
30515796c8dcSSimon Schubert 	  (*mangled) += n;
30525796c8dcSSimon Schubert 	}
30535796c8dcSSimon Schubert       if (success && (p == *mangled))
30545796c8dcSSimon Schubert 	{
30555796c8dcSSimon Schubert 	  /* Consumed everything up to the cplus_marker, append the
30565796c8dcSSimon Schubert 	     variable name.  */
30575796c8dcSSimon Schubert 	  (*mangled)++;
30585796c8dcSSimon Schubert 	  string_append (declp, SCOPE_STRING (work));
30595796c8dcSSimon Schubert 	  n = strlen (*mangled);
30605796c8dcSSimon Schubert 	  string_appendn (declp, *mangled, n);
30615796c8dcSSimon Schubert 	  (*mangled) += n;
30625796c8dcSSimon Schubert 	}
30635796c8dcSSimon Schubert       else
30645796c8dcSSimon Schubert 	{
30655796c8dcSSimon Schubert 	  success = 0;
30665796c8dcSSimon Schubert 	}
30675796c8dcSSimon Schubert     }
30685796c8dcSSimon Schubert   else if (strncmp (*mangled, "__thunk_", 8) == 0)
30695796c8dcSSimon Schubert     {
30705796c8dcSSimon Schubert       int delta;
30715796c8dcSSimon Schubert 
30725796c8dcSSimon Schubert       (*mangled) += 8;
30735796c8dcSSimon Schubert       delta = consume_count (mangled);
30745796c8dcSSimon Schubert       if (delta == -1)
30755796c8dcSSimon Schubert 	success = 0;
30765796c8dcSSimon Schubert       else
30775796c8dcSSimon Schubert 	{
30785796c8dcSSimon Schubert 	  char *method = internal_cplus_demangle (work, ++*mangled);
30795796c8dcSSimon Schubert 
30805796c8dcSSimon Schubert 	  if (method)
30815796c8dcSSimon Schubert 	    {
30825796c8dcSSimon Schubert 	      char buf[50];
30835796c8dcSSimon Schubert 	      sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
30845796c8dcSSimon Schubert 	      string_append (declp, buf);
30855796c8dcSSimon Schubert 	      string_append (declp, method);
30865796c8dcSSimon Schubert 	      free (method);
30875796c8dcSSimon Schubert 	      n = strlen (*mangled);
30885796c8dcSSimon Schubert 	      (*mangled) += n;
30895796c8dcSSimon Schubert 	    }
30905796c8dcSSimon Schubert 	  else
30915796c8dcSSimon Schubert 	    {
30925796c8dcSSimon Schubert 	      success = 0;
30935796c8dcSSimon Schubert 	    }
30945796c8dcSSimon Schubert 	}
30955796c8dcSSimon Schubert     }
30965796c8dcSSimon Schubert   else if (strncmp (*mangled, "__t", 3) == 0
30975796c8dcSSimon Schubert 	   && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
30985796c8dcSSimon Schubert     {
30995796c8dcSSimon Schubert       p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
31005796c8dcSSimon Schubert       (*mangled) += 4;
31015796c8dcSSimon Schubert       switch (**mangled)
31025796c8dcSSimon Schubert 	{
31035796c8dcSSimon Schubert 	case 'Q':
31045796c8dcSSimon Schubert 	case 'K':
31055796c8dcSSimon Schubert 	  success = demangle_qualified (work, mangled, declp, 0, 1);
31065796c8dcSSimon Schubert 	  break;
31075796c8dcSSimon Schubert 	case 't':
31085796c8dcSSimon Schubert 	  success = demangle_template (work, mangled, declp, 0, 1, 1);
31095796c8dcSSimon Schubert 	  break;
31105796c8dcSSimon Schubert 	default:
31115796c8dcSSimon Schubert 	  success = do_type (work, mangled, declp);
31125796c8dcSSimon Schubert 	  break;
31135796c8dcSSimon Schubert 	}
31145796c8dcSSimon Schubert       if (success && **mangled != '\0')
31155796c8dcSSimon Schubert 	success = 0;
31165796c8dcSSimon Schubert       if (success)
31175796c8dcSSimon Schubert 	string_append (declp, p);
31185796c8dcSSimon Schubert     }
31195796c8dcSSimon Schubert   else
31205796c8dcSSimon Schubert     {
31215796c8dcSSimon Schubert       success = 0;
31225796c8dcSSimon Schubert     }
31235796c8dcSSimon Schubert   return (success);
31245796c8dcSSimon Schubert }
31255796c8dcSSimon Schubert 
31265796c8dcSSimon Schubert static void
recursively_demangle(struct work_stuff * work,const char ** mangled,string * result,int namelength)31275796c8dcSSimon Schubert recursively_demangle(struct work_stuff *work, const char **mangled,
31285796c8dcSSimon Schubert                      string *result, int namelength)
31295796c8dcSSimon Schubert {
31305796c8dcSSimon Schubert   char * recurse = (char *)NULL;
31315796c8dcSSimon Schubert   char * recurse_dem = (char *)NULL;
31325796c8dcSSimon Schubert 
31335796c8dcSSimon Schubert   recurse = XNEWVEC (char, namelength + 1);
31345796c8dcSSimon Schubert   memcpy (recurse, *mangled, namelength);
31355796c8dcSSimon Schubert   recurse[namelength] = '\000';
31365796c8dcSSimon Schubert 
31375796c8dcSSimon Schubert   recurse_dem = cplus_demangle (recurse, work->options);
31385796c8dcSSimon Schubert 
31395796c8dcSSimon Schubert   if (recurse_dem)
31405796c8dcSSimon Schubert     {
31415796c8dcSSimon Schubert       string_append (result, recurse_dem);
31425796c8dcSSimon Schubert       free (recurse_dem);
31435796c8dcSSimon Schubert     }
31445796c8dcSSimon Schubert   else
31455796c8dcSSimon Schubert     {
31465796c8dcSSimon Schubert       string_appendn (result, *mangled, namelength);
31475796c8dcSSimon Schubert     }
31485796c8dcSSimon Schubert   free (recurse);
31495796c8dcSSimon Schubert   *mangled += namelength;
31505796c8dcSSimon Schubert }
31515796c8dcSSimon Schubert 
31525796c8dcSSimon Schubert /*
31535796c8dcSSimon Schubert 
31545796c8dcSSimon Schubert LOCAL FUNCTION
31555796c8dcSSimon Schubert 
31565796c8dcSSimon Schubert 	arm_special -- special handling of ARM/lucid mangled strings
31575796c8dcSSimon Schubert 
31585796c8dcSSimon Schubert SYNOPSIS
31595796c8dcSSimon Schubert 
31605796c8dcSSimon Schubert 	static int
31615796c8dcSSimon Schubert 	arm_special (const char **mangled,
31625796c8dcSSimon Schubert 		     string *declp);
31635796c8dcSSimon Schubert 
31645796c8dcSSimon Schubert 
31655796c8dcSSimon Schubert DESCRIPTION
31665796c8dcSSimon Schubert 
31675796c8dcSSimon Schubert 	Process some special ARM style mangling forms that don't fit
31685796c8dcSSimon Schubert 	the normal pattern.  For example:
31695796c8dcSSimon Schubert 
31705796c8dcSSimon Schubert 		__vtbl__3foo		(foo virtual table)
31715796c8dcSSimon Schubert 		__vtbl__3foo__3bar	(bar::foo virtual table)
31725796c8dcSSimon Schubert 
31735796c8dcSSimon Schubert  */
31745796c8dcSSimon Schubert 
31755796c8dcSSimon Schubert static int
arm_special(const char ** mangled,string * declp)31765796c8dcSSimon Schubert arm_special (const char **mangled, string *declp)
31775796c8dcSSimon Schubert {
31785796c8dcSSimon Schubert   int n;
31795796c8dcSSimon Schubert   int success = 1;
31805796c8dcSSimon Schubert   const char *scan;
31815796c8dcSSimon Schubert 
31825796c8dcSSimon Schubert   if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
31835796c8dcSSimon Schubert     {
31845796c8dcSSimon Schubert       /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
31855796c8dcSSimon Schubert          and create the decl.  Note that we consume the entire mangled
31865796c8dcSSimon Schubert 	 input string, which means that demangle_signature has no work
31875796c8dcSSimon Schubert 	 to do.  */
31885796c8dcSSimon Schubert       scan = *mangled + ARM_VTABLE_STRLEN;
31895796c8dcSSimon Schubert       while (*scan != '\0')        /* first check it can be demangled */
31905796c8dcSSimon Schubert         {
31915796c8dcSSimon Schubert           n = consume_count (&scan);
31925796c8dcSSimon Schubert           if (n == -1)
31935796c8dcSSimon Schubert 	    {
31945796c8dcSSimon Schubert 	      return (0);           /* no good */
31955796c8dcSSimon Schubert 	    }
31965796c8dcSSimon Schubert           scan += n;
31975796c8dcSSimon Schubert           if (scan[0] == '_' && scan[1] == '_')
31985796c8dcSSimon Schubert 	    {
31995796c8dcSSimon Schubert 	      scan += 2;
32005796c8dcSSimon Schubert 	    }
32015796c8dcSSimon Schubert         }
32025796c8dcSSimon Schubert       (*mangled) += ARM_VTABLE_STRLEN;
32035796c8dcSSimon Schubert       while (**mangled != '\0')
32045796c8dcSSimon Schubert 	{
32055796c8dcSSimon Schubert 	  n = consume_count (mangled);
32065796c8dcSSimon Schubert           if (n == -1
32075796c8dcSSimon Schubert 	      || n > (long) strlen (*mangled))
32085796c8dcSSimon Schubert 	    return 0;
32095796c8dcSSimon Schubert 	  string_prependn (declp, *mangled, n);
32105796c8dcSSimon Schubert 	  (*mangled) += n;
32115796c8dcSSimon Schubert 	  if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
32125796c8dcSSimon Schubert 	    {
32135796c8dcSSimon Schubert 	      string_prepend (declp, "::");
32145796c8dcSSimon Schubert 	      (*mangled) += 2;
32155796c8dcSSimon Schubert 	    }
32165796c8dcSSimon Schubert 	}
32175796c8dcSSimon Schubert       string_append (declp, " virtual table");
32185796c8dcSSimon Schubert     }
32195796c8dcSSimon Schubert   else
32205796c8dcSSimon Schubert     {
32215796c8dcSSimon Schubert       success = 0;
32225796c8dcSSimon Schubert     }
32235796c8dcSSimon Schubert   return (success);
32245796c8dcSSimon Schubert }
32255796c8dcSSimon Schubert 
32265796c8dcSSimon Schubert /*
32275796c8dcSSimon Schubert 
32285796c8dcSSimon Schubert LOCAL FUNCTION
32295796c8dcSSimon Schubert 
32305796c8dcSSimon Schubert 	demangle_qualified -- demangle 'Q' qualified name strings
32315796c8dcSSimon Schubert 
32325796c8dcSSimon Schubert SYNOPSIS
32335796c8dcSSimon Schubert 
32345796c8dcSSimon Schubert 	static int
32355796c8dcSSimon Schubert 	demangle_qualified (struct work_stuff *, const char *mangled,
32365796c8dcSSimon Schubert 			    string *result, int isfuncname, int append);
32375796c8dcSSimon Schubert 
32385796c8dcSSimon Schubert DESCRIPTION
32395796c8dcSSimon Schubert 
32405796c8dcSSimon Schubert 	Demangle a qualified name, such as "Q25Outer5Inner" which is
32415796c8dcSSimon Schubert 	the mangled form of "Outer::Inner".  The demangled output is
32425796c8dcSSimon Schubert 	prepended or appended to the result string according to the
32435796c8dcSSimon Schubert 	state of the append flag.
32445796c8dcSSimon Schubert 
32455796c8dcSSimon Schubert 	If isfuncname is nonzero, then the qualified name we are building
32465796c8dcSSimon Schubert 	is going to be used as a member function name, so if it is a
32475796c8dcSSimon Schubert 	constructor or destructor function, append an appropriate
32485796c8dcSSimon Schubert 	constructor or destructor name.  I.E. for the above example,
32495796c8dcSSimon Schubert 	the result for use as a constructor is "Outer::Inner::Inner"
32505796c8dcSSimon Schubert 	and the result for use as a destructor is "Outer::Inner::~Inner".
32515796c8dcSSimon Schubert 
32525796c8dcSSimon Schubert BUGS
32535796c8dcSSimon Schubert 
32545796c8dcSSimon Schubert 	Numeric conversion is ASCII dependent (FIXME).
32555796c8dcSSimon Schubert 
32565796c8dcSSimon Schubert  */
32575796c8dcSSimon Schubert 
32585796c8dcSSimon Schubert static int
demangle_qualified(struct work_stuff * work,const char ** mangled,string * result,int isfuncname,int append)32595796c8dcSSimon Schubert demangle_qualified (struct work_stuff *work, const char **mangled,
32605796c8dcSSimon Schubert                     string *result, int isfuncname, int append)
32615796c8dcSSimon Schubert {
32625796c8dcSSimon Schubert   int qualifiers = 0;
32635796c8dcSSimon Schubert   int success = 1;
32645796c8dcSSimon Schubert   char num[2];
32655796c8dcSSimon Schubert   string temp;
32665796c8dcSSimon Schubert   string last_name;
32675796c8dcSSimon Schubert   int bindex = register_Btype (work);
32685796c8dcSSimon Schubert 
32695796c8dcSSimon Schubert   /* We only make use of ISFUNCNAME if the entity is a constructor or
32705796c8dcSSimon Schubert      destructor.  */
32715796c8dcSSimon Schubert   isfuncname = (isfuncname
32725796c8dcSSimon Schubert 		&& ((work->constructor & 1) || (work->destructor & 1)));
32735796c8dcSSimon Schubert 
32745796c8dcSSimon Schubert   string_init (&temp);
32755796c8dcSSimon Schubert   string_init (&last_name);
32765796c8dcSSimon Schubert 
32775796c8dcSSimon Schubert   if ((*mangled)[0] == 'K')
32785796c8dcSSimon Schubert     {
32795796c8dcSSimon Schubert     /* Squangling qualified name reuse */
32805796c8dcSSimon Schubert       int idx;
32815796c8dcSSimon Schubert       (*mangled)++;
32825796c8dcSSimon Schubert       idx = consume_count_with_underscores (mangled);
32835796c8dcSSimon Schubert       if (idx == -1 || idx >= work -> numk)
32845796c8dcSSimon Schubert         success = 0;
32855796c8dcSSimon Schubert       else
32865796c8dcSSimon Schubert         string_append (&temp, work -> ktypevec[idx]);
32875796c8dcSSimon Schubert     }
32885796c8dcSSimon Schubert   else
32895796c8dcSSimon Schubert     switch ((*mangled)[1])
32905796c8dcSSimon Schubert     {
32915796c8dcSSimon Schubert     case '_':
32925796c8dcSSimon Schubert       /* GNU mangled name with more than 9 classes.  The count is preceded
32935796c8dcSSimon Schubert 	 by an underscore (to distinguish it from the <= 9 case) and followed
32945796c8dcSSimon Schubert 	 by an underscore.  */
32955796c8dcSSimon Schubert       (*mangled)++;
32965796c8dcSSimon Schubert       qualifiers = consume_count_with_underscores (mangled);
32975796c8dcSSimon Schubert       if (qualifiers == -1)
32985796c8dcSSimon Schubert 	success = 0;
32995796c8dcSSimon Schubert       break;
33005796c8dcSSimon Schubert 
33015796c8dcSSimon Schubert     case '1':
33025796c8dcSSimon Schubert     case '2':
33035796c8dcSSimon Schubert     case '3':
33045796c8dcSSimon Schubert     case '4':
33055796c8dcSSimon Schubert     case '5':
33065796c8dcSSimon Schubert     case '6':
33075796c8dcSSimon Schubert     case '7':
33085796c8dcSSimon Schubert     case '8':
33095796c8dcSSimon Schubert     case '9':
33105796c8dcSSimon Schubert       /* The count is in a single digit.  */
33115796c8dcSSimon Schubert       num[0] = (*mangled)[1];
33125796c8dcSSimon Schubert       num[1] = '\0';
33135796c8dcSSimon Schubert       qualifiers = atoi (num);
33145796c8dcSSimon Schubert 
33155796c8dcSSimon Schubert       /* If there is an underscore after the digit, skip it.  This is
33165796c8dcSSimon Schubert 	 said to be for ARM-qualified names, but the ARM makes no
33175796c8dcSSimon Schubert 	 mention of such an underscore.  Perhaps cfront uses one.  */
33185796c8dcSSimon Schubert       if ((*mangled)[2] == '_')
33195796c8dcSSimon Schubert 	{
33205796c8dcSSimon Schubert 	  (*mangled)++;
33215796c8dcSSimon Schubert 	}
33225796c8dcSSimon Schubert       (*mangled) += 2;
33235796c8dcSSimon Schubert       break;
33245796c8dcSSimon Schubert 
33255796c8dcSSimon Schubert     case '0':
33265796c8dcSSimon Schubert     default:
33275796c8dcSSimon Schubert       success = 0;
33285796c8dcSSimon Schubert     }
33295796c8dcSSimon Schubert 
33305796c8dcSSimon Schubert   if (!success)
33315796c8dcSSimon Schubert     return success;
33325796c8dcSSimon Schubert 
33335796c8dcSSimon Schubert   /* Pick off the names and collect them in the temp buffer in the order
33345796c8dcSSimon Schubert      in which they are found, separated by '::'.  */
33355796c8dcSSimon Schubert 
33365796c8dcSSimon Schubert   while (qualifiers-- > 0)
33375796c8dcSSimon Schubert     {
33385796c8dcSSimon Schubert       int remember_K = 1;
33395796c8dcSSimon Schubert       string_clear (&last_name);
33405796c8dcSSimon Schubert 
33415796c8dcSSimon Schubert       if (*mangled[0] == '_')
33425796c8dcSSimon Schubert 	(*mangled)++;
33435796c8dcSSimon Schubert 
33445796c8dcSSimon Schubert       if (*mangled[0] == 't')
33455796c8dcSSimon Schubert 	{
33465796c8dcSSimon Schubert 	  /* Here we always append to TEMP since we will want to use
33475796c8dcSSimon Schubert 	     the template name without the template parameters as a
33485796c8dcSSimon Schubert 	     constructor or destructor name.  The appropriate
33495796c8dcSSimon Schubert 	     (parameter-less) value is returned by demangle_template
33505796c8dcSSimon Schubert 	     in LAST_NAME.  We do not remember the template type here,
33515796c8dcSSimon Schubert 	     in order to match the G++ mangling algorithm.  */
33525796c8dcSSimon Schubert 	  success = demangle_template(work, mangled, &temp,
33535796c8dcSSimon Schubert 				      &last_name, 1, 0);
33545796c8dcSSimon Schubert 	  if (!success)
33555796c8dcSSimon Schubert 	    break;
33565796c8dcSSimon Schubert 	}
33575796c8dcSSimon Schubert       else if (*mangled[0] == 'K')
33585796c8dcSSimon Schubert 	{
33595796c8dcSSimon Schubert           int idx;
33605796c8dcSSimon Schubert           (*mangled)++;
33615796c8dcSSimon Schubert           idx = consume_count_with_underscores (mangled);
33625796c8dcSSimon Schubert           if (idx == -1 || idx >= work->numk)
33635796c8dcSSimon Schubert             success = 0;
33645796c8dcSSimon Schubert           else
33655796c8dcSSimon Schubert             string_append (&temp, work->ktypevec[idx]);
33665796c8dcSSimon Schubert           remember_K = 0;
33675796c8dcSSimon Schubert 
33685796c8dcSSimon Schubert 	  if (!success) break;
33695796c8dcSSimon Schubert 	}
33705796c8dcSSimon Schubert       else
33715796c8dcSSimon Schubert 	{
33725796c8dcSSimon Schubert 	  if (EDG_DEMANGLING)
33735796c8dcSSimon Schubert             {
33745796c8dcSSimon Schubert 	      int namelength;
33755796c8dcSSimon Schubert  	      /* Now recursively demangle the qualifier
33765796c8dcSSimon Schubert  	       * This is necessary to deal with templates in
33775796c8dcSSimon Schubert  	       * mangling styles like EDG */
33785796c8dcSSimon Schubert 	      namelength = consume_count (mangled);
33795796c8dcSSimon Schubert 	      if (namelength == -1)
33805796c8dcSSimon Schubert 		{
33815796c8dcSSimon Schubert 		  success = 0;
33825796c8dcSSimon Schubert 		  break;
33835796c8dcSSimon Schubert 		}
33845796c8dcSSimon Schubert  	      recursively_demangle(work, mangled, &temp, namelength);
33855796c8dcSSimon Schubert             }
33865796c8dcSSimon Schubert           else
33875796c8dcSSimon Schubert             {
33885796c8dcSSimon Schubert               string_delete (&last_name);
33895796c8dcSSimon Schubert               success = do_type (work, mangled, &last_name);
33905796c8dcSSimon Schubert               if (!success)
33915796c8dcSSimon Schubert                 break;
33925796c8dcSSimon Schubert               string_appends (&temp, &last_name);
33935796c8dcSSimon Schubert             }
33945796c8dcSSimon Schubert 	}
33955796c8dcSSimon Schubert 
33965796c8dcSSimon Schubert       if (remember_K)
33975796c8dcSSimon Schubert 	remember_Ktype (work, temp.b, LEN_STRING (&temp));
33985796c8dcSSimon Schubert 
33995796c8dcSSimon Schubert       if (qualifiers > 0)
34005796c8dcSSimon Schubert 	string_append (&temp, SCOPE_STRING (work));
34015796c8dcSSimon Schubert     }
34025796c8dcSSimon Schubert 
34035796c8dcSSimon Schubert   remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
34045796c8dcSSimon Schubert 
34055796c8dcSSimon Schubert   /* If we are using the result as a function name, we need to append
34065796c8dcSSimon Schubert      the appropriate '::' separated constructor or destructor name.
34075796c8dcSSimon Schubert      We do this here because this is the most convenient place, where
34085796c8dcSSimon Schubert      we already have a pointer to the name and the length of the name.  */
34095796c8dcSSimon Schubert 
34105796c8dcSSimon Schubert   if (isfuncname)
34115796c8dcSSimon Schubert     {
34125796c8dcSSimon Schubert       string_append (&temp, SCOPE_STRING (work));
34135796c8dcSSimon Schubert       if (work -> destructor & 1)
34145796c8dcSSimon Schubert 	string_append (&temp, "~");
34155796c8dcSSimon Schubert       string_appends (&temp, &last_name);
34165796c8dcSSimon Schubert     }
34175796c8dcSSimon Schubert 
34185796c8dcSSimon Schubert   /* Now either prepend the temp buffer to the result, or append it,
34195796c8dcSSimon Schubert      depending upon the state of the append flag.  */
34205796c8dcSSimon Schubert 
34215796c8dcSSimon Schubert   if (append)
34225796c8dcSSimon Schubert     string_appends (result, &temp);
34235796c8dcSSimon Schubert   else
34245796c8dcSSimon Schubert     {
34255796c8dcSSimon Schubert       if (!STRING_EMPTY (result))
34265796c8dcSSimon Schubert 	string_append (&temp, SCOPE_STRING (work));
34275796c8dcSSimon Schubert       string_prepends (result, &temp);
34285796c8dcSSimon Schubert     }
34295796c8dcSSimon Schubert 
34305796c8dcSSimon Schubert   string_delete (&last_name);
34315796c8dcSSimon Schubert   string_delete (&temp);
34325796c8dcSSimon Schubert   return (success);
34335796c8dcSSimon Schubert }
34345796c8dcSSimon Schubert 
34355796c8dcSSimon Schubert /*
34365796c8dcSSimon Schubert 
34375796c8dcSSimon Schubert LOCAL FUNCTION
34385796c8dcSSimon Schubert 
34395796c8dcSSimon Schubert 	get_count -- convert an ascii count to integer, consuming tokens
34405796c8dcSSimon Schubert 
34415796c8dcSSimon Schubert SYNOPSIS
34425796c8dcSSimon Schubert 
34435796c8dcSSimon Schubert 	static int
34445796c8dcSSimon Schubert 	get_count (const char **type, int *count)
34455796c8dcSSimon Schubert 
34465796c8dcSSimon Schubert DESCRIPTION
34475796c8dcSSimon Schubert 
34485796c8dcSSimon Schubert 	Assume that *type points at a count in a mangled name; set
34495796c8dcSSimon Schubert 	*count to its value, and set *type to the next character after
34505796c8dcSSimon Schubert 	the count.  There are some weird rules in effect here.
34515796c8dcSSimon Schubert 
34525796c8dcSSimon Schubert 	If *type does not point at a string of digits, return zero.
34535796c8dcSSimon Schubert 
34545796c8dcSSimon Schubert 	If *type points at a string of digits followed by an
34555796c8dcSSimon Schubert 	underscore, set *count to their value as an integer, advance
34565796c8dcSSimon Schubert 	*type to point *after the underscore, and return 1.
34575796c8dcSSimon Schubert 
34585796c8dcSSimon Schubert 	If *type points at a string of digits not followed by an
34595796c8dcSSimon Schubert 	underscore, consume only the first digit.  Set *count to its
34605796c8dcSSimon Schubert 	value as an integer, leave *type pointing after that digit,
34615796c8dcSSimon Schubert 	and return 1.
34625796c8dcSSimon Schubert 
34635796c8dcSSimon Schubert         The excuse for this odd behavior: in the ARM and HP demangling
34645796c8dcSSimon Schubert         styles, a type can be followed by a repeat count of the form
34655796c8dcSSimon Schubert         `Nxy', where:
34665796c8dcSSimon Schubert 
34675796c8dcSSimon Schubert         `x' is a single digit specifying how many additional copies
34685796c8dcSSimon Schubert             of the type to append to the argument list, and
34695796c8dcSSimon Schubert 
34705796c8dcSSimon Schubert         `y' is one or more digits, specifying the zero-based index of
34715796c8dcSSimon Schubert             the first repeated argument in the list.  Yes, as you're
34725796c8dcSSimon Schubert             unmangling the name you can figure this out yourself, but
34735796c8dcSSimon Schubert             it's there anyway.
34745796c8dcSSimon Schubert 
34755796c8dcSSimon Schubert         So, for example, in `bar__3fooFPiN51', the first argument is a
34765796c8dcSSimon Schubert         pointer to an integer (`Pi'), and then the next five arguments
34775796c8dcSSimon Schubert         are the same (`N5'), and the first repeat is the function's
34785796c8dcSSimon Schubert         second argument (`1').
34795796c8dcSSimon Schubert */
34805796c8dcSSimon Schubert 
34815796c8dcSSimon Schubert static int
get_count(const char ** type,int * count)34825796c8dcSSimon Schubert get_count (const char **type, int *count)
34835796c8dcSSimon Schubert {
34845796c8dcSSimon Schubert   const char *p;
34855796c8dcSSimon Schubert   int n;
34865796c8dcSSimon Schubert 
34875796c8dcSSimon Schubert   if (!ISDIGIT ((unsigned char)**type))
34885796c8dcSSimon Schubert     return (0);
34895796c8dcSSimon Schubert   else
34905796c8dcSSimon Schubert     {
34915796c8dcSSimon Schubert       *count = **type - '0';
34925796c8dcSSimon Schubert       (*type)++;
34935796c8dcSSimon Schubert       if (ISDIGIT ((unsigned char)**type))
34945796c8dcSSimon Schubert 	{
34955796c8dcSSimon Schubert 	  p = *type;
34965796c8dcSSimon Schubert 	  n = *count;
34975796c8dcSSimon Schubert 	  do
34985796c8dcSSimon Schubert 	    {
34995796c8dcSSimon Schubert 	      n *= 10;
35005796c8dcSSimon Schubert 	      n += *p - '0';
35015796c8dcSSimon Schubert 	      p++;
35025796c8dcSSimon Schubert 	    }
35035796c8dcSSimon Schubert 	  while (ISDIGIT ((unsigned char)*p));
35045796c8dcSSimon Schubert 	  if (*p == '_')
35055796c8dcSSimon Schubert 	    {
35065796c8dcSSimon Schubert 	      *type = p + 1;
35075796c8dcSSimon Schubert 	      *count = n;
35085796c8dcSSimon Schubert 	    }
35095796c8dcSSimon Schubert 	}
35105796c8dcSSimon Schubert     }
35115796c8dcSSimon Schubert   return (1);
35125796c8dcSSimon Schubert }
35135796c8dcSSimon Schubert 
35145796c8dcSSimon Schubert /* RESULT will be initialised here; it will be freed on failure.  The
35155796c8dcSSimon Schubert    value returned is really a type_kind_t.  */
35165796c8dcSSimon Schubert 
35175796c8dcSSimon Schubert static int
do_type(struct work_stuff * work,const char ** mangled,string * result)35185796c8dcSSimon Schubert do_type (struct work_stuff *work, const char **mangled, string *result)
35195796c8dcSSimon Schubert {
35205796c8dcSSimon Schubert   int n;
35215796c8dcSSimon Schubert   int done;
35225796c8dcSSimon Schubert   int success;
35235796c8dcSSimon Schubert   string decl;
35245796c8dcSSimon Schubert   const char *remembered_type;
35255796c8dcSSimon Schubert   int type_quals;
35265796c8dcSSimon Schubert   type_kind_t tk = tk_none;
35275796c8dcSSimon Schubert 
35285796c8dcSSimon Schubert   string_init (&decl);
35295796c8dcSSimon Schubert   string_init (result);
35305796c8dcSSimon Schubert 
35315796c8dcSSimon Schubert   done = 0;
35325796c8dcSSimon Schubert   success = 1;
35335796c8dcSSimon Schubert   while (success && !done)
35345796c8dcSSimon Schubert     {
35355796c8dcSSimon Schubert       int member;
35365796c8dcSSimon Schubert       switch (**mangled)
35375796c8dcSSimon Schubert 	{
35385796c8dcSSimon Schubert 
35395796c8dcSSimon Schubert 	  /* A pointer type */
35405796c8dcSSimon Schubert 	case 'P':
35415796c8dcSSimon Schubert 	case 'p':
35425796c8dcSSimon Schubert 	  (*mangled)++;
35435796c8dcSSimon Schubert 	  if (! (work -> options & DMGL_JAVA))
35445796c8dcSSimon Schubert 	    string_prepend (&decl, "*");
35455796c8dcSSimon Schubert 	  if (tk == tk_none)
35465796c8dcSSimon Schubert 	    tk = tk_pointer;
35475796c8dcSSimon Schubert 	  break;
35485796c8dcSSimon Schubert 
35495796c8dcSSimon Schubert 	  /* A reference type */
35505796c8dcSSimon Schubert 	case 'R':
35515796c8dcSSimon Schubert 	  (*mangled)++;
35525796c8dcSSimon Schubert 	  string_prepend (&decl, "&");
35535796c8dcSSimon Schubert 	  if (tk == tk_none)
35545796c8dcSSimon Schubert 	    tk = tk_reference;
35555796c8dcSSimon Schubert 	  break;
35565796c8dcSSimon Schubert 
35575796c8dcSSimon Schubert 	  /* An array */
35585796c8dcSSimon Schubert 	case 'A':
35595796c8dcSSimon Schubert 	  {
35605796c8dcSSimon Schubert 	    ++(*mangled);
35615796c8dcSSimon Schubert 	    if (!STRING_EMPTY (&decl)
35625796c8dcSSimon Schubert 		&& (decl.b[0] == '*' || decl.b[0] == '&'))
35635796c8dcSSimon Schubert 	      {
35645796c8dcSSimon Schubert 		string_prepend (&decl, "(");
35655796c8dcSSimon Schubert 		string_append (&decl, ")");
35665796c8dcSSimon Schubert 	      }
35675796c8dcSSimon Schubert 	    string_append (&decl, "[");
35685796c8dcSSimon Schubert 	    if (**mangled != '_')
35695796c8dcSSimon Schubert 	      success = demangle_template_value_parm (work, mangled, &decl,
35705796c8dcSSimon Schubert 						      tk_integral);
35715796c8dcSSimon Schubert 	    if (**mangled == '_')
35725796c8dcSSimon Schubert 	      ++(*mangled);
35735796c8dcSSimon Schubert 	    string_append (&decl, "]");
35745796c8dcSSimon Schubert 	    break;
35755796c8dcSSimon Schubert 	  }
35765796c8dcSSimon Schubert 
35775796c8dcSSimon Schubert 	/* A back reference to a previously seen type */
35785796c8dcSSimon Schubert 	case 'T':
35795796c8dcSSimon Schubert 	  (*mangled)++;
35805796c8dcSSimon Schubert 	  if (!get_count (mangled, &n) || n >= work -> ntypes)
35815796c8dcSSimon Schubert 	    {
35825796c8dcSSimon Schubert 	      success = 0;
35835796c8dcSSimon Schubert 	    }
35845796c8dcSSimon Schubert 	  else
35855796c8dcSSimon Schubert 	    {
35865796c8dcSSimon Schubert 	      remembered_type = work -> typevec[n];
35875796c8dcSSimon Schubert 	      mangled = &remembered_type;
35885796c8dcSSimon Schubert 	    }
35895796c8dcSSimon Schubert 	  break;
35905796c8dcSSimon Schubert 
35915796c8dcSSimon Schubert 	  /* A function */
35925796c8dcSSimon Schubert 	case 'F':
35935796c8dcSSimon Schubert 	  (*mangled)++;
35945796c8dcSSimon Schubert 	    if (!STRING_EMPTY (&decl)
35955796c8dcSSimon Schubert 		&& (decl.b[0] == '*' || decl.b[0] == '&'))
35965796c8dcSSimon Schubert 	    {
35975796c8dcSSimon Schubert 	      string_prepend (&decl, "(");
35985796c8dcSSimon Schubert 	      string_append (&decl, ")");
35995796c8dcSSimon Schubert 	    }
36005796c8dcSSimon Schubert 	  /* After picking off the function args, we expect to either find the
36015796c8dcSSimon Schubert 	     function return type (preceded by an '_') or the end of the
36025796c8dcSSimon Schubert 	     string.  */
36035796c8dcSSimon Schubert 	  if (!demangle_nested_args (work, mangled, &decl)
36045796c8dcSSimon Schubert 	      || (**mangled != '_' && **mangled != '\0'))
36055796c8dcSSimon Schubert 	    {
36065796c8dcSSimon Schubert 	      success = 0;
36075796c8dcSSimon Schubert 	      break;
36085796c8dcSSimon Schubert 	    }
36095796c8dcSSimon Schubert 	  if (success && (**mangled == '_'))
36105796c8dcSSimon Schubert 	    (*mangled)++;
36115796c8dcSSimon Schubert 	  break;
36125796c8dcSSimon Schubert 
36135796c8dcSSimon Schubert 	case 'M':
36145796c8dcSSimon Schubert 	case 'O':
36155796c8dcSSimon Schubert 	  {
36165796c8dcSSimon Schubert 	    type_quals = TYPE_UNQUALIFIED;
36175796c8dcSSimon Schubert 
36185796c8dcSSimon Schubert 	    member = **mangled == 'M';
36195796c8dcSSimon Schubert 	    (*mangled)++;
36205796c8dcSSimon Schubert 
36215796c8dcSSimon Schubert 	    string_append (&decl, ")");
36225796c8dcSSimon Schubert 
36235796c8dcSSimon Schubert 	    /* We don't need to prepend `::' for a qualified name;
36245796c8dcSSimon Schubert 	       demangle_qualified will do that for us.  */
36255796c8dcSSimon Schubert 	    if (**mangled != 'Q')
36265796c8dcSSimon Schubert 	      string_prepend (&decl, SCOPE_STRING (work));
36275796c8dcSSimon Schubert 
36285796c8dcSSimon Schubert 	    if (ISDIGIT ((unsigned char)**mangled))
36295796c8dcSSimon Schubert 	      {
36305796c8dcSSimon Schubert 		n = consume_count (mangled);
36315796c8dcSSimon Schubert 		if (n == -1
36325796c8dcSSimon Schubert 		    || (int) strlen (*mangled) < n)
36335796c8dcSSimon Schubert 		  {
36345796c8dcSSimon Schubert 		    success = 0;
36355796c8dcSSimon Schubert 		    break;
36365796c8dcSSimon Schubert 		  }
36375796c8dcSSimon Schubert 		string_prependn (&decl, *mangled, n);
36385796c8dcSSimon Schubert 		*mangled += n;
36395796c8dcSSimon Schubert 	      }
36405796c8dcSSimon Schubert 	    else if (**mangled == 'X' || **mangled == 'Y')
36415796c8dcSSimon Schubert 	      {
36425796c8dcSSimon Schubert 		string temp;
36435796c8dcSSimon Schubert 		do_type (work, mangled, &temp);
36445796c8dcSSimon Schubert 		string_prepends (&decl, &temp);
36455796c8dcSSimon Schubert 		string_delete (&temp);
36465796c8dcSSimon Schubert 	      }
36475796c8dcSSimon Schubert 	    else if (**mangled == 't')
36485796c8dcSSimon Schubert 	      {
36495796c8dcSSimon Schubert 		string temp;
36505796c8dcSSimon Schubert 		string_init (&temp);
36515796c8dcSSimon Schubert 		success = demangle_template (work, mangled, &temp,
36525796c8dcSSimon Schubert 					     NULL, 1, 1);
36535796c8dcSSimon Schubert 		if (success)
36545796c8dcSSimon Schubert 		  {
36555796c8dcSSimon Schubert 		    string_prependn (&decl, temp.b, temp.p - temp.b);
36565796c8dcSSimon Schubert 		    string_delete (&temp);
36575796c8dcSSimon Schubert 		  }
36585796c8dcSSimon Schubert 		else
36595796c8dcSSimon Schubert 		  break;
36605796c8dcSSimon Schubert 	      }
36615796c8dcSSimon Schubert 	    else if (**mangled == 'Q')
36625796c8dcSSimon Schubert 	      {
36635796c8dcSSimon Schubert 		success = demangle_qualified (work, mangled, &decl,
36645796c8dcSSimon Schubert 					      /*isfuncnam=*/0,
36655796c8dcSSimon Schubert 					      /*append=*/0);
36665796c8dcSSimon Schubert 		if (!success)
36675796c8dcSSimon Schubert 		  break;
36685796c8dcSSimon Schubert 	      }
36695796c8dcSSimon Schubert 	    else
36705796c8dcSSimon Schubert 	      {
36715796c8dcSSimon Schubert 		success = 0;
36725796c8dcSSimon Schubert 		break;
36735796c8dcSSimon Schubert 	      }
36745796c8dcSSimon Schubert 
36755796c8dcSSimon Schubert 	    string_prepend (&decl, "(");
36765796c8dcSSimon Schubert 	    if (member)
36775796c8dcSSimon Schubert 	      {
36785796c8dcSSimon Schubert 		switch (**mangled)
36795796c8dcSSimon Schubert 		  {
36805796c8dcSSimon Schubert 		  case 'C':
36815796c8dcSSimon Schubert 		  case 'V':
36825796c8dcSSimon Schubert 		  case 'u':
36835796c8dcSSimon Schubert 		    type_quals |= code_for_qualifier (**mangled);
36845796c8dcSSimon Schubert 		    (*mangled)++;
36855796c8dcSSimon Schubert 		    break;
36865796c8dcSSimon Schubert 
36875796c8dcSSimon Schubert 		  default:
36885796c8dcSSimon Schubert 		    break;
36895796c8dcSSimon Schubert 		  }
36905796c8dcSSimon Schubert 
36915796c8dcSSimon Schubert 		if (*(*mangled)++ != 'F')
36925796c8dcSSimon Schubert 		  {
36935796c8dcSSimon Schubert 		    success = 0;
36945796c8dcSSimon Schubert 		    break;
36955796c8dcSSimon Schubert 		  }
36965796c8dcSSimon Schubert 	      }
36975796c8dcSSimon Schubert 	    if ((member && !demangle_nested_args (work, mangled, &decl))
36985796c8dcSSimon Schubert 		|| **mangled != '_')
36995796c8dcSSimon Schubert 	      {
37005796c8dcSSimon Schubert 		success = 0;
37015796c8dcSSimon Schubert 		break;
37025796c8dcSSimon Schubert 	      }
37035796c8dcSSimon Schubert 	    (*mangled)++;
37045796c8dcSSimon Schubert 	    if (! PRINT_ANSI_QUALIFIERS)
37055796c8dcSSimon Schubert 	      {
37065796c8dcSSimon Schubert 		break;
37075796c8dcSSimon Schubert 	      }
37085796c8dcSSimon Schubert 	    if (type_quals != TYPE_UNQUALIFIED)
37095796c8dcSSimon Schubert 	      {
37105796c8dcSSimon Schubert 		APPEND_BLANK (&decl);
37115796c8dcSSimon Schubert 		string_append (&decl, qualifier_string (type_quals));
37125796c8dcSSimon Schubert 	      }
37135796c8dcSSimon Schubert 	    break;
37145796c8dcSSimon Schubert 	  }
37155796c8dcSSimon Schubert         case 'G':
37165796c8dcSSimon Schubert 	  (*mangled)++;
37175796c8dcSSimon Schubert 	  break;
37185796c8dcSSimon Schubert 
37195796c8dcSSimon Schubert 	case 'C':
37205796c8dcSSimon Schubert 	case 'V':
37215796c8dcSSimon Schubert 	case 'u':
37225796c8dcSSimon Schubert 	  if (PRINT_ANSI_QUALIFIERS)
37235796c8dcSSimon Schubert 	    {
37245796c8dcSSimon Schubert 	      if (!STRING_EMPTY (&decl))
37255796c8dcSSimon Schubert 		string_prepend (&decl, " ");
37265796c8dcSSimon Schubert 
37275796c8dcSSimon Schubert 	      string_prepend (&decl, demangle_qualifier (**mangled));
37285796c8dcSSimon Schubert 	    }
37295796c8dcSSimon Schubert 	  (*mangled)++;
37305796c8dcSSimon Schubert 	  break;
37315796c8dcSSimon Schubert 	  /*
37325796c8dcSSimon Schubert 	    }
37335796c8dcSSimon Schubert 	    */
37345796c8dcSSimon Schubert 
37355796c8dcSSimon Schubert 	  /* fall through */
37365796c8dcSSimon Schubert 	default:
37375796c8dcSSimon Schubert 	  done = 1;
37385796c8dcSSimon Schubert 	  break;
37395796c8dcSSimon Schubert 	}
37405796c8dcSSimon Schubert     }
37415796c8dcSSimon Schubert 
37425796c8dcSSimon Schubert   if (success) switch (**mangled)
37435796c8dcSSimon Schubert     {
37445796c8dcSSimon Schubert       /* A qualified name, such as "Outer::Inner".  */
37455796c8dcSSimon Schubert     case 'Q':
37465796c8dcSSimon Schubert     case 'K':
37475796c8dcSSimon Schubert       {
37485796c8dcSSimon Schubert         success = demangle_qualified (work, mangled, result, 0, 1);
37495796c8dcSSimon Schubert         break;
37505796c8dcSSimon Schubert       }
37515796c8dcSSimon Schubert 
37525796c8dcSSimon Schubert     /* A back reference to a previously seen squangled type */
37535796c8dcSSimon Schubert     case 'B':
37545796c8dcSSimon Schubert       (*mangled)++;
37555796c8dcSSimon Schubert       if (!get_count (mangled, &n) || n >= work -> numb)
37565796c8dcSSimon Schubert 	success = 0;
37575796c8dcSSimon Schubert       else
37585796c8dcSSimon Schubert 	string_append (result, work->btypevec[n]);
37595796c8dcSSimon Schubert       break;
37605796c8dcSSimon Schubert 
37615796c8dcSSimon Schubert     case 'X':
37625796c8dcSSimon Schubert     case 'Y':
37635796c8dcSSimon Schubert       /* A template parm.  We substitute the corresponding argument. */
37645796c8dcSSimon Schubert       {
37655796c8dcSSimon Schubert 	int idx;
37665796c8dcSSimon Schubert 
37675796c8dcSSimon Schubert 	(*mangled)++;
37685796c8dcSSimon Schubert 	idx = consume_count_with_underscores (mangled);
37695796c8dcSSimon Schubert 
37705796c8dcSSimon Schubert 	if (idx == -1
37715796c8dcSSimon Schubert 	    || (work->tmpl_argvec && idx >= work->ntmpl_args)
37725796c8dcSSimon Schubert 	    || consume_count_with_underscores (mangled) == -1)
37735796c8dcSSimon Schubert 	  {
37745796c8dcSSimon Schubert 	    success = 0;
37755796c8dcSSimon Schubert 	    break;
37765796c8dcSSimon Schubert 	  }
37775796c8dcSSimon Schubert 
37785796c8dcSSimon Schubert 	if (work->tmpl_argvec)
37795796c8dcSSimon Schubert 	  string_append (result, work->tmpl_argvec[idx]);
37805796c8dcSSimon Schubert 	else
37815796c8dcSSimon Schubert 	  string_append_template_idx (result, idx);
37825796c8dcSSimon Schubert 
37835796c8dcSSimon Schubert 	success = 1;
37845796c8dcSSimon Schubert       }
37855796c8dcSSimon Schubert     break;
37865796c8dcSSimon Schubert 
37875796c8dcSSimon Schubert     default:
37885796c8dcSSimon Schubert       success = demangle_fund_type (work, mangled, result);
37895796c8dcSSimon Schubert       if (tk == tk_none)
37905796c8dcSSimon Schubert 	tk = (type_kind_t) success;
37915796c8dcSSimon Schubert       break;
37925796c8dcSSimon Schubert     }
37935796c8dcSSimon Schubert 
37945796c8dcSSimon Schubert   if (success)
37955796c8dcSSimon Schubert     {
37965796c8dcSSimon Schubert       if (!STRING_EMPTY (&decl))
37975796c8dcSSimon Schubert 	{
37985796c8dcSSimon Schubert 	  string_append (result, " ");
37995796c8dcSSimon Schubert 	  string_appends (result, &decl);
38005796c8dcSSimon Schubert 	}
38015796c8dcSSimon Schubert     }
38025796c8dcSSimon Schubert   else
38035796c8dcSSimon Schubert     string_delete (result);
38045796c8dcSSimon Schubert   string_delete (&decl);
38055796c8dcSSimon Schubert 
38065796c8dcSSimon Schubert   if (success)
38075796c8dcSSimon Schubert     /* Assume an integral type, if we're not sure.  */
38085796c8dcSSimon Schubert     return (int) ((tk == tk_none) ? tk_integral : tk);
38095796c8dcSSimon Schubert   else
38105796c8dcSSimon Schubert     return 0;
38115796c8dcSSimon Schubert }
38125796c8dcSSimon Schubert 
38135796c8dcSSimon Schubert /* Given a pointer to a type string that represents a fundamental type
38145796c8dcSSimon Schubert    argument (int, long, unsigned int, etc) in TYPE, a pointer to the
38155796c8dcSSimon Schubert    string in which the demangled output is being built in RESULT, and
38165796c8dcSSimon Schubert    the WORK structure, decode the types and add them to the result.
38175796c8dcSSimon Schubert 
38185796c8dcSSimon Schubert    For example:
38195796c8dcSSimon Schubert 
38205796c8dcSSimon Schubert    	"Ci"	=>	"const int"
38215796c8dcSSimon Schubert 	"Sl"	=>	"signed long"
38225796c8dcSSimon Schubert 	"CUs"	=>	"const unsigned short"
38235796c8dcSSimon Schubert 
38245796c8dcSSimon Schubert    The value returned is really a type_kind_t.  */
38255796c8dcSSimon Schubert 
38265796c8dcSSimon Schubert static int
demangle_fund_type(struct work_stuff * work,const char ** mangled,string * result)38275796c8dcSSimon Schubert demangle_fund_type (struct work_stuff *work,
38285796c8dcSSimon Schubert                     const char **mangled, string *result)
38295796c8dcSSimon Schubert {
38305796c8dcSSimon Schubert   int done = 0;
38315796c8dcSSimon Schubert   int success = 1;
38325796c8dcSSimon Schubert   char buf[INTBUF_SIZE + 5 /* 'int%u_t' */];
38335796c8dcSSimon Schubert   unsigned int dec = 0;
38345796c8dcSSimon Schubert   type_kind_t tk = tk_integral;
38355796c8dcSSimon Schubert 
38365796c8dcSSimon Schubert   /* First pick off any type qualifiers.  There can be more than one.  */
38375796c8dcSSimon Schubert 
38385796c8dcSSimon Schubert   while (!done)
38395796c8dcSSimon Schubert     {
38405796c8dcSSimon Schubert       switch (**mangled)
38415796c8dcSSimon Schubert 	{
38425796c8dcSSimon Schubert 	case 'C':
38435796c8dcSSimon Schubert 	case 'V':
38445796c8dcSSimon Schubert 	case 'u':
38455796c8dcSSimon Schubert 	  if (PRINT_ANSI_QUALIFIERS)
38465796c8dcSSimon Schubert 	    {
38475796c8dcSSimon Schubert               if (!STRING_EMPTY (result))
38485796c8dcSSimon Schubert                 string_prepend (result, " ");
38495796c8dcSSimon Schubert 	      string_prepend (result, demangle_qualifier (**mangled));
38505796c8dcSSimon Schubert 	    }
38515796c8dcSSimon Schubert 	  (*mangled)++;
38525796c8dcSSimon Schubert 	  break;
38535796c8dcSSimon Schubert 	case 'U':
38545796c8dcSSimon Schubert 	  (*mangled)++;
38555796c8dcSSimon Schubert 	  APPEND_BLANK (result);
38565796c8dcSSimon Schubert 	  string_append (result, "unsigned");
38575796c8dcSSimon Schubert 	  break;
38585796c8dcSSimon Schubert 	case 'S': /* signed char only */
38595796c8dcSSimon Schubert 	  (*mangled)++;
38605796c8dcSSimon Schubert 	  APPEND_BLANK (result);
38615796c8dcSSimon Schubert 	  string_append (result, "signed");
38625796c8dcSSimon Schubert 	  break;
38635796c8dcSSimon Schubert 	case 'J':
38645796c8dcSSimon Schubert 	  (*mangled)++;
38655796c8dcSSimon Schubert 	  APPEND_BLANK (result);
38665796c8dcSSimon Schubert 	  string_append (result, "__complex");
38675796c8dcSSimon Schubert 	  break;
38685796c8dcSSimon Schubert 	default:
38695796c8dcSSimon Schubert 	  done = 1;
38705796c8dcSSimon Schubert 	  break;
38715796c8dcSSimon Schubert 	}
38725796c8dcSSimon Schubert     }
38735796c8dcSSimon Schubert 
38745796c8dcSSimon Schubert   /* Now pick off the fundamental type.  There can be only one.  */
38755796c8dcSSimon Schubert 
38765796c8dcSSimon Schubert   switch (**mangled)
38775796c8dcSSimon Schubert     {
38785796c8dcSSimon Schubert     case '\0':
38795796c8dcSSimon Schubert     case '_':
38805796c8dcSSimon Schubert       break;
38815796c8dcSSimon Schubert     case 'v':
38825796c8dcSSimon Schubert       (*mangled)++;
38835796c8dcSSimon Schubert       APPEND_BLANK (result);
38845796c8dcSSimon Schubert       string_append (result, "void");
38855796c8dcSSimon Schubert       break;
38865796c8dcSSimon Schubert     case 'x':
38875796c8dcSSimon Schubert       (*mangled)++;
38885796c8dcSSimon Schubert       APPEND_BLANK (result);
38895796c8dcSSimon Schubert       string_append (result, "long long");
38905796c8dcSSimon Schubert       break;
38915796c8dcSSimon Schubert     case 'l':
38925796c8dcSSimon Schubert       (*mangled)++;
38935796c8dcSSimon Schubert       APPEND_BLANK (result);
38945796c8dcSSimon Schubert       string_append (result, "long");
38955796c8dcSSimon Schubert       break;
38965796c8dcSSimon Schubert     case 'i':
38975796c8dcSSimon Schubert       (*mangled)++;
38985796c8dcSSimon Schubert       APPEND_BLANK (result);
38995796c8dcSSimon Schubert       string_append (result, "int");
39005796c8dcSSimon Schubert       break;
39015796c8dcSSimon Schubert     case 's':
39025796c8dcSSimon Schubert       (*mangled)++;
39035796c8dcSSimon Schubert       APPEND_BLANK (result);
39045796c8dcSSimon Schubert       string_append (result, "short");
39055796c8dcSSimon Schubert       break;
39065796c8dcSSimon Schubert     case 'b':
39075796c8dcSSimon Schubert       (*mangled)++;
39085796c8dcSSimon Schubert       APPEND_BLANK (result);
39095796c8dcSSimon Schubert       string_append (result, "bool");
39105796c8dcSSimon Schubert       tk = tk_bool;
39115796c8dcSSimon Schubert       break;
39125796c8dcSSimon Schubert     case 'c':
39135796c8dcSSimon Schubert       (*mangled)++;
39145796c8dcSSimon Schubert       APPEND_BLANK (result);
39155796c8dcSSimon Schubert       string_append (result, "char");
39165796c8dcSSimon Schubert       tk = tk_char;
39175796c8dcSSimon Schubert       break;
39185796c8dcSSimon Schubert     case 'w':
39195796c8dcSSimon Schubert       (*mangled)++;
39205796c8dcSSimon Schubert       APPEND_BLANK (result);
39215796c8dcSSimon Schubert       string_append (result, "wchar_t");
39225796c8dcSSimon Schubert       tk = tk_char;
39235796c8dcSSimon Schubert       break;
39245796c8dcSSimon Schubert     case 'r':
39255796c8dcSSimon Schubert       (*mangled)++;
39265796c8dcSSimon Schubert       APPEND_BLANK (result);
39275796c8dcSSimon Schubert       string_append (result, "long double");
39285796c8dcSSimon Schubert       tk = tk_real;
39295796c8dcSSimon Schubert       break;
39305796c8dcSSimon Schubert     case 'd':
39315796c8dcSSimon Schubert       (*mangled)++;
39325796c8dcSSimon Schubert       APPEND_BLANK (result);
39335796c8dcSSimon Schubert       string_append (result, "double");
39345796c8dcSSimon Schubert       tk = tk_real;
39355796c8dcSSimon Schubert       break;
39365796c8dcSSimon Schubert     case 'f':
39375796c8dcSSimon Schubert       (*mangled)++;
39385796c8dcSSimon Schubert       APPEND_BLANK (result);
39395796c8dcSSimon Schubert       string_append (result, "float");
39405796c8dcSSimon Schubert       tk = tk_real;
39415796c8dcSSimon Schubert       break;
39425796c8dcSSimon Schubert     case 'G':
39435796c8dcSSimon Schubert       (*mangled)++;
39445796c8dcSSimon Schubert       if (!ISDIGIT ((unsigned char)**mangled))
39455796c8dcSSimon Schubert 	{
39465796c8dcSSimon Schubert 	  success = 0;
39475796c8dcSSimon Schubert 	  break;
39485796c8dcSSimon Schubert 	}
39495796c8dcSSimon Schubert     case 'I':
39505796c8dcSSimon Schubert       (*mangled)++;
39515796c8dcSSimon Schubert       if (**mangled == '_')
39525796c8dcSSimon Schubert 	{
39535796c8dcSSimon Schubert 	  int i;
39545796c8dcSSimon Schubert 	  (*mangled)++;
39555796c8dcSSimon Schubert 	  for (i = 0;
39565796c8dcSSimon Schubert 	       i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
39575796c8dcSSimon Schubert 	       (*mangled)++, i++)
39585796c8dcSSimon Schubert 	    buf[i] = **mangled;
39595796c8dcSSimon Schubert 	  if (**mangled != '_')
39605796c8dcSSimon Schubert 	    {
39615796c8dcSSimon Schubert 	      success = 0;
39625796c8dcSSimon Schubert 	      break;
39635796c8dcSSimon Schubert 	    }
39645796c8dcSSimon Schubert 	  buf[i] = '\0';
39655796c8dcSSimon Schubert 	  (*mangled)++;
39665796c8dcSSimon Schubert 	}
39675796c8dcSSimon Schubert       else
39685796c8dcSSimon Schubert 	{
39695796c8dcSSimon Schubert 	  strncpy (buf, *mangled, 2);
39705796c8dcSSimon Schubert 	  buf[2] = '\0';
39715796c8dcSSimon Schubert 	  *mangled += min (strlen (*mangled), 2);
39725796c8dcSSimon Schubert 	}
39735796c8dcSSimon Schubert       sscanf (buf, "%x", &dec);
39745796c8dcSSimon Schubert       sprintf (buf, "int%u_t", dec);
39755796c8dcSSimon Schubert       APPEND_BLANK (result);
39765796c8dcSSimon Schubert       string_append (result, buf);
39775796c8dcSSimon Schubert       break;
39785796c8dcSSimon Schubert 
39795796c8dcSSimon Schubert       /* fall through */
39805796c8dcSSimon Schubert       /* An explicit type, such as "6mytype" or "7integer" */
39815796c8dcSSimon Schubert     case '0':
39825796c8dcSSimon Schubert     case '1':
39835796c8dcSSimon Schubert     case '2':
39845796c8dcSSimon Schubert     case '3':
39855796c8dcSSimon Schubert     case '4':
39865796c8dcSSimon Schubert     case '5':
39875796c8dcSSimon Schubert     case '6':
39885796c8dcSSimon Schubert     case '7':
39895796c8dcSSimon Schubert     case '8':
39905796c8dcSSimon Schubert     case '9':
39915796c8dcSSimon Schubert       {
39925796c8dcSSimon Schubert         int bindex = register_Btype (work);
39935796c8dcSSimon Schubert         string btype;
39945796c8dcSSimon Schubert         string_init (&btype);
39955796c8dcSSimon Schubert         if (demangle_class_name (work, mangled, &btype)) {
39965796c8dcSSimon Schubert           remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
39975796c8dcSSimon Schubert           APPEND_BLANK (result);
39985796c8dcSSimon Schubert           string_appends (result, &btype);
39995796c8dcSSimon Schubert         }
40005796c8dcSSimon Schubert         else
40015796c8dcSSimon Schubert           success = 0;
40025796c8dcSSimon Schubert         string_delete (&btype);
40035796c8dcSSimon Schubert         break;
40045796c8dcSSimon Schubert       }
40055796c8dcSSimon Schubert     case 't':
40065796c8dcSSimon Schubert       {
40075796c8dcSSimon Schubert         string btype;
40085796c8dcSSimon Schubert         string_init (&btype);
40095796c8dcSSimon Schubert         success = demangle_template (work, mangled, &btype, 0, 1, 1);
40105796c8dcSSimon Schubert         string_appends (result, &btype);
40115796c8dcSSimon Schubert         string_delete (&btype);
40125796c8dcSSimon Schubert         break;
40135796c8dcSSimon Schubert       }
40145796c8dcSSimon Schubert     default:
40155796c8dcSSimon Schubert       success = 0;
40165796c8dcSSimon Schubert       break;
40175796c8dcSSimon Schubert     }
40185796c8dcSSimon Schubert 
40195796c8dcSSimon Schubert   return success ? ((int) tk) : 0;
40205796c8dcSSimon Schubert }
40215796c8dcSSimon Schubert 
40225796c8dcSSimon Schubert 
40235796c8dcSSimon Schubert /* Handle a template's value parameter for HP aCC (extension from ARM)
40245796c8dcSSimon Schubert    **mangled points to 'S' or 'U' */
40255796c8dcSSimon Schubert 
40265796c8dcSSimon Schubert static int
do_hpacc_template_const_value(struct work_stuff * work ATTRIBUTE_UNUSED,const char ** mangled,string * result)40275796c8dcSSimon Schubert do_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED,
40285796c8dcSSimon Schubert                                const char **mangled, string *result)
40295796c8dcSSimon Schubert {
40305796c8dcSSimon Schubert   int unsigned_const;
40315796c8dcSSimon Schubert 
40325796c8dcSSimon Schubert   if (**mangled != 'U' && **mangled != 'S')
40335796c8dcSSimon Schubert     return 0;
40345796c8dcSSimon Schubert 
40355796c8dcSSimon Schubert   unsigned_const = (**mangled == 'U');
40365796c8dcSSimon Schubert 
40375796c8dcSSimon Schubert   (*mangled)++;
40385796c8dcSSimon Schubert 
40395796c8dcSSimon Schubert   switch (**mangled)
40405796c8dcSSimon Schubert     {
40415796c8dcSSimon Schubert       case 'N':
40425796c8dcSSimon Schubert         string_append (result, "-");
40435796c8dcSSimon Schubert         /* fall through */
40445796c8dcSSimon Schubert       case 'P':
40455796c8dcSSimon Schubert         (*mangled)++;
40465796c8dcSSimon Schubert         break;
40475796c8dcSSimon Schubert       case 'M':
40485796c8dcSSimon Schubert         /* special case for -2^31 */
40495796c8dcSSimon Schubert         string_append (result, "-2147483648");
40505796c8dcSSimon Schubert         (*mangled)++;
40515796c8dcSSimon Schubert         return 1;
40525796c8dcSSimon Schubert       default:
40535796c8dcSSimon Schubert         return 0;
40545796c8dcSSimon Schubert     }
40555796c8dcSSimon Schubert 
40565796c8dcSSimon Schubert   /* We have to be looking at an integer now */
40575796c8dcSSimon Schubert   if (!(ISDIGIT ((unsigned char)**mangled)))
40585796c8dcSSimon Schubert     return 0;
40595796c8dcSSimon Schubert 
40605796c8dcSSimon Schubert   /* We only deal with integral values for template
40615796c8dcSSimon Schubert      parameters -- so it's OK to look only for digits */
40625796c8dcSSimon Schubert   while (ISDIGIT ((unsigned char)**mangled))
40635796c8dcSSimon Schubert     {
40645796c8dcSSimon Schubert       char_str[0] = **mangled;
40655796c8dcSSimon Schubert       string_append (result, char_str);
40665796c8dcSSimon Schubert       (*mangled)++;
40675796c8dcSSimon Schubert     }
40685796c8dcSSimon Schubert 
40695796c8dcSSimon Schubert   if (unsigned_const)
40705796c8dcSSimon Schubert     string_append (result, "U");
40715796c8dcSSimon Schubert 
40725796c8dcSSimon Schubert   /* FIXME? Some day we may have 64-bit (or larger :-) ) constants
40735796c8dcSSimon Schubert      with L or LL suffixes. pai/1997-09-03 */
40745796c8dcSSimon Schubert 
40755796c8dcSSimon Schubert   return 1; /* success */
40765796c8dcSSimon Schubert }
40775796c8dcSSimon Schubert 
40785796c8dcSSimon Schubert /* Handle a template's literal parameter for HP aCC (extension from ARM)
40795796c8dcSSimon Schubert    **mangled is pointing to the 'A' */
40805796c8dcSSimon Schubert 
40815796c8dcSSimon Schubert static int
do_hpacc_template_literal(struct work_stuff * work,const char ** mangled,string * result)40825796c8dcSSimon Schubert do_hpacc_template_literal (struct work_stuff *work, const char **mangled,
40835796c8dcSSimon Schubert                            string *result)
40845796c8dcSSimon Schubert {
40855796c8dcSSimon Schubert   int literal_len = 0;
40865796c8dcSSimon Schubert   char * recurse;
40875796c8dcSSimon Schubert   char * recurse_dem;
40885796c8dcSSimon Schubert 
40895796c8dcSSimon Schubert   if (**mangled != 'A')
40905796c8dcSSimon Schubert     return 0;
40915796c8dcSSimon Schubert 
40925796c8dcSSimon Schubert   (*mangled)++;
40935796c8dcSSimon Schubert 
40945796c8dcSSimon Schubert   literal_len = consume_count (mangled);
40955796c8dcSSimon Schubert 
40965796c8dcSSimon Schubert   if (literal_len <= 0)
40975796c8dcSSimon Schubert     return 0;
40985796c8dcSSimon Schubert 
40995796c8dcSSimon Schubert   /* Literal parameters are names of arrays, functions, etc.  and the
41005796c8dcSSimon Schubert      canonical representation uses the address operator */
41015796c8dcSSimon Schubert   string_append (result, "&");
41025796c8dcSSimon Schubert 
41035796c8dcSSimon Schubert   /* Now recursively demangle the literal name */
41045796c8dcSSimon Schubert   recurse = XNEWVEC (char, literal_len + 1);
41055796c8dcSSimon Schubert   memcpy (recurse, *mangled, literal_len);
41065796c8dcSSimon Schubert   recurse[literal_len] = '\000';
41075796c8dcSSimon Schubert 
41085796c8dcSSimon Schubert   recurse_dem = cplus_demangle (recurse, work->options);
41095796c8dcSSimon Schubert 
41105796c8dcSSimon Schubert   if (recurse_dem)
41115796c8dcSSimon Schubert     {
41125796c8dcSSimon Schubert       string_append (result, recurse_dem);
41135796c8dcSSimon Schubert       free (recurse_dem);
41145796c8dcSSimon Schubert     }
41155796c8dcSSimon Schubert   else
41165796c8dcSSimon Schubert     {
41175796c8dcSSimon Schubert       string_appendn (result, *mangled, literal_len);
41185796c8dcSSimon Schubert     }
41195796c8dcSSimon Schubert   (*mangled) += literal_len;
41205796c8dcSSimon Schubert   free (recurse);
41215796c8dcSSimon Schubert 
41225796c8dcSSimon Schubert   return 1;
41235796c8dcSSimon Schubert }
41245796c8dcSSimon Schubert 
41255796c8dcSSimon Schubert static int
snarf_numeric_literal(const char ** args,string * arg)41265796c8dcSSimon Schubert snarf_numeric_literal (const char **args, string *arg)
41275796c8dcSSimon Schubert {
41285796c8dcSSimon Schubert   if (**args == '-')
41295796c8dcSSimon Schubert     {
41305796c8dcSSimon Schubert       char_str[0] = '-';
41315796c8dcSSimon Schubert       string_append (arg, char_str);
41325796c8dcSSimon Schubert       (*args)++;
41335796c8dcSSimon Schubert     }
41345796c8dcSSimon Schubert   else if (**args == '+')
41355796c8dcSSimon Schubert     (*args)++;
41365796c8dcSSimon Schubert 
41375796c8dcSSimon Schubert   if (!ISDIGIT ((unsigned char)**args))
41385796c8dcSSimon Schubert     return 0;
41395796c8dcSSimon Schubert 
41405796c8dcSSimon Schubert   while (ISDIGIT ((unsigned char)**args))
41415796c8dcSSimon Schubert     {
41425796c8dcSSimon Schubert       char_str[0] = **args;
41435796c8dcSSimon Schubert       string_append (arg, char_str);
41445796c8dcSSimon Schubert       (*args)++;
41455796c8dcSSimon Schubert     }
41465796c8dcSSimon Schubert 
41475796c8dcSSimon Schubert   return 1;
41485796c8dcSSimon Schubert }
41495796c8dcSSimon Schubert 
41505796c8dcSSimon Schubert /* Demangle the next argument, given by MANGLED into RESULT, which
41515796c8dcSSimon Schubert    *should be an uninitialized* string.  It will be initialized here,
41525796c8dcSSimon Schubert    and free'd should anything go wrong.  */
41535796c8dcSSimon Schubert 
41545796c8dcSSimon Schubert static int
do_arg(struct work_stuff * work,const char ** mangled,string * result)41555796c8dcSSimon Schubert do_arg (struct work_stuff *work, const char **mangled, string *result)
41565796c8dcSSimon Schubert {
41575796c8dcSSimon Schubert   /* Remember where we started so that we can record the type, for
41585796c8dcSSimon Schubert      non-squangling type remembering.  */
41595796c8dcSSimon Schubert   const char *start = *mangled;
41605796c8dcSSimon Schubert 
41615796c8dcSSimon Schubert   string_init (result);
41625796c8dcSSimon Schubert 
41635796c8dcSSimon Schubert   if (work->nrepeats > 0)
41645796c8dcSSimon Schubert     {
41655796c8dcSSimon Schubert       --work->nrepeats;
41665796c8dcSSimon Schubert 
41675796c8dcSSimon Schubert       if (work->previous_argument == 0)
41685796c8dcSSimon Schubert 	return 0;
41695796c8dcSSimon Schubert 
41705796c8dcSSimon Schubert       /* We want to reissue the previous type in this argument list.  */
41715796c8dcSSimon Schubert       string_appends (result, work->previous_argument);
41725796c8dcSSimon Schubert       return 1;
41735796c8dcSSimon Schubert     }
41745796c8dcSSimon Schubert 
41755796c8dcSSimon Schubert   if (**mangled == 'n')
41765796c8dcSSimon Schubert     {
41775796c8dcSSimon Schubert       /* A squangling-style repeat.  */
41785796c8dcSSimon Schubert       (*mangled)++;
41795796c8dcSSimon Schubert       work->nrepeats = consume_count(mangled);
41805796c8dcSSimon Schubert 
41815796c8dcSSimon Schubert       if (work->nrepeats <= 0)
41825796c8dcSSimon Schubert 	/* This was not a repeat count after all.  */
41835796c8dcSSimon Schubert 	return 0;
41845796c8dcSSimon Schubert 
41855796c8dcSSimon Schubert       if (work->nrepeats > 9)
41865796c8dcSSimon Schubert 	{
41875796c8dcSSimon Schubert 	  if (**mangled != '_')
41885796c8dcSSimon Schubert 	    /* The repeat count should be followed by an '_' in this
41895796c8dcSSimon Schubert 	       case.  */
41905796c8dcSSimon Schubert 	    return 0;
41915796c8dcSSimon Schubert 	  else
41925796c8dcSSimon Schubert 	    (*mangled)++;
41935796c8dcSSimon Schubert 	}
41945796c8dcSSimon Schubert 
41955796c8dcSSimon Schubert       /* Now, the repeat is all set up.  */
41965796c8dcSSimon Schubert       return do_arg (work, mangled, result);
41975796c8dcSSimon Schubert     }
41985796c8dcSSimon Schubert 
41995796c8dcSSimon Schubert   /* Save the result in WORK->previous_argument so that we can find it
42005796c8dcSSimon Schubert      if it's repeated.  Note that saving START is not good enough: we
42015796c8dcSSimon Schubert      do not want to add additional types to the back-referenceable
42025796c8dcSSimon Schubert      type vector when processing a repeated type.  */
42035796c8dcSSimon Schubert   if (work->previous_argument)
42045796c8dcSSimon Schubert     string_delete (work->previous_argument);
42055796c8dcSSimon Schubert   else
42065796c8dcSSimon Schubert     work->previous_argument = XNEW (string);
42075796c8dcSSimon Schubert 
42085796c8dcSSimon Schubert   if (!do_type (work, mangled, work->previous_argument))
42095796c8dcSSimon Schubert     return 0;
42105796c8dcSSimon Schubert 
42115796c8dcSSimon Schubert   string_appends (result, work->previous_argument);
42125796c8dcSSimon Schubert 
42135796c8dcSSimon Schubert   remember_type (work, start, *mangled - start);
42145796c8dcSSimon Schubert   return 1;
42155796c8dcSSimon Schubert }
42165796c8dcSSimon Schubert 
42175796c8dcSSimon Schubert static void
remember_type(struct work_stuff * work,const char * start,int len)42185796c8dcSSimon Schubert remember_type (struct work_stuff *work, const char *start, int len)
42195796c8dcSSimon Schubert {
42205796c8dcSSimon Schubert   char *tem;
42215796c8dcSSimon Schubert 
42225796c8dcSSimon Schubert   if (work->forgetting_types)
42235796c8dcSSimon Schubert     return;
42245796c8dcSSimon Schubert 
42255796c8dcSSimon Schubert   if (work -> ntypes >= work -> typevec_size)
42265796c8dcSSimon Schubert     {
42275796c8dcSSimon Schubert       if (work -> typevec_size == 0)
42285796c8dcSSimon Schubert 	{
42295796c8dcSSimon Schubert 	  work -> typevec_size = 3;
42305796c8dcSSimon Schubert 	  work -> typevec = XNEWVEC (char *, work->typevec_size);
42315796c8dcSSimon Schubert 	}
42325796c8dcSSimon Schubert       else
42335796c8dcSSimon Schubert 	{
42345796c8dcSSimon Schubert 	  work -> typevec_size *= 2;
42355796c8dcSSimon Schubert 	  work -> typevec
42365796c8dcSSimon Schubert 	    = XRESIZEVEC (char *, work->typevec, work->typevec_size);
42375796c8dcSSimon Schubert 	}
42385796c8dcSSimon Schubert     }
42395796c8dcSSimon Schubert   tem = XNEWVEC (char, len + 1);
42405796c8dcSSimon Schubert   memcpy (tem, start, len);
42415796c8dcSSimon Schubert   tem[len] = '\0';
42425796c8dcSSimon Schubert   work -> typevec[work -> ntypes++] = tem;
42435796c8dcSSimon Schubert }
42445796c8dcSSimon Schubert 
42455796c8dcSSimon Schubert 
42465796c8dcSSimon Schubert /* Remember a K type class qualifier. */
42475796c8dcSSimon Schubert static void
remember_Ktype(struct work_stuff * work,const char * start,int len)42485796c8dcSSimon Schubert remember_Ktype (struct work_stuff *work, const char *start, int len)
42495796c8dcSSimon Schubert {
42505796c8dcSSimon Schubert   char *tem;
42515796c8dcSSimon Schubert 
42525796c8dcSSimon Schubert   if (work -> numk >= work -> ksize)
42535796c8dcSSimon Schubert     {
42545796c8dcSSimon Schubert       if (work -> ksize == 0)
42555796c8dcSSimon Schubert 	{
42565796c8dcSSimon Schubert 	  work -> ksize = 5;
42575796c8dcSSimon Schubert 	  work -> ktypevec = XNEWVEC (char *, work->ksize);
42585796c8dcSSimon Schubert 	}
42595796c8dcSSimon Schubert       else
42605796c8dcSSimon Schubert 	{
42615796c8dcSSimon Schubert 	  work -> ksize *= 2;
42625796c8dcSSimon Schubert 	  work -> ktypevec
42635796c8dcSSimon Schubert 	    = XRESIZEVEC (char *, work->ktypevec, work->ksize);
42645796c8dcSSimon Schubert 	}
42655796c8dcSSimon Schubert     }
42665796c8dcSSimon Schubert   tem = XNEWVEC (char, len + 1);
42675796c8dcSSimon Schubert   memcpy (tem, start, len);
42685796c8dcSSimon Schubert   tem[len] = '\0';
42695796c8dcSSimon Schubert   work -> ktypevec[work -> numk++] = tem;
42705796c8dcSSimon Schubert }
42715796c8dcSSimon Schubert 
42725796c8dcSSimon Schubert /* Register a B code, and get an index for it. B codes are registered
42735796c8dcSSimon Schubert    as they are seen, rather than as they are completed, so map<temp<char> >
42745796c8dcSSimon Schubert    registers map<temp<char> > as B0, and temp<char> as B1 */
42755796c8dcSSimon Schubert 
42765796c8dcSSimon Schubert static int
register_Btype(struct work_stuff * work)42775796c8dcSSimon Schubert register_Btype (struct work_stuff *work)
42785796c8dcSSimon Schubert {
42795796c8dcSSimon Schubert   int ret;
42805796c8dcSSimon Schubert 
42815796c8dcSSimon Schubert   if (work -> numb >= work -> bsize)
42825796c8dcSSimon Schubert     {
42835796c8dcSSimon Schubert       if (work -> bsize == 0)
42845796c8dcSSimon Schubert 	{
42855796c8dcSSimon Schubert 	  work -> bsize = 5;
42865796c8dcSSimon Schubert 	  work -> btypevec = XNEWVEC (char *, work->bsize);
42875796c8dcSSimon Schubert 	}
42885796c8dcSSimon Schubert       else
42895796c8dcSSimon Schubert 	{
42905796c8dcSSimon Schubert 	  work -> bsize *= 2;
42915796c8dcSSimon Schubert 	  work -> btypevec
42925796c8dcSSimon Schubert 	    = XRESIZEVEC (char *, work->btypevec, work->bsize);
42935796c8dcSSimon Schubert 	}
42945796c8dcSSimon Schubert     }
42955796c8dcSSimon Schubert   ret = work -> numb++;
42965796c8dcSSimon Schubert   work -> btypevec[ret] = NULL;
42975796c8dcSSimon Schubert   return(ret);
42985796c8dcSSimon Schubert }
42995796c8dcSSimon Schubert 
43005796c8dcSSimon Schubert /* Store a value into a previously registered B code type. */
43015796c8dcSSimon Schubert 
43025796c8dcSSimon Schubert static void
remember_Btype(struct work_stuff * work,const char * start,int len,int index)43035796c8dcSSimon Schubert remember_Btype (struct work_stuff *work, const char *start,
43045796c8dcSSimon Schubert                 int len, int index)
43055796c8dcSSimon Schubert {
43065796c8dcSSimon Schubert   char *tem;
43075796c8dcSSimon Schubert 
43085796c8dcSSimon Schubert   tem = XNEWVEC (char, len + 1);
43095796c8dcSSimon Schubert   memcpy (tem, start, len);
43105796c8dcSSimon Schubert   tem[len] = '\0';
43115796c8dcSSimon Schubert   work -> btypevec[index] = tem;
43125796c8dcSSimon Schubert }
43135796c8dcSSimon Schubert 
43145796c8dcSSimon Schubert /* Lose all the info related to B and K type codes. */
43155796c8dcSSimon Schubert static void
forget_B_and_K_types(struct work_stuff * work)43165796c8dcSSimon Schubert forget_B_and_K_types (struct work_stuff *work)
43175796c8dcSSimon Schubert {
43185796c8dcSSimon Schubert   int i;
43195796c8dcSSimon Schubert 
43205796c8dcSSimon Schubert   while (work -> numk > 0)
43215796c8dcSSimon Schubert     {
43225796c8dcSSimon Schubert       i = --(work -> numk);
43235796c8dcSSimon Schubert       if (work -> ktypevec[i] != NULL)
43245796c8dcSSimon Schubert 	{
43255796c8dcSSimon Schubert 	  free (work -> ktypevec[i]);
43265796c8dcSSimon Schubert 	  work -> ktypevec[i] = NULL;
43275796c8dcSSimon Schubert 	}
43285796c8dcSSimon Schubert     }
43295796c8dcSSimon Schubert 
43305796c8dcSSimon Schubert   while (work -> numb > 0)
43315796c8dcSSimon Schubert     {
43325796c8dcSSimon Schubert       i = --(work -> numb);
43335796c8dcSSimon Schubert       if (work -> btypevec[i] != NULL)
43345796c8dcSSimon Schubert 	{
43355796c8dcSSimon Schubert 	  free (work -> btypevec[i]);
43365796c8dcSSimon Schubert 	  work -> btypevec[i] = NULL;
43375796c8dcSSimon Schubert 	}
43385796c8dcSSimon Schubert     }
43395796c8dcSSimon Schubert }
43405796c8dcSSimon Schubert /* Forget the remembered types, but not the type vector itself.  */
43415796c8dcSSimon Schubert 
43425796c8dcSSimon Schubert static void
forget_types(struct work_stuff * work)43435796c8dcSSimon Schubert forget_types (struct work_stuff *work)
43445796c8dcSSimon Schubert {
43455796c8dcSSimon Schubert   int i;
43465796c8dcSSimon Schubert 
43475796c8dcSSimon Schubert   while (work -> ntypes > 0)
43485796c8dcSSimon Schubert     {
43495796c8dcSSimon Schubert       i = --(work -> ntypes);
43505796c8dcSSimon Schubert       if (work -> typevec[i] != NULL)
43515796c8dcSSimon Schubert 	{
43525796c8dcSSimon Schubert 	  free (work -> typevec[i]);
43535796c8dcSSimon Schubert 	  work -> typevec[i] = NULL;
43545796c8dcSSimon Schubert 	}
43555796c8dcSSimon Schubert     }
43565796c8dcSSimon Schubert }
43575796c8dcSSimon Schubert 
43585796c8dcSSimon Schubert /* Process the argument list part of the signature, after any class spec
43595796c8dcSSimon Schubert    has been consumed, as well as the first 'F' character (if any).  For
43605796c8dcSSimon Schubert    example:
43615796c8dcSSimon Schubert 
43625796c8dcSSimon Schubert    "__als__3fooRT0"		=>	process "RT0"
43635796c8dcSSimon Schubert    "complexfunc5__FPFPc_PFl_i"	=>	process "PFPc_PFl_i"
43645796c8dcSSimon Schubert 
43655796c8dcSSimon Schubert    DECLP must be already initialised, usually non-empty.  It won't be freed
43665796c8dcSSimon Schubert    on failure.
43675796c8dcSSimon Schubert 
43685796c8dcSSimon Schubert    Note that g++ differs significantly from ARM and lucid style mangling
43695796c8dcSSimon Schubert    with regards to references to previously seen types.  For example, given
43705796c8dcSSimon Schubert    the source fragment:
43715796c8dcSSimon Schubert 
43725796c8dcSSimon Schubert      class foo {
43735796c8dcSSimon Schubert        public:
43745796c8dcSSimon Schubert        foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
43755796c8dcSSimon Schubert      };
43765796c8dcSSimon Schubert 
43775796c8dcSSimon Schubert      foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
43785796c8dcSSimon Schubert      void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
43795796c8dcSSimon Schubert 
43805796c8dcSSimon Schubert    g++ produces the names:
43815796c8dcSSimon Schubert 
43825796c8dcSSimon Schubert      __3fooiRT0iT2iT2
43835796c8dcSSimon Schubert      foo__FiR3fooiT1iT1
43845796c8dcSSimon Schubert 
43855796c8dcSSimon Schubert    while lcc (and presumably other ARM style compilers as well) produces:
43865796c8dcSSimon Schubert 
43875796c8dcSSimon Schubert      foo__FiR3fooT1T2T1T2
43885796c8dcSSimon Schubert      __ct__3fooFiR3fooT1T2T1T2
43895796c8dcSSimon Schubert 
43905796c8dcSSimon Schubert    Note that g++ bases its type numbers starting at zero and counts all
43915796c8dcSSimon Schubert    previously seen types, while lucid/ARM bases its type numbers starting
43925796c8dcSSimon Schubert    at one and only considers types after it has seen the 'F' character
43935796c8dcSSimon Schubert    indicating the start of the function args.  For lucid/ARM style, we
43945796c8dcSSimon Schubert    account for this difference by discarding any previously seen types when
43955796c8dcSSimon Schubert    we see the 'F' character, and subtracting one from the type number
43965796c8dcSSimon Schubert    reference.
43975796c8dcSSimon Schubert 
43985796c8dcSSimon Schubert  */
43995796c8dcSSimon Schubert 
44005796c8dcSSimon Schubert static int
demangle_args(struct work_stuff * work,const char ** mangled,string * declp)44015796c8dcSSimon Schubert demangle_args (struct work_stuff *work, const char **mangled,
44025796c8dcSSimon Schubert                string *declp)
44035796c8dcSSimon Schubert {
44045796c8dcSSimon Schubert   string arg;
44055796c8dcSSimon Schubert   int need_comma = 0;
44065796c8dcSSimon Schubert   int r;
44075796c8dcSSimon Schubert   int t;
44085796c8dcSSimon Schubert   const char *tem;
44095796c8dcSSimon Schubert   char temptype;
44105796c8dcSSimon Schubert 
44115796c8dcSSimon Schubert   if (PRINT_ARG_TYPES)
44125796c8dcSSimon Schubert     {
44135796c8dcSSimon Schubert       string_append (declp, "(");
44145796c8dcSSimon Schubert       if (**mangled == '\0')
44155796c8dcSSimon Schubert 	{
44165796c8dcSSimon Schubert 	  string_append (declp, "void");
44175796c8dcSSimon Schubert 	}
44185796c8dcSSimon Schubert     }
44195796c8dcSSimon Schubert 
44205796c8dcSSimon Schubert   while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
44215796c8dcSSimon Schubert 	 || work->nrepeats > 0)
44225796c8dcSSimon Schubert     {
44235796c8dcSSimon Schubert       if ((**mangled == 'N') || (**mangled == 'T'))
44245796c8dcSSimon Schubert 	{
44255796c8dcSSimon Schubert 	  temptype = *(*mangled)++;
44265796c8dcSSimon Schubert 
44275796c8dcSSimon Schubert 	  if (temptype == 'N')
44285796c8dcSSimon Schubert 	    {
44295796c8dcSSimon Schubert 	      if (!get_count (mangled, &r))
44305796c8dcSSimon Schubert 		{
44315796c8dcSSimon Schubert 		  return (0);
44325796c8dcSSimon Schubert 		}
44335796c8dcSSimon Schubert 	    }
44345796c8dcSSimon Schubert 	  else
44355796c8dcSSimon Schubert 	    {
44365796c8dcSSimon Schubert 	      r = 1;
44375796c8dcSSimon Schubert 	    }
44385796c8dcSSimon Schubert           if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
44395796c8dcSSimon Schubert             {
44405796c8dcSSimon Schubert               /* If we have 10 or more types we might have more than a 1 digit
44415796c8dcSSimon Schubert                  index so we'll have to consume the whole count here. This
44425796c8dcSSimon Schubert                  will lose if the next thing is a type name preceded by a
44435796c8dcSSimon Schubert                  count but it's impossible to demangle that case properly
44445796c8dcSSimon Schubert                  anyway. Eg if we already have 12 types is T12Pc "(..., type1,
44455796c8dcSSimon Schubert                  Pc, ...)"  or "(..., type12, char *, ...)" */
44465796c8dcSSimon Schubert               if ((t = consume_count(mangled)) <= 0)
44475796c8dcSSimon Schubert                 {
44485796c8dcSSimon Schubert                   return (0);
44495796c8dcSSimon Schubert                 }
44505796c8dcSSimon Schubert             }
44515796c8dcSSimon Schubert           else
44525796c8dcSSimon Schubert 	    {
44535796c8dcSSimon Schubert 	      if (!get_count (mangled, &t))
44545796c8dcSSimon Schubert 	    	{
44555796c8dcSSimon Schubert 	          return (0);
44565796c8dcSSimon Schubert 	    	}
44575796c8dcSSimon Schubert 	    }
44585796c8dcSSimon Schubert 	  if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
44595796c8dcSSimon Schubert 	    {
44605796c8dcSSimon Schubert 	      t--;
44615796c8dcSSimon Schubert 	    }
44625796c8dcSSimon Schubert 	  /* Validate the type index.  Protect against illegal indices from
44635796c8dcSSimon Schubert 	     malformed type strings.  */
44645796c8dcSSimon Schubert 	  if ((t < 0) || (t >= work -> ntypes))
44655796c8dcSSimon Schubert 	    {
44665796c8dcSSimon Schubert 	      return (0);
44675796c8dcSSimon Schubert 	    }
44685796c8dcSSimon Schubert 	  while (work->nrepeats > 0 || --r >= 0)
44695796c8dcSSimon Schubert 	    {
44705796c8dcSSimon Schubert 	      tem = work -> typevec[t];
44715796c8dcSSimon Schubert 	      if (need_comma && PRINT_ARG_TYPES)
44725796c8dcSSimon Schubert 		{
44735796c8dcSSimon Schubert 		  string_append (declp, ", ");
44745796c8dcSSimon Schubert 		}
44755796c8dcSSimon Schubert 	      if (!do_arg (work, &tem, &arg))
44765796c8dcSSimon Schubert 		{
44775796c8dcSSimon Schubert 		  return (0);
44785796c8dcSSimon Schubert 		}
44795796c8dcSSimon Schubert 	      if (PRINT_ARG_TYPES)
44805796c8dcSSimon Schubert 		{
44815796c8dcSSimon Schubert 		  string_appends (declp, &arg);
44825796c8dcSSimon Schubert 		}
44835796c8dcSSimon Schubert 	      string_delete (&arg);
44845796c8dcSSimon Schubert 	      need_comma = 1;
44855796c8dcSSimon Schubert 	    }
44865796c8dcSSimon Schubert 	}
44875796c8dcSSimon Schubert       else
44885796c8dcSSimon Schubert 	{
44895796c8dcSSimon Schubert 	  if (need_comma && PRINT_ARG_TYPES)
44905796c8dcSSimon Schubert 	    string_append (declp, ", ");
44915796c8dcSSimon Schubert 	  if (!do_arg (work, mangled, &arg))
44925796c8dcSSimon Schubert 	    return (0);
44935796c8dcSSimon Schubert 	  if (PRINT_ARG_TYPES)
44945796c8dcSSimon Schubert 	    string_appends (declp, &arg);
44955796c8dcSSimon Schubert 	  string_delete (&arg);
44965796c8dcSSimon Schubert 	  need_comma = 1;
44975796c8dcSSimon Schubert 	}
44985796c8dcSSimon Schubert     }
44995796c8dcSSimon Schubert 
45005796c8dcSSimon Schubert   if (**mangled == 'e')
45015796c8dcSSimon Schubert     {
45025796c8dcSSimon Schubert       (*mangled)++;
45035796c8dcSSimon Schubert       if (PRINT_ARG_TYPES)
45045796c8dcSSimon Schubert 	{
45055796c8dcSSimon Schubert 	  if (need_comma)
45065796c8dcSSimon Schubert 	    {
45075796c8dcSSimon Schubert 	      string_append (declp, ",");
45085796c8dcSSimon Schubert 	    }
45095796c8dcSSimon Schubert 	  string_append (declp, "...");
45105796c8dcSSimon Schubert 	}
45115796c8dcSSimon Schubert     }
45125796c8dcSSimon Schubert 
45135796c8dcSSimon Schubert   if (PRINT_ARG_TYPES)
45145796c8dcSSimon Schubert     {
45155796c8dcSSimon Schubert       string_append (declp, ")");
45165796c8dcSSimon Schubert     }
45175796c8dcSSimon Schubert   return (1);
45185796c8dcSSimon Schubert }
45195796c8dcSSimon Schubert 
45205796c8dcSSimon Schubert /* Like demangle_args, but for demangling the argument lists of function
45215796c8dcSSimon Schubert    and method pointers or references, not top-level declarations.  */
45225796c8dcSSimon Schubert 
45235796c8dcSSimon Schubert static int
demangle_nested_args(struct work_stuff * work,const char ** mangled,string * declp)45245796c8dcSSimon Schubert demangle_nested_args (struct work_stuff *work, const char **mangled,
45255796c8dcSSimon Schubert                       string *declp)
45265796c8dcSSimon Schubert {
45275796c8dcSSimon Schubert   string* saved_previous_argument;
45285796c8dcSSimon Schubert   int result;
45295796c8dcSSimon Schubert   int saved_nrepeats;
45305796c8dcSSimon Schubert 
45315796c8dcSSimon Schubert   /* The G++ name-mangling algorithm does not remember types on nested
45325796c8dcSSimon Schubert      argument lists, unless -fsquangling is used, and in that case the
45335796c8dcSSimon Schubert      type vector updated by remember_type is not used.  So, we turn
45345796c8dcSSimon Schubert      off remembering of types here.  */
45355796c8dcSSimon Schubert   ++work->forgetting_types;
45365796c8dcSSimon Schubert 
45375796c8dcSSimon Schubert   /* For the repeat codes used with -fsquangling, we must keep track of
45385796c8dcSSimon Schubert      the last argument.  */
45395796c8dcSSimon Schubert   saved_previous_argument = work->previous_argument;
45405796c8dcSSimon Schubert   saved_nrepeats = work->nrepeats;
45415796c8dcSSimon Schubert   work->previous_argument = 0;
45425796c8dcSSimon Schubert   work->nrepeats = 0;
45435796c8dcSSimon Schubert 
45445796c8dcSSimon Schubert   /* Actually demangle the arguments.  */
45455796c8dcSSimon Schubert   result = demangle_args (work, mangled, declp);
45465796c8dcSSimon Schubert 
45475796c8dcSSimon Schubert   /* Restore the previous_argument field.  */
45485796c8dcSSimon Schubert   if (work->previous_argument)
45495796c8dcSSimon Schubert     {
45505796c8dcSSimon Schubert       string_delete (work->previous_argument);
45515796c8dcSSimon Schubert       free ((char *) work->previous_argument);
45525796c8dcSSimon Schubert     }
45535796c8dcSSimon Schubert   work->previous_argument = saved_previous_argument;
45545796c8dcSSimon Schubert   --work->forgetting_types;
45555796c8dcSSimon Schubert   work->nrepeats = saved_nrepeats;
45565796c8dcSSimon Schubert 
45575796c8dcSSimon Schubert   return result;
45585796c8dcSSimon Schubert }
45595796c8dcSSimon Schubert 
45605796c8dcSSimon Schubert /* Returns 1 if a valid function name was found or 0 otherwise.  */
45615796c8dcSSimon Schubert 
45625796c8dcSSimon Schubert static int
demangle_function_name(struct work_stuff * work,const char ** mangled,string * declp,const char * scan)45635796c8dcSSimon Schubert demangle_function_name (struct work_stuff *work, const char **mangled,
45645796c8dcSSimon Schubert                         string *declp, const char *scan)
45655796c8dcSSimon Schubert {
45665796c8dcSSimon Schubert   size_t i;
45675796c8dcSSimon Schubert   string type;
45685796c8dcSSimon Schubert   const char *tem;
45695796c8dcSSimon Schubert 
45705796c8dcSSimon Schubert   string_appendn (declp, (*mangled), scan - (*mangled));
45715796c8dcSSimon Schubert   string_need (declp, 1);
45725796c8dcSSimon Schubert   *(declp -> p) = '\0';
45735796c8dcSSimon Schubert 
45745796c8dcSSimon Schubert   /* Consume the function name, including the "__" separating the name
45755796c8dcSSimon Schubert      from the signature.  We are guaranteed that SCAN points to the
45765796c8dcSSimon Schubert      separator.  */
45775796c8dcSSimon Schubert 
45785796c8dcSSimon Schubert   (*mangled) = scan + 2;
45795796c8dcSSimon Schubert   /* We may be looking at an instantiation of a template function:
45805796c8dcSSimon Schubert      foo__Xt1t2_Ft3t4, where t1, t2, ... are template arguments and a
45815796c8dcSSimon Schubert      following _F marks the start of the function arguments.  Handle
45825796c8dcSSimon Schubert      the template arguments first. */
45835796c8dcSSimon Schubert 
45845796c8dcSSimon Schubert   if (HP_DEMANGLING && (**mangled == 'X'))
45855796c8dcSSimon Schubert     {
45865796c8dcSSimon Schubert       demangle_arm_hp_template (work, mangled, 0, declp);
45875796c8dcSSimon Schubert       /* This leaves MANGLED pointing to the 'F' marking func args */
45885796c8dcSSimon Schubert     }
45895796c8dcSSimon Schubert 
45905796c8dcSSimon Schubert   if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
45915796c8dcSSimon Schubert     {
45925796c8dcSSimon Schubert 
45935796c8dcSSimon Schubert       /* See if we have an ARM style constructor or destructor operator.
45945796c8dcSSimon Schubert 	 If so, then just record it, clear the decl, and return.
45955796c8dcSSimon Schubert 	 We can't build the actual constructor/destructor decl until later,
45965796c8dcSSimon Schubert 	 when we recover the class name from the signature.  */
45975796c8dcSSimon Schubert 
45985796c8dcSSimon Schubert       if (strcmp (declp -> b, "__ct") == 0)
45995796c8dcSSimon Schubert 	{
46005796c8dcSSimon Schubert 	  work -> constructor += 1;
46015796c8dcSSimon Schubert 	  string_clear (declp);
46025796c8dcSSimon Schubert 	  return 1;
46035796c8dcSSimon Schubert 	}
46045796c8dcSSimon Schubert       else if (strcmp (declp -> b, "__dt") == 0)
46055796c8dcSSimon Schubert 	{
46065796c8dcSSimon Schubert 	  work -> destructor += 1;
46075796c8dcSSimon Schubert 	  string_clear (declp);
46085796c8dcSSimon Schubert 	  return 1;
46095796c8dcSSimon Schubert 	}
46105796c8dcSSimon Schubert     }
46115796c8dcSSimon Schubert 
46125796c8dcSSimon Schubert   if (declp->p - declp->b >= 3
46135796c8dcSSimon Schubert       && declp->b[0] == 'o'
46145796c8dcSSimon Schubert       && declp->b[1] == 'p'
46155796c8dcSSimon Schubert       && strchr (cplus_markers, declp->b[2]) != NULL)
46165796c8dcSSimon Schubert     {
46175796c8dcSSimon Schubert       /* see if it's an assignment expression */
46185796c8dcSSimon Schubert       if (declp->p - declp->b >= 10 /* op$assign_ */
46195796c8dcSSimon Schubert 	  && memcmp (declp->b + 3, "assign_", 7) == 0)
46205796c8dcSSimon Schubert 	{
46215796c8dcSSimon Schubert 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
46225796c8dcSSimon Schubert 	    {
46235796c8dcSSimon Schubert 	      int len = declp->p - declp->b - 10;
46245796c8dcSSimon Schubert 	      if ((int) strlen (optable[i].in) == len
46255796c8dcSSimon Schubert 		  && memcmp (optable[i].in, declp->b + 10, len) == 0)
46265796c8dcSSimon Schubert 		{
46275796c8dcSSimon Schubert 		  string_clear (declp);
46285796c8dcSSimon Schubert 		  string_append (declp, "operator");
46295796c8dcSSimon Schubert 		  string_append (declp, optable[i].out);
46305796c8dcSSimon Schubert 		  string_append (declp, "=");
46315796c8dcSSimon Schubert 		  break;
46325796c8dcSSimon Schubert 		}
46335796c8dcSSimon Schubert 	    }
46345796c8dcSSimon Schubert 	}
46355796c8dcSSimon Schubert       else
46365796c8dcSSimon Schubert 	{
46375796c8dcSSimon Schubert 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
46385796c8dcSSimon Schubert 	    {
46395796c8dcSSimon Schubert 	      int len = declp->p - declp->b - 3;
46405796c8dcSSimon Schubert 	      if ((int) strlen (optable[i].in) == len
46415796c8dcSSimon Schubert 		  && memcmp (optable[i].in, declp->b + 3, len) == 0)
46425796c8dcSSimon Schubert 		{
46435796c8dcSSimon Schubert 		  string_clear (declp);
46445796c8dcSSimon Schubert 		  string_append (declp, "operator");
46455796c8dcSSimon Schubert 		  string_append (declp, optable[i].out);
46465796c8dcSSimon Schubert 		  break;
46475796c8dcSSimon Schubert 		}
46485796c8dcSSimon Schubert 	    }
46495796c8dcSSimon Schubert 	}
46505796c8dcSSimon Schubert     }
46515796c8dcSSimon Schubert   else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
46525796c8dcSSimon Schubert 	   && strchr (cplus_markers, declp->b[4]) != NULL)
46535796c8dcSSimon Schubert     {
46545796c8dcSSimon Schubert       /* type conversion operator */
46555796c8dcSSimon Schubert       tem = declp->b + 5;
46565796c8dcSSimon Schubert       if (do_type (work, &tem, &type))
46575796c8dcSSimon Schubert 	{
46585796c8dcSSimon Schubert 	  string_clear (declp);
46595796c8dcSSimon Schubert 	  string_append (declp, "operator ");
46605796c8dcSSimon Schubert 	  string_appends (declp, &type);
46615796c8dcSSimon Schubert 	  string_delete (&type);
46625796c8dcSSimon Schubert 	}
46635796c8dcSSimon Schubert     }
46645796c8dcSSimon Schubert   else if (declp->b[0] == '_' && declp->b[1] == '_'
46655796c8dcSSimon Schubert 	   && declp->b[2] == 'o' && declp->b[3] == 'p')
46665796c8dcSSimon Schubert     {
46675796c8dcSSimon Schubert       /* ANSI.  */
46685796c8dcSSimon Schubert       /* type conversion operator.  */
46695796c8dcSSimon Schubert       tem = declp->b + 4;
46705796c8dcSSimon Schubert       if (do_type (work, &tem, &type))
46715796c8dcSSimon Schubert 	{
46725796c8dcSSimon Schubert 	  string_clear (declp);
46735796c8dcSSimon Schubert 	  string_append (declp, "operator ");
46745796c8dcSSimon Schubert 	  string_appends (declp, &type);
46755796c8dcSSimon Schubert 	  string_delete (&type);
46765796c8dcSSimon Schubert 	}
46775796c8dcSSimon Schubert     }
46785796c8dcSSimon Schubert   else if (declp->b[0] == '_' && declp->b[1] == '_'
46795796c8dcSSimon Schubert 	   && ISLOWER((unsigned char)declp->b[2])
46805796c8dcSSimon Schubert 	   && ISLOWER((unsigned char)declp->b[3]))
46815796c8dcSSimon Schubert     {
46825796c8dcSSimon Schubert       if (declp->b[4] == '\0')
46835796c8dcSSimon Schubert 	{
46845796c8dcSSimon Schubert 	  /* Operator.  */
46855796c8dcSSimon Schubert 	  for (i = 0; i < ARRAY_SIZE (optable); i++)
46865796c8dcSSimon Schubert 	    {
46875796c8dcSSimon Schubert 	      if (strlen (optable[i].in) == 2
46885796c8dcSSimon Schubert 		  && memcmp (optable[i].in, declp->b + 2, 2) == 0)
46895796c8dcSSimon Schubert 		{
46905796c8dcSSimon Schubert 		  string_clear (declp);
46915796c8dcSSimon Schubert 		  string_append (declp, "operator");
46925796c8dcSSimon Schubert 		  string_append (declp, optable[i].out);
46935796c8dcSSimon Schubert 		  break;
46945796c8dcSSimon Schubert 		}
46955796c8dcSSimon Schubert 	    }
46965796c8dcSSimon Schubert 	}
46975796c8dcSSimon Schubert       else
46985796c8dcSSimon Schubert 	{
46995796c8dcSSimon Schubert 	  if (declp->b[2] == 'a' && declp->b[5] == '\0')
47005796c8dcSSimon Schubert 	    {
47015796c8dcSSimon Schubert 	      /* Assignment.  */
47025796c8dcSSimon Schubert 	      for (i = 0; i < ARRAY_SIZE (optable); i++)
47035796c8dcSSimon Schubert 		{
47045796c8dcSSimon Schubert 		  if (strlen (optable[i].in) == 3
47055796c8dcSSimon Schubert 		      && memcmp (optable[i].in, declp->b + 2, 3) == 0)
47065796c8dcSSimon Schubert 		    {
47075796c8dcSSimon Schubert 		      string_clear (declp);
47085796c8dcSSimon Schubert 		      string_append (declp, "operator");
47095796c8dcSSimon Schubert 		      string_append (declp, optable[i].out);
47105796c8dcSSimon Schubert 		      break;
47115796c8dcSSimon Schubert 		    }
47125796c8dcSSimon Schubert 		}
47135796c8dcSSimon Schubert 	    }
47145796c8dcSSimon Schubert 	}
47155796c8dcSSimon Schubert     }
47165796c8dcSSimon Schubert 
47175796c8dcSSimon Schubert   /* If a function name was obtained but it's not valid, we were not
47185796c8dcSSimon Schubert      successful.  */
47195796c8dcSSimon Schubert   if (LEN_STRING (declp) == 1 && declp->b[0] == '.')
47205796c8dcSSimon Schubert     return 0;
47215796c8dcSSimon Schubert   else
47225796c8dcSSimon Schubert     return 1;
47235796c8dcSSimon Schubert }
47245796c8dcSSimon Schubert 
47255796c8dcSSimon Schubert /* a mini string-handling package */
47265796c8dcSSimon Schubert 
47275796c8dcSSimon Schubert static void
string_need(string * s,int n)47285796c8dcSSimon Schubert string_need (string *s, int n)
47295796c8dcSSimon Schubert {
47305796c8dcSSimon Schubert   int tem;
47315796c8dcSSimon Schubert 
47325796c8dcSSimon Schubert   if (s->b == NULL)
47335796c8dcSSimon Schubert     {
47345796c8dcSSimon Schubert       if (n < 32)
47355796c8dcSSimon Schubert 	{
47365796c8dcSSimon Schubert 	  n = 32;
47375796c8dcSSimon Schubert 	}
47385796c8dcSSimon Schubert       s->p = s->b = XNEWVEC (char, n);
47395796c8dcSSimon Schubert       s->e = s->b + n;
47405796c8dcSSimon Schubert     }
47415796c8dcSSimon Schubert   else if (s->e - s->p < n)
47425796c8dcSSimon Schubert     {
47435796c8dcSSimon Schubert       tem = s->p - s->b;
47445796c8dcSSimon Schubert       n += tem;
47455796c8dcSSimon Schubert       n *= 2;
47465796c8dcSSimon Schubert       s->b = XRESIZEVEC (char, s->b, n);
47475796c8dcSSimon Schubert       s->p = s->b + tem;
47485796c8dcSSimon Schubert       s->e = s->b + n;
47495796c8dcSSimon Schubert     }
47505796c8dcSSimon Schubert }
47515796c8dcSSimon Schubert 
47525796c8dcSSimon Schubert static void
string_delete(string * s)47535796c8dcSSimon Schubert string_delete (string *s)
47545796c8dcSSimon Schubert {
47555796c8dcSSimon Schubert   if (s->b != NULL)
47565796c8dcSSimon Schubert     {
47575796c8dcSSimon Schubert       free (s->b);
47585796c8dcSSimon Schubert       s->b = s->e = s->p = NULL;
47595796c8dcSSimon Schubert     }
47605796c8dcSSimon Schubert }
47615796c8dcSSimon Schubert 
47625796c8dcSSimon Schubert static void
string_init(string * s)47635796c8dcSSimon Schubert string_init (string *s)
47645796c8dcSSimon Schubert {
47655796c8dcSSimon Schubert   s->b = s->p = s->e = NULL;
47665796c8dcSSimon Schubert }
47675796c8dcSSimon Schubert 
47685796c8dcSSimon Schubert static void
string_clear(string * s)47695796c8dcSSimon Schubert string_clear (string *s)
47705796c8dcSSimon Schubert {
47715796c8dcSSimon Schubert   s->p = s->b;
47725796c8dcSSimon Schubert }
47735796c8dcSSimon Schubert 
47745796c8dcSSimon Schubert #if 0
47755796c8dcSSimon Schubert 
47765796c8dcSSimon Schubert static int
47775796c8dcSSimon Schubert string_empty (string *s)
47785796c8dcSSimon Schubert {
47795796c8dcSSimon Schubert   return (s->b == s->p);
47805796c8dcSSimon Schubert }
47815796c8dcSSimon Schubert 
47825796c8dcSSimon Schubert #endif
47835796c8dcSSimon Schubert 
47845796c8dcSSimon Schubert static void
string_append(string * p,const char * s)47855796c8dcSSimon Schubert string_append (string *p, const char *s)
47865796c8dcSSimon Schubert {
47875796c8dcSSimon Schubert   int n;
47885796c8dcSSimon Schubert   if (s == NULL || *s == '\0')
47895796c8dcSSimon Schubert     return;
47905796c8dcSSimon Schubert   n = strlen (s);
47915796c8dcSSimon Schubert   string_need (p, n);
47925796c8dcSSimon Schubert   memcpy (p->p, s, n);
47935796c8dcSSimon Schubert   p->p += n;
47945796c8dcSSimon Schubert }
47955796c8dcSSimon Schubert 
47965796c8dcSSimon Schubert static void
string_appends(string * p,string * s)47975796c8dcSSimon Schubert string_appends (string *p, string *s)
47985796c8dcSSimon Schubert {
47995796c8dcSSimon Schubert   int n;
48005796c8dcSSimon Schubert 
48015796c8dcSSimon Schubert   if (s->b != s->p)
48025796c8dcSSimon Schubert     {
48035796c8dcSSimon Schubert       n = s->p - s->b;
48045796c8dcSSimon Schubert       string_need (p, n);
48055796c8dcSSimon Schubert       memcpy (p->p, s->b, n);
48065796c8dcSSimon Schubert       p->p += n;
48075796c8dcSSimon Schubert     }
48085796c8dcSSimon Schubert }
48095796c8dcSSimon Schubert 
48105796c8dcSSimon Schubert static void
string_appendn(string * p,const char * s,int n)48115796c8dcSSimon Schubert string_appendn (string *p, const char *s, int n)
48125796c8dcSSimon Schubert {
48135796c8dcSSimon Schubert   if (n != 0)
48145796c8dcSSimon Schubert     {
48155796c8dcSSimon Schubert       string_need (p, n);
48165796c8dcSSimon Schubert       memcpy (p->p, s, n);
48175796c8dcSSimon Schubert       p->p += n;
48185796c8dcSSimon Schubert     }
48195796c8dcSSimon Schubert }
48205796c8dcSSimon Schubert 
48215796c8dcSSimon Schubert static void
string_prepend(string * p,const char * s)48225796c8dcSSimon Schubert string_prepend (string *p, const char *s)
48235796c8dcSSimon Schubert {
48245796c8dcSSimon Schubert   if (s != NULL && *s != '\0')
48255796c8dcSSimon Schubert     {
48265796c8dcSSimon Schubert       string_prependn (p, s, strlen (s));
48275796c8dcSSimon Schubert     }
48285796c8dcSSimon Schubert }
48295796c8dcSSimon Schubert 
48305796c8dcSSimon Schubert static void
string_prepends(string * p,string * s)48315796c8dcSSimon Schubert string_prepends (string *p, string *s)
48325796c8dcSSimon Schubert {
48335796c8dcSSimon Schubert   if (s->b != s->p)
48345796c8dcSSimon Schubert     {
48355796c8dcSSimon Schubert       string_prependn (p, s->b, s->p - s->b);
48365796c8dcSSimon Schubert     }
48375796c8dcSSimon Schubert }
48385796c8dcSSimon Schubert 
48395796c8dcSSimon Schubert static void
string_prependn(string * p,const char * s,int n)48405796c8dcSSimon Schubert string_prependn (string *p, const char *s, int n)
48415796c8dcSSimon Schubert {
48425796c8dcSSimon Schubert   char *q;
48435796c8dcSSimon Schubert 
48445796c8dcSSimon Schubert   if (n != 0)
48455796c8dcSSimon Schubert     {
48465796c8dcSSimon Schubert       string_need (p, n);
48475796c8dcSSimon Schubert       for (q = p->p - 1; q >= p->b; q--)
48485796c8dcSSimon Schubert 	{
48495796c8dcSSimon Schubert 	  q[n] = q[0];
48505796c8dcSSimon Schubert 	}
48515796c8dcSSimon Schubert       memcpy (p->b, s, n);
48525796c8dcSSimon Schubert       p->p += n;
48535796c8dcSSimon Schubert     }
48545796c8dcSSimon Schubert }
48555796c8dcSSimon Schubert 
48565796c8dcSSimon Schubert static void
string_append_template_idx(string * s,int idx)48575796c8dcSSimon Schubert string_append_template_idx (string *s, int idx)
48585796c8dcSSimon Schubert {
48595796c8dcSSimon Schubert   char buf[INTBUF_SIZE + 1 /* 'T' */];
48605796c8dcSSimon Schubert   sprintf(buf, "T%d", idx);
48615796c8dcSSimon Schubert   string_append (s, buf);
48625796c8dcSSimon Schubert }
4863