#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "safe-ctype.h"
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else
char * malloc ();
char * realloc ();
#endif
#include <demangle.h>
#undef CURRENT_DEMANGLING_STYLE
#define CURRENT_DEMANGLING_STYLE work->options
#include "libiberty.h"
static char *ada_demangle PARAMS ((const char *, int));
#define min(X,Y) (((X) < (Y)) ? (X) : (Y))
#define INTBUF_SIZE 32
extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
#if !defined (CPLUS_MARKER)
#define CPLUS_MARKER '$'
#endif
enum demangling_styles current_demangling_style = auto_demangling;
static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
static char char_str[2] = { '\000', '\000' };
void
set_cplus_marker_for_demangling (ch)
int ch;
{
cplus_markers[0] = ch;
}
typedef struct string
{
char *b;
char *p;
char *e;
} string;
struct work_stuff
{
int options;
char **typevec;
char **ktypevec;
char **btypevec;
int numk;
int numb;
int ksize;
int bsize;
int ntypes;
int typevec_size;
int constructor;
int destructor;
int static_type;
int temp_start;
int type_quals;
int dllimported;
char **tmpl_argvec;
int ntmpl_args;
int forgetting_types;
string* previous_argument;
int nrepeats;
};
#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
static const struct optable
{
const char *const in;
const char *const out;
const int flags;
} optable[] = {
{"nw", " new", DMGL_ANSI},
{"dl", " delete", DMGL_ANSI},
{"new", " new", 0},
{"delete", " delete", 0},
{"vn", " new []", DMGL_ANSI},
{"vd", " delete []", DMGL_ANSI},
{"as", "=", DMGL_ANSI},
{"ne", "!=", DMGL_ANSI},
{"eq", "==", DMGL_ANSI},
{"ge", ">=", DMGL_ANSI},
{"gt", ">", DMGL_ANSI},
{"le", "<=", DMGL_ANSI},
{"lt", "<", DMGL_ANSI},
{"plus", "+", 0},
{"pl", "+", DMGL_ANSI},
{"apl", "+=", DMGL_ANSI},
{"minus", "-", 0},
{"mi", "-", DMGL_ANSI},
{"ami", "-=", DMGL_ANSI},
{"mult", "*", 0},
{"ml", "*", DMGL_ANSI},
{"amu", "*=", DMGL_ANSI},
{"aml", "*=", DMGL_ANSI},
{"convert", "+", 0},
{"negate", "-", 0},
{"trunc_mod", "%", 0},
{"md", "%", DMGL_ANSI},
{"amd", "%=", DMGL_ANSI},
{"trunc_div", "/", 0},
{"dv", "/", DMGL_ANSI},
{"adv", "/=", DMGL_ANSI},
{"truth_andif", "&&", 0},
{"aa", "&&", DMGL_ANSI},
{"truth_orif", "||", 0},
{"oo", "||", DMGL_ANSI},
{"truth_not", "!", 0},
{"nt", "!", DMGL_ANSI},
{"postincrement","++", 0},
{"pp", "++", DMGL_ANSI},
{"postdecrement","--", 0},
{"mm", "--", DMGL_ANSI},
{"bit_ior", "|", 0},
{"or", "|", DMGL_ANSI},
{"aor", "|=", DMGL_ANSI},
{"bit_xor", "^", 0},
{"er", "^", DMGL_ANSI},
{"aer", "^=", DMGL_ANSI},
{"bit_and", "&", 0},
{"ad", "&", DMGL_ANSI},
{"aad", "&=", DMGL_ANSI},
{"bit_not", "~", 0},
{"co", "~", DMGL_ANSI},
{"call", "()", 0},
{"cl", "()", DMGL_ANSI},
{"alshift", "<<", 0},
{"ls", "<<", DMGL_ANSI},
{"als", "<<=", DMGL_ANSI},
{"arshift", ">>", 0},
{"rs", ">>", DMGL_ANSI},
{"ars", ">>=", DMGL_ANSI},
{"component", "->", 0},
{"pt", "->", DMGL_ANSI},
{"rf", "->", DMGL_ANSI},
{"indirect", "*", 0},
{"method_call", "->()", 0},
{"addr", "&", 0},
{"array", "[]", 0},
{"vc", "[]", DMGL_ANSI},
{"compound", ", ", 0},
{"cm", ", ", DMGL_ANSI},
{"cond", "?:", 0},
{"cn", "?:", DMGL_ANSI},
{"max", ">?", 0},
{"mx", ">?", DMGL_ANSI},
{"min", "<?", 0},
{"mn", "<?", DMGL_ANSI},
{"nop", "", 0},
{"rm", "->*", DMGL_ANSI},
{"sz", "sizeof ", DMGL_ANSI}
};
typedef enum type_kind_t
{
tk_none,
tk_pointer,
tk_reference,
tk_integral,
tk_bool,
tk_char,
tk_real
} type_kind_t;
const struct demangler_engine libiberty_demanglers[] =
{
{
NO_DEMANGLING_STYLE_STRING,
no_demangling,
"Demangling disabled"
}
,
{
AUTO_DEMANGLING_STYLE_STRING,
auto_demangling,
"Automatic selection based on executable"
}
,
{
GNU_DEMANGLING_STYLE_STRING,
gnu_demangling,
"GNU (g++) style demangling"
}
,
{
LUCID_DEMANGLING_STYLE_STRING,
lucid_demangling,
"Lucid (lcc) style demangling"
}
,
{
ARM_DEMANGLING_STYLE_STRING,
arm_demangling,
"ARM style demangling"
}
,
{
HP_DEMANGLING_STYLE_STRING,
hp_demangling,
"HP (aCC) style demangling"
}
,
{
EDG_DEMANGLING_STYLE_STRING,
edg_demangling,
"EDG style demangling"
}
,
{
GNU_V3_DEMANGLING_STYLE_STRING,
gnu_v3_demangling,
"GNU (g++) V3 ABI-style demangling"
}
,
{
JAVA_DEMANGLING_STYLE_STRING,
java_demangling,
"Java style demangling"
}
,
{
GNAT_DEMANGLING_STYLE_STRING,
gnat_demangling,
"GNAT style demangling"
}
,
{
NULL, unknown_demangling, NULL
}
};
#define STRING_EMPTY(str) ((str) -> b == (str) -> p)
#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
string_append(str, " ");}
#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
#define ARM_VTABLE_STRING "__vtbl__"
#define ARM_VTABLE_STRLEN 8
static void
delete_work_stuff PARAMS ((struct work_stuff *));
static void
delete_non_B_K_work_stuff PARAMS ((struct work_stuff *));
static char *
mop_up PARAMS ((struct work_stuff *, string *, int));
static void
squangle_mop_up PARAMS ((struct work_stuff *));
static void
work_stuff_copy_to_from PARAMS ((struct work_stuff *, struct work_stuff *));
#if 0
static int
demangle_method_args PARAMS ((struct work_stuff *, const char **, string *));
#endif
static char *
internal_cplus_demangle PARAMS ((struct work_stuff *, const char *));
static int
demangle_template_template_parm PARAMS ((struct work_stuff *work,
const char **, string *));
static int
demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
string *, int, int));
static int
arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
const char **));
static int
demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
static int
demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
int, int));
static int
demangle_class PARAMS ((struct work_stuff *, const char **, string *));
static int
demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
static int
demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
static int
demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
static int
gnu_special PARAMS ((struct work_stuff *, const char **, string *));
static int
arm_special PARAMS ((const char **, string *));
static void
string_need PARAMS ((string *, int));
static void
string_delete PARAMS ((string *));
static void
string_init PARAMS ((string *));
static void
string_clear PARAMS ((string *));
#if 0
static int
string_empty PARAMS ((string *));
#endif
static void
string_append PARAMS ((string *, const char *));
static void
string_appends PARAMS ((string *, string *));
static void
string_appendn PARAMS ((string *, const char *, int));
static void
string_prepend PARAMS ((string *, const char *));
static void
string_prependn PARAMS ((string *, const char *, int));
static void
string_append_template_idx PARAMS ((string *, int));
static int
get_count PARAMS ((const char **, int *));
static int
consume_count PARAMS ((const char **));
static int
consume_count_with_underscores PARAMS ((const char**));
static int
demangle_args PARAMS ((struct work_stuff *, const char **, string *));
static int
demangle_nested_args PARAMS ((struct work_stuff*, const char**, string*));
static int
do_type PARAMS ((struct work_stuff *, const char **, string *));
static int
do_arg PARAMS ((struct work_stuff *, const char **, string *));
static void
demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
const char *));
static int
iterate_demangle_function PARAMS ((struct work_stuff *,
const char **, string *, const char *));
static void
remember_type PARAMS ((struct work_stuff *, const char *, int));
static void
remember_Btype PARAMS ((struct work_stuff *, const char *, int, int));
static int
register_Btype PARAMS ((struct work_stuff *));
static void
remember_Ktype PARAMS ((struct work_stuff *, const char *, int));
static void
forget_types PARAMS ((struct work_stuff *));
static void
forget_B_and_K_types PARAMS ((struct work_stuff *));
static void
string_prepends PARAMS ((string *, string *));
static int
demangle_template_value_parm PARAMS ((struct work_stuff*, const char**,
string*, type_kind_t));
static int
do_hpacc_template_const_value PARAMS ((struct work_stuff *, const char **, string *));
static int
do_hpacc_template_literal PARAMS ((struct work_stuff *, const char **, string *));
static int
snarf_numeric_literal PARAMS ((const char **, string *));
#define TYPE_UNQUALIFIED 0x0
#define TYPE_QUAL_CONST 0x1
#define TYPE_QUAL_VOLATILE 0x2
#define TYPE_QUAL_RESTRICT 0x4
static int
code_for_qualifier PARAMS ((int));
static const char*
qualifier_string PARAMS ((int));
static const char*
demangle_qualifier PARAMS ((int));
static int
demangle_expression PARAMS ((struct work_stuff *, const char **, string *,
type_kind_t));
static int
demangle_integral_value PARAMS ((struct work_stuff *, const char **,
string *));
static int
demangle_real_value PARAMS ((struct work_stuff *, const char **, string *));
static void
demangle_arm_hp_template PARAMS ((struct work_stuff *, const char **, int,
string *));
static void
recursively_demangle PARAMS ((struct work_stuff *, const char **, string *,
int));
static void
grow_vect PARAMS ((char **, size_t *, size_t, int));
static int
consume_count (type)
const char **type;
{
int count = 0;
if (! ISDIGIT ((unsigned char)**type))
return -1;
while (ISDIGIT ((unsigned char)**type))
{
count *= 10;
if ((count % 10) != 0)
{
while (ISDIGIT ((unsigned char) **type))
(*type)++;
return -1;
}
count += **type - '0';
(*type)++;
}
if (count < 0)
count = -1;
return (count);
}
static int
consume_count_with_underscores (mangled)
const char **mangled;
{
int idx;
if (**mangled == '_')
{
(*mangled)++;
if (!ISDIGIT ((unsigned char)**mangled))
return -1;
idx = consume_count (mangled);
if (**mangled != '_')
return -1;
(*mangled)++;
}
else
{
if (**mangled < '0' || **mangled > '9')
return -1;
idx = **mangled - '0';
(*mangled)++;
}
return idx;
}
static int
code_for_qualifier (c)
int c;
{
switch (c)
{
case 'C':
return TYPE_QUAL_CONST;
case 'V':
return TYPE_QUAL_VOLATILE;
case 'u':
return TYPE_QUAL_RESTRICT;
default:
break;
}
abort ();
}
static const char*
qualifier_string (type_quals)
int type_quals;
{
switch (type_quals)
{
case TYPE_UNQUALIFIED:
return "";
case TYPE_QUAL_CONST:
return "const";
case TYPE_QUAL_VOLATILE:
return "volatile";
case TYPE_QUAL_RESTRICT:
return "__restrict";
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
return "const volatile";
case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
return "const __restrict";
case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
return "volatile __restrict";
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
return "const volatile __restrict";
default:
break;
}
abort ();
}
static const char*
demangle_qualifier (c)
int c;
{
return qualifier_string (code_for_qualifier (c));
}
int
cplus_demangle_opname (opname, result, options)
const char *opname;
char *result;
int options;
{
int len, len1, ret;
string type;
struct work_stuff work[1];
const char *tem;
len = strlen(opname);
result[0] = '\0';
ret = 0;
memset ((char *) work, 0, sizeof (work));
work->options = options;
if (opname[0] == '_' && opname[1] == '_'
&& opname[2] == 'o' && opname[3] == 'p')
{
tem = opname + 4;
if (do_type (work, &tem, &type))
{
strcat (result, "operator ");
strncat (result, type.b, type.p - type.b);
string_delete (&type);
ret = 1;
}
}
else if (opname[0] == '_' && opname[1] == '_'
&& ISLOWER((unsigned char)opname[2])
&& ISLOWER((unsigned char)opname[3]))
{
if (opname[4] == '\0')
{
size_t i;
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 2
&& memcmp (optable[i].in, opname + 2, 2) == 0)
{
strcat (result, "operator");
strcat (result, optable[i].out);
ret = 1;
break;
}
}
}
else
{
if (opname[2] == 'a' && opname[5] == '\0')
{
size_t i;
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 3
&& memcmp (optable[i].in, opname + 2, 3) == 0)
{
strcat (result, "operator");
strcat (result, optable[i].out);
ret = 1;
break;
}
}
}
}
}
else if (len >= 3
&& opname[0] == 'o'
&& opname[1] == 'p'
&& strchr (cplus_markers, opname[2]) != NULL)
{
if (len >= 10
&& memcmp (opname + 3, "assign_", 7) == 0)
{
size_t i;
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
len1 = len - 10;
if ((int) strlen (optable[i].in) == len1
&& memcmp (optable[i].in, opname + 10, len1) == 0)
{
strcat (result, "operator");
strcat (result, optable[i].out);
strcat (result, "=");
ret = 1;
break;
}
}
}
else
{
size_t i;
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
len1 = len - 3;
if ((int) strlen (optable[i].in) == len1
&& memcmp (optable[i].in, opname + 3, len1) == 0)
{
strcat (result, "operator");
strcat (result, optable[i].out);
ret = 1;
break;
}
}
}
}
else if (len >= 5 && memcmp (opname, "type", 4) == 0
&& strchr (cplus_markers, opname[4]) != NULL)
{
tem = opname + 5;
if (do_type (work, &tem, &type))
{
strcat (result, "operator ");
strncat (result, type.b, type.p - type.b);
string_delete (&type);
ret = 1;
}
}
squangle_mop_up (work);
return ret;
}
const char *
cplus_mangle_opname (opname, options)
const char *opname;
int options;
{
size_t i;
int len;
len = strlen (opname);
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if ((int) strlen (optable[i].out) == len
&& (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
&& memcmp (optable[i].out, opname, len) == 0)
return optable[i].in;
}
return (0);
}
enum demangling_styles
cplus_demangle_set_style (style)
enum demangling_styles style;
{
const struct demangler_engine *demangler = libiberty_demanglers;
for (; demangler->demangling_style != unknown_demangling; ++demangler)
if (style == demangler->demangling_style)
{
current_demangling_style = style;
return current_demangling_style;
}
return unknown_demangling;
}
enum demangling_styles
cplus_demangle_name_to_style (name)
const char *name;
{
const struct demangler_engine *demangler = libiberty_demanglers;
for (; demangler->demangling_style != unknown_demangling; ++demangler)
if (strcmp (name, demangler->demangling_style_name) == 0)
return demangler->demangling_style;
return unknown_demangling;
}
char *
cplus_demangle (mangled, options)
const char *mangled;
int options;
{
char *ret;
struct work_stuff work[1];
if (current_demangling_style == no_demangling)
return xstrdup (mangled);
memset ((char *) work, 0, sizeof (work));
work->options = options;
if ((work->options & DMGL_STYLE_MASK) == 0)
work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
{
ret = cplus_demangle_v3 (mangled, work->options);
if (ret || GNU_V3_DEMANGLING)
return ret;
}
if (JAVA_DEMANGLING)
{
ret = java_demangle_v3 (mangled);
if (ret)
return ret;
}
if (GNAT_DEMANGLING)
return ada_demangle(mangled,options);
ret = internal_cplus_demangle (work, mangled);
squangle_mop_up (work);
return (ret);
}
static void
grow_vect (old_vect, size, min_size, element_size)
char **old_vect;
size_t *size;
size_t min_size;
int element_size;
{
if (*size < min_size)
{
*size *= 2;
if (*size < min_size)
*size = min_size;
*old_vect = (void *) xrealloc (*old_vect, *size * element_size);
}
}
static char *
ada_demangle (mangled, option)
const char *mangled;
int option ATTRIBUTE_UNUSED;
{
int i, j;
int len0;
const char* p;
char *demangled = NULL;
int at_start_name;
int changed;
size_t demangled_size = 0;
changed = 0;
if (strncmp (mangled, "_ada_", 5) == 0)
{
mangled += 5;
changed = 1;
}
if (mangled[0] == '_' || mangled[0] == '<')
goto Suppress;
p = strstr (mangled, "___");
if (p == NULL)
len0 = strlen (mangled);
else
{
if (p[3] == 'X')
{
len0 = p - mangled;
changed = 1;
}
else
goto Suppress;
}
grow_vect (&demangled,
&demangled_size, 2 * len0 + 1,
sizeof (char));
if (ISDIGIT ((unsigned char) mangled[len0 - 1])) {
for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1)
;
if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_')
{
len0 = i - 1;
changed = 1;
}
else if (mangled[i] == '$')
{
len0 = i;
changed = 1;
}
}
for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
i += 1, j += 1)
demangled[j] = mangled[i];
at_start_name = 1;
while (i < len0)
{
at_start_name = 0;
if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_')
{
demangled[j] = '.';
changed = at_start_name = 1;
i += 2; j += 1;
}
else
{
demangled[j] = mangled[i];
i += 1; j += 1;
}
}
demangled[j] = '\000';
for (i = 0; demangled[i] != '\0'; i += 1)
if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ')
goto Suppress;
if (! changed)
return NULL;
else
return demangled;
Suppress:
grow_vect (&demangled,
&demangled_size, strlen (mangled) + 3,
sizeof (char));
if (mangled[0] == '<')
strcpy (demangled, mangled);
else
sprintf (demangled, "<%s>", mangled);
return demangled;
}
static char *
internal_cplus_demangle (work, mangled)
struct work_stuff *work;
const char *mangled;
{
string decl;
int success = 0;
char *demangled = NULL;
int s1, s2, s3, s4;
s1 = work->constructor;
s2 = work->destructor;
s3 = work->static_type;
s4 = work->type_quals;
work->constructor = work->destructor = 0;
work->type_quals = TYPE_UNQUALIFIED;
work->dllimported = 0;
if ((mangled != NULL) && (*mangled != '\0'))
{
string_init (&decl);
if ((AUTO_DEMANGLING || GNU_DEMANGLING))
{
success = gnu_special (work, &mangled, &decl);
}
if (!success)
{
success = demangle_prefix (work, &mangled, &decl);
}
if (success && (*mangled != '\0'))
{
success = demangle_signature (work, &mangled, &decl);
}
if (work->constructor == 2)
{
string_prepend (&decl, "global constructors keyed to ");
work->constructor = 0;
}
else if (work->destructor == 2)
{
string_prepend (&decl, "global destructors keyed to ");
work->destructor = 0;
}
else if (work->dllimported == 1)
{
string_prepend (&decl, "import stub for ");
work->dllimported = 0;
}
demangled = mop_up (work, &decl, success);
}
work->constructor = s1;
work->destructor = s2;
work->static_type = s3;
work->type_quals = s4;
return demangled;
}
static void
squangle_mop_up (work)
struct work_stuff *work;
{
forget_B_and_K_types (work);
if (work -> btypevec != NULL)
{
free ((char *) work -> btypevec);
}
if (work -> ktypevec != NULL)
{
free ((char *) work -> ktypevec);
}
}
static void
work_stuff_copy_to_from (to, from)
struct work_stuff *to;
struct work_stuff *from;
{
int i;
delete_work_stuff (to);
memcpy (to, from, sizeof (*to));
if (from->typevec_size)
to->typevec
= (char **) xmalloc (from->typevec_size * sizeof (to->typevec[0]));
for (i = 0; i < from->ntypes; i++)
{
int len = strlen (from->typevec[i]) + 1;
to->typevec[i] = xmalloc (len);
memcpy (to->typevec[i], from->typevec[i], len);
}
if (from->ksize)
to->ktypevec
= (char **) xmalloc (from->ksize * sizeof (to->ktypevec[0]));
for (i = 0; i < from->numk; i++)
{
int len = strlen (from->ktypevec[i]) + 1;
to->ktypevec[i] = xmalloc (len);
memcpy (to->ktypevec[i], from->ktypevec[i], len);
}
if (from->bsize)
to->btypevec
= (char **) xmalloc (from->bsize * sizeof (to->btypevec[0]));
for (i = 0; i < from->numb; i++)
{
int len = strlen (from->btypevec[i]) + 1;
to->btypevec[i] = xmalloc (len);
memcpy (to->btypevec[i], from->btypevec[i], len);
}
if (from->ntmpl_args)
to->tmpl_argvec
= (char **) xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0]));
for (i = 0; i < from->ntmpl_args; i++)
{
int len = strlen (from->tmpl_argvec[i]) + 1;
to->tmpl_argvec[i] = xmalloc (len);
memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
}
if (from->previous_argument)
{
to->previous_argument = (string*) xmalloc (sizeof (string));
string_init (to->previous_argument);
string_appends (to->previous_argument, from->previous_argument);
}
}
static void
delete_non_B_K_work_stuff (work)
struct work_stuff *work;
{
forget_types (work);
if (work -> typevec != NULL)
{
free ((char *) work -> typevec);
work -> typevec = NULL;
work -> typevec_size = 0;
}
if (work->tmpl_argvec)
{
int i;
for (i = 0; i < work->ntmpl_args; i++)
if (work->tmpl_argvec[i])
free ((char*) work->tmpl_argvec[i]);
free ((char*) work->tmpl_argvec);
work->tmpl_argvec = NULL;
}
if (work->previous_argument)
{
string_delete (work->previous_argument);
free ((char*) work->previous_argument);
work->previous_argument = NULL;
}
}
static void
delete_work_stuff (work)
struct work_stuff *work;
{
delete_non_B_K_work_stuff (work);
squangle_mop_up (work);
}
static char *
mop_up (work, declp, success)
struct work_stuff *work;
string *declp;
int success;
{
char *demangled = NULL;
delete_non_B_K_work_stuff (work);
if (!success)
{
string_delete (declp);
}
else
{
string_appendn (declp, "", 1);
demangled = declp->b;
}
return (demangled);
}
static int
demangle_signature (work, mangled, declp)
struct work_stuff *work;
const char **mangled;
string *declp;
{
int success = 1;
int func_done = 0;
int expect_func = 0;
int expect_return_type = 0;
const char *oldmangled = NULL;
string trawname;
string tname;
while (success && (**mangled != '\0'))
{
switch (**mangled)
{
case 'Q':
oldmangled = *mangled;
success = demangle_qualified (work, mangled, declp, 1, 0);
if (success)
remember_type (work, oldmangled, *mangled - oldmangled);
if (AUTO_DEMANGLING || GNU_DEMANGLING)
expect_func = 1;
oldmangled = NULL;
break;
case 'K':
oldmangled = *mangled;
success = demangle_qualified (work, mangled, declp, 1, 0);
if (AUTO_DEMANGLING || GNU_DEMANGLING)
{
expect_func = 1;
}
oldmangled = NULL;
break;
case 'S':
if (oldmangled == NULL)
{
oldmangled = *mangled;
}
(*mangled)++;
work -> static_type = 1;
break;
case 'C':
case 'V':
case 'u':
work->type_quals |= code_for_qualifier (**mangled);
if (oldmangled == NULL)
oldmangled = *mangled;
(*mangled)++;
break;
case 'L':
if (HP_DEMANGLING)
{
while (**mangled && (**mangled != '_'))
(*mangled)++;
if (!**mangled)
success = 0;
else
(*mangled)++;
}
else
success = 0;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (oldmangled == NULL)
{
oldmangled = *mangled;
}
work->temp_start = -1;
success = demangle_class (work, mangled, declp);
if (success)
{
remember_type (work, oldmangled, *mangled - oldmangled);
}
if (AUTO_DEMANGLING || GNU_DEMANGLING || EDG_DEMANGLING)
{
if (**mangled != 'F')
expect_func = 1;
}
oldmangled = NULL;
break;
case 'B':
{
string s;
success = do_type (work, mangled, &s);
if (success)
{
string_append (&s, SCOPE_STRING (work));
string_prepends (declp, &s);
string_delete (&s);
}
oldmangled = NULL;
expect_func = 1;
}
break;
case 'F':
oldmangled = NULL;
func_done = 1;
(*mangled)++;
if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
{
forget_types (work);
}
success = demangle_args (work, mangled, declp);
if (success && (AUTO_DEMANGLING || EDG_DEMANGLING) && **mangled == '_')
{
++(*mangled);
success = do_type (work, mangled, &tname);
string_delete (&tname);
}
break;
case 't':
string_init(&trawname);
string_init(&tname);
if (oldmangled == NULL)
{
oldmangled = *mangled;
}
success = demangle_template (work, mangled, &tname,
&trawname, 1, 1);
if (success)
{
remember_type (work, oldmangled, *mangled - oldmangled);
}
string_append (&tname, SCOPE_STRING (work));
string_prepends(declp, &tname);
if (work -> destructor & 1)
{
string_prepend (&trawname, "~");
string_appends (declp, &trawname);
work->destructor -= 1;
}
if ((work->constructor & 1) || (work->destructor & 1))
{
string_appends (declp, &trawname);
work->constructor -= 1;
}
string_delete(&trawname);
string_delete(&tname);
oldmangled = NULL;
expect_func = 1;
break;
case '_':
if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type)
{
string return_type;
(*mangled)++;
success = do_type (work, mangled, &return_type);
APPEND_BLANK (&return_type);
string_prepends (declp, &return_type);
string_delete (&return_type);
break;
}
else
if (HP_DEMANGLING)
{
(*mangled)++;
while (**mangled && ISDIGIT ((unsigned char)**mangled))
(*mangled)++;
}
else
success = 0;
break;
case 'H':
if (AUTO_DEMANGLING || GNU_DEMANGLING)
{
success = demangle_template (work, mangled, declp, 0, 0,
0);
if (!(work->constructor & 1))
expect_return_type = 1;
(*mangled)++;
break;
}
else
{;}
default:
if (AUTO_DEMANGLING || GNU_DEMANGLING)
{
func_done = 1;
success = demangle_args (work, mangled, declp);
}
else
{
success = 0;
}
break;
}
{
if (success && expect_func)
{
func_done = 1;
if (LUCID_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING)
{
forget_types (work);
}
success = demangle_args (work, mangled, declp);
expect_func = 0;
}
}
}
if (success && !func_done)
{
if (AUTO_DEMANGLING || GNU_DEMANGLING)
{
success = demangle_args (work, mangled, declp);
}
}
if (success && PRINT_ARG_TYPES)
{
if (work->static_type)
string_append (declp, " static");
if (work->type_quals != TYPE_UNQUALIFIED)
{
APPEND_BLANK (declp);
string_append (declp, qualifier_string (work->type_quals));
}
}
return (success);
}
#if 0
static int
demangle_method_args (work, mangled, declp)
struct work_stuff *work;
const char **mangled;
string *declp;
{
int success = 0;
if (work -> static_type)
{
string_append (declp, *mangled + 1);
*mangled += strlen (*mangled);
success = 1;
}
else
{
success = demangle_args (work, mangled, declp);
}
return (success);
}
#endif
static int
demangle_template_template_parm (work, mangled, tname)
struct work_stuff *work;
const char **mangled;
string *tname;
{
int i;
int r;
int need_comma = 0;
int success = 1;
string temp;
string_append (tname, "template <");
if (get_count (mangled, &r))
{
for (i = 0; i < r; i++)
{
if (need_comma)
{
string_append (tname, ", ");
}
if (**mangled == 'Z')
{
(*mangled)++;
string_append (tname, "class");
}
else if (**mangled == 'z')
{
(*mangled)++;
success =
demangle_template_template_parm (work, mangled, tname);
if (!success)
{
break;
}
}
else
{
success = do_type (work, mangled, &temp);
if (success)
{
string_appends (tname, &temp);
}
string_delete(&temp);
if (!success)
{
break;
}
}
need_comma = 1;
}
}
if (tname->p[-1] == '>')
string_append (tname, " ");
string_append (tname, "> class");
return (success);
}
static int
demangle_expression (work, mangled, s, tk)
struct work_stuff *work;
const char** mangled;
string* s;
type_kind_t tk;
{
int need_operator = 0;
int success;
success = 1;
string_appendn (s, "(", 1);
(*mangled)++;
while (success && **mangled != 'W' && **mangled != '\0')
{
if (need_operator)
{
size_t i;
size_t len;
success = 0;
len = strlen (*mangled);
for (i = 0; i < ARRAY_SIZE (optable); ++i)
{
size_t l = strlen (optable[i].in);
if (l <= len
&& memcmp (optable[i].in, *mangled, l) == 0)
{
string_appendn (s, " ", 1);
string_append (s, optable[i].out);
string_appendn (s, " ", 1);
success = 1;
(*mangled) += l;
break;
}
}
if (!success)
break;
}
else
need_operator = 1;
success = demangle_template_value_parm (work, mangled, s, tk);
}
if (**mangled != 'W')
success = 0;
else
{
string_appendn (s, ")", 1);
(*mangled)++;
}
return success;
}
static int
demangle_integral_value (work, mangled, s)
struct work_stuff *work;
const char** mangled;
string* s;
{
int success;
if (**mangled == 'E')
success = demangle_expression (work, mangled, s, tk_integral);
else if (**mangled == 'Q' || **mangled == 'K')
success = demangle_qualified (work, mangled, s, 0, 1);
else
{
int value;
int multidigit_without_leading_underscore = 0;
int leave_following_underscore = 0;
success = 0;
if (**mangled == '_')
{
if (mangled[0][1] == 'm')
{
multidigit_without_leading_underscore = 1;
string_appendn (s, "-", 1);
(*mangled) += 2;
}
else
{
leave_following_underscore = 1;
}
}
else
{
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
multidigit_without_leading_underscore = 1;
leave_following_underscore = 1;
}
if (multidigit_without_leading_underscore)
value = consume_count (mangled);
else
value = consume_count_with_underscores (mangled);
if (value != -1)
{
char buf[INTBUF_SIZE];
sprintf (buf, "%d", value);
string_append (s, buf);
if ((value > 9 || multidigit_without_leading_underscore)
&& ! leave_following_underscore
&& **mangled == '_')
(*mangled)++;
success = 1;
}
}
return success;
}
static int
demangle_real_value (work, mangled, s)
struct work_stuff *work;
const char **mangled;
string* s;
{
if (**mangled == 'E')
return demangle_expression (work, mangled, s, tk_real);
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
while (ISDIGIT ((unsigned char)**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
if (**mangled == '.')
{
string_appendn (s, ".", 1);
(*mangled)++;
while (ISDIGIT ((unsigned char)**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
if (**mangled == 'e')
{
string_appendn (s, "e", 1);
(*mangled)++;
while (ISDIGIT ((unsigned char)**mangled))
{
string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
return 1;
}
static int
demangle_template_value_parm (work, mangled, s, tk)
struct work_stuff *work;
const char **mangled;
string* s;
type_kind_t tk;
{
int success = 1;
if (**mangled == 'Y')
{
int idx;
(*mangled)++;
idx = consume_count_with_underscores (mangled);
if (idx == -1
|| (work->tmpl_argvec && idx >= work->ntmpl_args)
|| consume_count_with_underscores (mangled) == -1)
return -1;
if (work->tmpl_argvec)
string_append (s, work->tmpl_argvec[idx]);
else
string_append_template_idx (s, idx);
}
else if (tk == tk_integral)
success = demangle_integral_value (work, mangled, s);
else if (tk == tk_char)
{
char tmp[2];
int val;
if (**mangled == 'm')
{
string_appendn (s, "-", 1);
(*mangled)++;
}
string_appendn (s, "'", 1);
val = consume_count(mangled);
if (val <= 0)
success = 0;
else
{
tmp[0] = (char)val;
tmp[1] = '\0';
string_appendn (s, &tmp[0], 1);
string_appendn (s, "'", 1);
}
}
else if (tk == tk_bool)
{
int val = consume_count (mangled);
if (val == 0)
string_appendn (s, "false", 5);
else if (val == 1)
string_appendn (s, "true", 4);
else
success = 0;
}
else if (tk == tk_real)
success = demangle_real_value (work, mangled, s);
else if (tk == tk_pointer || tk == tk_reference)
{
if (**mangled == 'Q')
success = demangle_qualified (work, mangled, s,
0,
1);
else
{
int symbol_len = consume_count (mangled);
if (symbol_len == -1)
return -1;
if (symbol_len == 0)
string_appendn (s, "0", 1);
else
{
char *p = xmalloc (symbol_len + 1), *q;
strncpy (p, *mangled, symbol_len);
p [symbol_len] = '\0';
q = cplus_demangle (p, work->options);
if (tk == tk_pointer)
string_appendn (s, "&", 1);
if (q)
{
string_append (s, q);
free (q);
}
else
string_append (s, p);
free (p);
}
*mangled += symbol_len;
}
}
return success;
}
static int
demangle_template (work, mangled, tname, trawname, is_type, remember)
struct work_stuff *work;
const char **mangled;
string *tname;
string *trawname;
int is_type;
int remember;
{
int i;
int r;
int need_comma = 0;
int success = 0;
const char *start;
int is_java_array = 0;
string temp;
(*mangled)++;
if (is_type)
{
start = *mangled;
if (**mangled == 'z')
{
int idx;
(*mangled)++;
(*mangled)++;
idx = consume_count_with_underscores (mangled);
if (idx == -1
|| (work->tmpl_argvec && idx >= work->ntmpl_args)
|| consume_count_with_underscores (mangled) == -1)
return (0);
if (work->tmpl_argvec)
{
string_append (tname, work->tmpl_argvec[idx]);
if (trawname)
string_append (trawname, work->tmpl_argvec[idx]);
}
else
{
string_append_template_idx (tname, idx);
if (trawname)
string_append_template_idx (trawname, idx);
}
}
else
{
if ((r = consume_count (mangled)) <= 0
|| (int) strlen (*mangled) < r)
{
return (0);
}
is_java_array = (work -> options & DMGL_JAVA)
&& strncmp (*mangled, "JArray1Z", 8) == 0;
if (! is_java_array)
{
string_appendn (tname, *mangled, r);
}
if (trawname)
string_appendn (trawname, *mangled, r);
*mangled += r;
}
}
if (!is_java_array)
string_append (tname, "<");
if (!get_count (mangled, &r))
{
return (0);
}
if (!is_type)
{
work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
work->ntmpl_args = r;
for (i = 0; i < r; i++)
work->tmpl_argvec[i] = 0;
}
for (i = 0; i < r; i++)
{
if (need_comma)
{
string_append (tname, ", ");
}
if (**mangled == 'Z')
{
(*mangled)++;
success = do_type (work, mangled, &temp);
if (success)
{
string_appends (tname, &temp);
if (!is_type)
{
int len = temp.p - temp.b;
work->tmpl_argvec[i] = xmalloc (len + 1);
memcpy (work->tmpl_argvec[i], temp.b, len);
work->tmpl_argvec[i][len] = '\0';
}
}
string_delete(&temp);
if (!success)
{
break;
}
}
else if (**mangled == 'z')
{
int r2;
(*mangled)++;
success = demangle_template_template_parm (work, mangled, tname);
if (success
&& (r2 = consume_count (mangled)) > 0
&& (int) strlen (*mangled) >= r2)
{
string_append (tname, " ");
string_appendn (tname, *mangled, r2);
if (!is_type)
{
int len = r2;
work->tmpl_argvec[i] = xmalloc (len + 1);
memcpy (work->tmpl_argvec[i], *mangled, len);
work->tmpl_argvec[i][len] = '\0';
}
*mangled += r2;
}
if (!success)
{
break;
}
}
else
{
string param;
string* s;
success = do_type (work, mangled, &temp);
string_delete(&temp);
if (!success)
break;
if (!is_type)
{
s = ¶m;
string_init (s);
}
else
s = tname;
success = demangle_template_value_parm (work, mangled, s,
(type_kind_t) success);
if (!success)
{
if (!is_type)
string_delete (s);
success = 0;
break;
}
if (!is_type)
{
int len = s->p - s->b;
work->tmpl_argvec[i] = xmalloc (len + 1);
memcpy (work->tmpl_argvec[i], s->b, len);
work->tmpl_argvec[i][len] = '\0';
string_appends (tname, s);
string_delete (s);
}
}
need_comma = 1;
}
if (is_java_array)
{
string_append (tname, "[]");
}
else
{
if (tname->p[-1] == '>')
string_append (tname, " ");
string_append (tname, ">");
}
if (is_type && remember)
{
const int bindex = register_Btype (work);
remember_Btype (work, tname->b, LEN_STRING (tname), bindex);
}
return (success);
}
static int
arm_pt (work, mangled, n, anchor, args)
struct work_stuff *work;
const char *mangled;
int n;
const char **anchor, **args;
{
if ((ARM_DEMANGLING || HP_DEMANGLING) && (*anchor = strstr (mangled, "__pt__")))
{
int len;
*args = *anchor + 6;
len = consume_count (args);
if (len == -1)
return 0;
if (*args + len == mangled + n && **args == '_')
{
++*args;
return 1;
}
}
if (AUTO_DEMANGLING || EDG_DEMANGLING)
{
if ((*anchor = strstr (mangled, "__tm__"))
|| (*anchor = strstr (mangled, "__ps__"))
|| (*anchor = strstr (mangled, "__pt__")))
{
int len;
*args = *anchor + 6;
len = consume_count (args);
if (len == -1)
return 0;
if (*args + len == mangled + n && **args == '_')
{
++*args;
return 1;
}
}
else if ((*anchor = strstr (mangled, "__S")))
{
int len;
*args = *anchor + 3;
len = consume_count (args);
if (len == -1)
return 0;
if (*args + len == mangled + n && **args == '_')
{
++*args;
return 1;
}
}
}
return 0;
}
static void
demangle_arm_hp_template (work, mangled, n, declp)
struct work_stuff *work;
const char **mangled;
int n;
string *declp;
{
const char *p;
const char *args;
const char *e = *mangled + n;
string arg;
if (HP_DEMANGLING && ((*mangled)[n] == 'X'))
{
char *start_spec_args = NULL;
int hold_options;
start_spec_args = strchr (*mangled, '<');
if (start_spec_args && (start_spec_args - *mangled < n))
string_appendn (declp, *mangled, start_spec_args - *mangled);
else
string_appendn (declp, *mangled, n);
(*mangled) += n + 1;
string_init (&arg);
if (work->temp_start == -1)
work->temp_start = declp->p - declp->b;
hold_options = work->options;
work->options |= DMGL_PARAMS;
string_append (declp, "<");
while (1)
{
string_delete (&arg);
switch (**mangled)
{
case 'T':
(*mangled)++;
if (!do_type (work, mangled, &arg))
goto hpacc_template_args_done;
break;
case 'U':
case 'S':
if (!do_hpacc_template_const_value (work, mangled, &arg))
goto hpacc_template_args_done;
break;
case 'A':
if (!do_hpacc_template_literal (work, mangled, &arg))
goto hpacc_template_args_done;
break;
default:
goto hpacc_template_args_done;
}
string_appends (declp, &arg);
if ((**mangled == '\000') || (**mangled == '_'))
break;
else
string_append (declp, ",");
}
hpacc_template_args_done:
string_append (declp, ">");
string_delete (&arg);
if (**mangled == '_')
(*mangled)++;
work->options = hold_options;
return;
}
else if (arm_pt (work, *mangled, n, &p, &args))
{
int hold_options;
string type_str;
string_init (&arg);
string_appendn (declp, *mangled, p - *mangled);
if (work->temp_start == -1)
work->temp_start = declp->p - declp->b;
hold_options = work->options;
work->options |= DMGL_PARAMS;
string_append (declp, "<");
while (args < e) {
string_delete (&arg);
switch (*args)
{
case 'X':
args++;
if (!do_type (work, &args, &type_str))
goto cfront_template_args_done;
string_append (&arg, "(");
string_appends (&arg, &type_str);
string_delete (&type_str);
string_append (&arg, ")");
if (*args != 'L')
goto cfront_template_args_done;
args++;
if (!snarf_numeric_literal (&args, &arg))
goto cfront_template_args_done;
break;
case 'L':
args++;
if (!snarf_numeric_literal (&args, &arg))
goto cfront_template_args_done;
break;
default:
{
const char* old_args = args;
if (!do_type (work, &args, &arg))
goto cfront_template_args_done;
if (args == old_args)
{
work->options = hold_options;
return;
}
}
}
string_appends (declp, &arg);
string_append (declp, ",");
}
cfront_template_args_done:
string_delete (&arg);
if (args >= e)
--declp->p;
string_append (declp, ">");
work->options = hold_options;
}
else if (n>10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
&& (*mangled)[9] == 'N'
&& (*mangled)[8] == (*mangled)[10]
&& strchr (cplus_markers, (*mangled)[8]))
{
string_append (declp, "{anonymous}");
}
else
{
if (work->temp_start == -1)
work->temp_start = 0;
string_appendn (declp, *mangled, n);
}
*mangled += n;
}
static int
demangle_class_name (work, mangled, declp)
struct work_stuff *work;
const char **mangled;
string *declp;
{
int n;
int success = 0;
n = consume_count (mangled);
if (n == -1)
return 0;
if ((int) strlen (*mangled) >= n)
{
demangle_arm_hp_template (work, mangled, n, declp);
success = 1;
}
return (success);
}
static int
demangle_class (work, mangled, declp)
struct work_stuff *work;
const char **mangled;
string *declp;
{
int success = 0;
int btype;
string class_name;
char *save_class_name_end = 0;
string_init (&class_name);
btype = register_Btype (work);
if (demangle_class_name (work, mangled, &class_name))
{
save_class_name_end = class_name.p;
if ((work->constructor & 1) || (work->destructor & 1))
{
if (work->temp_start && (work->temp_start != -1))
{
class_name.p = class_name.b + work->temp_start;
}
string_prepends (declp, &class_name);
if (work -> destructor & 1)
{
string_prepend (declp, "~");
work -> destructor -= 1;
}
else
{
work -> constructor -= 1;
}
}
class_name.p = save_class_name_end;
remember_Ktype (work, class_name.b, LEN_STRING(&class_name));
remember_Btype (work, class_name.b, LEN_STRING(&class_name), btype);
string_prepend (declp, SCOPE_STRING (work));
string_prepends (declp, &class_name);
success = 1;
}
string_delete (&class_name);
return (success);
}
static int
iterate_demangle_function (work, mangled, declp, scan)
struct work_stuff *work;
const char **mangled;
string *declp;
const char *scan;
{
const char *mangle_init = *mangled;
int success = 0;
string decl_init;
struct work_stuff work_init;
if (*(scan + 2) == '\0')
return 0;
if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
|| strstr (scan + 2, "__") == NULL)
{
demangle_function_name (work, mangled, declp, scan);
return 1;
}
string_init (&decl_init);
string_appends (&decl_init, declp);
memset (&work_init, 0, sizeof work_init);
work_stuff_copy_to_from (&work_init, work);
while (scan[2])
{
demangle_function_name (work, mangled, declp, scan);
success = demangle_signature (work, mangled, declp);
if (success)
break;
*mangled = mangle_init;
string_clear (declp);
string_appends (declp, &decl_init);
work_stuff_copy_to_from (work, &work_init);
scan += 2;
while (*scan && (scan[0] != '_' || scan[1] != '_'))
scan++;
while (*scan && *scan == '_')
scan++;
scan -= 2;
}
delete_work_stuff (&work_init);
string_delete (&decl_init);
return success;
}
static int
demangle_prefix (work, mangled, declp)
struct work_stuff *work;
const char **mangled;
string *declp;
{
int success = 1;
const char *scan;
int i;
if (strlen(*mangled) > 6
&& (strncmp(*mangled, "_imp__", 6) == 0
|| strncmp(*mangled, "__imp_", 6) == 0))
{
(*mangled) += 6;
work->dllimported = 1;
}
else if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
{
char *marker = strchr (cplus_markers, (*mangled)[8]);
if (marker != NULL && *marker == (*mangled)[10])
{
if ((*mangled)[9] == 'D')
{
(*mangled) += 11;
work->destructor = 2;
if (gnu_special (work, mangled, declp))
return success;
}
else if ((*mangled)[9] == 'I')
{
(*mangled) += 11;
work->constructor = 2;
if (gnu_special (work, mangled, declp))
return success;
}
}
}
else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__std__", 7) == 0)
{
(*mangled) += 7;
work->destructor = 2;
}
else if ((ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING) && strncmp(*mangled, "__sti__", 7) == 0)
{
(*mangled) += 7;
work->constructor = 2;
}
{
scan = *mangled;
do {
scan = strchr (scan, '_');
} while (scan != NULL && *++scan != '_');
if (scan != NULL) --scan;
}
if (scan != NULL)
{
i = strspn (scan, "_");
if (i > 2)
{
scan += (i - 2);
}
}
if (scan == NULL)
{
success = 0;
}
else if (work -> static_type)
{
if (!ISDIGIT ((unsigned char)scan[0]) && (scan[0] != 't'))
{
success = 0;
}
}
else if ((scan == *mangled)
&& (ISDIGIT ((unsigned char)scan[2]) || (scan[2] == 'Q')
|| (scan[2] == 't') || (scan[2] == 'K') || (scan[2] == 'H')))
{
if ((LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING)
&& ISDIGIT ((unsigned char)scan[2]))
{
*mangled = scan + 2;
consume_count (mangled);
string_append (declp, *mangled);
*mangled += strlen (*mangled);
success = 1;
}
else
{
if (!(LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING))
work -> constructor += 1;
*mangled = scan + 2;
}
}
else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
{
success = 1;
demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
}
else if (EDG_DEMANGLING && ((scan[2] == 't' && scan[3] == 'm')
|| (scan[2] == 'p' && scan[3] == 's')
|| (scan[2] == 'p' && scan[3] == 't')))
{
success = 1;
demangle_arm_hp_template (work, mangled, strlen (*mangled), declp);
}
else if ((scan == *mangled) && !ISDIGIT ((unsigned char)scan[2])
&& (scan[2] != 't'))
{
if (!(ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
|| (arm_special (mangled, declp) == 0))
{
while (*scan == '_')
{
scan++;
}
if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
{
success = 0;
}
else
return iterate_demangle_function (work, mangled, declp, scan);
}
}
else if (*(scan + 2) != '\0')
{
return iterate_demangle_function (work, mangled, declp, scan);
}
else
{
success = 0;
}
if (!success && (work->constructor == 2 || work->destructor == 2))
{
string_append (declp, *mangled);
*mangled += strlen (*mangled);
success = 1;
}
return (success);
}
static int
gnu_special (work, mangled, declp)
struct work_stuff *work;
const char **mangled;
string *declp;
{
int n;
int success = 1;
const char *p;
if ((*mangled)[0] == '_'
&& strchr (cplus_markers, (*mangled)[1]) != NULL
&& (*mangled)[2] == '_')
{
(*mangled) += 3;
work -> destructor += 1;
}
else if ((*mangled)[0] == '_'
&& (((*mangled)[1] == '_'
&& (*mangled)[2] == 'v'
&& (*mangled)[3] == 't'
&& (*mangled)[4] == '_')
|| ((*mangled)[1] == 'v'
&& (*mangled)[2] == 't'
&& strchr (cplus_markers, (*mangled)[3]) != NULL)))
{
if ((*mangled)[2] == 'v')
(*mangled) += 5;
else
(*mangled) += 4;
while (**mangled != '\0')
{
switch (**mangled)
{
case 'Q':
case 'K':
success = demangle_qualified (work, mangled, declp, 0, 1);
break;
case 't':
success = demangle_template (work, mangled, declp, 0, 1,
1);
break;
default:
if (ISDIGIT((unsigned char)*mangled[0]))
{
n = consume_count(mangled);
if (n > (int) strlen (*mangled))
{
success = 1;
break;
}
}
else
{
n = strcspn (*mangled, cplus_markers);
}
string_appendn (declp, *mangled, n);
(*mangled) += n;
}
p = strpbrk (*mangled, cplus_markers);
if (success && ((p == NULL) || (p == *mangled)))
{
if (p != NULL)
{
string_append (declp, SCOPE_STRING (work));
(*mangled)++;
}
}
else
{
success = 0;
break;
}
}
if (success)
string_append (declp, " virtual table");
}
else if ((*mangled)[0] == '_'
&& (strchr("0123456789Qt", (*mangled)[1]) != NULL)
&& (p = strpbrk (*mangled, cplus_markers)) != NULL)
{
(*mangled)++;
switch (**mangled)
{
case 'Q':
case 'K':
success = demangle_qualified (work, mangled, declp, 0, 1);
break;
case 't':
success = demangle_template (work, mangled, declp, 0, 1, 1);
break;
default:
n = consume_count (mangled);
if (n < 0 || n > (long) strlen (*mangled))
{
success = 0;
break;
}
if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0
&& (*mangled)[9] == 'N'
&& (*mangled)[8] == (*mangled)[10]
&& strchr (cplus_markers, (*mangled)[8]))
{
string_append (declp, "{anonymous}");
(*mangled) += n;
p = strpbrk (*mangled, cplus_markers);
break;
}
string_appendn (declp, *mangled, n);
(*mangled) += n;
}
if (success && (p == *mangled))
{
(*mangled)++;
string_append (declp, SCOPE_STRING (work));
n = strlen (*mangled);
string_appendn (declp, *mangled, n);
(*mangled) += n;
}
else
{
success = 0;
}
}
else if (strncmp (*mangled, "__thunk_", 8) == 0)
{
int delta;
(*mangled) += 8;
delta = consume_count (mangled);
if (delta == -1)
success = 0;
else
{
char *method = internal_cplus_demangle (work, ++*mangled);
if (method)
{
char buf[50];
sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
string_append (declp, buf);
string_append (declp, method);
free (method);
n = strlen (*mangled);
(*mangled) += n;
}
else
{
success = 0;
}
}
}
else if (strncmp (*mangled, "__t", 3) == 0
&& ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
{
p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
(*mangled) += 4;
switch (**mangled)
{
case 'Q':
case 'K':
success = demangle_qualified (work, mangled, declp, 0, 1);
break;
case 't':
success = demangle_template (work, mangled, declp, 0, 1, 1);
break;
default:
success = do_type (work, mangled, declp);
break;
}
if (success && **mangled != '\0')
success = 0;
if (success)
string_append (declp, p);
}
else
{
success = 0;
}
return (success);
}
static void
recursively_demangle(work, mangled, result, namelength)
struct work_stuff *work;
const char **mangled;
string *result;
int namelength;
{
char * recurse = (char *)NULL;
char * recurse_dem = (char *)NULL;
recurse = (char *) xmalloc (namelength + 1);
memcpy (recurse, *mangled, namelength);
recurse[namelength] = '\000';
recurse_dem = cplus_demangle (recurse, work->options);
if (recurse_dem)
{
string_append (result, recurse_dem);
free (recurse_dem);
}
else
{
string_appendn (result, *mangled, namelength);
}
free (recurse);
*mangled += namelength;
}
static int
arm_special (mangled, declp)
const char **mangled;
string *declp;
{
int n;
int success = 1;
const char *scan;
if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
{
scan = *mangled + ARM_VTABLE_STRLEN;
while (*scan != '\0')
{
n = consume_count (&scan);
if (n == -1)
{
return (0);
}
scan += n;
if (scan[0] == '_' && scan[1] == '_')
{
scan += 2;
}
}
(*mangled) += ARM_VTABLE_STRLEN;
while (**mangled != '\0')
{
n = consume_count (mangled);
if (n == -1
|| n > (long) strlen (*mangled))
return 0;
string_prependn (declp, *mangled, n);
(*mangled) += n;
if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
{
string_prepend (declp, "::");
(*mangled) += 2;
}
}
string_append (declp, " virtual table");
}
else
{
success = 0;
}
return (success);
}
static int
demangle_qualified (work, mangled, result, isfuncname, append)
struct work_stuff *work;
const char **mangled;
string *result;
int isfuncname;
int append;
{
int qualifiers = 0;
int success = 1;
char num[2];
string temp;
string last_name;
int bindex = register_Btype (work);
isfuncname = (isfuncname
&& ((work->constructor & 1) || (work->destructor & 1)));
string_init (&temp);
string_init (&last_name);
if ((*mangled)[0] == 'K')
{
int idx;
(*mangled)++;
idx = consume_count_with_underscores (mangled);
if (idx == -1 || idx >= work -> numk)
success = 0;
else
string_append (&temp, work -> ktypevec[idx]);
}
else
switch ((*mangled)[1])
{
case '_':
(*mangled)++;
qualifiers = consume_count_with_underscores (mangled);
if (qualifiers == -1)
success = 0;
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
num[0] = (*mangled)[1];
num[1] = '\0';
qualifiers = atoi (num);
if ((*mangled)[2] == '_')
{
(*mangled)++;
}
(*mangled) += 2;
break;
case '0':
default:
success = 0;
}
if (!success)
return success;
while (qualifiers-- > 0)
{
int remember_K = 1;
string_clear (&last_name);
if (*mangled[0] == '_')
(*mangled)++;
if (*mangled[0] == 't')
{
success = demangle_template(work, mangled, &temp,
&last_name, 1, 0);
if (!success)
break;
}
else if (*mangled[0] == 'K')
{
int idx;
(*mangled)++;
idx = consume_count_with_underscores (mangled);
if (idx == -1 || idx >= work->numk)
success = 0;
else
string_append (&temp, work->ktypevec[idx]);
remember_K = 0;
if (!success) break;
}
else
{
if (EDG_DEMANGLING)
{
int namelength;
namelength = consume_count (mangled);
if (namelength == -1)
{
success = 0;
break;
}
recursively_demangle(work, mangled, &temp, namelength);
}
else
{
string_delete (&last_name);
success = do_type (work, mangled, &last_name);
if (!success)
break;
string_appends (&temp, &last_name);
}
}
if (remember_K)
remember_Ktype (work, temp.b, LEN_STRING (&temp));
if (qualifiers > 0)
string_append (&temp, SCOPE_STRING (work));
}
remember_Btype (work, temp.b, LEN_STRING (&temp), bindex);
if (isfuncname)
{
string_append (&temp, SCOPE_STRING (work));
if (work -> destructor & 1)
string_append (&temp, "~");
string_appends (&temp, &last_name);
}
if (append)
string_appends (result, &temp);
else
{
if (!STRING_EMPTY (result))
string_append (&temp, SCOPE_STRING (work));
string_prepends (result, &temp);
}
string_delete (&last_name);
string_delete (&temp);
return (success);
}
static int
get_count (type, count)
const char **type;
int *count;
{
const char *p;
int n;
if (!ISDIGIT ((unsigned char)**type))
return (0);
else
{
*count = **type - '0';
(*type)++;
if (ISDIGIT ((unsigned char)**type))
{
p = *type;
n = *count;
do
{
n *= 10;
n += *p - '0';
p++;
}
while (ISDIGIT ((unsigned char)*p));
if (*p == '_')
{
*type = p + 1;
*count = n;
}
}
}
return (1);
}
static int
do_type (work, mangled, result)
struct work_stuff *work;
const char **mangled;
string *result;
{
int n;
int done;
int success;
string decl;
const char *remembered_type;
int type_quals;
type_kind_t tk = tk_none;
string_init (&decl);
string_init (result);
done = 0;
success = 1;
while (success && !done)
{
int member;
switch (**mangled)
{
case 'P':
case 'p':
(*mangled)++;
if (! (work -> options & DMGL_JAVA))
string_prepend (&decl, "*");
if (tk == tk_none)
tk = tk_pointer;
break;
case 'R':
(*mangled)++;
string_prepend (&decl, "&");
if (tk == tk_none)
tk = tk_reference;
break;
case 'A':
{
++(*mangled);
if (!STRING_EMPTY (&decl)
&& (decl.b[0] == '*' || decl.b[0] == '&'))
{
string_prepend (&decl, "(");
string_append (&decl, ")");
}
string_append (&decl, "[");
if (**mangled != '_')
success = demangle_template_value_parm (work, mangled, &decl,
tk_integral);
if (**mangled == '_')
++(*mangled);
string_append (&decl, "]");
break;
}
case 'T':
(*mangled)++;
if (!get_count (mangled, &n) || n >= work -> ntypes)
{
success = 0;
}
else
{
remembered_type = work -> typevec[n];
mangled = &remembered_type;
}
break;
case 'F':
(*mangled)++;
if (!STRING_EMPTY (&decl)
&& (decl.b[0] == '*' || decl.b[0] == '&'))
{
string_prepend (&decl, "(");
string_append (&decl, ")");
}
if (!demangle_nested_args (work, mangled, &decl)
|| (**mangled != '_' && **mangled != '\0'))
{
success = 0;
break;
}
if (success && (**mangled == '_'))
(*mangled)++;
break;
case 'M':
case 'O':
{
type_quals = TYPE_UNQUALIFIED;
member = **mangled == 'M';
(*mangled)++;
string_append (&decl, ")");
if (**mangled != 'Q')
string_prepend (&decl, SCOPE_STRING (work));
if (ISDIGIT ((unsigned char)**mangled))
{
n = consume_count (mangled);
if (n == -1
|| (int) strlen (*mangled) < n)
{
success = 0;
break;
}
string_prependn (&decl, *mangled, n);
*mangled += n;
}
else if (**mangled == 'X' || **mangled == 'Y')
{
string temp;
do_type (work, mangled, &temp);
string_prepends (&decl, &temp);
string_delete (&temp);
}
else if (**mangled == 't')
{
string temp;
string_init (&temp);
success = demangle_template (work, mangled, &temp,
NULL, 1, 1);
if (success)
{
string_prependn (&decl, temp.b, temp.p - temp.b);
string_delete (&temp);
}
else
break;
}
else if (**mangled == 'Q')
{
success = demangle_qualified (work, mangled, &decl,
0,
0);
if (!success)
break;
}
else
{
success = 0;
break;
}
string_prepend (&decl, "(");
if (member)
{
switch (**mangled)
{
case 'C':
case 'V':
case 'u':
type_quals |= code_for_qualifier (**mangled);
(*mangled)++;
break;
default:
break;
}
if (*(*mangled)++ != 'F')
{
success = 0;
break;
}
}
if ((member && !demangle_nested_args (work, mangled, &decl))
|| **mangled != '_')
{
success = 0;
break;
}
(*mangled)++;
if (! PRINT_ANSI_QUALIFIERS)
{
break;
}
if (type_quals != TYPE_UNQUALIFIED)
{
APPEND_BLANK (&decl);
string_append (&decl, qualifier_string (type_quals));
}
break;
}
case 'G':
(*mangled)++;
break;
case 'C':
case 'V':
case 'u':
if (PRINT_ANSI_QUALIFIERS)
{
if (!STRING_EMPTY (&decl))
string_prepend (&decl, " ");
string_prepend (&decl, demangle_qualifier (**mangled));
}
(*mangled)++;
break;
default:
done = 1;
break;
}
}
if (success) switch (**mangled)
{
case 'Q':
case 'K':
{
success = demangle_qualified (work, mangled, result, 0, 1);
break;
}
case 'B':
(*mangled)++;
if (!get_count (mangled, &n) || n >= work -> numb)
success = 0;
else
string_append (result, work->btypevec[n]);
break;
case 'X':
case 'Y':
{
int idx;
(*mangled)++;
idx = consume_count_with_underscores (mangled);
if (idx == -1
|| (work->tmpl_argvec && idx >= work->ntmpl_args)
|| consume_count_with_underscores (mangled) == -1)
{
success = 0;
break;
}
if (work->tmpl_argvec)
string_append (result, work->tmpl_argvec[idx]);
else
string_append_template_idx (result, idx);
success = 1;
}
break;
default:
success = demangle_fund_type (work, mangled, result);
if (tk == tk_none)
tk = (type_kind_t) success;
break;
}
if (success)
{
if (!STRING_EMPTY (&decl))
{
string_append (result, " ");
string_appends (result, &decl);
}
}
else
string_delete (result);
string_delete (&decl);
if (success)
return (int) ((tk == tk_none) ? tk_integral : tk);
else
return 0;
}
static int
demangle_fund_type (work, mangled, result)
struct work_stuff *work;
const char **mangled;
string *result;
{
int done = 0;
int success = 1;
char buf[10];
unsigned int dec = 0;
type_kind_t tk = tk_integral;
while (!done)
{
switch (**mangled)
{
case 'C':
case 'V':
case 'u':
if (PRINT_ANSI_QUALIFIERS)
{
if (!STRING_EMPTY (result))
string_prepend (result, " ");
string_prepend (result, demangle_qualifier (**mangled));
}
(*mangled)++;
break;
case 'U':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "unsigned");
break;
case 'S':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "signed");
break;
case 'J':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "__complex");
break;
default:
done = 1;
break;
}
}
switch (**mangled)
{
case '\0':
case '_':
break;
case 'v':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "void");
break;
case 'x':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "long long");
break;
case 'l':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "long");
break;
case 'i':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "int");
break;
case 's':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "short");
break;
case 'b':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "bool");
tk = tk_bool;
break;
case 'c':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "char");
tk = tk_char;
break;
case 'w':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "wchar_t");
tk = tk_char;
break;
case 'r':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "long double");
tk = tk_real;
break;
case 'd':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "double");
tk = tk_real;
break;
case 'f':
(*mangled)++;
APPEND_BLANK (result);
string_append (result, "float");
tk = tk_real;
break;
case 'G':
(*mangled)++;
if (!ISDIGIT ((unsigned char)**mangled))
{
success = 0;
break;
}
case 'I':
(*mangled)++;
if (**mangled == '_')
{
int i;
(*mangled)++;
for (i = 0;
i < (long) sizeof (buf) - 1 && **mangled && **mangled != '_';
(*mangled)++, i++)
buf[i] = **mangled;
if (**mangled != '_')
{
success = 0;
break;
}
buf[i] = '\0';
(*mangled)++;
}
else
{
strncpy (buf, *mangled, 2);
buf[2] = '\0';
*mangled += min (strlen (*mangled), 2);
}
sscanf (buf, "%x", &dec);
sprintf (buf, "int%u_t", dec);
APPEND_BLANK (result);
string_append (result, buf);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
int bindex = register_Btype (work);
string btype;
string_init (&btype);
if (demangle_class_name (work, mangled, &btype)) {
remember_Btype (work, btype.b, LEN_STRING (&btype), bindex);
APPEND_BLANK (result);
string_appends (result, &btype);
}
else
success = 0;
string_delete (&btype);
break;
}
case 't':
{
string btype;
string_init (&btype);
success = demangle_template (work, mangled, &btype, 0, 1, 1);
string_appends (result, &btype);
string_delete (&btype);
break;
}
default:
success = 0;
break;
}
return success ? ((int) tk) : 0;
}
static int
do_hpacc_template_const_value (work, mangled, result)
struct work_stuff *work ATTRIBUTE_UNUSED;
const char **mangled;
string *result;
{
int unsigned_const;
if (**mangled != 'U' && **mangled != 'S')
return 0;
unsigned_const = (**mangled == 'U');
(*mangled)++;
switch (**mangled)
{
case 'N':
string_append (result, "-");
case 'P':
(*mangled)++;
break;
case 'M':
string_append (result, "-2147483648");
(*mangled)++;
return 1;
default:
return 0;
}
if (!(ISDIGIT ((unsigned char)**mangled)))
return 0;
while (ISDIGIT ((unsigned char)**mangled))
{
char_str[0] = **mangled;
string_append (result, char_str);
(*mangled)++;
}
if (unsigned_const)
string_append (result, "U");
return 1;
}
static int
do_hpacc_template_literal (work, mangled, result)
struct work_stuff *work;
const char **mangled;
string *result;
{
int literal_len = 0;
char * recurse;
char * recurse_dem;
if (**mangled != 'A')
return 0;
(*mangled)++;
literal_len = consume_count (mangled);
if (literal_len <= 0)
return 0;
string_append (result, "&");
recurse = (char *) xmalloc (literal_len + 1);
memcpy (recurse, *mangled, literal_len);
recurse[literal_len] = '\000';
recurse_dem = cplus_demangle (recurse, work->options);
if (recurse_dem)
{
string_append (result, recurse_dem);
free (recurse_dem);
}
else
{
string_appendn (result, *mangled, literal_len);
}
(*mangled) += literal_len;
free (recurse);
return 1;
}
static int
snarf_numeric_literal (args, arg)
const char ** args;
string * arg;
{
if (**args == '-')
{
char_str[0] = '-';
string_append (arg, char_str);
(*args)++;
}
else if (**args == '+')
(*args)++;
if (!ISDIGIT ((unsigned char)**args))
return 0;
while (ISDIGIT ((unsigned char)**args))
{
char_str[0] = **args;
string_append (arg, char_str);
(*args)++;
}
return 1;
}
static int
do_arg (work, mangled, result)
struct work_stuff *work;
const char **mangled;
string *result;
{
const char *start = *mangled;
string_init (result);
if (work->nrepeats > 0)
{
--work->nrepeats;
if (work->previous_argument == 0)
return 0;
string_appends (result, work->previous_argument);
return 1;
}
if (**mangled == 'n')
{
(*mangled)++;
work->nrepeats = consume_count(mangled);
if (work->nrepeats <= 0)
return 0;
if (work->nrepeats > 9)
{
if (**mangled != '_')
return 0;
else
(*mangled)++;
}
return do_arg (work, mangled, result);
}
if (work->previous_argument)
string_delete (work->previous_argument);
else
work->previous_argument = (string*) xmalloc (sizeof (string));
if (!do_type (work, mangled, work->previous_argument))
return 0;
string_appends (result, work->previous_argument);
remember_type (work, start, *mangled - start);
return 1;
}
static void
remember_type (work, start, len)
struct work_stuff *work;
const char *start;
int len;
{
char *tem;
if (work->forgetting_types)
return;
if (work -> ntypes >= work -> typevec_size)
{
if (work -> typevec_size == 0)
{
work -> typevec_size = 3;
work -> typevec
= (char **) xmalloc (sizeof (char *) * work -> typevec_size);
}
else
{
work -> typevec_size *= 2;
work -> typevec
= (char **) xrealloc ((char *)work -> typevec,
sizeof (char *) * work -> typevec_size);
}
}
tem = xmalloc (len + 1);
memcpy (tem, start, len);
tem[len] = '\0';
work -> typevec[work -> ntypes++] = tem;
}
static void
remember_Ktype (work, start, len)
struct work_stuff *work;
const char *start;
int len;
{
char *tem;
if (work -> numk >= work -> ksize)
{
if (work -> ksize == 0)
{
work -> ksize = 5;
work -> ktypevec
= (char **) xmalloc (sizeof (char *) * work -> ksize);
}
else
{
work -> ksize *= 2;
work -> ktypevec
= (char **) xrealloc ((char *)work -> ktypevec,
sizeof (char *) * work -> ksize);
}
}
tem = xmalloc (len + 1);
memcpy (tem, start, len);
tem[len] = '\0';
work -> ktypevec[work -> numk++] = tem;
}
static int
register_Btype (work)
struct work_stuff *work;
{
int ret;
if (work -> numb >= work -> bsize)
{
if (work -> bsize == 0)
{
work -> bsize = 5;
work -> btypevec
= (char **) xmalloc (sizeof (char *) * work -> bsize);
}
else
{
work -> bsize *= 2;
work -> btypevec
= (char **) xrealloc ((char *)work -> btypevec,
sizeof (char *) * work -> bsize);
}
}
ret = work -> numb++;
work -> btypevec[ret] = NULL;
return(ret);
}
static void
remember_Btype (work, start, len, index)
struct work_stuff *work;
const char *start;
int len, index;
{
char *tem;
tem = xmalloc (len + 1);
memcpy (tem, start, len);
tem[len] = '\0';
work -> btypevec[index] = tem;
}
static void
forget_B_and_K_types (work)
struct work_stuff *work;
{
int i;
while (work -> numk > 0)
{
i = --(work -> numk);
if (work -> ktypevec[i] != NULL)
{
free (work -> ktypevec[i]);
work -> ktypevec[i] = NULL;
}
}
while (work -> numb > 0)
{
i = --(work -> numb);
if (work -> btypevec[i] != NULL)
{
free (work -> btypevec[i]);
work -> btypevec[i] = NULL;
}
}
}
static void
forget_types (work)
struct work_stuff *work;
{
int i;
while (work -> ntypes > 0)
{
i = --(work -> ntypes);
if (work -> typevec[i] != NULL)
{
free (work -> typevec[i]);
work -> typevec[i] = NULL;
}
}
}
static int
demangle_args (work, mangled, declp)
struct work_stuff *work;
const char **mangled;
string *declp;
{
string arg;
int need_comma = 0;
int r;
int t;
const char *tem;
char temptype;
if (PRINT_ARG_TYPES)
{
string_append (declp, "(");
if (**mangled == '\0')
{
string_append (declp, "void");
}
}
while ((**mangled != '_' && **mangled != '\0' && **mangled != 'e')
|| work->nrepeats > 0)
{
if ((**mangled == 'N') || (**mangled == 'T'))
{
temptype = *(*mangled)++;
if (temptype == 'N')
{
if (!get_count (mangled, &r))
{
return (0);
}
}
else
{
r = 1;
}
if ((HP_DEMANGLING || ARM_DEMANGLING || EDG_DEMANGLING) && work -> ntypes >= 10)
{
if ((t = consume_count(mangled)) <= 0)
{
return (0);
}
}
else
{
if (!get_count (mangled, &t))
{
return (0);
}
}
if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
{
t--;
}
if ((t < 0) || (t >= work -> ntypes))
{
return (0);
}
while (work->nrepeats > 0 || --r >= 0)
{
tem = work -> typevec[t];
if (need_comma && PRINT_ARG_TYPES)
{
string_append (declp, ", ");
}
if (!do_arg (work, &tem, &arg))
{
return (0);
}
if (PRINT_ARG_TYPES)
{
string_appends (declp, &arg);
}
string_delete (&arg);
need_comma = 1;
}
}
else
{
if (need_comma && PRINT_ARG_TYPES)
string_append (declp, ", ");
if (!do_arg (work, mangled, &arg))
return (0);
if (PRINT_ARG_TYPES)
string_appends (declp, &arg);
string_delete (&arg);
need_comma = 1;
}
}
if (**mangled == 'e')
{
(*mangled)++;
if (PRINT_ARG_TYPES)
{
if (need_comma)
{
string_append (declp, ",");
}
string_append (declp, "...");
}
}
if (PRINT_ARG_TYPES)
{
string_append (declp, ")");
}
return (1);
}
static int
demangle_nested_args (work, mangled, declp)
struct work_stuff *work;
const char **mangled;
string *declp;
{
string* saved_previous_argument;
int result;
int saved_nrepeats;
++work->forgetting_types;
saved_previous_argument = work->previous_argument;
saved_nrepeats = work->nrepeats;
work->previous_argument = 0;
work->nrepeats = 0;
result = demangle_args (work, mangled, declp);
if (work->previous_argument)
{
string_delete (work->previous_argument);
free ((char *) work->previous_argument);
}
work->previous_argument = saved_previous_argument;
--work->forgetting_types;
work->nrepeats = saved_nrepeats;
return result;
}
static void
demangle_function_name (work, mangled, declp, scan)
struct work_stuff *work;
const char **mangled;
string *declp;
const char *scan;
{
size_t i;
string type;
const char *tem;
string_appendn (declp, (*mangled), scan - (*mangled));
string_need (declp, 1);
*(declp -> p) = '\0';
(*mangled) = scan + 2;
if (HP_DEMANGLING && (**mangled == 'X'))
{
demangle_arm_hp_template (work, mangled, 0, declp);
}
if (LUCID_DEMANGLING || ARM_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING)
{
if (strcmp (declp -> b, "__ct") == 0)
{
work -> constructor += 1;
string_clear (declp);
return;
}
else if (strcmp (declp -> b, "__dt") == 0)
{
work -> destructor += 1;
string_clear (declp);
return;
}
}
if (declp->p - declp->b >= 3
&& declp->b[0] == 'o'
&& declp->b[1] == 'p'
&& strchr (cplus_markers, declp->b[2]) != NULL)
{
if (declp->p - declp->b >= 10
&& memcmp (declp->b + 3, "assign_", 7) == 0)
{
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
int len = declp->p - declp->b - 10;
if ((int) strlen (optable[i].in) == len
&& memcmp (optable[i].in, declp->b + 10, len) == 0)
{
string_clear (declp);
string_append (declp, "operator");
string_append (declp, optable[i].out);
string_append (declp, "=");
break;
}
}
}
else
{
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
int len = declp->p - declp->b - 3;
if ((int) strlen (optable[i].in) == len
&& memcmp (optable[i].in, declp->b + 3, len) == 0)
{
string_clear (declp);
string_append (declp, "operator");
string_append (declp, optable[i].out);
break;
}
}
}
}
else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
&& strchr (cplus_markers, declp->b[4]) != NULL)
{
tem = declp->b + 5;
if (do_type (work, &tem, &type))
{
string_clear (declp);
string_append (declp, "operator ");
string_appends (declp, &type);
string_delete (&type);
}
}
else if (declp->b[0] == '_' && declp->b[1] == '_'
&& declp->b[2] == 'o' && declp->b[3] == 'p')
{
tem = declp->b + 4;
if (do_type (work, &tem, &type))
{
string_clear (declp);
string_append (declp, "operator ");
string_appends (declp, &type);
string_delete (&type);
}
}
else if (declp->b[0] == '_' && declp->b[1] == '_'
&& ISLOWER((unsigned char)declp->b[2])
&& ISLOWER((unsigned char)declp->b[3]))
{
if (declp->b[4] == '\0')
{
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 2
&& memcmp (optable[i].in, declp->b + 2, 2) == 0)
{
string_clear (declp);
string_append (declp, "operator");
string_append (declp, optable[i].out);
break;
}
}
}
else
{
if (declp->b[2] == 'a' && declp->b[5] == '\0')
{
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 3
&& memcmp (optable[i].in, declp->b + 2, 3) == 0)
{
string_clear (declp);
string_append (declp, "operator");
string_append (declp, optable[i].out);
break;
}
}
}
}
}
}
static void
string_need (s, n)
string *s;
int n;
{
int tem;
if (s->b == NULL)
{
if (n < 32)
{
n = 32;
}
s->p = s->b = xmalloc (n);
s->e = s->b + n;
}
else if (s->e - s->p < n)
{
tem = s->p - s->b;
n += tem;
n *= 2;
s->b = xrealloc (s->b, n);
s->p = s->b + tem;
s->e = s->b + n;
}
}
static void
string_delete (s)
string *s;
{
if (s->b != NULL)
{
free (s->b);
s->b = s->e = s->p = NULL;
}
}
static void
string_init (s)
string *s;
{
s->b = s->p = s->e = NULL;
}
static void
string_clear (s)
string *s;
{
s->p = s->b;
}
#if 0
static int
string_empty (s)
string *s;
{
return (s->b == s->p);
}
#endif
static void
string_append (p, s)
string *p;
const char *s;
{
int n;
if (s == NULL || *s == '\0')
return;
n = strlen (s);
string_need (p, n);
memcpy (p->p, s, n);
p->p += n;
}
static void
string_appends (p, s)
string *p, *s;
{
int n;
if (s->b != s->p)
{
n = s->p - s->b;
string_need (p, n);
memcpy (p->p, s->b, n);
p->p += n;
}
}
static void
string_appendn (p, s, n)
string *p;
const char *s;
int n;
{
if (n != 0)
{
string_need (p, n);
memcpy (p->p, s, n);
p->p += n;
}
}
static void
string_prepend (p, s)
string *p;
const char *s;
{
if (s != NULL && *s != '\0')
{
string_prependn (p, s, strlen (s));
}
}
static void
string_prepends (p, s)
string *p, *s;
{
if (s->b != s->p)
{
string_prependn (p, s->b, s->p - s->b);
}
}
static void
string_prependn (p, s, n)
string *p;
const char *s;
int n;
{
char *q;
if (n != 0)
{
string_need (p, n);
for (q = p->p - 1; q >= p->b; q--)
{
q[n] = q[0];
}
memcpy (p->b, s, n);
p->p += n;
}
}
static void
string_append_template_idx (s, idx)
string *s;
int idx;
{
char buf[INTBUF_SIZE + 1 ];
sprintf(buf, "T%d", idx);
string_append (s, buf);
}