📄 cplus-dem.c
字号:
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; } demangled = mop_up (work, &decl, success); } return (demangled);}static char *mop_up (work, declp, success) struct work_stuff *work; string *declp; int success;{ char *demangled = NULL; /* Discard the remembered types, if any. */ forget_types (work); if (work -> typevec != NULL) { free ((char *) work -> typevec); } /* If demangling was successful, ensure that the demangled string is null terminated and return it. Otherwise, free the demangling decl. */ if (!success) { string_delete (declp); } else { string_appendn (declp, "", 1); demangled = declp -> b; } return (demangled);}/*LOCAL FUNCTION demangle_signature -- demangle the signature part of a mangled nameSYNOPSIS static int demangle_signature (struct work_stuff *work, const char **mangled, string *declp);DESCRIPTION Consume and demangle the signature portion of the mangled name. DECLP is the string where demangled output is being built. At entry it contains the demangled root name from the mangled name prefix. I.E. either a demangled operator name or the root function name. In some special cases, it may contain nothing. *MANGLED points to the current unconsumed location in the mangled name. As tokens are consumed and demangling is performed, the pointer is updated to continuously point at the next token to be consumed. Demangling GNU style mangled names is nasty because there is no explicit token that marks the start of the outermost function argument list. */static intdemangle_signature (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp;{ int success = 1; int func_done = 0; int expect_func = 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 'S': /* Static member function */ if (oldmangled == NULL) { oldmangled = *mangled; } (*mangled)++; work -> static_type = 1; break; case 'C': /* a const member function */ if (oldmangled == NULL) { oldmangled = *mangled; } (*mangled)++; work -> const_type = 1; 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; } success = demangle_class (work, mangled, declp); if (success) { remember_type (work, oldmangled, *mangled - oldmangled); } if (AUTO_DEMANGLING || GNU_DEMANGLING) { expect_func = 1; } oldmangled = NULL; break; case 'F': /* Function */ /* ARM style demangling includes a specific 'F' character after the class name. For GNU style, it is just implied. So we can safely just consume any 'F' at this point and be compatible with either style. */ oldmangled = NULL; func_done = 1; (*mangled)++; /* For lucid/ARM style we have to forget any types we might have remembered up to this point, since they were not argument types. GNU style considers all types seen as available for back references. See comment in demangle_args() */ if (LUCID_DEMANGLING || ARM_DEMANGLING) { forget_types (work); } success = demangle_args (work, mangled, declp); break; case 't': /* G++ Template */ string_init(&trawname); string_init(&tname); if (oldmangled == NULL) { oldmangled = *mangled; } success = demangle_template (work, mangled, &tname, &trawname); if (success) { remember_type (work, oldmangled, *mangled - oldmangled); } string_append(&tname, "::"); 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 '_': /* At the outermost level, we cannot have a return type specified, so if we run into another '_' at this point we are dealing with a mangled name that is either bogus, or has been mangled by some algorithm we don't know how to deal with. So just reject the entire demangling. */ success = 0; break; default: if (AUTO_DEMANGLING || GNU_DEMANGLING) { /* Assume we have stumbled onto the first outermost function argument token, and start processing args. */ func_done = 1; success = demangle_args (work, mangled, declp); } else { /* Non-GNU demanglers use a specific token to mark the start of the outermost function argument tokens. Typically 'F', for ARM-demangling, for example. So if we find something we are not prepared for, it must be an error. */ success = 0; } break; } /* if (AUTO_DEMANGLING || GNU_DEMANGLING) */ { if (success && expect_func) { func_done = 1; success = demangle_args (work, mangled, declp); } } } if (success && !func_done) { if (AUTO_DEMANGLING || GNU_DEMANGLING) { /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and bar__3fooi is 'foo::bar(int)'. We get here when we find the first case, and need to ensure that the '(void)' gets added to the current declp. Note that with ARM, the first case represents the name of a static data member 'foo::bar', which is in the current declp, so we leave it alone. */ success = demangle_args (work, mangled, declp); } } if (success && work -> static_type && PRINT_ARG_TYPES) { string_append (declp, " static"); } if (success && work -> const_type && PRINT_ARG_TYPES) { string_append (declp, " const"); } return (success);}#if 0static intdemangle_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);}#endifstatic intdemangle_template (work, mangled, tname, trawname) struct work_stuff *work; const char **mangled; string *tname; string *trawname;{ int i; int is_pointer; int is_real; int is_integral; int is_char; int is_bool; int r; int need_comma = 0; int success = 0; int done; const char *old_p; const char *start; int symbol_len; string temp; (*mangled)++; start = *mangled; /* get template name */ if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r) { return (0); } if (trawname) string_appendn (trawname, *mangled, r); string_appendn (tname, *mangled, r); *mangled += r; string_append (tname, "<"); /* get size of template parameter list */ if (!get_count (mangled, &r)) { return (0); } for (i = 0; i < r; i++) { if (need_comma) { string_append (tname, ", "); } /* Z for type parameters */ if (**mangled == 'Z') { (*mangled)++; /* temp is initialized in do_type */ success = do_type (work, mangled, &temp); if (success) { string_appends (tname, &temp); } string_delete(&temp); if (!success) { break; } } else { /* otherwise, value parameter */ old_p = *mangled; is_pointer = 0; is_real = 0; is_integral = 0; is_char = 0; is_bool = 0; done = 0; /* temp is initialized in do_type */ success = do_type (work, mangled, &temp); /* if (success) { string_appends (tname, &temp); } */ string_delete(&temp); if (!success) { break; } /* string_append (tname, "="); */ while (*old_p && !done) { switch (*old_p) { case 'P': case 'p': case 'R': done = is_pointer = 1; break; case 'C': /* const */ case 'S': /* explicitly signed [char] */ case 'U': /* unsigned */ case 'V': /* volatile */ case 'F': /* function */ case 'M': /* member function */ case 'O': /* ??? */ old_p++; continue; case 'Q': /* qualified name */ done = is_integral = 1; break; case 'T': /* remembered type */ return 0; break; case 'v': /* void */ return 0; break; case 'x': /* long long */ case 'l': /* long */ case 'i': /* int */ case 's': /* short */ case 'w': /* wchar_t */ done = is_integral = 1; break; case 'b': /* bool */ done = is_bool = 1; break; case 'c': /* char */ done = is_char = 1; break; case 'r': /* long double */ case 'd': /* double */ case 'f': /* float */ done = is_real = 1; break; default: /* it's probably user defined type, let's assume it's integral, it seems hard to figure out what it really is */ done = is_integral = 1; } } if (is_integral) { if (**mangled == 'm') { string_appendn (tname, "-", 1); (*mangled)++; } while (isdigit (**mangled)) { string_appendn (tname, *mangled, 1); (*mangled)++; } } else if (is_char) { char tmp[2]; int val; if (**mangled == 'm') { string_appendn (tname, "-", 1); (*mangled)++; } string_appendn (tname, "'", 1); val = consume_count(mangled); if (val == 0) { success = 0; break; } tmp[0] = (char)val; tmp[1] = '\0'; string_appendn (tname, &tmp[0], 1); string_appendn (tname, "'", 1); } else if (is_bool) { int val = consume_count (mangled); if (val == 0) string_appendn (tname, "false", 5); else if (val == 1) string_appendn (tname, "true", 4); else success = 0; } else if (is_real) { if (**mangled == 'm') { string_appendn (tname, "-", 1); (*mangled)++; } while (isdigit (**mangled)) { string_appendn (tname, *mangled, 1); (*mangled)++; } if (**mangled == '.') /* fraction */ { string_appendn (tname, ".", 1); (*mangled)++; while (isdigit (**mangled)) { string_appendn (tname, *mangled, 1); (*mangled)++; } } if (**mangled == 'e') /* exponent */ { string_appendn (tname, "e", 1); (*mangled)++; while (isdigit (**mangled)) { string_appendn (tname, *mangled, 1); (*mangled)++; } } } else if (is_pointer) { symbol_len = consume_count (mangled); if (symbol_len == 0) { success = 0; break; } if (symbol_len == 0) string_appendn (tname, "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); string_appendn (tname, "&", 1); if (q) { string_append (tname, q); free (q); } else string_append (tname, p); free (p); } *mangled += symbol_len; } } need_comma = 1; } if (tname->p[-1] == '>') string_append (tname, " "); string_append (tname, ">"); /* if (work -> static_type) { string_append (declp, *mangled + 1); *mangled += strlen (*mangled); success = 1; } else { success = demangle_args (work, mangled, declp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -