📄 cplus-dem.c
字号:
/* cplus-dem.c - C++ link name demangler *//*modification history--------------------01a,10jun98,sn created from the GNU file libiberty/cplus-dem.c replaced xmalloc and xrealloc with malloc and realloc. removed calls to abort.*//*NOMANUAL*//* Demangler for GNU C++ Copyright 1989, 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.uucp) Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling This file is part of the libiberty library.Libiberty is free software; you can redistribute it and/ormodify it under the terms of the GNU Library General PublicLicense as published by the Free Software Foundation; eitherversion 2 of the License, or (at your option) any later version.Libiberty is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULibrary General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with libiberty; see the file COPYING.LIB. Ifnot, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. *//* This file exports two functions; cplus_mangle_opname and cplus_demangle. This file imports xmalloc and xrealloc, which are like malloc and realloc except that they generate a fatal error if there is no available memory. *//* This file lives in both GCC and libiberty. When making changes, please try not to break either. */#include <ctype.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <demangle.h>#undef CURRENT_DEMANGLING_STYLE#define CURRENT_DEMANGLING_STYLE work->options#define xmalloc malloc#define xrealloc realloc#if 0extern char *xmalloc (unsigned);extern char *xrealloc (char *, unsigned);#endifstatic const char *mystrstr (const char *, const char *);static const char *mystrstr (s1, s2) const char *s1, *s2;{ register const char *p = s1; register int len = strlen (s2); for (; (p = strchr (p, *s2)) != 0; p++) { if (strncmp (p, s2, len) == 0) { return (p); } } return (0);}/* In order to allow a single demangler executable to demangle strings using various common values of CPLUS_MARKER, as well as any specific one set at compile time, we maintain a string containing all the commonly used ones, and check to see if the marker we are looking for is in that string. CPLUS_MARKER is usually '$' on systems where the assembler can deal with that. Where the assembler can't, it's usually '.' (but on many systems '.' is used for other things). We put the current defined CPLUS_MARKER first (which defaults to '$'), followed by the next most common value, followed by an explicit '$' in case the value of CPLUS_MARKER is not '$'. We could avoid this if we could just get g++ to tell us what the actual cplus marker character is as part of the debug information, perhaps by ensuring that it is the character that terminates the gcc<n>_compiled marker symbol (FIXME). */#if !defined (CPLUS_MARKER)#define CPLUS_MARKER '$'#endifenum demangling_styles current_demangling_style = gnu_demangling;static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };voidset_cplus_marker_for_demangling (ch) int ch;{ cplus_markers[0] = ch;}/* Stuff that is shared between sub-routines. Using a shared structure allows cplus_demangle to be reentrant. */struct work_stuff{ int options; char **typevec; int ntypes; int typevec_size; int constructor; int destructor; int static_type; /* A static member function */ int const_type; /* A const member function */};#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)static const struct optable{ const char *in; const char *out; int flags;} optable[] = { {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */ {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ {"new", " new", 0}, /* old (1.91, and 1.x) */ {"delete", " delete", 0}, /* old (1.91, and 1.x) */ {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */ {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */ {"as", "=", DMGL_ANSI}, /* ansi */ {"ne", "!=", DMGL_ANSI}, /* old, ansi */ {"eq", "==", DMGL_ANSI}, /* old, ansi */ {"ge", ">=", DMGL_ANSI}, /* old, ansi */ {"gt", ">", DMGL_ANSI}, /* old, ansi */ {"le", "<=", DMGL_ANSI}, /* old, ansi */ {"lt", "<", DMGL_ANSI}, /* old, ansi */ {"plus", "+", 0}, /* old */ {"pl", "+", DMGL_ANSI}, /* ansi */ {"apl", "+=", DMGL_ANSI}, /* ansi */ {"minus", "-", 0}, /* old */ {"mi", "-", DMGL_ANSI}, /* ansi */ {"ami", "-=", DMGL_ANSI}, /* ansi */ {"mult", "*", 0}, /* old */ {"ml", "*", DMGL_ANSI}, /* ansi */ {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */ {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */ {"convert", "+", 0}, /* old (unary +) */ {"negate", "-", 0}, /* old (unary -) */ {"trunc_mod", "%", 0}, /* old */ {"md", "%", DMGL_ANSI}, /* ansi */ {"amd", "%=", DMGL_ANSI}, /* ansi */ {"trunc_div", "/", 0}, /* old */ {"dv", "/", DMGL_ANSI}, /* ansi */ {"adv", "/=", DMGL_ANSI}, /* ansi */ {"truth_andif", "&&", 0}, /* old */ {"aa", "&&", DMGL_ANSI}, /* ansi */ {"truth_orif", "||", 0}, /* old */ {"oo", "||", DMGL_ANSI}, /* ansi */ {"truth_not", "!", 0}, /* old */ {"nt", "!", DMGL_ANSI}, /* ansi */ {"postincrement","++", 0}, /* old */ {"pp", "++", DMGL_ANSI}, /* ansi */ {"postdecrement","--", 0}, /* old */ {"mm", "--", DMGL_ANSI}, /* ansi */ {"bit_ior", "|", 0}, /* old */ {"or", "|", DMGL_ANSI}, /* ansi */ {"aor", "|=", DMGL_ANSI}, /* ansi */ {"bit_xor", "^", 0}, /* old */ {"er", "^", DMGL_ANSI}, /* ansi */ {"aer", "^=", DMGL_ANSI}, /* ansi */ {"bit_and", "&", 0}, /* old */ {"ad", "&", DMGL_ANSI}, /* ansi */ {"aad", "&=", DMGL_ANSI}, /* ansi */ {"bit_not", "~", 0}, /* old */ {"co", "~", DMGL_ANSI}, /* ansi */ {"call", "()", 0}, /* old */ {"cl", "()", DMGL_ANSI}, /* ansi */ {"alshift", "<<", 0}, /* old */ {"ls", "<<", DMGL_ANSI}, /* ansi */ {"als", "<<=", DMGL_ANSI}, /* ansi */ {"arshift", ">>", 0}, /* old */ {"rs", ">>", DMGL_ANSI}, /* ansi */ {"ars", ">>=", DMGL_ANSI}, /* ansi */ {"component", "->", 0}, /* old */ {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */ {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */ {"indirect", "*", 0}, /* old */ {"method_call", "->()", 0}, /* old */ {"addr", "&", 0}, /* old (unary &) */ {"array", "[]", 0}, /* old */ {"vc", "[]", DMGL_ANSI}, /* ansi */ {"compound", ", ", 0}, /* old */ {"cm", ", ", DMGL_ANSI}, /* ansi */ {"cond", "?:", 0}, /* old */ {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */ {"max", ">?", 0}, /* old */ {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */ {"min", "<?", 0}, /* old */ {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */ {"nop", "", 0}, /* old (for operator=) */ {"rm", "->*", DMGL_ANSI} /* ansi */};typedef struct string /* Beware: these aren't required to be */{ /* '\0' terminated. */ char *b; /* pointer to start of string */ char *p; /* pointer after last character */ char *e; /* pointer after end of allocated space */} string;#define STRING_EMPTY(str) ((str) -> b == (str) -> p)#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ string_prepend(str, " ");}#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ string_append(str, " ");}#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) *//* Prototypes for local functions */static char *mop_up (struct work_stuff *, string *, int);#if 0static intdemangle_method_args (struct work_stuff *work, const char **, string *);#endifstatic intdemangle_template (struct work_stuff *work, const char **, string *, string *);static intarm_pt (struct work_stuff *, const char *, int, const char **, const char **);static voiddemangle_arm_pt (struct work_stuff *, const char **, int, string *);static intdemangle_class_name (struct work_stuff *, const char **, string *);static intdemangle_qualified (struct work_stuff *, const char **, string *, int, int);static intdemangle_class (struct work_stuff *, const char **, string *);static intdemangle_fund_type (struct work_stuff *, const char **, string *);static intdemangle_signature (struct work_stuff *, const char **, string *);static intdemangle_prefix (struct work_stuff *, const char **, string *);static intgnu_special (struct work_stuff *, const char **, string *);static intarm_special (struct work_stuff *, const char **, string *);static voidstring_need (string *, int);static voidstring_delete (string *);static voidstring_init (string *);static voidstring_clear (string *);#if 0static intstring_empty (string *);#endifstatic voidstring_append (string *, const char *);static voidstring_appends (string *, string *);static voidstring_appendn (string *, const char *, int);static voidstring_prepend (string *, const char *);static voidstring_prependn (string *, const char *, int);static intget_count (const char **, int *);static intconsume_count (const char **);static intdemangle_args (struct work_stuff *, const char **, string *);static intdo_type (struct work_stuff *, const char **, string *);static intdo_arg (struct work_stuff *, const char **, string *);static voiddemangle_function_name (struct work_stuff *, const char **, string *, const char *);static voidremember_type (struct work_stuff *, const char *, int);static voidforget_types (struct work_stuff *);static voidstring_prepends (string *, string *);/* Translate count to integer, consuming tokens in the process. Conversion terminates on the first non-digit character. Trying to consume something that isn't a count results in no consumption of input and a return of 0. */static intconsume_count (type) const char **type;{ int count = 0; while (isdigit (**type)) { count *= 10; count += **type - '0'; (*type)++; } return (count);}intcplus_demangle_opname (opname, result, options) const char *opname; char *result; int options;{ int len, i, len1, ret; string type; struct work_stuff work[1]; const char *tem; len = strlen(opname); result[0] = '\0'; ret = 0; work->options = options; if (opname[0] == '_' && opname[1] == '_' && opname[2] == 'o' && opname[3] == 'p') { /* ANSI. */ /* type conversion operator. */ 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] == '_' && opname[2] >= 'a' && opname[2] <= 'z' && opname[3] >= 'a' && opname[3] <= 'z') { if (opname[4] == '\0') { /* Operator. */ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); 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') { /* Assignment. */ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); 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) { /* see if it's an assignment expression */ if (len >= 10 /* op$assign_ */ && memcmp (opname + 3, "assign_", 7) == 0) { for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { len1 = len - 10; if (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 { for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { len1 = len - 3; if (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) { /* type conversion operator */ 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; } } return ret;}/* Takes operator name as e.g. "++" and returns mangled operator name (e.g. "postincrement_expr"), or NULL if not found. If OPTIONS & DMGL_ANSI == 1, return the ANSI name; if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */const char *cplus_mangle_opname (opname, options) const char *opname; int options;{ int i; int len; len = strlen (opname); for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) { if (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);}/* char *cplus_demangle (const char *mangled, int options) If MANGLED is a mangled function name produced by GNU C++, then a pointer to a malloced string giving a C++ representation of the name will be returned; otherwise NULL will be returned. It is the caller's responsibility to free the string which is returned. The OPTIONS arg may contain one or more of the following bits: DMGL_ANSI ANSI qualifiers such as `const' and `void' are included. DMGL_PARAMS Function parameters are included. For example, cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" cplus_demangle ("foo__1Ai", 0) => "A::foo" cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" cplus_demangle ("foo__1Afe", 0) => "A::foo" Note that any leading underscores, or other such characters prepended by the compilation system, are presumed to have already been stripped from MANGLED. */char *cplus_demangle (mangled, options) const char *mangled; int options;{ string decl; int success = 0; struct work_stuff work[1]; char *demangled = NULL; if ((mangled != NULL) && (*mangled != '\0')) { 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; string_init (&decl); /* First check to see if gnu style demangling is active and if the string to be demangled contains a CPLUS_MARKER. If so, attempt to recognize one of the gnu special forms rather than looking for a standard prefix. In particular, don't worry about whether there is a "__" string in the mangled string. Consider "_$_5__foo" for example. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -