/SheepShaver/src/kpx_cpu/src/cpu/jit/cxxdemangle.cpp
C++ | 4495 lines | 3251 code | 475 blank | 769 comment | 938 complexity | 1d936889ed9087db9f479b5db6bf9a35 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /*
- * cxxdemangle.cpp - C++ demangler
- *
- * Kheperix (C) 2003-2005 Gwenole Beauchesne
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <stdio.h>
- #include <stddef.h>
- #include <string.h>
- #include "cxxdemangle.h"
- #if defined(__GNUC__) && (__GXX_ABI_VERSION > 0)
- #include <cxxabi.h>
- char *
- cxx_demangle(const char *mangled_name, char *buf, size_t *n, int *status)
- {
- return abi::__cxa_demangle(mangled_name, buf, n, status);
- }
- #else
- /* Use demangler from libiberty */
- char *cplus_demangle (const char *mangled, int options);
- /* Options passed to cplus_demangle (in 2nd parameter). */
- #define DMGL_NO_OPTS 0 /* For readability... */
- #define DMGL_PARAMS (1 << 0) /* Include function args */
- #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
- #define DMGL_AUTO (1 << 8)
- #define DMGL_GNU (1 << 9)
- #define DMGL_LUCID (1 << 10)
- #define DMGL_ARM (1 << 11)
- #define DMGL_HP (1 << 12)
- #define DMGL_EDG (1 << 13)
- #ifdef __GNUC__
- #define DMGL_COMPILER DMGL_GNU
- #endif
- char *
- cxx_demangle(const char *mangled_name, char *buf, size_t *n, int *status)
- {
- if (mangled_name == NULL || (buf != NULL && n == NULL)) {
- if (status)
- *status = -3;
- return NULL;
- }
- char *demangled = cplus_demangle(mangled_name, DMGL_COMPILER | DMGL_PARAMS | DMGL_ANSI);
- if (demangled == NULL) {
- if (status)
- *status = -2;
- return NULL;
- }
- else {
- int len = strlen(demangled) + 1;
- if (buf && n) {
- if (len <= *n)
- strcpy(buf, demangled);
- else {
- if (status)
- *status = -1;
- return NULL;
- }
- }
- }
- if (status)
- *status = 0;
- return demangled;
- }
- #include <stdlib.h>
- #define xmalloc(size) malloc(size)
- #define xrealloc(ptr, size) realloc(ptr, size)
- #include <ctype.h>
- #define ISDIGIT(c) isdigit(c)
- #define ISLOWER(c) islower(c)
- /* ANSI and traditional C compatability macros
- Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
- This file is part of the GNU C Library. */
- #define PARAMS(ARGS) ARGS
- /* Define macros for some gcc attributes. This permits us to use the
- macros freely, and know that they will come into play for the
- version of gcc in which they are supported. */
- #ifndef ATTRIBUTE_UNUSED
- #define ATTRIBUTE_UNUSED
- #endif /* ATTRIBUTE_UNUSED */
- #ifndef ATTRIBUTE_NORETURN
- #define ATTRIBUTE_NORETURN
- #endif /* ATTRIBUTE_NORETURN */
- /* Demangler for GNU C++
- Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001 Free Software Foundation, Inc.
- Written by James Clark (jjc@jclark.uucp)
- Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
- Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
- This file is part of the libiberty library. */
- /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
- This file imports xmalloc and xrealloc, which are like malloc and
- realloc except that they generate a fatal error if there is no
- available memory. */
- /* This file lives in both GCC and libiberty. When making changes, please
- try not to break either. */
- #undef CURRENT_DEMANGLING_STYLE
- #define CURRENT_DEMANGLING_STYLE work->options
- #define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO)
- #define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU)
- #define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID)
- #define ARM_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_ARM)
- #define HP_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_HP)
- #define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG)
- #define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3)
- #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
- /* A value at least one greater than the maximum number of characters
- that will be output when using the `%d' format with `printf'. */
- #define INTBUF_SIZE 32
- #ifndef ARRAY_SIZE
- #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
- #endif
- extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
- /* In order to allow a single demangler executable to demangle strings
- using various common values of CPLUS_MARKER, as well as any specific
- one set at compile time, we maintain a string containing all the
- commonly used ones, and check to see if the marker we are looking for
- is in that string. CPLUS_MARKER is usually '$' on systems where the
- assembler can deal with that. Where the assembler can't, it's usually
- '.' (but on many systems '.' is used for other things). We put the
- current defined CPLUS_MARKER first (which defaults to '$'), followed
- by the next most common value, followed by an explicit '$' in case
- the value of CPLUS_MARKER is not '$'.
- We could avoid this if we could just get g++ to tell us what the actual
- cplus marker character is as part of the debug information, perhaps by
- ensuring that it is the character that terminates the gcc<n>_compiled
- marker symbol (FIXME). */
- #if !defined (CPLUS_MARKER)
- #define CPLUS_MARKER '$'
- #endif
- static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
- static char char_str[2] = { '\000', '\000' };
- typedef struct string /* Beware: these aren't required to be */
- { /* '\0' terminated. */
- char *b; /* pointer to start of string */
- char *p; /* pointer after last character */
- char *e; /* pointer after end of allocated space */
- } string;
- /* Stuff that is shared between sub-routines.
- Using a shared structure allows cplus_demangle to be reentrant. */
- struct work_stuff
- {
- int options;
- char **typevec;
- char **ktypevec;
- char **btypevec;
- int numk;
- int numb;
- int ksize;
- int bsize;
- int ntypes;
- int typevec_size;
- int constructor;
- int destructor;
- int static_type; /* A static member function */
- int temp_start; /* index in demangled to start of template args */
- int type_quals; /* The type qualifiers. */
- int dllimported; /* Symbol imported from a PE DLL */
- char **tmpl_argvec; /* Template function arguments. */
- int ntmpl_args; /* The number of template function arguments. */
- int forgetting_types; /* Nonzero if we are not remembering the types
- we see. */
- string* previous_argument; /* The last function argument demangled. */
- int nrepeats; /* The number of times to repeat the previous
- argument. */
- };
- #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
- #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
- static const struct optable
- {
- const char *const in;
- const char *const out;
- const int flags;
- } optable[] = {
- {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */
- {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */
- {"new", " new", 0}, /* old (1.91, and 1.x) */
- {"delete", " delete", 0}, /* old (1.91, and 1.x) */
- {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */
- {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */
- {"as", "=", DMGL_ANSI}, /* ansi */
- {"ne", "!=", DMGL_ANSI}, /* old, ansi */
- {"eq", "==", DMGL_ANSI}, /* old, ansi */
- {"ge", ">=", DMGL_ANSI}, /* old, ansi */
- {"gt", ">", DMGL_ANSI}, /* old, ansi */
- {"le", "<=", DMGL_ANSI}, /* old, ansi */
- {"lt", "<", DMGL_ANSI}, /* old, ansi */
- {"plus", "+", 0}, /* old */
- {"pl", "+", DMGL_ANSI}, /* ansi */
- {"apl", "+=", DMGL_ANSI}, /* ansi */
- {"minus", "-", 0}, /* old */
- {"mi", "-", DMGL_ANSI}, /* ansi */
- {"ami", "-=", DMGL_ANSI}, /* ansi */
- {"mult", "*", 0}, /* old */
- {"ml", "*", DMGL_ANSI}, /* ansi */
- {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */
- {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */
- {"convert", "+", 0}, /* old (unary +) */
- {"negate", "-", 0}, /* old (unary -) */
- {"trunc_mod", "%", 0}, /* old */
- {"md", "%", DMGL_ANSI}, /* ansi */
- {"amd", "%=", DMGL_ANSI}, /* ansi */
- {"trunc_div", "/", 0}, /* old */
- {"dv", "/", DMGL_ANSI}, /* ansi */
- {"adv", "/=", DMGL_ANSI}, /* ansi */
- {"truth_andif", "&&", 0}, /* old */
- {"aa", "&&", DMGL_ANSI}, /* ansi */
- {"truth_orif", "||", 0}, /* old */
- {"oo", "||", DMGL_ANSI}, /* ansi */
- {"truth_not", "!", 0}, /* old */
- {"nt", "!", DMGL_ANSI}, /* ansi */
- {"postincrement","++", 0}, /* old */
- {"pp", "++", DMGL_ANSI}, /* ansi */
- {"postdecrement","--", 0}, /* old */
- {"mm", "--", DMGL_ANSI}, /* ansi */
- {"bit_ior", "|", 0}, /* old */
- {"or", "|", DMGL_ANSI}, /* ansi */
- {"aor", "|=", DMGL_ANSI}, /* ansi */
- {"bit_xor", "^", 0}, /* old */
- {"er", "^", DMGL_ANSI}, /* ansi */
- {"aer", "^=", DMGL_ANSI}, /* ansi */
- {"bit_and", "&", 0}, /* old */
- {"ad", "&", DMGL_ANSI}, /* ansi */
- {"aad", "&=", DMGL_ANSI}, /* ansi */
- {"bit_not", "~", 0}, /* old */
- {"co", "~", DMGL_ANSI}, /* ansi */
- {"call", "()", 0}, /* old */
- {"cl", "()", DMGL_ANSI}, /* ansi */
- {"alshift", "<<", 0}, /* old */
- {"ls", "<<", DMGL_ANSI}, /* ansi */
- {"als", "<<=", DMGL_ANSI}, /* ansi */
- {"arshift", ">>", 0}, /* old */
- {"rs", ">>", DMGL_ANSI}, /* ansi */
- {"ars", ">>=", DMGL_ANSI}, /* ansi */
- {"component", "->", 0}, /* old */
- {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */
- {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */
- {"indirect", "*", 0}, /* old */
- {"method_call", "->()", 0}, /* old */
- {"addr", "&", 0}, /* old (unary &) */
- {"array", "[]", 0}, /* old */
- {"vc", "[]", DMGL_ANSI}, /* ansi */
- {"compound", ", ", 0}, /* old */
- {"cm", ", ", DMGL_ANSI}, /* ansi */
- {"cond", "?:", 0}, /* old */
- {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */
- {"max", ">?", 0}, /* old */
- {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */
- {"min", "<?", 0}, /* old */
- {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
- {"nop", "", 0}, /* old (for operator=) */
- {"rm", "->*", DMGL_ANSI}, /* ansi */
- {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */
- };
- /* These values are used to indicate the various type varieties.
- They are all non-zero so that they can be used as `success'
- values. */
- typedef enum type_kind_t
- {
- tk_none,
- tk_pointer,
- tk_reference,
- tk_integral,
- tk_bool,
- tk_char,
- tk_real
- } type_kind_t;
- #define STRING_EMPTY(str) ((str) -> b == (str) -> p)
- #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
- string_prepend(str, " ");}
- #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
- string_append(str, " ");}
- #define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
- /* The scope separator appropriate for the language being demangled. */
- #define SCOPE_STRING(work) "::"
- #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
- #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
- /* Prototypes for local functions */
- static void
- delete_work_stuff PARAMS ((work_stuff *));
- static void
- delete_non_B_K_work_stuff PARAMS ((work_stuff *));
- static char *
- mop_up PARAMS ((work_stuff *, string *, int));
- static void
- squangle_mop_up PARAMS ((work_stuff *));
- static void
- work_stuff_copy_to_from PARAMS ((work_stuff *, work_stuff *));
- static char *
- internal_cplus_demangle PARAMS ((work_stuff *, const char *));
- static int
- demangle_template_template_parm PARAMS ((work_stuff *work,
- const char **, string *));
- static int
- demangle_template PARAMS ((work_stuff *work, const char **, string *,
- string *, int, int));
- static int
- arm_pt PARAMS ((work_stuff *, const char *, int, const char **,
- const char **));
- static int
- demangle_class_name PARAMS ((work_stuff *, const char **, string *));
- static int
- demangle_qualified PARAMS ((work_stuff *, const char **, string *,
- int, int));
- static int
- demangle_class PARAMS ((work_stuff *, const char **, string *));
- static int
- demangle_fund_type PARAMS ((work_stuff *, const char **, string *));
- static int
- demangle_signature PARAMS ((work_stuff *, const char **, string *));
- static int
- demangle_prefix PARAMS ((work_stuff *, const char **, string *));
- static int
- gnu_special PARAMS ((work_stuff *, const char **, string *));
- static int
- arm_special PARAMS ((const char **, string *));
- static void
- string_need PARAMS ((string *, int));
- static void
- string_delete PARAMS ((string *));
- static void
- string_init PARAMS ((string *));
- static void
- string_clear PARAMS ((string *));
- static void
- string_append PARAMS ((string *, const char *));
- static void
- string_appends PARAMS ((string *, string *));
- static void
- string_appendn PARAMS ((string *, const char *, int));
- static void
- string_prepend PARAMS ((string *, const char *));
- static void
- string_prependn PARAMS ((string *, const char *, int));
- static void
- string_append_template_idx PARAMS ((string *, int));
- static int
- get_count PARAMS ((const char **, int *));
- static int
- consume_count PARAMS ((const char **));
- static int
- consume_count_with_underscores PARAMS ((const char**));
- static int
- demangle_args PARAMS ((work_stuff *, const char **, string *));
- static int
- demangle_nested_args PARAMS ((work_stuff*, const char**, string*));
- static int
- do_type PARAMS ((work_stuff *, const char **, string *));
- static int
- do_arg PARAMS ((work_stuff *, const char **, string *));
- static void
- demangle_function_name PARAMS ((work_stuff *, const char **, string *,
- const char *));
- static int
- iterate_demangle_function PARAMS ((work_stuff *,
- const char **, string *, const char *));
- static void
- remember_type PARAMS ((work_stuff *, const char *, int));
- static void
- remember_Btype PARAMS ((work_stuff *, const char *, int, int));
- static int
- register_Btype PARAMS ((work_stuff *));
- static void
- remember_Ktype PARAMS ((work_stuff *, const char *, int));
- static void
- forget_types PARAMS ((work_stuff *));
- static void
- forget_B_and_K_types PARAMS ((work_stuff *));
- static void
- string_prepends PARAMS ((string *, string *));
- static int
- demangle_template_value_parm PARAMS ((work_stuff*, const char**,
- string*, type_kind_t));
- static int
- do_hpacc_template_const_value PARAMS ((work_stuff *, const char **, string *));
- static int
- do_hpacc_template_literal PARAMS ((work_stuff *, const char **, string *));
- static int
- snarf_numeric_literal PARAMS ((const char **, string *));
- /* There is a TYPE_QUAL value for each type qualifier. They can be
- combined by bitwise-or to form the complete set of qualifiers for a
- type. */
- #define TYPE_UNQUALIFIED 0x0
- #define TYPE_QUAL_CONST 0x1
- #define TYPE_QUAL_VOLATILE 0x2
- #define TYPE_QUAL_RESTRICT 0x4
- static int
- code_for_qualifier PARAMS ((int));
- static const char*
- qualifier_string PARAMS ((int));
- static const char*
- demangle_qualifier PARAMS ((int));
- static int
- demangle_expression PARAMS ((work_stuff *, const char **, string *,
- type_kind_t));
- static int
- demangle_integral_value PARAMS ((work_stuff *, const char **,
- string *));
- static int
- demangle_real_value PARAMS ((work_stuff *, const char **, string *));
- static void
- demangle_arm_hp_template PARAMS ((work_stuff *, const char **, int,
- string *));
- static void
- recursively_demangle PARAMS ((work_stuff *, const char **, string *,
- int));
- static void
- grow_vect PARAMS ((void **, size_t *, size_t, int));
- /* Translate count to integer, consuming tokens in the process.
- Conversion terminates on the first non-digit character.
- Trying to consume something that isn't a count results in no
- consumption of input and a return of -1.
- Overflow consumes the rest of the digits, and returns -1. */
- static int
- consume_count (const char **type)
- {
- int count = 0;
- if (! ISDIGIT ((unsigned char)**type))
- return -1;
- while (ISDIGIT ((unsigned char)**type))
- {
- count *= 10;
- /* Check for overflow.
- We assume that count is represented using two's-complement;
- no power of two is divisible by ten, so if an overflow occurs
- when multiplying by ten, the result will not be a multiple of
- ten. */
- if ((count % 10) != 0)
- {
- while (ISDIGIT ((unsigned char) **type))
- (*type)++;
- return -1;
- }
- count += **type - '0';
- (*type)++;
- }
- if (count < 0)
- count = -1;
- return (count);
- }
- /* Like consume_count, but for counts that are preceded and followed
- by '_' if they are greater than 10. Also, -1 is returned for
- failure, since 0 can be a valid value. */
- static int
- consume_count_with_underscores (const char **mangled)
- {
- int idx;
- if (**mangled == '_')
- {
- (*mangled)++;
- if (!ISDIGIT ((unsigned char)**mangled))
- return -1;
- idx = consume_count (mangled);
- if (**mangled != '_')
- /* The trailing underscore was missing. */
- return -1;
- (*mangled)++;
- }
- else
- {
- if (**mangled < '0' || **mangled > '9')
- return -1;
- idx = **mangled - '0';
- (*mangled)++;
- }
- return idx;
- }
- /* C is the code for a type-qualifier. Return the TYPE_QUAL
- corresponding to this qualifier. */
- static int
- code_for_qualifier (int c)
- {
- switch (c)
- {
- case 'C':
- return TYPE_QUAL_CONST;
- case 'V':
- return TYPE_QUAL_VOLATILE;
- case 'u':
- return TYPE_QUAL_RESTRICT;
- default:
- break;
- }
- /* C was an invalid qualifier. */
- abort ();
- }
- /* Return the string corresponding to the qualifiers given by
- TYPE_QUALS. */
- static const char*
- qualifier_string (int type_quals)
- {
- switch (type_quals)
- {
- case TYPE_UNQUALIFIED:
- return "";
- case TYPE_QUAL_CONST:
- return "const";
- case TYPE_QUAL_VOLATILE:
- return "volatile";
- case TYPE_QUAL_RESTRICT:
- return "__restrict";
- case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
- return "const volatile";
- case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
- return "const __restrict";
- case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
- return "volatile __restrict";
- case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
- return "const volatile __restrict";
- default:
- break;
- }
- /* TYPE_QUALS was an invalid qualifier set. */
- abort ();
- }
- /* C is the code for a type-qualifier. Return the string
- corresponding to this qualifier. This function should only be
- called with a valid qualifier code. */
- static const char*
- demangle_qualifier (int c)
- {
- return qualifier_string (code_for_qualifier (c));
- }
- /* char *cplus_demangle (const char *mangled, int options)
- If MANGLED is a mangled function name produced by GNU C++, then
- a pointer to a @code{malloc}ed string giving a C++ representation
- of the name will be returned; otherwise NULL will be returned.
- It is the caller's responsibility to free the string which
- is returned.
- The OPTIONS arg may contain one or more of the following bits:
- DMGL_ANSI ANSI qualifiers such as `const' and `void' are
- included.
- DMGL_PARAMS Function parameters are included.
- For example,
- cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
- cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
- cplus_demangle ("foo__1Ai", 0) => "A::foo"
- cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
- cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
- cplus_demangle ("foo__1Afe", 0) => "A::foo"
- Note that any leading underscores, or other such characters prepended by
- the compilation system, are presumed to have already been stripped from
- MANGLED. */
- char *
- cplus_demangle (const char *mangled, int options)
- {
- char *ret;
- work_stuff work[1];
- memset ((char *) work, 0, sizeof (work));
- work->options = options;
- ret = internal_cplus_demangle (work, mangled);
- squangle_mop_up (work);
- return (ret);
- }
- /* Assuming *OLD_VECT points to an array of *SIZE objects of size
- ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
- updating *OLD_VECT and *SIZE as necessary. */
- static void
- grow_vect (void **old_vect, size_t *size, size_t min_size, int element_size)
- {
- if (*size < min_size)
- {
- *size *= 2;
- if (*size < min_size)
- *size = min_size;
- *old_vect = (char *) xrealloc (*old_vect, *size * element_size);
- }
- }
- /* This function performs most of what cplus_demangle use to do, but
- to be able to demangle a name with a B, K or n code, we need to
- have a longer term memory of what types have been seen. The original
- now initializes and cleans up the squangle code info, while internal
- calls go directly to this routine to avoid resetting that info. */
- static char *
- internal_cplus_demangle (work_stuff *work, const char *mangled)
- {
- string decl;
- int success = 0;
- char *demangled = NULL;
- int s1, s2, s3, s4;
- s1 = work->constructor;
- s2 = work->destructor;
- s3 = work->static_type;
- s4 = work->type_quals;
- work->constructor = work->destructor = 0;
- work->type_quals = TYPE_UNQUALIFIED;
- work->dllimported = 0;
- if ((mangled != NULL) && (*mangled != '\0'))
- {
- string_init (&decl);
- /* First check to see if gnu style demangling is active and if the
- string to be demangled contains a CPLUS_MARKER. If so, attempt to
- recognize one of the gnu special forms rather than looking for a
- standard prefix. In particular, don't worry about whether there
- is a "__" string in the mangled string. Consider "_$_5__foo" for
- example. */
- if ((AUTO_DEMANGLING || GNU_DEMANGLING))
- {
- success = gnu_special (work, &mangled, &decl);
- }
- if (!success)
- {
- success = demangle_prefix (work, &mangled, &decl);
- }
- if (success && (*mangled != '\0'))
- {
- success = demangle_signature (work, &mangled, &decl);
- }
- if (work->constructor == 2)
- {
- string_prepend (&decl, "global constructors keyed to ");
- work->constructor = 0;
- }
- else if (work->destructor == 2)
- {
- string_prepend (&decl, "global destructors keyed to ");
- work->destructor = 0;
- }
- else if (work->dllimported == 1)
- {
- string_prepend (&decl, "import stub for ");
- work->dllimported = 0;
- }
- demangled = mop_up (work, &decl, success);
- }
- work->constructor = s1;
- work->destructor = s2;
- work->static_type = s3;
- work->type_quals = s4;
- return demangled;
- }
- /* Clear out and squangling related storage */
- static void
- squangle_mop_up (work_stuff *work)
- {
- /* clean up the B and K type mangling types. */
- forget_B_and_K_types (work);
- if (work -> btypevec != NULL)
- {
- free ((char *) work -> btypevec);
- }
- if (work -> ktypevec != NULL)
- {
- free ((char *) work -> ktypevec);
- }
- }
- /* Copy the work state and storage. */
- static void
- work_stuff_copy_to_from (work_stuff *to, work_stuff *from)
- {
- int i;
- delete_work_stuff (to);
- /* Shallow-copy scalars. */
- memcpy (to, from, sizeof (*to));
- /* Deep-copy dynamic storage. */
- if (from->typevec_size)
- to->typevec
- = (char **) xmalloc (from->typevec_size * sizeof (to->typevec[0]));
- for (i = 0; i < from->ntypes; i++)
- {
- int len = strlen (from->typevec[i]) + 1;
- to->typevec[i] = (char *) xmalloc (len);
- memcpy (to->typevec[i], from->typevec[i], len);
- }
- if (from->ksize)
- to->ktypevec
- = (char **) xmalloc (from->ksize * sizeof (to->ktypevec[0]));
- for (i = 0; i < from->numk; i++)
- {
- int len = strlen (from->ktypevec[i]) + 1;
- to->ktypevec[i] = (char *) xmalloc (len);
- memcpy (to->ktypevec[i], from->ktypevec[i], len);
- }
- if (from->bsize)
- to->btypevec
- = (char **) xmalloc (from->bsize * sizeof (to->btypevec[0]));
- for (i = 0; i < from->numb; i++)
- {
- int len = strlen (from->btypevec[i]) + 1;
- to->btypevec[i] = (char *) xmalloc (len);
- memcpy (to->btypevec[i], from->btypevec[i], len);
- }
- if (from->ntmpl_args)
- to->tmpl_argvec
- = (char **) xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0]));
- for (i = 0; i < from->ntmpl_args; i++)
- {
- int len = strlen (from->tmpl_argvec[i]) + 1;
- to->tmpl_argvec[i] = (char *) xmalloc (len);
- memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
- }
- if (from->previous_argument)
- {
- to->previous_argument = (string*) xmalloc (sizeof (string));
- string_init (to->previous_argument);
- string_appends (to->previous_argument, from->previous_argument);
- }
- }
- /* Delete dynamic stuff in work_stuff that is not to be re-used. */
- static void
- delete_non_B_K_work_stuff (work_stuff *work)
- {
- /* Discard the remembered types, if any. */
- forget_types (work);
- if (work -> typevec != NULL)
- {
- free ((char *) work -> typevec);
- work -> typevec = NULL;
- work -> typevec_size = 0;
- }
- if (work->tmpl_argvec)
- {
- int i;
- for (i = 0; i < work->ntmpl_args; i++)
- if (work->tmpl_argvec[i])
- free ((char*) work->tmpl_argvec[i]);
- free ((char*) work->tmpl_argvec);
- work->tmpl_argvec = NULL;
- }
- if (work->previous_argument)
- {
- string_delete (work->previous_argument);
- free ((char*) work->previous_argument);
- work->previous_argument = NULL;
- }
- }
- /* Delete all dynamic storage in work_stuff. */
- static void
- delete_work_stuff (work_stuff *work)
- {
- delete_non_B_K_work_stuff (work);
- squangle_mop_up (work);
- }
- /* Clear out any mangled storage */
- static char *
- mop_up (work_stuff *work, string *declp, int success)
- {
- char *demangled = NULL;
- delete_non_B_K_work_stuff (work);
- /* If demangling was successful, ensure that the demangled string is null
- terminated and return it. Otherwise, free the demangling decl. */
- if (!success)
- {
- string_delete (declp);
- }
- else
- {
- string_appendn (declp, "", 1);
- demangled = declp->b;
- }
- return (demangled);
- }
- /*
- LOCAL FUNCTION
- demangle_signature -- demangle the signature part of a mangled name
- SYNOPSIS
- static int
- demangle_signature (work_stuff *work, const char **mangled,
- string *declp);
- DESCRIPTION
- Consume and demangle the signature portion of the mangled name.
- DECLP is the string where demangled output is being built. At
- entry it contains the demangled root name from the mangled name
- prefix. I.E. either a demangled operator name or the root function
- name. In some special cases, it may contain nothing.
- *MANGLED points to the current unconsumed location in the mangled
- name. As tokens are consumed and demangling is performed, the
- pointer is updated to continuously point at the next token to
- be consumed.
- Demangling GNU style mangled names is nasty because there is no
- explicit token that marks the start of the outermost function
- argument list. */
- static int
- demangle_signature (work_stuff *work, const char **mangled, string *declp)
- {
- int success = 1;
- int func_done = 0;
- int expect_func = 0;
- int expect_return_type = 0;
- const char *oldmangled = NULL;
- string trawname;
- string tname;
- while (success && (**mangled != '\0'))
- {
- switch (**mangled)
- {
- case 'Q':
- oldmangled = *mangled;
- success = demangle_qualified (work, mangled, declp, 1, 0);
- if (success)
- remember_type (work, oldmangled, *mangled - oldmangled);
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
- expect_func = 1;
- oldmangled = NULL;
- break;
- case 'K':
- oldmangled = *mangled;
- success = demangle_qualified (work, mangled, declp, 1, 0);
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
- {
- expect_func = 1;
- }
- oldmangled = NULL;
- break;
- case 'S':
- /* Static member function */
- if (oldmangled == NULL)
- {
- oldmangled = *mangled;
- }
- (*mangled)++;
- work -> static_type = 1;
- break;
- case 'C':
- case 'V':
- case 'u':
- work->type_quals |= code_for_qualifier (**mangled);
- /* a qualified member function */
- if (oldmangled == NULL)
- oldmangled = *mangled;
- (*mangled)++;
- break;
- case 'L':
- /* Local class name follows after "Lnnn_" */
- if (HP_DEMANGLING)
- {
- while (**mangled && (**mangled != '_'))
- (*mangled)++;
- if (!**mangled)
- success = 0;
- else
- (*mangled)++;
- }
- else
- success = 0;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (oldmangled == NULL)
- {
- oldmangled = *mangled;
- }
- work->temp_start = -1; /* uppermost call to demangle_class */
- success = demangle_class (work, mangled, declp);
- if (success)
- {
- remember_type (work, oldmangled, *mangled - oldmangled);
- }
- if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
- {
- /* EDG and others will have the "F", so we let the loop cycle
- if we are looking at one. */
- if (**mangled != 'F')
- expect_func = 1;
- }
- oldmangled = NULL;
- break;
- case 'B':
- {
- string s;
- success = do_type (work, mangled, &s);
- if (success)
- {
- string_append (&s, SCOPE_STRING (work));
- string_prepends (declp, &s);
- }
- oldmangled = NULL;
- expect_func = 1;
- }
- break;
- case 'F':
- /* Function */
- /* ARM/HP style demangling includes a specific 'F' character after
- the class name. For GNU style, it is just implied. So we can
- safely just consume any 'F' at this point and be compatible
- with either style. */
- oldmangled = NULL;
- func_done = 1;
- (*mangled)++;
- /* For lucid/ARM/HP style we have to forget any types we might
- have remembered up to this point, since they were not argument
- types. GNU style considers all types seen as available for
- back references. See comment in demangle_args() */
- if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
- {
- forget_types (work);
- }
- success = demangle_args (work, mangled, declp);
- /* After picking off the function args, we expect to either
- find the function return type (preceded by an '_') or the
- end of the string. */
- if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
- {
- ++(*mangled);
- /* At this level, we do not care about the return type. */
- success = do_type (work, mangled, &tname);
- string_delete (&tname);
- }
- break;
- case 't':
- /* G++ Template */
- string_init(&trawname);
- string_init(&tname);
- if (oldmangled == NULL)
- {
- oldmangled = *mangled;
- }
- success = demangle_template (work, mangled, &tname,
- &trawname, 1, 1);
- if (success)
- {
- remember_type (work, oldmangled, *mangled - oldmangled);
- }
- string_append (&tname, SCOPE_STRING (work));
- string_prepends(declp, &tname);
- if (work -> destructor & 1)
- {
- string_prepend (&trawname, "~");
- string_appends (declp, &trawname);
- work->destructor -= 1;
- }
- if ((work->constructor & 1) || (work->destructor & 1))
- {
- string_appends (declp, &trawname);
- work->constructor -= 1;
- }
- string_delete(&trawname);
- string_delete(&tname);
- oldmangled = NULL;
- expect_func = 1;
- break;
- case '_':
- if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
- {
- /* Read the return type. */
- string return_type;
- string_init (&return_type);
- (*mangled)++;
- success = do_type (work, mangled, &return_type);
- APPEND_BLANK (&return_type);
- string_prepends (declp, &return_type);
- string_delete (&return_type);
- break;
- }
- else
- /* At the outermost level, we cannot have a return type specified,
- so if we run into another '_' at this point we are dealing with
- a mangled name that is either bogus, or has been mangled by
- some algorithm we don't know how to deal with. So just
- reject the entire demangling. */
- /* However, "_nnn" is an expected suffix for alternate entry point
- numbered nnn for a function, with HP aCC, so skip over that
- without reporting failure. pai/1997-09-04 */
- if (HP_DEMANGLING)
- {
- (*mangled)++;
- while (**mangled && ISDIGIT ((unsigned char)**mangled))
- (*mangled)++;
- }
- else
- success = 0;
- break;
- case 'H':
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
- {
- /* A G++ template function. Read the template arguments. */
- success = demangle_template (work, mangled, declp, 0, 0,
- 0);
- if (!(work->constructor & 1))
- expect_return_type = 1;
- (*mangled)++;
- break;
- }
- else
- /* fall through */
- {;}
- default:
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
- {
- /* Assume we have stumbled onto the first outermost function
- argument token, and start processing args. */
- func_done = 1;
- success = demangle_args (work, mangled, declp);
- }
- else
- {
- /* Non-GNU demanglers use a specific token to mark the start
- of the outermost function argument tokens. Typically 'F',
- for ARM/HP-demangling, for example. So if we find something
- we are not prepared for, it must be an error. */
- success = 0;
- }
- break;
- }
- /*
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
- */
- {
- if (success && expect_func)
- {
- func_done = 1;
- if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
- {
- forget_types (work);
- }
- success = demangle_args (work, mangled, declp);
- /* Since template include the mangling of their return types,
- we must set expect_func to 0 so that we don't try do
- demangle more arguments the next time we get here. */
- expect_func = 0;
- }
- }
- }
- if (success && !func_done)
- {
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
- {
- /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
- bar__3fooi is 'foo::bar(int)'. We get here when we find the
- first case, and need to ensure that the '(void)' gets added to
- the current declp. Note that with ARM/HP, the first case
- represents the name of a static data member 'foo::bar',
- which is in the current declp, so we leave it alone. */
- success = demangle_args (work, mangled, declp);
- }
- }
- if (success && PRINT_ARG_TYPES)
- {
- if (work->static_type)
- string_append (declp, " static");
- if (work->type_quals != TYPE_UNQUALIFIED)
- {
- APPEND_BLANK (declp);
- string_append (declp, qualifier_string (work->type_quals));
- }
- }
- return (success);
- }
- static int
- demangle_template_template_parm (work_stuff *work,
- const char **mangled,
- string *tname)
- {
- int i;
- int r;
- int need_comma = 0;
- int success = 1;
- string temp;
- string_append (tname, "template <");
- /* get size of template parameter list */
- if (get_count (mangled, &r))
- {
- for (i = 0; i < r; i++)
- {
- if (need_comma)
- {
- string_append (tname, ", ");
- }
- /* Z for type parameters */
- if (**mangled == 'Z')
- {
- (*mangled)++;
- string_append (tname, "class");
- }
- /* z for template parameters */
- else if (**mangled == 'z')
- {
- (*mangled)++;
- success =
- demangle_template_template_parm (work, mangled, tname);
- if (!success)
- {
- break;
- }
- }
- else
- {
- /* temp is initialized in do_type */
- success = do_type (work, mangled, &temp);
- if (success)
- {
- string_appends (tname, &temp);
- }
- string_delete(&temp);
- if (!success)
- {
- break;
- }
- }
- need_comma = 1;
- }
- }
- if (tname->p[-1] == '>')
- string_append (tname, " ");
- string_append (tname, "> class");
- return (success);
- }
- static int
- demangle_expression (
- work_stuff *work,
- const char** mangled,
- string* s,
- type_kind_t tk)
- {
- int need_operator = 0;
- int success;
- success = 1;
- string_appendn (s, "(", 1);
- (*mangled)++;
- while (success && **mangled != 'W' && **mangled != '\0')
- {
- if (need_operator)
- {
- size_t i;
- size_t len;
- success = 0;
- len = strlen (*mangled);
- for (i = 0; i < (size_t)ARRAY_SIZE (optable); ++i)
- {
- size_t l = strlen (optable[i].in);
- if (l <= len
- && memcmp (optable[i].in, *mangled, l) == 0)
- {
- string_appendn (s, " ", 1);
- string_append (s, optable[i].out);
- string_appendn (s, " ", 1);
- success = 1;
- (*mangled) += l;
- break;
- }
- }
- if (!success)
- break;
- }
- else
- need_operator = 1;
- success = demangle_template_value_parm (work, mangled, s, tk);
- }
- if (**mangled != 'W')
- success = 0;
- else
- {
- string_appendn (s, ")", 1);
- (*mangled)++;
- }
- return success;
- }
- static int
- demangle_integral_value (
- work_stuff *work,
- const char** mangled,
- string* s)
- {
- int success;
- if (**mangled == 'E')
- success = demangle_expression (work, mangled, s, tk_integral);
- else if (**mangled == 'Q' || **mangled == 'K')
- success = demangle_qualified (work, mangled, s, 0, 1);
- else
- {
- int value;
- /* By default, we let the number decide whether we shall consume an
- underscore. */
- int consume_following_underscore = 0;
- int leave_following_underscore = 0;
- success = 0;
- /* Negative numbers are indicated with a leading `m'. */
- if (**mangled == 'm')
- {
- string_appendn (s, "-", 1);
- (*mangled)++;
- }
- else if (mangled[0][0] == '_' && mangled[0][1] == 'm')
- {
- /* Since consume_count_with_underscores does not handle the
- `m'-prefix we must do it here, using consume_count and
- adjusting underscores: we have to consume the underscore
- matching the prepended one. */
- consume_following_underscore = 1;
- string_appendn (s, "-", 1);
- (*mangled) += 2;
- }
- else if (**mangled == '_')
- {
- /* Do not consume a following underscore;
- consume_following_underscore will consume what should be
- consumed. */
- leave_following_underscore = 1;
- }
- /* We must call consume_count if we expect to remove a trailing
- underscore, since consume_count_with_underscores expects
- the leading underscore (that we consumed) if it is to handle
- multi-digit numbers. */
- if (consume_following_underscore)
- value = consume_count (mangled);
- else
- value = consume_count_with_underscores (mangled);
- if (value != -1)
- {
- char buf[INTBUF_SIZE];
- sprintf (buf, "%d", value);
- string_append (s, buf);
- /* Numbers not otherwise delimited, might have an underscore
- appended as a delimeter, which we should skip.
- ??? This used to always remove a following underscore, which
- is wrong. If other (arbitrary) cases are followed by an
- underscore, we need to do something more radical. */
- if ((value > 9 || consume_following_underscore)
- && ! leave_following_underscore
- && **mangled == '_')
- (*mangled)++;
- /* All is well. */
- success = 1;
- }
- }
- return success;
- }
- /* Demangle the real value in MANGLED. */
- static int
- demangle_real_value (
- work_stuff *work,
- const char **mangled,
- string* s)
- {
- if (**mangled == 'E')
- return demangle_expression (work, mangled, s, tk_real);
- if (**mangled == 'm')
- {
- string_appendn (s, "-", 1);
- (*mangled)++;
- }
- while (ISDIGIT ((unsigned char)**mangled))
- {
- string_appendn (s, *mangled, 1);
- (*mangled)++;
- }
- if (**mangled == '.') /* fraction */
- {
- string_appendn (s, ".", 1);
- (*mangled)++;
- while (ISDIGIT ((unsigned char)**mangled))
- {
- string_appendn (s, *mangled, 1);
- (*mangled)++;
- }
- }
- if (**mangled == 'e') /* exponent */
- {
- string_appendn (s, "e", 1);
- (*mangled)++;
- while (ISDIGIT ((unsigned char)**mangled))
- {
- string_appendn (s, *mangled, 1);
- (*mangled)++;
- }
- }
- return 1;
- }
- static int
- demangle_template_value_parm (
- work_stuff *work,
- const char **mangled,
- string* s,
- type_kind_t tk)
- {
- int success = 1;
- if (**mangled == 'Y')
- {
- /* The next argument is a template parameter. */
- int idx;
- (*mangled)++;
- idx = consume_count_with_underscores (mangled);
- if (idx == -1
- || (work->tmpl_argvec && idx >= work->ntmpl_args)
- || consume_count_with_underscores (mangled) == -1)
- return -1;
- if (work->tmpl_argvec)
- string_append (s, work->tmpl_argvec[idx]);
- else
- string_append_template_idx (s, idx);
- }
- else if (tk == tk_integral)
- success = demangle_integral_value (work, mangled, s);
- else if (tk == tk_char)
- {
- char tmp[2];
- int val;
- if (**mangled == 'm')
- {
- string_appendn (s, "-", 1);
- (*mangled)++;
- }
- string_appendn (s, "'", 1);
- val = consume_count(mangled);
- if (val <= 0)
- success = 0;
- else
- {
- tmp[0] = (char)val;
- tmp[1] = '\0';
- string_appendn (s, &tmp[0], 1);
- string_appendn (s, "'", 1);
- }
- }
- else if (tk == tk_bool)
- {
- int val = consume_count (mangled);
- if (val == 0)
- string_appendn (s, "false", 5);
- else if (val == 1)
- string_appendn (s, "true", 4);
- else
- success = 0;
- }
- else if (tk == tk_real)
- success = demangle_real_value (work, mangled, s);
- else if (tk == tk_pointer || tk == tk_reference)
- {
- if (**mangled == 'Q')
- success = demangle_qualified (work, mangled, s,
- /*isfuncname=*/0,
- /*append=*/1);
- else
- {
- int symbol_len = consume_count (mangled);
- if (symbol_len == -1)
- return -1;
- if (symbol_len == 0)
- string_appendn (s, "0", 1);
- else
- {
- char *p = (char *) xmalloc (symbol_len + 1), *q;
- strncpy (p, *mangled, symbol_len);
- p [symbol_len] = '\0';
- /* We use cplus_demangle here, rather than
- internal_cplus_demangle, because the name of the entity
- mangled here does not make use of any of the squangling
- or type-code information we have built up thus far; it is
- mangled independently. */
- q = cplus_demangle (p, work->options);
- if (tk == tk_pointer)
- string_appendn (s, "&", 1);
- /* FIXME: Pointer-to-member constants should get a
- qualifying class name here. */
- if (q)
- {
- string_append (s, q);
- free (q);
- }
- else
- string_append (s, p);
- free (p);
- }
- *mangled += symbol_len;
- }
- }
- return success;
- }
- /* Demangle the template name in MANGLED. The full name of the
- template (e.g., S<int>) is placed in TNAME. The name without the
- template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is
- non-NULL. If IS_TYPE is nonzero, this template is a type template,
- not a function template. If both IS_TYPE and REMEMBER are nonzero,
- the template is remembered in the list of back-referenceable
- types. */
- static int
- demangle_template (
- work_stuff *work,
- const char **mangled,
- string *tname,
- string *trawname,
- int is_type,
- int remember)
- {
- int i;
- int r;
- int need_comma = 0;
- int success = 0;
- const char *start;
- int is_java_array = 0;
- string temp;
- int bindex = 0;
- (*mangled)++;
- if (is_type)
- {
- if (remember)
- bindex = register_Btype (work);
- start = *mangled;
- /* get template name */
- if (**mangled == 'z')
- {
- int idx;
- (*mangled)++;
- (*mangled)++;
- idx = consume_count_with_underscores (mangled);
- if (idx == -1
- || (work->tmpl_argvec && idx >= work->ntmpl_args)
- || consume_count_with_underscores (mangled) == -1)
- return (0);
- if (work->tmpl_argvec)
- {
- string_append (tname, work->tmpl_argvec[idx]);
- if (trawname)
- string_append (trawname, work->tmpl_argvec[idx]);
- }
- else
- {
- string_append_template_idx (tname, idx);
- if (trawname)
- string_append_template_idx (trawname, idx);
- }
- }
- else
- {
- if ((r = consume_count (mangled)) <= 0
- || (int) strlen (*mangled) < r)
- {
- return (0);
- }
- string_appendn (tname, *mangled, r);
- if (trawname)
- string_appendn (trawname, *mangled, r);
- *mangled += r;
- }
- }
- if (!is_java_array)
- string_append (tname, "<");
- /* get size of template parameter list */
- if (!get_count (mangled, &r))
- {
- return (0);
- }
- if (!is_type)
- {
- /* Create an array for saving the template argument values. */
- work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
- work->ntmpl_args = r;
- for (i = 0; i < r; i++)
- work->tmpl_argvec[i] = 0;
- }
- for (i = 0; i < r; i++)
- {
- if (need_comma)
- {
- string_append (tname, ", ");
- }
- /* Z for type parameters */
- if (**mangled == 'Z')
- {
- (*mangled)++;
- /* temp is initialized in do_type */
- success = do_type (work, mangled, &temp);
- if (success)
- {
- string_appends (tname, &temp);
- if (!is_type)
- {
- /* Save the template argument. */
- int len = temp.p - temp.b;
- work->tmpl_argvec[i] = (char *) xmalloc (len + 1);
- memcpy (work->tmpl_argvec[i], temp.b, len);
- work->tmpl_argvec[i][len] = '\0';
- }
- }
- string_delete(&temp);
- if (!success)
- {
- break;
- }
- }
- /* z for template parameters */
- else if (**mangled == 'z')
- {
- int r2;
- (*mangled)++;
- success = demangle_template_template_parm (work, mangled, tname);
- if (success
- && (r2 = consume_count (mangled)) > 0
- && (int) strlen (*mangled) >= r2)
- {
- string_append (tname, " ");
- string_appendn (tname, *mangled, r2);
- if (!is_type)
- {
- /* Save the template argument. */
- int len = r2;
- work->tmpl_argvec[i] = (char *) xmalloc (len + 1);
- memcpy (work->tmpl_argvec[i], *mangled, len);
- work->tmpl_argvec[i][len] = '\0';
- }
- *mangled += r2;
- }
- if (!success)
- {
- break;
- }
- }
- else
- {
- string param;
- string* s;
- /* otherwise, value parameter */
- /* temp is initialized in do_type */
- success = do_type (work, mangled, &temp);
- string_delete(&temp);
- if (!success)
- break;
- if (!is_type)
- {
- s = ¶m;
- string_init (s);
- }
- else
- s = tname;
- success = demangle_template_value_parm (work, mangled, s,
- (type_kind_t) success);
- if (!success)
- {
- if (!is_type)
- string_delete (s);
- success = 0;
- break;
- }
- if (!is_type)
- {
- int len = s->p - s->b;
- work->tmpl_argvec[i] = (char *) xmalloc (len + 1);
- memcpy (work->tmpl_argvec[i], s->b, len);
- work->tmpl_argvec[i][len] = '\0';
- string_appends (tname, s);
- string_delete (s);
- }
- }
- need_comma = 1;
- }
- if (is_java_array)
- {
- string_append (tname, "[]");
- }
- else
- {
- if (tname->p[-1] == '>')
- string_append (tname, " ");
- string_append (tname, ">");
- }
- if (is_type && remember)
- remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
- /*
- if (work -> static_type)
- {
- string_append (declp, *mangled + 1);
- *mangled += strlen (*mangled);
- success = 1;
- }
- else
- {
- success = demangle_args (work, mangled, declp);
- }
- }
- */
- return (success);
- }
- static int
- arm_pt (
- work_stuff *work,
- const char *mangled,
- int n,
- const char **anchor,
- const char **args)
- {
- /* Check if ARM template with "__pt__" in it ("parameterized type") */
- /* Allow HP also here, because HP's cfront compiler follows ARM to some extent */
- if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
- {
- int len;
- *args = *anchor + 6;
- len = consume_count (args);
- if (len == -1)
- return 0;
- if (*args + len == mangled + n && **args == '_')
- {
- ++*args;
- return 1;
- }
- }
- if (AUTO_DEMANGLING || EDG_DEMANGLING)
- {
- if ((*anchor = strstr (mangled, "__tm__"))
- || (*anchor = strstr (mangled, "__ps__"))
- || (*anchor = strstr (mangled, "__pt__")))
- {
- int len;
- *args = *anchor + 6;
- len = consume_count (args);
- if (len == -1)
- return 0;
- if (*args + len == mangled + n && **args == '_')
- {
- ++*args;
- return 1;
- }
- }
- else if ((*anchor = strstr (mangled, "__S")))
- {
- int len;
- *args = *anchor + 3;
- len = consume_count (args);
- if (len == -1)
- return 0;
- if (*args + len == mangled + n && **args == '_')
- {
- ++*args;
- return 1;
- }
- }
- }
- return 0;
- }
- static void
- demangle_arm_hp_template (
- work_stuff *work,
- const char **mangled,
- int n,
- string *declp)
- {
- const char *p;
- const char *args;
- const char *e = *mangled + n;
- string arg;
- /* Check for HP aCC template spec: classXt1t2 where t1, t2 are
- template args */
- if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
- {
- char *start_spec_args = NULL;
- /* First check for and omit template specialization pseudo-arguments,
- such as in "Spec<#1,#1.*>" */
- start_spec_args = strchr (*mangled, '<');
- if (start_spec_args && (start_spec_args - *mangled < n))
- string_appendn (declp, *mangled, start_spec_args - *mangled);
- else
- string_appendn (declp, *mangled, n);
- (*mangled) += n + 1;
- string_init (&arg);
- if (work->temp_start == -1) /* non-recursive call */
- work->temp_start = declp->p - declp->b;
- string_append (declp, "<");
- while (1)
- {
- string_clear (&arg);
- switch (**mangled)
- {
- case 'T':
- …
Large files files are truncated, but you can click here to view the full file