📄 cp-demangle.c
字号:
case 'A': ret = d_array_type (di); break; case 'M': ret = d_pointer_to_member_type (di); break; case 'T': ret = d_template_param (di); if (d_peek_char (di) == 'I') { /* This is <template-template-param> <template-args>. The <template-template-param> part is a substitution candidate. */ if (! d_add_substitution (di, ret)) return NULL; ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, d_template_args (di)); } break; case 'S': /* If this is a special substitution, then it is the start of <class-enum-type>. */ { char peek_next; peek_next = d_peek_next_char (di); if (IS_DIGIT (peek_next) || peek_next == '_' || IS_UPPER (peek_next)) { ret = d_substitution (di, 0); /* The substituted name may have been a template name and may be followed by tepmlate args. */ if (d_peek_char (di) == 'I') ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, d_template_args (di)); else can_subst = 0; } else { ret = d_class_enum_type (di); /* If the substitution was a complete type, then it is not a new substitution candidate. However, if the substitution was followed by template arguments, then the whole thing is a substitution candidate. */ if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD) can_subst = 0; } } break; case 'O': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_RVALUE_REFERENCE, cplus_demangle_type (di), NULL); break; case 'P': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_POINTER, cplus_demangle_type (di), NULL); break; case 'R': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_REFERENCE, cplus_demangle_type (di), NULL); break; case 'C': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_COMPLEX, cplus_demangle_type (di), NULL); break; case 'G': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_IMAGINARY, cplus_demangle_type (di), NULL); break; case 'U': d_advance (di, 1); ret = d_source_name (di); ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, cplus_demangle_type (di), ret); break; default: return NULL; } if (can_subst) { if (! d_add_substitution (di, ret)) return NULL; } return ret;}/* <CV-qualifiers> ::= [r] [V] [K] */static struct demangle_component **d_cv_qualifiers (struct d_info *di, struct demangle_component **pret, int member_fn){ char peek; peek = d_peek_char (di); while (peek == 'r' || peek == 'V' || peek == 'K') { enum demangle_component_type t; d_advance (di, 1); if (peek == 'r') { t = (member_fn ? DEMANGLE_COMPONENT_RESTRICT_THIS : DEMANGLE_COMPONENT_RESTRICT); di->expansion += sizeof "restrict"; } else if (peek == 'V') { t = (member_fn ? DEMANGLE_COMPONENT_VOLATILE_THIS : DEMANGLE_COMPONENT_VOLATILE); di->expansion += sizeof "volatile"; } else { t = (member_fn ? DEMANGLE_COMPONENT_CONST_THIS : DEMANGLE_COMPONENT_CONST); di->expansion += sizeof "const"; } *pret = d_make_comp (di, t, NULL, NULL); if (*pret == NULL) return NULL; pret = &d_left (*pret); peek = d_peek_char (di); } return pret;}/* <function-type> ::= F [Y] <bare-function-type> E */static struct demangle_component *d_function_type (struct d_info *di){ struct demangle_component *ret; if (! d_check_char (di, 'F')) return NULL; if (d_peek_char (di) == 'Y') { /* Function has C linkage. We don't print this information. FIXME: We should print it in verbose mode. */ d_advance (di, 1); } ret = d_bare_function_type (di, 1); if (! d_check_char (di, 'E')) return NULL; return ret;}/* <bare-function-type> ::= [J]<type>+ */static struct demangle_component *d_bare_function_type (struct d_info *di, int has_return_type){ struct demangle_component *return_type; struct demangle_component *tl; struct demangle_component **ptl; char peek; /* Detect special qualifier indicating that the first argument is the return type. */ peek = d_peek_char (di); if (peek == 'J') { d_advance (di, 1); has_return_type = 1; } return_type = NULL; tl = NULL; ptl = &tl; while (1) { struct demangle_component *type; peek = d_peek_char (di); if (peek == '\0' || peek == 'E') break; type = cplus_demangle_type (di); if (type == NULL) return NULL; if (has_return_type) { return_type = type; has_return_type = 0; } else { *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL); if (*ptl == NULL) return NULL; ptl = &d_right (*ptl); } } /* There should be at least one parameter type besides the optional return type. A function which takes no arguments will have a single parameter type void. */ if (tl == NULL) return NULL; /* If we have a single parameter type void, omit it. */ if (d_right (tl) == NULL && d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID) { di->expansion -= d_left (tl)->u.s_builtin.type->len; tl = NULL; } return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl);}/* <class-enum-type> ::= <name> */static struct demangle_component *d_class_enum_type (struct d_info *di){ return d_name (di);}/* <array-type> ::= A <(positive dimension) number> _ <(element) type> ::= A [<(dimension) expression>] _ <(element) type>*/static struct demangle_component *d_array_type (struct d_info *di){ char peek; struct demangle_component *dim; if (! d_check_char (di, 'A')) return NULL; peek = d_peek_char (di); if (peek == '_') dim = NULL; else if (IS_DIGIT (peek)) { const char *s; s = d_str (di); do { d_advance (di, 1); peek = d_peek_char (di); } while (IS_DIGIT (peek)); dim = d_make_name (di, s, d_str (di) - s); if (dim == NULL) return NULL; } else { dim = d_expression (di); if (dim == NULL) return NULL; } if (! d_check_char (di, '_')) return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim, cplus_demangle_type (di));}/* <pointer-to-member-type> ::= M <(class) type> <(member) type> */static struct demangle_component *d_pointer_to_member_type (struct d_info *di){ struct demangle_component *cl; struct demangle_component *mem; struct demangle_component **pmem; if (! d_check_char (di, 'M')) return NULL; cl = cplus_demangle_type (di); /* The ABI specifies that any type can be a substitution source, and that M is followed by two types, and that when a CV-qualified type is seen both the base type and the CV-qualified types are substitution sources. The ABI also specifies that for a pointer to a CV-qualified member function, the qualifiers are attached to the second type. Given the grammar, a plain reading of the ABI suggests that both the CV-qualified member function and the non-qualified member function are substitution sources. However, g++ does not work that way. g++ treats only the CV-qualified member function as a substitution source. FIXME. So to work with g++, we need to pull off the CV-qualifiers here, in order to avoid calling add_substitution() in cplus_demangle_type(). But for a CV-qualified member which is not a function, g++ does follow the ABI, so we need to handle that case here by calling d_add_substitution ourselves. */ pmem = d_cv_qualifiers (di, &mem, 1); if (pmem == NULL) return NULL; *pmem = cplus_demangle_type (di); if (*pmem == NULL) return NULL; if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) { if (! d_add_substitution (di, mem)) return NULL; } return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);}/* <template-param> ::= T_ ::= T <(parameter-2 non-negative) number> _*/static struct demangle_component *d_template_param (struct d_info *di){ long param; if (! d_check_char (di, 'T')) return NULL; if (d_peek_char (di) == '_') param = 0; else { param = d_number (di); if (param < 0) return NULL; param += 1; } if (! d_check_char (di, '_')) return NULL; ++di->did_subs; return d_make_template_param (di, param);}/* <template-args> ::= I <template-arg>+ E */static struct demangle_component *d_template_args (struct d_info *di){ struct demangle_component *hold_last_name; struct demangle_component *al; struct demangle_component **pal; /* Preserve the last name we saw--don't let the template arguments clobber it, as that would give us the wrong name for a subsequent constructor or destructor. */ hold_last_name = di->last_name; if (! d_check_char (di, 'I')) return NULL; al = NULL; pal = &al; while (1) { struct demangle_component *a; a = d_template_arg (di); if (a == NULL) return NULL; *pal = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, a, NULL); if (*pal == NULL) return NULL; pal = &d_right (*pal); if (d_peek_char (di) == 'E') { d_advance (di, 1); break; } } di->last_name = hold_last_name; return al;}/* <template-arg> ::= <type> ::= X <expression> E ::= <expr-primary>*/static struct demangle_component *d_template_arg (struct d_info *di){ struct demangle_component *ret; switch (d_peek_char (di)) { case 'X': d_advance (di, 1); ret = d_expression (di); if (! d_check_char (di, 'E')) return NULL; return ret; case 'L': return d_expr_primary (di); default: return cplus_demangle_type (di); }}/* <expression> ::= <(unary) operator-name> <expression> ::= <(binary) operator-name> <expression> <expression> ::= <(trinary) operator-name> <expression> <expression> <expression> ::= st <type> ::= <template-param> ::= sr <type> <unqualified-name> ::= sr <type> <unqualified-name> <template-args> ::= <expr-primary>*/static struct demangle_component *d_expression (struct d_info *di){ char peek; peek = d_peek_char (di); if (peek == 'L') return d_expr_primary (di); else if (peek == 'T') return d_template_param (di); else if (peek == 's' && d_peek_next_char (di) == 'r') { struct demangle_component *type; struct demangle_component *name; d_advance (di, 2); type = cplus_demangle_type (di); name = d_unqualified_name (di); if (d_peek_char (di) != 'I') return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name); else return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, d_template_args (di))); } else { struct demangle_component *op; int args; op = d_operator_name (di); if (op == NULL) return NULL; if (op->type == DEMANGLE_COMPONENT_OPERATOR) di->expansion += op->u.s_operator.op->len - 2; if (op->type == DEMANGLE_COMPONENT_OPERATOR && strcmp (op->u.s_operator.op->code, "st") == 0) re
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -