📄 edg-decode.c
字号:
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 {#ifndef WRS_ORIG /* WRS LOCAL */ 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; default: bad_mangled_name(dctl); s = ""; } /* switch */ write_id_str(s, dctl); } /* if */ return p;} /* demangle_type_specifier */static char *demangle_function_parameters(char *ptr, a_decode_control_block_ptr dctl)/*Demangle the parameter list beginning at ptr and output the demangled form.Return a pointer to the character position following what was demangled.*/{ char *p = ptr; char *param_pos[10]; unsigned long curr_param_num, param_num, nreps; a_boolean any_params = FALSE; write_id_ch('(', dctl); if (*p == 'v') { /* Void parameter list. */ p++; } else { any_params = TRUE; /* Loop for each parameter. */ curr_param_num = 1; for (;;) { if (dctl->err_in_id) break; /* Avoid infinite loops on errors. */ if (*p == 'T' || *p == 'N') { /* Tn means repeat the type of parameter "n". */ /* Nmn means "m" repetitions of the type of parameter "n". "m" is a one-digit number. */ /* "n" is also treated as a single-digit number; the front end enforces that (in non-cfront object code compatibility mode). cfront does not, which leads to some ambiguities when "n" is followed by a class name. */ if (*p++ == 'N') { /* Get the number of repetitions. */ p = get_single_digit_number(p, &nreps, dctl); } else { nreps = 1; } /* if */ /* Get the parameter number. */ p = get_single_digit_number(p, ¶m_num, dctl); if (param_num < 1 || param_num >= curr_param_num || param_pos[param_num] == NULL) { /* Parameter number out of range. */ bad_mangled_name(dctl); goto end_of_routine; } /* if */ /* Produce "nreps" copies of parameter "param_num". */ for (; nreps > 0; nreps--) { if (dctl->err_in_id) break; /* Avoid infinite loops on errors. */ if (curr_param_num < 10) param_pos[curr_param_num] = NULL; (void)demangle_type(param_pos[param_num], dctl); if (nreps != 1) write_id_str(", ", dctl); curr_param_num++; } /* if */ } else { /* A normal parameter. */ if (curr_param_num < 10) param_pos[curr_param_num] = p; p = demangle_type(p, dctl); curr_param_num++; } /* if */ /* Stop after the last parameter. */ if (*p == '\0' || *p == 'e' || *p == '_') break; write_id_str(", ", dctl); } /* for */ } /* if */ if (*p == 'e') { /* Ellipsis. */ if (any_params) write_id_str(", ", dctl); write_id_str("...", dctl); p++; } /* if */ write_id_ch(')', dctl);end_of_routine: return p;} /* demangle_function_parameters */static char *skip_extern_C_indication(char *ptr)/*ptr points to the character after the "F" of a function type. Skip overand ignore an indication of extern "C" following the "F", if one is present.Return a pointer to the character following the extern "C" indication.There's no syntax for representing the extern "C" in the function type, sojust ignore it.*/{ if (*ptr == 'K') ptr++; return ptr;} /* skip_extern_C_indication */static char *demangle_type_first_part( char *ptr, a_boolean under_lhs_declarator, a_boolean need_trailing_space, a_decode_control_block_ptr dctl)/*Demangle the type at ptr and output the specifier part and the part of thedeclarator that precedes the name. Return a pointer to the characterposition following what was demangled. If under_lhs_declarator is TRUE,this type is directly under a type that uses a left-side declarator,e.g., a pointer type. (That's used to control use of parentheses aroundparts of the declarator.) If need_trailing_space is TRUE, put a spaceat the end of the specifiers part (needed if the declarator part isnot empty, because it contains a name or a derived type).*/{ char *p = ptr, *qualp = p; char kind; /* Remove type qualifiers. */ while (is_immediate_type_qualifier(p)) p++; kind = *p; if (kind == 'P' || kind == 'R') { /* Pointer or reference type, e.g., "Pc" is pointer to char. */ p = demangle_type_first_part(p+1, /*under_lhs_declarator=*/TRUE, /*need_trailing_space=*/TRUE, dctl); /* Output "*" or "&" for pointer or reference. */ if (kind == 'R') { write_id_ch('&', dctl); } else { write_id_ch('*', dctl); } /* if */ /* Output the type qualifiers on the pointer, if any. */ (void)demangle_type_qualifiers(qualp, /*trailing_space=*/TRUE, dctl); } else if (kind == 'M') { /* Pointer-to-member type, e.g., "M1Ai" is pointer to member of A of type int. */ char *classp = p+1; /* Skip over the class name. */ dctl->suppress_id_output++; p = demangle_type_name(classp, dctl); dctl->suppress_id_output--; p = demangle_type_first_part(p, /*under_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -