diff options
Diffstat (limited to 'libiberty/cplus-dem.c')
-rw-r--r-- | libiberty/cplus-dem.c | 1186 |
1 files changed, 933 insertions, 253 deletions
diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index 5794a5bb869..ccf7aef4a85 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -29,9 +29,14 @@ Boston, MA 02111-1307, USA. */ try not to break either. */ #include <ctype.h> +#include <sys/types.h> #include <string.h> #include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + #include <demangle.h> #undef CURRENT_DEMANGLING_STYLE #define CURRENT_DEMANGLING_STYLE work->options @@ -96,12 +101,20 @@ 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 const_type; /* A const member function */ + char **tmpl_argvec; /* Template function arguments. */ + int ntmpl_args; /* The number of template function arguments. */ }; #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) @@ -190,7 +203,8 @@ static const struct optable {"min", "<?", 0}, /* old */ {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */ {"nop", "", 0}, /* old (for operator=) */ - {"rm", "->*", DMGL_ANSI} /* ansi */ + {"rm", "->*", DMGL_ANSI}, /* ansi */ + {"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */ }; @@ -206,6 +220,7 @@ typedef struct string /* Beware: these aren't required to be */ 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)) #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ @@ -215,14 +230,24 @@ typedef struct string /* Beware: these aren't required to be */ static char * mop_up PARAMS ((struct work_stuff *, string *, int)); +static void +squangle_mop_up PARAMS ((struct work_stuff *)); + #if 0 static int -demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *)); +demangle_method_args PARAMS ((struct work_stuff *, const char **, string *)); #endif +static char * +internal_cplus_demangle PARAMS ((struct work_stuff *, const char *)); + +static int +demangle_template_template_parm PARAMS ((struct work_stuff *work, + const char **, string *)); + static int demangle_template PARAMS ((struct work_stuff *work, const char **, string *, - string *)); + string *, int)); static int arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **, @@ -254,7 +279,7 @@ static int gnu_special PARAMS ((struct work_stuff *, const char **, string *)); static int -arm_special PARAMS ((struct work_stuff *, const char **, string *)); +arm_special PARAMS ((const char **, string *)); static void string_need PARAMS ((string *, int)); @@ -294,6 +319,9 @@ 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 ((struct work_stuff *, const char **, string *)); @@ -311,11 +339,27 @@ static void remember_type PARAMS ((struct work_stuff *, const char *, int)); static void +remember_Btype PARAMS ((struct work_stuff *, const char *, int, int)); + +static int +register_Btype PARAMS ((struct work_stuff *)); + +static void +remember_Ktype PARAMS ((struct work_stuff *, const char *, int)); + +static void forget_types PARAMS ((struct work_stuff *)); static void +forget_B_and_K_types PARAMS ((struct work_stuff *)); + +static void string_prepends PARAMS ((string *, string *)); +static int +demangle_template_value_parm PARAMS ((struct work_stuff*, + const char**, string*)); + /* 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 @@ -336,13 +380,49 @@ consume_count (type) 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 (mangled) + const char **mangled; +{ + int idx; + + if (**mangled == '_') + { + (*mangled)++; + if (!isdigit (**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; +} + int cplus_demangle_opname (opname, result, options) const char *opname; char *result; int options; { - int len, i, len1, ret; + int len, len1, ret; string type; struct work_stuff work[1]; const char *tem; @@ -350,6 +430,7 @@ cplus_demangle_opname (opname, result, options) len = strlen(opname); result[0] = '\0'; ret = 0; + memset ((char *) work, 0, sizeof (work)); work->options = options; if (opname[0] == '_' && opname[1] == '_' @@ -373,6 +454,7 @@ cplus_demangle_opname (opname, result, options) if (opname[4] == '\0') { /* Operator. */ + size_t i; for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { if (strlen (optable[i].in) == 2 @@ -390,6 +472,7 @@ cplus_demangle_opname (opname, result, options) if (opname[2] == 'a' && opname[5] == '\0') { /* Assignment. */ + size_t i; for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { if (strlen (optable[i].in) == 3 @@ -413,6 +496,7 @@ cplus_demangle_opname (opname, result, options) if (len >= 10 /* op$assign_ */ && memcmp (opname + 3, "assign_", 7) == 0) { + size_t i; for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { len1 = len - 10; @@ -429,6 +513,7 @@ cplus_demangle_opname (opname, result, options) } else { + size_t i; for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { len1 = len - 3; @@ -456,6 +541,7 @@ cplus_demangle_opname (opname, result, options) ret = 1; } } + squangle_mop_up (work); return ret; } @@ -470,7 +556,7 @@ cplus_mangle_opname (opname, options) const char *opname; int options; { - int i; + size_t i; int len; len = strlen (opname); @@ -517,18 +603,44 @@ cplus_demangle (mangled, options) const char *mangled; int options; { + char *ret; + struct work_stuff work[1]; + 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; + + ret = internal_cplus_demangle (work, mangled); + squangle_mop_up (work); + return (ret); +} + + +/* 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 + 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; +{ + string decl; int success = 0; - struct work_stuff work[1]; char *demangled = NULL; + int s1,s2,s3,s4; + s1 = work->constructor; + s2 = work->destructor; + s3 = work->static_type; + s4 = work->const_type; + work->constructor = work->destructor = 0; + work->static_type = work->const_type = 0; if ((mangled != NULL) && (*mangled != '\0')) { - 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; - string_init (&decl); /* First check to see if gnu style demangling is active and if the @@ -552,19 +664,43 @@ cplus_demangle (mangled, options) } if (work->constructor == 2) { - string_prepend(&decl, "global constructors keyed to "); + string_prepend (&decl, "global constructors keyed to "); work->constructor = 0; } else if (work->destructor == 2) { - string_prepend(&decl, "global destructors keyed to "); + string_prepend (&decl, "global destructors keyed to "); work->destructor = 0; } demangled = mop_up (work, &decl, success); } + work->constructor = s1; + work->destructor = s2; + work->static_type = s3; + work->const_type = s4; return (demangled); } + +/* Clear out and squangling related storage */ +static void +squangle_mop_up (work) + struct 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); + } +} + +/* Clear out any mangled storage */ + static char * mop_up (work, declp, success) struct work_stuff *work; @@ -579,8 +715,20 @@ mop_up (work, declp, success) if (work -> typevec != NULL) { free ((char *) work -> typevec); + work -> typevec = NULL; } - + 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 demangling was successful, ensure that the demangled string is null terminated and return it. Otherwise, free the demangling decl. */ @@ -635,6 +783,7 @@ demangle_signature (work, mangled, 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; @@ -656,6 +805,16 @@ demangle_signature (work, mangled, declp) } 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 */ @@ -726,12 +885,13 @@ demangle_signature (work, mangled, declp) { oldmangled = *mangled; } - success = demangle_template (work, mangled, &tname, &trawname); + success = demangle_template (work, mangled, &tname, &trawname, 1); if (success) { remember_type (work, oldmangled, *mangled - oldmangled); } - string_append(&tname, (work -> options & DMGL_JAVA) ? "." : "::"); + string_append (&tname, "::"); + string_prepends(declp, &tname); if (work -> destructor & 1) { @@ -751,14 +911,43 @@ demangle_signature (work, mangled, declp) break; case '_': - /* 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. */ - success = 0; + if (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. */ + success = 0; break; + case 'H': + if (GNU_DEMANGLING) + { + /* A G++ template function. Read the template arguments. */ + success = demangle_template (work, mangled, declp, 0, 0); + if (!(work->constructor & 1)) + expect_return_type = 1; + (*mangled)++; + break; + } + else + /* fall through */ + {;} + default: if (AUTO_DEMANGLING || GNU_DEMANGLING) { @@ -785,6 +974,10 @@ demangle_signature (work, mangled, declp) { func_done = 1; 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; } } } @@ -838,50 +1031,411 @@ demangle_method_args (work, mangled, declp) #endif static int -demangle_template (work, mangled, tname, trawname) +demangle_template_template_parm (work, mangled, tname) + struct 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_integral_value (work, mangled, s) + struct work_stuff *work; + const char** mangled; + string* s; +{ + int success; + + if (**mangled == 'E') + { + int need_operator = 0; + + 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 < sizeof (optable) / sizeof (optable [0]); + ++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); + } + + if (**mangled != 'W') + success = 0; + else + { + string_appendn (s, ")", 1); + (*mangled)++; + } + } + else if (**mangled == 'Q' || **mangled == 'K') + success = demangle_qualified (work, mangled, s, 0, 1); + else + { + success = 0; + + if (**mangled == 'm') + { + string_appendn (s, "-", 1); + (*mangled)++; + } + while (isdigit (**mangled)) + { + string_appendn (s, *mangled, 1); + (*mangled)++; + success = 1; + } + } + + return success; +} + +static int +demangle_template_value_parm (work, mangled, s) + struct work_stuff *work; + const char **mangled; + string* s; +{ + const char *old_p = *mangled; + int is_pointer = 0; + int is_real = 0; + int is_integral = 0; + int is_char = 0; + int is_bool = 0; + int done = 0; + int success = 1; + + while (*old_p && !done) + { + switch (*old_p) + { + case 'P': + case 'p': + case 'R': + done = is_pointer = 1; + break; + case 'C': /* const */ + case 'S': /* explicitly signed [char] */ + case 'U': /* unsigned */ + case 'V': /* volatile */ + case 'F': /* function */ + case 'M': /* member function */ + case 'O': /* ??? */ + case 'J': /* complex */ + old_p++; + continue; + case 'E': /* expression */ + case 'Q': /* qualified name */ + case 'K': /* qualified name */ + done = is_integral = 1; + break; + case 'B': /* squangled name */ + done = is_integral = 1; + break; + case 'T': /* remembered type */ + abort (); + break; + case 'v': /* void */ + abort (); + break; + case 'x': /* long long */ + case 'l': /* long */ + case 'i': /* int */ + case 's': /* short */ + case 'w': /* wchar_t */ + done = is_integral = 1; + break; + case 'b': /* bool */ + done = is_bool = 1; + break; + case 'c': /* char */ + done = is_char = 1; + break; + case 'r': /* long double */ + case 'd': /* double */ + case 'f': /* float */ + done = is_real = 1; + break; + default: + /* it's probably user defined type, let's assume + it's integral, it seems hard to figure out + what it really is */ + done = is_integral = 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 + { + char buf[10]; + sprintf(buf, "T%d", idx); + string_append (s, buf); + } + } + else if (is_integral) + success = demangle_integral_value (work, mangled, s); + else if (is_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) + return -1; + tmp[0] = (char)val; + tmp[1] = '\0'; + string_appendn (s, &tmp[0], 1); + string_appendn (s, "'", 1); + } + else if (is_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 (is_real) + { + if (**mangled == 'm') + { + string_appendn (s, "-", 1); + (*mangled)++; + } + while (isdigit (**mangled)) + { + string_appendn (s, *mangled, 1); + (*mangled)++; + } + if (**mangled == '.') /* fraction */ + { + string_appendn (s, ".", 1); + (*mangled)++; + while (isdigit (**mangled)) + { + string_appendn (s, *mangled, 1); + (*mangled)++; + } + } + if (**mangled == 'e') /* exponent */ + { + string_appendn (s, "e", 1); + (*mangled)++; + while (isdigit (**mangled)) + { + string_appendn (s, *mangled, 1); + (*mangled)++; + } + } + } + else if (is_pointer) + { + int symbol_len = consume_count (mangled); + if (symbol_len == 0) + return -1; + if (symbol_len == 0) + string_appendn (s, "0", 1); + else + { + char *p = xmalloc (symbol_len + 1), *q; + strncpy (p, *mangled, symbol_len); + p [symbol_len] = '\0'; + q = internal_cplus_demangle (work, p); + string_appendn (s, "&", 1); + if (q) + { + string_append (s, q); + free (q); + } + else + string_append (s, p); + free (p); + } + *mangled += symbol_len; + } + + return success; +} + +static int +demangle_template (work, mangled, tname, trawname, is_type) struct work_stuff *work; const char **mangled; string *tname; string *trawname; + int is_type; { int i; - int is_pointer; - int is_real; - int is_integral; - int is_char; - int is_bool; int r; int need_comma = 0; int success = 0; - int done; - const char *old_p; const char *start; - int symbol_len; - int is_java_array; string temp; (*mangled)++; - start = *mangled; - /* get template name */ - if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r) + if (is_type) { - return (0); - } - if (trawname) - string_appendn (trawname, *mangled, r); - is_java_array = (work -> options & DMGL_JAVA) - && strncmp (*mangled, "JArray1Z", 8) == 0; - if (! is_java_array) - { - string_appendn (tname, *mangled, r); - string_append (tname, "<"); + 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 + { + char buf[10]; + sprintf(buf, "T%d", idx); + string_append (tname, buf); + if (trawname) + string_append (trawname, work->tmpl_argvec[idx]); + } + } + else + { + if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r) + { + return (0); + } + if (trawname) + string_appendn (trawname, *mangled, r); + string_appendn (tname, *mangled, r); + *mangled += r; + } } - *mangled += r; + 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) @@ -897,6 +1451,15 @@ demangle_template (work, mangled, tname, trawname) if (success) { string_appends (tname, &temp); + + if (!is_type) + { + /* Save the template argument. */ + int len = temp.p - temp.b; + work->tmpl_argvec[i] = xmalloc (len + 1); + memcpy (work->tmpl_argvec[i], temp.b, len); + work->tmpl_argvec[i][len] = '\0'; + } } string_delete(&temp); if (!success) @@ -904,22 +1467,46 @@ demangle_template (work, mangled, tname, trawname) 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 && 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] = 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 */ - old_p = *mangled; - is_pointer = 0; - is_real = 0; - is_integral = 0; - is_char = 0; - is_bool = 0; - done = 0; + /* temp is initialized in do_type */ success = do_type (work, mangled, &temp); /* if (success) { - string_appends (tname, &temp); + string_appends (s, &temp); } */ string_delete(&temp); @@ -928,174 +1515,40 @@ demangle_template (work, mangled, tname, trawname) break; } /* - string_append (tname, "="); + string_append (s, "="); */ - while (*old_p && !done) - { - switch (*old_p) - { - case 'P': - case 'p': - case 'R': - done = is_pointer = 1; - break; - case 'C': /* const */ - case 'S': /* explicitly signed [char] */ - case 'U': /* unsigned */ - case 'V': /* volatile */ - case 'F': /* function */ - case 'M': /* member function */ - case 'O': /* ??? */ - case 'J': /* complex */ - old_p++; - continue; - case 'Q': /* qualified name */ - done = is_integral = 1; - break; - case 'T': /* remembered type */ - abort (); - break; - case 'v': /* void */ - abort (); - break; - case 'x': /* long long */ - case 'l': /* long */ - case 'i': /* int */ - case 's': /* short */ - case 'w': /* wchar_t */ - done = is_integral = 1; - break; - case 'b': /* bool */ - done = is_bool = 1; - break; - case 'c': /* char */ - done = is_char = 1; - break; - case 'r': /* long double */ - case 'd': /* double */ - case 'f': /* float */ - done = is_real = 1; - break; - default: - /* it's probably user defined type, let's assume - it's integral, it seems hard to figure out - what it really is */ - done = is_integral = 1; - } - } - if (is_integral) - { - if (**mangled == 'm') - { - string_appendn (tname, "-", 1); - (*mangled)++; - } - while (isdigit (**mangled)) - { - string_appendn (tname, *mangled, 1); - (*mangled)++; - } - } - else if (is_char) + + if (!is_type) { - char tmp[2]; - int val; - if (**mangled == 'm') - { - string_appendn (tname, "-", 1); - (*mangled)++; - } - string_appendn (tname, "'", 1); - val = consume_count(mangled); - if (val == 0) - { - success = 0; - break; - } - tmp[0] = (char)val; - tmp[1] = '\0'; - string_appendn (tname, &tmp[0], 1); - string_appendn (tname, "'", 1); - } - else if (is_bool) - { - int val = consume_count (mangled); - if (val == 0) - string_appendn (tname, "false", 5); - else if (val == 1) - string_appendn (tname, "true", 4); - else - success = 0; + s = ¶m; + string_init (s); } - else if (is_real) + else + s = tname; + + success = demangle_template_value_parm (work, mangled, s); + + if (!success) { - if (**mangled == 'm') - { - string_appendn (tname, "-", 1); - (*mangled)++; - } - while (isdigit (**mangled)) - { - string_appendn (tname, *mangled, 1); - (*mangled)++; - } - if (**mangled == '.') /* fraction */ - { - string_appendn (tname, ".", 1); - (*mangled)++; - while (isdigit (**mangled)) - { - string_appendn (tname, *mangled, 1); - (*mangled)++; - } - } - if (**mangled == 'e') /* exponent */ - { - string_appendn (tname, "e", 1); - (*mangled)++; - while (isdigit (**mangled)) - { - string_appendn (tname, *mangled, 1); - (*mangled)++; - } - } + if (!is_type) + string_delete (s); + success = 0; + break; } - else if (is_pointer) + + if (!is_type) { - symbol_len = consume_count (mangled); - if (symbol_len == 0) - { - success = 0; - break; - } - if (symbol_len == 0) - string_appendn (tname, "0", 1); - else - { - char *p = xmalloc (symbol_len + 1), *q; - strncpy (p, *mangled, symbol_len); - p [symbol_len] = '\0'; - q = cplus_demangle (p, work->options); - string_appendn (tname, "&", 1); - if (q) - { - string_append (tname, q); - free (q); - } - else - string_append (tname, p); - free (p); - } - *mangled += symbol_len; + int len = s->p - s->b; + work->tmpl_argvec[i] = 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, " "); @@ -1237,9 +1690,11 @@ demangle_class (work, mangled, declp) string *declp; { int success = 0; + int btype; string class_name; string_init (&class_name); + btype = register_Btype (work); if (demangle_class_name (work, mangled, &class_name)) { if ((work->constructor & 1) || (work->destructor & 1)) @@ -1255,7 +1710,9 @@ demangle_class (work, mangled, declp) work -> constructor -= 1; } } - string_prepend (declp, (work -> options & DMGL_JAVA) ? "." : "::"); + remember_Ktype (work, class_name.b, LEN_STRING(&class_name)); + remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype); + string_prepend (declp, "::"); string_prepends (declp, &class_name); success = 1; } @@ -1377,7 +1834,8 @@ demangle_prefix (work, mangled, declp) } } else if ((scan == *mangled) - && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't'))) + && (isdigit (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 __<nesting_level> @@ -1394,7 +1852,8 @@ demangle_prefix (work, mangled, declp) { /* A GNU style constructor starts with __[0-9Qt]. But cfront uses names like __Q2_3foo3bar for nested type names. So don't accept - this style of constructor for cfront demangling. */ + this style of constructor for cfront demangling. A GNU + style member-template constructor starts with 'H'. */ if (!(LUCID_DEMANGLING || ARM_DEMANGLING)) work -> constructor += 1; *mangled = scan + 2; @@ -1406,7 +1865,7 @@ demangle_prefix (work, mangled, declp) then find the next "__" that separates the prefix from the signature. */ if (!(ARM_DEMANGLING || LUCID_DEMANGLING) - || (arm_special (work, mangled, declp) == 0)) + || (arm_special (mangled, declp) == 0)) { while (*scan == '_') { @@ -1523,15 +1982,25 @@ gnu_special (work, mangled, declp) switch (**mangled) { case 'Q': + case 'K': success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': - success = demangle_template (work, mangled, declp, 0); + success = demangle_template (work, mangled, declp, 0, 1); break; default: if (isdigit(*mangled[0])) { n = consume_count(mangled); + /* We may be seeing a too-large size, or else a + ".<digits>" indicating a static local symbol. In + any case, declare victory and move on; *don't* try + to use n to allocate. */ + if (n > strlen (*mangled)) + { + success = 1; + break; + } } else { @@ -1545,8 +2014,7 @@ gnu_special (work, mangled, declp) { if (p != NULL) { - string_append (declp, - (work -> options & DMGL_JAVA) ? "." : "::"); + string_append (declp, "::"); (*mangled)++; } } @@ -1568,10 +2036,11 @@ gnu_special (work, mangled, declp) switch (**mangled) { case 'Q': + case 'K': success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': - success = demangle_template (work, mangled, declp, 0); + success = demangle_template (work, mangled, declp, 0, 1); break; default: n = consume_count (mangled); @@ -1583,7 +2052,7 @@ gnu_special (work, mangled, declp) /* Consumed everything up to the cplus_marker, append the variable name. */ (*mangled)++; - string_append (declp, (work -> options & DMGL_JAVA) ? "." : "::"); + string_append (declp, "::"); n = strlen (*mangled); string_appendn (declp, *mangled, n); (*mangled) += n; @@ -1596,7 +2065,7 @@ gnu_special (work, mangled, declp) else if (strncmp (*mangled, "__thunk_", 8) == 0) { int delta = ((*mangled) += 8, consume_count (mangled)); - char *method = cplus_demangle (++*mangled, work->options); + char *method = internal_cplus_demangle (work, ++*mangled); if (method) { char buf[50]; @@ -1620,10 +2089,11 @@ gnu_special (work, mangled, declp) switch (**mangled) { case 'Q': + case 'K': success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': - success = demangle_template (work, mangled, declp, 0); + success = demangle_template (work, mangled, declp, 0, 1); break; default: success = demangle_fund_type (work, mangled, declp); @@ -1650,8 +2120,8 @@ LOCAL FUNCTION SYNOPSIS static int - arm_special (struct work_stuff *work, const char **mangled, - string *declp); + arm_special (const char **mangled, + string *declp); DESCRIPTION @@ -1665,8 +2135,7 @@ DESCRIPTION */ static int -arm_special (work, mangled, declp) - struct work_stuff *work; +arm_special (mangled, declp) const char **mangled; string *declp; { @@ -1755,7 +2224,7 @@ demangle_qualified (work, mangled, result, isfuncname, append) int isfuncname; int append; { - int qualifiers; + int qualifiers = 0; int namelength; int success = 1; const char *p; @@ -1763,7 +2232,20 @@ demangle_qualified (work, mangled, result, isfuncname, append) string temp; string_init (&temp); - switch ((*mangled)[1]) + + if ((*mangled)[0] == 'K') + { + /* Squangling qualified name reuse */ + int idx; + (*mangled)++; + idx = consume_count_with_underscores (mangled); + if (idx == -1 || idx > work -> numk) + success = 0; + else + string_append (&temp, work -> ktypevec[idx]); + } + else + switch ((*mangled)[1]) { case '_': /* GNU mangled name with more than 9 classes. The count is preceded @@ -1821,11 +2303,30 @@ demangle_qualified (work, mangled, result, isfuncname, append) while (qualifiers-- > 0) { + int remember_K = 1; if (*mangled[0] == '_') *mangled = *mangled + 1; if (*mangled[0] == 't') { - success = demangle_template(work, mangled, &temp, 0); + success = demangle_template(work, mangled, &temp, 0, 1); + if (!success) break; + } + else if (*mangled[0] == 'X') + { + success = do_type (work, mangled, &temp); + if (!success) break; + } + else if (*mangled[0] == 'K') + { + int idx; + (*mangled)++; + idx = consume_count_with_underscores (mangled); + if (idx == -1 || idx > work->numk) + success = 0; + else + string_append (&temp, work->ktypevec[idx]); + remember_K = 0; + if (!success) break; } else @@ -1840,9 +2341,15 @@ demangle_qualified (work, mangled, result, isfuncname, append) string_appendn (&temp, *mangled, namelength); *mangled += namelength; } + + if (remember_K) + { + remember_Ktype (work, temp.b, LEN_STRING (&temp)); + } + if (qualifiers > 0) { - string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::"); + string_append (&temp, "::"); } } @@ -1853,7 +2360,7 @@ demangle_qualified (work, mangled, result, isfuncname, append) if (isfuncname && (work->constructor & 1 || work->destructor & 1)) { - string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::"); + string_append (&temp, "::"); if (work -> destructor & 1) { string_append (&temp, "~"); @@ -1872,7 +2379,7 @@ demangle_qualified (work, mangled, result, isfuncname, append) { if (!STRING_EMPTY (result)) { - string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::"); + string_append (&temp, "::"); } string_prepends (result, &temp); } @@ -1949,7 +2456,9 @@ do_type (work, mangled, result) const char *remembered_type; int constp; int volatilep; + string btype; + string_init (&btype); string_init (&decl); string_init (result); @@ -1965,7 +2474,6 @@ do_type (work, mangled, result) case 'P': case 'p': (*mangled)++; - if (! (work -> options & DMGL_JAVA)) string_prepend (&decl, "*"); break; @@ -2048,7 +2556,7 @@ do_type (work, mangled, result) } string_append (&decl, ")"); - string_prepend (&decl, (work -> options & DMGL_JAVA) ? "." : "::"); + string_prepend (&decl, "::"); if (isdigit (**mangled)) { n = consume_count (mangled); @@ -2064,7 +2572,7 @@ do_type (work, mangled, result) { string temp; string_init (&temp); - success = demangle_template (work, mangled, &temp, NULL); + success = demangle_template (work, mangled, &temp, NULL, 1); if (success) { string_prependn (&decl, temp.b, temp.p - temp.b); @@ -2149,9 +2657,56 @@ do_type (work, mangled, result) { /* A qualified name, such as "Outer::Inner". */ case 'Q': - success = demangle_qualified (work, mangled, result, 0, 1); + case 'K': + { + int btype = register_Btype (work); + success = demangle_qualified (work, mangled, result, 0, 1); + remember_Btype (work, result->b, LEN_STRING (result), btype); + + break; + } + + /* A back reference to a previously seen squangled type */ + case 'B': + (*mangled)++; + if (!get_count (mangled, &n) || n >= work -> numb) + success = 0; + else + { + string_append (result, work->btypevec[n]); + } break; + case 'X': + case 'Y': + /* A template parm. We substitute the corresponding argument. */ + { + 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) + { + success = 0; + break; + } + + if (work->tmpl_argvec) + string_append (result, work->tmpl_argvec[idx]); + else + { + char buf[10]; + sprintf(buf, "T%d", idx); + string_append (result, buf); + } + + success = 1; + } + break; + default: success = demangle_fund_type (work, mangled, result); break; @@ -2194,6 +2749,8 @@ demangle_fund_type (work, mangled, result) { int done = 0; int success = 1; + string btype; + string_init (&btype); /* First pick off any type qualifiers. There can be more than one. */ @@ -2230,7 +2787,7 @@ demangle_fund_type (work, mangled, result) case 'J': (*mangled)++; APPEND_BLANK (result); - string_append (result, "complex"); + string_append (result, "__complex"); break; default: done = 1; @@ -2319,15 +2876,28 @@ demangle_fund_type (work, mangled, result) case '7': case '8': case '9': - APPEND_BLANK (result); - if (!demangle_class_name (work, mangled, result)) { - --result->p; - success = 0; + { + int bindex = register_Btype (work); + string btype; + string_init (&btype); + if (demangle_class_name (work, mangled, &btype)) { + remember_Btype (work, btype.b, LEN_STRING (&btype), bindex); + APPEND_BLANK (result); + string_appends (result, &btype); + } + else + success = 0; + string_delete (&btype); + break; } - break; case 't': - success = demangle_template(work,mangled, result, 0); - break; + { + int bindex= register_Btype (work); + success = demangle_template (work, mangled, &btype, 0, 1); + remember_Btype (work, btype.b, LEN_STRING (&btype), bindex); + string_appends (result, &btype); + break; + } default: success = 0; break; @@ -2387,6 +2957,112 @@ remember_type (work, start, len) work -> typevec[work -> ntypes++] = tem; } + +/* Remember a K type class qualifier. */ +static void +remember_Ktype (work, start, len) + struct work_stuff *work; + const char *start; + int len; +{ + char *tem; + + if (work -> numk >= work -> ksize) + { + if (work -> ksize == 0) + { + work -> ksize = 5; + work -> ktypevec + = (char **) xmalloc (sizeof (char *) * work -> ksize); + } + else + { + work -> ksize *= 2; + work -> ktypevec + = (char **) xrealloc ((char *)work -> ktypevec, + sizeof (char *) * work -> ksize); + } + } + tem = xmalloc (len + 1); + memcpy (tem, start, len); + tem[len] = '\0'; + work -> ktypevec[work -> numk++] = tem; +} + +/* Register a B code, and get an index for it. B codes are registered + as they are seen, rather than as they are completed, so map<temp<char> > + registers map<temp<char> > as B0, and temp<char> as B1 */ + +static int +register_Btype (work) + struct work_stuff *work; +{ + int ret; + + if (work -> numb >= work -> bsize) + { + if (work -> bsize == 0) + { + work -> bsize = 5; + work -> btypevec + = (char **) xmalloc (sizeof (char *) * work -> bsize); + } + else + { + work -> bsize *= 2; + work -> btypevec + = (char **) xrealloc ((char *)work -> btypevec, + sizeof (char *) * work -> bsize); + } + } + ret = work -> numb++; + work -> btypevec[ret] = NULL; + return(ret); +} + +/* 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; +{ + char *tem; + + tem = xmalloc (len + 1); + memcpy (tem, start, len); + tem[len] = '\0'; + work -> btypevec[index] = tem; +} + +/* Lose all the info related to B and K type codes. */ +static void +forget_B_and_K_types (work) + struct work_stuff *work; +{ + int i; + + while (work -> numk > 0) + { + i = --(work -> numk); + if (work -> ktypevec[i] != NULL) + { + free (work -> ktypevec[i]); + work -> ktypevec[i] = NULL; + } + } + + while (work -> numb > 0) + { + i = --(work -> numb); + if (work -> btypevec[i] != NULL) + { + free (work -> btypevec[i]); + work -> btypevec[i] = NULL; + } + } +} /* Forget the remembered types, but not the type vector itself. */ static void @@ -2582,8 +3258,7 @@ demangle_function_name (work, mangled, declp, scan) string *declp; const char *scan; { - int i; - int len; + size_t i; string type; const char *tem; @@ -2630,7 +3305,7 @@ demangle_function_name (work, mangled, declp, scan) { for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { - len = declp->p - declp->b - 10; + int len = declp->p - declp->b - 10; if (strlen (optable[i].in) == len && memcmp (optable[i].in, declp->b + 10, len) == 0) { @@ -2934,12 +3609,20 @@ 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."); +} + int main (argc, argv) int argc; @@ -2970,9 +3653,6 @@ main (argc, argv) case '_': strip_underscore = 1; break; - case 'j': - flags |= DMGL_JAVA; - break; case 's': if (strcmp (optarg, "gnu") == 0) { |