summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/libiberty/cplus-dem.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/binutils/libiberty/cplus-dem.c')
-rw-r--r--contrib/binutils/libiberty/cplus-dem.c384
1 files changed, 307 insertions, 77 deletions
diff --git a/contrib/binutils/libiberty/cplus-dem.c b/contrib/binutils/libiberty/cplus-dem.c
index 9579021..f4d7123 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 = &param;
+ 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] == '.')
OpenPOWER on IntegriCloud