Commit 2d6c4025 by Ian Lance Taylor Committed by Ian Lance Taylor

cp-demangle.c (CP_DYNAMIC_ARRAYS): Define if compiler supports dynamic arrays.

	* cp-demangle.c (CP_DYNAMIC_ARRAYS): Define if compiler supports
	dynamic arrays.
	(struct d_operator_info): Add len field.
	(struct d_builtin_type_info): Add len and java_len fields.
	(struct d_standard_sub_info): Add simple_len, full_len, and
	set_last_name_len fields.
	(struct d_comp): Add len field to s_string.
	(struct d_info): Add send, did_subs, and expansion fields.
	(d_append_string_constant): Define.
	(d_append_string): Remove.  Change all users to use
	d_append_string_constant or d_append_buffer instead.
	(d_make_sub): Add len parameter.  Change all callers.
	(d_name): Increase expansion when substituting std::.
	(d_unqualified_name): Increase expansion for an operator.
	(d_number): Don't use multiplication for negative numbers.
	(d_identifier): Make sure there are enough characters in the
	string for the specified length.  Adjust expansion for an
	anonymous namespace.
	(d_operators): Initialize len field.
	(d_special_name, d_ctor_dtor_name): Increase expansion.
	(d_builtin_types): Initialize len and java_len fields.
	(d_type): Increase expansion for a builtin type.
	(d_cv_qualifiers): Increase expansion for each qualifier.
	(d_bare_function_type): Decrease expansion when removing single
	void parameter.
	(d_template_param): Increment did_subs.
	(d_expression): Increase expansion for an operator.
	(d_expr_primary): Decrease expansion for a type we will print
	specially.
	(standard_subs): Initialize new fields.
	(d_substitution): Increment did_subs when doing a normal
	substitution.  Increase expansion for a special substitution.
	(d_print): Add estimate parameter.  Change all callers.
	(d_print_comp) [D_COMP_NAME]: Handle C++ case inline.
	(d_print_comp) [D_COMP_BINARY]: Use length to avoid strcmp call.
	(d_print_java_identifier): Rename from d_print_identifier.  Handle
	only Java case.  Change caller.
	(d_init_info): Change return type to void.  Change all callers.
	Initialize send, did_subs, and expansion fields.  Do not
	initialize comps and subs fields.
	(d_demangle): Ifdef CP_DYNAMIC_ARRAYS, allocate comps and subs
	arrays on stack.  Make an estimate of the length of the demangled
	name.  Ifdef CP_DEMANGLE_DEBUG, print estimation failures.
	(is_ctor_or_dtor): Ifdef CP_DYNAMIC_ARRAYS, allocate comps and
	subs arrays on stack.

From-SVN: r74933
parent a827daa0
2003-12-22 Ian Lance Taylor <ian@wasabisystems.com>
* cp-demangle.c (CP_DYNAMIC_ARRAYS): Define if compiler supports
dynamic arrays.
(struct d_operator_info): Add len field.
(struct d_builtin_type_info): Add len and java_len fields.
(struct d_standard_sub_info): Add simple_len, full_len, and
set_last_name_len fields.
(struct d_comp): Add len field to s_string.
(struct d_info): Add send, did_subs, and expansion fields.
(d_append_string_constant): Define.
(d_append_string): Remove. Change all users to use
d_append_string_constant or d_append_buffer instead.
(d_make_sub): Add len parameter. Change all callers.
(d_name): Increase expansion when substituting std::.
(d_unqualified_name): Increase expansion for an operator.
(d_number): Don't use multiplication for negative numbers.
(d_identifier): Make sure there are enough characters in the
string for the specified length. Adjust expansion for an
anonymous namespace.
(d_operators): Initialize len field.
(d_special_name, d_ctor_dtor_name): Increase expansion.
(d_builtin_types): Initialize len and java_len fields.
(d_type): Increase expansion for a builtin type.
(d_cv_qualifiers): Increase expansion for each qualifier.
(d_bare_function_type): Decrease expansion when removing single
void parameter.
(d_template_param): Increment did_subs.
(d_expression): Increase expansion for an operator.
(d_expr_primary): Decrease expansion for a type we will print
specially.
(standard_subs): Initialize new fields.
(d_substitution): Increment did_subs when doing a normal
substitution. Increase expansion for a special substitution.
(d_print): Add estimate parameter. Change all callers.
(d_print_comp) [D_COMP_NAME]: Handle C++ case inline.
(d_print_comp) [D_COMP_BINARY]: Use length to avoid strcmp call.
(d_print_java_identifier): Rename from d_print_identifier. Handle
only Java case. Change caller.
(d_init_info): Change return type to void. Change all callers.
Initialize send, did_subs, and expansion fields. Do not
initialize comps and subs fields.
(d_demangle): Ifdef CP_DYNAMIC_ARRAYS, allocate comps and subs
arrays on stack. Make an estimate of the length of the demangled
name. Ifdef CP_DEMANGLE_DEBUG, print estimation failures.
(is_ctor_or_dtor): Ifdef CP_DYNAMIC_ARRAYS, allocate comps and
subs arrays on stack.
2003-12-20 Ian Lance Taylor <ian@wasabisystems.com> 2003-12-20 Ian Lance Taylor <ian@wasabisystems.com>
* cp-demangle.c (d_identifier): In Java mode, skip an optional '$' * cp-demangle.c (d_identifier): In Java mode, skip an optional '$'
......
...@@ -82,6 +82,20 @@ ...@@ -82,6 +82,20 @@
#include "libiberty.h" #include "libiberty.h"
#include "demangle.h" #include "demangle.h"
/* See if the compiler supports dynamic arrays. */
#ifdef __GNUC__
#define CP_DYNAMIC_ARRAYS
#else
#ifdef __STDC__
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ >= 199901L
#define CP_DYNAMIC_ARRAYS
#endif /* __STDC__VERSION >= 199901L */
#endif /* defined (__STDC_VERSION__) */
#endif /* defined (__STDC__) */
#endif /* ! defined (__GNUC__) */
/* We avoid pulling in the ctype tables, to prevent pulling in /* We avoid pulling in the ctype tables, to prevent pulling in
additional unresolved symbols when this code is used in a library. additional unresolved symbols when this code is used in a library.
FIXME: Is this really a valid reason? This comes from the original FIXME: Is this really a valid reason? This comes from the original
...@@ -109,6 +123,8 @@ struct d_operator_info ...@@ -109,6 +123,8 @@ struct d_operator_info
const char *code; const char *code;
/* Real name. */ /* Real name. */
const char *name; const char *name;
/* Length of real name. */
int len;
/* Number of arguments. */ /* Number of arguments. */
int args; int args;
}; };
...@@ -135,8 +151,12 @@ struct d_builtin_type_info ...@@ -135,8 +151,12 @@ struct d_builtin_type_info
{ {
/* Type name. */ /* Type name. */
const char *name; const char *name;
/* Length of type name. */
int len;
/* Type name when using Java. */ /* Type name when using Java. */
const char *java_name; const char *java_name;
/* Length of java name. */
int java_len;
/* How to print a value of this type. */ /* How to print a value of this type. */
enum d_builtin_type_print print; enum d_builtin_type_print print;
}; };
...@@ -149,13 +169,19 @@ struct d_standard_sub_info ...@@ -149,13 +169,19 @@ struct d_standard_sub_info
char code; char code;
/* The simple string it expands to. */ /* The simple string it expands to. */
const char *simple_expansion; const char *simple_expansion;
/* The length of the simple expansion. */
int simple_len;
/* The results of a full, verbose, expansion. This is used when /* The results of a full, verbose, expansion. This is used when
qualifying a constructor/destructor, or when in verbose mode. */ qualifying a constructor/destructor, or when in verbose mode. */
const char *full_expansion; const char *full_expansion;
/* The length of the full expansion. */
int full_len;
/* What to set the last_name field of d_info to; NULL if we should /* What to set the last_name field of d_info to; NULL if we should
not set it. This is only relevant when qualifying a not set it. This is only relevant when qualifying a
constructor/destructor. */ constructor/destructor. */
const char *set_last_name; const char *set_last_name;
/* The length of set_last_name. */
int set_last_name_len;
}; };
/* Component types found in mangled names. */ /* Component types found in mangled names. */
...@@ -320,6 +346,7 @@ struct d_comp ...@@ -320,6 +346,7 @@ struct d_comp
struct struct
{ {
const char* string; const char* string;
int len;
} s_string; } s_string;
/* For D_COMP_TEMPLATE_PARAM. */ /* For D_COMP_TEMPLATE_PARAM. */
...@@ -347,6 +374,8 @@ struct d_info ...@@ -347,6 +374,8 @@ struct d_info
{ {
/* The string we are demangling. */ /* The string we are demangling. */
const char *s; const char *s;
/* The end of the string we are demangling. */
const char *send;
/* The options passed to the demangler. */ /* The options passed to the demangler. */
int options; int options;
/* The next character in the string to consider. */ /* The next character in the string to consider. */
...@@ -363,8 +392,16 @@ struct d_info ...@@ -363,8 +392,16 @@ struct d_info
int next_sub; int next_sub;
/* The number of available entries in the subs array. */ /* The number of available entries in the subs array. */
int num_subs; int num_subs;
/* The number of substitutions which we actually made from the subs
array, plus the number of template parameter references we
saw. */
int did_subs;
/* The last name we saw, for constructors and destructors. */ /* The last name we saw, for constructors and destructors. */
struct d_comp *last_name; struct d_comp *last_name;
/* A running total of the length of large expansions from the
mangled name to the demangled name, such as standard
substitutions and builtin types. */
int expansion;
}; };
#define d_peek_char(di) (*((di)->n)) #define d_peek_char(di) (*((di)->n))
...@@ -444,13 +481,8 @@ struct d_print_info ...@@ -444,13 +481,8 @@ struct d_print_info
} \ } \
while (0) while (0)
#define d_append_string(dpi, s) \ #define d_append_string_constant(dpi, s) \
do \ d_append_buffer (dpi, (s), sizeof (s) - 1)
{ \
size_t d_append_string_len = strlen (s); \
d_append_buffer ((dpi), (s), d_append_string_len); \
} \
while (0)
#define d_last_char(dpi) \ #define d_last_char(dpi) \
((dpi)->buf == NULL || (dpi)->len == 0 ? '\0' : (dpi)->buf[(dpi)->len - 1]) ((dpi)->buf == NULL || (dpi)->len == 0 ? '\0' : (dpi)->buf[(dpi)->len - 1])
...@@ -478,7 +510,7 @@ static struct d_comp *d_make_dtor PARAMS ((struct d_info *, ...@@ -478,7 +510,7 @@ static struct d_comp *d_make_dtor PARAMS ((struct d_info *,
enum gnu_v3_dtor_kinds, enum gnu_v3_dtor_kinds,
struct d_comp *)); struct d_comp *));
static struct d_comp *d_make_template_param PARAMS ((struct d_info *, long)); static struct d_comp *d_make_template_param PARAMS ((struct d_info *, long));
static struct d_comp *d_make_sub PARAMS ((struct d_info *, const char *)); static struct d_comp *d_make_sub PARAMS ((struct d_info *, const char *, int));
static struct d_comp *d_mangled_name PARAMS ((struct d_info *, int)); static struct d_comp *d_mangled_name PARAMS ((struct d_info *, int));
static int has_return_type PARAMS ((struct d_comp *)); static int has_return_type PARAMS ((struct d_comp *));
static int is_ctor_dtor_or_conversion PARAMS ((struct d_comp *)); static int is_ctor_dtor_or_conversion PARAMS ((struct d_comp *));
...@@ -516,11 +548,11 @@ static void d_print_append_char PARAMS ((struct d_print_info *, int)); ...@@ -516,11 +548,11 @@ static void d_print_append_char PARAMS ((struct d_print_info *, int));
static void d_print_append_buffer PARAMS ((struct d_print_info *, const char *, static void d_print_append_buffer PARAMS ((struct d_print_info *, const char *,
size_t)); size_t));
static void d_print_error PARAMS ((struct d_print_info *)); static void d_print_error PARAMS ((struct d_print_info *));
static char *d_print PARAMS ((int, const struct d_comp *, size_t *)); static char *d_print PARAMS ((int, const struct d_comp *, int, size_t *));
static void d_print_comp PARAMS ((struct d_print_info *, static void d_print_comp PARAMS ((struct d_print_info *,
const struct d_comp *)); const struct d_comp *));
static void d_print_identifier PARAMS ((struct d_print_info *, const char *, static void d_print_java_identifier PARAMS ((struct d_print_info *,
int)); const char *, int));
static void d_print_mod_list PARAMS ((struct d_print_info *, static void d_print_mod_list PARAMS ((struct d_print_info *,
struct d_print_mod *, int)); struct d_print_mod *, int));
static void d_print_mod PARAMS ((struct d_print_info *, static void d_print_mod PARAMS ((struct d_print_info *,
...@@ -535,7 +567,7 @@ static void d_print_expr_op PARAMS ((struct d_print_info *, ...@@ -535,7 +567,7 @@ static void d_print_expr_op PARAMS ((struct d_print_info *,
const struct d_comp *)); const struct d_comp *));
static void d_print_cast PARAMS ((struct d_print_info *, static void d_print_cast PARAMS ((struct d_print_info *,
const struct d_comp *)); const struct d_comp *));
static int d_init_info PARAMS ((const char *, int, size_t, struct d_info *)); static void d_init_info PARAMS ((const char *, int, size_t, struct d_info *));
static char *d_demangle PARAMS ((const char *, int, size_t *)); static char *d_demangle PARAMS ((const char *, int, size_t *));
#ifdef CP_DEMANGLE_DEBUG #ifdef CP_DEMANGLE_DEBUG
...@@ -961,15 +993,19 @@ d_make_template_param (di, i) ...@@ -961,15 +993,19 @@ d_make_template_param (di, i)
/* Add a new standard substitution component. */ /* Add a new standard substitution component. */
static struct d_comp * static struct d_comp *
d_make_sub (di, name) d_make_sub (di, name, len)
struct d_info *di; struct d_info *di;
const char *name; const char *name;
int len;
{ {
struct d_comp *p; struct d_comp *p;
p = d_make_empty (di, D_COMP_SUB_STD); p = d_make_empty (di, D_COMP_SUB_STD);
if (p != NULL) if (p != NULL)
p->u.s_string.string = name; {
p->u.s_string.string = name;
p->u.s_string.len = len;
}
return p; return p;
} }
...@@ -1125,6 +1161,7 @@ d_name (di) ...@@ -1125,6 +1161,7 @@ d_name (di)
d_advance (di, 2); d_advance (di, 2);
dc = d_make_comp (di, D_COMP_QUAL_NAME, d_make_name (di, "std", 3), dc = d_make_comp (di, D_COMP_QUAL_NAME, d_make_name (di, "std", 3),
d_unqualified_name (di)); d_unqualified_name (di));
di->expansion += 3;
subst = 0; subst = 0;
} }
...@@ -1275,7 +1312,14 @@ d_unqualified_name (di) ...@@ -1275,7 +1312,14 @@ d_unqualified_name (di)
if (IS_DIGIT (peek)) if (IS_DIGIT (peek))
return d_source_name (di); return d_source_name (di);
else if (IS_LOWER (peek)) else if (IS_LOWER (peek))
return d_operator_name (di); {
struct d_comp *ret;
ret = d_operator_name (di);
if (ret != NULL && ret->type == D_COMP_OPERATOR)
di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2;
return ret;
}
else if (peek == 'C' || peek == 'D') else if (peek == 'C' || peek == 'D')
return d_ctor_dtor_name (di); return d_ctor_dtor_name (di);
else else
...@@ -1305,15 +1349,15 @@ static long ...@@ -1305,15 +1349,15 @@ static long
d_number (di) d_number (di)
struct d_info *di; struct d_info *di;
{ {
int sign; int negative;
char peek; char peek;
long ret; long ret;
sign = 1; negative = 0;
peek = d_peek_char (di); peek = d_peek_char (di);
if (peek == 'n') if (peek == 'n')
{ {
sign = -1; negative = 1;
d_advance (di, 1); d_advance (di, 1);
peek = d_peek_char (di); peek = d_peek_char (di);
} }
...@@ -1322,7 +1366,11 @@ d_number (di) ...@@ -1322,7 +1366,11 @@ d_number (di)
while (1) while (1)
{ {
if (! IS_DIGIT (peek)) if (! IS_DIGIT (peek))
return ret * sign; {
if (negative)
ret = - ret;
return ret;
}
ret = ret * 10 + peek - '0'; ret = ret * 10 + peek - '0';
d_advance (di, 1); d_advance (di, 1);
peek = d_peek_char (di); peek = d_peek_char (di);
...@@ -1339,6 +1387,10 @@ d_identifier (di, len) ...@@ -1339,6 +1387,10 @@ d_identifier (di, len)
const char *name; const char *name;
name = d_str (di); name = d_str (di);
if (di->send - name < len)
return NULL;
d_advance (di, len); d_advance (di, len);
/* A Java mangled name may have a trailing '$' if it is a C++ /* A Java mangled name may have a trailing '$' if it is a C++
...@@ -1360,8 +1412,11 @@ d_identifier (di, len) ...@@ -1360,8 +1412,11 @@ d_identifier (di, len)
s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN; s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN;
if ((*s == '.' || *s == '_' || *s == '$') if ((*s == '.' || *s == '_' || *s == '$')
&& s[1] == 'N') && s[1] == 'N')
return d_make_name (di, "(anonymous namespace)", {
sizeof "(anonymous namespace)" - 1); di->expansion -= len - sizeof "(anonymous namespace)";
return d_make_name (di, "(anonymous namespace)",
sizeof "(anonymous namespace)" - 1);
}
} }
return d_make_name (di, name, len); return d_make_name (di, name, len);
...@@ -1372,57 +1427,59 @@ d_identifier (di, len) ...@@ -1372,57 +1427,59 @@ d_identifier (di, len)
::= v <digit> <source-name> ::= v <digit> <source-name>
*/ */
#define NL(s) s, (sizeof s) - 1
static const struct d_operator_info d_operators[] = static const struct d_operator_info d_operators[] =
{ {
{ "aN", "&=", 2 }, { "aN", NL ("&="), 2 },
{ "aS", "=", 2 }, { "aS", NL ("="), 2 },
{ "aa", "&&", 2 }, { "aa", NL ("&&"), 2 },
{ "ad", "&", 1 }, { "ad", NL ("&"), 1 },
{ "an", "&", 2 }, { "an", NL ("&"), 2 },
{ "cl", "()", 0 }, { "cl", NL ("()"), 0 },
{ "cm", ",", 2 }, { "cm", NL (","), 2 },
{ "co", "~", 1 }, { "co", NL ("~"), 1 },
{ "dV", "/=", 2 }, { "dV", NL ("/="), 2 },
{ "da", "delete[]", 1 }, { "da", NL ("delete[]"), 1 },
{ "de", "*", 1 }, { "de", NL ("*"), 1 },
{ "dl", "delete", 1 }, { "dl", NL ("delete"), 1 },
{ "dv", "/", 2 }, { "dv", NL ("/"), 2 },
{ "eO", "^=", 2 }, { "eO", NL ("^="), 2 },
{ "eo", "^", 2 }, { "eo", NL ("^"), 2 },
{ "eq", "==", 2 }, { "eq", NL ("=="), 2 },
{ "ge", ">=", 2 }, { "ge", NL (">="), 2 },
{ "gt", ">", 2 }, { "gt", NL (">"), 2 },
{ "ix", "[]", 2 }, { "ix", NL ("[]"), 2 },
{ "lS", "<<=", 2 }, { "lS", NL ("<<="), 2 },
{ "le", "<=", 2 }, { "le", NL ("<="), 2 },
{ "ls", "<<", 2 }, { "ls", NL ("<<"), 2 },
{ "lt", "<", 2 }, { "lt", NL ("<"), 2 },
{ "mI", "-=", 2 }, { "mI", NL ("-="), 2 },
{ "mL", "*=", 2 }, { "mL", NL ("*="), 2 },
{ "mi", "-", 2 }, { "mi", NL ("-"), 2 },
{ "ml", "*", 2 }, { "ml", NL ("*"), 2 },
{ "mm", "--", 1 }, { "mm", NL ("--"), 1 },
{ "na", "new[]", 1 }, { "na", NL ("new[]"), 1 },
{ "ne", "!=", 2 }, { "ne", NL ("!="), 2 },
{ "ng", "-", 1 }, { "ng", NL ("-"), 1 },
{ "nt", "!", 1 }, { "nt", NL ("!"), 1 },
{ "nw", "new", 1 }, { "nw", NL ("new"), 1 },
{ "oR", "|=", 2 }, { "oR", NL ("|="), 2 },
{ "oo", "||", 2 }, { "oo", NL ("||"), 2 },
{ "or", "|", 2 }, { "or", NL ("|"), 2 },
{ "pL", "+=", 2 }, { "pL", NL ("+="), 2 },
{ "pl", "+", 2 }, { "pl", NL ("+"), 2 },
{ "pm", "->*", 2 }, { "pm", NL ("->*"), 2 },
{ "pp", "++", 1 }, { "pp", NL ("++"), 1 },
{ "ps", "+", 1 }, { "ps", NL ("+"), 1 },
{ "pt", "->", 2 }, { "pt", NL ("->"), 2 },
{ "qu", "?", 3 }, { "qu", NL ("?"), 3 },
{ "rM", "%=", 2 }, { "rM", NL ("%="), 2 },
{ "rS", ">>=", 2 }, { "rS", NL (">>="), 2 },
{ "rm", "%", 2 }, { "rm", NL ("%"), 2 },
{ "rs", ">>", 2 }, { "rs", NL (">>"), 2 },
{ "st", "sizeof ", 1 }, { "st", NL ("sizeof "), 1 },
{ "sz", "sizeof ", 1 } { "sz", NL ("sizeof "), 1 }
}; };
static struct d_comp * static struct d_comp *
...@@ -1484,14 +1541,17 @@ d_special_name (di) ...@@ -1484,14 +1541,17 @@ d_special_name (di)
{ {
char c; char c;
di->expansion += 20;
c = d_next_char (di); c = d_next_char (di);
if (c == 'T') if (c == 'T')
{ {
switch (d_next_char (di)) switch (d_next_char (di))
{ {
case 'V': case 'V':
di->expansion -= 5;
return d_make_comp (di, D_COMP_VTABLE, d_type (di), NULL); return d_make_comp (di, D_COMP_VTABLE, d_type (di), NULL);
case 'T': case 'T':
di->expansion -= 10;
return d_make_comp (di, D_COMP_VTT, d_type (di), NULL); return d_make_comp (di, D_COMP_VTT, d_type (di), NULL);
case 'I': case 'I':
return d_make_comp (di, D_COMP_TYPEINFO, d_type (di), NULL); return d_make_comp (di, D_COMP_TYPEINFO, d_type (di), NULL);
...@@ -1532,6 +1592,7 @@ d_special_name (di) ...@@ -1532,6 +1592,7 @@ d_special_name (di)
base_type = d_type (di); base_type = d_type (di);
/* We don't display the offset. FIXME: We should display /* We don't display the offset. FIXME: We should display
it in verbose mode. */ it in verbose mode. */
di->expansion += 5;
return d_make_comp (di, D_COMP_CONSTRUCTION_VTABLE, base_type, return d_make_comp (di, D_COMP_CONSTRUCTION_VTABLE, base_type,
derived_type); derived_type);
} }
...@@ -1617,6 +1678,13 @@ static struct d_comp * ...@@ -1617,6 +1678,13 @@ static struct d_comp *
d_ctor_dtor_name (di) d_ctor_dtor_name (di)
struct d_info *di; struct d_info *di;
{ {
if (di->last_name != NULL)
{
if (di->last_name->type == D_COMP_NAME)
di->expansion += di->last_name->u.s_name.len;
else if (di->last_name->type == D_COMP_SUB_STD)
di->expansion += di->last_name->u.s_string.len;
}
switch (d_next_char (di)) switch (d_next_char (di))
{ {
case 'C': case 'C':
...@@ -1687,32 +1755,32 @@ d_ctor_dtor_name (di) ...@@ -1687,32 +1755,32 @@ d_ctor_dtor_name (di)
static const struct d_builtin_type_info d_builtin_types[26] = static const struct d_builtin_type_info d_builtin_types[26] =
{ {
/* a */ { "signed char", "signed char", D_PRINT_INT }, /* a */ { NL ("signed char"), NL ("signed char"), D_PRINT_INT },
/* b */ { "bool", "boolean", D_PRINT_BOOL }, /* b */ { NL ("bool"), NL ("boolean"), D_PRINT_BOOL },
/* c */ { "char", "byte", D_PRINT_INT }, /* c */ { NL ("char"), NL ("byte"), D_PRINT_INT },
/* d */ { "double", "double", D_PRINT_DEFAULT }, /* d */ { NL ("double"), NL ("double"), D_PRINT_DEFAULT },
/* e */ { "long double", "long double", D_PRINT_DEFAULT }, /* e */ { NL ("long double"), NL ("long double"), D_PRINT_DEFAULT },
/* f */ { "float", "float", D_PRINT_DEFAULT }, /* f */ { NL ("float"), NL ("float"), D_PRINT_DEFAULT },
/* g */ { "__float128", "__float128", D_PRINT_DEFAULT }, /* g */ { NL ("__float128"), NL ("__float128"), D_PRINT_DEFAULT },
/* h */ { "unsigned char", "unsigned char", D_PRINT_INT }, /* h */ { NL ("unsigned char"), NL ("unsigned char"), D_PRINT_INT },
/* i */ { "int", "int", D_PRINT_INT }, /* i */ { NL ("int"), NL ("int"), D_PRINT_INT },
/* j */ { "unsigned int", "unsigned", D_PRINT_INT }, /* j */ { NL ("unsigned int"), NL ("unsigned"), D_PRINT_INT },
/* k */ { NULL, NULL, D_PRINT_DEFAULT }, /* k */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* l */ { "long", "long", D_PRINT_LONG }, /* l */ { NL ("long"), NL ("long"), D_PRINT_LONG },
/* m */ { "unsigned long", "unsigned long", D_PRINT_LONG }, /* m */ { NL ("unsigned long"), NL ("unsigned long"), D_PRINT_LONG },
/* n */ { "__int128", "__int128", D_PRINT_DEFAULT }, /* n */ { NL ("__int128"), NL ("__int128"), D_PRINT_DEFAULT },
/* o */ { "unsigned __int128", "unsigned __int128", D_PRINT_DEFAULT }, /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"), D_PRINT_DEFAULT },
/* p */ { NULL, NULL, D_PRINT_DEFAULT }, /* p */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* q */ { NULL, NULL, D_PRINT_DEFAULT }, /* q */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* r */ { NULL, NULL, D_PRINT_DEFAULT }, /* r */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* s */ { "short", "short", D_PRINT_INT }, /* s */ { NL ("short"), NL ("short"), D_PRINT_INT },
/* t */ { "unsigned short", "unsigned short", D_PRINT_INT }, /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_INT },
/* u */ { NULL, NULL, D_PRINT_DEFAULT }, /* u */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
/* v */ { "void", "void", D_PRINT_VOID }, /* v */ { NL ("void"), NL ("void"), D_PRINT_VOID },
/* w */ { "wchar_t", "char", D_PRINT_INT }, /* w */ { NL ("wchar_t"), NL ("char"), D_PRINT_INT },
/* x */ { "long long", "long", D_PRINT_DEFAULT }, /* x */ { NL ("long long"), NL ("long"), D_PRINT_DEFAULT },
/* y */ { "unsigned long long", "unsigned long long", D_PRINT_DEFAULT }, /* y */ { NL ("unsigned long long"), NL ("unsigned long long"), D_PRINT_DEFAULT },
/* z */ { "...", "...", D_PRINT_DEFAULT }, /* z */ { NL ("..."), NL ("..."), D_PRINT_DEFAULT },
}; };
static struct d_comp * static struct d_comp *
...@@ -1761,6 +1829,7 @@ d_type (di) ...@@ -1761,6 +1829,7 @@ d_type (di)
case 'o': case 's': case 't': case 'o': case 's': case 't':
case 'v': case 'w': case 'x': case 'y': case 'z': case 'v': case 'w': case 'x': case 'y': case 'z':
ret = d_make_builtin_type (di, &d_builtin_types[peek - 'a']); ret = d_make_builtin_type (di, &d_builtin_types[peek - 'a']);
di->expansion += ret->u.s_builtin.type->len;
can_subst = 0; can_subst = 0;
d_advance (di, 1); d_advance (di, 1);
break; break;
...@@ -1891,11 +1960,20 @@ d_cv_qualifiers (di, pret, member_fn) ...@@ -1891,11 +1960,20 @@ d_cv_qualifiers (di, pret, member_fn)
d_advance (di, 1); d_advance (di, 1);
if (peek == 'r') if (peek == 'r')
t = member_fn ? D_COMP_RESTRICT_THIS: D_COMP_RESTRICT; {
t = member_fn ? D_COMP_RESTRICT_THIS : D_COMP_RESTRICT;
di->expansion += sizeof "restrict";
}
else if (peek == 'V') else if (peek == 'V')
t = member_fn ? D_COMP_VOLATILE_THIS : D_COMP_VOLATILE; {
t = member_fn ? D_COMP_VOLATILE_THIS : D_COMP_VOLATILE;
di->expansion += sizeof "volatile";
}
else else
t = member_fn ? D_COMP_CONST_THIS: D_COMP_CONST; {
t = member_fn ? D_COMP_CONST_THIS : D_COMP_CONST;
di->expansion += sizeof "const";
}
*pret = d_make_comp (di, t, NULL, NULL); *pret = d_make_comp (di, t, NULL, NULL);
if (*pret == NULL) if (*pret == NULL)
...@@ -1979,7 +2057,10 @@ d_bare_function_type (di, has_return_type) ...@@ -1979,7 +2057,10 @@ d_bare_function_type (di, has_return_type)
if (d_right (tl) == NULL if (d_right (tl) == NULL
&& d_left (tl)->type == D_COMP_BUILTIN_TYPE && d_left (tl)->type == D_COMP_BUILTIN_TYPE
&& d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID) && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID)
tl = NULL; {
di->expansion -= d_left (tl)->u.s_builtin.type->len;
tl = NULL;
}
return d_make_comp (di, D_COMP_FUNCTION_TYPE, return_type, tl); return d_make_comp (di, D_COMP_FUNCTION_TYPE, return_type, tl);
} }
...@@ -2100,6 +2181,8 @@ d_template_param (di) ...@@ -2100,6 +2181,8 @@ d_template_param (di)
if (d_next_char (di) != '_') if (d_next_char (di) != '_')
return NULL; return NULL;
++di->did_subs;
return d_make_template_param (di, param); return d_make_template_param (di, param);
} }
...@@ -2221,6 +2304,9 @@ d_expression (di) ...@@ -2221,6 +2304,9 @@ d_expression (di)
if (op == NULL) if (op == NULL)
return NULL; return NULL;
if (op->type == D_COMP_OPERATOR)
di->expansion += op->u.s_operator.op->len - 2;
if (op->type == D_COMP_OPERATOR if (op->type == D_COMP_OPERATOR
&& strcmp (op->u.s_operator.op->code, "st") == 0) && strcmp (op->u.s_operator.op->code, "st") == 0)
return d_make_comp (di, D_COMP_UNARY, op, d_type (di)); return d_make_comp (di, D_COMP_UNARY, op, d_type (di));
...@@ -2296,6 +2382,12 @@ d_expr_primary (di) ...@@ -2296,6 +2382,12 @@ d_expr_primary (di)
type = d_type (di); type = d_type (di);
/* If we have a type we know how to print, we aren't going to
print the type name itself. */
if (type->type == D_COMP_BUILTIN_TYPE
&& type->u.s_builtin.type->print != D_PRINT_DEFAULT)
di->expansion -= type->u.s_builtin.type->len;
/* Rather than try to interpret the literal value, we just /* Rather than try to interpret the literal value, we just
collect it as a string. Note that it's possible to have a collect it as a string. Note that it's possible to have a
floating point literal here. The ABI specifies that the floating point literal here. The ABI specifies that the
...@@ -2418,21 +2510,27 @@ d_add_substitution (di, dc) ...@@ -2418,21 +2510,27 @@ d_add_substitution (di, dc)
static const struct d_standard_sub_info standard_subs[] = static const struct d_standard_sub_info standard_subs[] =
{ {
{ 't', "std", "std", NULL }, { 't', NL ("std"),
{ 'a', "std::allocator", "std::allocator", "allocator" }, NL ("std"),
{ 'b', "std::basic_string", "std::basic_string", "basic_string" }, NULL, 0 },
{ 's', "std::string", { 'a', NL ("std::allocator"),
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >", NL ("std::allocator"),
"basic_string" }, NL ("allocator") },
{ 'i', "std::istream", { 'b', NL ("std::basic_string"),
"std::basic_istream<char, std::char_traits<char> >", NL ("std::basic_string"),
"basic_istream" }, NL ("basic_string") },
{ 'o', "std::ostream", { 's', NL ("std::string"),
"std::basic_ostream<char, std::char_traits<char> >", NL ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
"basic_ostream" }, NL ("basic_string") },
{ 'd', "std::iostream", { 'i', NL ("std::istream"),
"std::basic_iostream<char, std::char_traits<char> >", NL ("std::basic_istream<char, std::char_traits<char> >"),
"basic_iostream" } NL ("basic_istream") },
{ 'o', NL ("std::ostream"),
NL ("std::basic_ostream<char, std::char_traits<char> >"),
NL ("basic_ostream") },
{ 'd', NL ("std::iostream"),
NL ("std::basic_iostream<char, std::char_traits<char> >"),
NL ("basic_iostream") }
}; };
static struct d_comp * static struct d_comp *
...@@ -2471,6 +2569,8 @@ d_substitution (di, prefix) ...@@ -2471,6 +2569,8 @@ d_substitution (di, prefix)
if (id >= di->next_sub) if (id >= di->next_sub)
return NULL; return NULL;
++di->did_subs;
return di->subs[id]; return di->subs[id];
} }
else else
...@@ -2495,12 +2595,24 @@ d_substitution (di, prefix) ...@@ -2495,12 +2595,24 @@ d_substitution (di, prefix)
{ {
if (c == p->code) if (c == p->code)
{ {
const char *s;
int len;
if (p->set_last_name != NULL) if (p->set_last_name != NULL)
di->last_name = d_make_sub (di, p->set_last_name); di->last_name = d_make_sub (di, p->set_last_name,
p->set_last_name_len);
if (verbose) if (verbose)
return d_make_sub (di, p->full_expansion); {
s = p->full_expansion;
len = p->full_len;
}
else else
return d_make_sub (di, p->simple_expansion); {
s = p->simple_expansion;
len = p->simple_len;
}
di->expansion += len;
return d_make_sub (di, s, len);
} }
} }
...@@ -2592,22 +2704,26 @@ d_print_error (dpi) ...@@ -2592,22 +2704,26 @@ d_print_error (dpi)
dpi->buf = NULL; dpi->buf = NULL;
} }
/* Turn components into a human readable string. Returns a string /* Turn components into a human readable string. OPTIONS is the
allocated by malloc, or NULL on error. On success, this sets *PALC options bits passed to the demangler. DC is the tree to print.
to the size of the allocated buffer. On failure, this sets *PALC ESTIMATE is a guess at the length of the result. This returns a
to 0 for a bad parse, or to 1 for a memory allocation failure. */ string allocated by malloc, or NULL on error. On success, this
sets *PALC to the size of the allocated buffer. On failure, this
sets *PALC to 0 for a bad parse, or to 1 for a memory allocation
failure. */
static char * static char *
d_print (options, dc, palc) d_print (options, dc, estimate, palc)
int options; int options;
const struct d_comp *dc; const struct d_comp *dc;
int estimate;
size_t *palc; size_t *palc;
{ {
struct d_print_info dpi; struct d_print_info dpi;
dpi.options = options; dpi.options = options;
dpi.alc = 64; dpi.alc = estimate + 1;
dpi.buf = malloc (dpi.alc); dpi.buf = malloc (dpi.alc);
if (dpi.buf == NULL) if (dpi.buf == NULL)
{ {
...@@ -2651,13 +2767,19 @@ d_print_comp (dpi, dc) ...@@ -2651,13 +2767,19 @@ d_print_comp (dpi, dc)
switch (dc->type) switch (dc->type)
{ {
case D_COMP_NAME: case D_COMP_NAME:
d_print_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len); if ((dpi->options & DMGL_JAVA) == 0)
d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len);
else
d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
return; return;
case D_COMP_QUAL_NAME: case D_COMP_QUAL_NAME:
case D_COMP_LOCAL_NAME: case D_COMP_LOCAL_NAME:
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
d_append_string (dpi, (dpi->options & DMGL_JAVA) == 0 ? "::" : "."); if ((dpi->options & DMGL_JAVA) == 0)
d_append_string_constant (dpi, "::");
else
d_append_char (dpi, '.');
d_print_comp (dpi, d_right (dc)); d_print_comp (dpi, d_right (dc));
return; return;
...@@ -2844,69 +2966,69 @@ d_print_comp (dpi, dc) ...@@ -2844,69 +2966,69 @@ d_print_comp (dpi, dc)
return; return;
case D_COMP_VTABLE: case D_COMP_VTABLE:
d_append_string (dpi, "vtable for "); d_append_string_constant (dpi, "vtable for ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_VTT: case D_COMP_VTT:
d_append_string (dpi, "VTT for "); d_append_string_constant (dpi, "VTT for ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_CONSTRUCTION_VTABLE: case D_COMP_CONSTRUCTION_VTABLE:
d_append_string (dpi, "construction vtable for "); d_append_string_constant (dpi, "construction vtable for ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
d_append_string (dpi, "-in-"); d_append_string_constant (dpi, "-in-");
d_print_comp (dpi, d_right (dc)); d_print_comp (dpi, d_right (dc));
return; return;
case D_COMP_TYPEINFO: case D_COMP_TYPEINFO:
d_append_string (dpi, "typeinfo for "); d_append_string_constant (dpi, "typeinfo for ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_TYPEINFO_NAME: case D_COMP_TYPEINFO_NAME:
d_append_string (dpi, "typeinfo name for "); d_append_string_constant (dpi, "typeinfo name for ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_TYPEINFO_FN: case D_COMP_TYPEINFO_FN:
d_append_string (dpi, "typeinfo fn for "); d_append_string_constant (dpi, "typeinfo fn for ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_THUNK: case D_COMP_THUNK:
d_append_string (dpi, "non-virtual thunk to "); d_append_string_constant (dpi, "non-virtual thunk to ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_VIRTUAL_THUNK: case D_COMP_VIRTUAL_THUNK:
d_append_string (dpi, "virtual thunk to "); d_append_string_constant (dpi, "virtual thunk to ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_COVARIANT_THUNK: case D_COMP_COVARIANT_THUNK:
d_append_string (dpi, "covariant return thunk to "); d_append_string_constant (dpi, "covariant return thunk to ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_JAVA_CLASS: case D_COMP_JAVA_CLASS:
d_append_string (dpi, "java Class for "); d_append_string_constant (dpi, "java Class for ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_GUARD: case D_COMP_GUARD:
d_append_string (dpi, "guard variable for "); d_append_string_constant (dpi, "guard variable for ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_REFTEMP: case D_COMP_REFTEMP:
d_append_string (dpi, "reference temporary for "); d_append_string_constant (dpi, "reference temporary for ");
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
return; return;
case D_COMP_SUB_STD: case D_COMP_SUB_STD:
d_append_string (dpi, dc->u.s_string.string); d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len);
return; return;
case D_COMP_RESTRICT: case D_COMP_RESTRICT:
...@@ -2944,9 +3066,11 @@ d_print_comp (dpi, dc) ...@@ -2944,9 +3066,11 @@ d_print_comp (dpi, dc)
case D_COMP_BUILTIN_TYPE: case D_COMP_BUILTIN_TYPE:
if ((dpi->options & DMGL_JAVA) == 0) if ((dpi->options & DMGL_JAVA) == 0)
d_append_string (dpi, dc->u.s_builtin.type->name); d_append_buffer (dpi, dc->u.s_builtin.type->name,
dc->u.s_builtin.type->len);
else else
d_append_string (dpi, dc->u.s_builtin.type->java_name); d_append_buffer (dpi, dc->u.s_builtin.type->java_name,
dc->u.s_builtin.type->java_len);
return; return;
case D_COMP_VENDOR_TYPE: case D_COMP_VENDOR_TYPE:
...@@ -3026,7 +3150,7 @@ d_print_comp (dpi, dc) ...@@ -3026,7 +3150,7 @@ d_print_comp (dpi, dc)
{ {
d_append_char (dpi, ' '); d_append_char (dpi, ' ');
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
d_append_string (dpi, "::*"); d_append_string_constant (dpi, "::*");
} }
dpi->modifiers = dpm.next; dpi->modifiers = dpm.next;
...@@ -3039,7 +3163,7 @@ d_print_comp (dpi, dc) ...@@ -3039,7 +3163,7 @@ d_print_comp (dpi, dc)
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
if (d_right (dc) != NULL) if (d_right (dc) != NULL)
{ {
d_append_string (dpi, ", "); d_append_string_constant (dpi, ", ");
d_print_comp (dpi, d_right (dc)); d_print_comp (dpi, d_right (dc));
} }
return; return;
...@@ -3048,21 +3172,22 @@ d_print_comp (dpi, dc) ...@@ -3048,21 +3172,22 @@ d_print_comp (dpi, dc)
{ {
char c; char c;
d_append_string (dpi, "operator"); d_append_string_constant (dpi, "operator");
c = dc->u.s_operator.op->name[0]; c = dc->u.s_operator.op->name[0];
if (IS_LOWER (c)) if (IS_LOWER (c))
d_append_char (dpi, ' '); d_append_char (dpi, ' ');
d_append_string (dpi, dc->u.s_operator.op->name); d_append_buffer (dpi, dc->u.s_operator.op->name,
dc->u.s_operator.op->len);
return; return;
} }
case D_COMP_EXTENDED_OPERATOR: case D_COMP_EXTENDED_OPERATOR:
d_append_string (dpi, "operator "); d_append_string_constant (dpi, "operator ");
d_print_comp (dpi, dc->u.s_extended_operator.name); d_print_comp (dpi, dc->u.s_extended_operator.name);
return; return;
case D_COMP_CAST: case D_COMP_CAST:
d_append_string (dpi, "operator "); d_append_string_constant (dpi, "operator ");
d_print_cast (dpi, dc); d_print_cast (dpi, dc);
return; return;
...@@ -3071,7 +3196,7 @@ d_print_comp (dpi, dc) ...@@ -3071,7 +3196,7 @@ d_print_comp (dpi, dc)
d_print_expr_op (dpi, d_left (dc)); d_print_expr_op (dpi, d_left (dc));
else else
{ {
d_append_string (dpi, "(("); d_append_string_constant (dpi, "((");
d_print_cast (dpi, d_left (dc)); d_print_cast (dpi, d_left (dc));
d_append_char (dpi, ')'); d_append_char (dpi, ')');
} }
...@@ -3093,19 +3218,21 @@ d_print_comp (dpi, dc) ...@@ -3093,19 +3218,21 @@ d_print_comp (dpi, dc)
an extra layer of parens so that it does not get confused an extra layer of parens so that it does not get confused
with the '>' which ends the template parameters. */ with the '>' which ends the template parameters. */
if (d_left (dc)->type == D_COMP_OPERATOR if (d_left (dc)->type == D_COMP_OPERATOR
&& strcmp (d_left (dc)->u.s_operator.op->name, ">") == 0) && d_left (dc)->u.s_operator.op->len == 1
&& d_left (dc)->u.s_operator.op->name[0] == '>')
d_append_char (dpi, '('); d_append_char (dpi, '(');
d_append_char (dpi, '('); d_append_char (dpi, '(');
d_print_comp (dpi, d_left (d_right (dc))); d_print_comp (dpi, d_left (d_right (dc)));
d_append_string (dpi, ") "); d_append_string_constant (dpi, ") ");
d_print_expr_op (dpi, d_left (dc)); d_print_expr_op (dpi, d_left (dc));
d_append_string (dpi, " ("); d_append_string_constant (dpi, " (");
d_print_comp (dpi, d_right (d_right (dc))); d_print_comp (dpi, d_right (d_right (dc)));
d_append_char (dpi, ')'); d_append_char (dpi, ')');
if (d_left (dc)->type == D_COMP_OPERATOR if (d_left (dc)->type == D_COMP_OPERATOR
&& strcmp (d_left (dc)->u.s_operator.op->name, ">") == 0) && d_left (dc)->u.s_operator.op->len == 1
&& d_left (dc)->u.s_operator.op->name[0] == '>')
d_append_char (dpi, ')'); d_append_char (dpi, ')');
return; return;
...@@ -3124,11 +3251,11 @@ d_print_comp (dpi, dc) ...@@ -3124,11 +3251,11 @@ d_print_comp (dpi, dc)
} }
d_append_char (dpi, '('); d_append_char (dpi, '(');
d_print_comp (dpi, d_left (d_right (dc))); d_print_comp (dpi, d_left (d_right (dc)));
d_append_string (dpi, ") "); d_append_string_constant (dpi, ") ");
d_print_expr_op (dpi, d_left (dc)); d_print_expr_op (dpi, d_left (dc));
d_append_string (dpi, " ("); d_append_string_constant (dpi, " (");
d_print_comp (dpi, d_left (d_right (d_right (dc)))); d_print_comp (dpi, d_left (d_right (d_right (dc))));
d_append_string (dpi, ") : ("); d_append_string_constant (dpi, ") : (");
d_print_comp (dpi, d_right (d_right (d_right (dc)))); d_print_comp (dpi, d_right (d_right (d_right (dc))));
d_append_char (dpi, ')'); d_append_char (dpi, ')');
return; return;
...@@ -3175,10 +3302,10 @@ d_print_comp (dpi, dc) ...@@ -3175,10 +3302,10 @@ d_print_comp (dpi, dc)
switch (d_right (dc)->u.s_name.s[0]) switch (d_right (dc)->u.s_name.s[0])
{ {
case '0': case '0':
d_append_string (dpi, "false"); d_append_string_constant (dpi, "false");
return; return;
case '1': case '1':
d_append_string (dpi, "true"); d_append_string_constant (dpi, "true");
return; return;
default: default:
break; break;
...@@ -3205,64 +3332,58 @@ d_print_comp (dpi, dc) ...@@ -3205,64 +3332,58 @@ d_print_comp (dpi, dc)
} }
} }
/* Print an identifier. */ /* Print a Java dentifier. For Java we try to handle encoded extended
Unicode characters. The C++ ABI doesn't mention Unicode encoding,
so we don't it for C++. Characters are encoded as
__U<hex-char>+_. */
static void static void
d_print_identifier (dpi, name, len) d_print_java_identifier (dpi, name, len)
struct d_print_info *dpi; struct d_print_info *dpi;
const char *name; const char *name;
int len; int len;
{ {
if ((dpi->options & DMGL_JAVA) == 0) const char *p;
d_append_buffer (dpi, name, len); const char *end;
else
end = name + len;
for (p = name; p < end; ++p)
{ {
const char *p; if (end - p > 3
const char *end; && p[0] == '_'
&& p[1] == '_'
/* For Java we try to handle encoded extended Unicode && p[2] == 'U')
characters. The C++ ABI doesn't mention Unicode encoding, so
we don't it for C++. Characters are encoded as
__U<hex-char>+_. */
end = name + len;
for (p = name; p < end; ++p)
{ {
if (end - p > 3 unsigned long c;
&& p[0] == '_' const char *q;
&& p[1] == '_'
&& p[2] == 'U') c = 0;
for (q = p + 3; q < end; ++q)
{ {
unsigned long c; int dig;
const char *q;
if (IS_DIGIT (*q))
dig = *q - '0';
else if (*q >= 'A' && *q <= 'F')
dig = *q - 'A' + 10;
else if (*q >= 'a' && *q <= 'f')
dig = *q - 'a' + 10;
else
break;
c = 0; c = c * 16 + dig;
for (q = p + 3; q < end; ++q) }
{ /* If the Unicode character is larger than 256, we don't try
int dig; to deal with it here. FIXME. */
if (q < end && *q == '_' && c < 256)
if (IS_DIGIT (*q)) {
dig = *q - '0'; d_append_char (dpi, c);
else if (*q >= 'A' && *q <= 'F') p = q;
dig = *q - 'A' + 10; continue;
else if (*q >= 'a' && *q <= 'f')
dig = *q - 'a' + 10;
else
break;
c = c * 16 + dig;
}
/* If the Unicode character is larger than 256, we don't
try to deal with it here. FIXME. */
if (q < end && *q == '_' && c < 256)
{
d_append_char (dpi, c);
p = q;
continue;
}
} }
d_append_char (dpi, *p);
} }
d_append_char (dpi, *p);
} }
} }
...@@ -3322,7 +3443,10 @@ d_print_mod_list (dpi, mods, suffix) ...@@ -3322,7 +3443,10 @@ d_print_mod_list (dpi, mods, suffix)
d_print_comp (dpi, d_left (mods->mod)); d_print_comp (dpi, d_left (mods->mod));
dpi->modifiers = hold_modifiers; dpi->modifiers = hold_modifiers;
d_append_string (dpi, (dpi->options & DMGL_JAVA) == 0 ? "::" : "."); if ((dpi->options & DMGL_JAVA) == 0)
d_append_string_constant (dpi, "::");
else
d_append_char (dpi, '.');
dc = d_right (mods->mod); dc = d_right (mods->mod);
while (dc->type == D_COMP_RESTRICT_THIS while (dc->type == D_COMP_RESTRICT_THIS
...@@ -3354,15 +3478,15 @@ d_print_mod (dpi, mod) ...@@ -3354,15 +3478,15 @@ d_print_mod (dpi, mod)
{ {
case D_COMP_RESTRICT: case D_COMP_RESTRICT:
case D_COMP_RESTRICT_THIS: case D_COMP_RESTRICT_THIS:
d_append_string (dpi, " restrict"); d_append_string_constant (dpi, " restrict");
return; return;
case D_COMP_VOLATILE: case D_COMP_VOLATILE:
case D_COMP_VOLATILE_THIS: case D_COMP_VOLATILE_THIS:
d_append_string (dpi, " volatile"); d_append_string_constant (dpi, " volatile");
return; return;
case D_COMP_CONST: case D_COMP_CONST:
case D_COMP_CONST_THIS: case D_COMP_CONST_THIS:
d_append_string (dpi, " const"); d_append_string_constant (dpi, " const");
return; return;
case D_COMP_VENDOR_TYPE_QUAL: case D_COMP_VENDOR_TYPE_QUAL:
d_append_char (dpi, ' '); d_append_char (dpi, ' ');
...@@ -3377,16 +3501,16 @@ d_print_mod (dpi, mod) ...@@ -3377,16 +3501,16 @@ d_print_mod (dpi, mod)
d_append_char (dpi, '&'); d_append_char (dpi, '&');
return; return;
case D_COMP_COMPLEX: case D_COMP_COMPLEX:
d_append_string (dpi, "complex "); d_append_string_constant (dpi, "complex ");
return; return;
case D_COMP_IMAGINARY: case D_COMP_IMAGINARY:
d_append_string (dpi, "imaginary "); d_append_string_constant (dpi, "imaginary ");
return; return;
case D_COMP_PTRMEM_TYPE: case D_COMP_PTRMEM_TYPE:
if (d_last_char (dpi) != '(') if (d_last_char (dpi) != '(')
d_append_char (dpi, ' '); d_append_char (dpi, ' ');
d_print_comp (dpi, d_left (mod)); d_print_comp (dpi, d_left (mod));
d_append_string (dpi, "::*"); d_append_string_constant (dpi, "::*");
return; return;
case D_COMP_TYPED_NAME: case D_COMP_TYPED_NAME:
d_print_comp (dpi, d_left (mod)); d_print_comp (dpi, d_left (mod));
...@@ -3520,7 +3644,7 @@ d_print_array_type (dpi, dc, mods) ...@@ -3520,7 +3644,7 @@ d_print_array_type (dpi, dc, mods)
} }
if (need_paren) if (need_paren)
d_append_string (dpi, " ("); d_append_string_constant (dpi, " (");
d_print_mod_list (dpi, mods, 0); d_print_mod_list (dpi, mods, 0);
...@@ -3547,7 +3671,8 @@ d_print_expr_op (dpi, dc) ...@@ -3547,7 +3671,8 @@ d_print_expr_op (dpi, dc)
const struct d_comp *dc; const struct d_comp *dc;
{ {
if (dc->type == D_COMP_OPERATOR) if (dc->type == D_COMP_OPERATOR)
d_append_string (dpi, dc->u.s_operator.op->name); d_append_buffer (dpi, dc->u.s_operator.op->name,
dc->u.s_operator.op->len);
else else
d_print_comp (dpi, dc); d_print_comp (dpi, dc);
} }
...@@ -3599,7 +3724,7 @@ d_print_cast (dpi, dc) ...@@ -3599,7 +3724,7 @@ d_print_cast (dpi, dc)
/* Initialize the information structure we use to pass around /* Initialize the information structure we use to pass around
information. */ information. */
static int static void
d_init_info (mangled, options, len, di) d_init_info (mangled, options, len, di)
const char *mangled; const char *mangled;
int options; int options;
...@@ -3607,6 +3732,7 @@ d_init_info (mangled, options, len, di) ...@@ -3607,6 +3732,7 @@ d_init_info (mangled, options, len, di)
struct d_info *di; struct d_info *di;
{ {
di->s = mangled; di->s = mangled;
di->send = mangled + len;
di->options = options; di->options = options;
di->n = mangled; di->n = mangled;
...@@ -3615,29 +3741,17 @@ d_init_info (mangled, options, len, di) ...@@ -3615,29 +3741,17 @@ d_init_info (mangled, options, len, di)
the mangled string. Most components correspond directly to the mangled string. Most components correspond directly to
chars, but the ARGLIST types are exceptions. */ chars, but the ARGLIST types are exceptions. */
di->num_comps = 2 * len; di->num_comps = 2 * len;
di->comps = (struct d_comp *) malloc (di->num_comps
* sizeof (struct d_comp));
di->next_comp = 0; di->next_comp = 0;
/* Similarly, we can not need more substitutions than there are /* Similarly, we can not need more substitutions than there are
chars in the mangled string. */ chars in the mangled string. */
di->num_subs = len; di->num_subs = len;
di->subs = (struct d_comp **) malloc (di->num_subs
* sizeof (struct d_comp *));
di->next_sub = 0; di->next_sub = 0;
di->did_subs = 0;
di->last_name = NULL; di->last_name = NULL;
if (di->comps == NULL || di->subs == NULL) di->expansion = 0;
{
if (di->comps != NULL)
free (di->comps);
if (di->subs != NULL)
free (di->subs);
return 0;
}
return 1;
} }
/* Entry point for the demangler. If MANGLED is a g++ v3 ABI mangled /* Entry point for the demangler. If MANGLED is a g++ v3 ABI mangled
...@@ -3657,6 +3771,7 @@ d_demangle (mangled, options, palc) ...@@ -3657,6 +3771,7 @@ d_demangle (mangled, options, palc)
int type; int type;
struct d_info di; struct d_info di;
struct d_comp *dc; struct d_comp *dc;
int estimate;
char *ret; char *ret;
*palc = 0; *palc = 0;
...@@ -3692,39 +3807,82 @@ d_demangle (mangled, options, palc) ...@@ -3692,39 +3807,82 @@ d_demangle (mangled, options, palc)
type = 1; type = 1;
} }
if (! d_init_info (mangled, options, len, &di)) d_init_info (mangled, options, len, &di);
{
*palc = 1;
return NULL;
}
if (! type) {
dc = d_mangled_name (&di, 1); #ifdef CP_DYNAMIC_ARRAYS
else __extension__ struct d_comp comps[di.num_comps];
dc = d_type (&di); __extension__ struct d_comp *subs[di.num_subs];
di.comps = &comps[0];
di.subs = &subs[0];
#else
di.comps = (struct d_comp *) malloc (di.num_comps
* sizeof (struct d_comp));
di.subs = (struct d_comp **) malloc (di.num_subs
* sizeof (struct d_comp *));
if (di.comps == NULL || di.subs == NULL)
{
if (di.comps != NULL)
free (di.comps);
if (di.subs != NULL)
free (di.subs);
*palc = 1;
return NULL;
}
#endif
if (! type)
dc = d_mangled_name (&di, 1);
else
dc = d_type (&di);
/* If DMGL_PARAMS is set, then if we didn't consume the entire /* If DMGL_PARAMS is set, then if we didn't consume the entire
mangled string, then we didn't successfully demangle it. If mangled string, then we didn't successfully demangle it. If
DMGL_PARAMS is not set, we didn't look at the trailing DMGL_PARAMS is not set, we didn't look at the trailing
parameters. */ parameters. */
if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0') if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0')
dc = NULL; dc = NULL;
#ifdef CP_DEMANGLE_DEBUG #ifdef CP_DEMANGLE_DEBUG
if (dc == NULL) if (dc == NULL)
printf ("failed demangling\n"); printf ("failed demangling\n");
else else
d_dump (dc, 0); d_dump (dc, 0);
#endif #endif
free (di.subs); /* We try to guess the length of the demangled string, to minimize
di.subs = NULL; calls to realloc during demangling. */
estimate = len + di.expansion + 10 * di.did_subs;
estimate += estimate / 8;
ret = NULL; ret = NULL;
if (dc != NULL) if (dc != NULL)
ret = d_print (options, dc, palc); ret = d_print (options, dc, estimate, palc);
free (di.comps); #ifndef CP_DYNAMIC_ARRAYS
free (di.comps);
free (di.subs);
#endif
#ifdef CP_DEMANGLE_DEBUG
if (ret != NULL)
{
int rlen;
rlen = strlen (ret);
if (rlen > 2 * estimate)
printf ("*** Length %d much greater than estimate %d\n",
rlen, estimate);
else if (rlen > estimate)
printf ("*** Length %d greater than estimate %d\n",
rlen, estimate);
else if (rlen < estimate / 2)
printf ("*** Length %d much less than estimate %d\n",
rlen, estimate);
}
#endif
}
return ret; return ret;
} }
...@@ -3907,48 +4065,73 @@ is_ctor_or_dtor (mangled, ctor_kind, dtor_kind) ...@@ -3907,48 +4065,73 @@ is_ctor_or_dtor (mangled, ctor_kind, dtor_kind)
*ctor_kind = (enum gnu_v3_ctor_kinds) 0; *ctor_kind = (enum gnu_v3_ctor_kinds) 0;
*dtor_kind = (enum gnu_v3_dtor_kinds) 0; *dtor_kind = (enum gnu_v3_dtor_kinds) 0;
if (! d_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di)) d_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di);
return 0;
dc = d_mangled_name (&di, 1); {
#ifdef CP_DYNAMIC_ARRAYS
__extension__ struct d_comp comps[di.num_comps];
__extension__ struct d_comp *subs[di.num_subs];
di.comps = &comps[0];
di.subs = &subs[0];
#else
di.comps = (struct d_comp *) malloc (di.num_comps
* sizeof (struct d_comp));
di.subs = (struct d_comp **) malloc (di.num_subs
* sizeof (struct d_comp *));
if (di.comps == NULL || di.subs == NULL)
{
if (di.comps != NULL)
free (di.comps);
if (di.subs != NULL)
free (di.subs);
*palc = 1;
return NULL;
}
#endif
/* Note that because we did not pass DMGL_PARAMS, we don't expect to dc = d_mangled_name (&di, 1);
demangle the entire string. */
ret = 0; /* Note that because we did not pass DMGL_PARAMS, we don't expect
while (dc != NULL) to demangle the entire string. */
{
switch (dc->type)
{
default:
dc = NULL;
break;
case D_COMP_TYPED_NAME:
case D_COMP_TEMPLATE:
case D_COMP_RESTRICT_THIS:
case D_COMP_VOLATILE_THIS:
case D_COMP_CONST_THIS:
dc = d_left (dc);
break;
case D_COMP_QUAL_NAME:
case D_COMP_LOCAL_NAME:
dc = d_right (dc);
break;
case D_COMP_CTOR:
*ctor_kind = dc->u.s_ctor.kind;
ret = 1;
dc = NULL;
break;
case D_COMP_DTOR:
*dtor_kind = dc->u.s_dtor.kind;
ret = 1;
dc = NULL;
break;
}
}
free (di.subs); ret = 0;
free (di.comps); while (dc != NULL)
{
switch (dc->type)
{
default:
dc = NULL;
break;
case D_COMP_TYPED_NAME:
case D_COMP_TEMPLATE:
case D_COMP_RESTRICT_THIS:
case D_COMP_VOLATILE_THIS:
case D_COMP_CONST_THIS:
dc = d_left (dc);
break;
case D_COMP_QUAL_NAME:
case D_COMP_LOCAL_NAME:
dc = d_right (dc);
break;
case D_COMP_CTOR:
*ctor_kind = dc->u.s_ctor.kind;
ret = 1;
dc = NULL;
break;
case D_COMP_DTOR:
*dtor_kind = dc->u.s_dtor.kind;
ret = 1;
dc = NULL;
break;
}
}
#ifndef CP_DYNAMIC_ARRAYS
free (di.subs);
free (di.comps);
#endif
}
return ret; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment