gcc/libiberty/cplus-dem.c

491 lines
13 KiB
C
Raw Normal View History

/* Demangler for GNU C++
Copyright (C) 1989-2019 Free Software Foundation, Inc.
1997-08-22 00:57:35 +02:00
Written by James Clark (jjc@jclark.uucp)
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
* HP aCC demangling support. * cplus-dem.c (main): Remove default to HP style demangling, set to EDG demangling correctly when -edg specified; set the demangling style when user specifies 'edg'. Set strip_underscore to prepends_underscore, if not HPUXHPPA. Set current_demangling_style to hp_demangling if HPUXHPPA. Set current demangling style correctly if the switch is hp. Read label correctly also in the HP style case. (work_stuff): add temp_start field; add field for volatile member function. (arm_pt): handle ARM_DEMANGLING and EDG_DEMANGLING styles; HP style for this case is the same as ARM. (demangle_args): handle EDG_DEMANGLING style; support HP style. (demangle_arm_hp_template): new function. (It was demangle_arm_pt.); check and set value of temp_start field in multiple places. Also, when ceching for end of template args, check to see if at end of static member of template class. (demangle_class): new local variable : save_class_name_end Don't include template args in string defining class. (demangle_class_name): use demangel_arm_hp_template. (demangle_function_name): handle case where demangling style is HP_DEMANGLING and currently point at an 'X' in the mangled name. Handle EDG_DEMANGLING style. Handle constructor and destructor ops for HP style. (demangle_prefix): handle EDG_DEMANGLING and ARM_DEMANGLING styles. global destructor and constructor for HP style are same as for ARM style. Same for local variables. (demangle_qualified): handle EDG_DEMANGLING style. (demangle_signature): add case for volatile member function. For cases '1' - '9' : initialize the temp_start field to -1 and handle the EDG_DEMANGLING style. for case 'F' : handle EDG_DEMANGLING and AUTO_DEMANGLING styles. If expecting a function and managed to demangle the funct args, then handle the LUCID_DEMANGLING, ARM_DEMANGLING, and EDG_DEMANGLING styles. Add case for local class name after "Lnnn_ in HP style case. HP style too needs to forget types. _nnn is OK for HP style, so don't report failure. (do_hpacc_template_const_value): new function. Handle template's value param for HP/aCC. (do_hpacc_template_literal): new function. Handle a template's literal parameter for HP aCC. (recursively_demangle): new function (snarf_numeric_literal): new function. (usage): add 'edg' to the list of demangling styles; add hp switch to message. Co-Authored-By: Andrew MacLeod <amacleod@cygnus.com> Co-Authored-By: Edith Epstein <eepstein@cygnus.com> Co-Authored-By: Elena Zannoni <ezannoni@cygnus.com> Co-Authored-By: Satish Pai <pai@apollo.hp.com> Co-Authored-By: Stan Shebs <shebs@cygnus.com> From-SVN: r24170
1998-12-07 23:21:45 +01:00
Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
1997-08-22 00:57:35 +02:00
This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Library General Public
License, the Free Software Foundation gives you unlimited permission
to link the compiled version of this file into combinations with other
programs, and to distribute those combinations without any restriction
coming from the use of this file. (The Library Public License
restrictions do apply in other respects; for example, they cover
modification of the file, and distribution when not linked into a
combined executable.)
1997-08-22 00:57:35 +02:00
Libiberty is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with libiberty; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA. */
1997-08-22 00:57:35 +02:00
/* This file lives in both GCC and libiberty. When making changes, please
try not to break either. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
safe-ctype.h: New file. include: * safe-ctype.h: New file. libiberty: * safe-ctype.c: New file. * Makefile.in (CFILES): Add safe-ctype.c. (REQUIRED_OFILES): Add safe-ctype.o. * argv.c: Define ISBLANK and use it, not isspace. * basename.c, cplus-dem.c, fnmatch.c, pexecute.c, strtod.c, strtol.c, strtoul.c: Include safe-ctype.h, not ctype.h. Use uppercase ctype macros. Don't test ISUPPER(c)/ISLOWER(c) before calling TOLOWER(c)/TOUPPER(c). gcc: * Makefile.in (HOST_RTL): Add safe-ctype.o. (safe-ctype.o): New rule. * system.h: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. * cpphash.h: Zap IStable and related macros. Define is_* in terms of safe-ctype.h macros. * cppinit.c: Delete the IStable and all related code. * tradcpp.c: Delete is_idchar, is_idstart, is_hor_space, and is_space arrays. Delete initialize_char_syntax. Change all references to the above arrays to use macros instead. * tradcpp.h: Define is_idchar, is_idstart, is_space, and is_nvspace in terms of safe_ctype.h's macros. * tradcif.y: is_idchar, is_idstart are macros not arrays. * config/i370/i370.c, config/winnt/dirent.c, config/winnt/fixinc-nt.c, config/winnt/ld.c: Use uppercase ctype macros. If we included ctype.h, include safe-ctype.h instead. * fixinc/fixfixes.c: Use uppercase ctype macros. Don't test ISLOWER(c) before calling TOUPPER(c). * fixinc/fixincl.c (extract_quoted_files): Simplify out some gunk. * fixinc/gnu-regex.c: Include safe-ctype.h, not ctype.h. No need to wrap ctype macros. Don't test ISUPPER(x) before calling TOLOWER(x). gcc/ch: * lex.c: Don't bother checking whether ISUPPER(c) before calling TOLOWER(c). Don't bother checking whether isascii(c) before testing ISSPACE(c); ISSPACE(c) includes '\n'. gcc/f: * Make-lang.in: Link f/fini with safe-ctype.o. * bad.c: Don't test ISUPPER(c) || ISLOWER(c) before calling TOUPPER(c). * com.c: Use TOUPPER, not ffesrc_toupper. * fini.c: Don't test ISALPHA(c) before calling TOUPPER(c)/TOLOWER(c). * intrin.c: Don't test IN_CTYPE_DOMAIN(c). * src.c: Delete ffesrc_toupper_ and ffesrc_tolower_ and their initializing code; use TOUPPER and TOLOWER instead of ffesrc_toupper and ffesrc_tolower. * src.h: Don't declare ffesrc_toupper_ or ffesrc_tolower_. Don't define ffesrc_toupper or ffesrc_tolower. gcc/java: * jvgenmain.c: Use ISPRINT not isascii. From-SVN: r38124
2000-12-08 04:00:26 +01:00
#include "safe-ctype.h"
1997-08-22 00:57:35 +02:00
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else
void * malloc ();
void * realloc ();
#endif
1997-08-22 00:57:35 +02:00
#include <demangle.h>
#undef CURRENT_DEMANGLING_STYLE
#define CURRENT_DEMANGLING_STYLE options
1997-08-22 00:57:35 +02:00
#include "libiberty.h"
1997-08-22 00:57:35 +02:00
enum demangling_styles current_demangling_style = auto_demangling;
1997-08-22 00:57:35 +02:00
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_V3_DEMANGLING_STYLE_STRING,
gnu_v3_demangling,
"GNU (g++) V3 (Itanium C++ ABI) style demangling"
}
,
{
JAVA_DEMANGLING_STYLE_STRING,
java_demangling,
"Java style demangling"
}
,
{
GNAT_DEMANGLING_STYLE_STRING,
gnat_demangling,
"GNAT style demangling"
}
,
{
DLANG_DEMANGLING_STYLE_STRING,
dlang_demangling,
"DLANG style demangling"
}
,
{
RUST_DEMANGLING_STYLE_STRING,
rust_demangling,
"Rust style demangling"
}
,
{
NULL, unknown_demangling, NULL
}
};
/* Add a routine to set the demangling style to be sure it is valid and
allow for any demangler initialization that maybe necessary. */
enum demangling_styles
Convert libiberty to use ISO C prototype style 3/n. * cplus-dem.c (set_cplus_marker_for_demangling, consume_count, consume_count_with_underscores, code_for_qualifier, qualifier_string, demangle_qualifier, cplus_demangle_opname, cplus_mangle_opname, cplus_demangle_set_style, cplus_demangle_name_to_style, cplus_demangle, grow_vect, ada_demangle, internal_cplus_demangle, squangle_mop_up, work_stuff_copy_to_from, delete_non_B_K_work_stuff, delete_work_stuff, mop_up, demangle_signature, demangle_method_args, demangle_template_template_parm, demangle_expression, demangle_integral_value, demangle_real_value, demangle_template_value_parm, demangle_template, arm_pt, demangle_arm_hp_template, demangle_class_name, demangle_class, iterate_demangle_function, demangle_prefix, gnu_special, recursively_demangle, arm_special, demangle_qualified, get_count, do_type, demangle_fund_type, do_hpacc_template_const_value, do_hpacc_template_literal, snarf_numeric_literal, do_arg, remember_type, remember_Ktype, register_Btype, remember_Btype, forget_B_and_K_types, forget_types, demangle_args, demangle_nested_args, demangle_function_name, string_need, string_delete, string_init, string_clear, string_empty, string_append, string_appends, string_appendn, string_prepend, string_prepends, string_prependn, string_append_template_idx): Use ISO C prootype style. * cp-demint.c (cplus_demangle_fill_component, cplus_demangle_fill_builtin_type, cplus_demangle_fill_operator, cplus_demangle_v3_components): Likewise. From-SVN: r97109
2005-03-27 07:00:12 +02:00
cplus_demangle_set_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;
}
/* Do string name to style translation */
enum demangling_styles
Convert libiberty to use ISO C prototype style 3/n. * cplus-dem.c (set_cplus_marker_for_demangling, consume_count, consume_count_with_underscores, code_for_qualifier, qualifier_string, demangle_qualifier, cplus_demangle_opname, cplus_mangle_opname, cplus_demangle_set_style, cplus_demangle_name_to_style, cplus_demangle, grow_vect, ada_demangle, internal_cplus_demangle, squangle_mop_up, work_stuff_copy_to_from, delete_non_B_K_work_stuff, delete_work_stuff, mop_up, demangle_signature, demangle_method_args, demangle_template_template_parm, demangle_expression, demangle_integral_value, demangle_real_value, demangle_template_value_parm, demangle_template, arm_pt, demangle_arm_hp_template, demangle_class_name, demangle_class, iterate_demangle_function, demangle_prefix, gnu_special, recursively_demangle, arm_special, demangle_qualified, get_count, do_type, demangle_fund_type, do_hpacc_template_const_value, do_hpacc_template_literal, snarf_numeric_literal, do_arg, remember_type, remember_Ktype, register_Btype, remember_Btype, forget_B_and_K_types, forget_types, demangle_args, demangle_nested_args, demangle_function_name, string_need, string_delete, string_init, string_clear, string_empty, string_append, string_appends, string_appendn, string_prepend, string_prepends, string_prependn, string_append_template_idx): Use ISO C prootype style. * cp-demint.c (cplus_demangle_fill_component, cplus_demangle_fill_builtin_type, cplus_demangle_fill_operator, cplus_demangle_v3_components): Likewise. From-SVN: r97109
2005-03-27 07:00:12 +02:00
cplus_demangle_name_to_style (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;
}
1997-08-22 00:57:35 +02:00
/* char *cplus_demangle (const char *mangled, int options)
If MANGLED is a mangled function name produced by GNU C++, then
a pointer to a @code{malloc}ed string giving a C++ representation
1997-08-22 00:57:35 +02:00
of the name will be returned; otherwise NULL will be returned.
It is the caller's responsibility to free the string which
is returned.
Note that any leading underscores, or other such characters prepended by
the compilation system, are presumed to have already been stripped from
MANGLED. */
char *
Convert libiberty to use ISO C prototype style 3/n. * cplus-dem.c (set_cplus_marker_for_demangling, consume_count, consume_count_with_underscores, code_for_qualifier, qualifier_string, demangle_qualifier, cplus_demangle_opname, cplus_mangle_opname, cplus_demangle_set_style, cplus_demangle_name_to_style, cplus_demangle, grow_vect, ada_demangle, internal_cplus_demangle, squangle_mop_up, work_stuff_copy_to_from, delete_non_B_K_work_stuff, delete_work_stuff, mop_up, demangle_signature, demangle_method_args, demangle_template_template_parm, demangle_expression, demangle_integral_value, demangle_real_value, demangle_template_value_parm, demangle_template, arm_pt, demangle_arm_hp_template, demangle_class_name, demangle_class, iterate_demangle_function, demangle_prefix, gnu_special, recursively_demangle, arm_special, demangle_qualified, get_count, do_type, demangle_fund_type, do_hpacc_template_const_value, do_hpacc_template_literal, snarf_numeric_literal, do_arg, remember_type, remember_Ktype, register_Btype, remember_Btype, forget_B_and_K_types, forget_types, demangle_args, demangle_nested_args, demangle_function_name, string_need, string_delete, string_init, string_clear, string_empty, string_append, string_appends, string_appendn, string_prepend, string_prepends, string_prependn, string_append_template_idx): Use ISO C prootype style. * cp-demint.c (cplus_demangle_fill_component, cplus_demangle_fill_builtin_type, cplus_demangle_fill_operator, cplus_demangle_v3_components): Likewise. From-SVN: r97109
2005-03-27 07:00:12 +02:00
cplus_demangle (const char *mangled, int options)
1997-08-22 00:57:35 +02:00
{
char *ret;
if (current_demangling_style == no_demangling)
return xstrdup (mangled);
if ((options & DMGL_STYLE_MASK) == 0)
options |= (int) current_demangling_style & DMGL_STYLE_MASK;
/* The V3 ABI demangling is implemented elsewhere. */
if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
{
ret = cplus_demangle_v3 (mangled, options);
if (GNU_V3_DEMANGLING)
return ret;
if (ret)
{
/* Rust symbols are GNU_V3 mangled plus some extra subtitutions.
The subtitutions are always smaller, so do in place changes. */
if (rust_is_mangled (ret))
rust_demangle_sym (ret);
else if (RUST_DEMANGLING)
{
free (ret);
ret = NULL;
}
}
if (ret || RUST_DEMANGLING)
return ret;
}
if (JAVA_DEMANGLING)
{
ret = java_demangle_v3 (mangled);
if (ret)
return ret;
}
if (GNAT_DEMANGLING)
return ada_demangle (mangled, options);
if (DLANG_DEMANGLING)
{
ret = dlang_demangle (mangled, options);
if (ret)
return ret;
}
return (ret);
}
char *
rust_demangle (const char *mangled, int options)
{
/* Rust symbols are GNU_V3 mangled plus some extra subtitutions. */
char *ret = cplus_demangle_v3 (mangled, options);
/* The Rust subtitutions are always smaller, so do in place changes. */
if (ret != NULL)
{
if (rust_is_mangled (ret))
rust_demangle_sym (ret);
else
{
free (ret);
ret = NULL;
}
}
return ret;
}
/* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
char *
Convert libiberty to use ISO C prototype style 3/n. * cplus-dem.c (set_cplus_marker_for_demangling, consume_count, consume_count_with_underscores, code_for_qualifier, qualifier_string, demangle_qualifier, cplus_demangle_opname, cplus_mangle_opname, cplus_demangle_set_style, cplus_demangle_name_to_style, cplus_demangle, grow_vect, ada_demangle, internal_cplus_demangle, squangle_mop_up, work_stuff_copy_to_from, delete_non_B_K_work_stuff, delete_work_stuff, mop_up, demangle_signature, demangle_method_args, demangle_template_template_parm, demangle_expression, demangle_integral_value, demangle_real_value, demangle_template_value_parm, demangle_template, arm_pt, demangle_arm_hp_template, demangle_class_name, demangle_class, iterate_demangle_function, demangle_prefix, gnu_special, recursively_demangle, arm_special, demangle_qualified, get_count, do_type, demangle_fund_type, do_hpacc_template_const_value, do_hpacc_template_literal, snarf_numeric_literal, do_arg, remember_type, remember_Ktype, register_Btype, remember_Btype, forget_B_and_K_types, forget_types, demangle_args, demangle_nested_args, demangle_function_name, string_need, string_delete, string_init, string_clear, string_empty, string_append, string_appends, string_appendn, string_prepend, string_prepends, string_prependn, string_append_template_idx): Use ISO C prootype style. * cp-demint.c (cplus_demangle_fill_component, cplus_demangle_fill_builtin_type, cplus_demangle_fill_operator, cplus_demangle_v3_components): Likewise. From-SVN: r97109
2005-03-27 07:00:12 +02:00
ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
{
int len0;
const char* p;
char *d;
char *demangled = NULL;
/* Discard leading _ada_, which is used for library level subprograms. */
if (strncmp (mangled, "_ada_", 5) == 0)
mangled += 5;
/* All ada unit names are lower-case. */
if (!ISLOWER (mangled[0]))
goto unknown;
/* Most of the demangling will trivially remove chars. Operator names
may add one char but because they are always preceeded by '__' which is
replaced by '.', they eventually never expand the size.
A few special names such as '___elabs' add a few chars (at most 7), but
they occur only once. */
len0 = strlen (mangled) + 7 + 1;
demangled = XNEWVEC (char, len0);
d = demangled;
p = mangled;
while (1)
{
/* An entity names is expected. */
if (ISLOWER (*p))
{
/* An identifier, which is always lower case. */
do
*d++ = *p++;
while (ISLOWER(*p) || ISDIGIT (*p)
|| (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
}
else if (p[0] == 'O')
{
/* An operator name. */
static const char * const operators[][2] =
{{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"},
{"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"},
{"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="},
{"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"},
{"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"},
{"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
{"Oexpon", "**"}, {NULL, NULL}};
int k;
for (k = 0; operators[k][0] != NULL; k++)
{
size_t slen = strlen (operators[k][0]);
if (strncmp (p, operators[k][0], slen) == 0)
{
p += slen;
slen = strlen (operators[k][1]);
*d++ = '"';
memcpy (d, operators[k][1], slen);
d += slen;
*d++ = '"';
break;
}
}
/* Operator not found. */
if (operators[k][0] == NULL)
goto unknown;
}
else
{
/* Not a GNAT encoding. */
goto unknown;
}
/* The name can be directly followed by some uppercase letters. */
if (p[0] == 'T' && p[1] == 'K')
{
/* Task stuff. */
if (p[2] == 'B' && p[3] == 0)
{
/* Subprogram for task body. */
break;
}
else if (p[2] == '_' && p[3] == '_')
{
/* Inner declarations in a task. */
p += 4;
*d++ = '.';
continue;
}
else
goto unknown;
}
if (p[0] == 'E' && p[1] == 0)
{
/* Exception name. */
goto unknown;
}
if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
{
/* Protected type subprogram. */
break;
}
if ((*p == 'N' || *p == 'S') && p[1] == 0)
{
/* Enumerated type name table. */
goto unknown;
}
if (p[0] == 'X')
{
/* Body nested. */
p++;
while (p[0] == 'n' || p[0] == 'b')
p++;
}
if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
{
/* Stream operations. */
const char *name;
switch (p[1])
{
case 'R':
name = "'Read";
break;
case 'W':
name = "'Write";
break;
case 'I':
name = "'Input";
break;
case 'O':
name = "'Output";
break;
default:
goto unknown;
}
p += 2;
strcpy (d, name);
d += strlen (name);
}
else if (p[0] == 'D')
{
/* Controlled type operation. */
const char *name;
switch (p[1])
{
case 'F':
name = ".Finalize";
break;
case 'A':
name = ".Adjust";
break;
default:
goto unknown;
}
strcpy (d, name);
d += strlen (name);
break;
}
if (p[0] == '_')
{
/* Separator. */
if (p[1] == '_')
{
/* Standard separator. Handled first. */
p += 2;
if (ISDIGIT (*p))
{
/* Overloading number. */
do
p++;
while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
if (*p == 'X')
{
p++;
while (p[0] == 'n' || p[0] == 'b')
p++;
}
}
else if (p[0] == '_' && p[1] != '_')
{
/* Special names. */
static const char * const special[][2] = {
{ "_elabb", "'Elab_Body" },
{ "_elabs", "'Elab_Spec" },
{ "_size", "'Size" },
{ "_alignment", "'Alignment" },
{ "_assign", ".\":=\"" },
{ NULL, NULL }
};
int k;
for (k = 0; special[k][0] != NULL; k++)
{
size_t slen = strlen (special[k][0]);
if (strncmp (p, special[k][0], slen) == 0)
{
p += slen;
slen = strlen (special[k][1]);
memcpy (d, special[k][1], slen);
d += slen;
break;
}
}
if (special[k][0] != NULL)
break;
else
goto unknown;
}
else
{
*d++ = '.';
continue;
}
}
else if (p[1] == 'B' || p[1] == 'E')
{
/* Entry Body or barrier Evaluation. */
p += 2;
while (ISDIGIT (*p))
p++;
if (p[0] == 's' && p[1] == 0)
break;
else
goto unknown;
}
else
goto unknown;
}
if (p[0] == '.' && ISDIGIT (p[1]))
{
/* Nested subprogram. */
p += 2;
while (ISDIGIT (*p))
p++;
}
if (*p == 0)
{
/* End of mangled name. */
break;
}
else
goto unknown;
}
*d = 0;
return demangled;
unknown:
XDELETEVEC (demangled);
len0 = strlen (mangled);
demangled = XNEWVEC (char, len0 + 3);
if (mangled[0] == '<')
strcpy (demangled, mangled);
else
sprintf (demangled, "<%s>", mangled);
return demangled;
}