📄 etoa_decode.c
字号:
/* Get the block number. */ p = get_number(ptr, &block_number, dctl); /* Check for the two underscores following the block number. For local class names in some older versions of the mangling scheme, there is no following function name. */ if (p[0] == '_' && p[1] == '_') { p += 2; /* Put out the function name. */ if (nchars != 0) nchars -= (p - ptr); p = full_demangle_identifier(p, nchars, dctl); /* Put out the block number if needed. Block 0 is the top-level block of the function, and need not be identified. */ if (block_number != 0) { char buffer[30]; write_id_str("[block ", dctl); (void)sprintf(buffer, "%lu", block_number); write_id_str(buffer, dctl); write_id_ch(']', dctl); } /* if */ write_id_str("::", dctl); } /* if */ return p;} /* demangle_function_local_indication */static char *demangle_name_with_preceding_length( char *ptr, a_boolean allow_member, a_template_param_block_ptr temp_par_info, a_decode_control_block_ptr dctl)/*Demangle a name that is preceded by a length, e.g., "3abc" for the typename "abc". Return a pointer to the character position following whatwas demangled. When temp_par_info != NULL, it points to a block thatcontrols output of extra information on template parameters.If allow_member is TRUE, the name may be a member name.*/{ char *p = ptr; char *p2; unsigned long nchars, nchars2; a_boolean has_function_local_info = FALSE; a_boolean is_member = FALSE; /* Get the length. */ p = get_length(p, &nchars, dctl); if (nchars >= 8) { /* Look for a function-local indication, e.g., "__Ln__f" for block "n" of function "f". */ for (p2 = p+1; p2+6 < p+nchars; p2++) { if (p2[0] == '_' && p2[1] == '_' && p2[2] == 'L') { has_function_local_info = TRUE; nchars2 = nchars; /* Set the length for the scan below to stop just before "__L". */ nchars = p2 - p; p2 += 3; /* Points to block number after "__L". */ nchars2 -= (p2 - p); /* Scan over (but do not output) the block number and function name. */ dctl->suppress_id_output++; p2 = demangle_function_local_indication(p2, nchars2, dctl); dctl->suppress_id_output--; break; } /* if */ } /* for */ } /* if */ if (allow_member) { /* This might be a member name. Demangle once to see if we take the whole name. If not, the rest should be two underscores and the parent name. */ unsigned long nchars_left, old_nchars; dctl->suppress_id_output++; p2 = demangle_name(p, nchars, /*stop_on_underscores=*/FALSE, &nchars_left, (char *)NULL, (a_template_param_block_ptr)NULL, dctl); dctl->suppress_id_output--; if (nchars_left != 0) { /* We came up short on the name. Expect two underscores and the parent type. */ if (p2[0] != '_' || p2[1] != '_') { bad_mangled_name(dctl); } else { is_member = TRUE; old_nchars = nchars; nchars = p2 - p; p2 += 2; p2 = demangle_type_name(p2, dctl); write_id_str("::", dctl); /* See if we ended up in the right place. */ if (p2 != p+old_nchars) { bad_mangled_name(dctl); } /* if */ } /* if */ } /* if */ } /* if */ /* Demangle the name. */ p = demangle_name(p, nchars, /*stop_on_underscores=*/FALSE, (unsigned long *)NULL, (char *)NULL, temp_par_info, dctl); if (has_function_local_info || is_member) p = p2; return p;} /* demangle_name_with_preceding_length */static char *demangle_simple_type_name( char *ptr, a_template_param_block_ptr temp_par_info, a_decode_control_block_ptr dctl)/*Demangle a type name (or namespace name) consisting of a length followedby the name. Return a pointer to the character position following whatwas demangled. The name is not a nested name, but it can have templatearguments. When temp_par_info != NULL, it points to a block thatcontrols output of extra information on template parameters.*/{ char *p = ptr; if (*p == 'Z') { /* A template parameter name. */ p = demangle_template_parameter_name(p, /*nontype=*/FALSE, dctl); } else { /* A simple mangled type name consists of digits indicating the length of the name followed by the name itself, e.g., "3abc". */ p = demangle_name_with_preceding_length(p, /*allow_member=*/FALSE, temp_par_info, dctl); } /* if */ return p;} /* demangle_simple_type_name */static char *full_demangle_type_name(char *ptr, a_boolean base_name_only, a_template_param_block_ptr temp_par_info, a_decode_control_block_ptr dctl)/*Demangle the type name at ptr and output the demangled form. Return a pointerto the character position following what was demangled. The name can bea simple type name or a nested type name, or the name of a namespace.If base_name_only is TRUE, do not put out any nested type qualifiers,e.g., put out "A::x" as simply "x". When temp_par_info != NULL, itpoints to a block that controls output of extra information on templateparameters. Note that this routine is called for namespaces too(the mangling is the same as for class names; you can't actually tellthe difference in a mangled name). See demangle_type_name for aninterface to this routine for the simple case.*/{ char *p = ptr; unsigned long nquals; if (*p == 'Q') { /* A nested type name has the form Q2_5outer5inner (outer::inner) ^-----^--------Names from outermost to innermost ^----------------Number of levels of qualification. Note that the levels in the qualifier can be class names or namespace names. */ p = get_number(p+1, &nquals, dctl); p = advance_past_underscore(p, dctl); /* Handle each level of qualification. */ for (; nquals > 0; nquals--) { if (dctl->err_in_id) break; /* Avoid infinite loops on errors. */ /* Do not put out the nested type qualifiers if base_name_only is TRUE. */ if (base_name_only && nquals != 1) dctl->suppress_id_output++; p = demangle_simple_type_name(p, temp_par_info, dctl); if (nquals != 1) write_id_str("::", dctl); if (base_name_only && nquals != 1) dctl->suppress_id_output--; } /* for */ } else {#if ENABLE_GNU_LIKE_OUTPUT a_template_param_block ctdt_temp_par_info; if (base_name_only) { /* Also need to suppress template parameters when printing these! */ temp_par_info = &ctdt_temp_par_info; clear_template_param_block(temp_par_info); temp_par_info->base_name_only = TRUE; } /* N.B. when base_name_only is true, temp_par_info is also NULL. We need it to pass down base_name_only, so we create a blank one at this level. But note, we don't preserve temp_par_info so if you add code that needs the old one, also add code to save/restore it. */#endif /* A simple (non-nested) type name. */ p = demangle_simple_type_name(p, temp_par_info, dctl); } /* if */ return p;} /* full_demangle_type_name */static char *demangle_vtbl_class_name(char *ptr, a_decode_control_block_ptr dctl)/*Demangle a class or base class name that is one component of a virtualfunction table name. Such names are mangled mostly as types, but witha few special quirks.*/{ char *p = ptr; a_boolean nested_name_case = FALSE; /* If the name begins with a number, "Q", and another number, assume it's a name with a form like "7Q2_1A1B", which is used to encode A::B as the complete object class name component of a virtual function table name. This doesn't have any particular sense to it; it's just what cfront does (and EDG's front end does the same at ABI versions >= 2.30 in cfront compatibility mode). This could fail if the user actually has a class with a name that begins like "Q2_", but there's not much we can do about that. */ if (isdigit((unsigned char)*p)) { do { p++; } while (isdigit((unsigned char)*p)); if (*p == 'Q') { char *save_p = p; p++; if (isdigit((unsigned char)*p)) { do { p++; } while (isdigit((unsigned char)*p)); if (*p == '_') { /* Yes, this is the strange nested name case. Start the demangling at the "Q". */ nested_name_case = TRUE; p = save_p; } /* if */ } /* if */ } /* if */ } /* if */ if (!nested_name_case) p = ptr; /* Now use the normal routine to demangle the class name. */ p = demangle_type_name(p, dctl); return p;} /* demangle_vtbl_class_name */static char *demangle_type_qualifiers( char *ptr, a_boolean trailing_space, a_decode_control_block_ptr dctl)/*Demangle any type qualifiers (const/volatile) at the indicated location.Return a pointer to the character position following what was demangled.If trailing_space is TRUE, add a space at the end if any qualifiers wereput out.*/{ char *p = ptr; a_boolean any_quals = FALSE; for (;; p++) { if (*p == 'C') { if (any_quals) write_id_ch(' ', dctl); write_id_str("const", dctl); } else if (*p == 'V') { if (any_quals) write_id_ch(' ', dctl); write_id_str("volatile", dctl); } else { break; } /* if */ any_quals = TRUE; } /* for */ if (any_quals && trailing_space) write_id_ch(' ', dctl); return p;} /* demangle_type_qualifiers */static char *demangle_type_specifier(char *ptr, a_decode_control_block_ptr dctl)/*Demangle the type at ptr and output the specifier part. Return a pointerto the character position following what was demangled.*/{ char *p = ptr, *s; /* Process type qualifiers. */ p = demangle_type_qualifiers(p, /*trailing_space=*/TRUE, dctl); if (isdigit((unsigned char)*p) || *p == 'Q' || *p == 'Z') { /* Named type, like class or enum, e.g., "3abc". */ p = demangle_type_name(p, dctl); } else { /* Builtin type. */ /* Handle signed and unsigned. */ if (*p == 'S') { write_id_str("signed ", dctl); p++; } else if (*p == 'U') { write_id_str("unsigned ", dctl); p++; } /* if */ switch (*p++) { case 'v': s = "void"; break; case 'c': s = "char"; break; case 'w': s = "wchar_t"; break; case 'b': s = "bool"; break; case 's': s = "short"; break; case 'i': s = "int"; break; case 'l': s = "long"; break; case 'L': s = "long long"; break; case 'f': s = "float"; break; case 'd': s = "double"; break; case 'r': s = "long double"; break; case 'm': /* Microsoft intrinsic __intN types (Visual C++ 6.0 and later). */ switch (*p++) { case '1': s = "__int8"; break; case '2': s = "__int16"; break; case '4': s = "__int32"; break; case '8': s = "__int64"; break; default: bad_mangled_name(dctl); s = ""; } /* switch */ break; case 'B': /* Altivec vector */ switch (*p++) { case 'U': switch(*p++) { case 'c': s = "vector unsigned char"; break; case 's': s = "vector unsigned short int"; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -