📄 cp-dem.c
字号:
/* Demangler for GNU C++ Copyright (C) 1989, 1992 Free Software Foundation, Inc. written by James Clark (jjc@jclark.uucp) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* This is for g++ 1.36.1 (November 6 version). It will probably require changes for any other version. Modified for g++ 1.36.2 (November 18 version). Modified for g++ 1.90.06 (December 31 version). Modified for g++ 1.95.03 (November 13 version). *//* This file exports one function char *cplus_demangle (const char *name) If NAME 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. For example, cplus_demangle ("_foo__1Ai") returns "A::foo(int)" 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. *//* #define nounderscore 1 /* define this is names don't start with _ */#include <stdio.h>#include <ctype.h>#ifdef USG#include <memory.h>#else#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))#endif/* This is '$' on systems where the assembler can deal with that. Where the assembler can't, it's '.' (but on many systems '.' is used for other things). */#if !defined (CPLUS_MARKER)#define CPLUS_MARKER '$'#endif#ifndef __STDC__#define const#endif#ifdef __STDC__extern char *cplus_demangle (const char *type);#elseextern char *cplus_demangle ();#endif#ifdef __STDC__extern char *xmalloc (int);extern char *xrealloc (char *, int);extern void free (char *);#elseextern char *xmalloc ();extern char *xrealloc ();extern void free ();#endifstatic char **typevec = 0;static int ntypes = 0;static int typevec_size = 0;static struct { const char *in; const char *out;} optable[] = { "nw", " new", /* new (1.92, ansi) */ "dl", " delete", /* new (1.92, ansi) */ "new", " new", /* old (1.91) */ "delete", " delete", /* old (1.91) */ "ne", "!=", /* old, ansi */ "eq", "==", /* old, ansi */ "ge", ">=", /* old, ansi */ "gt", ">", /* old, ansi */ "le", "<=", /* old, ansi */ "lt", "<", /* old, ansi */ "plus", "+", /* old */ "pl", "+", /* ansi */ "apl", "+=", /* ansi */ "minus", "-", /* old */ "mi", "-", /* ansi */ "ami", "-=", /* ansi */ "mult", "*", /* old */ "ml", "*", /* ansi */ "aml", "*=", /* ansi */ "convert", "+", /* old (unary +) */ "negate", "-", /* old (unary -) */ "trunc_mod", "%", /* old */ "md", "%", /* ansi */ "amd", "%=", /* ansi */ "trunc_div", "/", /* old */ "dv", "/", /* ansi */ "adv", "/=", /* ansi */ "truth_andif", "&&", /* old */ "aa", "&&", /* ansi */ "truth_orif", "||", /* old */ "oo", "||", /* ansi */ "truth_not", "!", /* old */ "nt", "!", /* ansi */ "postincrement", "++", /* old */ "pp", "++", /* ansi */ "postdecrement", "--", /* old */ "mm", "--", /* ansi */ "bit_ior", "|", /* old */ "or", "|", /* ansi */ "aor", "|=", /* ansi */ "bit_xor", "^", /* old */ "er", "^", /* ansi */ "aer", "^=", /* ansi */ "bit_and", "&", /* old */ "ad", "&", /* ansi */ "aad", "&=", /* ansi */ "bit_not", "~", /* old */ "co", "~", /* ansi */ "call", "()", /* old */ "cl", "()", /* ansi */ "cond", "?:", /* old */ "alshift", "<<", /* old */ "ls", "<<", /* ansi */ "als", "<<=", /* ansi */ "arshift", ">>", /* old */ "rs", ">>", /* ansi */ "ars", ">>=", /* ansi */ "component", "->", /* old */ "rf", "->", /* ansi */ "indirect", "*", /* old */ "method_call", "->()", /* old */ "addr", "&", /* old (unary &) */ "array", "[]", /* old */ "vc", "[]", /* ansi */ "compound", ",", /* old */ "cm", ",", /* ansi */ "nop", "", /* old (for operator=) */ "as", "=", /* ansi */};/* Beware: these aren't '\0' terminated. */typedef struct { char *b; /* pointer to start of string */ char *p; /* pointer after last character */ char *e; /* pointer after end of allocated space */} string;#ifdef __STDC__static void string_need (string *s, int n);static void string_delete (string *s);static void string_init (string *s);static void string_clear (string *s);static int string_empty (string *s);static void string_append (string *p, const char *s);static void string_appends (string *p, string *s);static void string_appendn (string *p, const char *s, int n);static void string_prepend (string *p, const char *s);#if 0static void string_prepends (string *p, string *s);#endifstatic void string_prependn (string *p, const char *s, int n);static int get_count (const char **type, int *count);static int do_args (const char **type, string *decl);static int do_type (const char **type, string *result);static int do_arg (const char **type, string *result);static int do_args (const char **type, string *decl);static void munge_function_name (string *name);static void remember_type (const char *type, int len);#elsestatic void string_need ();static void string_delete ();static void string_init ();static void string_clear ();static int string_empty ();static void string_append ();static void string_appends ();static void string_appendn ();static void string_prepend ();static void string_prepends ();static void string_prependn ();static int get_count ();static int do_args ();static int do_type ();static int do_arg ();static int do_args ();static void munge_function_name ();static void remember_type ();#endifintget_simple_count (type, res) char **type; int *res;{ int n = 0, success = 1;; do { n *= 10; n += **type - '0'; *type += 1; } while (isdigit (**type)); if (strlen (*type) < n) { success = 0; } *res = n; return success;}char *cplus_demangle (type) const char *type;{ string decl; int n; int success = 0; int constructor = 0; int destructor = 0; int static_type = 0; int const_flag = 0; int i; const char *p;#ifndef LONGERNAMES const char *premangle;#endif if (type == NULL || *type == '\0') return NULL;#ifndef nounderscore if (*type++ != '_') return NULL;#endif p = type; while (*p != '\0' && !(*p == '_' && p[1] == '_')) p++; if (*p == '\0') { /* destructor */ if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_') { destructor = 1; p = type; } /* static data member */ else if (*type != '_' && (index (type, CPLUS_MARKER) != NULL)) { static_type = 1; p = type; } /* virtual table "_vt$" */ else if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER) { int n = strlen (type + 4) + 14 + 1; char *tem = (char *) xmalloc (n); strcpy (tem, type + 4); strcat (tem, " virtual table"); return tem; } else return NULL; } string_init (&decl); if (static_type) { if (!isdigit (p[0]) && ('t' != p[0])) { string_delete (&decl); return NULL; } } else if (destructor) { if (!isdigit (p[3])&& ('t' != p[3])) { string_delete (&decl); return NULL; } p += 3; } else if (p == type) { if (!isdigit (p[2]) && ('t' != p[2])) { p += 1; while (*p != '\0' && !(*p == '_' && p[1] == '_')) p++; string_appendn (&decl, type, p - type); string_appendn (&decl, "", 1); munge_function_name (&decl); if (decl.b[0] == '_') { string_delete (&decl); return NULL; } else p += 2; } else { constructor = 1; p += 2; } } else { string_appendn (&decl, type, p - type); decl.p[0] = '0'; munge_function_name (&decl); p += 2; }#ifndef LONGERNAMES premangle = p;#endif switch (*p) { case 'C': /* a const member function */ if (!isdigit (p[1])) { string_delete (&decl); return NULL; } p += 1; const_flag = 1; /* fall through */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; do { n *= 10; n += *p - '0'; p += 1; } while (isdigit (*p)); if (strlen (p) < n) { string_delete (&decl); return NULL; } if (constructor || destructor) { string_appendn (&decl, p, n); string_append (&decl, "::"); if (destructor) string_append(&decl, "~"); string_appendn (&decl, p, n); } else { string_prepend (&decl, "::"); string_prependn (&decl, p, n); } p += n;#ifndef LONGERNAMES remember_type (premangle, p - premangle);#endif if (static_type) { string_append(&decl, p+1); p += strlen(p); success = 1; } else success = do_args (&p, &decl); if (const_flag) string_append (&decl, " const"); break; case 'F': p += 1; success = do_args (&p, &decl); break; /* template additions */ case 't': p += 1; { int r, i; string tname; string trawname; string temp; int need_comma = 0; string_init(&tname); string_init(&trawname); /* get template name */ if (!get_simple_count (&p, &r)) { string_delete (&decl); return 0; } string_appendn (&tname, p, r); string_appendn (&trawname, p, r); string_appendn (&trawname, "", 1); p += r; string_append (&tname, "<"); /* get size of template parameter list */ if (!get_count (&p, &r)) return 0; for (i = 0; i < r; i++) { if (need_comma) string_append (&tname, ", "); /* Z for type parameters */ if (*p == 'Z') { p += 1; success = do_type (&p, &temp); string_appendn (&temp, "", 1); if (success) string_append (&tname, temp.b); string_delete(&temp); if (!success) break; } /* otherwise, value parameter */ else { const char *old_p = p; int is_pointer = 0; int is_real = 0; int is_integral = 0; int done = 0; success = do_type (&p, &temp); string_appendn (&temp, "", 1); if (success) string_append (&tname, temp.b); string_delete(&temp); if (!success) break; string_append (&tname, "="); while (*old_p && !done) { switch (*old_p) { case 'P': case 'R': done = is_pointer = 1; break; case 'C': /* const */ case 'U': /* unsigned */ case 'V': /* volatile */ case 'F': /* function */ case 'M': /* member function */ case 'O': /* ??? */ old_p++; continue; case 'Q': /* repetition of following */ case 'T': /* remembered type */ abort(); break; case 'v': /* void */ abort(); break; case 'x': /* long long */ case 'l': /* long */ case 'i': /* int */ case 's': /* short */ case 'c': /* char */ case 'w': /* wchar_t */ done = is_integral = 1; break; case 'r': /* long double */ case 'd': /* double */ case 'f': /* float */ done = is_real = 1; break; default: abort(); } } if (is_integral) { if (*p == 'm') { string_appendn (&tname, "-", 1); p++; } while (isdigit (*p)) { string_appendn (&tname, p, 1); p++; } } else if (is_real) { if (*p == 'm') { string_appendn (&tname, "-", 1); p++; } while (isdigit (*p)) { string_appendn (&tname, p, 1); p++; } if (*p == '.') /* fraction */ { string_appendn (&tname, ".", 1); p++; while (isdigit (*p)) { string_appendn (&tname, p, 1); p++; } } if (*p == 'e') /* exponent */ { string_appendn (&tname, "e", 1); p++; while (isdigit (*p)) { string_appendn (&tname, p, 1); p++; } } } else if (is_pointer) { int symbol_len; if (!get_count (&p, &symbol_len)) { success = 0; break; } string_appendn (&tname, p, symbol_len); p += symbol_len; } } need_comma = 1; } string_append (&tname, ">::"); if (destructor) string_append(&tname, "~"); if (constructor || destructor) { string_appendn (&trawname, "", 1); string_append (&tname, trawname.b); } string_delete(&trawname); if (!success) { string_delete(&tname); return 0; } string_appendn (&tname, "", 1); string_prepend (&decl, tname.b); string_delete (&tname); if (static_type) { string_append (&decl, p+1); p += strlen (p); success = 1; } else success = do_args (&p, &decl); break; } } for (i = 0; i < ntypes; i++) if (typevec[i] != NULL) free (typevec[i]); ntypes = 0; if (typevec != NULL) { free ((char *)typevec); typevec = NULL; typevec_size = 0; } if (success) { string_appendn (&decl, "", 1); return decl.b; } else { string_delete (&decl); return NULL; }}static intget_count (type, count) const char **type; int *count;{ if (!isdigit (**type)) return 0; *count = **type - '0'; *type += 1; /* see flush_repeats in cp-method.c */ if (isdigit (**type)) { const char *p = *type; int n = *count; do { n *= 10; n += *p - '0'; p += 1; } while (isdigit (*p)); if (*p == '_') { *type = p + 1; *count = n; } } return 1;}/* result will be initialised here; it will be freed on failure */static intdo_type (type, result) const char **type; string *result;{ int n; int done; int non_empty = 0; int success; string decl; const char *remembered_type; string_init (&decl); string_init (result); done = 0; success = 1; while (success && !done)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -