aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libiberty/ChangeLog48
-rw-r--r--libiberty/cp-demangle.c765
2 files changed, 522 insertions, 291 deletions
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 20d6552..c1de8de 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,51 @@
+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>
* cp-demangle.c (d_identifier): In Java mode, skip an optional '$'
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 1e5684c..b54cbe2 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -82,6 +82,20 @@
#include "libiberty.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
additional unresolved symbols when this code is used in a library.
FIXME: Is this really a valid reason? This comes from the original
@@ -109,6 +123,8 @@ struct d_operator_info
const char *code;
/* Real name. */
const char *name;
+ /* Length of real name. */
+ int len;
/* Number of arguments. */
int args;
};
@@ -135,8 +151,12 @@ struct d_builtin_type_info
{
/* Type name. */
const char *name;
+ /* Length of type name. */
+ int len;
/* Type name when using Java. */
const char *java_name;
+ /* Length of java name. */
+ int java_len;
/* How to print a value of this type. */
enum d_builtin_type_print print;
};
@@ -149,13 +169,19 @@ struct d_standard_sub_info
char code;
/* The simple string it expands to. */
const char *simple_expansion;
+ /* The length of the simple expansion. */
+ int simple_len;
/* The results of a full, verbose, expansion. This is used when
qualifying a constructor/destructor, or when in verbose mode. */
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
not set it. This is only relevant when qualifying a
constructor/destructor. */
const char *set_last_name;
+ /* The length of set_last_name. */
+ int set_last_name_len;
};
/* Component types found in mangled names. */
@@ -320,6 +346,7 @@ struct d_comp
struct
{
const char* string;
+ int len;
} s_string;
/* For D_COMP_TEMPLATE_PARAM. */
@@ -347,6 +374,8 @@ struct d_info
{
/* The string we are demangling. */
const char *s;
+ /* The end of the string we are demangling. */
+ const char *send;
/* The options passed to the demangler. */
int options;
/* The next character in the string to consider. */
@@ -363,8 +392,16 @@ struct d_info
int next_sub;
/* The number of available entries in the subs array. */
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. */
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))
@@ -444,13 +481,8 @@ struct d_print_info
} \
while (0)
-#define d_append_string(dpi, s) \
- do \
- { \
- size_t d_append_string_len = strlen (s); \
- d_append_buffer ((dpi), (s), d_append_string_len); \
- } \
- while (0)
+#define d_append_string_constant(dpi, s) \
+ d_append_buffer (dpi, (s), sizeof (s) - 1)
#define d_last_char(dpi) \
((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 *,
enum gnu_v3_dtor_kinds,
struct d_comp *));
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 int has_return_type 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));
static void d_print_append_buffer PARAMS ((struct d_print_info *, const char *,
size_t));
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 *,
const struct d_comp *));
-static void d_print_identifier PARAMS ((struct d_print_info *, const char *,
- int));
+static void d_print_java_identifier PARAMS ((struct d_print_info *,
+ const char *, int));
static void d_print_mod_list PARAMS ((struct d_print_info *,
struct d_print_mod *, int));
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 *,
const struct d_comp *));
static void d_print_cast PARAMS ((struct d_print_info *,
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 *));
#ifdef CP_DEMANGLE_DEBUG
@@ -961,15 +993,19 @@ d_make_template_param (di, i)
/* Add a new standard substitution component. */
static struct d_comp *
-d_make_sub (di, name)
+d_make_sub (di, name, len)
struct d_info *di;
const char *name;
+ int len;
{
struct d_comp *p;
p = d_make_empty (di, D_COMP_SUB_STD);
if (p != NULL)
- p->u.s_string.string = name;
+ {
+ p->u.s_string.string = name;
+ p->u.s_string.len = len;
+ }
return p;
}
@@ -1125,6 +1161,7 @@ d_name (di)
d_advance (di, 2);
dc = d_make_comp (di, D_COMP_QUAL_NAME, d_make_name (di, "std", 3),
d_unqualified_name (di));
+ di->expansion += 3;
subst = 0;
}
@@ -1275,7 +1312,14 @@ d_unqualified_name (di)
if (IS_DIGIT (peek))
return d_source_name (di);
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')
return d_ctor_dtor_name (di);
else
@@ -1305,15 +1349,15 @@ static long
d_number (di)
struct d_info *di;
{
- int sign;
+ int negative;
char peek;
long ret;
- sign = 1;
+ negative = 0;
peek = d_peek_char (di);
if (peek == 'n')
{
- sign = -1;
+ negative = 1;
d_advance (di, 1);
peek = d_peek_char (di);
}
@@ -1322,7 +1366,11 @@ d_number (di)
while (1)
{
if (! IS_DIGIT (peek))
- return ret * sign;
+ {
+ if (negative)
+ ret = - ret;
+ return ret;
+ }
ret = ret * 10 + peek - '0';
d_advance (di, 1);
peek = d_peek_char (di);
@@ -1339,6 +1387,10 @@ d_identifier (di, len)
const char *name;
name = d_str (di);
+
+ if (di->send - name < len)
+ return NULL;
+
d_advance (di, len);
/* A Java mangled name may have a trailing '$' if it is a C++
@@ -1360,8 +1412,11 @@ d_identifier (di, len)
s = name + ANONYMOUS_NAMESPACE_PREFIX_LEN;
if ((*s == '.' || *s == '_' || *s == '$')
&& 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);
@@ -1372,57 +1427,59 @@ d_identifier (di, len)
::= v <digit> <source-name>
*/
+#define NL(s) s, (sizeof s) - 1
+
static const struct d_operator_info d_operators[] =
{
- { "aN", "&=", 2 },
- { "aS", "=", 2 },
- { "aa", "&&", 2 },
- { "ad", "&", 1 },
- { "an", "&", 2 },
- { "cl", "()", 0 },
- { "cm", ",", 2 },
- { "co", "~", 1 },
- { "dV", "/=", 2 },
- { "da", "delete[]", 1 },
- { "de", "*", 1 },
- { "dl", "delete", 1 },
- { "dv", "/", 2 },
- { "eO", "^=", 2 },
- { "eo", "^", 2 },
- { "eq", "==", 2 },
- { "ge", ">=", 2 },
- { "gt", ">", 2 },
- { "ix", "[]", 2 },
- { "lS", "<<=", 2 },
- { "le", "<=", 2 },
- { "ls", "<<", 2 },
- { "lt", "<", 2 },
- { "mI", "-=", 2 },
- { "mL", "*=", 2 },
- { "mi", "-", 2 },
- { "ml", "*", 2 },
- { "mm", "--", 1 },
- { "na", "new[]", 1 },
- { "ne", "!=", 2 },
- { "ng", "-", 1 },
- { "nt", "!", 1 },
- { "nw", "new", 1 },
- { "oR", "|=", 2 },
- { "oo", "||", 2 },
- { "or", "|", 2 },
- { "pL", "+=", 2 },
- { "pl", "+", 2 },
- { "pm", "->*", 2 },
- { "pp", "++", 1 },
- { "ps", "+", 1 },
- { "pt", "->", 2 },
- { "qu", "?", 3 },
- { "rM", "%=", 2 },
- { "rS", ">>=", 2 },
- { "rm", "%", 2 },
- { "rs", ">>", 2 },
- { "st", "sizeof ", 1 },
- { "sz", "sizeof ", 1 }
+ { "aN", NL ("&="), 2 },
+ { "aS", NL ("="), 2 },
+ { "aa", NL ("&&"), 2 },
+ { "ad", NL ("&"), 1 },
+ { "an", NL ("&"), 2 },
+ { "cl", NL ("()"), 0 },
+ { "cm", NL (","), 2 },
+ { "co", NL ("~"), 1 },
+ { "dV", NL ("/="), 2 },
+ { "da", NL ("delete[]"), 1 },
+ { "de", NL ("*"), 1 },
+ { "dl", NL ("delete"), 1 },
+ { "dv", NL ("/"), 2 },
+ { "eO", NL ("^="), 2 },
+ { "eo", NL ("^"), 2 },
+ { "eq", NL ("=="), 2 },
+ { "ge", NL (">="), 2 },
+ { "gt", NL (">"), 2 },
+ { "ix", NL ("[]"), 2 },
+ { "lS", NL ("<<="), 2 },
+ { "le", NL ("<="), 2 },
+ { "ls", NL ("<<"), 2 },
+ { "lt", NL ("<"), 2 },
+ { "mI", NL ("-="), 2 },
+ { "mL", NL ("*="), 2 },
+ { "mi", NL ("-"), 2 },
+ { "ml", NL ("*"), 2 },
+ { "mm", NL ("--"), 1 },
+ { "na", NL ("new[]"), 1 },
+ { "ne", NL ("!="), 2 },
+ { "ng", NL ("-"), 1 },
+ { "nt", NL ("!"), 1 },
+ { "nw", NL ("new"), 1 },
+ { "oR", NL ("|="), 2 },
+ { "oo", NL ("||"), 2 },
+ { "or", NL ("|"), 2 },
+ { "pL", NL ("+="), 2 },
+ { "pl", NL ("+"), 2 },
+ { "pm", NL ("->*"), 2 },
+ { "pp", NL ("++"), 1 },
+ { "ps", NL ("+"), 1 },
+ { "pt", NL ("->"), 2 },
+ { "qu", NL ("?"), 3 },
+ { "rM", NL ("%="), 2 },
+ { "rS", NL (">>="), 2 },
+ { "rm", NL ("%"), 2 },
+ { "rs", NL (">>"), 2 },
+ { "st", NL ("sizeof "), 1 },
+ { "sz", NL ("sizeof "), 1 }
};
static struct d_comp *
@@ -1484,14 +1541,17 @@ d_special_name (di)
{
char c;
+ di->expansion += 20;
c = d_next_char (di);
if (c == 'T')
{
switch (d_next_char (di))
{
case 'V':
+ di->expansion -= 5;
return d_make_comp (di, D_COMP_VTABLE, d_type (di), NULL);
case 'T':
+ di->expansion -= 10;
return d_make_comp (di, D_COMP_VTT, d_type (di), NULL);
case 'I':
return d_make_comp (di, D_COMP_TYPEINFO, d_type (di), NULL);
@@ -1532,6 +1592,7 @@ d_special_name (di)
base_type = d_type (di);
/* We don't display the offset. FIXME: We should display
it in verbose mode. */
+ di->expansion += 5;
return d_make_comp (di, D_COMP_CONSTRUCTION_VTABLE, base_type,
derived_type);
}
@@ -1617,6 +1678,13 @@ static struct d_comp *
d_ctor_dtor_name (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))
{
case 'C':
@@ -1687,32 +1755,32 @@ d_ctor_dtor_name (di)
static const struct d_builtin_type_info d_builtin_types[26] =
{
- /* a */ { "signed char", "signed char", D_PRINT_INT },
- /* b */ { "bool", "boolean", D_PRINT_BOOL },
- /* c */ { "char", "byte", D_PRINT_INT },
- /* d */ { "double", "double", D_PRINT_DEFAULT },
- /* e */ { "long double", "long double", D_PRINT_DEFAULT },
- /* f */ { "float", "float", D_PRINT_DEFAULT },
- /* g */ { "__float128", "__float128", D_PRINT_DEFAULT },
- /* h */ { "unsigned char", "unsigned char", D_PRINT_INT },
- /* i */ { "int", "int", D_PRINT_INT },
- /* j */ { "unsigned int", "unsigned", D_PRINT_INT },
- /* k */ { NULL, NULL, D_PRINT_DEFAULT },
- /* l */ { "long", "long", D_PRINT_LONG },
- /* m */ { "unsigned long", "unsigned long", D_PRINT_LONG },
- /* n */ { "__int128", "__int128", D_PRINT_DEFAULT },
- /* o */ { "unsigned __int128", "unsigned __int128", D_PRINT_DEFAULT },
- /* p */ { NULL, NULL, D_PRINT_DEFAULT },
- /* q */ { NULL, NULL, D_PRINT_DEFAULT },
- /* r */ { NULL, NULL, D_PRINT_DEFAULT },
- /* s */ { "short", "short", D_PRINT_INT },
- /* t */ { "unsigned short", "unsigned short", D_PRINT_INT },
- /* u */ { NULL, NULL, D_PRINT_DEFAULT },
- /* v */ { "void", "void", D_PRINT_VOID },
- /* w */ { "wchar_t", "char", D_PRINT_INT },
- /* x */ { "long long", "long", D_PRINT_DEFAULT },
- /* y */ { "unsigned long long", "unsigned long long", D_PRINT_DEFAULT },
- /* z */ { "...", "...", D_PRINT_DEFAULT },
+ /* a */ { NL ("signed char"), NL ("signed char"), D_PRINT_INT },
+ /* b */ { NL ("bool"), NL ("boolean"), D_PRINT_BOOL },
+ /* c */ { NL ("char"), NL ("byte"), D_PRINT_INT },
+ /* d */ { NL ("double"), NL ("double"), D_PRINT_DEFAULT },
+ /* e */ { NL ("long double"), NL ("long double"), D_PRINT_DEFAULT },
+ /* f */ { NL ("float"), NL ("float"), D_PRINT_DEFAULT },
+ /* g */ { NL ("__float128"), NL ("__float128"), D_PRINT_DEFAULT },
+ /* h */ { NL ("unsigned char"), NL ("unsigned char"), D_PRINT_INT },
+ /* i */ { NL ("int"), NL ("int"), D_PRINT_INT },
+ /* j */ { NL ("unsigned int"), NL ("unsigned"), D_PRINT_INT },
+ /* k */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* l */ { NL ("long"), NL ("long"), D_PRINT_LONG },
+ /* m */ { NL ("unsigned long"), NL ("unsigned long"), D_PRINT_LONG },
+ /* n */ { NL ("__int128"), NL ("__int128"), D_PRINT_DEFAULT },
+ /* o */ { NL ("unsigned __int128"), NL ("unsigned __int128"), D_PRINT_DEFAULT },
+ /* p */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* q */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* r */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* s */ { NL ("short"), NL ("short"), D_PRINT_INT },
+ /* t */ { NL ("unsigned short"), NL ("unsigned short"), D_PRINT_INT },
+ /* u */ { NULL, 0, NULL, 0, D_PRINT_DEFAULT },
+ /* v */ { NL ("void"), NL ("void"), D_PRINT_VOID },
+ /* w */ { NL ("wchar_t"), NL ("char"), D_PRINT_INT },
+ /* x */ { NL ("long long"), NL ("long"), D_PRINT_DEFAULT },
+ /* y */ { NL ("unsigned long long"), NL ("unsigned long long"), D_PRINT_DEFAULT },
+ /* z */ { NL ("..."), NL ("..."), D_PRINT_DEFAULT },
};
static struct d_comp *
@@ -1761,6 +1829,7 @@ d_type (di)
case 'o': case 's': case 't':
case 'v': case 'w': case 'x': case 'y': case 'z':
ret = d_make_builtin_type (di, &d_builtin_types[peek - 'a']);
+ di->expansion += ret->u.s_builtin.type->len;
can_subst = 0;
d_advance (di, 1);
break;
@@ -1891,11 +1960,20 @@ d_cv_qualifiers (di, pret, member_fn)
d_advance (di, 1);
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')
- 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
- 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);
if (*pret == NULL)
@@ -1979,7 +2057,10 @@ d_bare_function_type (di, has_return_type)
if (d_right (tl) == NULL
&& d_left (tl)->type == D_COMP_BUILTIN_TYPE
&& 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);
}
@@ -2100,6 +2181,8 @@ d_template_param (di)
if (d_next_char (di) != '_')
return NULL;
+ ++di->did_subs;
+
return d_make_template_param (di, param);
}
@@ -2221,6 +2304,9 @@ d_expression (di)
if (op == NULL)
return NULL;
+ if (op->type == D_COMP_OPERATOR)
+ di->expansion += op->u.s_operator.op->len - 2;
+
if (op->type == D_COMP_OPERATOR
&& strcmp (op->u.s_operator.op->code, "st") == 0)
return d_make_comp (di, D_COMP_UNARY, op, d_type (di));
@@ -2296,6 +2382,12 @@ d_expr_primary (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
collect it as a string. Note that it's possible to have a
floating point literal here. The ABI specifies that the
@@ -2418,21 +2510,27 @@ d_add_substitution (di, dc)
static const struct d_standard_sub_info standard_subs[] =
{
- { 't', "std", "std", NULL },
- { 'a', "std::allocator", "std::allocator", "allocator" },
- { 'b', "std::basic_string", "std::basic_string", "basic_string" },
- { 's', "std::string",
- "std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
- "basic_string" },
- { 'i', "std::istream",
- "std::basic_istream<char, std::char_traits<char> >",
- "basic_istream" },
- { 'o', "std::ostream",
- "std::basic_ostream<char, std::char_traits<char> >",
- "basic_ostream" },
- { 'd', "std::iostream",
- "std::basic_iostream<char, std::char_traits<char> >",
- "basic_iostream" }
+ { 't', NL ("std"),
+ NL ("std"),
+ NULL, 0 },
+ { 'a', NL ("std::allocator"),
+ NL ("std::allocator"),
+ NL ("allocator") },
+ { 'b', NL ("std::basic_string"),
+ NL ("std::basic_string"),
+ NL ("basic_string") },
+ { 's', NL ("std::string"),
+ NL ("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
+ NL ("basic_string") },
+ { 'i', NL ("std::istream"),
+ NL ("std::basic_istream<char, std::char_traits<char> >"),
+ 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 *
@@ -2471,6 +2569,8 @@ d_substitution (di, prefix)
if (id >= di->next_sub)
return NULL;
+ ++di->did_subs;
+
return di->subs[id];
}
else
@@ -2495,12 +2595,24 @@ d_substitution (di, prefix)
{
if (c == p->code)
{
+ const char *s;
+ int len;
+
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)
- return d_make_sub (di, p->full_expansion);
+ {
+ s = p->full_expansion;
+ len = p->full_len;
+ }
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)
dpi->buf = NULL;
}
-/* Turn components into a human readable string. Returns a 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. */
+/* Turn components into a human readable string. OPTIONS is the
+ options bits passed to the demangler. DC is the tree to print.
+ ESTIMATE is a guess at the length of the result. This returns a
+ 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 *
-d_print (options, dc, palc)
+d_print (options, dc, estimate, palc)
int options;
const struct d_comp *dc;
+ int estimate;
size_t *palc;
{
struct d_print_info dpi;
dpi.options = options;
- dpi.alc = 64;
+ dpi.alc = estimate + 1;
dpi.buf = malloc (dpi.alc);
if (dpi.buf == NULL)
{
@@ -2651,13 +2767,19 @@ d_print_comp (dpi, dc)
switch (dc->type)
{
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;
case D_COMP_QUAL_NAME:
case D_COMP_LOCAL_NAME:
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));
return;
@@ -2844,69 +2966,69 @@ d_print_comp (dpi, dc)
return;
case D_COMP_VTABLE:
- d_append_string (dpi, "vtable for ");
+ d_append_string_constant (dpi, "vtable for ");
d_print_comp (dpi, d_left (dc));
return;
case D_COMP_VTT:
- d_append_string (dpi, "VTT for ");
+ d_append_string_constant (dpi, "VTT for ");
d_print_comp (dpi, d_left (dc));
return;
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_append_string (dpi, "-in-");
+ d_append_string_constant (dpi, "-in-");
d_print_comp (dpi, d_right (dc));
return;
case D_COMP_TYPEINFO:
- d_append_string (dpi, "typeinfo for ");
+ d_append_string_constant (dpi, "typeinfo for ");
d_print_comp (dpi, d_left (dc));
return;
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));
return;
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));
return;
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));
return;
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));
return;
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));
return;
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));
return;
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));
return;
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));
return;
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;
case D_COMP_RESTRICT:
@@ -2944,9 +3066,11 @@ d_print_comp (dpi, dc)
case D_COMP_BUILTIN_TYPE:
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
- 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;
case D_COMP_VENDOR_TYPE:
@@ -3026,7 +3150,7 @@ d_print_comp (dpi, dc)
{
d_append_char (dpi, ' ');
d_print_comp (dpi, d_left (dc));
- d_append_string (dpi, "::*");
+ d_append_string_constant (dpi, "::*");
}
dpi->modifiers = dpm.next;
@@ -3039,7 +3163,7 @@ d_print_comp (dpi, dc)
d_print_comp (dpi, d_left (dc));
if (d_right (dc) != NULL)
{
- d_append_string (dpi, ", ");
+ d_append_string_constant (dpi, ", ");
d_print_comp (dpi, d_right (dc));
}
return;
@@ -3048,21 +3172,22 @@ d_print_comp (dpi, dc)
{
char c;
- d_append_string (dpi, "operator");
+ d_append_string_constant (dpi, "operator");
c = dc->u.s_operator.op->name[0];
if (IS_LOWER (c))
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;
}
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);
return;
case D_COMP_CAST:
- d_append_string (dpi, "operator ");
+ d_append_string_constant (dpi, "operator ");
d_print_cast (dpi, dc);
return;
@@ -3071,7 +3196,7 @@ d_print_comp (dpi, dc)
d_print_expr_op (dpi, d_left (dc));
else
{
- d_append_string (dpi, "((");
+ d_append_string_constant (dpi, "((");
d_print_cast (dpi, d_left (dc));
d_append_char (dpi, ')');
}
@@ -3093,19 +3218,21 @@ d_print_comp (dpi, dc)
an extra layer of parens so that it does not get confused
with the '>' which ends the template parameters. */
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_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_append_string (dpi, " (");
+ d_append_string_constant (dpi, " (");
d_print_comp (dpi, d_right (d_right (dc)));
d_append_char (dpi, ')');
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, ')');
return;
@@ -3124,11 +3251,11 @@ d_print_comp (dpi, dc)
}
d_append_char (dpi, '(');
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_append_string (dpi, " (");
+ d_append_string_constant (dpi, " (");
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_append_char (dpi, ')');
return;
@@ -3175,10 +3302,10 @@ d_print_comp (dpi, dc)
switch (d_right (dc)->u.s_name.s[0])
{
case '0':
- d_append_string (dpi, "false");
+ d_append_string_constant (dpi, "false");
return;
case '1':
- d_append_string (dpi, "true");
+ d_append_string_constant (dpi, "true");
return;
default:
break;
@@ -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
-d_print_identifier (dpi, name, len)
+d_print_java_identifier (dpi, name, len)
struct d_print_info *dpi;
const char *name;
int len;
{
- if ((dpi->options & DMGL_JAVA) == 0)
- d_append_buffer (dpi, name, len);
- else
+ const char *p;
+ const char *end;
+
+ end = name + len;
+ for (p = name; p < end; ++p)
{
- const char *p;
- const char *end;
-
- /* 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>+_. */
- end = name + len;
- for (p = name; p < end; ++p)
+ if (end - p > 3
+ && p[0] == '_'
+ && p[1] == '_'
+ && p[2] == 'U')
{
- if (end - p > 3
- && p[0] == '_'
- && p[1] == '_'
- && p[2] == 'U')
+ unsigned long c;
+ const char *q;
+
+ c = 0;
+ for (q = p + 3; q < end; ++q)
{
- unsigned long c;
- const char *q;
+ int dig;
+
+ 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;
- for (q = p + 3; q < end; ++q)
- {
- int dig;
-
- 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 = 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;
- }
+ 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)
d_print_comp (dpi, d_left (mods->mod));
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);
while (dc->type == D_COMP_RESTRICT_THIS
@@ -3354,15 +3478,15 @@ d_print_mod (dpi, mod)
{
case D_COMP_RESTRICT:
case D_COMP_RESTRICT_THIS:
- d_append_string (dpi, " restrict");
+ d_append_string_constant (dpi, " restrict");
return;
case D_COMP_VOLATILE:
case D_COMP_VOLATILE_THIS:
- d_append_string (dpi, " volatile");
+ d_append_string_constant (dpi, " volatile");
return;
case D_COMP_CONST:
case D_COMP_CONST_THIS:
- d_append_string (dpi, " const");
+ d_append_string_constant (dpi, " const");
return;
case D_COMP_VENDOR_TYPE_QUAL:
d_append_char (dpi, ' ');
@@ -3377,16 +3501,16 @@ d_print_mod (dpi, mod)
d_append_char (dpi, '&');
return;
case D_COMP_COMPLEX:
- d_append_string (dpi, "complex ");
+ d_append_string_constant (dpi, "complex ");
return;
case D_COMP_IMAGINARY:
- d_append_string (dpi, "imaginary ");
+ d_append_string_constant (dpi, "imaginary ");
return;
case D_COMP_PTRMEM_TYPE:
if (d_last_char (dpi) != '(')
d_append_char (dpi, ' ');
d_print_comp (dpi, d_left (mod));
- d_append_string (dpi, "::*");
+ d_append_string_constant (dpi, "::*");
return;
case D_COMP_TYPED_NAME:
d_print_comp (dpi, d_left (mod));
@@ -3520,7 +3644,7 @@ d_print_array_type (dpi, dc, mods)
}
if (need_paren)
- d_append_string (dpi, " (");
+ d_append_string_constant (dpi, " (");
d_print_mod_list (dpi, mods, 0);
@@ -3547,7 +3671,8 @@ d_print_expr_op (dpi, dc)
const struct d_comp *dc;
{
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
d_print_comp (dpi, dc);
}
@@ -3599,7 +3724,7 @@ d_print_cast (dpi, dc)
/* Initialize the information structure we use to pass around
information. */
-static int
+static void
d_init_info (mangled, options, len, di)
const char *mangled;
int options;
@@ -3607,6 +3732,7 @@ d_init_info (mangled, options, len, di)
struct d_info *di;
{
di->s = mangled;
+ di->send = mangled + len;
di->options = options;
di->n = mangled;
@@ -3615,29 +3741,17 @@ d_init_info (mangled, options, len, di)
the mangled string. Most components correspond directly to
chars, but the ARGLIST types are exceptions. */
di->num_comps = 2 * len;
- di->comps = (struct d_comp *) malloc (di->num_comps
- * sizeof (struct d_comp));
di->next_comp = 0;
/* Similarly, we can not need more substitutions than there are
chars in the mangled string. */
di->num_subs = len;
- di->subs = (struct d_comp **) malloc (di->num_subs
- * sizeof (struct d_comp *));
di->next_sub = 0;
+ di->did_subs = 0;
di->last_name = NULL;
- if (di->comps == NULL || di->subs == NULL)
- {
- if (di->comps != NULL)
- free (di->comps);
- if (di->subs != NULL)
- free (di->subs);
- return 0;
- }
-
- return 1;
+ di->expansion = 0;
}
/* Entry point for the demangler. If MANGLED is a g++ v3 ABI mangled
@@ -3657,6 +3771,7 @@ d_demangle (mangled, options, palc)
int type;
struct d_info di;
struct d_comp *dc;
+ int estimate;
char *ret;
*palc = 0;
@@ -3692,39 +3807,82 @@ d_demangle (mangled, options, palc)
type = 1;
}
- if (! d_init_info (mangled, options, len, &di))
- {
- *palc = 1;
- return NULL;
- }
+ d_init_info (mangled, options, len, &di);
- if (! type)
- dc = d_mangled_name (&di, 1);
- else
- dc = d_type (&di);
+ {
+#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
+
+ 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
- mangled string, then we didn't successfully demangle it. If
- DMGL_PARAMS is not set, we didn't look at the trailing
- parameters. */
- if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0')
- dc = NULL;
+ /* If DMGL_PARAMS is set, then if we didn't consume the entire
+ mangled string, then we didn't successfully demangle it. If
+ DMGL_PARAMS is not set, we didn't look at the trailing
+ parameters. */
+ if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0')
+ dc = NULL;
#ifdef CP_DEMANGLE_DEBUG
- if (dc == NULL)
- printf ("failed demangling\n");
- else
- d_dump (dc, 0);
+ if (dc == NULL)
+ printf ("failed demangling\n");
+ else
+ d_dump (dc, 0);
#endif
- free (di.subs);
- di.subs = NULL;
+ /* We try to guess the length of the demangled string, to minimize
+ calls to realloc during demangling. */
+ estimate = len + di.expansion + 10 * di.did_subs;
+ estimate += estimate / 8;
- ret = NULL;
- if (dc != NULL)
- ret = d_print (options, dc, palc);
+ ret = NULL;
+ if (dc != NULL)
+ 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;
}
@@ -3907,48 +4065,73 @@ is_ctor_or_dtor (mangled, ctor_kind, dtor_kind)
*ctor_kind = (enum gnu_v3_ctor_kinds) 0;
*dtor_kind = (enum gnu_v3_dtor_kinds) 0;
- if (! d_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di))
- return 0;
+ d_init_info (mangled, DMGL_GNU_V3, strlen (mangled), &di);
- 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
- demangle the entire string. */
+ dc = d_mangled_name (&di, 1);
- ret = 0;
- 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;
- }
- }
+ /* Note that because we did not pass DMGL_PARAMS, we don't expect
+ to demangle the entire string. */
- free (di.subs);
- free (di.comps);
+ ret = 0;
+ 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;
}