summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/libiberty/cp-demangle.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/binutils/libiberty/cp-demangle.c')
-rw-r--r--contrib/binutils/libiberty/cp-demangle.c348
1 files changed, 312 insertions, 36 deletions
diff --git a/contrib/binutils/libiberty/cp-demangle.c b/contrib/binutils/libiberty/cp-demangle.c
index 1cc4847..457a09f 100644
--- a/contrib/binutils/libiberty/cp-demangle.c
+++ b/contrib/binutils/libiberty/cp-demangle.c
@@ -1,5 +1,5 @@
/* Demangler for IA64 / g++ V3 ABI.
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Written by Alex Samuel <samuel@codesourcery.com>.
This file is part of GNU CC.
@@ -68,6 +68,9 @@
anonymous namespace. */
#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
+/* Character(s) to use for namespace separation in demangled output */
+#define NAMESPACE_SEPARATOR (dm->style == DMGL_JAVA ? "." : "::")
+
/* If flag_verbose is zero, some simplifications will be made to the
output to make it easier to read and supress details that are
generally not of interest to the average C++ programmer.
@@ -166,6 +169,18 @@ struct demangling_def
/* The most recently demangled source-name. */
dyn_string_t last_source_name;
+
+ /* Language style to use for demangled output. */
+ int style;
+
+ /* Set to non-zero iff this name is a constructor. The actual value
+ indicates what sort of constructor this is; see demangle.h. */
+ enum gnu_v3_ctor_kinds is_constructor;
+
+ /* Set to non-zero iff this name is a destructor. The actual value
+ indicates what sort of destructor this is; see demangle.h. */
+ enum gnu_v3_dtor_kinds is_destructor;
+
};
typedef struct demangling_def *demangling_t;
@@ -240,7 +255,7 @@ static void template_arg_list_print
static template_arg_list_t current_template_arg_list
PARAMS ((demangling_t));
static demangling_t demangling_new
- PARAMS ((const char *));
+ PARAMS ((const char *, int));
static void demangling_delete
PARAMS ((demangling_t));
@@ -409,7 +424,7 @@ string_list_delete (node)
while (node != NULL)
{
string_list_t next = node->next;
- free (node);
+ dyn_string_delete ((dyn_string_t) node);
node = next;
}
}
@@ -783,8 +798,9 @@ current_template_arg_list (dm)
Returns NULL if allocation fails. */
static demangling_t
-demangling_new (name)
+demangling_new (name, style)
const char *name;
+ int style;
{
demangling_t dm;
dm = (demangling_t) malloc (sizeof (struct demangling_def));
@@ -807,6 +823,9 @@ demangling_new (name)
dyn_string_delete (dm->last_source_name);
return NULL;
}
+ dm->style = style;
+ dm->is_constructor = 0;
+ dm->is_destructor = 0;
return dm;
}
@@ -918,7 +937,7 @@ static status_t demangle_local_name
static status_t demangle_discriminator
PARAMS ((demangling_t, int));
static status_t cp_demangle
- PARAMS ((const char *, dyn_string_t));
+ PARAMS ((const char *, dyn_string_t, int));
#ifdef IN_LIBGCC2
static status_t cp_demangle_type
PARAMS ((const char*, dyn_string_t));
@@ -1222,7 +1241,7 @@ demangle_prefix (dm, encode_return_type)
{
/* We have another level of scope qualification. */
if (nested)
- RETURN_IF_ERROR (result_add (dm, "::"));
+ RETURN_IF_ERROR (result_add (dm, NAMESPACE_SEPARATOR));
else
nested = 1;
@@ -1538,11 +1557,11 @@ demangle_operator_name (dm, short_name, num_args)
struct operator_code
{
/* The mangled code for this operator. */
- const char *code;
+ const char *const code;
/* The source name of this operator. */
- const char *name;
+ const char *const name;
/* The number of arguments this operator takes. */
- int num_args;
+ const int num_args;
};
static const struct operator_code operators[] =
@@ -1823,11 +1842,27 @@ demangle_special_name (dm)
if (peek == 'G')
{
- /* A guard variable name. Consume the G. */
+ /* Consume the G. */
advance_char (dm);
- RETURN_IF_ERROR (demangle_char (dm, 'V'));
- RETURN_IF_ERROR (result_add (dm, "guard variable for "));
- RETURN_IF_ERROR (demangle_name (dm, &unused));
+ switch (peek_char (dm))
+ {
+ case 'V':
+ /* A guard variable name. */
+ advance_char (dm);
+ RETURN_IF_ERROR (result_add (dm, "guard variable for "));
+ RETURN_IF_ERROR (demangle_name (dm, &unused));
+ break;
+
+ case 'R':
+ /* A reference temporary. */
+ advance_char (dm);
+ RETURN_IF_ERROR (result_add (dm, "reference temporary for "));
+ RETURN_IF_ERROR (demangle_name (dm, &unused));
+ break;
+
+ default:
+ return "Unrecognized <special-name>.";
+ }
}
else if (peek == 'T')
{
@@ -2010,15 +2045,24 @@ demangle_ctor_dtor_name (dm)
{
/* A constructor name. Consume the C. */
advance_char (dm);
- if (peek_char (dm) < '1' || peek_char (dm) > '3')
+ flavor = next_char (dm);
+ if (flavor < '1' || flavor > '3')
return "Unrecognized constructor.";
RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
+ switch (flavor)
+ {
+ case '1': dm->is_constructor = gnu_v3_complete_object_ctor;
+ break;
+ case '2': dm->is_constructor = gnu_v3_base_object_ctor;
+ break;
+ case '3': dm->is_constructor = gnu_v3_complete_object_allocating_ctor;
+ break;
+ }
/* Print the flavor of the constructor if in verbose mode. */
- flavor = next_char (dm) - '1';
if (flag_verbose)
{
RETURN_IF_ERROR (result_add (dm, "["));
- RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor]));
+ RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor - '1']));
RETURN_IF_ERROR (result_add_char (dm, ']'));
}
}
@@ -2026,16 +2070,25 @@ demangle_ctor_dtor_name (dm)
{
/* A destructor name. Consume the D. */
advance_char (dm);
- if (peek_char (dm) < '0' || peek_char (dm) > '2')
+ flavor = next_char (dm);
+ if (flavor < '0' || flavor > '2')
return "Unrecognized destructor.";
RETURN_IF_ERROR (result_add_char (dm, '~'));
RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
+ switch (flavor)
+ {
+ case '0': dm->is_destructor = gnu_v3_deleting_dtor;
+ break;
+ case '1': dm->is_destructor = gnu_v3_complete_object_dtor;
+ break;
+ case '2': dm->is_destructor = gnu_v3_base_object_dtor;
+ break;
+ }
/* Print the flavor of the destructor if in verbose mode. */
- flavor = next_char (dm) - '0';
if (flag_verbose)
{
RETURN_IF_ERROR (result_add (dm, " ["));
- RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor]));
+ RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor - '0']));
RETURN_IF_ERROR (result_add_char (dm, ']'));
}
}
@@ -2093,8 +2146,10 @@ demangle_type_ptr (dm, insert_pos, substitution_start)
RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
substitution_start));
/* Insert an asterisk where we're told to; it doesn't
- necessarily go at the end. */
- RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
+ necessarily go at the end. If we're doing Java style output,
+ there is no pointer symbol. */
+ if (dm->style != DMGL_JAVA)
+ RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
/* The next (outermost) pointer or reference character should go
after this one. */
++(*insert_pos);
@@ -2469,6 +2524,39 @@ static const char *const builtin_type_names[26] =
"..." /* z */
};
+/* Java source names of builtin types. Types that arn't valid in Java
+ are also included here - we don't fail if someone attempts to demangle a
+ C++ symbol in Java style. */
+static const char *const java_builtin_type_names[26] =
+{
+ "signed char", /* a */
+ "boolean", /* C++ "bool" */ /* b */
+ "byte", /* C++ "char" */ /* c */
+ "double", /* d */
+ "long double", /* e */
+ "float", /* f */
+ "__float128", /* g */
+ "unsigned char", /* h */
+ "int", /* i */
+ "unsigned", /* j */
+ NULL, /* k */
+ "long", /* l */
+ "unsigned long", /* m */
+ "__int128", /* n */
+ "unsigned __int128", /* o */
+ NULL, /* p */
+ NULL, /* q */
+ NULL, /* r */
+ "short", /* s */
+ "unsigned short", /* t */
+ NULL, /* u */
+ "void", /* v */
+ "char", /* C++ "wchar_t" */ /* w */
+ "long", /* C++ "long long" */ /* x */
+ "unsigned long long", /* y */
+ "..." /* z */
+};
+
/* Demangles and emits a <builtin-type>.
<builtin-type> ::= v # void
@@ -2511,7 +2599,12 @@ demangle_builtin_type (dm)
}
else if (code >= 'a' && code <= 'z')
{
- const char *type_name = builtin_type_names[code - 'a'];
+ const char *type_name;
+ /* Java uses different names for some built-in types. */
+ if (dm->style == DMGL_JAVA)
+ type_name = java_builtin_type_names[code - 'a'];
+ else
+ type_name = builtin_type_names[code - 'a'];
if (type_name == NULL)
return "Unrecognized <builtin-type> code.";
@@ -3369,15 +3462,11 @@ demangle_discriminator (dm, suppress_first)
/* Write the discriminator. The mangled number is two
less than the discriminator ordinal, counting from
zero. */
- RETURN_IF_ERROR (int_to_dyn_string (discriminator + 2,
+ RETURN_IF_ERROR (int_to_dyn_string (discriminator + 1,
(dyn_string_t) dm->result));
}
else
- {
- if (flag_verbose)
- /* A missing digit correspond to one. */
- RETURN_IF_ERROR (result_add_char (dm, '1'));
- }
+ return STATUS_ERROR;
if (flag_verbose)
RETURN_IF_ERROR (result_add_char (dm, ']'));
}
@@ -3395,16 +3484,17 @@ demangle_discriminator (dm, suppress_first)
an error message, and the contents of RESULT are unchanged. */
static status_t
-cp_demangle (name, result)
+cp_demangle (name, result, style)
const char *name;
dyn_string_t result;
+ int style;
{
status_t status;
int length = strlen (name);
if (length > 2 && name[0] == '_' && name[1] == 'Z')
{
- demangling_t dm = demangling_new (name);
+ demangling_t dm = demangling_new (name, style);
if (dm == NULL)
return STATUS_ALLOCATION_FAILED;
@@ -3551,7 +3641,7 @@ __cxa_demangle (mangled_name, output_buffer, length, status)
if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
/* MANGLED_NAME apprears to be a function or variable name.
Demangle it accordingly. */
- result = cp_demangle (mangled_name, &demangled_name);
+ result = cp_demangle (mangled_name, &demangled_name, 0);
else
/* Try to demangled MANGLED_NAME as the name of a type. */
result = cp_demangle_type (mangled_name, &demangled_name);
@@ -3610,7 +3700,7 @@ cplus_demangle_v3 (mangled)
/* Create a dyn_string to hold the demangled name. */
demangled = dyn_string_new (0);
/* Attempt the demangling. */
- status = cp_demangle ((char *) mangled, demangled);
+ status = cp_demangle ((char *) mangled, demangled, 0);
if (STATUS_NO_ERROR (status))
/* Demangling succeeded. */
@@ -3634,8 +3724,194 @@ cplus_demangle_v3 (mangled)
}
}
+/* Demangle a Java symbol. Java uses a subset of the V3 ABI C++ mangling
+ conventions, but the output formatting is a little different.
+ This instructs the C++ demangler not to emit pointer characters ("*"), and
+ to use Java's namespace separator symbol ("." instead of "::"). It then
+ does an additional pass over the demangled output to replace instances
+ of JArray<TYPE> with TYPE[]. */
+
+char *
+java_demangle_v3 (mangled)
+ const char* mangled;
+{
+ dyn_string_t demangled;
+ char *next;
+ char *end;
+ int len;
+ status_t status;
+ int nesting = 0;
+ char *cplus_demangled;
+ char *return_value;
+
+ /* Create a dyn_string to hold the demangled name. */
+ demangled = dyn_string_new (0);
+
+ /* Attempt the demangling. */
+ status = cp_demangle ((char *) mangled, demangled, DMGL_JAVA);
+
+ if (STATUS_NO_ERROR (status))
+ /* Demangling succeeded. */
+ {
+ /* Grab the demangled result from the dyn_string. */
+ cplus_demangled = dyn_string_release (demangled);
+ }
+ else if (status == STATUS_ALLOCATION_FAILED)
+ {
+ fprintf (stderr, "Memory allocation failed.\n");
+ abort ();
+ }
+ else
+ /* Demangling failed. */
+ {
+ dyn_string_delete (demangled);
+ return NULL;
+ }
+
+ len = strlen (cplus_demangled);
+ next = cplus_demangled;
+ end = next + len;
+ demangled = NULL;
+
+ /* Replace occurances of JArray<TYPE> with TYPE[]. */
+ while (next < end)
+ {
+ char *open_str = strstr (next, "JArray<");
+ char *close_str = NULL;
+ if (nesting > 0)
+ close_str = strchr (next, '>');
+
+ if (open_str != NULL && (close_str == NULL || close_str > open_str))
+ {
+ ++nesting;
+
+ if (!demangled)
+ demangled = dyn_string_new(len);
+
+ /* Copy prepending symbols, if any. */
+ if (open_str > next)
+ {
+ open_str[0] = 0;
+ dyn_string_append_cstr (demangled, next);
+ }
+ next = open_str + 7;
+ }
+ else if (close_str != NULL)
+ {
+ --nesting;
+
+ /* Copy prepending type symbol, if any. Squash any spurious
+ whitespace. */
+ if (close_str > next && next[0] != ' ')
+ {
+ close_str[0] = 0;
+ dyn_string_append_cstr (demangled, next);
+ }
+ dyn_string_append_cstr (demangled, "[]");
+ next = close_str + 1;
+ }
+ else
+ {
+ /* There are no more arrays. Copy the rest of the symbol, or
+ simply return the original symbol if no changes were made. */
+ if (next == cplus_demangled)
+ return cplus_demangled;
+
+ dyn_string_append_cstr (demangled, next);
+ next = end;
+ }
+ }
+
+ free (cplus_demangled);
+
+ return_value = dyn_string_release (demangled);
+ return return_value;
+}
+
#endif /* IN_LIBGCC2 */
+
+/* Demangle NAME in the G++ V3 ABI demangling style, and return either
+ zero, indicating that some error occurred, or a demangling_t
+ holding the results. */
+static demangling_t
+demangle_v3_with_details (name)
+ const char *name;
+{
+ demangling_t dm;
+ status_t status;
+
+ if (strncmp (name, "_Z", 2))
+ return 0;
+
+ dm = demangling_new (name, DMGL_GNU_V3);
+ if (dm == NULL)
+ {
+ fprintf (stderr, "Memory allocation failed.\n");
+ abort ();
+ }
+
+ status = result_push (dm);
+ if (! STATUS_NO_ERROR (status))
+ {
+ demangling_delete (dm);
+ fprintf (stderr, "%s\n", status);
+ abort ();
+ }
+
+ status = demangle_mangled_name (dm);
+ if (STATUS_NO_ERROR (status))
+ return dm;
+
+ demangling_delete (dm);
+ return 0;
+}
+
+
+/* Return non-zero iff NAME is the mangled form of a constructor name
+ in the G++ V3 ABI demangling style. Specifically, return:
+ - '1' if NAME is a complete object constructor,
+ - '2' if NAME is a base object constructor, or
+ - '3' if NAME is a complete object allocating constructor. */
+enum gnu_v3_ctor_kinds
+is_gnu_v3_mangled_ctor (name)
+ const char *name;
+{
+ demangling_t dm = demangle_v3_with_details (name);
+
+ if (dm)
+ {
+ enum gnu_v3_ctor_kinds result = dm->is_constructor;
+ demangling_delete (dm);
+ return result;
+ }
+ else
+ return 0;
+}
+
+
+/* Return non-zero iff NAME is the mangled form of a destructor name
+ in the G++ V3 ABI demangling style. Specifically, return:
+ - '0' if NAME is a deleting destructor,
+ - '1' if NAME is a complete object destructor, or
+ - '2' if NAME is a base object destructor. */
+enum gnu_v3_dtor_kinds
+is_gnu_v3_mangled_dtor (name)
+ const char *name;
+{
+ demangling_t dm = demangle_v3_with_details (name);
+
+ if (dm)
+ {
+ enum gnu_v3_dtor_kinds result = dm->is_destructor;
+ demangling_delete (dm);
+ return result;
+ }
+ else
+ return 0;
+}
+
+
#ifdef STANDALONE_DEMANGLER
#include "getopt.h"
@@ -3669,7 +3945,7 @@ print_usage (fp, exit_value)
}
/* Option specification for getopt_long. */
-static struct option long_options[] =
+static const struct option long_options[] =
{
{ "help", no_argument, NULL, 'h' },
{ "strict", no_argument, NULL, 's' },
@@ -3771,7 +4047,7 @@ main (argc, argv)
}
/* Attempt to demangle the name. */
- status = cp_demangle (dyn_string_buf (mangled), demangled);
+ status = cp_demangle (dyn_string_buf (mangled), demangled, 0);
/* If the demangling succeeded, great! Print out the
demangled version. */
@@ -3810,7 +4086,7 @@ main (argc, argv)
for (i = optind; i < argc; ++i)
{
/* Attempt to demangle. */
- status = cp_demangle (argv[i], result);
+ status = cp_demangle (argv[i], result, 0);
/* If it worked, print the demangled name. */
if (STATUS_NO_ERROR (status))
@@ -3818,7 +4094,7 @@ main (argc, argv)
/* Abort on allocaiton failures. */
else if (status == STATUS_ALLOCATION_FAILED)
{
- fprintf (stderr, "Memory allocaiton failed.\n");
+ fprintf (stderr, "Memory allocation failed.\n");
abort ();
}
/* If not, print the error message to stderr instead. */
OpenPOWER on IntegriCloud