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