diff options
Diffstat (limited to 'contrib/binutils/libiberty/cplus-dem.c')
-rw-r--r-- | contrib/binutils/libiberty/cplus-dem.c | 384 |
1 files changed, 307 insertions, 77 deletions
diff --git a/contrib/binutils/libiberty/cplus-dem.c b/contrib/binutils/libiberty/cplus-dem.c index 9579021aa9b3..f4d71238c400 100644 --- a/contrib/binutils/libiberty/cplus-dem.c +++ b/contrib/binutils/libiberty/cplus-dem.c @@ -102,6 +102,8 @@ struct work_stuff 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) @@ -222,7 +224,7 @@ demangle_method_args 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 **, @@ -294,6 +296,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 *)); @@ -336,6 +341,42 @@ consume_count (type) return (count); } + +/* Like consume_count, but for counts that are preceeded 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; @@ -580,7 +621,17 @@ mop_up (work, declp, success) { free ((char *) work -> typevec); } - + 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); + } + /* If demangling was successful, ensure that the demangled string is null terminated and return it. Otherwise, free the demangling decl. */ @@ -635,6 +686,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; @@ -726,12 +778,12 @@ 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, "::"); + string_append(&tname, (work -> options & DMGL_JAVA) ? "." : "::"); string_prepends(declp, &tname); if (work -> destructor & 1) { @@ -751,14 +803,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 +866,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,11 +923,12 @@ demangle_method_args (work, mangled, declp) #endif static int -demangle_template (work, mangled, tname, trawname) +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; @@ -857,25 +943,43 @@ demangle_template (work, mangled, tname, trawname) const char *old_p; const char *start; int symbol_len; + int is_java_array = 0; string temp; (*mangled)++; - start = *mangled; - /* get template name */ - if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r) + if (is_type) { - return (0); + start = *mangled; + /* get template name */ + if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r) + { + 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); + } + *mangled += r; } - if (trawname) - string_appendn (trawname, *mangled, r); - string_appendn (tname, *mangled, r); - *mangled += r; - string_append (tname, "<"); + if (!is_java_array) + string_append (tname, "<"); /* get size of template parameter list */ if (!get_count (mangled, &r)) { return (0); } + if (!is_type) + { + /* Create an array for saving the template argument values. */ + work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *)); + work->ntmpl_args = r; + for (i = 0; i < r; i++) + work->tmpl_argvec[i] = 0; + } for (i = 0; i < r; i++) { if (need_comma) @@ -891,6 +995,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) @@ -900,6 +1013,9 @@ demangle_template (work, mangled, tname, trawname) } else { + string param; + string* s; + /* otherwise, value parameter */ old_p = *mangled; is_pointer = 0; @@ -913,7 +1029,7 @@ demangle_template (work, mangled, tname, trawname) /* if (success) { - string_appends (tname, &temp); + string_appends (s, &temp); } */ string_delete(&temp); @@ -922,8 +1038,17 @@ demangle_template (work, mangled, tname, trawname) break; } /* - string_append (tname, "="); + string_append (s, "="); */ + + if (!is_type) + { + s = ¶m; + string_init (s); + } + else + s = tname; + while (*old_p && !done) { switch (*old_p) @@ -940,6 +1065,7 @@ demangle_template (work, mangled, tname, trawname) case 'F': /* function */ case 'M': /* member function */ case 'O': /* ??? */ + case 'J': /* complex */ old_p++; continue; case 'Q': /* qualified name */ @@ -976,16 +1102,41 @@ demangle_template (work, mangled, tname, trawname) done = is_integral = 1; } } - if (is_integral) + 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) + { + success = 0; + if (!is_type) + string_delete (s); + break; + } + 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) { if (**mangled == 'm') { - string_appendn (tname, "-", 1); + string_appendn (s, "-", 1); (*mangled)++; } while (isdigit (**mangled)) { - string_appendn (tname, *mangled, 1); + string_appendn (s, *mangled, 1); (*mangled)++; } } @@ -995,28 +1146,30 @@ demangle_template (work, mangled, tname, trawname) int val; if (**mangled == 'm') { - string_appendn (tname, "-", 1); + string_appendn (s, "-", 1); (*mangled)++; } - string_appendn (tname, "'", 1); + string_appendn (s, "'", 1); val = consume_count(mangled); if (val == 0) { success = 0; + if (!is_type) + string_delete (s); break; } tmp[0] = (char)val; tmp[1] = '\0'; - string_appendn (tname, &tmp[0], 1); - string_appendn (tname, "'", 1); + string_appendn (s, &tmp[0], 1); + string_appendn (s, "'", 1); } else if (is_bool) { int val = consume_count (mangled); if (val == 0) - string_appendn (tname, "false", 5); + string_appendn (s, "false", 5); else if (val == 1) - string_appendn (tname, "true", 4); + string_appendn (s, "true", 4); else success = 0; } @@ -1024,31 +1177,31 @@ demangle_template (work, mangled, tname, trawname) { if (**mangled == 'm') { - string_appendn (tname, "-", 1); + string_appendn (s, "-", 1); (*mangled)++; } while (isdigit (**mangled)) { - string_appendn (tname, *mangled, 1); + string_appendn (s, *mangled, 1); (*mangled)++; } if (**mangled == '.') /* fraction */ { - string_appendn (tname, ".", 1); + string_appendn (s, ".", 1); (*mangled)++; while (isdigit (**mangled)) { - string_appendn (tname, *mangled, 1); + string_appendn (s, *mangled, 1); (*mangled)++; } } if (**mangled == 'e') /* exponent */ { - string_appendn (tname, "e", 1); + string_appendn (s, "e", 1); (*mangled)++; while (isdigit (**mangled)) { - string_appendn (tname, *mangled, 1); + string_appendn (s, *mangled, 1); (*mangled)++; } } @@ -1059,34 +1212,53 @@ demangle_template (work, mangled, tname, trawname) if (symbol_len == 0) { success = 0; + if (!is_type) + string_delete (s); break; } if (symbol_len == 0) - string_appendn (tname, "0", 1); + string_appendn (s, "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); + string_appendn (s, "&", 1); if (q) { - string_append (tname, q); + string_append (s, q); free (q); } else - string_append (tname, p); + string_append (s, p); free (p); } *mangled += symbol_len; } + if (!is_type) + { + 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 (tname->p[-1] == '>') - string_append (tname, " "); - string_append (tname, ">"); + if (is_java_array) + { + string_append (tname, "[]"); + } + else + { + if (tname->p[-1] == '>') + string_append (tname, " "); + string_append (tname, ">"); + } /* if (work -> static_type) @@ -1241,7 +1413,7 @@ demangle_class (work, mangled, declp) work -> constructor -= 1; } } - string_prepend (declp, "::"); + string_prepend (declp, (work -> options & DMGL_JAVA) ? "." : "::"); string_prepends (declp, &class_name); success = 1; } @@ -1362,8 +1534,9 @@ demangle_prefix (work, mangled, declp) success = 0; } } - else if ((scan == *mangled) && - (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't'))) + else if ((scan == *mangled) + && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't') + || (scan[2] == 'H'))) { /* The ARM says nothing about the mangling of local variables. But cfront mangles local variables by prepending __<nesting_level> @@ -1380,7 +1553,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; @@ -1512,12 +1686,21 @@ gnu_special (work, mangled, declp) 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 { @@ -1531,7 +1714,8 @@ gnu_special (work, mangled, declp) { if (p != NULL) { - string_append (declp, "::"); + string_append (declp, + (work -> options & DMGL_JAVA) ? "." : "::"); (*mangled)++; } } @@ -1556,7 +1740,7 @@ gnu_special (work, mangled, declp) 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); @@ -1568,7 +1752,7 @@ gnu_special (work, mangled, declp) /* Consumed everything up to the cplus_marker, append the variable name. */ (*mangled)++; - string_append (declp, "::"); + string_append (declp, (work -> options & DMGL_JAVA) ? "." : "::"); n = strlen (*mangled); string_appendn (declp, *mangled, n); (*mangled) += n; @@ -1608,7 +1792,7 @@ gnu_special (work, mangled, declp) 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); @@ -1810,7 +1994,12 @@ demangle_qualified (work, mangled, result, isfuncname, append) *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 @@ -1827,7 +2016,7 @@ demangle_qualified (work, mangled, result, isfuncname, append) } if (qualifiers > 0) { - string_appendn (&temp, "::", 2); + string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::"); } } @@ -1838,7 +2027,7 @@ demangle_qualified (work, mangled, result, isfuncname, append) if (isfuncname && (work->constructor & 1 || work->destructor & 1)) { - string_appendn (&temp, "::", 2); + string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::"); if (work -> destructor & 1) { string_append (&temp, "~"); @@ -1857,7 +2046,7 @@ demangle_qualified (work, mangled, result, isfuncname, append) { if (!STRING_EMPTY (result)) { - string_appendn (&temp, "::", 2); + string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::"); } string_prepends (result, &temp); } @@ -1950,7 +2139,8 @@ do_type (work, mangled, result) case 'P': case 'p': (*mangled)++; - string_prepend (&decl, "*"); + if (! (work -> options & DMGL_JAVA)) + string_prepend (&decl, "*"); break; /* A reference type */ @@ -2032,7 +2222,7 @@ do_type (work, mangled, result) } string_append (&decl, ")"); - string_prepend (&decl, "::"); + string_prepend (&decl, (work -> options & DMGL_JAVA) ? "." : "::"); if (isdigit (**mangled)) { n = consume_count (mangled); @@ -2048,7 +2238,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); @@ -2136,6 +2326,37 @@ do_type (work, mangled, result) success = demangle_qualified (work, mangled, result, 0, 1); break; + case 'X': + case 'Y': + /* A template parm. We substitute the corresponding argument. */ + { + int idx; + int lvl; + + (*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; @@ -2211,6 +2432,11 @@ demangle_fund_type (work, mangled, result) string_append (result, "volatile"); } break; + case 'J': + (*mangled)++; + APPEND_BLANK (result); + string_append (result, "__complex"); + break; default: done = 1; break; @@ -2305,7 +2531,7 @@ demangle_fund_type (work, mangled, result) } break; case 't': - success = demangle_template(work,mangled, result, 0); + success = demangle_template(work,mangled, result, 0, 1); break; default: success = 0; @@ -2349,15 +2575,15 @@ 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 + = (char **) xmalloc (sizeof (char *) * work -> typevec_size); } else { work -> typevec_size *= 2; - work -> typevec = - (char **) xrealloc ((char *)work -> typevec, - sizeof (char *) * work -> typevec_size); + work -> typevec + = (char **) xrealloc ((char *)work -> typevec, + sizeof (char *) * work -> typevec_size); } } tem = xmalloc (len + 1); @@ -2860,6 +3086,12 @@ string_prependn (p, s, n) #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 *)); @@ -2870,7 +3102,7 @@ demangle_it (mangled_name) { char *result; - result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI); + result = cplus_demangle (mangled_name, flags); if (result == NULL) { printf ("%s\n", mangled_name); @@ -2882,11 +3114,6 @@ demangle_it (mangled_name) } } -#include "getopt.h" - -static char *program_name; -static char *program_version = VERSION; - static void usage (stream, status) FILE *stream; @@ -2894,8 +3121,8 @@ usage (stream, status) { fprintf (stream, "\ Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\ -[--no-strip-underscores] [--format={gnu,lucid,arm}]\n\ -[--help] [--version] [arg...]\n", + [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\ + [--help] [--version] [arg...]\n", program_name); exit (status); } @@ -2912,6 +3139,7 @@ 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} @@ -2929,7 +3157,7 @@ main (argc, argv) strip_underscore = prepends_underscore; - while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF) + while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF) { switch (c) { @@ -2947,6 +3175,9 @@ main (argc, argv) case '_': strip_underscore = 1; break; + case 'j': + flags |= DMGL_JAVA; + break; case 's': if (strcmp (optarg, "gnu") == 0) { @@ -3005,8 +3236,7 @@ main (argc, argv) mbuffer[i] = 0; - result = cplus_demangle (mbuffer + skip_first, - DMGL_PARAMS | DMGL_ANSI); + result = cplus_demangle (mbuffer + skip_first, flags); if (result) { if (mbuffer[0] == '.') |