📄 cplus-dem.c
字号:
CONST char *p; if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) { /* Found a cfront style virtual table, get past ARM_VTABLE_STRING and create the decl. Note that we consume the entire mangled input string, which means that demangle_signature has no work to do. */ (*mangled) += ARM_VTABLE_STRLEN; while (**mangled != '\0') { n = consume_count (mangled); string_prependn (declp, *mangled, n); (*mangled) += n; if ((*mangled)[0] == '_' && (*mangled)[1] == '_') { string_prepend (declp, "::"); (*mangled) += 2; } } string_append (declp, " virtual table"); } else { success = 0; } return (success);}/*LOCAL FUNCTION demangle_qualified -- demangle 'Q' qualified name stringsSYNOPSIS static int demangle_qualified (struct work_stuff *, const char *mangled, string *result, int isfuncname);DESCRIPTION Demangle a qualified name, such as "Q25Outer5Inner" which is the mangled form of "Outer::Inner". The demangled output is appended to the result string. If isfuncname is nonzero, then the qualified name we are building is going to be used as a member function name, so if it is a constructor or destructor function, append an appropriate constructor or destructor name. I.E. for the above example, the result for use as a constructor is "Outer::Inner::Inner" and the result for use as a destructor is "Outer::Inner::~Inner".BUGS Numeric conversion is ASCII dependent (FIXME). */static intdemangle_qualified (work, mangled, result, isfuncname) struct work_stuff *work; CONST char **mangled; string *result; int isfuncname;{ int qualifiers; int namelength; int success = 0; qualifiers = (*mangled)[1] - '0'; if (qualifiers > 0 && qualifiers < 10) { /* Assume success until we discover otherwise. Skip over the 'Q', the qualifier count, and any '_' between the qualifier count and the first name (cfront qualified names). */ success = 1; if ((*mangled)[2] == '_') { (*mangled)++; } (*mangled) += 2; /* Pick off the names and append them to the result string as they are found, separated by '::'. */ while (qualifiers-- > 0) { namelength = consume_count (mangled); if (strlen (*mangled) < namelength) { /* Simple sanity check failed */ success = 0; break; } string_appendn (result, *mangled, namelength); if (qualifiers > 0) { string_appendn (result, "::", 2); } *mangled += namelength; } /* If we are using the result as a function name, we need to append the appropriate '::' separated constructor or destructor name. We do this here because this is the most convenient place, where we already have a pointer to the name and the length of the name. */ if (isfuncname && (work -> constructor || work -> destructor)) { string_appendn (result, "::", 2); if (work -> destructor) { string_append (result, "~"); } string_appendn (result, (*mangled) - namelength, namelength); } } return (success);}/*LOCAL FUNCTION get_count -- convert an ascii count to integer, consuming tokensSYNOPSIS static int get_count (const char **type, int *count)DESCRIPTION Return 0 if no conversion is performed, 1 if a string is converted.*/static intget_count (type, count) CONST char **type; int *count;{ CONST char *p; int n; if (!isdigit (**type)) { return (0); } else { *count = **type - '0'; (*type)++; if (isdigit (**type)) { p = *type; n = *count; do { n *= 10; n += *p - '0'; p++; } 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 (work, mangled, result) struct work_stuff *work; CONST char **mangled; string *result;{ int n; int done; int success; string decl; CONST char *remembered_type; int constp; int volatilep; string_init (&decl); string_init (result); done = 0; success = 1; while (success && !done) { int member; switch (**mangled) { /* A pointer type */ case 'P': (*mangled)++; string_prepend (&decl, "*"); break; /* A reference type */ case 'R': (*mangled)++; string_prepend (&decl, "&"); break; /* A back reference to a previously seen type */ case 'T': (*mangled)++; if (!get_count (mangled, &n) || n >= work -> ntypes) { success = 0; } else { remembered_type = work -> typevec[n]; mangled = &remembered_type; } break; /* A function */ case 'F': (*mangled)++; if (!STRING_EMPTY (&decl) && decl.b[0] == '*') { string_prepend (&decl, "("); string_append (&decl, ")"); } /* After picking off the function args, we expect to either find the function return type (preceded by an '_') or the end of the string. */ if (!demangle_args (work, mangled, &decl) || (**mangled != '_' && **mangled != '\0')) { success = 0; } if (success && (**mangled == '_')) { (*mangled)++; } break; case 'M': case 'O': { constp = 0; volatilep = 0; member = **mangled == 'M'; (*mangled)++; if (!isdigit (**mangled)) { success = 0; break; } n = consume_count (mangled); if (strlen (*mangled) < n) { success = 0; break; } string_append (&decl, ")"); string_prepend (&decl, "::"); string_prependn (&decl, *mangled, n); string_prepend (&decl, "("); *mangled += n; if (member) { if (**mangled == 'C') { (*mangled)++; constp = 1; } if (**mangled == 'V') { (*mangled)++; volatilep = 1; } if (*(*mangled)++ != 'F') { success = 0; break; } } if ((member && !demangle_args (work, mangled, &decl)) || **mangled != '_') { success = 0; break; } (*mangled)++; if (! PRINT_ANSI_QUALIFIERS) { break; } if (constp) { APPEND_BLANK (&decl); string_append (&decl, "const"); } if (volatilep) { APPEND_BLANK (&decl); string_append (&decl, "volatile"); } break; } case 'C': if ((*mangled)[1] == 'P') { (*mangled)++; if (PRINT_ANSI_QUALIFIERS) { if (!STRING_EMPTY (&decl)) { string_prepend (&decl, " "); } string_prepend (&decl, "const"); } break; } /* fall through */ default: done = 1; break; } } switch (**mangled) { /* A qualified name, such as "Outer::Inner". */ case 'Q': success = demangle_qualified (work, mangled, result, 0); break; default: success = demangle_fund_type (work, mangled, result); break; } if (success) { if (!STRING_EMPTY (&decl)) { string_append (result, " "); string_appends (result, &decl); } } else { string_delete (result); } string_delete (&decl); return (success);}/* Given a pointer to a type string that represents a fundamental type argument (int, long, unsigned int, etc) in TYPE, a pointer to the string in which the demangled output is being built in RESULT, and the WORK structure, decode the types and add them to the result. For example: "Ci" => "const int" "Sl" => "signed long" "CUs" => "const unsigned short" */static intdemangle_fund_type (work, mangled, result) struct work_stuff *work; CONST char **mangled; string *result;{ int done = 0; int success = 1; int n; /* First pick off any type qualifiers. There can be more than one. */ while (!done) { switch (**mangled) { case 'C': (*mangled)++; if (PRINT_ANSI_QUALIFIERS) { APPEND_BLANK (result); string_append (result, "const"); } break; case 'U': (*mangled)++; APPEND_BLANK (result); string_append (result, "unsigned"); break; case 'S': /* signed char only */ (*mangled)++; APPEND_BLANK (result); string_append (result, "signed"); break; case 'V': (*mangled)++; if (PRINT_ANSI_QUALIFIERS) { APPEND_BLANK (result); string_append (result, "volatile"); } break; default: done = 1; break; } } /* Now pick off the fundamental type. There can be only one. */ switch (**mangled) { case '\0': case '_': break; case 'v': (*mangled)++; APPEND_BLANK (result); string_append (result, "void"); break; case 'x': (*mangled)++; APPEND_BLANK (result); string_append (result, "long long"); break; case 'l': (*mangled)++; APPEND_BLANK (result); string_append (result, "long"); break; case 'i': (*mangled)++; APPEND_BLANK (result); string_append (result, "int"); break; case 's': (*mangled)++; APPEND_BLANK (result); string_append (result, "short"); break; case 'c': (*mangled)++; APPEND_BLANK (result); string_append (result, "char"); break; case 'w': (*mangled)++; APPEND_BLANK (result); string_append (result, "wchar_t"); break; case 'r': (*mangled)++; APPEND_BLANK (result); string_append (result, "long double"); break; case 'd': (*mangled)++; APPEND_BLANK (result); string_append (result, "double"); break; case 'f': (*mangled)++; APPEND_BLANK (result); string_append (result, "float"); break; case 'G': (*mangled)++; if (!isdigit (**mangled)) { success = 0; break; } /* fall through */ /* An explicit type, such as "6mytype" or "7integer" */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = consume_count (mangled); if (strlen (*mangled) < n) { success = 0; break; } APPEND_BLANK (result); string_appendn (result, *mangled, n); *mangled += n; break; default: success = 0; break; } return (success);}/* `result' will be initialized in do_type; it will be freed on failure */static intdo_arg (work, mangled, result) struct work_stuff *work; CONST char **mangled; string *result;{ CONST char *start = *mangled; if (!do_type (work, mangled, result)) { return (0); } else { remember_type (work, start, *mangled - start); return (1); }}static voidremember_type (work, start, len) struct work_stuff *work; CONST char *start; int len;{ char *tem; if (work -> ntypes >= work -> typevec_size) { if (work -> typevec_size == 0) { work -> typevec_size = 3; work -> typevec = (char **) xmalloc (sizeof (char *) * work -> typevec_size); } else { work -> typevec_size *= 2; work -> typevec = (char **) xrealloc ((char *)work -> typevec, sizeof (char *) * work -> typevec_size); } } tem = xmalloc (len + 1); memcpy (tem, start, len); tem[len] = '\0'; work -> typevec[work -> ntypes++] = tem;}/* Forget the remembered types, but not the type vector itself. */static voidforget_types (work) struct work_stuff *work;{ int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -