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.c443
1 files changed, 261 insertions, 182 deletions
diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index 14ef56a..52249d2 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -51,6 +51,14 @@ char * realloc ();
#include "libiberty.h"
+#define min(X,Y) (((X) < (Y)) ? (X) : (Y))
+
+/* A value at least one greater than the maximum number of characters
+ that will be output when using the `%d' format with `printf'. */
+#define INTBUF_SIZE 32
+
+extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
+
static const char *mystrstr PARAMS ((const char *, const char *));
static const char *
@@ -343,6 +351,9 @@ string_prepend PARAMS ((string *, const char *));
static void
string_prependn PARAMS ((string *, const char *, int));
+static void
+string_append_template_idx PARAMS ((string *, int));
+
static int
get_count PARAMS ((const char **, int *));
@@ -420,6 +431,25 @@ qualifier_string PARAMS ((int));
static const char*
demangle_qualifier PARAMS ((int));
+static int
+demangle_expression PARAMS ((struct work_stuff *, const char **, string *,
+ type_kind_t));
+
+static int
+demangle_integral_value PARAMS ((struct work_stuff *, const char **,
+ string *));
+
+static int
+demangle_real_value PARAMS ((struct work_stuff *, const char **, string *));
+
+static void
+demangle_arm_hp_template PARAMS ((struct work_stuff *, const char **, int,
+ string *));
+
+static void
+recursively_demangle PARAMS ((struct work_stuff *, const char **, string *,
+ int));
+
/* Translate count to integer, consuming tokens in the process.
Conversion terminates on the first non-digit character.
@@ -1326,87 +1356,155 @@ demangle_template_template_parm (work, mangled, tname)
}
static int
-demangle_integral_value (work, mangled, s)
+demangle_expression (work, mangled, s, tk)
struct work_stuff *work;
const char** mangled;
string* s;
+ type_kind_t tk;
{
+ int need_operator = 0;
int success;
- if (**mangled == 'E')
+ success = 1;
+ string_appendn (s, "(", 1);
+ (*mangled)++;
+ while (success && **mangled != 'W' && **mangled != '\0')
{
- int need_operator = 0;
-
- success = 1;
- string_appendn (s, "(", 1);
- (*mangled)++;
- while (success && **mangled != 'W' && **mangled != '\0')
+ if (need_operator)
{
- if (need_operator)
- {
- size_t i;
- size_t len;
+ size_t i;
+ size_t len;
- success = 0;
+ success = 0;
- len = strlen (*mangled);
+ len = strlen (*mangled);
- for (i = 0;
- i < sizeof (optable) / sizeof (optable [0]);
- ++i)
- {
- size_t l = strlen (optable[i].in);
+ for (i = 0;
+ i < 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 (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,
- tk_integral);
+ if (!success)
+ break;
}
-
- if (**mangled != 'W')
- success = 0;
else
- {
- string_appendn (s, ")", 1);
- (*mangled)++;
- }
+ need_operator = 1;
+
+ success = demangle_template_value_parm (work, mangled, s, tk);
}
+
+ if (**mangled != 'W')
+ success = 0;
+ else
+ {
+ string_appendn (s, ")", 1);
+ (*mangled)++;
+ }
+
+ return success;
+}
+
+static int
+demangle_integral_value (work, mangled, s)
+ struct work_stuff *work;
+ const char** mangled;
+ string* s;
+{
+ int success;
+
+ if (**mangled == 'E')
+ success = demangle_expression (work, mangled, s, tk_integral);
else if (**mangled == 'Q' || **mangled == 'K')
success = demangle_qualified (work, mangled, s, 0, 1);
else
{
+ int value;
+
success = 0;
+ /* Negative numbers are indicated with a leading `m'. */
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
+
+ /* Read the rest of the number. */
+ value = consume_count_with_underscores (mangled);
+ if (value != -1)
+ {
+ char buf[INTBUF_SIZE];
+ sprintf (buf, "%d", value);
+ string_append (s, buf);
+
+ /* If the next character is an underscore, skip it. */
+ if (**mangled == '_')
+ (*mangled)++;
+
+ /* All is well. */
+ success = 1;
+ }
+ }
+
+ return success;
+}
+
+/* Demangle the real value in MANGLED. */
+
+static int
+demangle_real_value (work, mangled, s)
+ struct work_stuff *work;
+ const char **mangled;
+ string* s;
+{
+ if (**mangled == 'E')
+ return demangle_expression (work, mangled, s, tk_real);
+
+ if (**mangled == 'm')
+ {
+ string_appendn (s, "-", 1);
+ (*mangled)++;
+ }
+ while (isdigit ((unsigned char)**mangled))
+ {
+ string_appendn (s, *mangled, 1);
+ (*mangled)++;
+ }
+ if (**mangled == '.') /* fraction */
+ {
+ string_appendn (s, ".", 1);
+ (*mangled)++;
+ while (isdigit ((unsigned char)**mangled))
+ {
+ string_appendn (s, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ if (**mangled == 'e') /* exponent */
+ {
+ string_appendn (s, "e", 1);
+ (*mangled)++;
while (isdigit ((unsigned char)**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
- success = 1;
}
}
- return success;
+ return 1;
}
static int
@@ -1432,11 +1530,7 @@ demangle_template_value_parm (work, mangled, s, tk)
if (work->tmpl_argvec)
string_append (s, work->tmpl_argvec[idx]);
else
- {
- char buf[10];
- sprintf(buf, "T%d", idx);
- string_append (s, buf);
- }
+ string_append_template_idx (s, idx);
}
else if (tk == tk_integral)
success = demangle_integral_value (work, mangled, s);
@@ -1472,70 +1566,46 @@ demangle_template_value_parm (work, mangled, s, tk)
success = 0;
}
else if (tk == tk_real)
- {
- if (**mangled == 'm')
- {
- string_appendn (s, "-", 1);
- (*mangled)++;
- }
- while (isdigit ((unsigned char)**mangled))
- {
- string_appendn (s, *mangled, 1);
- (*mangled)++;
- }
- if (**mangled == '.') /* fraction */
- {
- string_appendn (s, ".", 1);
- (*mangled)++;
- while (isdigit ((unsigned char)**mangled))
- {
- string_appendn (s, *mangled, 1);
- (*mangled)++;
- }
- }
- if (**mangled == 'e') /* exponent */
- {
- string_appendn (s, "e", 1);
- (*mangled)++;
- while (isdigit ((unsigned char)**mangled))
- {
- string_appendn (s, *mangled, 1);
- (*mangled)++;
- }
- }
- }
+ success = demangle_real_value (work, mangled, s);
else if (tk == tk_pointer || tk == tk_reference)
{
- int symbol_len = consume_count (mangled);
- if (symbol_len == -1)
- return -1;
- if (symbol_len == 0)
- string_appendn (s, "0", 1);
+ if (**mangled == 'Q')
+ success = demangle_qualified (work, mangled, s,
+ /*isfuncname=*/0,
+ /*append=*/1);
else
{
- char *p = xmalloc (symbol_len + 1), *q;
- strncpy (p, *mangled, symbol_len);
- p [symbol_len] = '\0';
- /* We use cplus_demangle here, rather than
- internal_cplus_demangle, because the name of the entity
- mangled here does not make use of any of the squangling
- or type-code information we have built up thus far; it is
- mangled independently. */
- q = cplus_demangle (p, work->options);
- if (tk == tk_pointer)
- string_appendn (s, "&", 1);
- /* FIXME: Pointer-to-member constants should get a
- qualifying class name here. */
- if (q)
+ int symbol_len = consume_count (mangled);
+ if (symbol_len == -1)
+ return -1;
+ if (symbol_len == 0)
+ string_appendn (s, "0", 1);
+ else
{
- string_append (s, q);
- free (q);
+ char *p = xmalloc (symbol_len + 1), *q;
+ strncpy (p, *mangled, symbol_len);
+ p [symbol_len] = '\0';
+ /* We use cplus_demangle here, rather than
+ internal_cplus_demangle, because the name of the entity
+ mangled here does not make use of any of the squangling
+ or type-code information we have built up thus far; it is
+ mangled independently. */
+ q = cplus_demangle (p, work->options);
+ if (tk == tk_pointer)
+ string_appendn (s, "&", 1);
+ /* FIXME: Pointer-to-member constants should get a
+ qualifying class name here. */
+ if (q)
+ {
+ string_append (s, q);
+ free (q);
+ }
+ else
+ string_append (s, p);
+ free (p);
}
- else
- string_append (s, p);
- free (p);
+ *mangled += symbol_len;
}
- *mangled += symbol_len;
}
return success;
@@ -1594,11 +1664,9 @@ demangle_template (work, mangled, tname, trawname, is_type, remember)
}
else
{
- char buf[10];
- sprintf(buf, "T%d", idx);
- string_append (tname, buf);
+ string_append_template_idx (tname, idx);
if (trawname)
- string_append (trawname, buf);
+ string_append_template_idx (trawname, idx);
}
}
else
@@ -2439,7 +2507,7 @@ gnu_special (work, mangled, declp)
break;
default:
n = consume_count (mangled);
- if (n < 0 || n > strlen (*mangled))
+ if (n < 0 || n > (long) strlen (*mangled))
{
success = 0;
break;
@@ -2606,7 +2674,7 @@ arm_special (mangled, declp)
{
n = consume_count (mangled);
if (n == -1
- || n > strlen (*mangled))
+ || n > (long) strlen (*mangled))
return 0;
string_prependn (declp, *mangled, n);
(*mangled) += n;
@@ -2667,7 +2735,6 @@ demangle_qualified (work, mangled, result, isfuncname, append)
{
int qualifiers = 0;
int success = 1;
- const char *p;
char num[2];
string temp;
string last_name;
@@ -2699,19 +2766,10 @@ demangle_qualified (work, mangled, result, isfuncname, append)
/* GNU mangled name with more than 9 classes. The count is preceded
by an underscore (to distinguish it from the <= 9 case) and followed
by an underscore. */
- p = *mangled + 2;
- qualifiers = atoi (p);
- if (!isdigit ((unsigned char)*p) || *p == '0')
- success = 0;
-
- /* Skip the digits. */
- while (isdigit ((unsigned char)*p))
- ++p;
-
- if (*p != '_')
+ (*mangled)++;
+ qualifiers = consume_count_with_underscores (mangled);
+ if (qualifiers == -1)
success = 0;
-
- *mangled = p + 1;
break;
case '1':
@@ -2902,9 +2960,7 @@ get_count (type, count)
int n;
if (!isdigit ((unsigned char)**type))
- {
- return (0);
- }
+ return (0);
else
{
*count = **type - '0';
@@ -3041,14 +3097,14 @@ do_type (work, mangled, result)
member = **mangled == 'M';
(*mangled)++;
- if (!isdigit ((unsigned char)**mangled) && **mangled != 't')
- {
- success = 0;
- break;
- }
string_append (&decl, ")");
- string_prepend (&decl, SCOPE_STRING (work));
+
+ /* We don't need to prepend `::' for a qualified name;
+ demangle_qualified will do that for us. */
+ if (**mangled != 'Q')
+ string_prepend (&decl, SCOPE_STRING (work));
+
if (isdigit ((unsigned char)**mangled))
{
n = consume_count (mangled);
@@ -3061,7 +3117,13 @@ do_type (work, mangled, result)
string_prependn (&decl, *mangled, n);
*mangled += n;
}
- else
+ else if (**mangled == 'X' || **mangled == 'Y')
+ {
+ string temp;
+ do_type (work, mangled, &temp);
+ string_prepends (&decl, &temp);
+ }
+ else if (**mangled == 't')
{
string temp;
string_init (&temp);
@@ -3075,6 +3137,20 @@ do_type (work, mangled, result)
else
break;
}
+ else if (**mangled == 'Q')
+ {
+ success = demangle_qualified (work, mangled, &decl,
+ /*isfuncnam=*/0,
+ /*append=*/0);
+ if (!success)
+ break;
+ }
+ else
+ {
+ success = 0;
+ break;
+ }
+
string_prepend (&decl, "(");
if (member)
{
@@ -3181,11 +3257,7 @@ do_type (work, mangled, result)
if (work->tmpl_argvec)
string_append (result, work->tmpl_argvec[idx]);
else
- {
- char buf[10];
- sprintf(buf, "T%d", idx);
- string_append (result, buf);
- }
+ string_append_template_idx (result, idx);
success = 1;
}
@@ -3359,14 +3431,14 @@ demangle_fund_type (work, mangled, result)
break;
}
case 'I':
- ++(*mangled);
+ (*mangled)++;
if (**mangled == '_')
{
int i;
- ++(*mangled);
+ (*mangled)++;
for (i = 0;
- (i < sizeof (buf) - 1 && **mangled && **mangled != '_');
- ++(*mangled), ++i)
+ i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
+ (*mangled)++, i++)
buf[i] = **mangled;
if (**mangled != '_')
{
@@ -3374,13 +3446,13 @@ demangle_fund_type (work, mangled, result)
break;
}
buf[i] = '\0';
- ++(*mangled);
+ (*mangled)++;
}
else
{
strncpy (buf, *mangled, 2);
buf[2] = '\0';
- *mangled += 2;
+ *mangled += min (strlen (*mangled), 2);
}
sscanf (buf, "%x", &dec);
sprintf (buf, "int%i_t", dec);
@@ -3434,7 +3506,7 @@ demangle_fund_type (work, mangled, result)
static int
do_hpacc_template_const_value (work, mangled, result)
- struct work_stuff *work;
+ struct work_stuff *work ATTRIBUTE_UNUSED;
const char **mangled;
string *result;
{
@@ -4304,6 +4376,16 @@ string_prependn (p, s, n)
}
}
+static void
+string_append_template_idx (s, idx)
+ string *s;
+ int idx;
+{
+ char buf[INTBUF_SIZE + 1 /* 'T' */];
+ sprintf(buf, "T%d", idx);
+ string_append (s, buf);
+}
+
/* To generate a standalone demangler program for testing purposes,
just compile and link this file with -DMAIN and libiberty.a. When
run, it demangles each command line arg, or each stdin string, and
@@ -4313,13 +4395,13 @@ string_prependn (p, s, n)
#include "getopt.h"
-static char *program_name;
-static char *program_version = VERSION;
+static const char *program_name;
+static const char *program_version = VERSION;
static int flags = DMGL_PARAMS | DMGL_ANSI;
static void demangle_it PARAMS ((char *));
-static void usage PARAMS ((FILE *, int));
-static void fatal PARAMS ((char *));
+static void usage PARAMS ((FILE *, int)) ATTRIBUTE_NORETURN;
+static void fatal PARAMS ((const char *)) ATTRIBUTE_NORETURN;
static void
demangle_it (mangled_name)
@@ -4380,25 +4462,25 @@ fancy_abort ()
}
-/* Fill in TABLE so that TABLE[C] is true iff C (as an unsigned char)
- is a valid symbol component, in the standard assembler symbol
- syntax. */
-void
-standard_symbol_alphabet (char *table)
-{
- int c;
+static const char *
+standard_symbol_characters PARAMS ((void));
+
+static const char *
+hp_symbol_characters PARAMS ((void));
- for (c = 0; c < 256; c++)
- table[c] = isalnum(c);
+/* Return the string of non-alnum characters that may occur
+ as a valid symbol component, in the standard assembler symbol
+ syntax. */
- table['_'] = 1;
- table['$'] = 1;
- table['.'] = 1;
+static const char *
+standard_symbol_characters ()
+{
+ return "_$.";
}
-/* Fill in TABLE so that TABLE[C] is true iff C (as an unsigned char)
- is a valid symbol name component in an HP object file.
+/* Return the string of non-alnum characters that may occur
+ as a valid symbol name component in an HP object file.
Note that, since HP's compiler generates object code straight from
C++ source, without going through an assembler, its mangled
@@ -4427,18 +4509,15 @@ standard_symbol_alphabet (char *table)
non-digit character.
So have fun. */
-void
-hp_symbol_alphabet (char *table)
+static const char *
+hp_symbol_characters ()
{
- char *c;
-
- standard_symbol_alphabet (table);
-
- for (c = "<>#,*&[]:(){}"; *c; c++)
- table[(unsigned char) *c] = 1;
+ return "_$.<>#,*&[]:(){}";
}
+extern int main PARAMS ((int, char **));
+
int
main (argc, argv)
int argc;
@@ -4446,7 +4525,7 @@ main (argc, argv)
{
char *result;
int c;
- char symbol_alphabet[256];
+ const char *valid_symbols;
program_name = argv[0];
@@ -4466,7 +4545,7 @@ main (argc, argv)
break;
case 'v':
printf ("GNU %s (C++ demangler), version %s\n", program_name, program_version);
- exit (0);
+ return (0);
case '_':
strip_underscore = 1;
break;
@@ -4498,7 +4577,7 @@ main (argc, argv)
{
fprintf (stderr, "%s: unknown demangling style `%s'\n",
program_name, optarg);
- exit (1);
+ return (1);
}
break;
}
@@ -4519,10 +4598,10 @@ main (argc, argv)
case lucid_demangling:
case arm_demangling:
case edg_demangling:
- standard_symbol_alphabet (symbol_alphabet);
+ valid_symbols = standard_symbol_characters ();
break;
case hp_demangling:
- hp_symbol_alphabet (symbol_alphabet);
+ valid_symbols = hp_symbol_characters ();
break;
default:
/* Folks should explicitly indicate the appropriate alphabet for
@@ -4536,7 +4615,7 @@ main (argc, argv)
int i = 0;
c = getchar ();
/* Try to read a label. */
- while (c != EOF && symbol_alphabet[c])
+ while (c != EOF && (isalnum (c) || strchr (valid_symbols, c)))
{
if (i >= MBUF_SIZE-1)
break;
@@ -4576,12 +4655,12 @@ main (argc, argv)
}
}
- exit (0);
+ return (0);
}
static void
fatal (str)
- char *str;
+ const char *str;
{
fprintf (stderr, "%s: %s\n", program_name, str);
exit (1);