📄 cplus-dem.c
字号:
} } */ return (success);}static intarm_pt (work, mangled, n, anchor, args) struct work_stuff *work; const char *mangled; int n; const char **anchor, **args;{ /* ARM template? */ if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__"))) { int len; *args = *anchor + 6; len = consume_count (args); if (*args + len == mangled + n && **args == '_') { ++*args; return 1; } } return 0;}static voiddemangle_arm_pt (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; /* ARM template? */ if (arm_pt (work, *mangled, n, &p, &args)) { string arg; string_init (&arg); string_appendn (declp, *mangled, p - *mangled); string_append (declp, "<"); /* should do error checking here */ while (args < e) { string_clear (&arg); do_type (work, &args, &arg); string_appends (declp, &arg); string_append (declp, ","); } string_delete (&arg); --declp->p; string_append (declp, ">"); } else { string_appendn (declp, *mangled, n); } *mangled += n;}static intdemangle_class_name (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp;{ int n; int success = 0; n = consume_count (mangled); if (strlen (*mangled) >= n) { demangle_arm_pt (work, mangled, n, declp); success = 1; } return (success);}/*LOCAL FUNCTION demangle_class -- demangle a mangled class sequenceSYNOPSIS static int demangle_class (struct work_stuff *work, const char **mangled, strint *declp)DESCRIPTION DECLP points to the buffer into which demangling is being done. *MANGLED points to the current token to be demangled. On input, it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) On exit, it points to the next token after the mangled class on success, or the first unconsumed token on failure. If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then we are demangling a constructor or destructor. In this case we prepend "class::class" or "class::~class" to DECLP. Otherwise, we prepend "class::" to the current DECLP. Reset the constructor/destructor flags once they have been "consumed". This allows demangle_class to be called later during the same demangling, to do normal class demangling. Returns 1 if demangling is successful, 0 otherwise.*/static intdemangle_class (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp;{ int success = 0; string class_name; string_init (&class_name); if (demangle_class_name (work, mangled, &class_name)) { if ((work->constructor & 1) || (work->destructor & 1)) { string_prepends (declp, &class_name); if (work -> destructor & 1) { string_prepend (declp, "~"); work -> destructor -= 1; } else { work -> constructor -= 1; } } string_prepend (declp, "::"); string_prepends (declp, &class_name); success = 1; } string_delete (&class_name); return (success);}/*LOCAL FUNCTION demangle_prefix -- consume the mangled name prefix and find signatureSYNOPSIS static int demangle_prefix (struct work_stuff *work, const char **mangled, string *declp);DESCRIPTION Consume and demangle the prefix of the mangled name. DECLP points to the string buffer into which demangled output is placed. On entry, the buffer is empty. On exit it contains the root function name, the demangled operator name, or in some special cases either nothing or the completely demangled result. MANGLED points to the current pointer into the mangled name. As each token of the mangled name is consumed, it is updated. Upon entry the current mangled name pointer points to the first character of the mangled name. Upon exit, it should point to the first character of the signature if demangling was successful, or to the first unconsumed character if demangling of the prefix was unsuccessful. Returns 1 on success, 0 otherwise. */static intdemangle_prefix (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp;{ int success = 1; const char *scan; int i; 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') { /* it's a GNU global destructor to be executed at program exit */ (*mangled) += 11; work->destructor = 2; if (gnu_special (work, mangled, declp)) return success; } else if ((*mangled)[9] == 'I') { /* it's a GNU global constructor to be executed at program init */ (*mangled) += 11; work->constructor = 2; if (gnu_special (work, mangled, declp)) return success; } } } else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0) { /* it's a ARM global destructor to be executed at program exit */ (*mangled) += 7; work->destructor = 2; } else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0) { /* it's a ARM global constructor to be executed at program initial */ (*mangled) += 7; work->constructor = 2; } /* This block of code is a reduction in strength time optimization of: scan = mystrstr (*mangled, "__"); */ { scan = *mangled; do { scan = strchr (scan, '_'); } while (scan != NULL && *++scan != '_'); if (scan != NULL) --scan; } if (scan != NULL) { /* We found a sequence of two or more '_', ensure that we start at the last pair in the sequence. */ i = strspn (scan, "_"); if (i > 2) { scan += (i - 2); } } if (scan == NULL) { success = 0; } else if (work -> static_type) { if (!isdigit (scan[0]) && (scan[0] != 't')) { success = 0; } } else if ((scan == *mangled) && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't'))) { /* The ARM says nothing about the mangling of local variables. But cfront mangles local variables by prepending __<nesting_level> to them. As an extension to ARM demangling we handle this case. */ if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2])) { *mangled = scan + 2; consume_count (mangled); string_append (declp, *mangled); *mangled += strlen (*mangled); success = 1; } else { /* A GNU style constructor starts with __[0-9Qt]. But cfront uses names like __Q2_3foo3bar for nested type names. So don't accept this style of constructor for cfront demangling. */ if (!(LUCID_DEMANGLING || ARM_DEMANGLING)) work -> constructor += 1; *mangled = scan + 2; } } else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't')) { /* Mangled name starts with "__". Skip over any leading '_' characters, then find the next "__" that separates the prefix from the signature. */ if (!(ARM_DEMANGLING || LUCID_DEMANGLING) || (arm_special (work, mangled, declp) == 0)) { while (*scan == '_') { scan++; } if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) { /* No separator (I.E. "__not_mangled"), or empty signature (I.E. "__not_mangled_either__") */ success = 0; } else { demangle_function_name (work, mangled, declp, scan); } } } else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't') { /* Cfront-style parameterized type. Handled later as a signature. */ success = 1; /* ARM template? */ demangle_arm_pt (work, mangled, strlen (*mangled), declp); } else if (*(scan + 2) != '\0') { /* Mangled name does not start with "__" but does have one somewhere in there with non empty stuff after it. Looks like a global function name. */ demangle_function_name (work, mangled, declp, scan); } else { /* Doesn't look like a mangled name */ success = 0; } if (!success && (work->constructor == 2 || work->destructor == 2)) { string_append (declp, *mangled); *mangled += strlen (*mangled); success = 1; } return (success);}/*LOCAL FUNCTION gnu_special -- special handling of gnu mangled stringsSYNOPSIS static int gnu_special (struct work_stuff *work, const char **mangled, string *declp);DESCRIPTION Process some special GNU style mangling forms that don't fit the normal pattern. For example: _$_3foo (destructor for class foo) _vt$foo (foo virtual table) _vt$foo$bar (foo::bar virtual table) __vt_foo (foo virtual table, new style with thunks) _3foo$varname (static data member) _Q22rs2tu$vw (static data member) __t6vector1Zii (constructor with template) __thunk_4__$_7ostream (virtual function thunk) */static intgnu_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] == '_') { /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */ (*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))) { /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>" and create the decl. Note that we consume the entire mangled input string, which means that demangle_signature has no work to do. */ if ((*mangled)[2] == 'v') (*mangled) += 5; /* New style, with thunks: "__vt_" */ else (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */ while (**mangled != '\0') { p = strpbrk (*mangled, cplus_markers); switch (**mangled) { case 'Q': success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': success = demangle_template (work, mangled, declp, 0); break; default: if (isdigit(*mangled[0])) { n = consume_count(mangled); } else { n = strcspn (*mangled, cplus_markers); } string_appendn (declp, *mangled, n); (*mangled) += n; } if (success && ((p == NULL) || (p == *mangled))) { if (p != NULL) { string_append (declp, "::"); (*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) { /* static data member, "_3foo$varname" for example */ (*mangled)++; switch (**mangled) { case 'Q': success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': success = demangle_template (work, mangled, declp, 0); break; default: n = consume_count (mangled); string_appendn (declp, *mangled, n); (*mangled) += n; } if (success && (p == *mangled)) { /* Consumed everything up to the cplus_marker, append the variable name. */ (*mangled)++; string_append (declp, "::"); n = strlen (*mangled); string_appendn (declp, *mangled, n); (*mangled) += n; } else { success = 0; } } else if (strncmp (*mangled, "__thunk_", 8) == 0) { int delta = ((*mangled) += 8, consume_count (mangled)); char *method = cplus_demangle (++*mangled, work->options); 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': success = demangle_qualified (work, mangled, declp, 0, 1); break; case 't': success = demangle_template (work, mangled, declp, 0); break; default: success = demangle_fund_type (work, mangled, declp); break; } if (success && **mangled != '\0') success = 0; if (success) string_append (declp, p); } else { success = 0; } return (success);}/*LOCAL FUNCTION arm_special -- special handling of ARM/lucid mangled stringsSYNOPSIS static int arm_special (struct work_stuff *work, const char **mangled, string *declp);DESCRIPTION Process some special ARM style mangling forms that don't fit the normal pattern. For example: __vtbl__3foo (foo virtual table) __vtbl__3foo__3bar (bar::foo virtual table) */static intarm_special (work, mangled, declp) struct work_stuff *work; const char **mangled; string *declp;{ int n; int success = 1; const char *scan;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -