aboutsummaryrefslogtreecommitdiff
path: root/libiberty/cplus-dem.c
diff options
context:
space:
mode:
Diffstat (limited to 'libiberty/cplus-dem.c')
-rw-r--r--libiberty/cplus-dem.c1186
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 = &param;
+ 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)
{