📄 cplus-dem.c
字号:
if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) { /* Found a ARM 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. */ scan = *mangled + ARM_VTABLE_STRLEN; while (*scan != '\0') /* first check it can be demangled */ { n = consume_count (&scan); if (n==0) { return (0); /* no good */ } scan += n; if (scan[0] == '_' && scan[1] == '_') { scan += 2; } } (*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, int append);DESCRIPTION Demangle a qualified name, such as "Q25Outer5Inner" which is the mangled form of "Outer::Inner". The demangled output is prepended or appended to the result string according to the state of the append flag. 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, append) struct work_stuff *work; const char **mangled; string *result; int isfuncname; int append;{ int qualifiers; int namelength; int success = 1; const char *p; char num[2]; string temp; string_init (&temp); switch ((*mangled)[1]) { case '_': /* GNU mangled name with more than 9 classes. The count is preceded by an underscore (to distinguish it from the <= 9 case) and followed by an underscore. */ p = *mangled + 2; qualifiers = atoi (p); if (!isdigit (*p) || *p == '0') success = 0; /* Skip the digits. */ while (isdigit (*p)) ++p; if (*p != '_') success = 0; *mangled = p + 1; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* The count is in a single digit. */ num[0] = (*mangled)[1]; num[1] = '\0'; qualifiers = atoi (num); /* If there is an underscore after the digit, skip it. This is said to be for ARM-qualified names, but the ARM makes no mention of such an underscore. Perhaps cfront uses one. */ if ((*mangled)[2] == '_') { (*mangled)++; } (*mangled) += 2; break; case '0': default: success = 0; } if (!success) return success; /* Pick off the names and collect them in the temp buffer in the order in which they are found, separated by '::'. */ while (qualifiers-- > 0) { if (*mangled[0] == '_') *mangled = *mangled + 1; if (*mangled[0] == 't') { success = demangle_template(work, mangled, &temp, 0); if (!success) break; } else { namelength = consume_count (mangled); if (strlen (*mangled) < namelength) { /* Simple sanity check failed */ success = 0; break; } string_appendn (&temp, *mangled, namelength); *mangled += namelength; } if (qualifiers > 0) { string_appendn (&temp, "::", 2); } } /* 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 & 1 || work->destructor & 1)) { string_appendn (&temp, "::", 2); if (work -> destructor & 1) { string_append (&temp, "~"); } string_appendn (&temp, (*mangled) - namelength, namelength); } /* Now either prepend the temp buffer to the result, or append it, depending upon the state of the append flag. */ if (append) { string_appends (result, &temp); } else { if (!STRING_EMPTY (result)) { string_appendn (&temp, "::", 2); } string_prepends (result, &temp); } string_delete (&temp); 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': case 'p': (*mangled)++; string_prepend (&decl, "*"); break; /* A reference type */ case 'R': (*mangled)++; string_prepend (&decl, "&"); break; /* An array */ case 'A': { const char *p = ++(*mangled); string_prepend (&decl, "("); string_append (&decl, ")["); /* Copy anything up until the next underscore (the size of the array). */ while (**mangled && **mangled != '_') ++(*mangled); if (**mangled == '_') { string_appendn (&decl, p, *mangled - p); string_append (&decl, "]"); *mangled += 1; } else success = 0; 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) && **mangled != 't') { success = 0; break; } string_append (&decl, ")"); string_prepend (&decl, "::"); if (isdigit (**mangled)) { n = consume_count (mangled); if (strlen (*mangled) < n) { success = 0; break; } string_prependn (&decl, *mangled, n); *mangled += n; } else { string temp; string_init (&temp); success = demangle_template (work, mangled, &temp, NULL); if (success) { string_prependn (&decl, temp.b, temp.p - temp.b); string_clear (&temp); } else break; } string_prepend (&decl, "("); 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 'G': (*mangled)++; break; case 'C': (*mangled)++; /* if ((*mangled)[1] == 'P') { */ 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, 1); 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; /* 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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -