X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libiberty%2Fcplus-dem.c;h=e94848767e780847ca9e4bd6f879906c72d99fcf;hb=531354d1951452f3860b2f991bf709201f1f4ff6;hp=7fea97a81b38fbea1c11fde8111ea9e581679315;hpb=ac126d8255f548619688460bf50f2aa323d065d3;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index 7fea97a81b3..e94848767e7 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -1,5 +1,6 @@ /* Demangler for GNU C++ - Copyright 1989, 91, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. + Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2010 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 @@ -10,6 +11,15 @@ modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. +In addition to the permissions in the GNU Library General Public +License, the Free Software Foundation gives you unlimited permission +to link the compiled version of this file into combinations with other +programs, and to distribute those combinations without any restriction +coming from the use of this file. (The Library Public License +restrictions do apply in other respects; for example, they cover +modification of the file, and distribution when not linked into a +combined executable.) + Libiberty 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 @@ -17,8 +27,8 @@ Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with libiberty; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +Boston, MA 02110-1301, USA. */ /* This file exports two functions; cplus_mangle_opname and cplus_demangle. @@ -33,7 +43,8 @@ Boston, MA 02111-1307, USA. */ #include "config.h" #endif -#include +#include "safe-ctype.h" + #include #include #include @@ -41,8 +52,8 @@ Boston, MA 02111-1307, USA. */ #ifdef HAVE_STDLIB_H #include #else -char * malloc (); -char * realloc (); +void * malloc (); +void * realloc (); #endif #include @@ -53,24 +64,11 @@ char * realloc (); #define min(X,Y) (((X) < (Y)) ? (X) : (Y)) -static const char *mystrstr PARAMS ((const char *, const char *)); +/* 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 -static const char * -mystrstr (s1, s2) - const char *s1, *s2; -{ - register const char *p = s1; - register int len = strlen (s2); - - for (; (p = strchr (p, *s2)) != 0; p++) - { - if (strncmp (p, s2, len) == 0) - { - return (p); - } - } - return (0); -} +extern void fancy_abort (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 @@ -92,15 +90,14 @@ mystrstr (s1, s2) #define CPLUS_MARKER '$' #endif -enum demangling_styles current_demangling_style = gnu_demangling; +enum demangling_styles current_demangling_style = auto_demangling; static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; static char char_str[2] = { '\000', '\000' }; void -set_cplus_marker_for_demangling (ch) - int ch; +set_cplus_marker_for_demangling (int ch) { cplus_markers[0] = ch; } @@ -147,9 +144,9 @@ struct work_stuff static const struct optable { - const char *in; - const char *out; - int flags; + 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) */ @@ -246,9 +243,74 @@ typedef enum type_kind_t tk_real } type_kind_t; +const struct demangler_engine libiberty_demanglers[] = +{ + { + NO_DEMANGLING_STYLE_STRING, + no_demangling, + "Demangling disabled" + } + , + { + AUTO_DEMANGLING_STYLE_STRING, + auto_demangling, + "Automatic selection based on executable" + } + , + { + GNU_DEMANGLING_STYLE_STRING, + gnu_demangling, + "GNU (g++) style demangling" + } + , + { + LUCID_DEMANGLING_STYLE_STRING, + lucid_demangling, + "Lucid (lcc) style demangling" + } + , + { + ARM_DEMANGLING_STYLE_STRING, + arm_demangling, + "ARM style demangling" + } + , + { + HP_DEMANGLING_STYLE_STRING, + hp_demangling, + "HP (aCC) style demangling" + } + , + { + EDG_DEMANGLING_STYLE_STRING, + edg_demangling, + "EDG style demangling" + } + , + { + GNU_V3_DEMANGLING_STYLE_STRING, + gnu_v3_demangling, + "GNU (g++) V3 ABI-style demangling" + } + , + { + JAVA_DEMANGLING_STYLE_STRING, + java_demangling, + "Java style demangling" + } + , + { + GNAT_DEMANGLING_STYLE_STRING, + gnat_demangling, + "GNAT style demangling" + } + , + { + NULL, unknown_demangling, NULL + } +}; + #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)) @@ -262,147 +324,127 @@ typedef enum type_kind_t /* Prototypes for local functions */ -static char * -mop_up PARAMS ((struct work_stuff *, string *, int)); +static void delete_work_stuff (struct work_stuff *); -static void -squangle_mop_up PARAMS ((struct work_stuff *)); +static void delete_non_B_K_work_stuff (struct work_stuff *); + +static char *mop_up (struct work_stuff *, string *, int); + +static void squangle_mop_up (struct work_stuff *); + +static void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *); #if 0 static int -demangle_method_args PARAMS ((struct work_stuff *, const char **, string *)); +demangle_method_args (struct work_stuff *, const char **, string *); #endif static char * -internal_cplus_demangle PARAMS ((struct work_stuff *, const char *)); +internal_cplus_demangle (struct work_stuff *, const char *); static int -demangle_template_template_parm PARAMS ((struct work_stuff *work, - const char **, string *)); +demangle_template_template_parm (struct work_stuff *work, + const char **, string *); static int -demangle_template PARAMS ((struct work_stuff *work, const char **, string *, - string *, int, int)); +demangle_template (struct work_stuff *work, const char **, string *, + string *, int, int); static int -arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **, - const char **)); +arm_pt (struct work_stuff *, const char *, int, const char **, + const char **); static int -demangle_class_name PARAMS ((struct work_stuff *, const char **, string *)); +demangle_class_name (struct work_stuff *, const char **, string *); static int -demangle_qualified PARAMS ((struct work_stuff *, const char **, string *, - int, int)); +demangle_qualified (struct work_stuff *, const char **, string *, + int, int); -static int -demangle_class PARAMS ((struct work_stuff *, const char **, string *)); +static int demangle_class (struct work_stuff *, const char **, string *); -static int -demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *)); +static int demangle_fund_type (struct work_stuff *, const char **, string *); -static int -demangle_signature PARAMS ((struct work_stuff *, const char **, string *)); +static int demangle_signature (struct work_stuff *, const char **, string *); -static int -demangle_prefix PARAMS ((struct work_stuff *, const char **, string *)); +static int demangle_prefix (struct work_stuff *, const char **, string *); -static int -gnu_special PARAMS ((struct work_stuff *, const char **, string *)); +static int gnu_special (struct work_stuff *, const char **, string *); -static int -arm_special PARAMS ((const char **, string *)); +static int arm_special (const char **, string *); -static void -string_need PARAMS ((string *, int)); +static void string_need (string *, int); -static void -string_delete PARAMS ((string *)); +static void string_delete (string *); static void -string_init PARAMS ((string *)); +string_init (string *); -static void -string_clear PARAMS ((string *)); +static void string_clear (string *); #if 0 -static int -string_empty PARAMS ((string *)); +static int string_empty (string *); #endif -static void -string_append PARAMS ((string *, const char *)); +static void string_append (string *, const char *); -static void -string_appends PARAMS ((string *, string *)); +static void string_appends (string *, string *); -static void -string_appendn PARAMS ((string *, const char *, int)); +static void string_appendn (string *, const char *, int); -static void -string_prepend PARAMS ((string *, const char *)); +static void string_prepend (string *, const char *); -static void -string_prependn PARAMS ((string *, const char *, int)); +static void string_prependn (string *, const char *, int); -static int -get_count PARAMS ((const char **, int *)); +static void string_append_template_idx (string *, int); -static int -consume_count PARAMS ((const char **)); +static int get_count (const char **, int *); -static int -consume_count_with_underscores PARAMS ((const char**)); +static int consume_count (const char **); -static int -demangle_args PARAMS ((struct work_stuff *, const char **, string *)); +static int consume_count_with_underscores (const char**); -static int -demangle_nested_args PARAMS ((struct work_stuff*, const char**, string*)); +static int demangle_args (struct work_stuff *, const char **, string *); + +static int demangle_nested_args (struct work_stuff*, const char**, string*); + +static int do_type (struct work_stuff *, const char **, string *); + +static int do_arg (struct work_stuff *, const char **, string *); static int -do_type PARAMS ((struct work_stuff *, const char **, string *)); +demangle_function_name (struct work_stuff *, const char **, string *, + const char *); static int -do_arg PARAMS ((struct work_stuff *, const char **, string *)); +iterate_demangle_function (struct work_stuff *, + const char **, string *, const char *); -static void -demangle_function_name PARAMS ((struct work_stuff *, const char **, string *, - const char *)); +static void remember_type (struct work_stuff *, const char *, int); -static void -remember_type PARAMS ((struct work_stuff *, const char *, int)); +static void remember_Btype (struct work_stuff *, const char *, int, int); -static void -remember_Btype PARAMS ((struct work_stuff *, const char *, int, int)); +static int register_Btype (struct work_stuff *); -static int -register_Btype PARAMS ((struct work_stuff *)); +static void remember_Ktype (struct work_stuff *, const char *, int); -static void -remember_Ktype PARAMS ((struct work_stuff *, const char *, int)); +static void forget_types (struct work_stuff *); -static void -forget_types PARAMS ((struct work_stuff *)); +static void forget_B_and_K_types (struct work_stuff *); -static void -forget_B_and_K_types PARAMS ((struct work_stuff *)); - -static void -string_prepends PARAMS ((string *, string *)); +static void string_prepends (string *, string *); static int -demangle_template_value_parm PARAMS ((struct work_stuff*, const char**, - string*, type_kind_t)); +demangle_template_value_parm (struct work_stuff*, const char**, + string*, type_kind_t); static int -do_hpacc_template_const_value PARAMS ((struct work_stuff *, const char **, string *)); +do_hpacc_template_const_value (struct work_stuff *, const char **, string *); static int -do_hpacc_template_literal PARAMS ((struct work_stuff *, const char **, string *)); +do_hpacc_template_literal (struct work_stuff *, const char **, string *); -static int -snarf_numeric_literal PARAMS ((const char **, string *)); +static int snarf_numeric_literal (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 @@ -413,14 +455,26 @@ snarf_numeric_literal PARAMS ((const char **, string *)); #define TYPE_QUAL_VOLATILE 0x2 #define TYPE_QUAL_RESTRICT 0x4 +static int code_for_qualifier (int); + +static const char* qualifier_string (int); + +static const char* demangle_qualifier (int); + +static int demangle_expression (struct work_stuff *, const char **, string *, + type_kind_t); + static int -code_for_qualifier PARAMS ((int)); +demangle_integral_value (struct work_stuff *, const char **, string *); -static const char* -qualifier_string PARAMS ((int)); +static int +demangle_real_value (struct work_stuff *, const char **, string *); -static const char* -demangle_qualifier PARAMS ((int)); +static void +demangle_arm_hp_template (struct work_stuff *, const char **, int, string *); + +static void +recursively_demangle (struct work_stuff *, const char **, string *, int); /* Translate count to integer, consuming tokens in the process. Conversion terminates on the first non-digit character. @@ -431,15 +485,14 @@ demangle_qualifier PARAMS ((int)); Overflow consumes the rest of the digits, and returns -1. */ static int -consume_count (type) - const char **type; +consume_count (const char **type) { int count = 0; - if (! isdigit ((unsigned char)**type)) + if (! ISDIGIT ((unsigned char)**type)) return -1; - while (isdigit ((unsigned char)**type)) + while (ISDIGIT ((unsigned char)**type)) { count *= 10; @@ -450,7 +503,7 @@ consume_count (type) ten. */ if ((count % 10) != 0) { - while (isdigit ((unsigned char) **type)) + while (ISDIGIT ((unsigned char) **type)) (*type)++; return -1; } @@ -459,6 +512,9 @@ consume_count (type) (*type)++; } + if (count < 0) + count = -1; + return (count); } @@ -468,15 +524,14 @@ consume_count (type) failure, since 0 can be a valid value. */ static int -consume_count_with_underscores (mangled) - const char **mangled; +consume_count_with_underscores (const char **mangled) { int idx; if (**mangled == '_') { (*mangled)++; - if (!isdigit ((unsigned char)**mangled)) + if (!ISDIGIT ((unsigned char)**mangled)) return -1; idx = consume_count (mangled); @@ -502,8 +557,7 @@ consume_count_with_underscores (mangled) corresponding to this qualifier. */ static int -code_for_qualifier (c) - int c; +code_for_qualifier (int c) { switch (c) { @@ -528,8 +582,7 @@ code_for_qualifier (c) TYPE_QUALS. */ static const char* -qualifier_string (type_quals) - int type_quals; +qualifier_string (int type_quals) { switch (type_quals) { @@ -570,17 +623,13 @@ qualifier_string (type_quals) called with a valid qualifier code. */ static const char* -demangle_qualifier (c) - int c; +demangle_qualifier (int c) { return qualifier_string (code_for_qualifier (c)); } int -cplus_demangle_opname (opname, result, options) - const char *opname; - char *result; - int options; +cplus_demangle_opname (const char *opname, char *result, int options) { int len, len1, ret; string type; @@ -608,14 +657,14 @@ cplus_demangle_opname (opname, result, options) } } else if (opname[0] == '_' && opname[1] == '_' - && opname[2] >= 'a' && opname[2] <= 'z' - && opname[3] >= 'a' && opname[3] <= 'z') + && ISLOWER((unsigned char)opname[2]) + && ISLOWER((unsigned char)opname[3])) { if (opname[4] == '\0') { /* Operator. */ size_t i; - for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + for (i = 0; i < ARRAY_SIZE (optable); i++) { if (strlen (optable[i].in) == 2 && memcmp (optable[i].in, opname + 2, 2) == 0) @@ -633,7 +682,7 @@ cplus_demangle_opname (opname, result, options) { /* Assignment. */ size_t i; - for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + for (i = 0; i < ARRAY_SIZE (optable); i++) { if (strlen (optable[i].in) == 3 && memcmp (optable[i].in, opname + 2, 3) == 0) @@ -657,7 +706,7 @@ cplus_demangle_opname (opname, result, options) && memcmp (opname + 3, "assign_", 7) == 0) { size_t i; - for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + for (i = 0; i < ARRAY_SIZE (optable); i++) { len1 = len - 10; if ((int) strlen (optable[i].in) == len1 @@ -674,7 +723,7 @@ cplus_demangle_opname (opname, result, options) else { size_t i; - for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + for (i = 0; i < ARRAY_SIZE (optable); i++) { len1 = len - 3; if ((int) strlen (optable[i].in) == len1 @@ -705,6 +754,7 @@ cplus_demangle_opname (opname, result, options) return ret; } + /* Takes operator name as e.g. "++" and returns mangled operator name (e.g. "postincrement_expr"), or NULL if not found. @@ -712,15 +762,13 @@ cplus_demangle_opname (opname, result, options) if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ const char * -cplus_mangle_opname (opname, options) - const char *opname; - int options; +cplus_mangle_opname (const char *opname, int options) { size_t i; int len; len = strlen (opname); - for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + for (i = 0; i < ARRAY_SIZE (optable); i++) { if ((int) strlen (optable[i].out) == len && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI) @@ -730,10 +778,42 @@ cplus_mangle_opname (opname, options) return (0); } +/* Add a routine to set the demangling style to be sure it is valid and + allow for any demangler initialization that maybe necessary. */ + +enum demangling_styles +cplus_demangle_set_style (enum demangling_styles style) +{ + const struct demangler_engine *demangler = libiberty_demanglers; + + for (; demangler->demangling_style != unknown_demangling; ++demangler) + if (style == demangler->demangling_style) + { + current_demangling_style = style; + return current_demangling_style; + } + + return unknown_demangling; +} + +/* Do string name to style translation */ + +enum demangling_styles +cplus_demangle_name_to_style (const char *name) +{ + const struct demangler_engine *demangler = libiberty_demanglers; + + for (; demangler->demangling_style != unknown_demangling; ++demangler) + if (strcmp (name, demangler->demangling_style_name) == 0) + return demangler->demangling_style; + + return unknown_demangling; +} + /* char *cplus_demangle (const char *mangled, int options) If MANGLED is a mangled function name produced by GNU C++, then - a pointer to a malloced string giving a C++ representation + 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. @@ -759,39 +839,320 @@ cplus_mangle_opname (opname, options) MANGLED. */ char * -cplus_demangle (mangled, options) - const char *mangled; - int options; +cplus_demangle (const char *mangled, int options) { char *ret; struct work_stuff work[1]; + + if (current_demangling_style == no_demangling) + return xstrdup (mangled); + memset ((char *) work, 0, sizeof (work)); - work -> options = options; - if ((work -> options & DMGL_STYLE_MASK) == 0) - work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK; + work->options = options; + if ((work->options & DMGL_STYLE_MASK) == 0) + work->options |= (int) current_demangling_style & DMGL_STYLE_MASK; + + /* The V3 ABI demangling is implemented elsewhere. */ + if (GNU_V3_DEMANGLING || AUTO_DEMANGLING) + { + ret = cplus_demangle_v3 (mangled, work->options); + if (ret || GNU_V3_DEMANGLING) + return ret; + } + + if (JAVA_DEMANGLING) + { + ret = java_demangle_v3 (mangled); + if (ret) + return ret; + } + + if (GNAT_DEMANGLING) + return ada_demangle (mangled, options); ret = internal_cplus_demangle (work, mangled); squangle_mop_up (work); return (ret); } +/* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */ + +char * +ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) +{ + int len0; + const char* p; + char *d; + char *demangled; + + /* Discard leading _ada_, which is used for library level subprograms. */ + if (strncmp (mangled, "_ada_", 5) == 0) + mangled += 5; + + /* All ada unit names are lower-case. */ + if (!ISLOWER (mangled[0])) + goto unknown; + + /* Most of the demangling will trivially remove chars. Operator names + may add one char but because they are always preceeded by '__' which is + replaced by '.', they eventually never expand the size. + A few special names such as '___elabs' add a few chars (at most 7), but + they occur only once. */ + len0 = strlen (mangled) + 7 + 1; + demangled = XNEWVEC (char, len0); + + d = demangled; + p = mangled; + while (1) + { + /* An entity names is expected. */ + if (ISLOWER (*p)) + { + /* An identifier, which is always lower case. */ + do + *d++ = *p++; + while (ISLOWER(*p) || ISDIGIT (*p) + || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1])))); + } + else if (p[0] == 'O') + { + /* An operator name. */ + static const char * const operators[][2] = + {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"}, + {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"}, + {"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="}, + {"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"}, + {"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"}, + {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"}, + {"Oexpon", "**"}, {NULL, NULL}}; + int k; + + for (k = 0; operators[k][0] != NULL; k++) + { + size_t slen = strlen (operators[k][0]); + if (strncmp (p, operators[k][0], slen) == 0) + { + p += slen; + slen = strlen (operators[k][1]); + *d++ = '"'; + memcpy (d, operators[k][1], slen); + d += slen; + *d++ = '"'; + break; + } + } + /* Operator not found. */ + if (operators[k][0] == NULL) + goto unknown; + } + else + { + /* Not a GNAT encoding. */ + goto unknown; + } + + /* The name can be directly followed by some uppercase letters. */ + if (p[0] == 'T' && p[1] == 'K') + { + /* Task stuff. */ + if (p[2] == 'B' && p[3] == 0) + { + /* Subprogram for task body. */ + break; + } + else if (p[2] == '_' && p[3] == '_') + { + /* Inner declarations in a task. */ + p += 4; + *d++ = '.'; + continue; + } + else + goto unknown; + } + if (p[0] == 'E' && p[1] == 0) + { + /* Exception name. */ + goto unknown; + } + if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0) + { + /* Protected type subprogram. */ + break; + } + if ((*p == 'N' || *p == 'S') && p[1] == 0) + { + /* Enumerated type name table. */ + goto unknown; + } + if (p[0] == 'X') + { + /* Body nested. */ + p++; + while (p[0] == 'n' || p[0] == 'b') + p++; + } + if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0)) + { + /* Stream operations. */ + const char *name; + switch (p[1]) + { + case 'R': + name = "'Read"; + break; + case 'W': + name = "'Write"; + break; + case 'I': + name = "'Input"; + break; + case 'O': + name = "'Output"; + break; + default: + goto unknown; + } + p += 2; + strcpy (d, name); + d += strlen (name); + } + else if (p[0] == 'D') + { + /* Controlled type operation. */ + const char *name; + switch (p[1]) + { + case 'F': + name = ".Finalize"; + break; + case 'A': + name = ".Adjust"; + break; + default: + goto unknown; + } + strcpy (d, name); + d += strlen (name); + break; + } + + if (p[0] == '_') + { + /* Separator. */ + if (p[1] == '_') + { + /* Standard separator. Handled first. */ + p += 2; + + if (ISDIGIT (*p)) + { + /* Overloading number. */ + do + p++; + while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1]))); + if (*p == 'X') + { + p++; + while (p[0] == 'n' || p[0] == 'b') + p++; + } + } + else if (p[0] == '_' && p[1] != '_') + { + /* Special names. */ + static const char * const special[][2] = { + { "_elabb", "'Elab_Body" }, + { "_elabs", "'Elab_Spec" }, + { "_size", "'Size" }, + { "_alignment", "'Alignment" }, + { "_assign", ".\":=\"" }, + { NULL, NULL } + }; + int k; + + for (k = 0; special[k][0] != NULL; k++) + { + size_t slen = strlen (special[k][0]); + if (strncmp (p, special[k][0], slen) == 0) + { + p += slen; + slen = strlen (special[k][1]); + memcpy (d, special[k][1], slen); + d += slen; + break; + } + } + if (special[k][0] != NULL) + break; + else + goto unknown; + } + else + { + *d++ = '.'; + continue; + } + } + else if (p[1] == 'B' || p[1] == 'E') + { + /* Entry Body or barrier Evaluation. */ + p += 2; + while (ISDIGIT (*p)) + p++; + if (p[0] == 's' && p[1] == 0) + break; + else + goto unknown; + } + else + goto unknown; + } + + if (p[0] == '.' && ISDIGIT (p[1])) + { + /* Nested subprogram. */ + p += 2; + while (ISDIGIT (*p)) + p++; + } + if (*p == 0) + { + /* End of mangled name. */ + break; + } + else + goto unknown; + } + *d = 0; + return demangled; + + unknown: + len0 = strlen (mangled); + demangled = XNEWVEC (char, len0 + 3); + + if (mangled[0] == '<') + strcpy (demangled, mangled); + else + sprintf (demangled, "<%s>", mangled); + + return demangled; +} /* 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 intializes and cleans up the squangle code info, while internal + 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, mangled) - struct work_stuff *work; - const char *mangled; +internal_cplus_demangle (struct work_stuff *work, const char *mangled) { string decl; int success = 0; char *demangled = NULL; - int s1,s2,s3,s4; + int s1, s2, s3, s4; s1 = work->constructor; s2 = work->destructor; s3 = work->static_type; @@ -844,14 +1205,13 @@ internal_cplus_demangle (work, mangled) work->destructor = s2; work->static_type = s3; work->type_quals = s4; - return (demangled); + return demangled; } /* Clear out and squangling related storage */ static void -squangle_mop_up (work) - struct work_stuff *work; +squangle_mop_up (struct work_stuff *work) { /* clean up the B and K type mangling types. */ forget_B_and_K_types (work); @@ -865,16 +1225,78 @@ squangle_mop_up (work) } } -/* Clear out any mangled storage */ -static char * -mop_up (work, declp, success) - struct work_stuff *work; - string *declp; - int success; +/* Copy the work state and storage. */ + +static void +work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from) { - char *demangled = NULL; + int i; + + delete_work_stuff (to); + + /* Shallow-copy scalars. */ + memcpy (to, from, sizeof (*to)); + + /* Deep-copy dynamic storage. */ + if (from->typevec_size) + to->typevec = XNEWVEC (char *, from->typevec_size); + + for (i = 0; i < from->ntypes; i++) + { + int len = strlen (from->typevec[i]) + 1; + + to->typevec[i] = XNEWVEC (char, len); + memcpy (to->typevec[i], from->typevec[i], len); + } + + if (from->ksize) + to->ktypevec = XNEWVEC (char *, from->ksize); + + for (i = 0; i < from->numk; i++) + { + int len = strlen (from->ktypevec[i]) + 1; + + to->ktypevec[i] = XNEWVEC (char, len); + memcpy (to->ktypevec[i], from->ktypevec[i], len); + } + + if (from->bsize) + to->btypevec = XNEWVEC (char *, from->bsize); + + for (i = 0; i < from->numb; i++) + { + int len = strlen (from->btypevec[i]) + 1; + + to->btypevec[i] = XNEWVEC (char , len); + memcpy (to->btypevec[i], from->btypevec[i], len); + } + + if (from->ntmpl_args) + to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args); + + for (i = 0; i < from->ntmpl_args; i++) + { + int len = strlen (from->tmpl_argvec[i]) + 1; + + to->tmpl_argvec[i] = XNEWVEC (char, len); + memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len); + } + + if (from->previous_argument) + { + to->previous_argument = XNEW (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 (struct work_stuff *work) +{ /* Discard the remembered types, if any. */ forget_types (work); @@ -889,8 +1311,7 @@ mop_up (work, declp, success) 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[i]); free ((char*) work->tmpl_argvec); work->tmpl_argvec = NULL; @@ -901,6 +1322,26 @@ mop_up (work, declp, success) free ((char*) work->previous_argument); work->previous_argument = NULL; } +} + + +/* Delete all dynamic storage in work_stuff. */ +static void +delete_work_stuff (struct work_stuff *work) +{ + delete_non_B_K_work_stuff (work); + squangle_mop_up (work); +} + + +/* Clear out any mangled storage */ + +static char * +mop_up (struct 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. */ @@ -912,7 +1353,7 @@ mop_up (work, declp, success) else { string_appendn (declp, "", 1); - demangled = declp -> b; + demangled = declp->b; } return (demangled); } @@ -948,10 +1389,8 @@ DESCRIPTION argument list. */ static int -demangle_signature (work, mangled, declp) - struct work_stuff *work; - const char **mangled; - string *declp; +demangle_signature (struct work_stuff *work, + const char **mangled, string *declp) { int success = 1; int func_done = 0; @@ -1051,6 +1490,7 @@ demangle_signature (work, mangled, declp) { string_append (&s, SCOPE_STRING (work)); string_prepends (declp, &s); + string_delete (&s); } oldmangled = NULL; expect_func = 1; @@ -1126,11 +1566,10 @@ demangle_signature (work, mangled, declp) break; case '_': - if (GNU_DEMANGLING && expect_return_type) + 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); @@ -1152,7 +1591,7 @@ demangle_signature (work, mangled, declp) if (HP_DEMANGLING) { (*mangled)++; - while (**mangled && isdigit ((unsigned char)**mangled)) + while (**mangled && ISDIGIT ((unsigned char)**mangled)) (*mangled)++; } else @@ -1160,7 +1599,7 @@ demangle_signature (work, mangled, declp) break; case 'H': - if (GNU_DEMANGLING) + if (AUTO_DEMANGLING || GNU_DEMANGLING) { /* A G++ template function. Read the template arguments. */ success = demangle_template (work, mangled, declp, 0, 0, @@ -1241,10 +1680,8 @@ demangle_signature (work, mangled, declp) #if 0 static int -demangle_method_args (work, mangled, declp) - struct work_stuff *work; - const char **mangled; - string *declp; +demangle_method_args (struct work_stuff *work, const char **mangled, + string *declp) { int success = 0; @@ -1264,10 +1701,8 @@ demangle_method_args (work, mangled, declp) #endif static int -demangle_template_template_parm (work, mangled, tname) - struct work_stuff *work; - const char **mangled; - string *tname; +demangle_template_template_parm (struct work_stuff *work, + const char **mangled, string *tname) { int i; int r; @@ -1328,95 +1763,202 @@ demangle_template_template_parm (work, mangled, tname) } static int -demangle_integral_value (work, mangled, s) - struct work_stuff *work; - const char** mangled; - string* s; +demangle_expression (struct work_stuff *work, const char **mangled, + string *s, type_kind_t tk) { + int need_operator = 0; int success; - if (**mangled == 'E') + success = 1; + string_appendn (s, "(", 1); + (*mangled)++; + while (success && **mangled != 'W' && **mangled != '\0') { - int need_operator = 0; - - success = 1; - string_appendn (s, "(", 1); - (*mangled)++; - while (success && **mangled != 'W' && **mangled != '\0') + if (need_operator) { - if (need_operator) - { - size_t i; - size_t len; + size_t i; + size_t len; - success = 0; + success = 0; - len = strlen (*mangled); + len = strlen (*mangled); - for (i = 0; - i < sizeof (optable) / sizeof (optable [0]); - ++i) - { - size_t l = strlen (optable[i].in); + for (i = 0; i < 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 (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; + 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 (struct 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 multidigit_without_leading_underscore = 0; + int leave_following_underscore = 0; + + success = 0; + + if (**mangled == '_') + { + if (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. */ + multidigit_without_leading_underscore = 1; + string_appendn (s, "-", 1); + (*mangled) += 2; } else - need_operator = 1; + { + /* Do not consume a following underscore; + consume_count_with_underscores will consume what + should be consumed. */ + leave_following_underscore = 1; + } + } + else + { + /* Negative numbers are indicated with a leading `m'. */ + if (**mangled == 'm') + { + string_appendn (s, "-", 1); + (*mangled)++; + } + /* Since consume_count_with_underscores does not handle + multi-digit numbers that do not start with an underscore, + and this number can be an integer template parameter, + we have to call consume_count. */ + multidigit_without_leading_underscore = 1; + /* These multi-digit numbers never end on an underscore, + so if there is one then don't eat it. */ + 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 (multidigit_without_leading_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 || multidigit_without_leading_underscore) + && ! leave_following_underscore + && **mangled == '_') + (*mangled)++; + + /* All is well. */ + success = 1; + } + } + + return success; +} + +/* Demangle the real value in MANGLED. */ - success = demangle_template_value_parm (work, mangled, s, - tk_integral); - } +static int +demangle_real_value (struct work_stuff *work, + const char **mangled, string *s) +{ + if (**mangled == 'E') + return demangle_expression (work, mangled, s, tk_real); - if (**mangled != 'W') - success = 0; - else - { - string_appendn (s, ")", 1); - (*mangled)++; - } + if (**mangled == 'm') + { + string_appendn (s, "-", 1); + (*mangled)++; } - else if (**mangled == 'Q' || **mangled == 'K') - success = demangle_qualified (work, mangled, s, 0, 1); - else + while (ISDIGIT ((unsigned char)**mangled)) { - success = 0; - - if (**mangled == 'm') + string_appendn (s, *mangled, 1); + (*mangled)++; + } + if (**mangled == '.') /* fraction */ + { + string_appendn (s, ".", 1); + (*mangled)++; + while (ISDIGIT ((unsigned char)**mangled)) { - string_appendn (s, "-", 1); + string_appendn (s, *mangled, 1); (*mangled)++; } - while (isdigit ((unsigned char)**mangled)) + } + if (**mangled == 'e') /* exponent */ + { + string_appendn (s, "e", 1); + (*mangled)++; + while (ISDIGIT ((unsigned char)**mangled)) { string_appendn (s, *mangled, 1); (*mangled)++; - success = 1; } } - return success; + return 1; } static int -demangle_template_value_parm (work, mangled, s, tk) - struct work_stuff *work; - const char **mangled; - string* s; - type_kind_t tk; +demangle_template_value_parm (struct work_stuff *work, const char **mangled, + string *s, type_kind_t tk) { int success = 1; @@ -1434,11 +1976,7 @@ demangle_template_value_parm (work, mangled, s, tk) if (work->tmpl_argvec) string_append (s, work->tmpl_argvec[idx]); else - { - char buf[10]; - sprintf(buf, "T%d", idx); - string_append (s, buf); - } + string_append_template_idx (s, idx); } else if (tk == tk_integral) success = demangle_integral_value (work, mangled, s); @@ -1474,38 +2012,7 @@ demangle_template_value_parm (work, mangled, s, tk) success = 0; } else if (tk == 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)++; - } - } - } + success = demangle_real_value (work, mangled, s); else if (tk == tk_pointer || tk == tk_reference) { if (**mangled == 'Q') @@ -1521,7 +2028,7 @@ demangle_template_value_parm (work, mangled, s, tk) string_appendn (s, "0", 1); else { - char *p = xmalloc (symbol_len + 1), *q; + char *p = XNEWVEC (char, symbol_len + 1), *q; strncpy (p, *mangled, symbol_len); p [symbol_len] = '\0'; /* We use cplus_demangle here, rather than @@ -1555,33 +2062,24 @@ demangle_template_value_parm (work, mangled, s, tk) 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 tmeplate is remembered in the list of back-referenceable + the template is remembered in the list of back-referenceable types. */ static int -demangle_template (work, mangled, tname, trawname, is_type, remember) - struct work_stuff *work; - const char **mangled; - string *tname; - string *trawname; - int is_type; - int remember; +demangle_template (struct 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') { @@ -1603,11 +2101,9 @@ demangle_template (work, mangled, tname, trawname, is_type, remember) } else { - char buf[10]; - sprintf(buf, "T%d", idx); - string_append (tname, buf); + string_append_template_idx (tname, idx); if (trawname) - string_append (trawname, buf); + string_append_template_idx (trawname, idx); } } else @@ -1638,7 +2134,7 @@ demangle_template (work, mangled, tname, trawname, is_type, remember) if (!is_type) { /* Create an array for saving the template argument values. */ - work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *)); + work->tmpl_argvec = XNEWVEC (char *, r); work->ntmpl_args = r; for (i = 0; i < r; i++) work->tmpl_argvec[i] = 0; @@ -1663,7 +2159,7 @@ demangle_template (work, mangled, tname, trawname, is_type, remember) { /* Save the template argument. */ int len = temp.p - temp.b; - work->tmpl_argvec[i] = xmalloc (len + 1); + work->tmpl_argvec[i] = XNEWVEC (char, len + 1); memcpy (work->tmpl_argvec[i], temp.b, len); work->tmpl_argvec[i][len] = '\0'; } @@ -1691,7 +2187,7 @@ demangle_template (work, mangled, tname, trawname, is_type, remember) { /* Save the template argument. */ int len = r2; - work->tmpl_argvec[i] = xmalloc (len + 1); + work->tmpl_argvec[i] = XNEWVEC (char, len + 1); memcpy (work->tmpl_argvec[i], *mangled, len); work->tmpl_argvec[i][len] = '\0'; } @@ -1737,7 +2233,7 @@ demangle_template (work, mangled, tname, trawname, is_type, remember) if (!is_type) { int len = s->p - s->b; - work->tmpl_argvec[i] = xmalloc (len + 1); + work->tmpl_argvec[i] = XNEWVEC (char, len + 1); memcpy (work->tmpl_argvec[i], s->b, len); work->tmpl_argvec[i][len] = '\0'; @@ -1759,7 +2255,10 @@ demangle_template (work, mangled, tname, trawname, is_type, remember) } if (is_type && remember) - remember_Btype (work, tname->b, LEN_STRING (tname), bindex); + { + const int bindex = register_Btype (work); + remember_Btype (work, tname->b, LEN_STRING (tname), bindex); + } /* if (work -> static_type) @@ -1778,15 +2277,12 @@ demangle_template (work, mangled, tname, trawname, is_type, remember) } static int -arm_pt (work, mangled, n, anchor, args) - struct work_stuff *work; - const char *mangled; - int n; - const char **anchor, **args; +arm_pt (struct 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 = mystrstr (mangled, "__pt__"))) + if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__"))) { int len; *args = *anchor + 6; @@ -1801,9 +2297,9 @@ arm_pt (work, mangled, n, anchor, args) } if (AUTO_DEMANGLING || EDG_DEMANGLING) { - if ((*anchor = mystrstr (mangled, "__tm__")) - || (*anchor = mystrstr (mangled, "__ps__")) - || (*anchor = mystrstr (mangled, "__pt__"))) + if ((*anchor = strstr (mangled, "__tm__")) + || (*anchor = strstr (mangled, "__ps__")) + || (*anchor = strstr (mangled, "__pt__"))) { int len; *args = *anchor + 6; @@ -1816,7 +2312,7 @@ arm_pt (work, mangled, n, anchor, args) return 1; } } - else if ((*anchor = mystrstr (mangled, "__S"))) + else if ((*anchor = strstr (mangled, "__S"))) { int len; *args = *anchor + 3; @@ -1835,11 +2331,8 @@ arm_pt (work, mangled, n, anchor, args) } static void -demangle_arm_hp_template (work, mangled, n, declp) - struct work_stuff *work; - const char **mangled; - int n; - string *declp; +demangle_arm_hp_template (struct work_stuff *work, const char **mangled, + int n, string *declp) { const char *p; const char *args; @@ -1851,6 +2344,7 @@ demangle_arm_hp_template (work, mangled, n, declp) if (HP_DEMANGLING && ((*mangled)[n] == 'X')) { char *start_spec_args = NULL; + int hold_options; /* First check for and omit template specialization pseudo-arguments, such as in "Spec<#1,#1.*>" */ @@ -1863,10 +2357,16 @@ demangle_arm_hp_template (work, mangled, n, declp) string_init (&arg); if (work->temp_start == -1) /* non-recursive call */ work->temp_start = declp->p - declp->b; + + /* We want to unconditionally demangle parameter types in + template parameters. */ + hold_options = work->options; + work->options |= DMGL_PARAMS; + string_append (declp, "<"); while (1) { - string_clear (&arg); + string_delete (&arg); switch (**mangled) { case 'T': @@ -1909,21 +2409,29 @@ demangle_arm_hp_template (work, mangled, n, declp) string_delete (&arg); if (**mangled == '_') (*mangled)++; + work->options = hold_options; return; } /* ARM template? (Also handles HP cfront extensions) */ else if (arm_pt (work, *mangled, n, &p, &args)) { + int hold_options; string type_str; string_init (&arg); string_appendn (declp, *mangled, p - *mangled); if (work->temp_start == -1) /* non-recursive call */ work->temp_start = declp->p - declp->b; + + /* We want to unconditionally demangle parameter types in + template parameters. */ + hold_options = work->options; + work->options |= DMGL_PARAMS; + string_append (declp, "<"); /* should do error checking here */ while (args < e) { - string_clear (&arg); + string_delete (&arg); /* Check for type or literal here */ switch (*args) @@ -1938,6 +2446,7 @@ demangle_arm_hp_template (work, mangled, n, declp) goto cfront_template_args_done; string_append (&arg, "("); string_appends (&arg, &type_str); + string_delete (&type_str); string_append (&arg, ")"); if (*args != 'L') goto cfront_template_args_done; @@ -1955,8 +2464,18 @@ demangle_arm_hp_template (work, mangled, n, declp) break; default: /* Not handling other HP cfront stuff */ - if (!do_type (work, &args, &arg)) - goto cfront_template_args_done; + { + const char* old_args = args; + if (!do_type (work, &args, &arg)) + goto cfront_template_args_done; + + /* Fail if we didn't make any progress: prevent infinite loop. */ + if (args == old_args) + { + work->options = hold_options; + return; + } + } } string_appends (declp, &arg); string_append (declp, ","); @@ -1966,6 +2485,7 @@ demangle_arm_hp_template (work, mangled, n, declp) if (args >= e) --declp->p; /* remove extra comma */ string_append (declp, ">"); + work->options = hold_options; } else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 && (*mangled)[9] == 'N' @@ -1989,10 +2509,8 @@ demangle_arm_hp_template (work, mangled, n, declp) already been dealt with */ static int -demangle_class_name (work, mangled, declp) - struct work_stuff *work; - const char **mangled; - string *declp; +demangle_class_name (struct work_stuff *work, const char **mangled, + string *declp) { int n; int success = 0; @@ -2045,10 +2563,7 @@ DESCRIPTION */ static int -demangle_class (work, mangled, declp) - struct work_stuff *work; - const char **mangled; - string *declp; +demangle_class (struct work_stuff *work, const char **mangled, string *declp) { int success = 0; int btype; @@ -2089,6 +2604,82 @@ demangle_class (work, mangled, declp) return (success); } + +/* Called when there's a "__" in the mangled name, with `scan' pointing to + the rightmost guess. + + Find the correct "__"-sequence where the function name ends and the + signature starts, which is ambiguous with GNU mangling. + Call demangle_signature here, so we can make sure we found the right + one; *mangled will be consumed so caller will not make further calls to + demangle_signature. */ + +static int +iterate_demangle_function (struct work_stuff *work, const char **mangled, + string *declp, const char *scan) +{ + const char *mangle_init = *mangled; + int success = 0; + string decl_init; + struct work_stuff work_init; + + if (*(scan + 2) == '\0') + return 0; + + /* Do not iterate for some demangling modes, or if there's only one + "__"-sequence. This is the normal case. */ + if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING + || strstr (scan + 2, "__") == NULL) + return demangle_function_name (work, mangled, declp, scan); + + /* Save state so we can restart if the guess at the correct "__" was + wrong. */ + string_init (&decl_init); + string_appends (&decl_init, declp); + memset (&work_init, 0, sizeof work_init); + work_stuff_copy_to_from (&work_init, work); + + /* Iterate over occurrences of __, allowing names and types to have a + "__" sequence in them. We must start with the first (not the last) + occurrence, since "__" most often occur between independent mangled + parts, hence starting at the last occurence inside a signature + might get us a "successful" demangling of the signature. */ + + while (scan[2]) + { + if (demangle_function_name (work, mangled, declp, scan)) + { + success = demangle_signature (work, mangled, declp); + if (success) + break; + } + + /* Reset demangle state for the next round. */ + *mangled = mangle_init; + string_clear (declp); + string_appends (declp, &decl_init); + work_stuff_copy_to_from (work, &work_init); + + /* Leave this underscore-sequence. */ + scan += 2; + + /* Scan for the next "__" sequence. */ + while (*scan && (scan[0] != '_' || scan[1] != '_')) + scan++; + + /* Move to last "__" in this sequence. */ + while (*scan && *scan == '_') + scan++; + scan -= 2; + } + + /* Delete saved state. */ + delete_work_stuff (&work_init); + string_delete (&decl_init); + + return success; +} + /* LOCAL FUNCTION @@ -2104,6 +2695,8 @@ SYNOPSIS DESCRIPTION Consume and demangle the prefix of the mangled name. + While processing the function name root, arrange to call + demangle_signature if the root is ambiguous. DECLP points to the string buffer into which demangled output is placed. On entry, the buffer is empty. On exit it contains @@ -2121,10 +2714,8 @@ DESCRIPTION */ static int -demangle_prefix (work, mangled, declp) - struct work_stuff *work; - const char **mangled; - string *declp; +demangle_prefix (struct work_stuff *work, const char **mangled, + string *declp) { int success = 1; const char *scan; @@ -2178,7 +2769,7 @@ demangle_prefix (work, mangled, declp) /* This block of code is a reduction in strength time optimization of: - scan = mystrstr (*mangled, "__"); */ + scan = strstr (*mangled, "__"); */ { scan = *mangled; @@ -2207,20 +2798,20 @@ demangle_prefix (work, mangled, declp) } else if (work -> static_type) { - if (!isdigit ((unsigned char)scan[0]) && (scan[0] != 't')) + if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't')) { success = 0; } } else if ((scan == *mangled) - && (isdigit ((unsigned char)scan[2]) || (scan[2] == 'Q') + && (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q') || (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H'))) { /* The ARM says nothing about the mangling of local variables. But cfront mangles local variables by prepending __ to them. As an extension to ARM demangling we handle this case. */ if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING) - && isdigit ((unsigned char)scan[2])) + && ISDIGIT ((unsigned char)scan[2])) { *mangled = scan + 2; consume_count (mangled); @@ -2257,7 +2848,7 @@ demangle_prefix (work, mangled, declp) /* EDG template? */ demangle_arm_hp_template (work, mangled, strlen (*mangled), declp); } - else if ((scan == *mangled) && !isdigit ((unsigned char)scan[2]) + else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2]) && (scan[2] != 't')) { /* Mangled name starts with "__". Skip over any leading '_' characters, @@ -2270,36 +2861,23 @@ demangle_prefix (work, mangled, declp) { scan++; } - if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) + if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) { /* No separator (I.E. "__not_mangled"), or empty signature (I.E. "__not_mangled_either__") */ success = 0; } else - { - const char *tmp; - - /* Look for the LAST occurrence of __, allowing names to - have the '__' sequence embedded in them. */ - if (!(ARM_DEMANGLING || HP_DEMANGLING)) - { - while ((tmp = mystrstr (scan + 2, "__")) != NULL) - scan = tmp; - } - if (*(scan + 2) == '\0') - success = 0; - else - demangle_function_name (work, mangled, declp, scan); - } + return iterate_demangle_function (work, mangled, declp, scan); } } else if (*(scan + 2) != '\0') { /* Mangled name does not start with "__" but does have one somewhere in there with non empty stuff after it. Looks like a global - function name. */ - demangle_function_name (work, mangled, declp, scan); + function name. Iterate over all "__":s until the right + one is found. */ + return iterate_demangle_function (work, mangled, declp, scan); } else { @@ -2345,10 +2923,7 @@ DESCRIPTION */ static int -gnu_special (work, mangled, declp) - struct work_stuff *work; - const char **mangled; - string *declp; +gnu_special (struct work_stuff *work, const char **mangled, string *declp) { int n; int success = 1; @@ -2392,7 +2967,7 @@ gnu_special (work, mangled, declp) 1); break; default: - if (isdigit((unsigned char)*mangled[0])) + if (ISDIGIT((unsigned char)*mangled[0])) { n = consume_count(mangled); /* We may be seeing a too-large size, or else a @@ -2453,6 +3028,25 @@ gnu_special (work, mangled, declp) success = 0; break; } + + if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 + && (*mangled)[9] == 'N' + && (*mangled)[8] == (*mangled)[10] + && strchr (cplus_markers, (*mangled)[8])) + { + /* A member of the anonymous namespace. There's information + about what identifier or filename it was keyed to, but + it's just there to make the mangled name unique; we just + step over it. */ + string_append (declp, "{anonymous}"); + (*mangled) += n; + + /* Now p points to the marker before the N, so we need to + update it to the first marker after what we consumed. */ + p = strpbrk (*mangled, cplus_markers); + break; + } + string_appendn (declp, *mangled, n); (*mangled) += n; } @@ -2514,7 +3108,7 @@ gnu_special (work, mangled, declp) success = demangle_template (work, mangled, declp, 0, 1, 1); break; default: - success = demangle_fund_type (work, mangled, declp); + success = do_type (work, mangled, declp); break; } if (success && **mangled != '\0') @@ -2530,16 +3124,13 @@ gnu_special (work, mangled, declp) } static void -recursively_demangle(work, mangled, result, namelength) - struct work_stuff *work; - const char **mangled; - string *result; - int namelength; +recursively_demangle(struct work_stuff *work, const char **mangled, + string *result, int namelength) { char * recurse = (char *)NULL; char * recurse_dem = (char *)NULL; - recurse = (char *) xmalloc (namelength + 1); + recurse = XNEWVEC (char, namelength + 1); memcpy (recurse, *mangled, namelength); recurse[namelength] = '\000'; @@ -2582,9 +3173,7 @@ DESCRIPTION */ static int -arm_special (mangled, declp) - const char **mangled; - string *declp; +arm_special (const char **mangled, string *declp) { int n; int success = 1; @@ -2667,16 +3256,11 @@ BUGS */ static int -demangle_qualified (work, mangled, result, isfuncname, append) - struct work_stuff *work; - const char **mangled; - string *result; - int isfuncname; - int append; +demangle_qualified (struct work_stuff *work, const char **mangled, + string *result, int isfuncname, int append) { int qualifiers = 0; int success = 1; - const char *p; char num[2]; string temp; string last_name; @@ -2708,19 +3292,10 @@ demangle_qualified (work, mangled, result, isfuncname, append) /* GNU mangled name with more than 9 classes. The count is preceded by an underscore (to distinguish it from the <= 9 case) and followed by an underscore. */ - p = *mangled + 2; - qualifiers = atoi (p); - if (!isdigit ((unsigned char)*p) || *p == '0') - success = 0; - - /* Skip the digits. */ - while (isdigit ((unsigned char)*p)) - ++p; - - if (*p != '_') + (*mangled)++; + qualifiers = consume_count_with_underscores (mangled); + if (qualifiers == -1) success = 0; - - *mangled = p + 1; break; case '1': @@ -2810,6 +3385,7 @@ demangle_qualified (work, mangled, result, isfuncname, append) } else { + string_delete (&last_name); success = do_type (work, mangled, &last_name); if (!success) break; @@ -2903,22 +3479,18 @@ DESCRIPTION */ static int -get_count (type, count) - const char **type; - int *count; +get_count (const char **type, int *count) { const char *p; int n; - if (!isdigit ((unsigned char)**type)) - { - return (0); - } + if (!ISDIGIT ((unsigned char)**type)) + return (0); else { *count = **type - '0'; (*type)++; - if (isdigit ((unsigned char)**type)) + if (ISDIGIT ((unsigned char)**type)) { p = *type; n = *count; @@ -2928,7 +3500,7 @@ get_count (type, count) n += *p - '0'; p++; } - while (isdigit ((unsigned char)*p)); + while (ISDIGIT ((unsigned char)*p)); if (*p == '_') { *type = p + 1; @@ -2943,10 +3515,7 @@ get_count (type, count) value returned is really a type_kind_t. */ static int -do_type (work, mangled, result) - struct work_stuff *work; - const char **mangled; - string *result; +do_type (struct work_stuff *work, const char **mangled, string *result) { int n; int done; @@ -2954,10 +3523,8 @@ do_type (work, mangled, result) string decl; const char *remembered_type; int type_quals; - string btype; type_kind_t tk = tk_none; - string_init (&btype); string_init (&decl); string_init (result); @@ -3052,8 +3619,13 @@ do_type (work, mangled, result) (*mangled)++; string_append (&decl, ")"); - string_prepend (&decl, SCOPE_STRING (work)); - if (isdigit ((unsigned char)**mangled)) + + /* We don't need to prepend `::' for a qualified name; + demangle_qualified will do that for us. */ + if (**mangled != 'Q') + string_prepend (&decl, SCOPE_STRING (work)); + + if (ISDIGIT ((unsigned char)**mangled)) { n = consume_count (mangled); if (n == -1 @@ -3070,6 +3642,7 @@ do_type (work, mangled, result) string temp; do_type (work, mangled, &temp); string_prepends (&decl, &temp); + string_delete (&temp); } else if (**mangled == 't') { @@ -3080,11 +3653,19 @@ do_type (work, mangled, result) if (success) { string_prependn (&decl, temp.b, temp.p - temp.b); - string_clear (&temp); + string_delete (&temp); } else break; } + else if (**mangled == 'Q') + { + success = demangle_qualified (work, mangled, &decl, + /*isfuncnam=*/0, + /*append=*/0); + if (!success) + break; + } else { success = 0; @@ -3197,11 +3778,7 @@ do_type (work, mangled, result) if (work->tmpl_argvec) string_append (result, work->tmpl_argvec[idx]); else - { - char buf[10]; - sprintf(buf, "T%d", idx); - string_append (result, buf); - } + string_append_template_idx (result, idx); success = 1; } @@ -3247,20 +3824,15 @@ do_type (work, mangled, result) The value returned is really a type_kind_t. */ static int -demangle_fund_type (work, mangled, result) - struct work_stuff *work; - const char **mangled; - string *result; +demangle_fund_type (struct work_stuff *work, + const char **mangled, string *result) { int done = 0; int success = 1; - char buf[10]; - int dec = 0; - string btype; + char buf[INTBUF_SIZE + 5 /* 'int%u_t' */]; + unsigned int dec = 0; type_kind_t tk = tk_integral; - string_init (&btype); - /* First pick off any type qualifiers. There can be more than one. */ while (!done) @@ -3369,7 +3941,7 @@ demangle_fund_type (work, mangled, result) break; case 'G': (*mangled)++; - if (!isdigit ((unsigned char)**mangled)) + if (!ISDIGIT ((unsigned char)**mangled)) { success = 0; break; @@ -3399,7 +3971,7 @@ demangle_fund_type (work, mangled, result) *mangled += min (strlen (*mangled), 2); } sscanf (buf, "%x", &dec); - sprintf (buf, "int%i_t", dec); + sprintf (buf, "int%u_t", dec); APPEND_BLANK (result); string_append (result, buf); break; @@ -3432,8 +4004,11 @@ demangle_fund_type (work, mangled, result) } case 't': { + string btype; + string_init (&btype); success = demangle_template (work, mangled, &btype, 0, 1, 1); string_appends (result, &btype); + string_delete (&btype); break; } default: @@ -3449,10 +4024,8 @@ demangle_fund_type (work, mangled, result) **mangled points to 'S' or 'U' */ static int -do_hpacc_template_const_value (work, mangled, result) - struct work_stuff *work ATTRIBUTE_UNUSED; - const char **mangled; - string *result; +do_hpacc_template_const_value (struct work_stuff *work ATTRIBUTE_UNUSED, + const char **mangled, string *result) { int unsigned_const; @@ -3481,12 +4054,12 @@ do_hpacc_template_const_value (work, mangled, result) } /* We have to be looking at an integer now */ - if (!(isdigit ((unsigned char)**mangled))) + if (!(ISDIGIT ((unsigned char)**mangled))) return 0; /* We only deal with integral values for template parameters -- so it's OK to look only for digits */ - while (isdigit ((unsigned char)**mangled)) + while (ISDIGIT ((unsigned char)**mangled)) { char_str[0] = **mangled; string_append (result, char_str); @@ -3506,10 +4079,8 @@ do_hpacc_template_const_value (work, mangled, result) **mangled is pointing to the 'A' */ static int -do_hpacc_template_literal (work, mangled, result) - struct work_stuff *work; - const char **mangled; - string *result; +do_hpacc_template_literal (struct work_stuff *work, const char **mangled, + string *result) { int literal_len = 0; char * recurse; @@ -3530,7 +4101,7 @@ do_hpacc_template_literal (work, mangled, result) string_append (result, "&"); /* Now recursively demangle the literal name */ - recurse = (char *) xmalloc (literal_len + 1); + recurse = XNEWVEC (char, literal_len + 1); memcpy (recurse, *mangled, literal_len); recurse[literal_len] = '\000'; @@ -3552,9 +4123,7 @@ do_hpacc_template_literal (work, mangled, result) } static int -snarf_numeric_literal (args, arg) - const char ** args; - string * arg; +snarf_numeric_literal (const char **args, string *arg) { if (**args == '-') { @@ -3565,10 +4134,10 @@ snarf_numeric_literal (args, arg) else if (**args == '+') (*args)++; - if (!isdigit ((unsigned char)**args)) + if (!ISDIGIT ((unsigned char)**args)) return 0; - while (isdigit ((unsigned char)**args)) + while (ISDIGIT ((unsigned char)**args)) { char_str[0] = **args; string_append (arg, char_str); @@ -3583,10 +4152,7 @@ snarf_numeric_literal (args, arg) and free'd should anything go wrong. */ static int -do_arg (work, mangled, result) - struct work_stuff *work; - const char **mangled; - string *result; +do_arg (struct work_stuff *work, const char **mangled, string *result) { /* Remember where we started so that we can record the type, for non-squangling type remembering. */ @@ -3635,12 +4201,9 @@ do_arg (work, mangled, result) do not want to add additional types to the back-referenceable type vector when processing a repeated type. */ if (work->previous_argument) - string_clear (work->previous_argument); + string_delete (work->previous_argument); else - { - work->previous_argument = (string*) xmalloc (sizeof (string)); - string_init (work->previous_argument); - } + work->previous_argument = XNEW (string); if (!do_type (work, mangled, work->previous_argument)) return 0; @@ -3652,10 +4215,7 @@ do_arg (work, mangled, result) } static void -remember_type (work, start, len) - struct work_stuff *work; - const char *start; - int len; +remember_type (struct work_stuff *work, const char *start, int len) { char *tem; @@ -3667,18 +4227,16 @@ remember_type (work, start, len) if (work -> typevec_size == 0) { work -> typevec_size = 3; - work -> typevec - = (char **) xmalloc (sizeof (char *) * work -> typevec_size); + work -> typevec = XNEWVEC (char *, work->typevec_size); } else { work -> typevec_size *= 2; work -> typevec - = (char **) xrealloc ((char *)work -> typevec, - sizeof (char *) * work -> typevec_size); + = XRESIZEVEC (char *, work->typevec, work->typevec_size); } } - tem = xmalloc (len + 1); + tem = XNEWVEC (char, len + 1); memcpy (tem, start, len); tem[len] = '\0'; work -> typevec[work -> ntypes++] = tem; @@ -3687,10 +4245,7 @@ remember_type (work, start, len) /* Remember a K type class qualifier. */ static void -remember_Ktype (work, start, len) - struct work_stuff *work; - const char *start; - int len; +remember_Ktype (struct work_stuff *work, const char *start, int len) { char *tem; @@ -3699,18 +4254,16 @@ remember_Ktype (work, start, len) if (work -> ksize == 0) { work -> ksize = 5; - work -> ktypevec - = (char **) xmalloc (sizeof (char *) * work -> ksize); + work -> ktypevec = XNEWVEC (char *, work->ksize); } else { work -> ksize *= 2; work -> ktypevec - = (char **) xrealloc ((char *)work -> ktypevec, - sizeof (char *) * work -> ksize); + = XRESIZEVEC (char *, work->ktypevec, work->ksize); } } - tem = xmalloc (len + 1); + tem = XNEWVEC (char, len + 1); memcpy (tem, start, len); tem[len] = '\0'; work -> ktypevec[work -> numk++] = tem; @@ -3721,8 +4274,7 @@ remember_Ktype (work, start, len) registers map > as B0, and temp as B1 */ static int -register_Btype (work) - struct work_stuff *work; +register_Btype (struct work_stuff *work) { int ret; @@ -3731,15 +4283,13 @@ register_Btype (work) if (work -> bsize == 0) { work -> bsize = 5; - work -> btypevec - = (char **) xmalloc (sizeof (char *) * work -> bsize); + work -> btypevec = XNEWVEC (char *, work->bsize); } else { work -> bsize *= 2; work -> btypevec - = (char **) xrealloc ((char *)work -> btypevec, - sizeof (char *) * work -> bsize); + = XRESIZEVEC (char *, work->btypevec, work->bsize); } } ret = work -> numb++; @@ -3750,14 +4300,12 @@ register_Btype (work) /* Store a value into a previously registered B code type. */ static void -remember_Btype (work, start, len, index) - struct work_stuff *work; - const char *start; - int len, index; +remember_Btype (struct work_stuff *work, const char *start, + int len, int index) { char *tem; - tem = xmalloc (len + 1); + tem = XNEWVEC (char, len + 1); memcpy (tem, start, len); tem[len] = '\0'; work -> btypevec[index] = tem; @@ -3765,8 +4313,7 @@ remember_Btype (work, start, len, index) /* Lose all the info related to B and K type codes. */ static void -forget_B_and_K_types (work) - struct work_stuff *work; +forget_B_and_K_types (struct work_stuff *work) { int i; @@ -3793,8 +4340,7 @@ forget_B_and_K_types (work) /* Forget the remembered types, but not the type vector itself. */ static void -forget_types (work) - struct work_stuff *work; +forget_types (struct work_stuff *work) { int i; @@ -3852,10 +4398,8 @@ forget_types (work) */ static int -demangle_args (work, mangled, declp) - struct work_stuff *work; - const char **mangled; - string *declp; +demangle_args (struct work_stuff *work, const char **mangled, + string *declp) { string arg; int need_comma = 0; @@ -3977,10 +4521,8 @@ demangle_args (work, mangled, declp) and method pointers or references, not top-level declarations. */ static int -demangle_nested_args (work, mangled, declp) - struct work_stuff *work; - const char **mangled; - string *declp; +demangle_nested_args (struct work_stuff *work, const char **mangled, + string *declp) { string* saved_previous_argument; int result; @@ -4004,7 +4546,10 @@ demangle_nested_args (work, mangled, declp) /* Restore the previous_argument field. */ if (work->previous_argument) - string_delete (work->previous_argument); + { + string_delete (work->previous_argument); + free ((char *) work->previous_argument); + } work->previous_argument = saved_previous_argument; --work->forgetting_types; work->nrepeats = saved_nrepeats; @@ -4012,12 +4557,11 @@ demangle_nested_args (work, mangled, declp) return result; } -static void -demangle_function_name (work, mangled, declp, scan) - struct work_stuff *work; - const char **mangled; - string *declp; - const char *scan; +/* Returns 1 if a valid function name was found or 0 otherwise. */ + +static int +demangle_function_name (struct work_stuff *work, const char **mangled, + string *declp, const char *scan) { size_t i; string type; @@ -4055,13 +4599,13 @@ demangle_function_name (work, mangled, declp, scan) { work -> constructor += 1; string_clear (declp); - return; + return 1; } else if (strcmp (declp -> b, "__dt") == 0) { work -> destructor += 1; string_clear (declp); - return; + return 1; } } @@ -4074,7 +4618,7 @@ demangle_function_name (work, mangled, declp, scan) if (declp->p - declp->b >= 10 /* op$assign_ */ && memcmp (declp->b + 3, "assign_", 7) == 0) { - for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + for (i = 0; i < ARRAY_SIZE (optable); i++) { int len = declp->p - declp->b - 10; if ((int) strlen (optable[i].in) == len @@ -4090,7 +4634,7 @@ demangle_function_name (work, mangled, declp, scan) } else { - for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + for (i = 0; i < ARRAY_SIZE (optable); i++) { int len = declp->p - declp->b - 3; if ((int) strlen (optable[i].in) == len @@ -4132,13 +4676,13 @@ demangle_function_name (work, mangled, declp, scan) } } else if (declp->b[0] == '_' && declp->b[1] == '_' - && declp->b[2] >= 'a' && declp->b[2] <= 'z' - && declp->b[3] >= 'a' && declp->b[3] <= 'z') + && ISLOWER((unsigned char)declp->b[2]) + && ISLOWER((unsigned char)declp->b[3])) { if (declp->b[4] == '\0') { /* Operator. */ - for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + for (i = 0; i < ARRAY_SIZE (optable); i++) { if (strlen (optable[i].in) == 2 && memcmp (optable[i].in, declp->b + 2, 2) == 0) @@ -4155,7 +4699,7 @@ demangle_function_name (work, mangled, declp, scan) if (declp->b[2] == 'a' && declp->b[5] == '\0') { /* Assignment. */ - for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) + for (i = 0; i < ARRAY_SIZE (optable); i++) { if (strlen (optable[i].in) == 3 && memcmp (optable[i].in, declp->b + 2, 3) == 0) @@ -4169,14 +4713,19 @@ demangle_function_name (work, mangled, declp, scan) } } } + + /* If a function name was obtained but it's not valid, we were not + successful. */ + if (LEN_STRING (declp) == 1 && declp->b[0] == '.') + return 0; + else + return 1; } /* a mini string-handling package */ static void -string_need (s, n) - string *s; - int n; +string_need (string *s, int n) { int tem; @@ -4186,7 +4735,7 @@ string_need (s, n) { n = 32; } - s->p = s->b = xmalloc (n); + s->p = s->b = XNEWVEC (char, n); s->e = s->b + n; } else if (s->e - s->p < n) @@ -4194,15 +4743,14 @@ string_need (s, n) tem = s->p - s->b; n += tem; n *= 2; - s->b = xrealloc (s->b, n); + s->b = XRESIZEVEC (char, s->b, n); s->p = s->b + tem; s->e = s->b + n; } } static void -string_delete (s) - string *s; +string_delete (string *s) { if (s->b != NULL) { @@ -4212,15 +4760,13 @@ string_delete (s) } static void -string_init (s) - string *s; +string_init (string *s) { s->b = s->p = s->e = NULL; } static void -string_clear (s) - string *s; +string_clear (string *s) { s->p = s->b; } @@ -4228,8 +4774,7 @@ string_clear (s) #if 0 static int -string_empty (s) - string *s; +string_empty (string *s) { return (s->b == s->p); } @@ -4237,9 +4782,7 @@ string_empty (s) #endif static void -string_append (p, s) - string *p; - const char *s; +string_append (string *p, const char *s) { int n; if (s == NULL || *s == '\0') @@ -4251,8 +4794,7 @@ string_append (p, s) } static void -string_appends (p, s) - string *p, *s; +string_appends (string *p, string *s) { int n; @@ -4266,10 +4808,7 @@ string_appends (p, s) } static void -string_appendn (p, s, n) - string *p; - const char *s; - int n; +string_appendn (string *p, const char *s, int n) { if (n != 0) { @@ -4280,9 +4819,7 @@ string_appendn (p, s, n) } static void -string_prepend (p, s) - string *p; - const char *s; +string_prepend (string *p, const char *s) { if (s != NULL && *s != '\0') { @@ -4291,8 +4828,7 @@ string_prepend (p, s) } static void -string_prepends (p, s) - string *p, *s; +string_prepends (string *p, string *s) { if (s->b != s->p) { @@ -4301,10 +4837,7 @@ string_prepends (p, s) } static void -string_prependn (p, s, n) - string *p; - const char *s; - int n; +string_prependn (string *p, const char *s, int n) { char *q; @@ -4320,296 +4853,10 @@ string_prependn (p, s, n) } } -/* To generate a standalone demangler program for testing purposes, - just compile and link this file with -DMAIN and libiberty.a. When - run, it demangles each command line arg, or each stdin string, and - prints the result on stdout. */ - -#ifdef MAIN - -#include "getopt.h" - -static char *program_name; -static char *program_version = VERSION; -static int flags = DMGL_PARAMS | DMGL_ANSI; - -static void demangle_it PARAMS ((char *)); -static void usage PARAMS ((FILE *, int)); -static void fatal PARAMS ((char *)); - -static void -demangle_it (mangled_name) - char *mangled_name; -{ - char *result; - - result = cplus_demangle (mangled_name, flags); - if (result == NULL) - { - printf ("%s\n", mangled_name); - } - else - { - printf ("%s\n", result); - free (result); - } -} - -static void -usage (stream, status) - FILE *stream; - int status; -{ - fprintf (stream, "\ -Usage: %s [-_] [-n] [-s {gnu,lucid,arm,hp,edg}] [--strip-underscores]\n\ - [--no-strip-underscores] [--format={gnu,lucid,arm,hp,edg}]\n\ - [--help] [--version] [arg...]\n", - program_name); - exit (status); -} - -#define MBUF_SIZE 32767 -char mbuffer[MBUF_SIZE]; - -/* Defined in the automatically-generated underscore.c. */ -extern int prepends_underscore; - -int strip_underscore = 0; - -static struct option long_options[] = { - {"strip-underscores", no_argument, 0, '_'}, - {"format", required_argument, 0, 's'}, - {"help", no_argument, 0, 'h'}, - {"java", no_argument, 0, 'j'}, - {"no-strip-underscores", no_argument, 0, 'n'}, - {"version", no_argument, 0, 'v'}, - {0, no_argument, 0, 0} -}; - -/* More 'friendly' abort that prints the line and file. - config.h can #define abort fancy_abort if you like that sort of thing. */ - -void -fancy_abort () -{ - fatal ("Internal gcc abort."); -} - - -/* Return the string of non-alnum characters that may occur - as a valid symbol component, in the standard assembler symbol - syntax. */ - -static const char * -standard_symbol_characters () -{ - return "_$."; -} - - -/* Return the string of non-alnum characters that may occur - as a valid symbol name component in an HP object file. - - Note that, since HP's compiler generates object code straight from - C++ source, without going through an assembler, its mangled - identifiers can use all sorts of characters that no assembler would - tolerate, so the alphabet this function creates is a little odd. - Here are some sample mangled identifiers offered by HP: - - typeid*__XT24AddressIndExpClassMember_ - [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv - __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv - - This still seems really weird to me, since nowhere else in this - file is there anything to recognize curly brackets, parens, etc. - I've talked with Srikanth , and he assures me - this is right, but I still strongly suspect that there's a - misunderstanding here. - - If we decide it's better for c++filt to use HP's assembler syntax - to scrape identifiers out of its input, here's the definition of - the symbol name syntax from the HP assembler manual: - - Symbols are composed of uppercase and lowercase letters, decimal - digits, dollar symbol, period (.), ampersand (&), pound sign(#) and - underscore (_). A symbol can begin with a letter, digit underscore or - dollar sign. If a symbol begins with a digit, it must contain a - non-digit character. - - So have fun. */ -static const char * -hp_symbol_characters () -{ - return "_$.<>#,*&[]:(){}"; -} - - -int -main (argc, argv) - int argc; - char **argv; -{ - char *result; - int c; - const char *valid_symbols; - - program_name = argv[0]; - - strip_underscore = prepends_underscore; - - while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF) - { - switch (c) - { - case '?': - usage (stderr, 1); - break; - case 'h': - usage (stdout, 0); - case 'n': - strip_underscore = 0; - break; - case 'v': - printf ("GNU %s (C++ demangler), version %s\n", program_name, program_version); - exit (0); - case '_': - strip_underscore = 1; - break; - case 'j': - flags |= DMGL_JAVA; - break; - case 's': - if (strcmp (optarg, "gnu") == 0) - { - current_demangling_style = gnu_demangling; - } - else if (strcmp (optarg, "lucid") == 0) - { - current_demangling_style = lucid_demangling; - } - else if (strcmp (optarg, "arm") == 0) - { - current_demangling_style = arm_demangling; - } - else if (strcmp (optarg, "hp") == 0) - { - current_demangling_style = hp_demangling; - } - else if (strcmp (optarg, "edg") == 0) - { - current_demangling_style = edg_demangling; - } - else - { - fprintf (stderr, "%s: unknown demangling style `%s'\n", - program_name, optarg); - exit (1); - } - break; - } - } - - if (optind < argc) - { - for ( ; optind < argc; optind++) - { - demangle_it (argv[optind]); - } - } - else - { - switch (current_demangling_style) - { - case gnu_demangling: - case lucid_demangling: - case arm_demangling: - case edg_demangling: - valid_symbols = standard_symbol_characters (); - break; - case hp_demangling: - valid_symbols = hp_symbol_characters (); - break; - default: - /* Folks should explicitly indicate the appropriate alphabet for - each demangling. Providing a default would allow the - question to go unconsidered. */ - abort (); - } - - for (;;) - { - int i = 0; - c = getchar (); - /* Try to read a label. */ - while (c != EOF && (isalnum (c) || strchr (valid_symbols, c))) - { - if (i >= MBUF_SIZE-1) - break; - mbuffer[i++] = c; - c = getchar (); - } - if (i > 0) - { - int skip_first = 0; - - if (mbuffer[0] == '.') - ++skip_first; - if (strip_underscore && mbuffer[skip_first] == '_') - ++skip_first; - - if (skip_first > i) - skip_first = i; - - mbuffer[i] = 0; - - result = cplus_demangle (mbuffer + skip_first, flags); - if (result) - { - if (mbuffer[0] == '.') - putc ('.', stdout); - fputs (result, stdout); - free (result); - } - else - fputs (mbuffer, stdout); - - fflush (stdout); - } - if (c == EOF) - break; - putchar (c); - } - } - - exit (0); -} - static void -fatal (str) - char *str; -{ - fprintf (stderr, "%s: %s\n", program_name, str); - exit (1); -} - -PTR -xmalloc (size) - size_t size; -{ - register PTR value = (PTR) malloc (size); - if (value == 0) - fatal ("virtual memory exhausted"); - return value; -} - -PTR -xrealloc (ptr, size) - PTR ptr; - size_t size; +string_append_template_idx (string *s, int idx) { - register PTR value = (PTR) realloc (ptr, size); - if (value == 0) - fatal ("virtual memory exhausted"); - return value; + char buf[INTBUF_SIZE + 1 /* 'T' */]; + sprintf(buf, "T%d", idx); + string_append (s, buf); } -#endif /* main */