Index: contrib/libcxxrt/libelftc_dem_gnu3.c =================================================================== --- contrib/libcxxrt/libelftc_dem_gnu3.c +++ contrib/libcxxrt/libelftc_dem_gnu3.c @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2007, 2008 Hyogeol Lee + * Copyright (c) 2007 Hyogeol Lee + * Copyright (c) 2015-2017 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,12 +55,17 @@ }; #define BUFFER_GROWFACTOR 1.618 -#define VECTOR_DEF_CAPACITY 8 +#define BUFFER_GROW(x) (((x)+0.5)*BUFFER_GROWFACTOR) + +#define ELFTC_FAILURE 0 #define ELFTC_ISDIGIT(C) (isdigit((C) & 0xFF)) +#define ELFTC_SUCCESS 1 +#define VECTOR_DEF_CAPACITY 8 + enum type_qualifier { TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT, - TYPE_CST, TYPE_VEC + TYPE_CST, TYPE_VEC, TYPE_RREF }; struct vector_type_qualifier { @@ -73,35 +79,57 @@ READ_TYPE, READ_FUNC, READ_PTRMEM }; +struct read_cmd_item { + enum read_cmd cmd; + void *data; +}; + struct vector_read_cmd { size_t size, capacity; - enum read_cmd *r_container; + struct read_cmd_item *r_container; }; +enum push_qualifier { + PUSH_ALL_QUALIFIER, + PUSH_CV_QUALIFIER, + PUSH_NON_CV_QUALIFIER, +}; + struct cpp_demangle_data { struct vector_str output; /* output string vector */ - struct vector_str output_tmp; struct vector_str subst; /* substitution string vector */ struct vector_str tmpl; struct vector_str class_type; + struct vector_str *cur_output; /* ptr to current output vec */ struct vector_read_cmd cmd; - bool paren; /* parenthesis opened */ - bool pfirst; /* first element of parameter */ bool mem_rst; /* restrict member function */ bool mem_vat; /* volatile member function */ bool mem_cst; /* const member function */ + bool mem_ref; /* lvalue-ref member func */ + bool mem_rref; /* rvalue-ref member func */ + bool is_tmpl; /* template args */ + bool is_functype; /* function type */ + bool ref_qualifier; /* ref qualifier */ + enum type_qualifier ref_qualifier_type; /* ref qualifier type */ + enum push_qualifier push_qualifier; /* which qualifiers to push */ int func_type; const char *cur; /* current mangled name ptr */ const char *last_sname; /* last source name */ - int push_head; }; +struct type_delimit { + bool paren; + bool firstp; +}; + #define CPP_DEMANGLE_TRY_LIMIT 128 #define FLOAT_SPRINTF_TRY_LIMIT 5 #define FLOAT_QUADRUPLE_BYTES 16 #define FLOAT_EXTENED_BYTES 10 #define SIMPLE_HASH(x,y) (64 * x + y) +#define DEM_PUSH_STR(d,s) cpp_demangle_push_str((d), (s), strlen((s))) +#define VEC_PUSH_STR(d,s) vector_str_push((d), (s), strlen((s))) static size_t get_strlen_sum(const struct vector_str *v); static bool vector_str_grow(struct vector_str *v); @@ -125,7 +153,7 @@ /** * @brief Deallocate resource in vector_str. */ -static void +void vector_str_dest(struct vector_str *v) { size_t i; @@ -146,7 +174,7 @@ * @param l Length of the string. * @return -1 at failed, 0 at not found, 1 at found. */ -static int +int vector_str_find(const struct vector_str *v, const char *o, size_t l) { size_t i; @@ -169,7 +197,7 @@ * @param l Length of the string. * @return NULL at failed or NUL terminated new allocated string. */ -static char * +char * vector_str_get_flat(const struct vector_str *v, size_t *l) { ssize_t elem_pos, elem_size, rtn_size; @@ -213,7 +241,7 @@ assert(v->capacity > 0); - tmp_cap = v->capacity * BUFFER_GROWFACTOR; + tmp_cap = BUFFER_GROW(v->capacity); assert(tmp_cap > v->capacity); @@ -235,7 +263,7 @@ * @brief Initialize vector_str. * @return false at failed, true at success. */ -static bool +bool vector_str_init(struct vector_str *v) { @@ -259,7 +287,7 @@ * @brief Remove last element in vector_str. * @return false at failed, true at success. */ -static bool +bool vector_str_pop(struct vector_str *v) { @@ -281,7 +309,7 @@ * @brief Push back string to vector. * @return false at failed, true at success. */ -static bool +bool vector_str_push(struct vector_str *v, const char *str, size_t len) { @@ -305,7 +333,7 @@ * @brief Push front org vector to det vector. * @return false at failed, true at success. */ -static bool +bool vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org) { size_t i, j, tmp_cap; @@ -314,7 +342,7 @@ if (dst == NULL || org == NULL) return (false); - tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR; + tmp_cap = BUFFER_GROW(dst->size + org->size); if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL) return (false); @@ -342,12 +370,53 @@ } /** + * @brief Push org vector to the tail of det vector. + * @return false at failed, true at success. + */ +bool +vector_str_push_vector(struct vector_str *dst, struct vector_str *org) +{ + size_t i, j, tmp_cap; + char **tmp_ctn; + + if (dst == NULL || org == NULL) + return (false); + + tmp_cap = BUFFER_GROW(dst->size + org->size); + + if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL) + return (false); + + for (i = 0; i < dst->size; ++i) + tmp_ctn[i] = dst->container[i]; + + for (i = 0; i < org->size; ++i) + if ((tmp_ctn[i + dst->size] = strdup(org->container[i])) == + NULL) { + for (j = 0; j < i + dst->size; ++j) + free(tmp_ctn[j]); + + free(tmp_ctn); + + return (false); + } + + free(dst->container); + + dst->container = tmp_ctn; + dst->capacity = tmp_cap; + dst->size += org->size; + + return (true); +} + +/** * @brief Get new allocated flat string from vector between begin and end. * * If r_len is not NULL, string length will be returned. * @return NULL at failed or NUL terminated new allocated string. */ -static char * +char * vector_str_substr(const struct vector_str *v, size_t begin, size_t end, size_t *r_len) { @@ -387,6 +456,7 @@ char *(*)(const char *, size_t)); static int cpp_demangle_push_str(struct cpp_demangle_data *, const char *, size_t); +static int cpp_demangle_pop_str(struct cpp_demangle_data *); static int cpp_demangle_push_subst(struct cpp_demangle_data *, const char *, size_t); static int cpp_demangle_push_subst_v(struct cpp_demangle_data *, @@ -419,16 +489,18 @@ static int cpp_demangle_read_nv_offset(struct cpp_demangle_data *); static int cpp_demangle_read_offset(struct cpp_demangle_data *); static int cpp_demangle_read_offset_number(struct cpp_demangle_data *); -static int cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *); +static int cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *, + struct vector_type_qualifier *); static int cpp_demangle_read_sname(struct cpp_demangle_data *); static int cpp_demangle_read_subst(struct cpp_demangle_data *); static int cpp_demangle_read_subst_std(struct cpp_demangle_data *); static int cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *, - const char *, size_t); + const char *); static int cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *); static int cpp_demangle_read_tmpl_args(struct cpp_demangle_data *); static int cpp_demangle_read_tmpl_param(struct cpp_demangle_data *); -static int cpp_demangle_read_type(struct cpp_demangle_data *, int); +static int cpp_demangle_read_type(struct cpp_demangle_data *, + struct type_delimit *); static int cpp_demangle_read_type_flat(struct cpp_demangle_data *, char **); static int cpp_demangle_read_uqname(struct cpp_demangle_data *); @@ -440,10 +512,12 @@ static char *decode_fp_to_long_double(const char *, size_t); static int hex_to_dec(char); static void vector_read_cmd_dest(struct vector_read_cmd *); -static int vector_read_cmd_find(struct vector_read_cmd *, enum read_cmd); +static struct read_cmd_item *vector_read_cmd_find(struct vector_read_cmd *, + enum read_cmd); static int vector_read_cmd_init(struct vector_read_cmd *); static int vector_read_cmd_pop(struct vector_read_cmd *); -static int vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd); +static int vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd, + void *); static void vector_type_qualifier_dest(struct vector_type_qualifier *); static int vector_type_qualifier_init(struct vector_type_qualifier *); static int vector_type_qualifier_push(struct vector_type_qualifier *, @@ -460,14 +534,16 @@ __cxa_demangle_gnu3(const char *org) { struct cpp_demangle_data ddata; + struct vector_str ret_type; + struct type_delimit td; ssize_t org_len; unsigned int limit; - char *rtn = NULL; + char *rtn; + bool has_ret, more_type; - if (org == NULL) + if (org == NULL || (org_len = strlen(org)) < 2) return (NULL); - org_len = strlen(org); if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) { if ((rtn = malloc(org_len + 19)) == NULL) return (NULL); @@ -476,52 +552,100 @@ return (rtn); } - // Try demangling as a type for short encodings - if ((org_len < 2) || (org[0] != '_' || org[1] != 'Z' )) { - if (!cpp_demangle_data_init(&ddata, org)) - return (NULL); - if (!cpp_demangle_read_type(&ddata, 0)) - goto clean; - rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL); - goto clean; - } + if (org[0] != '_' || org[1] != 'Z') + return (NULL); - if (!cpp_demangle_data_init(&ddata, org + 2)) return (NULL); rtn = NULL; + has_ret = more_type = false; if (!cpp_demangle_read_encoding(&ddata)) goto clean; + /* + * Pop function name from substitution candidate list. + */ + if (*ddata.cur != 0 && ddata.subst.size >= 1) { + if (!vector_str_pop(&ddata.subst)) + goto clean; + } + + td.paren = false; + td.firstp = true; limit = 0; + + /* + * The first type is a return type if we just demangled template + * args. (the template args is right next to the function name, + * which means it's a template function) + */ + if (ddata.is_tmpl) { + ddata.is_tmpl = false; + if (!vector_str_init(&ret_type)) + goto clean; + ddata.cur_output = &ret_type; + has_ret = true; + } + while (*ddata.cur != '\0') { /* * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4 */ if (*ddata.cur == '@' && *(ddata.cur + 1) == '@') break; - if (!cpp_demangle_read_type(&ddata, 1)) - goto clean; + + if (has_ret) { + /* Read return type */ + if (!cpp_demangle_read_type(&ddata, NULL)) + goto clean; + } else { + /* Read function arg type */ + if (!cpp_demangle_read_type(&ddata, &td)) + goto clean; + } + + if (has_ret) { + /* Push return type to the beginning */ + if (!VEC_PUSH_STR(&ret_type, " ")) + goto clean; + if (!vector_str_push_vector_head(&ddata.output, + &ret_type)) + goto clean; + ddata.cur_output = &ddata.output; + vector_str_dest(&ret_type); + has_ret = false; + more_type = true; + } else if (more_type) + more_type = false; if (limit++ > CPP_DEMANGLE_TRY_LIMIT) goto clean; } + if (more_type) + goto clean; if (ddata.output.size == 0) goto clean; - if (ddata.paren && !vector_str_push(&ddata.output, ")", 1)) + if (td.paren && !VEC_PUSH_STR(&ddata.output, ")")) goto clean; - if (ddata.mem_vat && !vector_str_push(&ddata.output, " volatile", 9)) + if (ddata.mem_vat && !VEC_PUSH_STR(&ddata.output, " volatile")) goto clean; - if (ddata.mem_cst && !vector_str_push(&ddata.output, " const", 6)) + if (ddata.mem_cst && !VEC_PUSH_STR(&ddata.output, " const")) goto clean; - if (ddata.mem_rst && !vector_str_push(&ddata.output, " restrict", 9)) + if (ddata.mem_rst && !VEC_PUSH_STR(&ddata.output, " restrict")) goto clean; + if (ddata.mem_ref && !VEC_PUSH_STR(&ddata.output, " &")) + goto clean; + if (ddata.mem_rref && !VEC_PUSH_STR(&ddata.output, " &&")) + goto clean; rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL); clean: + if (has_ret) + vector_str_dest(&ret_type); + cpp_demangle_data_dest(&ddata); return (rtn); @@ -538,7 +662,6 @@ vector_str_dest(&d->class_type); vector_str_dest(&d->tmpl); vector_str_dest(&d->subst); - vector_str_dest(&d->output_tmp); vector_str_dest(&d->output); } @@ -551,43 +674,42 @@ if (!vector_str_init(&d->output)) return (0); - if (!vector_str_init(&d->output_tmp)) - goto clean1; if (!vector_str_init(&d->subst)) - goto clean2; + goto clean1; if (!vector_str_init(&d->tmpl)) - goto clean3; + goto clean2; if (!vector_str_init(&d->class_type)) - goto clean4; + goto clean3; if (!vector_read_cmd_init(&d->cmd)) - goto clean5; + goto clean4; assert(d->output.container != NULL); - assert(d->output_tmp.container != NULL); assert(d->subst.container != NULL); assert(d->tmpl.container != NULL); assert(d->class_type.container != NULL); - d->paren = false; - d->pfirst = false; d->mem_rst = false; d->mem_vat = false; d->mem_cst = false; + d->mem_ref = false; + d->mem_rref = false; + d->is_tmpl = false; + d->is_functype = false; + d->ref_qualifier = false; + d->push_qualifier = PUSH_ALL_QUALIFIER; d->func_type = 0; d->cur = cur; + d->cur_output = &d->output; d->last_sname = NULL; - d->push_head = 0; return (1); -clean5: - vector_str_dest(&d->class_type); clean4: - vector_str_dest(&d->tmpl); + vector_str_dest(&d->class_type); clean3: - vector_str_dest(&d->subst); + vector_str_dest(&d->tmpl); clean2: - vector_str_dest(&d->output_tmp); + vector_str_dest(&d->subst); clean1: vector_str_dest(&d->output); @@ -632,13 +754,27 @@ if (ddata == NULL || str == NULL || len == 0) return (0); - if (ddata->push_head > 0) - return (vector_str_push(&ddata->output_tmp, str, len)); + /* + * is_tmpl is used to check if the type (function arg) is right next + * to template args, and should always be cleared whenever new string + * pushed. + */ + ddata->is_tmpl = false; - return (vector_str_push(&ddata->output, str, len)); + return (vector_str_push(ddata->cur_output, str, len)); } static int +cpp_demangle_pop_str(struct cpp_demangle_data *ddata) +{ + + if (ddata == NULL) + return (0); + + return (vector_str_pop(ddata->cur_output)); +} + +static int cpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str, size_t len) { @@ -677,9 +813,11 @@ struct vector_type_qualifier *v, const char *type_str) { struct vector_str subst_v; + enum type_qualifier t; size_t idx, e_idx, e_len; - int rtn; char *buf; + int rtn; + bool cv; if (ddata == NULL || v == NULL) return (0); @@ -691,18 +829,22 @@ if (type_str != NULL) { if (!vector_str_init(&subst_v)) return (0); - if (!vector_str_push(&subst_v, type_str, strlen(type_str))) + if (!VEC_PUSH_STR(&subst_v, type_str)) goto clean; } + cv = true; e_idx = 0; while (idx > 0) { switch (v->q_container[idx - 1]) { case TYPE_PTR: - if (!cpp_demangle_push_str(ddata, "*", 1)) + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; + if (!DEM_PUSH_STR(ddata, "*")) goto clean; if (type_str != NULL) { - if (!vector_str_push(&subst_v, "*", 1)) + if (!VEC_PUSH_STR(&subst_v, "*")) goto clean; if (!cpp_demangle_push_subst_v(ddata, &subst_v)) @@ -711,10 +853,13 @@ break; case TYPE_REF: - if (!cpp_demangle_push_str(ddata, "&", 1)) + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; + if (!DEM_PUSH_STR(ddata, "&")) goto clean; if (type_str != NULL) { - if (!vector_str_push(&subst_v, "&", 1)) + if (!VEC_PUSH_STR(&subst_v, "&")) goto clean; if (!cpp_demangle_push_subst_v(ddata, &subst_v)) @@ -722,11 +867,29 @@ } break; + case TYPE_RREF: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; + if (!DEM_PUSH_STR(ddata, "&&")) + goto clean; + if (type_str != NULL) { + if (!VEC_PUSH_STR(&subst_v, "&&")) + goto clean; + if (!cpp_demangle_push_subst_v(ddata, + &subst_v)) + goto clean; + } + break; + case TYPE_CMX: - if (!cpp_demangle_push_str(ddata, " complex", 8)) + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; + if (!DEM_PUSH_STR(ddata, " complex")) goto clean; if (type_str != NULL) { - if (!vector_str_push(&subst_v, " complex", 8)) + if (!VEC_PUSH_STR(&subst_v, " complex")) goto clean; if (!cpp_demangle_push_subst_v(ddata, &subst_v)) @@ -735,11 +898,13 @@ break; case TYPE_IMG: - if (!cpp_demangle_push_str(ddata, " imaginary", 10)) + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; + if (!DEM_PUSH_STR(ddata, " imaginary")) goto clean; if (type_str != NULL) { - if (!vector_str_push(&subst_v, " imaginary", - 10)) + if (!VEC_PUSH_STR(&subst_v, " imaginary")) goto clean; if (!cpp_demangle_push_subst_v(ddata, &subst_v)) @@ -748,6 +913,9 @@ break; case TYPE_EXT: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; if (v->ext_name.size == 0 || e_idx > v->ext_name.size - 1) goto clean; @@ -759,14 +927,13 @@ snprintf(buf, e_len + 2, " %s", v->ext_name.container[e_idx]); - if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) { + if (!DEM_PUSH_STR(ddata, buf)) { free(buf); goto clean; } if (type_str != NULL) { - if (!vector_str_push(&subst_v, buf, - e_len + 1)) { + if (!VEC_PUSH_STR(&subst_v, buf)) { free(buf); goto clean; } @@ -781,11 +948,22 @@ break; case TYPE_RST: - if (!cpp_demangle_push_str(ddata, " restrict", 9)) + if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER && + cv) + break; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv) + break; + if (!DEM_PUSH_STR(ddata, " restrict")) goto clean; if (type_str != NULL) { - if (!vector_str_push(&subst_v, " restrict", 9)) + if (!VEC_PUSH_STR(&subst_v, " restrict")) goto clean; + if (idx - 1 > 0) { + t = v->q_container[idx - 2]; + if (t == TYPE_RST || t == TYPE_VAT || + t == TYPE_CST) + break; + } if (!cpp_demangle_push_subst_v(ddata, &subst_v)) goto clean; @@ -793,11 +971,22 @@ break; case TYPE_VAT: - if (!cpp_demangle_push_str(ddata, " volatile", 9)) + if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER && + cv) + break; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv) + break; + if (!DEM_PUSH_STR(ddata, " volatile")) goto clean; if (type_str != NULL) { - if (!vector_str_push(&subst_v, " volatile", 9)) + if (!VEC_PUSH_STR(&subst_v, " volatile")) goto clean; + if (idx - 1 > 0) { + t = v->q_container[idx - 2]; + if (t == TYPE_RST || t == TYPE_VAT || + t == TYPE_CST) + break; + } if (!cpp_demangle_push_subst_v(ddata, &subst_v)) goto clean; @@ -805,11 +994,22 @@ break; case TYPE_CST: - if (!cpp_demangle_push_str(ddata, " const", 6)) + if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER && + cv) + break; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv) + break; + if (!DEM_PUSH_STR(ddata, " const")) goto clean; if (type_str != NULL) { - if (!vector_str_push(&subst_v, " const", 6)) + if (!VEC_PUSH_STR(&subst_v, " const")) goto clean; + if (idx - 1 > 0) { + t = v->q_container[idx - 2]; + if (t == TYPE_RST || t == TYPE_VAT || + t == TYPE_CST) + break; + } if (!cpp_demangle_push_subst_v(ddata, &subst_v)) goto clean; @@ -817,6 +1017,9 @@ break; case TYPE_VEC: + cv = false; + if (ddata->push_qualifier == PUSH_CV_QUALIFIER) + break; if (v->ext_name.size == 0 || e_idx > v->ext_name.size - 1) goto clean; @@ -827,13 +1030,12 @@ goto clean; snprintf(buf, e_len + 12, " __vector(%s)", v->ext_name.container[e_idx]); - if (!cpp_demangle_push_str(ddata, buf, e_len + 11)) { + if (!DEM_PUSH_STR(ddata, buf)) { free(buf); goto clean; } if (type_str != NULL) { - if (!vector_str_push(&subst_v, buf, - e_len + 11)) { + if (!VEC_PUSH_STR(&subst_v, buf)) { free(buf); goto clean; } @@ -907,10 +1109,10 @@ if (*(++ddata->cur) == '\0') return (0); - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); - if (!cpp_demangle_push_str(ddata, "[]", 2)) + if (!DEM_PUSH_STR(ddata, "[]")) return (0); } else { if (ELFTC_ISDIGIT(*ddata->cur) != 0) { @@ -923,13 +1125,13 @@ assert(num_len > 0); if (*(++ddata->cur) == '\0') return (0); - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); - if (!cpp_demangle_push_str(ddata, "[", 1)) + if (!DEM_PUSH_STR(ddata, "[")) return (0); if (!cpp_demangle_push_str(ddata, num, num_len)) return (0); - if (!cpp_demangle_push_str(ddata, "]", 1)) + if (!DEM_PUSH_STR(ddata, "]")) return (0); } else { p_idx = ddata->output.size; @@ -953,11 +1155,11 @@ free(exp); return (0); } - if (!cpp_demangle_read_type(ddata, 0)) { + if (!cpp_demangle_read_type(ddata, NULL)) { free(exp); return (0); } - if (!cpp_demangle_push_str(ddata, "[", 1)) { + if (!DEM_PUSH_STR(ddata, "[")) { free(exp); return (0); } @@ -965,7 +1167,7 @@ free(exp); return (0); } - if (!cpp_demangle_push_str(ddata, "]", 1)) { + if (!DEM_PUSH_STR(ddata, "]")) { free(exp); return (0); } @@ -1001,10 +1203,10 @@ switch (*(++ddata->cur)) { case '0': ddata->cur += 2; - return (cpp_demangle_push_str(ddata, "false", 5)); + return (DEM_PUSH_STR(ddata, "false")); case '1': ddata->cur += 2; - return (cpp_demangle_push_str(ddata, "true", 4)); + return (DEM_PUSH_STR(ddata, "true")); default: return (0); } @@ -1041,7 +1243,7 @@ case 'x': case 'y': if (*(++ddata->cur) == 'n') { - if (!cpp_demangle_push_str(ddata, "-", 1)) + if (!DEM_PUSH_STR(ddata, "-")) return (0); ++ddata->cur; } @@ -1070,11 +1272,11 @@ switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { case SIMPLE_HASH('s', 't'): ddata->cur += 2; - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('s', 'r'): ddata->cur += 2; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); if (!cpp_demangle_read_uqname(ddata)) return (0); @@ -1351,8 +1553,7 @@ size_t i, p_idx, idx, exp_len; char *exp; - output = ddata->push_head > 0 ? &ddata->output_tmp : - &ddata->output; + output = &ddata->output; p_idx = output->size; @@ -1429,8 +1630,12 @@ cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c, struct vector_type_qualifier *v) { + struct type_delimit td; + struct read_cmd_item *rc; size_t class_type_size, class_type_len, limit; const char *class_type; + int i; + bool paren, non_cv_qualifier; if (ddata == NULL || *ddata->cur != 'F' || v == NULL) return (0); @@ -1441,12 +1646,43 @@ *ext_c = 1; ++ddata->cur; } - if (!cpp_demangle_read_type(ddata, 0)) + + /* Return type */ + if (!cpp_demangle_read_type(ddata, NULL)) return (0); + if (*ddata->cur != 'E') { - if (!cpp_demangle_push_str(ddata, "(", 1)) + if (!DEM_PUSH_STR(ddata, " ")) return (0); - if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM)) { + + non_cv_qualifier = false; + if (v->size > 0) { + for (i = 0; (size_t) i < v->size; i++) { + if (v->q_container[i] != TYPE_RST && + v->q_container[i] != TYPE_VAT && + v->q_container[i] != TYPE_CST) { + non_cv_qualifier = true; + break; + } + } + } + + paren = false; + rc = vector_read_cmd_find(&ddata->cmd, READ_PTRMEM); + if (non_cv_qualifier || rc != NULL) { + if (!DEM_PUSH_STR(ddata, "(")) + return (0); + paren = true; + } + + /* Push non-cv qualifiers. */ + ddata->push_qualifier = PUSH_NON_CV_QUALIFIER; + if (!cpp_demangle_push_type_qualifier(ddata, v, NULL)) + return (0); + + if (rc) { + if (non_cv_qualifier && !DEM_PUSH_STR(ddata, " ")) + return (0); if ((class_type_size = ddata->class_type.size) == 0) return (0); class_type = @@ -1458,42 +1694,69 @@ if (!cpp_demangle_push_str(ddata, class_type, class_type_len)) return (0); - if (!cpp_demangle_push_str(ddata, "::*", 3)) + if (!DEM_PUSH_STR(ddata, "::*")) return (0); + /* Push pointer-to-member qualifiers. */ + ddata->push_qualifier = PUSH_ALL_QUALIFIER; + if (!cpp_demangle_push_type_qualifier(ddata, rc->data, + NULL)) + return (0); ++ddata->func_type; - } else { - if (!cpp_demangle_push_type_qualifier(ddata, v, - (const char *) NULL)) + } + + if (paren) { + if (!DEM_PUSH_STR(ddata, ")")) return (0); - vector_type_qualifier_dest(v); - if (!vector_type_qualifier_init(v)) - return (0); + paren = false; } - if (!cpp_demangle_push_str(ddata, ")(", 2)) - return (0); - + td.paren = false; + td.firstp = true; limit = 0; + ddata->is_functype = true; for (;;) { - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, &td)) return (0); if (*ddata->cur == 'E') break; if (limit++ > CPP_DEMANGLE_TRY_LIMIT) return (0); } - - if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM) == 1) { - if (!cpp_demangle_push_type_qualifier(ddata, v, - (const char *) NULL)) + ddata->is_functype = false; + if (td.paren) { + if (!DEM_PUSH_STR(ddata, ")")) return (0); - vector_type_qualifier_dest(v); - if (!vector_type_qualifier_init(v)) - return (0); + td.paren = false; } - if (!cpp_demangle_push_str(ddata, ")", 1)) + /* Push CV qualifiers. */ + ddata->push_qualifier = PUSH_CV_QUALIFIER; + if (!cpp_demangle_push_type_qualifier(ddata, v, NULL)) return (0); + + ddata->push_qualifier = PUSH_ALL_QUALIFIER; + + /* Release type qualifier vector. */ + vector_type_qualifier_dest(v); + if (!vector_type_qualifier_init(v)) + return (0); + + /* Push ref-qualifiers. */ + if (ddata->ref_qualifier) { + switch (ddata->ref_qualifier_type) { + case TYPE_REF: + if (!DEM_PUSH_STR(ddata, " &")) + return (0); + break; + case TYPE_RREF: + if (!DEM_PUSH_STR(ddata, " &&")) + return (0); + break; + default: + return (0); + } + ddata->ref_qualifier = false; + } } ++ddata->cur; @@ -1515,7 +1778,7 @@ /* special name */ switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { case SIMPLE_HASH('G', 'A'): - if (!cpp_demangle_push_str(ddata, "hidden alias for ", 17)) + if (!DEM_PUSH_STR(ddata, "hidden alias for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') @@ -1523,7 +1786,7 @@ return (cpp_demangle_read_encoding(ddata)); case SIMPLE_HASH('G', 'R'): - if (!cpp_demangle_push_str(ddata, "reference temporary #", 21)) + if (!DEM_PUSH_STR(ddata, "reference temporary #")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') @@ -1533,11 +1796,11 @@ rtn = 0; if (!cpp_demangle_read_number_as_string(ddata, &num_str)) goto clean1; - if (!cpp_demangle_push_str(ddata, num_str, strlen(num_str))) + if (!DEM_PUSH_STR(ddata, num_str)) goto clean2; - if (!cpp_demangle_push_str(ddata, " for ", 5)) + if (!DEM_PUSH_STR(ddata, " for ")) goto clean2; - if (!cpp_demangle_push_str(ddata, name, strlen(name))) + if (!DEM_PUSH_STR(ddata, name)) goto clean2; rtn = 1; clean2: @@ -1552,14 +1815,12 @@ return (0); switch (*ddata->cur) { case 'n': - if (!cpp_demangle_push_str(ddata, - "non-transaction clone for ", 26)) + if (!DEM_PUSH_STR(ddata, "non-transaction clone for ")) return (0); break; case 't': default: - if (!cpp_demangle_push_str(ddata, - "transaction clone for ", 22)) + if (!DEM_PUSH_STR(ddata, "transaction clone for ")) return (0); break; } @@ -1568,15 +1829,15 @@ case SIMPLE_HASH('G', 'V'): /* sentry object for 1 time init */ - if (!cpp_demangle_push_str(ddata, "guard variable for ", 20)) + if (!DEM_PUSH_STR(ddata, "guard variable for ")) return (0); ddata->cur += 2; break; case SIMPLE_HASH('T', 'c'): /* virtual function covariant override thunk */ - if (!cpp_demangle_push_str(ddata, - "virtual function covariant override ", 36)) + if (!DEM_PUSH_STR(ddata, + "virtual function covariant override ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') @@ -1589,8 +1850,7 @@ case SIMPLE_HASH('T', 'C'): /* construction vtable */ - if (!cpp_demangle_push_str(ddata, "construction vtable for ", - 24)) + if (!DEM_PUSH_STR(ddata, "construction vtable for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') @@ -1602,11 +1862,11 @@ goto clean3; if (*ddata->cur++ != '_') goto clean3; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) goto clean3; - if (!cpp_demangle_push_str(ddata, "-in-", 4)) + if (!DEM_PUSH_STR(ddata, "-in-")) goto clean3; - if (!cpp_demangle_push_str(ddata, type, strlen(type))) + if (!DEM_PUSH_STR(ddata, type)) goto clean3; rtn = 1; clean3: @@ -1619,17 +1879,17 @@ case SIMPLE_HASH('T', 'F'): /* typeinfo fn */ - if (!cpp_demangle_push_str(ddata, "typeinfo fn for ", 16)) + if (!DEM_PUSH_STR(ddata, "typeinfo fn for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'h'): /* virtual function non-virtual override thunk */ - if (!cpp_demangle_push_str(ddata, - "virtual function non-virtual override ", 38)) + if (!DEM_PUSH_STR(ddata, + "virtual function non-virtual override ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') @@ -1640,8 +1900,7 @@ case SIMPLE_HASH('T', 'H'): /* TLS init function */ - if (!cpp_demangle_push_str(ddata, "TLS init function for ", - 22)) + if (!DEM_PUSH_STR(ddata, "TLS init function for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') @@ -1650,44 +1909,43 @@ case SIMPLE_HASH('T', 'I'): /* typeinfo structure */ - if (!cpp_demangle_push_str(ddata, "typeinfo for ", 13)) + if (!DEM_PUSH_STR(ddata, "typeinfo for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'J'): /* java class */ - if (!cpp_demangle_push_str(ddata, "java Class for ", 15)) + if (!DEM_PUSH_STR(ddata, "java Class for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'S'): /* RTTI name (NTBS) */ - if (!cpp_demangle_push_str(ddata, "typeinfo name for ", 18)) + if (!DEM_PUSH_STR(ddata, "typeinfo name for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'T'): /* VTT table */ - if (!cpp_demangle_push_str(ddata, "VTT for ", 8)) + if (!DEM_PUSH_STR(ddata, "VTT for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'v'): /* virtual function virtual override thunk */ - if (!cpp_demangle_push_str(ddata, - "virtual function virtual override ", 34)) + if (!DEM_PUSH_STR(ddata, "virtual function virtual override ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') @@ -1698,17 +1956,16 @@ case SIMPLE_HASH('T', 'V'): /* virtual table */ - if (!cpp_demangle_push_str(ddata, "vtable for ", 12)) + if (!DEM_PUSH_STR(ddata, "vtable for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') return (0); - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('T', 'W'): /* TLS wrapper function */ - if (!cpp_demangle_push_str(ddata, "TLS wrapper function for ", - 25)) + if (!DEM_PUSH_STR(ddata, "TLS wrapper function for ")) return (0); ddata->cur += 2; if (*ddata->cur == '\0') @@ -1722,35 +1979,80 @@ static int cpp_demangle_read_local_name(struct cpp_demangle_data *ddata) { + struct vector_str local_name; + struct type_delimit td; size_t limit; + bool more_type; if (ddata == NULL) return (0); if (*(++ddata->cur) == '\0') return (0); - if (!cpp_demangle_read_encoding(ddata)) + + if (!vector_str_init(&local_name)) return (0); + ddata->cur_output = &local_name; + if (!cpp_demangle_read_encoding(ddata)) { + vector_str_dest(&local_name); + return (0); + } + + ddata->cur_output = &ddata->output; + + td.paren = false; + td.firstp = true; + more_type = false; limit = 0; - for (;;) { - if (!cpp_demangle_read_type(ddata, 1)) + + /* + * The first type is a return type if we just demangled template + * args. (the template args is right next to the function name, + * which means it's a template function) + */ + if (ddata->is_tmpl) { + ddata->is_tmpl = false; + + /* Read return type */ + if (!cpp_demangle_read_type(ddata, NULL)) { + vector_str_dest(&local_name); return (0); + } + + more_type = true; + } + + /* Now we can push the name after possible return type is handled. */ + if (!vector_str_push_vector(&ddata->output, &local_name)) { + vector_str_dest(&local_name); + return (0); + } + vector_str_dest(&local_name); + + while (*ddata->cur != '\0') { + if (!cpp_demangle_read_type(ddata, &td)) + return (0); + if (more_type) + more_type = false; if (*ddata->cur == 'E') break; if (limit++ > CPP_DEMANGLE_TRY_LIMIT) return (0); } + if (more_type) + return (0); + if (*(++ddata->cur) == '\0') return (0); - if (ddata->paren == true) { - if (!cpp_demangle_push_str(ddata, ")", 1)) + if (td.paren == true) { + if (!DEM_PUSH_STR(ddata, ")")) return (0); - ddata->paren = false; + td.paren = false; } if (*ddata->cur == 's') ++ddata->cur; else { - if (!cpp_demangle_push_str(ddata, "::", 2)) + if (!DEM_PUSH_STR(ddata, "::")) return (0); if (!cpp_demangle_read_name(ddata)) return (0); @@ -1775,7 +2077,7 @@ if (ddata == NULL || *ddata->cur == '\0') return (0); - output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; + output = ddata->cur_output; subst_str = NULL; @@ -1837,8 +2139,7 @@ size_t i, p_idx, idx, name_len; char *name; - output = ddata->push_head > 0 ? &ddata->output_tmp : - &ddata->output; + output = ddata->cur_output; p_idx = output->size; @@ -1875,8 +2176,7 @@ if (*(++ddata->cur) == '\0') return (0); - while (*ddata->cur == 'r' || *ddata->cur == 'V' || - *ddata->cur == 'K') { + do { switch (*ddata->cur) { case 'r': ddata->mem_rst = true; @@ -1887,11 +2187,19 @@ case 'K': ddata->mem_cst = true; break; + case 'R': + ddata->mem_ref = true; + break; + case 'O': + ddata->mem_rref = true; + break; + default: + goto next; } - ++ddata->cur; - } + } while (*(++ddata->cur)); - output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; +next: + output = ddata->cur_output; if (!vector_str_init(&v)) return (0); @@ -1917,6 +2225,8 @@ goto clean; } + if (p_idx == output->size) + goto next_comp; if ((subst_str = vector_str_substr(output, p_idx, output->size - 1, &subst_str_len)) == NULL) goto clean; @@ -1928,13 +2238,15 @@ if (!cpp_demangle_push_subst_v(ddata, &v)) goto clean; + + next_comp: if (*ddata->cur == 'E') break; - else if (*ddata->cur != 'I' && - *ddata->cur != 'C' && *ddata->cur != 'D') { - if (!cpp_demangle_push_str(ddata, "::", 2)) + else if (*ddata->cur != 'I' && *ddata->cur != 'C' && + *ddata->cur != 'D' && p_idx != output->size) { + if (!DEM_PUSH_STR(ddata, "::")) goto clean; - if (!vector_str_push(&v, "::", 2)) + if (!VEC_PUSH_STR(&v, "::")) goto clean; } if (limit++ > CPP_DEMANGLE_TRY_LIMIT) @@ -2012,7 +2324,7 @@ if (ddata == NULL) return (0); - if (!cpp_demangle_push_str(ddata, "offset : ", 9)) + if (!DEM_PUSH_STR(ddata, "offset : ")) return (0); return (cpp_demangle_read_offset_number(ddata)); @@ -2058,14 +2370,14 @@ while (*ddata->cur != '_') ++ddata->cur; - if (negative && !cpp_demangle_push_str(ddata, "-", 1)) + if (negative && !DEM_PUSH_STR(ddata, "-")) return (0); assert(start != NULL); if (!cpp_demangle_push_str(ddata, start, ddata->cur - start)) return (0); - if (!cpp_demangle_push_str(ddata, " ", 1)) + if (!DEM_PUSH_STR(ddata, " ")) return (0); ++ddata->cur; @@ -2074,7 +2386,8 @@ } static int -cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata) +cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata, + struct vector_type_qualifier *v) { size_t class_type_len, i, idx, p_idx; int p_func_type, rtn; @@ -2084,7 +2397,7 @@ return (0); p_idx = ddata->output.size; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); if ((class_type = vector_str_substr(&ddata->output, p_idx, @@ -2097,22 +2410,22 @@ if (!vector_str_pop(&ddata->output)) goto clean1; - if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM)) + if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM, v)) goto clean1; if (!vector_str_push(&ddata->class_type, class_type, class_type_len)) goto clean2; p_func_type = ddata->func_type; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) goto clean3; if (p_func_type == ddata->func_type) { - if (!cpp_demangle_push_str(ddata, " ", 1)) + if (!DEM_PUSH_STR(ddata, " ")) goto clean3; if (!cpp_demangle_push_str(ddata, class_type, class_type_len)) goto clean3; - if (!cpp_demangle_push_str(ddata, "::*", 3)) + if (!DEM_PUSH_STR(ddata, "::*")) goto clean3; } @@ -2126,6 +2439,10 @@ clean1: free(class_type); + vector_type_qualifier_dest(v); + if (!vector_type_qualifier_init(v)) + return (0); + return (rtn); } @@ -2141,17 +2458,17 @@ return (0); if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0)) - err = cpp_demangle_push_str(ddata, "(anonymous namespace)", 21); + err = DEM_PUSH_STR(ddata, "(anonymous namespace)"); else err = cpp_demangle_push_str(ddata, ddata->cur, len); if (err == 0) return (0); - assert(ddata->output.size > 0); - if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == 0) + assert(ddata->cur_output->size > 0); + if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == NULL) ddata->last_sname = - ddata->output.container[ddata->output.size - 1]; + ddata->cur_output->container[ddata->output.size - 1]; ddata->cur += len; @@ -2170,55 +2487,61 @@ switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { case SIMPLE_HASH('S', 'a'): /* std::allocator */ - if (cpp_demangle_push_str(ddata, "std::allocator", 14) == 0) + if (!DEM_PUSH_STR(ddata, "std::allocator")) return (0); ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::allocator", 14)); + "std::allocator")); return (1); case SIMPLE_HASH('S', 'b'): /* std::basic_string */ - if (!cpp_demangle_push_str(ddata, "std::basic_string", 17)) + if (!DEM_PUSH_STR(ddata, "std::basic_string")) return (0); ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::basic_string", 17)); + "std::basic_string")); return (1); case SIMPLE_HASH('S', 'd'): /* std::basic_iostream > */ - if (!cpp_demangle_push_str(ddata, "std::basic_iostream", 19)) + if (!DEM_PUSH_STR(ddata, "std::basic_iostream >")) return (0); ddata->last_sname = "basic_iostream"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::basic_iostream", 19)); + "std::basic_iostream >")); return (1); case SIMPLE_HASH('S', 'i'): /* std::basic_istream > */ - if (!cpp_demangle_push_str(ddata, "std::basic_istream", 18)) + if (!DEM_PUSH_STR(ddata, "std::basic_istream >")) return (0); ddata->last_sname = "basic_istream"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::basic_istream", 18)); + "std::basic_istream >")); return (1); case SIMPLE_HASH('S', 'o'): /* std::basic_ostream > */ - if (!cpp_demangle_push_str(ddata, "std::basic_ostream", 18)) + if (!DEM_PUSH_STR(ddata, "std::basic_ostream >")) return (0); ddata->last_sname = "basic_ostream"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::basic_ostream", 18)); + "std::basic_ostream >")); return (1); case SIMPLE_HASH('S', 's'): @@ -2228,13 +2551,15 @@ * * a.k.a std::string */ - if (!cpp_demangle_push_str(ddata, "std::string", 11)) + if (!DEM_PUSH_STR(ddata, "std::basic_string, std::allocator >")) return (0); ddata->last_sname = "string"; ddata->cur += 2; if (*ddata->cur == 'I') return (cpp_demangle_read_subst_stdtmpl(ddata, - "std::string", 11)); + "std::basic_string," + " std::allocator >")); return (1); case SIMPLE_HASH('S', 't'): @@ -2245,6 +2570,14 @@ if (*(++ddata->cur) == '\0') return (0); + /* Skip unknown substitution abbreviations. */ + if (!(*ddata->cur >= '0' && *ddata->cur <= '9') && + !(*ddata->cur >= 'A' && *ddata->cur <= 'Z') && + *ddata->cur != '_') { + ++ddata->cur; + return (1); + } + /* substitution */ if (*ddata->cur == '_') return (cpp_demangle_get_subst(ddata, 0)); @@ -2286,15 +2619,15 @@ subst_str = NULL; rtn = 0; - if (!cpp_demangle_push_str(ddata, "std::", 5)) + if (!DEM_PUSH_STR(ddata, "std::")) goto clean; - if (!vector_str_push(&v, "std::", 5)) + if (!VEC_PUSH_STR(&v, "std::")) goto clean; ddata->cur += 2; - output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; + output = ddata->cur_output; p_idx = output->size; if (!cpp_demangle_read_uqname(ddata)) @@ -2334,18 +2667,21 @@ static int cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata, - const char *str, size_t len) + const char *str) { struct vector_str *output; - size_t p_idx, substr_len; + size_t p_idx, substr_len, len; int rtn; char *subst_str, *substr; - if (ddata == NULL || str == NULL || len == 0) + if (ddata == NULL || str == NULL) return (0); - output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; + if ((len = strlen(str)) == 0) + return (0); + output = ddata->cur_output; + p_idx = output->size; substr = NULL; subst_str = NULL; @@ -2387,10 +2723,13 @@ case 'L': return (cpp_demangle_read_expr_primary(ddata)); case 'X': - return (cpp_demangle_read_expression(ddata)); + ++ddata->cur; + if (!cpp_demangle_read_expression(ddata)) + return (0); + return (*ddata->cur++ == 'E'); } - return (cpp_demangle_read_type(ddata, 0)); + return (cpp_demangle_read_type(ddata, NULL)); } static int @@ -2405,14 +2744,14 @@ ++ddata->cur; - if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL)) + if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL, NULL)) return (0); - if (!cpp_demangle_push_str(ddata, "<", 1)) + if (!DEM_PUSH_STR(ddata, "<")) return (0); limit = 0; - v = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output; + v = ddata->cur_output; for (;;) { idx = v->size; if (!cpp_demangle_read_tmpl_arg(ddata)) @@ -2433,13 +2772,14 @@ size = v->size; assert(size > 0); if (!strncmp(v->container[size - 1], ">", 1)) { - if (!cpp_demangle_push_str(ddata, " >", 2)) + if (!DEM_PUSH_STR(ddata, " >")) return (0); - } else if (!cpp_demangle_push_str(ddata, ">", 1)) + } else if (!DEM_PUSH_STR(ddata, ">")) return (0); + ddata->is_tmpl = true; break; } else if (*ddata->cur != 'I' && - !cpp_demangle_push_str(ddata, ", ", 2)) + !DEM_PUSH_STR(ddata, ", ")) return (0); if (limit++ > CPP_DEMANGLE_TRY_LIMIT) @@ -2488,46 +2828,42 @@ } static int -cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit) +cpp_demangle_read_type(struct cpp_demangle_data *ddata, + struct type_delimit *td) { struct vector_type_qualifier v; - struct vector_str *output; - size_t p_idx, type_str_len; + struct vector_str *output, sv; + size_t p_idx, type_str_len, subst_str_len; int extern_c, is_builtin; long len; - char *type_str, *exp_str, *num_str; + const char *p; + char *type_str, *exp_str, *num_str, *subst_str; + bool skip_ref_qualifier, omit_void; if (ddata == NULL) return (0); - output = &ddata->output; - if (ddata->output.size > 0 && !strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) { - ddata->push_head++; - output = &ddata->output_tmp; - } else if (delimit == 1) { - if (ddata->paren == false) { - if (!cpp_demangle_push_str(ddata, "(", 1)) + output = ddata->cur_output; + if (td) { + if (td->paren == false) { + if (!DEM_PUSH_STR(ddata, "(")) return (0); if (ddata->output.size < 2) return (0); - ddata->paren = true; - ddata->pfirst = true; - /* Need pop function name */ - if (ddata->subst.size == 1 && - !vector_str_pop(&ddata->subst)) - return (0); + td->paren = true; } - if (ddata->pfirst) - ddata->pfirst = false; - else if (*ddata->cur != 'I' && - !cpp_demangle_push_str(ddata, ", ", 2)) - return (0); + if (!td->firstp) { + if (*ddata->cur != 'I') { + if (!DEM_PUSH_STR(ddata, ", ")) + return (0); + } + } } assert(output != NULL); /* - * [r, V, K] [P, R, C, G, U] builtin, function, class-enum, array + * [r, V, K] [P, R, O, C, G, U] builtin, function, class-enum, array * pointer-to-member, template-param, template-template-param, subst */ @@ -2538,12 +2874,19 @@ is_builtin = 1; p_idx = output->size; type_str = exp_str = num_str = NULL; + skip_ref_qualifier = false; + again: + + /* Clear ref-qualifier flag */ + if (*ddata->cur != 'R' && *ddata->cur != 'O' && *ddata->cur != 'E') + ddata->ref_qualifier = false; + /* builtin type */ switch (*ddata->cur) { case 'a': /* signed char */ - if (!cpp_demangle_push_str(ddata, "signed char", 11)) + if (!DEM_PUSH_STR(ddata, "signed char")) goto clean; ++ddata->cur; goto rtn; @@ -2557,7 +2900,7 @@ case 'b': /* bool */ - if (!cpp_demangle_push_str(ddata, "bool", 4)) + if (!DEM_PUSH_STR(ddata, "bool")) goto clean; ++ddata->cur; goto rtn; @@ -2567,18 +2910,20 @@ if (!vector_type_qualifier_push(&v, TYPE_CMX)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'c': /* char */ - if (!cpp_demangle_push_str(ddata, "char", 4)) + if (!DEM_PUSH_STR(ddata, "char")) goto clean; ++ddata->cur; goto rtn; case 'd': /* double */ - if (!cpp_demangle_push_str(ddata, "double", 6)) + if (!DEM_PUSH_STR(ddata, "double")) goto clean; ++ddata->cur; goto rtn; @@ -2586,46 +2931,57 @@ case 'D': ++ddata->cur; switch (*ddata->cur) { + case 'a': + /* auto */ + if (!DEM_PUSH_STR(ddata, "auto")) + goto clean; + ++ddata->cur; + break; + case 'c': + /* decltype(auto) */ + if (!DEM_PUSH_STR(ddata, "decltype(auto)")) + goto clean; + ++ddata->cur; + break; case 'd': /* IEEE 754r decimal floating point (64 bits) */ - if (!cpp_demangle_push_str(ddata, "decimal64", 9)) + if (!DEM_PUSH_STR(ddata, "decimal64")) goto clean; ++ddata->cur; break; case 'e': /* IEEE 754r decimal floating point (128 bits) */ - if (!cpp_demangle_push_str(ddata, "decimal128", 10)) + if (!DEM_PUSH_STR(ddata, "decimal128")) goto clean; ++ddata->cur; break; case 'f': /* IEEE 754r decimal floating point (32 bits) */ - if (!cpp_demangle_push_str(ddata, "decimal32", 9)) + if (!DEM_PUSH_STR(ddata, "decimal32")) goto clean; ++ddata->cur; break; case 'h': /* IEEE 754r half-precision floating point (16 bits) */ - if (!cpp_demangle_push_str(ddata, "half", 4)) + if (!DEM_PUSH_STR(ddata, "half")) goto clean; ++ddata->cur; break; case 'i': /* char32_t */ - if (!cpp_demangle_push_str(ddata, "char32_t", 8)) + if (!DEM_PUSH_STR(ddata, "char32_t")) goto clean; ++ddata->cur; break; case 'n': /* std::nullptr_t (i.e., decltype(nullptr)) */ - if (!cpp_demangle_push_str(ddata, "decltype(nullptr)", - 17)) + if (!DEM_PUSH_STR(ddata, "decltype(nullptr)")) goto clean; ++ddata->cur; break; case 's': /* char16_t */ - if (!cpp_demangle_push_str(ddata, "char16_t", 8)) + if (!DEM_PUSH_STR(ddata, "char16_t")) goto clean; ++ddata->cur; break; @@ -2637,15 +2993,13 @@ if (!cpp_demangle_read_expression_flat(ddata, &exp_str)) goto clean; - if (!vector_str_push(&v.ext_name, exp_str, - strlen(exp_str))) + if (!VEC_PUSH_STR(&v.ext_name, exp_str)) goto clean; } else { if (!cpp_demangle_read_number_as_string(ddata, &num_str)) goto clean; - if (!vector_str_push(&v.ext_name, num_str, - strlen(num_str))) + if (!VEC_PUSH_STR(&v.ext_name, num_str)) goto clean; } if (*ddata->cur != '_') @@ -2653,6 +3007,8 @@ ++ddata->cur; if (!vector_type_qualifier_push(&v, TYPE_VEC)) goto clean; + if (td) + td->firstp = false; goto again; default: goto clean; @@ -2661,14 +3017,24 @@ case 'e': /* long double */ - if (!cpp_demangle_push_str(ddata, "long double", 11)) + if (!DEM_PUSH_STR(ddata, "long double")) goto clean; ++ddata->cur; goto rtn; + case 'E': + /* unexpected end except ref-qualifiers */ + if (ddata->ref_qualifier && ddata->is_functype) { + skip_ref_qualifier = true; + /* Pop the delimiter. */ + cpp_demangle_pop_str(ddata); + goto rtn; + } + goto clean; + case 'f': /* float */ - if (!cpp_demangle_push_str(ddata, "float", 5)) + if (!DEM_PUSH_STR(ddata, "float")) goto clean; ++ddata->cur; goto rtn; @@ -2682,7 +3048,7 @@ case 'g': /* __float128 */ - if (!cpp_demangle_push_str(ddata, "__float128", 10)) + if (!DEM_PUSH_STR(ddata, "__float128")) goto clean; ++ddata->cur; goto rtn; @@ -2692,25 +3058,53 @@ if (!vector_type_qualifier_push(&v, TYPE_IMG)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'h': /* unsigned char */ - if (!cpp_demangle_push_str(ddata, "unsigned char", 13)) + if (!DEM_PUSH_STR(ddata, "unsigned char")) goto clean; ++ddata->cur; goto rtn; case 'i': /* int */ - if (!cpp_demangle_push_str(ddata, "int", 3)) + if (!DEM_PUSH_STR(ddata, "int")) goto clean; ++ddata->cur; goto rtn; + case 'I': + /* template args. */ + /* handles */ + p_idx = output->size; + if (!cpp_demangle_read_tmpl_args(ddata)) + goto clean; + if ((subst_str = vector_str_substr(output, p_idx, + output->size - 1, &subst_str_len)) == NULL) + goto clean; + if (!vector_str_init(&sv)) { + free(subst_str); + goto clean; + } + if (!vector_str_push(&sv, subst_str, subst_str_len)) { + free(subst_str); + vector_str_dest(&sv); + goto clean; + } + free(subst_str); + if (!cpp_demangle_push_subst_v(ddata, &sv)) { + vector_str_dest(&sv); + goto clean; + } + vector_str_dest(&sv); + goto rtn; + case 'j': /* unsigned int */ - if (!cpp_demangle_push_str(ddata, "unsigned int", 12)) + if (!DEM_PUSH_STR(ddata, "unsigned int")) goto clean; ++ddata->cur; goto rtn; @@ -2720,18 +3114,20 @@ if (!vector_type_qualifier_push(&v, TYPE_CST)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'l': /* long */ - if (!cpp_demangle_push_str(ddata, "long", 4)) + if (!DEM_PUSH_STR(ddata, "long")) goto clean; ++ddata->cur; goto rtn; case 'm': /* unsigned long */ - if (!cpp_demangle_push_str(ddata, "unsigned long", 13)) + if (!DEM_PUSH_STR(ddata, "unsigned long")) goto clean; ++ddata->cur; @@ -2739,30 +3135,45 @@ goto rtn; case 'M': /* pointer to member */ - if (!cpp_demangle_read_pointer_to_member(ddata)) + if (!cpp_demangle_read_pointer_to_member(ddata, &v)) goto clean; is_builtin = 0; goto rtn; case 'n': /* __int128 */ - if (!cpp_demangle_push_str(ddata, "__int128", 8)) + if (!DEM_PUSH_STR(ddata, "__int128")) goto clean; ++ddata->cur; goto rtn; case 'o': /* unsigned __int128 */ - if (!cpp_demangle_push_str(ddata, "unsigned __int128", 17)) + if (!DEM_PUSH_STR(ddata, "unsigned __int128")) goto clean; ++ddata->cur; goto rtn; + case 'O': + /* rvalue reference */ + if (ddata->ref_qualifier) + goto clean; + if (!vector_type_qualifier_push(&v, TYPE_RREF)) + goto clean; + ddata->ref_qualifier = true; + ddata->ref_qualifier_type = TYPE_RREF; + ++ddata->cur; + if (td) + td->firstp = false; + goto again; + case 'P': /* pointer */ if (!vector_type_qualifier_push(&v, TYPE_PTR)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'r': @@ -2770,18 +3181,26 @@ if (!vector_type_qualifier_push(&v, TYPE_RST)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'R': /* reference */ + if (ddata->ref_qualifier) + goto clean; if (!vector_type_qualifier_push(&v, TYPE_REF)) goto clean; + ddata->ref_qualifier = true; + ddata->ref_qualifier_type = TYPE_REF; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 's': /* short, local string */ - if (!cpp_demangle_push_str(ddata, "short", 5)) + if (!DEM_PUSH_STR(ddata, "short")) goto clean; ++ddata->cur; goto rtn; @@ -2795,7 +3214,7 @@ case 't': /* unsigned short */ - if (!cpp_demangle_push_str(ddata, "unsigned short", 14)) + if (!DEM_PUSH_STR(ddata, "unsigned short")) goto clean; ++ddata->cur; goto rtn; @@ -2817,20 +3236,39 @@ case 'U': /* vendor extended type qualifier */ + ++ddata->cur; if (!cpp_demangle_read_number(ddata, &len)) goto clean; if (len <= 0) goto clean; if (!vector_str_push(&v.ext_name, ddata->cur, len)) - return (0); + goto clean; ddata->cur += len; if (!vector_type_qualifier_push(&v, TYPE_EXT)) goto clean; + if (td) + td->firstp = false; goto again; case 'v': /* void */ - if (!cpp_demangle_push_str(ddata, "void", 4)) + omit_void = false; + if (td && td->firstp) { + /* + * peek into next bytes and see if we should omit + * the "void". + */ + omit_void = true; + for (p = ddata->cur + 1; *p != '\0'; p++) { + if (*p == 'E') + break; + if (*p != 'R' && *p != 'O') { + omit_void = false; + break; + } + } + } + if (!omit_void && !DEM_PUSH_STR(ddata, "void")) goto clean; ++ddata->cur; goto rtn; @@ -2840,32 +3278,34 @@ if (!vector_type_qualifier_push(&v, TYPE_VAT)) goto clean; ++ddata->cur; + if (td) + td->firstp = false; goto again; case 'w': /* wchar_t */ - if (!cpp_demangle_push_str(ddata, "wchar_t", 7)) + if (!DEM_PUSH_STR(ddata, "wchar_t")) goto clean; ++ddata->cur; goto rtn; case 'x': /* long long */ - if (!cpp_demangle_push_str(ddata, "long long", 9)) + if (!DEM_PUSH_STR(ddata, "long long")) goto clean; ++ddata->cur; goto rtn; case 'y': /* unsigned long long */ - if (!cpp_demangle_push_str(ddata, "unsigned long long", 18)) + if (!DEM_PUSH_STR(ddata, "unsigned long long")) goto clean; ++ddata->cur; goto rtn; case 'z': /* ellipsis */ - if (!cpp_demangle_push_str(ddata, "...", 3)) + if (!DEM_PUSH_STR(ddata, "...")) goto clean; ++ddata->cur; goto rtn; @@ -2876,50 +3316,28 @@ is_builtin = 0; rtn: - if ((type_str = vector_str_substr(output, p_idx, output->size - 1, - &type_str_len)) == NULL) - goto clean; + type_str = vector_str_substr(output, p_idx, output->size - 1, + &type_str_len); + if (is_builtin == 0) { if (!vector_str_find(&ddata->subst, type_str, type_str_len) && !vector_str_push(&ddata->subst, type_str, type_str_len)) goto clean; } - if (!cpp_demangle_push_type_qualifier(ddata, &v, type_str)) + if (!skip_ref_qualifier && + !cpp_demangle_push_type_qualifier(ddata, &v, type_str)) goto clean; + if (td) + td->firstp = false; + free(type_str); free(exp_str); free(num_str); vector_type_qualifier_dest(&v); - if (ddata->push_head > 0) { - if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata) - == 0) - return (0); - - if (--ddata->push_head > 0) - return (1); - - if (!vector_str_push(&ddata->output_tmp, " ", 1)) - return (0); - - if (!vector_str_push_vector_head(&ddata->output, - &ddata->output_tmp)) - return (0); - - vector_str_dest(&ddata->output_tmp); - if (!vector_str_init(&ddata->output_tmp)) - return (0); - - if (!cpp_demangle_push_str(ddata, "(", 1)) - return (0); - - ddata->paren = true; - ddata->pfirst = true; - } - return (1); clean: free(type_str); @@ -2937,12 +3355,11 @@ size_t i, p_idx, idx, type_len; char *type; - output = ddata->push_head > 0 ? &ddata->output_tmp : - &ddata->output; + output = ddata->cur_output; p_idx = output->size; - if (!cpp_demangle_read_type(ddata, 0)) + if (!cpp_demangle_read_type(ddata, NULL)) return (0); if ((type = vector_str_substr(output, p_idx, output->size - 1, @@ -2978,358 +3395,357 @@ switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { case SIMPLE_HASH('a', 'a'): /* operator && */ - if (!cpp_demangle_push_str(ddata, "operator&&", 10)) + if (!DEM_PUSH_STR(ddata, "operator&&")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('a', 'd'): /* operator & (unary) */ - if (!cpp_demangle_push_str(ddata, "operator&", 9)) + if (!DEM_PUSH_STR(ddata, "operator&")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('a', 'n'): /* operator & */ - if (!cpp_demangle_push_str(ddata, "operator&", 9)) + if (!DEM_PUSH_STR(ddata, "operator&")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('a', 'N'): /* operator &= */ - if (!cpp_demangle_push_str(ddata, "operator&=", 10)) + if (!DEM_PUSH_STR(ddata, "operator&=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('a', 'S'): /* operator = */ - if (!cpp_demangle_push_str(ddata, "operator=", 9)) + if (!DEM_PUSH_STR(ddata, "operator=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('c', 'l'): /* operator () */ - if (!cpp_demangle_push_str(ddata, "operator()", 10)) + if (!DEM_PUSH_STR(ddata, "operator()")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('c', 'm'): /* operator , */ - if (!cpp_demangle_push_str(ddata, "operator,", 9)) + if (!DEM_PUSH_STR(ddata, "operator,")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('c', 'o'): /* operator ~ */ - if (!cpp_demangle_push_str(ddata, "operator~", 9)) + if (!DEM_PUSH_STR(ddata, "operator~")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('c', 'v'): /* operator (cast) */ - if (!cpp_demangle_push_str(ddata, "operator(cast)", 14)) + if (!DEM_PUSH_STR(ddata, "operator(cast)")) return (0); ddata->cur += 2; - return (cpp_demangle_read_type(ddata, 1)); + return (cpp_demangle_read_type(ddata, NULL)); case SIMPLE_HASH('d', 'a'): /* operator delete [] */ - if (!cpp_demangle_push_str(ddata, "operator delete []", 18)) + if (!DEM_PUSH_STR(ddata, "operator delete []")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('d', 'e'): /* operator * (unary) */ - if (!cpp_demangle_push_str(ddata, "operator*", 9)) + if (!DEM_PUSH_STR(ddata, "operator*")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('d', 'l'): /* operator delete */ - if (!cpp_demangle_push_str(ddata, "operator delete", 15)) + if (!DEM_PUSH_STR(ddata, "operator delete")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('d', 'v'): /* operator / */ - if (!cpp_demangle_push_str(ddata, "operator/", 9)) + if (!DEM_PUSH_STR(ddata, "operator/")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('d', 'V'): /* operator /= */ - if (!cpp_demangle_push_str(ddata, "operator/=", 10)) + if (!DEM_PUSH_STR(ddata, "operator/=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('e', 'o'): /* operator ^ */ - if (!cpp_demangle_push_str(ddata, "operator^", 9)) + if (!DEM_PUSH_STR(ddata, "operator^")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('e', 'O'): /* operator ^= */ - if (!cpp_demangle_push_str(ddata, "operator^=", 10)) + if (!DEM_PUSH_STR(ddata, "operator^=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('e', 'q'): /* operator == */ - if (!cpp_demangle_push_str(ddata, "operator==", 10)) + if (!DEM_PUSH_STR(ddata, "operator==")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('g', 'e'): /* operator >= */ - if (!cpp_demangle_push_str(ddata, "operator>=", 10)) + if (!DEM_PUSH_STR(ddata, "operator>=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('g', 't'): /* operator > */ - if (!cpp_demangle_push_str(ddata, "operator>", 9)) + if (!DEM_PUSH_STR(ddata, "operator>")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('i', 'x'): /* operator [] */ - if (!cpp_demangle_push_str(ddata, "operator[]", 10)) + if (!DEM_PUSH_STR(ddata, "operator[]")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('l', 'e'): /* operator <= */ - if (!cpp_demangle_push_str(ddata, "operator<=", 10)) + if (!DEM_PUSH_STR(ddata, "operator<=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('l', 's'): /* operator << */ - if (!cpp_demangle_push_str(ddata, "operator<<", 10)) + if (!DEM_PUSH_STR(ddata, "operator<<")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('l', 'S'): /* operator <<= */ - if (!cpp_demangle_push_str(ddata, "operator<<=", 11)) + if (!DEM_PUSH_STR(ddata, "operator<<=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('l', 't'): /* operator < */ - if (!cpp_demangle_push_str(ddata, "operator<", 9)) + if (!DEM_PUSH_STR(ddata, "operator<")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('m', 'i'): /* operator - */ - if (!cpp_demangle_push_str(ddata, "operator-", 9)) + if (!DEM_PUSH_STR(ddata, "operator-")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('m', 'I'): /* operator -= */ - if (!cpp_demangle_push_str(ddata, "operator-=", 10)) + if (!DEM_PUSH_STR(ddata, "operator-=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('m', 'l'): /* operator * */ - if (!cpp_demangle_push_str(ddata, "operator*", 9)) + if (!DEM_PUSH_STR(ddata, "operator*")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('m', 'L'): /* operator *= */ - if (!cpp_demangle_push_str(ddata, "operator*=", 10)) + if (!DEM_PUSH_STR(ddata, "operator*=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('m', 'm'): /* operator -- */ - if (!cpp_demangle_push_str(ddata, "operator--", 10)) + if (!DEM_PUSH_STR(ddata, "operator--")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('n', 'a'): /* operator new[] */ - if (!cpp_demangle_push_str(ddata, "operator new []", 15)) + if (!DEM_PUSH_STR(ddata, "operator new []")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('n', 'e'): /* operator != */ - if (!cpp_demangle_push_str(ddata, "operator!=", 10)) + if (!DEM_PUSH_STR(ddata, "operator!=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('n', 'g'): /* operator - (unary) */ - if (!cpp_demangle_push_str(ddata, "operator-", 9)) + if (!DEM_PUSH_STR(ddata, "operator-")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('n', 't'): /* operator ! */ - if (!cpp_demangle_push_str(ddata, "operator!", 9)) + if (!DEM_PUSH_STR(ddata, "operator!")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('n', 'w'): /* operator new */ - if (!cpp_demangle_push_str(ddata, "operator new", 12)) + if (!DEM_PUSH_STR(ddata, "operator new")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('o', 'o'): /* operator || */ - if (!cpp_demangle_push_str(ddata, "operator||", 10)) + if (!DEM_PUSH_STR(ddata, "operator||")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('o', 'r'): /* operator | */ - if (!cpp_demangle_push_str(ddata, "operator|", 9)) + if (!DEM_PUSH_STR(ddata, "operator|")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('o', 'R'): /* operator |= */ - if (!cpp_demangle_push_str(ddata, "operator|=", 10)) + if (!DEM_PUSH_STR(ddata, "operator|=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('p', 'l'): /* operator + */ - if (!cpp_demangle_push_str(ddata, "operator+", 9)) + if (!DEM_PUSH_STR(ddata, "operator+")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('p', 'L'): /* operator += */ - if (!cpp_demangle_push_str(ddata, "operator+=", 10)) + if (!DEM_PUSH_STR(ddata, "operator+=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('p', 'm'): /* operator ->* */ - if (!cpp_demangle_push_str(ddata, "operator->*", 11)) + if (!DEM_PUSH_STR(ddata, "operator->*")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('p', 'p'): /* operator ++ */ - if (!cpp_demangle_push_str(ddata, "operator++", 10)) + if (!DEM_PUSH_STR(ddata, "operator++")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('p', 's'): /* operator + (unary) */ - if (!cpp_demangle_push_str(ddata, "operator+", 9)) + if (!DEM_PUSH_STR(ddata, "operator+")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('p', 't'): /* operator -> */ - if (!cpp_demangle_push_str(ddata, "operator->", 10)) + if (!DEM_PUSH_STR(ddata, "operator->")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('q', 'u'): /* operator ? */ - if (!cpp_demangle_push_str(ddata, "operator?", 9)) + if (!DEM_PUSH_STR(ddata, "operator?")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('r', 'm'): /* operator % */ - if (!cpp_demangle_push_str(ddata, "operator%", 9)) + if (!DEM_PUSH_STR(ddata, "operator%")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('r', 'M'): /* operator %= */ - if (!cpp_demangle_push_str(ddata, "operator%=", 10)) + if (!DEM_PUSH_STR(ddata, "operator%=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('r', 's'): /* operator >> */ - if (!cpp_demangle_push_str(ddata, "operator>>", 10)) + if (!DEM_PUSH_STR(ddata, "operator>>")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('r', 'S'): /* operator >>= */ - if (!cpp_demangle_push_str(ddata, "operator>>=", 11)) + if (!DEM_PUSH_STR(ddata, "operator>>=")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('r', 'z'): /* operator sizeof */ - if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16)) + if (!DEM_PUSH_STR(ddata, "operator sizeof ")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('s', 'r'): /* scope resolution operator */ - if (!cpp_demangle_push_str(ddata, "scope resolution operator ", - 26)) + if (!DEM_PUSH_STR(ddata, "scope resolution operator ")) return (0); ddata->cur += 2; return (1); case SIMPLE_HASH('s', 'v'): /* operator sizeof */ - if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16)) + if (!DEM_PUSH_STR(ddata, "operator sizeof ")) return (0); ddata->cur += 2; return (1); @@ -3337,8 +3753,7 @@ /* vendor extened operator */ if (*ddata->cur == 'v' && ELFTC_ISDIGIT(*(ddata->cur + 1))) { - if (!cpp_demangle_push_str(ddata, "vendor extened operator ", - 24)) + if (!DEM_PUSH_STR(ddata, "vendor extened operator ")) return (0); if (!cpp_demangle_push_str(ddata, ddata->cur + 1, 1)) return (0); @@ -3349,15 +3764,13 @@ /* ctor-dtor-name */ switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) { case SIMPLE_HASH('C', '1'): - /* FALLTHROUGH */ case SIMPLE_HASH('C', '2'): - /* FALLTHROUGH */ case SIMPLE_HASH('C', '3'): if (ddata->last_sname == NULL) return (0); if ((len = strlen(ddata->last_sname)) == 0) return (0); - if (!cpp_demangle_push_str(ddata, "::", 2)) + if (!DEM_PUSH_STR(ddata, "::")) return (0); if (!cpp_demangle_push_str(ddata, ddata->last_sname, len)) return (0); @@ -3365,15 +3778,13 @@ return (1); case SIMPLE_HASH('D', '0'): - /* FALLTHROUGH */ case SIMPLE_HASH('D', '1'): - /* FALLTHROUGH */ case SIMPLE_HASH('D', '2'): if (ddata->last_sname == NULL) return (0); if ((len = strlen(ddata->last_sname)) == 0) return (0); - if (!cpp_demangle_push_str(ddata, "::~", 3)) + if (!DEM_PUSH_STR(ddata, "::~")) return (0); if (!cpp_demangle_push_str(ddata, ddata->last_sname, len)) return (0); @@ -3428,13 +3839,13 @@ if (ddata == NULL) return (0); - if (!cpp_demangle_push_str(ddata, "offset : ", 9)) + if (!DEM_PUSH_STR(ddata, "offset : ")) return (0); if (!cpp_demangle_read_offset_number(ddata)) return (0); - if (!cpp_demangle_push_str(ddata, "virtual offset : ", 17)) + if (!DEM_PUSH_STR(ddata, "virtual offset : ")) return (0); return (!cpp_demangle_read_offset_number(ddata)); @@ -3745,6 +4156,22 @@ } } +/** + * @brief Test input string is mangled by IA-64 C++ ABI style. + * + * Test string heads with "_Z" or "_GLOBAL__I_". + * @return Return 0 at false. + */ +bool +is_cpp_mangled_gnu3(const char *org) +{ + size_t len; + + len = strlen(org); + return ((len > 2 && *org == '_' && *(org + 1) == 'Z') || + (len > 11 && !strncmp(org, "_GLOBAL__I_", 11))); +} + static void vector_read_cmd_dest(struct vector_read_cmd *v) { @@ -3755,20 +4182,19 @@ free(v->r_container); } -/* return -1 at failed, 0 at not found, 1 at found. */ -static int +static struct read_cmd_item * vector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst) { - size_t i; + int i; if (v == NULL || dst == READ_FAIL) - return (-1); + return (NULL); - for (i = 0; i < v->size; ++i) - if (v->r_container[i] == dst) - return (1); + for (i = (int) v->size - 1; i >= 0; i--) + if (v->r_container[i].cmd == dst) + return (&v->r_container[i]); - return (0); + return (NULL); } static int @@ -3781,7 +4207,7 @@ v->size = 0; v->capacity = VECTOR_DEF_CAPACITY; - if ((v->r_container = malloc(sizeof(enum read_cmd) * v->capacity)) + if ((v->r_container = malloc(sizeof(*v->r_container) * v->capacity)) == NULL) return (0); @@ -3796,15 +4222,16 @@ return (0); --v->size; - v->r_container[v->size] = READ_FAIL; + v->r_container[v->size].cmd = READ_FAIL; + v->r_container[v->size].data = NULL; return (1); } static int -vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd) +vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd, void *data) { - enum read_cmd *tmp_r_ctn; + struct read_cmd_item *tmp_r_ctn; size_t tmp_cap; size_t i; @@ -3812,9 +4239,8 @@ return (0); if (v->size == v->capacity) { - tmp_cap = v->capacity * BUFFER_GROWFACTOR; - if ((tmp_r_ctn = malloc(sizeof(enum read_cmd) * tmp_cap)) - == NULL) + tmp_cap = BUFFER_GROW(v->capacity); + if ((tmp_r_ctn = malloc(sizeof(*tmp_r_ctn) * tmp_cap)) == NULL) return (0); for (i = 0; i < v->size; ++i) tmp_r_ctn[i] = v->r_container[i]; @@ -3823,7 +4249,8 @@ v->capacity = tmp_cap; } - v->r_container[v->size] = cmd; + v->r_container[v->size].cmd = cmd; + v->r_container[v->size].data = data; ++v->size; return (1); @@ -3857,7 +4284,7 @@ assert(v->q_container != NULL); - if (vector_str_init(&v->ext_name) == false) { + if (!vector_str_init(&v->ext_name)) { free(v->q_container); return (0); } @@ -3877,7 +4304,7 @@ return (0); if (v->size == v->capacity) { - tmp_cap = v->capacity * BUFFER_GROWFACTOR; + tmp_cap = BUFFER_GROW(v->capacity); if ((tmp_ctn = malloc(sizeof(enum type_qualifier) * tmp_cap)) == NULL) return (0);