17a984708SDavid Chisnall /*-
2a7941b33SDimitry Andric * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
3a7941b33SDimitry Andric * Copyright (c) 2015-2017 Kai Wang <kaiwang27@gmail.com>
47a984708SDavid Chisnall * All rights reserved.
57a984708SDavid Chisnall *
67a984708SDavid Chisnall * Redistribution and use in source and binary forms, with or without
77a984708SDavid Chisnall * modification, are permitted provided that the following conditions
87a984708SDavid Chisnall * are met:
97a984708SDavid Chisnall * 1. Redistributions of source code must retain the above copyright
107a984708SDavid Chisnall * notice, this list of conditions and the following disclaimer
117a984708SDavid Chisnall * in this position and unchanged.
127a984708SDavid Chisnall * 2. Redistributions in binary form must reproduce the above copyright
137a984708SDavid Chisnall * notice, this list of conditions and the following disclaimer in the
147a984708SDavid Chisnall * documentation and/or other materials provided with the distribution.
157a984708SDavid Chisnall *
167a984708SDavid Chisnall * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
177a984708SDavid Chisnall * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
187a984708SDavid Chisnall * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
197a984708SDavid Chisnall * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
207a984708SDavid Chisnall * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
217a984708SDavid Chisnall * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
227a984708SDavid Chisnall * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
237a984708SDavid Chisnall * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
247a984708SDavid Chisnall * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
257a984708SDavid Chisnall * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
267a984708SDavid Chisnall */
277a984708SDavid Chisnall #include <sys/types.h>
287a984708SDavid Chisnall #include <assert.h>
297a984708SDavid Chisnall #include <ctype.h>
307a984708SDavid Chisnall #include <errno.h>
317a984708SDavid Chisnall #include <limits.h>
327a984708SDavid Chisnall #include <stdbool.h>
337a984708SDavid Chisnall #include <stdio.h>
347a984708SDavid Chisnall #include <stdlib.h>
357a984708SDavid Chisnall #include <string.h>
367a984708SDavid Chisnall
377a984708SDavid Chisnall /**
387a984708SDavid Chisnall * @file cpp_demangle.c
397a984708SDavid Chisnall * @brief Decode IA-64 C++ ABI style implementation.
407a984708SDavid Chisnall *
417a984708SDavid Chisnall * IA-64 standard ABI(Itanium C++ ABI) references.
427a984708SDavid Chisnall *
437a984708SDavid Chisnall * http://www.codesourcery.com/cxx-abi/abi.html#mangling \n
447a984708SDavid Chisnall * http://www.codesourcery.com/cxx-abi/abi-mangling.html
457a984708SDavid Chisnall */
467a984708SDavid Chisnall
477a984708SDavid Chisnall /** @brief Dynamic vector data for string. */
487a984708SDavid Chisnall struct vector_str {
497a984708SDavid Chisnall /** Current size */
507a984708SDavid Chisnall size_t size;
517a984708SDavid Chisnall /** Total capacity */
527a984708SDavid Chisnall size_t capacity;
537a984708SDavid Chisnall /** String array */
547a984708SDavid Chisnall char **container;
557a984708SDavid Chisnall };
567a984708SDavid Chisnall
577a984708SDavid Chisnall #define BUFFER_GROWFACTOR 1.618
58a7941b33SDimitry Andric #define BUFFER_GROW(x) (((x)+0.5)*BUFFER_GROWFACTOR)
59a7941b33SDimitry Andric
60a7941b33SDimitry Andric #define ELFTC_FAILURE 0
617a984708SDavid Chisnall #define ELFTC_ISDIGIT(C) (isdigit((C) & 0xFF))
62a7941b33SDimitry Andric #define ELFTC_SUCCESS 1
63a7941b33SDimitry Andric
64a7941b33SDimitry Andric #define VECTOR_DEF_CAPACITY 8
657a984708SDavid Chisnall
667a984708SDavid Chisnall enum type_qualifier {
677a984708SDavid Chisnall TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
68a7941b33SDimitry Andric TYPE_CST, TYPE_VEC, TYPE_RREF
697a984708SDavid Chisnall };
707a984708SDavid Chisnall
717a984708SDavid Chisnall struct vector_type_qualifier {
727a984708SDavid Chisnall size_t size, capacity;
737a984708SDavid Chisnall enum type_qualifier *q_container;
747a984708SDavid Chisnall struct vector_str ext_name;
757a984708SDavid Chisnall };
767a984708SDavid Chisnall
777a984708SDavid Chisnall enum read_cmd {
787a984708SDavid Chisnall READ_FAIL, READ_NEST, READ_TMPL, READ_EXPR, READ_EXPL, READ_LOCAL,
797a984708SDavid Chisnall READ_TYPE, READ_FUNC, READ_PTRMEM
807a984708SDavid Chisnall };
817a984708SDavid Chisnall
82a7941b33SDimitry Andric struct read_cmd_item {
83a7941b33SDimitry Andric enum read_cmd cmd;
84a7941b33SDimitry Andric void *data;
85a7941b33SDimitry Andric };
86a7941b33SDimitry Andric
877a984708SDavid Chisnall struct vector_read_cmd {
887a984708SDavid Chisnall size_t size, capacity;
89a7941b33SDimitry Andric struct read_cmd_item *r_container;
90a7941b33SDimitry Andric };
91a7941b33SDimitry Andric
92a7941b33SDimitry Andric enum push_qualifier {
93a7941b33SDimitry Andric PUSH_ALL_QUALIFIER,
94a7941b33SDimitry Andric PUSH_CV_QUALIFIER,
95a7941b33SDimitry Andric PUSH_NON_CV_QUALIFIER,
967a984708SDavid Chisnall };
977a984708SDavid Chisnall
987a984708SDavid Chisnall struct cpp_demangle_data {
997a984708SDavid Chisnall struct vector_str output; /* output string vector */
1007a984708SDavid Chisnall struct vector_str subst; /* substitution string vector */
1017a984708SDavid Chisnall struct vector_str tmpl;
1027a984708SDavid Chisnall struct vector_str class_type;
103a7941b33SDimitry Andric struct vector_str *cur_output; /* ptr to current output vec */
1047a984708SDavid Chisnall struct vector_read_cmd cmd;
1057a984708SDavid Chisnall bool mem_rst; /* restrict member function */
1067a984708SDavid Chisnall bool mem_vat; /* volatile member function */
1077a984708SDavid Chisnall bool mem_cst; /* const member function */
108a7941b33SDimitry Andric bool mem_ref; /* lvalue-ref member func */
109a7941b33SDimitry Andric bool mem_rref; /* rvalue-ref member func */
110a7941b33SDimitry Andric bool is_tmpl; /* template args */
111a7941b33SDimitry Andric bool is_functype; /* function type */
112a7941b33SDimitry Andric bool ref_qualifier; /* ref qualifier */
113a7941b33SDimitry Andric enum type_qualifier ref_qualifier_type; /* ref qualifier type */
114a7941b33SDimitry Andric enum push_qualifier push_qualifier; /* which qualifiers to push */
1157a984708SDavid Chisnall int func_type;
1167a984708SDavid Chisnall const char *cur; /* current mangled name ptr */
1177a984708SDavid Chisnall const char *last_sname; /* last source name */
118a7941b33SDimitry Andric };
119a7941b33SDimitry Andric
120a7941b33SDimitry Andric struct type_delimit {
121a7941b33SDimitry Andric bool paren;
122a7941b33SDimitry Andric bool firstp;
1237a984708SDavid Chisnall };
1247a984708SDavid Chisnall
1257a984708SDavid Chisnall #define CPP_DEMANGLE_TRY_LIMIT 128
1267a984708SDavid Chisnall #define FLOAT_SPRINTF_TRY_LIMIT 5
1277a984708SDavid Chisnall #define FLOAT_QUADRUPLE_BYTES 16
1287a984708SDavid Chisnall #define FLOAT_EXTENED_BYTES 10
1297a984708SDavid Chisnall
1307a984708SDavid Chisnall #define SIMPLE_HASH(x,y) (64 * x + y)
131a7941b33SDimitry Andric #define DEM_PUSH_STR(d,s) cpp_demangle_push_str((d), (s), strlen((s)))
132a7941b33SDimitry Andric #define VEC_PUSH_STR(d,s) vector_str_push((d), (s), strlen((s)))
1337a984708SDavid Chisnall
1347a984708SDavid Chisnall static size_t get_strlen_sum(const struct vector_str *v);
1357a984708SDavid Chisnall static bool vector_str_grow(struct vector_str *v);
1367a984708SDavid Chisnall
1377a984708SDavid Chisnall static size_t
get_strlen_sum(const struct vector_str * v)1387a984708SDavid Chisnall get_strlen_sum(const struct vector_str *v)
1397a984708SDavid Chisnall {
1407a984708SDavid Chisnall size_t i, len = 0;
1417a984708SDavid Chisnall
1427a984708SDavid Chisnall if (v == NULL)
1437a984708SDavid Chisnall return (0);
1447a984708SDavid Chisnall
1457a984708SDavid Chisnall assert(v->size > 0);
1467a984708SDavid Chisnall
1477a984708SDavid Chisnall for (i = 0; i < v->size; ++i)
1487a984708SDavid Chisnall len += strlen(v->container[i]);
1497a984708SDavid Chisnall
1507a984708SDavid Chisnall return (len);
1517a984708SDavid Chisnall }
1527a984708SDavid Chisnall
1537a984708SDavid Chisnall /**
1547a984708SDavid Chisnall * @brief Deallocate resource in vector_str.
1557a984708SDavid Chisnall */
1567b7921b4SDimitry Andric static void
vector_str_dest(struct vector_str * v)1577a984708SDavid Chisnall vector_str_dest(struct vector_str *v)
1587a984708SDavid Chisnall {
1597a984708SDavid Chisnall size_t i;
1607a984708SDavid Chisnall
1617a984708SDavid Chisnall if (v == NULL)
1627a984708SDavid Chisnall return;
1637a984708SDavid Chisnall
1647a984708SDavid Chisnall for (i = 0; i < v->size; ++i)
1657a984708SDavid Chisnall free(v->container[i]);
1667a984708SDavid Chisnall
1677a984708SDavid Chisnall free(v->container);
1687a984708SDavid Chisnall }
1697a984708SDavid Chisnall
1707a984708SDavid Chisnall /**
1717a984708SDavid Chisnall * @brief Find string in vector_str.
1727a984708SDavid Chisnall * @param v Destination vector.
1737a984708SDavid Chisnall * @param o String to find.
1747a984708SDavid Chisnall * @param l Length of the string.
1757a984708SDavid Chisnall * @return -1 at failed, 0 at not found, 1 at found.
1767a984708SDavid Chisnall */
1777b7921b4SDimitry Andric static int
vector_str_find(const struct vector_str * v,const char * o,size_t l)1787a984708SDavid Chisnall vector_str_find(const struct vector_str *v, const char *o, size_t l)
1797a984708SDavid Chisnall {
1807a984708SDavid Chisnall size_t i;
1817a984708SDavid Chisnall
1827a984708SDavid Chisnall if (v == NULL || o == NULL)
1837a984708SDavid Chisnall return (-1);
1847a984708SDavid Chisnall
1857a984708SDavid Chisnall for (i = 0; i < v->size; ++i)
1867a984708SDavid Chisnall if (strncmp(v->container[i], o, l) == 0)
1877a984708SDavid Chisnall return (1);
1887a984708SDavid Chisnall
1897a984708SDavid Chisnall return (0);
1907a984708SDavid Chisnall }
1917a984708SDavid Chisnall
1927a984708SDavid Chisnall /**
1937a984708SDavid Chisnall * @brief Get new allocated flat string from vector.
1947a984708SDavid Chisnall *
1957a984708SDavid Chisnall * If l is not NULL, return length of the string.
1967a984708SDavid Chisnall * @param v Destination vector.
1977a984708SDavid Chisnall * @param l Length of the string.
1987a984708SDavid Chisnall * @return NULL at failed or NUL terminated new allocated string.
1997a984708SDavid Chisnall */
2007b7921b4SDimitry Andric static char *
vector_str_get_flat(const struct vector_str * v,size_t * l)2017a984708SDavid Chisnall vector_str_get_flat(const struct vector_str *v, size_t *l)
2027a984708SDavid Chisnall {
2037a984708SDavid Chisnall size_t i;
204*13da1af1SEd Maste char *rtn, *p;
205*13da1af1SEd Maste ssize_t rtn_size;
2067a984708SDavid Chisnall
2077a984708SDavid Chisnall if (v == NULL || v->size == 0)
2087a984708SDavid Chisnall return (NULL);
2097a984708SDavid Chisnall
2107a984708SDavid Chisnall if ((rtn_size = get_strlen_sum(v)) == 0)
2117a984708SDavid Chisnall return (NULL);
2127a984708SDavid Chisnall
2137a984708SDavid Chisnall if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL)
2147a984708SDavid Chisnall return (NULL);
2157a984708SDavid Chisnall
216*13da1af1SEd Maste p = rtn;
217*13da1af1SEd Maste for (i = 0; i < v->size; ++i)
218*13da1af1SEd Maste p = stpcpy(p, v->container[i]);
2197a984708SDavid Chisnall
2207a984708SDavid Chisnall if (l != NULL)
2217a984708SDavid Chisnall *l = rtn_size;
2227a984708SDavid Chisnall
2237a984708SDavid Chisnall return (rtn);
2247a984708SDavid Chisnall }
2257a984708SDavid Chisnall
2267a984708SDavid Chisnall static bool
vector_str_grow(struct vector_str * v)2277a984708SDavid Chisnall vector_str_grow(struct vector_str *v)
2287a984708SDavid Chisnall {
2297a984708SDavid Chisnall size_t i, tmp_cap;
2307a984708SDavid Chisnall char **tmp_ctn;
2317a984708SDavid Chisnall
2327a984708SDavid Chisnall if (v == NULL)
2337a984708SDavid Chisnall return (false);
2347a984708SDavid Chisnall
2357a984708SDavid Chisnall assert(v->capacity > 0);
2367a984708SDavid Chisnall
237a7941b33SDimitry Andric tmp_cap = BUFFER_GROW(v->capacity);
2387a984708SDavid Chisnall
2397a984708SDavid Chisnall assert(tmp_cap > v->capacity);
2407a984708SDavid Chisnall
2417a984708SDavid Chisnall if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
2427a984708SDavid Chisnall return (false);
2437a984708SDavid Chisnall
2447a984708SDavid Chisnall for (i = 0; i < v->size; ++i)
2457a984708SDavid Chisnall tmp_ctn[i] = v->container[i];
2467a984708SDavid Chisnall
2477a984708SDavid Chisnall free(v->container);
2487a984708SDavid Chisnall
2497a984708SDavid Chisnall v->container = tmp_ctn;
2507a984708SDavid Chisnall v->capacity = tmp_cap;
2517a984708SDavid Chisnall
2527a984708SDavid Chisnall return (true);
2537a984708SDavid Chisnall }
2547a984708SDavid Chisnall
2557a984708SDavid Chisnall /**
2567a984708SDavid Chisnall * @brief Initialize vector_str.
2577a984708SDavid Chisnall * @return false at failed, true at success.
2587a984708SDavid Chisnall */
2597b7921b4SDimitry Andric static bool
vector_str_init(struct vector_str * v)2607a984708SDavid Chisnall vector_str_init(struct vector_str *v)
2617a984708SDavid Chisnall {
2627a984708SDavid Chisnall
2637a984708SDavid Chisnall if (v == NULL)
2647a984708SDavid Chisnall return (false);
2657a984708SDavid Chisnall
2667a984708SDavid Chisnall v->size = 0;
2677a984708SDavid Chisnall v->capacity = VECTOR_DEF_CAPACITY;
2687a984708SDavid Chisnall
2697a984708SDavid Chisnall assert(v->capacity > 0);
2707a984708SDavid Chisnall
2717a984708SDavid Chisnall if ((v->container = malloc(sizeof(char *) * v->capacity)) == NULL)
2727a984708SDavid Chisnall return (false);
2737a984708SDavid Chisnall
2747a984708SDavid Chisnall assert(v->container != NULL);
2757a984708SDavid Chisnall
2767a984708SDavid Chisnall return (true);
2777a984708SDavid Chisnall }
2787a984708SDavid Chisnall
2797a984708SDavid Chisnall /**
2807a984708SDavid Chisnall * @brief Remove last element in vector_str.
2817a984708SDavid Chisnall * @return false at failed, true at success.
2827a984708SDavid Chisnall */
2837b7921b4SDimitry Andric static bool
vector_str_pop(struct vector_str * v)2847a984708SDavid Chisnall vector_str_pop(struct vector_str *v)
2857a984708SDavid Chisnall {
2867a984708SDavid Chisnall
2877a984708SDavid Chisnall if (v == NULL)
2887a984708SDavid Chisnall return (false);
2897a984708SDavid Chisnall
2907a984708SDavid Chisnall if (v->size == 0)
2917a984708SDavid Chisnall return (true);
2927a984708SDavid Chisnall
2937a984708SDavid Chisnall --v->size;
2947a984708SDavid Chisnall
2957a984708SDavid Chisnall free(v->container[v->size]);
2967a984708SDavid Chisnall v->container[v->size] = NULL;
2977a984708SDavid Chisnall
2987a984708SDavid Chisnall return (true);
2997a984708SDavid Chisnall }
3007a984708SDavid Chisnall
3017a984708SDavid Chisnall /**
302*13da1af1SEd Maste * @brief Implements strlcpy() without result.
303*13da1af1SEd Maste */
304*13da1af1SEd Maste static void
copy_string(char * dst,const char * src,size_t dsize)305*13da1af1SEd Maste copy_string(char *dst, const char *src, size_t dsize)
306*13da1af1SEd Maste {
307*13da1af1SEd Maste size_t remain;
308*13da1af1SEd Maste if ((remain = dsize))
309*13da1af1SEd Maste while (--remain)
310*13da1af1SEd Maste if (!(*dst++ = *src++))
311*13da1af1SEd Maste break;
312*13da1af1SEd Maste if (!remain && dsize)
313*13da1af1SEd Maste *dst = 0;
314*13da1af1SEd Maste }
315*13da1af1SEd Maste
316*13da1af1SEd Maste /**
3177a984708SDavid Chisnall * @brief Push back string to vector.
3187a984708SDavid Chisnall * @return false at failed, true at success.
3197a984708SDavid Chisnall */
3207b7921b4SDimitry Andric static bool
vector_str_push(struct vector_str * v,const char * str,size_t len)3217a984708SDavid Chisnall vector_str_push(struct vector_str *v, const char *str, size_t len)
3227a984708SDavid Chisnall {
3237a984708SDavid Chisnall
3247a984708SDavid Chisnall if (v == NULL || str == NULL)
3257a984708SDavid Chisnall return (false);
3267a984708SDavid Chisnall
3277a984708SDavid Chisnall if (v->size == v->capacity && vector_str_grow(v) == false)
3287a984708SDavid Chisnall return (false);
3297a984708SDavid Chisnall
3307a984708SDavid Chisnall if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL)
3317a984708SDavid Chisnall return (false);
3327a984708SDavid Chisnall
333*13da1af1SEd Maste copy_string(v->container[v->size], str, len + 1);
3347a984708SDavid Chisnall
3357a984708SDavid Chisnall ++v->size;
3367a984708SDavid Chisnall
3377a984708SDavid Chisnall return (true);
3387a984708SDavid Chisnall }
3397a984708SDavid Chisnall
3407a984708SDavid Chisnall /**
3417a984708SDavid Chisnall * @brief Push front org vector to det vector.
3427a984708SDavid Chisnall * @return false at failed, true at success.
3437a984708SDavid Chisnall */
3447b7921b4SDimitry Andric static bool
vector_str_push_vector_head(struct vector_str * dst,struct vector_str * org)3457a984708SDavid Chisnall vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org)
3467a984708SDavid Chisnall {
3477a984708SDavid Chisnall size_t i, j, tmp_cap;
3487a984708SDavid Chisnall char **tmp_ctn;
3497a984708SDavid Chisnall
3507a984708SDavid Chisnall if (dst == NULL || org == NULL)
3517a984708SDavid Chisnall return (false);
3527a984708SDavid Chisnall
353a7941b33SDimitry Andric tmp_cap = BUFFER_GROW(dst->size + org->size);
3547a984708SDavid Chisnall
3557a984708SDavid Chisnall if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
3567a984708SDavid Chisnall return (false);
3577a984708SDavid Chisnall
3587a984708SDavid Chisnall for (i = 0; i < org->size; ++i)
3597a984708SDavid Chisnall if ((tmp_ctn[i] = strdup(org->container[i])) == NULL) {
3607a984708SDavid Chisnall for (j = 0; j < i; ++j)
3617a984708SDavid Chisnall free(tmp_ctn[j]);
3627a984708SDavid Chisnall
3637a984708SDavid Chisnall free(tmp_ctn);
3647a984708SDavid Chisnall
3657a984708SDavid Chisnall return (false);
3667a984708SDavid Chisnall }
3677a984708SDavid Chisnall
3687a984708SDavid Chisnall for (i = 0; i < dst->size; ++i)
3697a984708SDavid Chisnall tmp_ctn[i + org->size] = dst->container[i];
3707a984708SDavid Chisnall
3717a984708SDavid Chisnall free(dst->container);
3727a984708SDavid Chisnall
3737a984708SDavid Chisnall dst->container = tmp_ctn;
3747a984708SDavid Chisnall dst->capacity = tmp_cap;
3757a984708SDavid Chisnall dst->size += org->size;
3767a984708SDavid Chisnall
3777a984708SDavid Chisnall return (true);
3787a984708SDavid Chisnall }
3797a984708SDavid Chisnall
3807a984708SDavid Chisnall /**
381a7941b33SDimitry Andric * @brief Push org vector to the tail of det vector.
382a7941b33SDimitry Andric * @return false at failed, true at success.
383a7941b33SDimitry Andric */
3847b7921b4SDimitry Andric static bool
vector_str_push_vector(struct vector_str * dst,struct vector_str * org)385a7941b33SDimitry Andric vector_str_push_vector(struct vector_str *dst, struct vector_str *org)
386a7941b33SDimitry Andric {
387a7941b33SDimitry Andric size_t i, j, tmp_cap;
388a7941b33SDimitry Andric char **tmp_ctn;
389a7941b33SDimitry Andric
390a7941b33SDimitry Andric if (dst == NULL || org == NULL)
391a7941b33SDimitry Andric return (false);
392a7941b33SDimitry Andric
393a7941b33SDimitry Andric tmp_cap = BUFFER_GROW(dst->size + org->size);
394a7941b33SDimitry Andric
395a7941b33SDimitry Andric if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
396a7941b33SDimitry Andric return (false);
397a7941b33SDimitry Andric
398a7941b33SDimitry Andric for (i = 0; i < dst->size; ++i)
399a7941b33SDimitry Andric tmp_ctn[i] = dst->container[i];
400a7941b33SDimitry Andric
401a7941b33SDimitry Andric for (i = 0; i < org->size; ++i)
402a7941b33SDimitry Andric if ((tmp_ctn[i + dst->size] = strdup(org->container[i])) ==
403a7941b33SDimitry Andric NULL) {
404a7941b33SDimitry Andric for (j = 0; j < i + dst->size; ++j)
405a7941b33SDimitry Andric free(tmp_ctn[j]);
406a7941b33SDimitry Andric
407a7941b33SDimitry Andric free(tmp_ctn);
408a7941b33SDimitry Andric
409a7941b33SDimitry Andric return (false);
410a7941b33SDimitry Andric }
411a7941b33SDimitry Andric
412a7941b33SDimitry Andric free(dst->container);
413a7941b33SDimitry Andric
414a7941b33SDimitry Andric dst->container = tmp_ctn;
415a7941b33SDimitry Andric dst->capacity = tmp_cap;
416a7941b33SDimitry Andric dst->size += org->size;
417a7941b33SDimitry Andric
418a7941b33SDimitry Andric return (true);
419a7941b33SDimitry Andric }
420a7941b33SDimitry Andric
421a7941b33SDimitry Andric /**
4227a984708SDavid Chisnall * @brief Get new allocated flat string from vector between begin and end.
4237a984708SDavid Chisnall *
4247a984708SDavid Chisnall * If r_len is not NULL, string length will be returned.
4257a984708SDavid Chisnall * @return NULL at failed or NUL terminated new allocated string.
4267a984708SDavid Chisnall */
4277b7921b4SDimitry Andric static char *
vector_str_substr(const struct vector_str * v,size_t begin,size_t end,size_t * r_len)4287a984708SDavid Chisnall vector_str_substr(const struct vector_str *v, size_t begin, size_t end,
4297a984708SDavid Chisnall size_t *r_len)
4307a984708SDavid Chisnall {
431*13da1af1SEd Maste char *rtn, *p;
432*13da1af1SEd Maste size_t i, len;
4337a984708SDavid Chisnall
4347a984708SDavid Chisnall if (v == NULL || begin > end)
4357a984708SDavid Chisnall return (NULL);
4367a984708SDavid Chisnall
4377a984708SDavid Chisnall len = 0;
4387a984708SDavid Chisnall for (i = begin; i < end + 1; ++i)
4397a984708SDavid Chisnall len += strlen(v->container[i]);
4407a984708SDavid Chisnall
4417a984708SDavid Chisnall if ((rtn = malloc(sizeof(char) * (len + 1))) == NULL)
4427a984708SDavid Chisnall return (NULL);
4437a984708SDavid Chisnall
4447a984708SDavid Chisnall if (r_len != NULL)
4457a984708SDavid Chisnall *r_len = len;
4467a984708SDavid Chisnall
447*13da1af1SEd Maste p = rtn;
448*13da1af1SEd Maste for (i = begin; i < end + 1; ++i)
449*13da1af1SEd Maste p = stpcpy(p, v->container[i]);
4507a984708SDavid Chisnall
4517a984708SDavid Chisnall return (rtn);
4527a984708SDavid Chisnall }
4537a984708SDavid Chisnall
4547a984708SDavid Chisnall static void cpp_demangle_data_dest(struct cpp_demangle_data *);
4557a984708SDavid Chisnall static int cpp_demangle_data_init(struct cpp_demangle_data *,
4567a984708SDavid Chisnall const char *);
4577a984708SDavid Chisnall static int cpp_demangle_get_subst(struct cpp_demangle_data *, size_t);
4587a984708SDavid Chisnall static int cpp_demangle_get_tmpl_param(struct cpp_demangle_data *, size_t);
4597a984708SDavid Chisnall static int cpp_demangle_push_fp(struct cpp_demangle_data *,
4607a984708SDavid Chisnall char *(*)(const char *, size_t));
4617a984708SDavid Chisnall static int cpp_demangle_push_str(struct cpp_demangle_data *, const char *,
4627a984708SDavid Chisnall size_t);
463a7941b33SDimitry Andric static int cpp_demangle_pop_str(struct cpp_demangle_data *);
4647a984708SDavid Chisnall static int cpp_demangle_push_subst(struct cpp_demangle_data *,
4657a984708SDavid Chisnall const char *, size_t);
4667a984708SDavid Chisnall static int cpp_demangle_push_subst_v(struct cpp_demangle_data *,
4677a984708SDavid Chisnall struct vector_str *);
4687a984708SDavid Chisnall static int cpp_demangle_push_type_qualifier(struct cpp_demangle_data *,
4697a984708SDavid Chisnall struct vector_type_qualifier *, const char *);
4707a984708SDavid Chisnall static int cpp_demangle_read_array(struct cpp_demangle_data *);
4717a984708SDavid Chisnall static int cpp_demangle_read_encoding(struct cpp_demangle_data *);
4727a984708SDavid Chisnall static int cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
4737a984708SDavid Chisnall static int cpp_demangle_read_expression(struct cpp_demangle_data *);
474fa7477ceSEd Maste static int cpp_demangle_read_expression_flat(struct cpp_demangle_data *,
475fa7477ceSEd Maste char **);
4767a984708SDavid Chisnall static int cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
4777a984708SDavid Chisnall const char *, size_t);
4787a984708SDavid Chisnall static int cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
4797a984708SDavid Chisnall const char *, size_t);
4807a984708SDavid Chisnall static int cpp_demangle_read_expression_trinary(struct cpp_demangle_data *,
4817a984708SDavid Chisnall const char *, size_t, const char *, size_t);
4827a984708SDavid Chisnall static int cpp_demangle_read_function(struct cpp_demangle_data *, int *,
4837a984708SDavid Chisnall struct vector_type_qualifier *);
4840f9eee39SDavid Chisnall static int cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
4857a984708SDavid Chisnall static int cpp_demangle_read_local_name(struct cpp_demangle_data *);
4867a984708SDavid Chisnall static int cpp_demangle_read_name(struct cpp_demangle_data *);
487fa7477ceSEd Maste static int cpp_demangle_read_name_flat(struct cpp_demangle_data *,
488fa7477ceSEd Maste char**);
4897a984708SDavid Chisnall static int cpp_demangle_read_nested_name(struct cpp_demangle_data *);
4907a984708SDavid Chisnall static int cpp_demangle_read_number(struct cpp_demangle_data *, long *);
491fa7477ceSEd Maste static int cpp_demangle_read_number_as_string(struct cpp_demangle_data *,
492fa7477ceSEd Maste char **);
4937a984708SDavid Chisnall static int cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
4947a984708SDavid Chisnall static int cpp_demangle_read_offset(struct cpp_demangle_data *);
4957a984708SDavid Chisnall static int cpp_demangle_read_offset_number(struct cpp_demangle_data *);
496a7941b33SDimitry Andric static int cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *,
497a7941b33SDimitry Andric struct vector_type_qualifier *);
4987a984708SDavid Chisnall static int cpp_demangle_read_sname(struct cpp_demangle_data *);
4997a984708SDavid Chisnall static int cpp_demangle_read_subst(struct cpp_demangle_data *);
5007a984708SDavid Chisnall static int cpp_demangle_read_subst_std(struct cpp_demangle_data *);
5017a984708SDavid Chisnall static int cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *,
502a7941b33SDimitry Andric const char *);
5037a984708SDavid Chisnall static int cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
5047a984708SDavid Chisnall static int cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
5057a984708SDavid Chisnall static int cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
506a7941b33SDimitry Andric static int cpp_demangle_read_type(struct cpp_demangle_data *,
507a7941b33SDimitry Andric struct type_delimit *);
508fa7477ceSEd Maste static int cpp_demangle_read_type_flat(struct cpp_demangle_data *,
509fa7477ceSEd Maste char **);
5107a984708SDavid Chisnall static int cpp_demangle_read_uqname(struct cpp_demangle_data *);
5117a984708SDavid Chisnall static int cpp_demangle_read_v_offset(struct cpp_demangle_data *);
5127a984708SDavid Chisnall static char *decode_fp_to_double(const char *, size_t);
5137a984708SDavid Chisnall static char *decode_fp_to_float(const char *, size_t);
5147a984708SDavid Chisnall static char *decode_fp_to_float128(const char *, size_t);
5157a984708SDavid Chisnall static char *decode_fp_to_float80(const char *, size_t);
5167a984708SDavid Chisnall static char *decode_fp_to_long_double(const char *, size_t);
5177a984708SDavid Chisnall static int hex_to_dec(char);
5187a984708SDavid Chisnall static void vector_read_cmd_dest(struct vector_read_cmd *);
519a7941b33SDimitry Andric static struct read_cmd_item *vector_read_cmd_find(struct vector_read_cmd *,
520a7941b33SDimitry Andric enum read_cmd);
5217a984708SDavid Chisnall static int vector_read_cmd_init(struct vector_read_cmd *);
5227a984708SDavid Chisnall static int vector_read_cmd_pop(struct vector_read_cmd *);
523a7941b33SDimitry Andric static int vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd,
524a7941b33SDimitry Andric void *);
5257a984708SDavid Chisnall static void vector_type_qualifier_dest(struct vector_type_qualifier *);
5267a984708SDavid Chisnall static int vector_type_qualifier_init(struct vector_type_qualifier *);
5277a984708SDavid Chisnall static int vector_type_qualifier_push(struct vector_type_qualifier *,
5287a984708SDavid Chisnall enum type_qualifier);
5297a984708SDavid Chisnall
5307a984708SDavid Chisnall /**
5317a984708SDavid Chisnall * @brief Decode the input string by IA-64 C++ ABI style.
5327a984708SDavid Chisnall *
5337a984708SDavid Chisnall * GNU GCC v3 use IA-64 standard ABI.
5347a984708SDavid Chisnall * @return New allocated demangled string or NULL if failed.
5357a984708SDavid Chisnall * @todo 1. Testing and more test case. 2. Code cleaning.
5367a984708SDavid Chisnall */
5377a984708SDavid Chisnall char *
__cxa_demangle_gnu3(const char * org)5387a984708SDavid Chisnall __cxa_demangle_gnu3(const char *org)
5397a984708SDavid Chisnall {
5407a984708SDavid Chisnall struct cpp_demangle_data ddata;
541a7941b33SDimitry Andric struct vector_str ret_type;
542a7941b33SDimitry Andric struct type_delimit td;
5437a984708SDavid Chisnall ssize_t org_len;
5447a984708SDavid Chisnall unsigned int limit;
545d1498777SDimitry Andric char *rtn = NULL;
546d1498777SDimitry Andric bool has_ret = false, more_type = false;
5477a984708SDavid Chisnall
5480ee0dbfbSDimitry Andric if (org == NULL)
5497a984708SDavid Chisnall return (NULL);
5507a984708SDavid Chisnall
5510ee0dbfbSDimitry Andric org_len = strlen(org);
5520ee0dbfbSDimitry Andric // Try demangling as a type for short encodings
5530ee0dbfbSDimitry Andric if ((org_len < 2) || (org[0] != '_' || org[1] != 'Z' )) {
5540ee0dbfbSDimitry Andric if (!cpp_demangle_data_init(&ddata, org))
5550ee0dbfbSDimitry Andric return (NULL);
5560ee0dbfbSDimitry Andric if (!cpp_demangle_read_type(&ddata, 0))
5570ee0dbfbSDimitry Andric goto clean;
5580ee0dbfbSDimitry Andric rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
5590ee0dbfbSDimitry Andric goto clean;
5600ee0dbfbSDimitry Andric }
5617a984708SDavid Chisnall if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) {
5627a984708SDavid Chisnall if ((rtn = malloc(org_len + 19)) == NULL)
5637a984708SDavid Chisnall return (NULL);
5647a984708SDavid Chisnall snprintf(rtn, org_len + 19,
5657a984708SDavid Chisnall "global constructors keyed to %s", org + 11);
5667a984708SDavid Chisnall return (rtn);
5677a984708SDavid Chisnall }
5687a984708SDavid Chisnall
5697a984708SDavid Chisnall if (!cpp_demangle_data_init(&ddata, org + 2))
5707a984708SDavid Chisnall return (NULL);
5717a984708SDavid Chisnall
5727a984708SDavid Chisnall if (!cpp_demangle_read_encoding(&ddata))
5737a984708SDavid Chisnall goto clean;
5747a984708SDavid Chisnall
575a7941b33SDimitry Andric /*
576a7941b33SDimitry Andric * Pop function name from substitution candidate list.
577a7941b33SDimitry Andric */
578a7941b33SDimitry Andric if (*ddata.cur != 0 && ddata.subst.size >= 1) {
579a7941b33SDimitry Andric if (!vector_str_pop(&ddata.subst))
580a7941b33SDimitry Andric goto clean;
581a7941b33SDimitry Andric }
582a7941b33SDimitry Andric
583a7941b33SDimitry Andric td.paren = false;
584a7941b33SDimitry Andric td.firstp = true;
5857a984708SDavid Chisnall limit = 0;
586a7941b33SDimitry Andric
587a7941b33SDimitry Andric /*
588a7941b33SDimitry Andric * The first type is a return type if we just demangled template
589a7941b33SDimitry Andric * args. (the template args is right next to the function name,
590a7941b33SDimitry Andric * which means it's a template function)
591a7941b33SDimitry Andric */
592a7941b33SDimitry Andric if (ddata.is_tmpl) {
593a7941b33SDimitry Andric ddata.is_tmpl = false;
594a7941b33SDimitry Andric if (!vector_str_init(&ret_type))
595a7941b33SDimitry Andric goto clean;
596a7941b33SDimitry Andric ddata.cur_output = &ret_type;
597a7941b33SDimitry Andric has_ret = true;
598a7941b33SDimitry Andric }
599a7941b33SDimitry Andric
6007a984708SDavid Chisnall while (*ddata.cur != '\0') {
6017a984708SDavid Chisnall /*
6027a984708SDavid Chisnall * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4
6037a984708SDavid Chisnall */
6047a984708SDavid Chisnall if (*ddata.cur == '@' && *(ddata.cur + 1) == '@')
6057a984708SDavid Chisnall break;
606a7941b33SDimitry Andric
607a7941b33SDimitry Andric if (has_ret) {
608a7941b33SDimitry Andric /* Read return type */
609a7941b33SDimitry Andric if (!cpp_demangle_read_type(&ddata, NULL))
6107a984708SDavid Chisnall goto clean;
611a7941b33SDimitry Andric } else {
612a7941b33SDimitry Andric /* Read function arg type */
613a7941b33SDimitry Andric if (!cpp_demangle_read_type(&ddata, &td))
6147a984708SDavid Chisnall goto clean;
6157a984708SDavid Chisnall }
6167a984708SDavid Chisnall
617a7941b33SDimitry Andric if (has_ret) {
618a7941b33SDimitry Andric /* Push return type to the beginning */
619a7941b33SDimitry Andric if (!VEC_PUSH_STR(&ret_type, " "))
620a7941b33SDimitry Andric goto clean;
621a7941b33SDimitry Andric if (!vector_str_push_vector_head(&ddata.output,
622a7941b33SDimitry Andric &ret_type))
623a7941b33SDimitry Andric goto clean;
624a7941b33SDimitry Andric ddata.cur_output = &ddata.output;
625a7941b33SDimitry Andric vector_str_dest(&ret_type);
626a7941b33SDimitry Andric has_ret = false;
627a7941b33SDimitry Andric more_type = true;
628a7941b33SDimitry Andric } else if (more_type)
629a7941b33SDimitry Andric more_type = false;
630a7941b33SDimitry Andric if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
631a7941b33SDimitry Andric goto clean;
632a7941b33SDimitry Andric }
633a7941b33SDimitry Andric if (more_type)
634a7941b33SDimitry Andric goto clean;
635a7941b33SDimitry Andric
6367a984708SDavid Chisnall if (ddata.output.size == 0)
6377a984708SDavid Chisnall goto clean;
638a7941b33SDimitry Andric if (td.paren && !VEC_PUSH_STR(&ddata.output, ")"))
6397a984708SDavid Chisnall goto clean;
640a7941b33SDimitry Andric if (ddata.mem_vat && !VEC_PUSH_STR(&ddata.output, " volatile"))
6417a984708SDavid Chisnall goto clean;
642a7941b33SDimitry Andric if (ddata.mem_cst && !VEC_PUSH_STR(&ddata.output, " const"))
6437a984708SDavid Chisnall goto clean;
644a7941b33SDimitry Andric if (ddata.mem_rst && !VEC_PUSH_STR(&ddata.output, " restrict"))
645a7941b33SDimitry Andric goto clean;
646a7941b33SDimitry Andric if (ddata.mem_ref && !VEC_PUSH_STR(&ddata.output, " &"))
647a7941b33SDimitry Andric goto clean;
648a7941b33SDimitry Andric if (ddata.mem_rref && !VEC_PUSH_STR(&ddata.output, " &&"))
6497a984708SDavid Chisnall goto clean;
6507a984708SDavid Chisnall
6517a984708SDavid Chisnall rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
6527a984708SDavid Chisnall
6537a984708SDavid Chisnall clean:
654a7941b33SDimitry Andric if (has_ret)
655a7941b33SDimitry Andric vector_str_dest(&ret_type);
656a7941b33SDimitry Andric
6577a984708SDavid Chisnall cpp_demangle_data_dest(&ddata);
6587a984708SDavid Chisnall
6597a984708SDavid Chisnall return (rtn);
6607a984708SDavid Chisnall }
6617a984708SDavid Chisnall
6627a984708SDavid Chisnall static void
cpp_demangle_data_dest(struct cpp_demangle_data * d)6637a984708SDavid Chisnall cpp_demangle_data_dest(struct cpp_demangle_data *d)
6647a984708SDavid Chisnall {
6657a984708SDavid Chisnall
6667a984708SDavid Chisnall if (d == NULL)
6677a984708SDavid Chisnall return;
6687a984708SDavid Chisnall
6697a984708SDavid Chisnall vector_read_cmd_dest(&d->cmd);
6707a984708SDavid Chisnall vector_str_dest(&d->class_type);
6717a984708SDavid Chisnall vector_str_dest(&d->tmpl);
6727a984708SDavid Chisnall vector_str_dest(&d->subst);
6737a984708SDavid Chisnall vector_str_dest(&d->output);
6747a984708SDavid Chisnall }
6757a984708SDavid Chisnall
6767a984708SDavid Chisnall static int
cpp_demangle_data_init(struct cpp_demangle_data * d,const char * cur)6777a984708SDavid Chisnall cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
6787a984708SDavid Chisnall {
6797a984708SDavid Chisnall
6807a984708SDavid Chisnall if (d == NULL || cur == NULL)
6817a984708SDavid Chisnall return (0);
6827a984708SDavid Chisnall
6837a984708SDavid Chisnall if (!vector_str_init(&d->output))
6847a984708SDavid Chisnall return (0);
6857a984708SDavid Chisnall if (!vector_str_init(&d->subst))
686a7941b33SDimitry Andric goto clean1;
6877a984708SDavid Chisnall if (!vector_str_init(&d->tmpl))
688a7941b33SDimitry Andric goto clean2;
6897a984708SDavid Chisnall if (!vector_str_init(&d->class_type))
690a7941b33SDimitry Andric goto clean3;
6917a984708SDavid Chisnall if (!vector_read_cmd_init(&d->cmd))
692a7941b33SDimitry Andric goto clean4;
6937a984708SDavid Chisnall
6947a984708SDavid Chisnall assert(d->output.container != NULL);
6957a984708SDavid Chisnall assert(d->subst.container != NULL);
6967a984708SDavid Chisnall assert(d->tmpl.container != NULL);
6977a984708SDavid Chisnall assert(d->class_type.container != NULL);
6987a984708SDavid Chisnall
6997a984708SDavid Chisnall d->mem_rst = false;
7007a984708SDavid Chisnall d->mem_vat = false;
7017a984708SDavid Chisnall d->mem_cst = false;
702a7941b33SDimitry Andric d->mem_ref = false;
703a7941b33SDimitry Andric d->mem_rref = false;
704a7941b33SDimitry Andric d->is_tmpl = false;
705a7941b33SDimitry Andric d->is_functype = false;
706a7941b33SDimitry Andric d->ref_qualifier = false;
707a7941b33SDimitry Andric d->push_qualifier = PUSH_ALL_QUALIFIER;
7087a984708SDavid Chisnall d->func_type = 0;
7097a984708SDavid Chisnall d->cur = cur;
710a7941b33SDimitry Andric d->cur_output = &d->output;
7117a984708SDavid Chisnall d->last_sname = NULL;
7127a984708SDavid Chisnall
7137a984708SDavid Chisnall return (1);
7147a984708SDavid Chisnall
7157a984708SDavid Chisnall clean4:
716a7941b33SDimitry Andric vector_str_dest(&d->class_type);
7177a984708SDavid Chisnall clean3:
718a7941b33SDimitry Andric vector_str_dest(&d->tmpl);
7197a984708SDavid Chisnall clean2:
720a7941b33SDimitry Andric vector_str_dest(&d->subst);
7217a984708SDavid Chisnall clean1:
7227a984708SDavid Chisnall vector_str_dest(&d->output);
7237a984708SDavid Chisnall
7247a984708SDavid Chisnall return (0);
7257a984708SDavid Chisnall }
7267a984708SDavid Chisnall
7277a984708SDavid Chisnall static int
cpp_demangle_push_fp(struct cpp_demangle_data * ddata,char * (* decoder)(const char *,size_t))7287a984708SDavid Chisnall cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
7297a984708SDavid Chisnall char *(*decoder)(const char *, size_t))
7307a984708SDavid Chisnall {
7317a984708SDavid Chisnall size_t len;
7327a984708SDavid Chisnall int rtn;
7337a984708SDavid Chisnall const char *fp;
7347a984708SDavid Chisnall char *f;
7357a984708SDavid Chisnall
7367a984708SDavid Chisnall if (ddata == NULL || decoder == NULL)
7377a984708SDavid Chisnall return (0);
7387a984708SDavid Chisnall
7397a984708SDavid Chisnall fp = ddata->cur;
7407a984708SDavid Chisnall while (*ddata->cur != 'E')
7417a984708SDavid Chisnall ++ddata->cur;
7427a984708SDavid Chisnall
7437a984708SDavid Chisnall if ((f = decoder(fp, ddata->cur - fp)) == NULL)
7447a984708SDavid Chisnall return (0);
7457a984708SDavid Chisnall
7467a984708SDavid Chisnall rtn = 0;
7470f9eee39SDavid Chisnall if ((len = strlen(f)) > 0)
7480f9eee39SDavid Chisnall rtn = cpp_demangle_push_str(ddata, f, len);
7497a984708SDavid Chisnall
7507a984708SDavid Chisnall free(f);
7517a984708SDavid Chisnall
752fa7477ceSEd Maste ++ddata->cur;
753fa7477ceSEd Maste
7540f9eee39SDavid Chisnall return (rtn);
7557a984708SDavid Chisnall }
7567a984708SDavid Chisnall
7577a984708SDavid Chisnall static int
cpp_demangle_push_str(struct cpp_demangle_data * ddata,const char * str,size_t len)7587a984708SDavid Chisnall cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
7597a984708SDavid Chisnall size_t len)
7607a984708SDavid Chisnall {
7617a984708SDavid Chisnall
7627a984708SDavid Chisnall if (ddata == NULL || str == NULL || len == 0)
7637a984708SDavid Chisnall return (0);
7647a984708SDavid Chisnall
765a7941b33SDimitry Andric /*
766a7941b33SDimitry Andric * is_tmpl is used to check if the type (function arg) is right next
767a7941b33SDimitry Andric * to template args, and should always be cleared whenever new string
768a7941b33SDimitry Andric * pushed.
769a7941b33SDimitry Andric */
770a7941b33SDimitry Andric ddata->is_tmpl = false;
7717a984708SDavid Chisnall
772a7941b33SDimitry Andric return (vector_str_push(ddata->cur_output, str, len));
773a7941b33SDimitry Andric }
774a7941b33SDimitry Andric
775a7941b33SDimitry Andric static int
cpp_demangle_pop_str(struct cpp_demangle_data * ddata)776a7941b33SDimitry Andric cpp_demangle_pop_str(struct cpp_demangle_data *ddata)
777a7941b33SDimitry Andric {
778a7941b33SDimitry Andric
779a7941b33SDimitry Andric if (ddata == NULL)
780a7941b33SDimitry Andric return (0);
781a7941b33SDimitry Andric
782a7941b33SDimitry Andric return (vector_str_pop(ddata->cur_output));
7837a984708SDavid Chisnall }
7847a984708SDavid Chisnall
7857a984708SDavid Chisnall static int
cpp_demangle_push_subst(struct cpp_demangle_data * ddata,const char * str,size_t len)7867a984708SDavid Chisnall cpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str,
7877a984708SDavid Chisnall size_t len)
7887a984708SDavid Chisnall {
7897a984708SDavid Chisnall
7907a984708SDavid Chisnall if (ddata == NULL || str == NULL || len == 0)
7917a984708SDavid Chisnall return (0);
7927a984708SDavid Chisnall
7937a984708SDavid Chisnall if (!vector_str_find(&ddata->subst, str, len))
7947a984708SDavid Chisnall return (vector_str_push(&ddata->subst, str, len));
7957a984708SDavid Chisnall
7967a984708SDavid Chisnall return (1);
7977a984708SDavid Chisnall }
7987a984708SDavid Chisnall
7997a984708SDavid Chisnall static int
cpp_demangle_push_subst_v(struct cpp_demangle_data * ddata,struct vector_str * v)8007a984708SDavid Chisnall cpp_demangle_push_subst_v(struct cpp_demangle_data *ddata, struct vector_str *v)
8017a984708SDavid Chisnall {
8027a984708SDavid Chisnall size_t str_len;
8037a984708SDavid Chisnall int rtn;
8047a984708SDavid Chisnall char *str;
8057a984708SDavid Chisnall
8067a984708SDavid Chisnall if (ddata == NULL || v == NULL)
8077a984708SDavid Chisnall return (0);
8087a984708SDavid Chisnall
8097a984708SDavid Chisnall if ((str = vector_str_get_flat(v, &str_len)) == NULL)
8107a984708SDavid Chisnall return (0);
8117a984708SDavid Chisnall
8127a984708SDavid Chisnall rtn = cpp_demangle_push_subst(ddata, str, str_len);
8130f9eee39SDavid Chisnall
8147a984708SDavid Chisnall free(str);
8157a984708SDavid Chisnall
8167a984708SDavid Chisnall return (rtn);
8177a984708SDavid Chisnall }
8187a984708SDavid Chisnall
8197a984708SDavid Chisnall static int
cpp_demangle_push_type_qualifier(struct cpp_demangle_data * ddata,struct vector_type_qualifier * v,const char * type_str)8207a984708SDavid Chisnall cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
8217a984708SDavid Chisnall struct vector_type_qualifier *v, const char *type_str)
8227a984708SDavid Chisnall {
8237a984708SDavid Chisnall struct vector_str subst_v;
824a7941b33SDimitry Andric enum type_qualifier t;
8257a984708SDavid Chisnall size_t idx, e_idx, e_len;
8267a984708SDavid Chisnall char *buf;
827a7941b33SDimitry Andric int rtn;
828a7941b33SDimitry Andric bool cv;
8297a984708SDavid Chisnall
8307a984708SDavid Chisnall if (ddata == NULL || v == NULL)
8317a984708SDavid Chisnall return (0);
8327a984708SDavid Chisnall
8337a984708SDavid Chisnall if ((idx = v->size) == 0)
8347a984708SDavid Chisnall return (1);
8357a984708SDavid Chisnall
8367a984708SDavid Chisnall rtn = 0;
8377a984708SDavid Chisnall if (type_str != NULL) {
8387a984708SDavid Chisnall if (!vector_str_init(&subst_v))
8397a984708SDavid Chisnall return (0);
840a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, type_str))
8417a984708SDavid Chisnall goto clean;
8427a984708SDavid Chisnall }
8437a984708SDavid Chisnall
844a7941b33SDimitry Andric cv = true;
8457a984708SDavid Chisnall e_idx = 0;
8467a984708SDavid Chisnall while (idx > 0) {
8477a984708SDavid Chisnall switch (v->q_container[idx - 1]) {
8487a984708SDavid Chisnall case TYPE_PTR:
849a7941b33SDimitry Andric cv = false;
850a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
851a7941b33SDimitry Andric break;
852a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "*"))
8537a984708SDavid Chisnall goto clean;
8547a984708SDavid Chisnall if (type_str != NULL) {
855a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, "*"))
8567a984708SDavid Chisnall goto clean;
857fa7477ceSEd Maste if (!cpp_demangle_push_subst_v(ddata,
858fa7477ceSEd Maste &subst_v))
8597a984708SDavid Chisnall goto clean;
8607a984708SDavid Chisnall }
8617a984708SDavid Chisnall break;
8627a984708SDavid Chisnall
8637a984708SDavid Chisnall case TYPE_REF:
864a7941b33SDimitry Andric cv = false;
865a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
866a7941b33SDimitry Andric break;
867a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "&"))
8687a984708SDavid Chisnall goto clean;
8697a984708SDavid Chisnall if (type_str != NULL) {
870a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, "&"))
871a7941b33SDimitry Andric goto clean;
872a7941b33SDimitry Andric if (!cpp_demangle_push_subst_v(ddata,
873a7941b33SDimitry Andric &subst_v))
874a7941b33SDimitry Andric goto clean;
875a7941b33SDimitry Andric }
876a7941b33SDimitry Andric break;
877a7941b33SDimitry Andric
878a7941b33SDimitry Andric case TYPE_RREF:
879a7941b33SDimitry Andric cv = false;
880a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
881a7941b33SDimitry Andric break;
882a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "&&"))
883a7941b33SDimitry Andric goto clean;
884a7941b33SDimitry Andric if (type_str != NULL) {
885a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, "&&"))
8867a984708SDavid Chisnall goto clean;
887fa7477ceSEd Maste if (!cpp_demangle_push_subst_v(ddata,
888fa7477ceSEd Maste &subst_v))
8897a984708SDavid Chisnall goto clean;
8907a984708SDavid Chisnall }
8917a984708SDavid Chisnall break;
8927a984708SDavid Chisnall
8937a984708SDavid Chisnall case TYPE_CMX:
894a7941b33SDimitry Andric cv = false;
895a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
896a7941b33SDimitry Andric break;
897a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " complex"))
8987a984708SDavid Chisnall goto clean;
8997a984708SDavid Chisnall if (type_str != NULL) {
900a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, " complex"))
9017a984708SDavid Chisnall goto clean;
902fa7477ceSEd Maste if (!cpp_demangle_push_subst_v(ddata,
903fa7477ceSEd Maste &subst_v))
9047a984708SDavid Chisnall goto clean;
9057a984708SDavid Chisnall }
9067a984708SDavid Chisnall break;
9077a984708SDavid Chisnall
9087a984708SDavid Chisnall case TYPE_IMG:
909a7941b33SDimitry Andric cv = false;
910a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
911a7941b33SDimitry Andric break;
912a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " imaginary"))
9137a984708SDavid Chisnall goto clean;
9147a984708SDavid Chisnall if (type_str != NULL) {
915a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, " imaginary"))
9167a984708SDavid Chisnall goto clean;
917fa7477ceSEd Maste if (!cpp_demangle_push_subst_v(ddata,
918fa7477ceSEd Maste &subst_v))
9197a984708SDavid Chisnall goto clean;
9207a984708SDavid Chisnall }
9217a984708SDavid Chisnall break;
9227a984708SDavid Chisnall
9237a984708SDavid Chisnall case TYPE_EXT:
924a7941b33SDimitry Andric cv = false;
925a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
926a7941b33SDimitry Andric break;
927fa7477ceSEd Maste if (v->ext_name.size == 0 ||
928fa7477ceSEd Maste e_idx > v->ext_name.size - 1)
9297a984708SDavid Chisnall goto clean;
930fa7477ceSEd Maste if ((e_len = strlen(v->ext_name.container[e_idx])) ==
931fa7477ceSEd Maste 0)
9327a984708SDavid Chisnall goto clean;
933fa7477ceSEd Maste if ((buf = malloc(e_len + 2)) == NULL)
9347a984708SDavid Chisnall goto clean;
935fa7477ceSEd Maste snprintf(buf, e_len + 2, " %s",
936fa7477ceSEd Maste v->ext_name.container[e_idx]);
9377a984708SDavid Chisnall
938a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, buf)) {
9397a984708SDavid Chisnall free(buf);
9407a984708SDavid Chisnall goto clean;
9417a984708SDavid Chisnall }
9427a984708SDavid Chisnall
9437a984708SDavid Chisnall if (type_str != NULL) {
944a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, buf)) {
9457a984708SDavid Chisnall free(buf);
9467a984708SDavid Chisnall goto clean;
9477a984708SDavid Chisnall }
948fa7477ceSEd Maste if (!cpp_demangle_push_subst_v(ddata,
949fa7477ceSEd Maste &subst_v)) {
9507a984708SDavid Chisnall free(buf);
9517a984708SDavid Chisnall goto clean;
9527a984708SDavid Chisnall }
9537a984708SDavid Chisnall }
9547a984708SDavid Chisnall free(buf);
9557a984708SDavid Chisnall ++e_idx;
9567a984708SDavid Chisnall break;
9577a984708SDavid Chisnall
9587a984708SDavid Chisnall case TYPE_RST:
959a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
960a7941b33SDimitry Andric cv)
961a7941b33SDimitry Andric break;
962a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
963a7941b33SDimitry Andric break;
964a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " restrict"))
9657a984708SDavid Chisnall goto clean;
9667a984708SDavid Chisnall if (type_str != NULL) {
967a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, " restrict"))
9687a984708SDavid Chisnall goto clean;
969a7941b33SDimitry Andric if (idx - 1 > 0) {
970a7941b33SDimitry Andric t = v->q_container[idx - 2];
971a7941b33SDimitry Andric if (t == TYPE_RST || t == TYPE_VAT ||
972a7941b33SDimitry Andric t == TYPE_CST)
973a7941b33SDimitry Andric break;
974a7941b33SDimitry Andric }
975fa7477ceSEd Maste if (!cpp_demangle_push_subst_v(ddata,
976fa7477ceSEd Maste &subst_v))
9777a984708SDavid Chisnall goto clean;
9787a984708SDavid Chisnall }
9797a984708SDavid Chisnall break;
9807a984708SDavid Chisnall
9817a984708SDavid Chisnall case TYPE_VAT:
982a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
983a7941b33SDimitry Andric cv)
984a7941b33SDimitry Andric break;
985a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
986a7941b33SDimitry Andric break;
987a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " volatile"))
9887a984708SDavid Chisnall goto clean;
9897a984708SDavid Chisnall if (type_str != NULL) {
990a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, " volatile"))
9917a984708SDavid Chisnall goto clean;
992a7941b33SDimitry Andric if (idx - 1 > 0) {
993a7941b33SDimitry Andric t = v->q_container[idx - 2];
994a7941b33SDimitry Andric if (t == TYPE_RST || t == TYPE_VAT ||
995a7941b33SDimitry Andric t == TYPE_CST)
996a7941b33SDimitry Andric break;
997a7941b33SDimitry Andric }
998fa7477ceSEd Maste if (!cpp_demangle_push_subst_v(ddata,
999fa7477ceSEd Maste &subst_v))
10007a984708SDavid Chisnall goto clean;
10017a984708SDavid Chisnall }
10027a984708SDavid Chisnall break;
10037a984708SDavid Chisnall
10047a984708SDavid Chisnall case TYPE_CST:
1005a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
1006a7941b33SDimitry Andric cv)
1007a7941b33SDimitry Andric break;
1008a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
1009a7941b33SDimitry Andric break;
1010a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " const"))
10117a984708SDavid Chisnall goto clean;
10127a984708SDavid Chisnall if (type_str != NULL) {
1013a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, " const"))
10147a984708SDavid Chisnall goto clean;
1015a7941b33SDimitry Andric if (idx - 1 > 0) {
1016a7941b33SDimitry Andric t = v->q_container[idx - 2];
1017a7941b33SDimitry Andric if (t == TYPE_RST || t == TYPE_VAT ||
1018a7941b33SDimitry Andric t == TYPE_CST)
1019a7941b33SDimitry Andric break;
1020a7941b33SDimitry Andric }
1021fa7477ceSEd Maste if (!cpp_demangle_push_subst_v(ddata,
1022fa7477ceSEd Maste &subst_v))
10237a984708SDavid Chisnall goto clean;
10247a984708SDavid Chisnall }
10257a984708SDavid Chisnall break;
10267a984708SDavid Chisnall
1027fa7477ceSEd Maste case TYPE_VEC:
1028a7941b33SDimitry Andric cv = false;
1029a7941b33SDimitry Andric if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
1030a7941b33SDimitry Andric break;
1031fa7477ceSEd Maste if (v->ext_name.size == 0 ||
1032fa7477ceSEd Maste e_idx > v->ext_name.size - 1)
1033fa7477ceSEd Maste goto clean;
1034fa7477ceSEd Maste if ((e_len = strlen(v->ext_name.container[e_idx])) ==
1035fa7477ceSEd Maste 0)
1036fa7477ceSEd Maste goto clean;
1037fa7477ceSEd Maste if ((buf = malloc(e_len + 12)) == NULL)
1038fa7477ceSEd Maste goto clean;
1039fa7477ceSEd Maste snprintf(buf, e_len + 12, " __vector(%s)",
1040fa7477ceSEd Maste v->ext_name.container[e_idx]);
1041a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, buf)) {
1042fa7477ceSEd Maste free(buf);
1043fa7477ceSEd Maste goto clean;
1044fa7477ceSEd Maste }
1045fa7477ceSEd Maste if (type_str != NULL) {
1046a7941b33SDimitry Andric if (!VEC_PUSH_STR(&subst_v, buf)) {
1047fa7477ceSEd Maste free(buf);
1048fa7477ceSEd Maste goto clean;
1049fa7477ceSEd Maste }
1050fa7477ceSEd Maste if (!cpp_demangle_push_subst_v(ddata,
1051fa7477ceSEd Maste &subst_v)) {
1052fa7477ceSEd Maste free(buf);
1053fa7477ceSEd Maste goto clean;
1054fa7477ceSEd Maste }
1055fa7477ceSEd Maste }
1056fa7477ceSEd Maste free(buf);
1057fa7477ceSEd Maste ++e_idx;
1058fa7477ceSEd Maste break;
10594a1f3708SDimitry Andric }
10607a984708SDavid Chisnall --idx;
10617a984708SDavid Chisnall }
10627a984708SDavid Chisnall
10637a984708SDavid Chisnall rtn = 1;
10647a984708SDavid Chisnall clean:
10657a984708SDavid Chisnall if (type_str != NULL)
10667a984708SDavid Chisnall vector_str_dest(&subst_v);
10677a984708SDavid Chisnall
10687a984708SDavid Chisnall return (rtn);
10697a984708SDavid Chisnall }
10707a984708SDavid Chisnall
10717a984708SDavid Chisnall static int
cpp_demangle_get_subst(struct cpp_demangle_data * ddata,size_t idx)10727a984708SDavid Chisnall cpp_demangle_get_subst(struct cpp_demangle_data *ddata, size_t idx)
10737a984708SDavid Chisnall {
10747a984708SDavid Chisnall size_t len;
10757a984708SDavid Chisnall
10767a984708SDavid Chisnall if (ddata == NULL || ddata->subst.size <= idx)
10777a984708SDavid Chisnall return (0);
10787a984708SDavid Chisnall if ((len = strlen(ddata->subst.container[idx])) == 0)
10797a984708SDavid Chisnall return (0);
10807a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, ddata->subst.container[idx], len))
10817a984708SDavid Chisnall return (0);
10827a984708SDavid Chisnall
10837a984708SDavid Chisnall /* skip '_' */
10847a984708SDavid Chisnall ++ddata->cur;
10857a984708SDavid Chisnall
10867a984708SDavid Chisnall return (1);
10877a984708SDavid Chisnall }
10887a984708SDavid Chisnall
10897a984708SDavid Chisnall static int
cpp_demangle_get_tmpl_param(struct cpp_demangle_data * ddata,size_t idx)10907a984708SDavid Chisnall cpp_demangle_get_tmpl_param(struct cpp_demangle_data *ddata, size_t idx)
10917a984708SDavid Chisnall {
10927a984708SDavid Chisnall size_t len;
10937a984708SDavid Chisnall
10947a984708SDavid Chisnall if (ddata == NULL || ddata->tmpl.size <= idx)
10957a984708SDavid Chisnall return (0);
10967a984708SDavid Chisnall if ((len = strlen(ddata->tmpl.container[idx])) == 0)
10977a984708SDavid Chisnall return (0);
10987a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, ddata->tmpl.container[idx], len))
10997a984708SDavid Chisnall return (0);
11007a984708SDavid Chisnall
11017a984708SDavid Chisnall ++ddata->cur;
11027a984708SDavid Chisnall
11037a984708SDavid Chisnall return (1);
11047a984708SDavid Chisnall }
11057a984708SDavid Chisnall
11067a984708SDavid Chisnall static int
cpp_demangle_read_array(struct cpp_demangle_data * ddata)11077a984708SDavid Chisnall cpp_demangle_read_array(struct cpp_demangle_data *ddata)
11087a984708SDavid Chisnall {
11097a984708SDavid Chisnall size_t i, num_len, exp_len, p_idx, idx;
11107a984708SDavid Chisnall const char *num;
11117a984708SDavid Chisnall char *exp;
11127a984708SDavid Chisnall
11137a984708SDavid Chisnall if (ddata == NULL || *(++ddata->cur) == '\0')
11147a984708SDavid Chisnall return (0);
11157a984708SDavid Chisnall
11167a984708SDavid Chisnall if (*ddata->cur == '_') {
11177a984708SDavid Chisnall if (*(++ddata->cur) == '\0')
11187a984708SDavid Chisnall return (0);
11197a984708SDavid Chisnall
1120a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL))
11217a984708SDavid Chisnall return (0);
11227a984708SDavid Chisnall
1123a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " []"))
11247a984708SDavid Chisnall return (0);
11257a984708SDavid Chisnall } else {
11267a984708SDavid Chisnall if (ELFTC_ISDIGIT(*ddata->cur) != 0) {
11277a984708SDavid Chisnall num = ddata->cur;
11287a984708SDavid Chisnall while (ELFTC_ISDIGIT(*ddata->cur) != 0)
11297a984708SDavid Chisnall ++ddata->cur;
11307a984708SDavid Chisnall if (*ddata->cur != '_')
11317a984708SDavid Chisnall return (0);
11327a984708SDavid Chisnall num_len = ddata->cur - num;
11337a984708SDavid Chisnall assert(num_len > 0);
11347a984708SDavid Chisnall if (*(++ddata->cur) == '\0')
11357a984708SDavid Chisnall return (0);
1136a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL))
11377a984708SDavid Chisnall return (0);
1138a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " ["))
11397a984708SDavid Chisnall return (0);
11407a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, num, num_len))
11417a984708SDavid Chisnall return (0);
1142a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "]"))
11437a984708SDavid Chisnall return (0);
11447a984708SDavid Chisnall } else {
11457a984708SDavid Chisnall p_idx = ddata->output.size;
11467a984708SDavid Chisnall if (!cpp_demangle_read_expression(ddata))
11477a984708SDavid Chisnall return (0);
11487a984708SDavid Chisnall if ((exp = vector_str_substr(&ddata->output, p_idx,
11497a984708SDavid Chisnall ddata->output.size - 1, &exp_len)) == NULL)
11507a984708SDavid Chisnall return (0);
11517a984708SDavid Chisnall idx = ddata->output.size;
11527a984708SDavid Chisnall for (i = p_idx; i < idx; ++i)
11537a984708SDavid Chisnall if (!vector_str_pop(&ddata->output)) {
11547a984708SDavid Chisnall free(exp);
11557a984708SDavid Chisnall return (0);
11567a984708SDavid Chisnall }
11577a984708SDavid Chisnall if (*ddata->cur != '_') {
11587a984708SDavid Chisnall free(exp);
11597a984708SDavid Chisnall return (0);
11607a984708SDavid Chisnall }
11617a984708SDavid Chisnall ++ddata->cur;
11627a984708SDavid Chisnall if (*ddata->cur == '\0') {
11637a984708SDavid Chisnall free(exp);
11647a984708SDavid Chisnall return (0);
11657a984708SDavid Chisnall }
1166a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL)) {
11677a984708SDavid Chisnall free(exp);
11687a984708SDavid Chisnall return (0);
11697a984708SDavid Chisnall }
1170a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " [")) {
11717a984708SDavid Chisnall free(exp);
11727a984708SDavid Chisnall return (0);
11737a984708SDavid Chisnall }
11747a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, exp, exp_len)) {
11757a984708SDavid Chisnall free(exp);
11767a984708SDavid Chisnall return (0);
11777a984708SDavid Chisnall }
1178a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "]")) {
11797a984708SDavid Chisnall free(exp);
11807a984708SDavid Chisnall return (0);
11817a984708SDavid Chisnall }
11827a984708SDavid Chisnall free(exp);
11837a984708SDavid Chisnall }
11847a984708SDavid Chisnall }
11857a984708SDavid Chisnall
11867a984708SDavid Chisnall return (1);
11877a984708SDavid Chisnall }
11887a984708SDavid Chisnall
11897a984708SDavid Chisnall static int
cpp_demangle_read_expr_primary(struct cpp_demangle_data * ddata)11907a984708SDavid Chisnall cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
11917a984708SDavid Chisnall {
11927a984708SDavid Chisnall const char *num;
11937a984708SDavid Chisnall
11947a984708SDavid Chisnall if (ddata == NULL || *(++ddata->cur) == '\0')
11957a984708SDavid Chisnall return (0);
11967a984708SDavid Chisnall
11977a984708SDavid Chisnall if (*ddata->cur == '_' && *(ddata->cur + 1) == 'Z') {
11987a984708SDavid Chisnall ddata->cur += 2;
11997a984708SDavid Chisnall if (*ddata->cur == '\0')
12007a984708SDavid Chisnall return (0);
12017a984708SDavid Chisnall if (!cpp_demangle_read_encoding(ddata))
12027a984708SDavid Chisnall return (0);
12037a984708SDavid Chisnall ++ddata->cur;
12047a984708SDavid Chisnall return (1);
12057a984708SDavid Chisnall }
12067a984708SDavid Chisnall
12077a984708SDavid Chisnall switch (*ddata->cur) {
12087a984708SDavid Chisnall case 'b':
1209fa7477ceSEd Maste if (*(ddata->cur + 2) != 'E')
1210fa7477ceSEd Maste return (0);
12117a984708SDavid Chisnall switch (*(++ddata->cur)) {
12127a984708SDavid Chisnall case '0':
1213fa7477ceSEd Maste ddata->cur += 2;
1214a7941b33SDimitry Andric return (DEM_PUSH_STR(ddata, "false"));
12157a984708SDavid Chisnall case '1':
1216fa7477ceSEd Maste ddata->cur += 2;
1217a7941b33SDimitry Andric return (DEM_PUSH_STR(ddata, "true"));
12187a984708SDavid Chisnall default:
12197a984708SDavid Chisnall return (0);
12204a1f3708SDimitry Andric }
12217a984708SDavid Chisnall
12227a984708SDavid Chisnall case 'd':
12237a984708SDavid Chisnall ++ddata->cur;
12247a984708SDavid Chisnall return (cpp_demangle_push_fp(ddata, decode_fp_to_double));
12257a984708SDavid Chisnall
12267a984708SDavid Chisnall case 'e':
12277a984708SDavid Chisnall ++ddata->cur;
12287a984708SDavid Chisnall if (sizeof(long double) == 10)
12297a984708SDavid Chisnall return (cpp_demangle_push_fp(ddata,
12307a984708SDavid Chisnall decode_fp_to_double));
12317a984708SDavid Chisnall return (cpp_demangle_push_fp(ddata, decode_fp_to_float80));
12327a984708SDavid Chisnall
12337a984708SDavid Chisnall case 'f':
12347a984708SDavid Chisnall ++ddata->cur;
12357a984708SDavid Chisnall return (cpp_demangle_push_fp(ddata, decode_fp_to_float));
12367a984708SDavid Chisnall
12377a984708SDavid Chisnall case 'g':
12387a984708SDavid Chisnall ++ddata->cur;
12397a984708SDavid Chisnall if (sizeof(long double) == 16)
12407a984708SDavid Chisnall return (cpp_demangle_push_fp(ddata,
12417a984708SDavid Chisnall decode_fp_to_double));
12427a984708SDavid Chisnall return (cpp_demangle_push_fp(ddata, decode_fp_to_float128));
12437a984708SDavid Chisnall
12447a984708SDavid Chisnall case 'i':
12457a984708SDavid Chisnall case 'j':
12467a984708SDavid Chisnall case 'l':
12477a984708SDavid Chisnall case 'm':
12487a984708SDavid Chisnall case 'n':
12497a984708SDavid Chisnall case 's':
12507a984708SDavid Chisnall case 't':
12517a984708SDavid Chisnall case 'x':
12527a984708SDavid Chisnall case 'y':
12537a984708SDavid Chisnall if (*(++ddata->cur) == 'n') {
1254a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "-"))
12557a984708SDavid Chisnall return (0);
12567a984708SDavid Chisnall ++ddata->cur;
12577a984708SDavid Chisnall }
12587a984708SDavid Chisnall num = ddata->cur;
12597a984708SDavid Chisnall while (*ddata->cur != 'E') {
12607a984708SDavid Chisnall if (!ELFTC_ISDIGIT(*ddata->cur))
12617a984708SDavid Chisnall return (0);
12627a984708SDavid Chisnall ++ddata->cur;
12637a984708SDavid Chisnall }
12647a984708SDavid Chisnall ++ddata->cur;
1265fa7477ceSEd Maste return (cpp_demangle_push_str(ddata, num,
1266fa7477ceSEd Maste ddata->cur - num - 1));
12677a984708SDavid Chisnall
12687a984708SDavid Chisnall default:
12697a984708SDavid Chisnall return (0);
12704a1f3708SDimitry Andric }
12717a984708SDavid Chisnall }
12727a984708SDavid Chisnall
12737a984708SDavid Chisnall static int
cpp_demangle_read_expression(struct cpp_demangle_data * ddata)12747a984708SDavid Chisnall cpp_demangle_read_expression(struct cpp_demangle_data *ddata)
12757a984708SDavid Chisnall {
12767a984708SDavid Chisnall
12777a984708SDavid Chisnall if (ddata == NULL || *ddata->cur == '\0')
12787a984708SDavid Chisnall return (0);
12797a984708SDavid Chisnall
12807a984708SDavid Chisnall switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
12817a984708SDavid Chisnall case SIMPLE_HASH('s', 't'):
12827a984708SDavid Chisnall ddata->cur += 2;
1283a7941b33SDimitry Andric return (cpp_demangle_read_type(ddata, NULL));
12847a984708SDavid Chisnall
12857a984708SDavid Chisnall case SIMPLE_HASH('s', 'r'):
12867a984708SDavid Chisnall ddata->cur += 2;
1287a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL))
12887a984708SDavid Chisnall return (0);
12897a984708SDavid Chisnall if (!cpp_demangle_read_uqname(ddata))
12907a984708SDavid Chisnall return (0);
12917a984708SDavid Chisnall if (*ddata->cur == 'I')
12927a984708SDavid Chisnall return (cpp_demangle_read_tmpl_args(ddata));
12937a984708SDavid Chisnall return (1);
12947a984708SDavid Chisnall
12957a984708SDavid Chisnall case SIMPLE_HASH('a', 'a'):
12967a984708SDavid Chisnall /* operator && */
12977a984708SDavid Chisnall ddata->cur += 2;
12987a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "&&", 2));
12997a984708SDavid Chisnall
13007a984708SDavid Chisnall case SIMPLE_HASH('a', 'd'):
13017a984708SDavid Chisnall /* operator & (unary) */
13027a984708SDavid Chisnall ddata->cur += 2;
13037a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "&", 1));
13047a984708SDavid Chisnall
13057a984708SDavid Chisnall case SIMPLE_HASH('a', 'n'):
13067a984708SDavid Chisnall /* operator & */
13077a984708SDavid Chisnall ddata->cur += 2;
13087a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "&", 1));
13097a984708SDavid Chisnall
13107a984708SDavid Chisnall case SIMPLE_HASH('a', 'N'):
13117a984708SDavid Chisnall /* operator &= */
13127a984708SDavid Chisnall ddata->cur += 2;
13137a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "&=", 2));
13147a984708SDavid Chisnall
13157a984708SDavid Chisnall case SIMPLE_HASH('a', 'S'):
13167a984708SDavid Chisnall /* operator = */
13177a984708SDavid Chisnall ddata->cur += 2;
13187a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "=", 1));
13197a984708SDavid Chisnall
13207a984708SDavid Chisnall case SIMPLE_HASH('c', 'l'):
13217a984708SDavid Chisnall /* operator () */
13227a984708SDavid Chisnall ddata->cur += 2;
13237a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "()", 2));
13247a984708SDavid Chisnall
13257a984708SDavid Chisnall case SIMPLE_HASH('c', 'm'):
13267a984708SDavid Chisnall /* operator , */
13277a984708SDavid Chisnall ddata->cur += 2;
13287a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, ",", 1));
13297a984708SDavid Chisnall
13307a984708SDavid Chisnall case SIMPLE_HASH('c', 'o'):
13317a984708SDavid Chisnall /* operator ~ */
13327a984708SDavid Chisnall ddata->cur += 2;
13337a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "~", 1));
13347a984708SDavid Chisnall
13357a984708SDavid Chisnall case SIMPLE_HASH('c', 'v'):
13367a984708SDavid Chisnall /* operator (cast) */
13377a984708SDavid Chisnall ddata->cur += 2;
13387a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "(cast)", 6));
13397a984708SDavid Chisnall
13407a984708SDavid Chisnall case SIMPLE_HASH('d', 'a'):
13417a984708SDavid Chisnall /* operator delete [] */
13427a984708SDavid Chisnall ddata->cur += 2;
13437a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "delete []", 9));
13447a984708SDavid Chisnall
13457a984708SDavid Chisnall case SIMPLE_HASH('d', 'e'):
13467a984708SDavid Chisnall /* operator * (unary) */
13477a984708SDavid Chisnall ddata->cur += 2;
13487a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "*", 1));
13497a984708SDavid Chisnall
13507a984708SDavid Chisnall case SIMPLE_HASH('d', 'l'):
13517a984708SDavid Chisnall /* operator delete */
13527a984708SDavid Chisnall ddata->cur += 2;
13537a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "delete", 6));
13547a984708SDavid Chisnall
13557a984708SDavid Chisnall case SIMPLE_HASH('d', 'v'):
13567a984708SDavid Chisnall /* operator / */
13577a984708SDavid Chisnall ddata->cur += 2;
13587a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "/", 1));
13597a984708SDavid Chisnall
13607a984708SDavid Chisnall case SIMPLE_HASH('d', 'V'):
13617a984708SDavid Chisnall /* operator /= */
13627a984708SDavid Chisnall ddata->cur += 2;
13637a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "/=", 2));
13647a984708SDavid Chisnall
13657a984708SDavid Chisnall case SIMPLE_HASH('e', 'o'):
13667a984708SDavid Chisnall /* operator ^ */
13677a984708SDavid Chisnall ddata->cur += 2;
13687a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "^", 1));
13697a984708SDavid Chisnall
13707a984708SDavid Chisnall case SIMPLE_HASH('e', 'O'):
13717a984708SDavid Chisnall /* operator ^= */
13727a984708SDavid Chisnall ddata->cur += 2;
13737a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "^=", 2));
13747a984708SDavid Chisnall
13757a984708SDavid Chisnall case SIMPLE_HASH('e', 'q'):
13767a984708SDavid Chisnall /* operator == */
13777a984708SDavid Chisnall ddata->cur += 2;
13787a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "==", 2));
13797a984708SDavid Chisnall
13807a984708SDavid Chisnall case SIMPLE_HASH('g', 'e'):
13817a984708SDavid Chisnall /* operator >= */
13827a984708SDavid Chisnall ddata->cur += 2;
13837a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, ">=", 2));
13847a984708SDavid Chisnall
13857a984708SDavid Chisnall case SIMPLE_HASH('g', 't'):
13867a984708SDavid Chisnall /* operator > */
13877a984708SDavid Chisnall ddata->cur += 2;
13887a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, ">", 1));
13897a984708SDavid Chisnall
13907a984708SDavid Chisnall case SIMPLE_HASH('i', 'x'):
13917a984708SDavid Chisnall /* operator [] */
13927a984708SDavid Chisnall ddata->cur += 2;
13937a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "[]", 2));
13947a984708SDavid Chisnall
13957a984708SDavid Chisnall case SIMPLE_HASH('l', 'e'):
13967a984708SDavid Chisnall /* operator <= */
13977a984708SDavid Chisnall ddata->cur += 2;
13987a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "<=", 2));
13997a984708SDavid Chisnall
14007a984708SDavid Chisnall case SIMPLE_HASH('l', 's'):
14017a984708SDavid Chisnall /* operator << */
14027a984708SDavid Chisnall ddata->cur += 2;
14037a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "<<", 2));
14047a984708SDavid Chisnall
14057a984708SDavid Chisnall case SIMPLE_HASH('l', 'S'):
14067a984708SDavid Chisnall /* operator <<= */
14077a984708SDavid Chisnall ddata->cur += 2;
14087a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "<<=", 3));
14097a984708SDavid Chisnall
14107a984708SDavid Chisnall case SIMPLE_HASH('l', 't'):
14117a984708SDavid Chisnall /* operator < */
14127a984708SDavid Chisnall ddata->cur += 2;
14137a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "<", 1));
14147a984708SDavid Chisnall
14157a984708SDavid Chisnall case SIMPLE_HASH('m', 'i'):
14167a984708SDavid Chisnall /* operator - */
14177a984708SDavid Chisnall ddata->cur += 2;
14187a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "-", 1));
14197a984708SDavid Chisnall
14207a984708SDavid Chisnall case SIMPLE_HASH('m', 'I'):
14217a984708SDavid Chisnall /* operator -= */
14227a984708SDavid Chisnall ddata->cur += 2;
14237a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "-=", 2));
14247a984708SDavid Chisnall
14257a984708SDavid Chisnall case SIMPLE_HASH('m', 'l'):
14267a984708SDavid Chisnall /* operator * */
14277a984708SDavid Chisnall ddata->cur += 2;
14287a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "*", 1));
14297a984708SDavid Chisnall
14307a984708SDavid Chisnall case SIMPLE_HASH('m', 'L'):
14317a984708SDavid Chisnall /* operator *= */
14327a984708SDavid Chisnall ddata->cur += 2;
14337a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "*=", 2));
14347a984708SDavid Chisnall
14357a984708SDavid Chisnall case SIMPLE_HASH('m', 'm'):
14367a984708SDavid Chisnall /* operator -- */
14377a984708SDavid Chisnall ddata->cur += 2;
14387a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "--", 2));
14397a984708SDavid Chisnall
14407a984708SDavid Chisnall case SIMPLE_HASH('n', 'a'):
14417a984708SDavid Chisnall /* operator new[] */
14427a984708SDavid Chisnall ddata->cur += 2;
14437a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "new []", 6));
14447a984708SDavid Chisnall
14457a984708SDavid Chisnall case SIMPLE_HASH('n', 'e'):
14467a984708SDavid Chisnall /* operator != */
14477a984708SDavid Chisnall ddata->cur += 2;
14487a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "!=", 2));
14497a984708SDavid Chisnall
14507a984708SDavid Chisnall case SIMPLE_HASH('n', 'g'):
14517a984708SDavid Chisnall /* operator - (unary) */
14527a984708SDavid Chisnall ddata->cur += 2;
14537a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "-", 1));
14547a984708SDavid Chisnall
14557a984708SDavid Chisnall case SIMPLE_HASH('n', 't'):
14567a984708SDavid Chisnall /* operator ! */
14577a984708SDavid Chisnall ddata->cur += 2;
14587a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "!", 1));
14597a984708SDavid Chisnall
14607a984708SDavid Chisnall case SIMPLE_HASH('n', 'w'):
14617a984708SDavid Chisnall /* operator new */
14627a984708SDavid Chisnall ddata->cur += 2;
14637a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "new", 3));
14647a984708SDavid Chisnall
14657a984708SDavid Chisnall case SIMPLE_HASH('o', 'o'):
14667a984708SDavid Chisnall /* operator || */
14677a984708SDavid Chisnall ddata->cur += 2;
14687a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "||", 2));
14697a984708SDavid Chisnall
14707a984708SDavid Chisnall case SIMPLE_HASH('o', 'r'):
14717a984708SDavid Chisnall /* operator | */
14727a984708SDavid Chisnall ddata->cur += 2;
14737a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "|", 1));
14747a984708SDavid Chisnall
14757a984708SDavid Chisnall case SIMPLE_HASH('o', 'R'):
14767a984708SDavid Chisnall /* operator |= */
14777a984708SDavid Chisnall ddata->cur += 2;
14787a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "|=", 2));
14797a984708SDavid Chisnall
14807a984708SDavid Chisnall case SIMPLE_HASH('p', 'l'):
14817a984708SDavid Chisnall /* operator + */
14827a984708SDavid Chisnall ddata->cur += 2;
14837a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "+", 1));
14847a984708SDavid Chisnall
14857a984708SDavid Chisnall case SIMPLE_HASH('p', 'L'):
14867a984708SDavid Chisnall /* operator += */
14877a984708SDavid Chisnall ddata->cur += 2;
14887a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "+=", 2));
14897a984708SDavid Chisnall
14907a984708SDavid Chisnall case SIMPLE_HASH('p', 'm'):
14917a984708SDavid Chisnall /* operator ->* */
14927a984708SDavid Chisnall ddata->cur += 2;
14937a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "->*", 3));
14947a984708SDavid Chisnall
14957a984708SDavid Chisnall case SIMPLE_HASH('p', 'p'):
14967a984708SDavid Chisnall /* operator ++ */
14977a984708SDavid Chisnall ddata->cur += 2;
14987a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "++", 2));
14997a984708SDavid Chisnall
15007a984708SDavid Chisnall case SIMPLE_HASH('p', 's'):
15017a984708SDavid Chisnall /* operator + (unary) */
15027a984708SDavid Chisnall ddata->cur += 2;
15037a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "+", 1));
15047a984708SDavid Chisnall
15057a984708SDavid Chisnall case SIMPLE_HASH('p', 't'):
15067a984708SDavid Chisnall /* operator -> */
15077a984708SDavid Chisnall ddata->cur += 2;
15087a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "->", 2));
15097a984708SDavid Chisnall
15107a984708SDavid Chisnall case SIMPLE_HASH('q', 'u'):
15117a984708SDavid Chisnall /* operator ? */
15127a984708SDavid Chisnall ddata->cur += 2;
15137a984708SDavid Chisnall return (cpp_demangle_read_expression_trinary(ddata, "?", 1,
15147a984708SDavid Chisnall ":", 1));
15157a984708SDavid Chisnall
15167a984708SDavid Chisnall case SIMPLE_HASH('r', 'm'):
15177a984708SDavid Chisnall /* operator % */
15187a984708SDavid Chisnall ddata->cur += 2;
15197a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "%", 1));
15207a984708SDavid Chisnall
15217a984708SDavid Chisnall case SIMPLE_HASH('r', 'M'):
15227a984708SDavid Chisnall /* operator %= */
15237a984708SDavid Chisnall ddata->cur += 2;
15247a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, "%=", 2));
15257a984708SDavid Chisnall
15267a984708SDavid Chisnall case SIMPLE_HASH('r', 's'):
15277a984708SDavid Chisnall /* operator >> */
15287a984708SDavid Chisnall ddata->cur += 2;
15297a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, ">>", 2));
15307a984708SDavid Chisnall
15317a984708SDavid Chisnall case SIMPLE_HASH('r', 'S'):
15327a984708SDavid Chisnall /* operator >>= */
15337a984708SDavid Chisnall ddata->cur += 2;
15347a984708SDavid Chisnall return (cpp_demangle_read_expression_binary(ddata, ">>=", 3));
15357a984708SDavid Chisnall
15367a984708SDavid Chisnall case SIMPLE_HASH('r', 'z'):
15377a984708SDavid Chisnall /* operator sizeof */
15387a984708SDavid Chisnall ddata->cur += 2;
15397a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
15407a984708SDavid Chisnall
15417a984708SDavid Chisnall case SIMPLE_HASH('s', 'v'):
15427a984708SDavid Chisnall /* operator sizeof */
15437a984708SDavid Chisnall ddata->cur += 2;
15447a984708SDavid Chisnall return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
15454a1f3708SDimitry Andric }
15467a984708SDavid Chisnall
15477a984708SDavid Chisnall switch (*ddata->cur) {
15487a984708SDavid Chisnall case 'L':
15497a984708SDavid Chisnall return (cpp_demangle_read_expr_primary(ddata));
15507a984708SDavid Chisnall case 'T':
15517a984708SDavid Chisnall return (cpp_demangle_read_tmpl_param(ddata));
15524a1f3708SDimitry Andric }
15537a984708SDavid Chisnall
15547a984708SDavid Chisnall return (0);
15557a984708SDavid Chisnall }
15567a984708SDavid Chisnall
15577a984708SDavid Chisnall static int
cpp_demangle_read_expression_flat(struct cpp_demangle_data * ddata,char ** str)1558fa7477ceSEd Maste cpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str)
1559fa7477ceSEd Maste {
1560fa7477ceSEd Maste struct vector_str *output;
1561fa7477ceSEd Maste size_t i, p_idx, idx, exp_len;
1562fa7477ceSEd Maste char *exp;
1563fa7477ceSEd Maste
1564a7941b33SDimitry Andric output = &ddata->output;
1565fa7477ceSEd Maste
1566fa7477ceSEd Maste p_idx = output->size;
1567fa7477ceSEd Maste
1568fa7477ceSEd Maste if (!cpp_demangle_read_expression(ddata))
1569fa7477ceSEd Maste return (0);
1570fa7477ceSEd Maste
1571fa7477ceSEd Maste if ((exp = vector_str_substr(output, p_idx, output->size - 1,
1572fa7477ceSEd Maste &exp_len)) == NULL)
1573fa7477ceSEd Maste return (0);
1574fa7477ceSEd Maste
1575fa7477ceSEd Maste idx = output->size;
1576fa7477ceSEd Maste for (i = p_idx; i < idx; ++i) {
1577fa7477ceSEd Maste if (!vector_str_pop(output)) {
1578fa7477ceSEd Maste free(exp);
1579fa7477ceSEd Maste return (0);
1580fa7477ceSEd Maste }
1581fa7477ceSEd Maste }
1582fa7477ceSEd Maste
1583fa7477ceSEd Maste *str = exp;
1584fa7477ceSEd Maste
1585fa7477ceSEd Maste return (1);
1586fa7477ceSEd Maste }
1587fa7477ceSEd Maste
1588fa7477ceSEd Maste static int
cpp_demangle_read_expression_binary(struct cpp_demangle_data * ddata,const char * name,size_t len)15897a984708SDavid Chisnall cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
15907a984708SDavid Chisnall const char *name, size_t len)
15917a984708SDavid Chisnall {
15927a984708SDavid Chisnall
15937a984708SDavid Chisnall if (ddata == NULL || name == NULL || len == 0)
15947a984708SDavid Chisnall return (0);
15957a984708SDavid Chisnall if (!cpp_demangle_read_expression(ddata))
15967a984708SDavid Chisnall return (0);
15977a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, name, len))
15987a984708SDavid Chisnall return (0);
15997a984708SDavid Chisnall
16007a984708SDavid Chisnall return (cpp_demangle_read_expression(ddata));
16017a984708SDavid Chisnall }
16027a984708SDavid Chisnall
16037a984708SDavid Chisnall static int
cpp_demangle_read_expression_unary(struct cpp_demangle_data * ddata,const char * name,size_t len)16047a984708SDavid Chisnall cpp_demangle_read_expression_unary(struct cpp_demangle_data *ddata,
16057a984708SDavid Chisnall const char *name, size_t len)
16067a984708SDavid Chisnall {
16077a984708SDavid Chisnall
16087a984708SDavid Chisnall if (ddata == NULL || name == NULL || len == 0)
16097a984708SDavid Chisnall return (0);
16107a984708SDavid Chisnall if (!cpp_demangle_read_expression(ddata))
16117a984708SDavid Chisnall return (0);
16127a984708SDavid Chisnall
16137a984708SDavid Chisnall return (cpp_demangle_push_str(ddata, name, len));
16147a984708SDavid Chisnall }
16157a984708SDavid Chisnall
16167a984708SDavid Chisnall static int
cpp_demangle_read_expression_trinary(struct cpp_demangle_data * ddata,const char * name1,size_t len1,const char * name2,size_t len2)16177a984708SDavid Chisnall cpp_demangle_read_expression_trinary(struct cpp_demangle_data *ddata,
16187a984708SDavid Chisnall const char *name1, size_t len1, const char *name2, size_t len2)
16197a984708SDavid Chisnall {
16207a984708SDavid Chisnall
16217a984708SDavid Chisnall if (ddata == NULL || name1 == NULL || len1 == 0 || name2 == NULL ||
16227a984708SDavid Chisnall len2 == 0)
16237a984708SDavid Chisnall return (0);
16247a984708SDavid Chisnall
16257a984708SDavid Chisnall if (!cpp_demangle_read_expression(ddata))
16267a984708SDavid Chisnall return (0);
16277a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, name1, len1))
16287a984708SDavid Chisnall return (0);
16297a984708SDavid Chisnall if (!cpp_demangle_read_expression(ddata))
16307a984708SDavid Chisnall return (0);
16317a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, name2, len2))
16327a984708SDavid Chisnall return (0);
16337a984708SDavid Chisnall
16347a984708SDavid Chisnall return (cpp_demangle_read_expression(ddata));
16357a984708SDavid Chisnall }
16367a984708SDavid Chisnall
16377a984708SDavid Chisnall static int
cpp_demangle_read_function(struct cpp_demangle_data * ddata,int * ext_c,struct vector_type_qualifier * v)16387a984708SDavid Chisnall cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
16397a984708SDavid Chisnall struct vector_type_qualifier *v)
16407a984708SDavid Chisnall {
1641a7941b33SDimitry Andric struct type_delimit td;
1642a7941b33SDimitry Andric struct read_cmd_item *rc;
16437a984708SDavid Chisnall size_t class_type_size, class_type_len, limit;
16447a984708SDavid Chisnall const char *class_type;
1645a7941b33SDimitry Andric int i;
1646a7941b33SDimitry Andric bool paren, non_cv_qualifier;
16477a984708SDavid Chisnall
16487a984708SDavid Chisnall if (ddata == NULL || *ddata->cur != 'F' || v == NULL)
16497a984708SDavid Chisnall return (0);
16507a984708SDavid Chisnall
16517a984708SDavid Chisnall ++ddata->cur;
16527a984708SDavid Chisnall if (*ddata->cur == 'Y') {
16537a984708SDavid Chisnall if (ext_c != NULL)
16547a984708SDavid Chisnall *ext_c = 1;
16557a984708SDavid Chisnall ++ddata->cur;
16567a984708SDavid Chisnall }
1657a7941b33SDimitry Andric
1658a7941b33SDimitry Andric /* Return type */
1659a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL))
16607a984708SDavid Chisnall return (0);
1661a7941b33SDimitry Andric
16627a984708SDavid Chisnall if (*ddata->cur != 'E') {
1663a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " "))
16647a984708SDavid Chisnall return (0);
1665a7941b33SDimitry Andric
1666a7941b33SDimitry Andric non_cv_qualifier = false;
1667a7941b33SDimitry Andric if (v->size > 0) {
1668a7941b33SDimitry Andric for (i = 0; (size_t) i < v->size; i++) {
1669a7941b33SDimitry Andric if (v->q_container[i] != TYPE_RST &&
1670a7941b33SDimitry Andric v->q_container[i] != TYPE_VAT &&
1671a7941b33SDimitry Andric v->q_container[i] != TYPE_CST) {
1672a7941b33SDimitry Andric non_cv_qualifier = true;
1673a7941b33SDimitry Andric break;
1674a7941b33SDimitry Andric }
1675a7941b33SDimitry Andric }
1676a7941b33SDimitry Andric }
1677a7941b33SDimitry Andric
1678a7941b33SDimitry Andric paren = false;
1679a7941b33SDimitry Andric rc = vector_read_cmd_find(&ddata->cmd, READ_PTRMEM);
1680a7941b33SDimitry Andric if (non_cv_qualifier || rc != NULL) {
1681a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "("))
1682a7941b33SDimitry Andric return (0);
1683a7941b33SDimitry Andric paren = true;
1684a7941b33SDimitry Andric }
1685a7941b33SDimitry Andric
1686a7941b33SDimitry Andric /* Push non-cv qualifiers. */
1687a7941b33SDimitry Andric ddata->push_qualifier = PUSH_NON_CV_QUALIFIER;
1688a7941b33SDimitry Andric if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
1689a7941b33SDimitry Andric return (0);
1690a7941b33SDimitry Andric
1691a7941b33SDimitry Andric if (rc) {
1692a7941b33SDimitry Andric if (non_cv_qualifier && !DEM_PUSH_STR(ddata, " "))
1693a7941b33SDimitry Andric return (0);
16947a984708SDavid Chisnall if ((class_type_size = ddata->class_type.size) == 0)
16957a984708SDavid Chisnall return (0);
16967a984708SDavid Chisnall class_type =
16977a984708SDavid Chisnall ddata->class_type.container[class_type_size - 1];
16987a984708SDavid Chisnall if (class_type == NULL)
16997a984708SDavid Chisnall return (0);
17007a984708SDavid Chisnall if ((class_type_len = strlen(class_type)) == 0)
17017a984708SDavid Chisnall return (0);
17027a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, class_type,
17037a984708SDavid Chisnall class_type_len))
17047a984708SDavid Chisnall return (0);
1705a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "::*"))
1706a7941b33SDimitry Andric return (0);
1707a7941b33SDimitry Andric /* Push pointer-to-member qualifiers. */
1708a7941b33SDimitry Andric ddata->push_qualifier = PUSH_ALL_QUALIFIER;
1709a7941b33SDimitry Andric if (!cpp_demangle_push_type_qualifier(ddata, rc->data,
1710a7941b33SDimitry Andric NULL))
17117a984708SDavid Chisnall return (0);
17127a984708SDavid Chisnall ++ddata->func_type;
17137a984708SDavid Chisnall }
17147a984708SDavid Chisnall
1715a7941b33SDimitry Andric if (paren) {
1716a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, ")"))
17177a984708SDavid Chisnall return (0);
1718a7941b33SDimitry Andric paren = false;
1719a7941b33SDimitry Andric }
17207a984708SDavid Chisnall
1721a7941b33SDimitry Andric td.paren = false;
1722a7941b33SDimitry Andric td.firstp = true;
17237a984708SDavid Chisnall limit = 0;
1724a7941b33SDimitry Andric ddata->is_functype = true;
17257a984708SDavid Chisnall for (;;) {
1726a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, &td))
17277a984708SDavid Chisnall return (0);
17287a984708SDavid Chisnall if (*ddata->cur == 'E')
17297a984708SDavid Chisnall break;
17307a984708SDavid Chisnall if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
17317a984708SDavid Chisnall return (0);
17327a984708SDavid Chisnall }
1733a7941b33SDimitry Andric ddata->is_functype = false;
1734a7941b33SDimitry Andric if (td.paren) {
1735a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, ")"))
17367a984708SDavid Chisnall return (0);
1737a7941b33SDimitry Andric td.paren = false;
1738a7941b33SDimitry Andric }
1739a7941b33SDimitry Andric
1740a7941b33SDimitry Andric /* Push CV qualifiers. */
1741a7941b33SDimitry Andric ddata->push_qualifier = PUSH_CV_QUALIFIER;
1742a7941b33SDimitry Andric if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
1743a7941b33SDimitry Andric return (0);
1744a7941b33SDimitry Andric
1745a7941b33SDimitry Andric ddata->push_qualifier = PUSH_ALL_QUALIFIER;
1746a7941b33SDimitry Andric
1747a7941b33SDimitry Andric /* Release type qualifier vector. */
17487a984708SDavid Chisnall vector_type_qualifier_dest(v);
17497a984708SDavid Chisnall if (!vector_type_qualifier_init(v))
17507a984708SDavid Chisnall return (0);
17517a984708SDavid Chisnall
1752a7941b33SDimitry Andric /* Push ref-qualifiers. */
1753a7941b33SDimitry Andric if (ddata->ref_qualifier) {
1754a7941b33SDimitry Andric switch (ddata->ref_qualifier_type) {
1755a7941b33SDimitry Andric case TYPE_REF:
1756a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " &"))
17577a984708SDavid Chisnall return (0);
1758a7941b33SDimitry Andric break;
1759a7941b33SDimitry Andric case TYPE_RREF:
1760a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " &&"))
1761a7941b33SDimitry Andric return (0);
1762a7941b33SDimitry Andric break;
1763a7941b33SDimitry Andric default:
1764a7941b33SDimitry Andric return (0);
1765a7941b33SDimitry Andric }
1766a7941b33SDimitry Andric ddata->ref_qualifier = false;
1767a7941b33SDimitry Andric }
17687a984708SDavid Chisnall }
17697a984708SDavid Chisnall
17707a984708SDavid Chisnall ++ddata->cur;
17717a984708SDavid Chisnall
17727a984708SDavid Chisnall return (1);
17737a984708SDavid Chisnall }
17747a984708SDavid Chisnall
17757a984708SDavid Chisnall /* read encoding, encoding are function name, data name, special-name */
17767a984708SDavid Chisnall static int
cpp_demangle_read_encoding(struct cpp_demangle_data * ddata)17777a984708SDavid Chisnall cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
17787a984708SDavid Chisnall {
1779fa7477ceSEd Maste char *name, *type, *num_str;
1780fa7477ceSEd Maste long offset;
1781fa7477ceSEd Maste int rtn;
17827a984708SDavid Chisnall
17837a984708SDavid Chisnall if (ddata == NULL || *ddata->cur == '\0')
17847a984708SDavid Chisnall return (0);
17857a984708SDavid Chisnall
17867a984708SDavid Chisnall /* special name */
17877a984708SDavid Chisnall switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
1788fa7477ceSEd Maste case SIMPLE_HASH('G', 'A'):
1789a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "hidden alias for "))
1790fa7477ceSEd Maste return (0);
1791fa7477ceSEd Maste ddata->cur += 2;
1792fa7477ceSEd Maste if (*ddata->cur == '\0')
1793fa7477ceSEd Maste return (0);
1794fa7477ceSEd Maste return (cpp_demangle_read_encoding(ddata));
1795fa7477ceSEd Maste
1796fa7477ceSEd Maste case SIMPLE_HASH('G', 'R'):
1797a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "reference temporary #"))
1798fa7477ceSEd Maste return (0);
1799fa7477ceSEd Maste ddata->cur += 2;
1800fa7477ceSEd Maste if (*ddata->cur == '\0')
1801fa7477ceSEd Maste return (0);
1802fa7477ceSEd Maste if (!cpp_demangle_read_name_flat(ddata, &name))
1803fa7477ceSEd Maste return (0);
1804fa7477ceSEd Maste rtn = 0;
1805fa7477ceSEd Maste if (!cpp_demangle_read_number_as_string(ddata, &num_str))
1806fa7477ceSEd Maste goto clean1;
1807a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, num_str))
1808fa7477ceSEd Maste goto clean2;
1809a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " for "))
1810fa7477ceSEd Maste goto clean2;
1811a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, name))
1812fa7477ceSEd Maste goto clean2;
1813fa7477ceSEd Maste rtn = 1;
1814fa7477ceSEd Maste clean2:
1815fa7477ceSEd Maste free(num_str);
1816fa7477ceSEd Maste clean1:
1817fa7477ceSEd Maste free(name);
1818fa7477ceSEd Maste return (rtn);
1819fa7477ceSEd Maste
1820fa7477ceSEd Maste case SIMPLE_HASH('G', 'T'):
1821fa7477ceSEd Maste ddata->cur += 2;
1822fa7477ceSEd Maste if (*ddata->cur == '\0')
1823fa7477ceSEd Maste return (0);
1824fa7477ceSEd Maste switch (*ddata->cur) {
1825fa7477ceSEd Maste case 'n':
1826a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "non-transaction clone for "))
1827fa7477ceSEd Maste return (0);
18284a1f3708SDimitry Andric break;
1829fa7477ceSEd Maste case 't':
1830fa7477ceSEd Maste default:
1831a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "transaction clone for "))
1832fa7477ceSEd Maste return (0);
18334a1f3708SDimitry Andric break;
1834fa7477ceSEd Maste }
1835fa7477ceSEd Maste ++ddata->cur;
1836fa7477ceSEd Maste return (cpp_demangle_read_encoding(ddata));
1837fa7477ceSEd Maste
18387a984708SDavid Chisnall case SIMPLE_HASH('G', 'V'):
18397a984708SDavid Chisnall /* sentry object for 1 time init */
1840a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "guard variable for "))
18417a984708SDavid Chisnall return (0);
18427a984708SDavid Chisnall ddata->cur += 2;
18437a984708SDavid Chisnall break;
18447a984708SDavid Chisnall
18457a984708SDavid Chisnall case SIMPLE_HASH('T', 'c'):
18467a984708SDavid Chisnall /* virtual function covariant override thunk */
1847a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata,
1848a7941b33SDimitry Andric "virtual function covariant override "))
18497a984708SDavid Chisnall return (0);
18507a984708SDavid Chisnall ddata->cur += 2;
18517a984708SDavid Chisnall if (*ddata->cur == '\0')
18527a984708SDavid Chisnall return (0);
18537a984708SDavid Chisnall if (!cpp_demangle_read_offset(ddata))
18547a984708SDavid Chisnall return (0);
18557a984708SDavid Chisnall if (!cpp_demangle_read_offset(ddata))
18567a984708SDavid Chisnall return (0);
18577a984708SDavid Chisnall return (cpp_demangle_read_encoding(ddata));
18587a984708SDavid Chisnall
1859fa7477ceSEd Maste case SIMPLE_HASH('T', 'C'):
1860fa7477ceSEd Maste /* construction vtable */
1861a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "construction vtable for "))
1862fa7477ceSEd Maste return (0);
1863fa7477ceSEd Maste ddata->cur += 2;
1864fa7477ceSEd Maste if (*ddata->cur == '\0')
1865fa7477ceSEd Maste return (0);
1866fa7477ceSEd Maste if (!cpp_demangle_read_type_flat(ddata, &type))
1867fa7477ceSEd Maste return (0);
1868fa7477ceSEd Maste rtn = 0;
1869fa7477ceSEd Maste if (!cpp_demangle_read_number(ddata, &offset))
1870fa7477ceSEd Maste goto clean3;
1871fa7477ceSEd Maste if (*ddata->cur++ != '_')
1872fa7477ceSEd Maste goto clean3;
1873a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL))
1874fa7477ceSEd Maste goto clean3;
1875a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "-in-"))
1876fa7477ceSEd Maste goto clean3;
1877a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, type))
1878fa7477ceSEd Maste goto clean3;
1879fa7477ceSEd Maste rtn = 1;
1880fa7477ceSEd Maste clean3:
1881fa7477ceSEd Maste free(type);
1882fa7477ceSEd Maste return (rtn);
1883fa7477ceSEd Maste
18847a984708SDavid Chisnall case SIMPLE_HASH('T', 'D'):
18857a984708SDavid Chisnall /* typeinfo common proxy */
18867a984708SDavid Chisnall break;
18877a984708SDavid Chisnall
1888fa7477ceSEd Maste case SIMPLE_HASH('T', 'F'):
1889fa7477ceSEd Maste /* typeinfo fn */
1890a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "typeinfo fn for "))
1891fa7477ceSEd Maste return (0);
1892fa7477ceSEd Maste ddata->cur += 2;
1893fa7477ceSEd Maste if (*ddata->cur == '\0')
1894fa7477ceSEd Maste return (0);
1895a7941b33SDimitry Andric return (cpp_demangle_read_type(ddata, NULL));
1896fa7477ceSEd Maste
18977a984708SDavid Chisnall case SIMPLE_HASH('T', 'h'):
18987a984708SDavid Chisnall /* virtual function non-virtual override thunk */
1899a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata,
1900a7941b33SDimitry Andric "virtual function non-virtual override "))
19017a984708SDavid Chisnall return (0);
19027a984708SDavid Chisnall ddata->cur += 2;
19037a984708SDavid Chisnall if (*ddata->cur == '\0')
19047a984708SDavid Chisnall return (0);
19057a984708SDavid Chisnall if (!cpp_demangle_read_nv_offset(ddata))
19067a984708SDavid Chisnall return (0);
19077a984708SDavid Chisnall return (cpp_demangle_read_encoding(ddata));
19087a984708SDavid Chisnall
1909fa7477ceSEd Maste case SIMPLE_HASH('T', 'H'):
1910fa7477ceSEd Maste /* TLS init function */
1911a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "TLS init function for "))
19127a984708SDavid Chisnall return (0);
19137a984708SDavid Chisnall ddata->cur += 2;
19147a984708SDavid Chisnall if (*ddata->cur == '\0')
19157a984708SDavid Chisnall return (0);
1916fa7477ceSEd Maste break;
1917fa7477ceSEd Maste
1918fa7477ceSEd Maste case SIMPLE_HASH('T', 'I'):
1919fa7477ceSEd Maste /* typeinfo structure */
1920a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "typeinfo for "))
1921fa7477ceSEd Maste return (0);
1922fa7477ceSEd Maste ddata->cur += 2;
1923fa7477ceSEd Maste if (*ddata->cur == '\0')
1924fa7477ceSEd Maste return (0);
1925a7941b33SDimitry Andric return (cpp_demangle_read_type(ddata, NULL));
1926fa7477ceSEd Maste
1927fa7477ceSEd Maste case SIMPLE_HASH('T', 'J'):
1928fa7477ceSEd Maste /* java class */
1929a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "java Class for "))
1930fa7477ceSEd Maste return (0);
1931fa7477ceSEd Maste ddata->cur += 2;
1932fa7477ceSEd Maste if (*ddata->cur == '\0')
1933fa7477ceSEd Maste return (0);
1934a7941b33SDimitry Andric return (cpp_demangle_read_type(ddata, NULL));
1935fa7477ceSEd Maste
1936fa7477ceSEd Maste case SIMPLE_HASH('T', 'S'):
1937fa7477ceSEd Maste /* RTTI name (NTBS) */
1938a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "typeinfo name for "))
1939fa7477ceSEd Maste return (0);
1940fa7477ceSEd Maste ddata->cur += 2;
1941fa7477ceSEd Maste if (*ddata->cur == '\0')
1942fa7477ceSEd Maste return (0);
1943a7941b33SDimitry Andric return (cpp_demangle_read_type(ddata, NULL));
19447a984708SDavid Chisnall
19457a984708SDavid Chisnall case SIMPLE_HASH('T', 'T'):
19467a984708SDavid Chisnall /* VTT table */
1947a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "VTT for "))
19487a984708SDavid Chisnall return (0);
19497a984708SDavid Chisnall ddata->cur += 2;
1950fa7477ceSEd Maste if (*ddata->cur == '\0')
1951fa7477ceSEd Maste return (0);
1952a7941b33SDimitry Andric return (cpp_demangle_read_type(ddata, NULL));
19537a984708SDavid Chisnall
19547a984708SDavid Chisnall case SIMPLE_HASH('T', 'v'):
19557a984708SDavid Chisnall /* virtual function virtual override thunk */
1956a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "virtual function virtual override "))
19577a984708SDavid Chisnall return (0);
19587a984708SDavid Chisnall ddata->cur += 2;
19597a984708SDavid Chisnall if (*ddata->cur == '\0')
19607a984708SDavid Chisnall return (0);
19617a984708SDavid Chisnall if (!cpp_demangle_read_v_offset(ddata))
19627a984708SDavid Chisnall return (0);
19637a984708SDavid Chisnall return (cpp_demangle_read_encoding(ddata));
19647a984708SDavid Chisnall
19657a984708SDavid Chisnall case SIMPLE_HASH('T', 'V'):
19667a984708SDavid Chisnall /* virtual table */
1967a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "vtable for "))
19687a984708SDavid Chisnall return (0);
19697a984708SDavid Chisnall ddata->cur += 2;
19707a984708SDavid Chisnall if (*ddata->cur == '\0')
19717a984708SDavid Chisnall return (0);
1972a7941b33SDimitry Andric return (cpp_demangle_read_type(ddata, NULL));
1973fa7477ceSEd Maste
1974fa7477ceSEd Maste case SIMPLE_HASH('T', 'W'):
1975fa7477ceSEd Maste /* TLS wrapper function */
1976a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "TLS wrapper function for "))
1977fa7477ceSEd Maste return (0);
1978fa7477ceSEd Maste ddata->cur += 2;
1979fa7477ceSEd Maste if (*ddata->cur == '\0')
1980fa7477ceSEd Maste return (0);
1981fa7477ceSEd Maste break;
19824a1f3708SDimitry Andric }
19837a984708SDavid Chisnall
19847a984708SDavid Chisnall return (cpp_demangle_read_name(ddata));
19857a984708SDavid Chisnall }
19867a984708SDavid Chisnall
19877a984708SDavid Chisnall static int
cpp_demangle_read_local_name(struct cpp_demangle_data * ddata)19887a984708SDavid Chisnall cpp_demangle_read_local_name(struct cpp_demangle_data *ddata)
19897a984708SDavid Chisnall {
1990a7941b33SDimitry Andric struct vector_str local_name;
1991a7941b33SDimitry Andric struct type_delimit td;
19927a984708SDavid Chisnall size_t limit;
1993a7941b33SDimitry Andric bool more_type;
19947a984708SDavid Chisnall
19957a984708SDavid Chisnall if (ddata == NULL)
19967a984708SDavid Chisnall return (0);
19977a984708SDavid Chisnall if (*(++ddata->cur) == '\0')
19987a984708SDavid Chisnall return (0);
19997a984708SDavid Chisnall
2000a7941b33SDimitry Andric if (!vector_str_init(&local_name))
20017a984708SDavid Chisnall return (0);
2002a7941b33SDimitry Andric ddata->cur_output = &local_name;
2003a7941b33SDimitry Andric
2004a7941b33SDimitry Andric if (!cpp_demangle_read_encoding(ddata)) {
2005a7941b33SDimitry Andric vector_str_dest(&local_name);
2006a7941b33SDimitry Andric return (0);
2007a7941b33SDimitry Andric }
2008a7941b33SDimitry Andric
2009a7941b33SDimitry Andric ddata->cur_output = &ddata->output;
2010a7941b33SDimitry Andric
2011a7941b33SDimitry Andric td.paren = false;
2012a7941b33SDimitry Andric td.firstp = true;
2013a7941b33SDimitry Andric more_type = false;
2014a7941b33SDimitry Andric limit = 0;
2015a7941b33SDimitry Andric
2016a7941b33SDimitry Andric /*
2017a7941b33SDimitry Andric * The first type is a return type if we just demangled template
2018a7941b33SDimitry Andric * args. (the template args is right next to the function name,
2019a7941b33SDimitry Andric * which means it's a template function)
2020a7941b33SDimitry Andric */
2021a7941b33SDimitry Andric if (ddata->is_tmpl) {
2022a7941b33SDimitry Andric ddata->is_tmpl = false;
2023a7941b33SDimitry Andric
2024a7941b33SDimitry Andric /* Read return type */
2025a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL)) {
2026a7941b33SDimitry Andric vector_str_dest(&local_name);
2027a7941b33SDimitry Andric return (0);
2028a7941b33SDimitry Andric }
2029a7941b33SDimitry Andric
2030a7941b33SDimitry Andric more_type = true;
2031a7941b33SDimitry Andric }
2032a7941b33SDimitry Andric
2033a7941b33SDimitry Andric /* Now we can push the name after possible return type is handled. */
2034a7941b33SDimitry Andric if (!vector_str_push_vector(&ddata->output, &local_name)) {
2035a7941b33SDimitry Andric vector_str_dest(&local_name);
2036a7941b33SDimitry Andric return (0);
2037a7941b33SDimitry Andric }
2038a7941b33SDimitry Andric vector_str_dest(&local_name);
2039a7941b33SDimitry Andric
2040a7941b33SDimitry Andric while (*ddata->cur != '\0') {
2041a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, &td))
2042a7941b33SDimitry Andric return (0);
2043a7941b33SDimitry Andric if (more_type)
2044a7941b33SDimitry Andric more_type = false;
20457a984708SDavid Chisnall if (*ddata->cur == 'E')
20467a984708SDavid Chisnall break;
20477a984708SDavid Chisnall if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
20487a984708SDavid Chisnall return (0);
20497a984708SDavid Chisnall }
2050a7941b33SDimitry Andric if (more_type)
2051a7941b33SDimitry Andric return (0);
2052a7941b33SDimitry Andric
20537a984708SDavid Chisnall if (*(++ddata->cur) == '\0')
20547a984708SDavid Chisnall return (0);
2055a7941b33SDimitry Andric if (td.paren == true) {
2056a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, ")"))
20577a984708SDavid Chisnall return (0);
2058a7941b33SDimitry Andric td.paren = false;
20597a984708SDavid Chisnall }
20607a984708SDavid Chisnall if (*ddata->cur == 's')
20617a984708SDavid Chisnall ++ddata->cur;
20627a984708SDavid Chisnall else {
2063a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "::"))
20647a984708SDavid Chisnall return (0);
20657a984708SDavid Chisnall if (!cpp_demangle_read_name(ddata))
20667a984708SDavid Chisnall return (0);
20677a984708SDavid Chisnall }
20687a984708SDavid Chisnall if (*ddata->cur == '_') {
20697a984708SDavid Chisnall ++ddata->cur;
20707a984708SDavid Chisnall while (ELFTC_ISDIGIT(*ddata->cur) != 0)
20717a984708SDavid Chisnall ++ddata->cur;
20727a984708SDavid Chisnall }
20737a984708SDavid Chisnall
20747a984708SDavid Chisnall return (1);
20757a984708SDavid Chisnall }
20767a984708SDavid Chisnall
20777a984708SDavid Chisnall static int
cpp_demangle_read_name(struct cpp_demangle_data * ddata)20787a984708SDavid Chisnall cpp_demangle_read_name(struct cpp_demangle_data *ddata)
20797a984708SDavid Chisnall {
20807a984708SDavid Chisnall struct vector_str *output, v;
20817a984708SDavid Chisnall size_t p_idx, subst_str_len;
20827a984708SDavid Chisnall int rtn;
20837a984708SDavid Chisnall char *subst_str;
20847a984708SDavid Chisnall
20857a984708SDavid Chisnall if (ddata == NULL || *ddata->cur == '\0')
20867a984708SDavid Chisnall return (0);
20877a984708SDavid Chisnall
2088a7941b33SDimitry Andric output = ddata->cur_output;
20897a984708SDavid Chisnall
20907a984708SDavid Chisnall subst_str = NULL;
20917a984708SDavid Chisnall
20927a984708SDavid Chisnall switch (*ddata->cur) {
20937a984708SDavid Chisnall case 'S':
20947a984708SDavid Chisnall return (cpp_demangle_read_subst(ddata));
20957a984708SDavid Chisnall case 'N':
20967a984708SDavid Chisnall return (cpp_demangle_read_nested_name(ddata));
20977a984708SDavid Chisnall case 'Z':
20987a984708SDavid Chisnall return (cpp_demangle_read_local_name(ddata));
20994a1f3708SDimitry Andric }
21007a984708SDavid Chisnall
21017a984708SDavid Chisnall if (!vector_str_init(&v))
21027a984708SDavid Chisnall return (0);
21037a984708SDavid Chisnall
21047a984708SDavid Chisnall p_idx = output->size;
21057a984708SDavid Chisnall rtn = 0;
21067a984708SDavid Chisnall if (!cpp_demangle_read_uqname(ddata))
21077a984708SDavid Chisnall goto clean;
21087a984708SDavid Chisnall if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
21097a984708SDavid Chisnall &subst_str_len)) == NULL)
21107a984708SDavid Chisnall goto clean;
21117a984708SDavid Chisnall if (subst_str_len > 8 && strstr(subst_str, "operator") != NULL) {
21127a984708SDavid Chisnall rtn = 1;
21137a984708SDavid Chisnall goto clean;
21147a984708SDavid Chisnall }
21157a984708SDavid Chisnall if (!vector_str_push(&v, subst_str, subst_str_len))
21167a984708SDavid Chisnall goto clean;
21177a984708SDavid Chisnall if (!cpp_demangle_push_subst_v(ddata, &v))
21187a984708SDavid Chisnall goto clean;
21197a984708SDavid Chisnall
21207a984708SDavid Chisnall if (*ddata->cur == 'I') {
21217a984708SDavid Chisnall p_idx = output->size;
21227a984708SDavid Chisnall if (!cpp_demangle_read_tmpl_args(ddata))
21237a984708SDavid Chisnall goto clean;
21247a984708SDavid Chisnall free(subst_str);
21257a984708SDavid Chisnall if ((subst_str = vector_str_substr(output, p_idx,
21267a984708SDavid Chisnall output->size - 1, &subst_str_len)) == NULL)
21277a984708SDavid Chisnall goto clean;
21287a984708SDavid Chisnall if (!vector_str_push(&v, subst_str, subst_str_len))
21297a984708SDavid Chisnall goto clean;
21307a984708SDavid Chisnall if (!cpp_demangle_push_subst_v(ddata, &v))
21317a984708SDavid Chisnall goto clean;
21327a984708SDavid Chisnall }
21337a984708SDavid Chisnall
21347a984708SDavid Chisnall rtn = 1;
21357a984708SDavid Chisnall
21367a984708SDavid Chisnall clean:
21377a984708SDavid Chisnall free(subst_str);
21387a984708SDavid Chisnall vector_str_dest(&v);
21397a984708SDavid Chisnall
21407a984708SDavid Chisnall return (rtn);
21417a984708SDavid Chisnall }
21427a984708SDavid Chisnall
21437a984708SDavid Chisnall static int
cpp_demangle_read_name_flat(struct cpp_demangle_data * ddata,char ** str)2144fa7477ceSEd Maste cpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str)
2145fa7477ceSEd Maste {
2146fa7477ceSEd Maste struct vector_str *output;
2147fa7477ceSEd Maste size_t i, p_idx, idx, name_len;
2148fa7477ceSEd Maste char *name;
2149fa7477ceSEd Maste
2150a7941b33SDimitry Andric output = ddata->cur_output;
2151fa7477ceSEd Maste
2152fa7477ceSEd Maste p_idx = output->size;
2153fa7477ceSEd Maste
2154fa7477ceSEd Maste if (!cpp_demangle_read_name(ddata))
2155fa7477ceSEd Maste return (0);
2156fa7477ceSEd Maste
2157fa7477ceSEd Maste if ((name = vector_str_substr(output, p_idx, output->size - 1,
2158fa7477ceSEd Maste &name_len)) == NULL)
2159fa7477ceSEd Maste return (0);
2160fa7477ceSEd Maste
2161fa7477ceSEd Maste idx = output->size;
2162fa7477ceSEd Maste for (i = p_idx; i < idx; ++i) {
2163fa7477ceSEd Maste if (!vector_str_pop(output)) {
2164fa7477ceSEd Maste free(name);
2165fa7477ceSEd Maste return (0);
2166fa7477ceSEd Maste }
2167fa7477ceSEd Maste }
2168fa7477ceSEd Maste
2169fa7477ceSEd Maste *str = name;
2170fa7477ceSEd Maste
2171fa7477ceSEd Maste return (1);
2172fa7477ceSEd Maste }
2173fa7477ceSEd Maste
2174fa7477ceSEd Maste static int
cpp_demangle_read_nested_name(struct cpp_demangle_data * ddata)21757a984708SDavid Chisnall cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
21767a984708SDavid Chisnall {
21777a984708SDavid Chisnall struct vector_str *output, v;
21787a984708SDavid Chisnall size_t limit, p_idx, subst_str_len;
21797a984708SDavid Chisnall int rtn;
21807a984708SDavid Chisnall char *subst_str;
21817a984708SDavid Chisnall
21827a984708SDavid Chisnall if (ddata == NULL || *ddata->cur != 'N')
21837a984708SDavid Chisnall return (0);
21847a984708SDavid Chisnall if (*(++ddata->cur) == '\0')
21857a984708SDavid Chisnall return (0);
21867a984708SDavid Chisnall
2187a7941b33SDimitry Andric do {
21887a984708SDavid Chisnall switch (*ddata->cur) {
21897a984708SDavid Chisnall case 'r':
21907a984708SDavid Chisnall ddata->mem_rst = true;
21917a984708SDavid Chisnall break;
21927a984708SDavid Chisnall case 'V':
21937a984708SDavid Chisnall ddata->mem_vat = true;
21947a984708SDavid Chisnall break;
21957a984708SDavid Chisnall case 'K':
21967a984708SDavid Chisnall ddata->mem_cst = true;
21977a984708SDavid Chisnall break;
2198a7941b33SDimitry Andric case 'R':
2199a7941b33SDimitry Andric ddata->mem_ref = true;
2200a7941b33SDimitry Andric break;
2201a7941b33SDimitry Andric case 'O':
2202a7941b33SDimitry Andric ddata->mem_rref = true;
2203a7941b33SDimitry Andric break;
2204a7941b33SDimitry Andric default:
2205a7941b33SDimitry Andric goto next;
22064a1f3708SDimitry Andric }
2207a7941b33SDimitry Andric } while (*(++ddata->cur));
22087a984708SDavid Chisnall
2209a7941b33SDimitry Andric next:
2210a7941b33SDimitry Andric output = ddata->cur_output;
22117a984708SDavid Chisnall if (!vector_str_init(&v))
22127a984708SDavid Chisnall return (0);
22137a984708SDavid Chisnall
22147a984708SDavid Chisnall rtn = 0;
22157a984708SDavid Chisnall limit = 0;
22167a984708SDavid Chisnall for (;;) {
22177a984708SDavid Chisnall p_idx = output->size;
22187a984708SDavid Chisnall switch (*ddata->cur) {
22197a984708SDavid Chisnall case 'I':
22207a984708SDavid Chisnall if (!cpp_demangle_read_tmpl_args(ddata))
22217a984708SDavid Chisnall goto clean;
22227a984708SDavid Chisnall break;
22237a984708SDavid Chisnall case 'S':
22247a984708SDavid Chisnall if (!cpp_demangle_read_subst(ddata))
22257a984708SDavid Chisnall goto clean;
22267a984708SDavid Chisnall break;
22277a984708SDavid Chisnall case 'T':
22287a984708SDavid Chisnall if (!cpp_demangle_read_tmpl_param(ddata))
22297a984708SDavid Chisnall goto clean;
22307a984708SDavid Chisnall break;
22317a984708SDavid Chisnall default:
22327a984708SDavid Chisnall if (!cpp_demangle_read_uqname(ddata))
22337a984708SDavid Chisnall goto clean;
22344a1f3708SDimitry Andric }
22357a984708SDavid Chisnall
2236a7941b33SDimitry Andric if (p_idx == output->size)
2237a7941b33SDimitry Andric goto next_comp;
22387a984708SDavid Chisnall if ((subst_str = vector_str_substr(output, p_idx,
22397a984708SDavid Chisnall output->size - 1, &subst_str_len)) == NULL)
22407a984708SDavid Chisnall goto clean;
22417a984708SDavid Chisnall if (!vector_str_push(&v, subst_str, subst_str_len)) {
22427a984708SDavid Chisnall free(subst_str);
22437a984708SDavid Chisnall goto clean;
22447a984708SDavid Chisnall }
22457a984708SDavid Chisnall free(subst_str);
22467a984708SDavid Chisnall
22477a984708SDavid Chisnall if (!cpp_demangle_push_subst_v(ddata, &v))
22487a984708SDavid Chisnall goto clean;
2249a7941b33SDimitry Andric
2250a7941b33SDimitry Andric next_comp:
22517a984708SDavid Chisnall if (*ddata->cur == 'E')
22527a984708SDavid Chisnall break;
2253a7941b33SDimitry Andric else if (*ddata->cur != 'I' && *ddata->cur != 'C' &&
2254a7941b33SDimitry Andric *ddata->cur != 'D' && p_idx != output->size) {
2255a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "::"))
22567a984708SDavid Chisnall goto clean;
2257a7941b33SDimitry Andric if (!VEC_PUSH_STR(&v, "::"))
22587a984708SDavid Chisnall goto clean;
22597a984708SDavid Chisnall }
22607a984708SDavid Chisnall if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
22617a984708SDavid Chisnall goto clean;
22627a984708SDavid Chisnall }
22637a984708SDavid Chisnall
22647a984708SDavid Chisnall ++ddata->cur;
22657a984708SDavid Chisnall rtn = 1;
22667a984708SDavid Chisnall
22677a984708SDavid Chisnall clean:
22687a984708SDavid Chisnall vector_str_dest(&v);
22697a984708SDavid Chisnall
22707a984708SDavid Chisnall return (rtn);
22717a984708SDavid Chisnall }
22727a984708SDavid Chisnall
22737a984708SDavid Chisnall /*
22747a984708SDavid Chisnall * read number
22757a984708SDavid Chisnall * number ::= [n] <decimal>
22767a984708SDavid Chisnall */
22777a984708SDavid Chisnall static int
cpp_demangle_read_number(struct cpp_demangle_data * ddata,long * rtn)22787a984708SDavid Chisnall cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
22797a984708SDavid Chisnall {
22807a984708SDavid Chisnall long len, negative_factor;
22817a984708SDavid Chisnall
22827a984708SDavid Chisnall if (ddata == NULL || rtn == NULL)
22837a984708SDavid Chisnall return (0);
22847a984708SDavid Chisnall
22857a984708SDavid Chisnall negative_factor = 1;
22867a984708SDavid Chisnall if (*ddata->cur == 'n') {
22877a984708SDavid Chisnall negative_factor = -1;
22887a984708SDavid Chisnall
22897a984708SDavid Chisnall ++ddata->cur;
22907a984708SDavid Chisnall }
22917a984708SDavid Chisnall if (ELFTC_ISDIGIT(*ddata->cur) == 0)
22927a984708SDavid Chisnall return (0);
22937a984708SDavid Chisnall
22947a984708SDavid Chisnall errno = 0;
22957a984708SDavid Chisnall if ((len = strtol(ddata->cur, (char **) NULL, 10)) == 0 &&
22967a984708SDavid Chisnall errno != 0)
22977a984708SDavid Chisnall return (0);
22987a984708SDavid Chisnall
22997a984708SDavid Chisnall while (ELFTC_ISDIGIT(*ddata->cur) != 0)
23007a984708SDavid Chisnall ++ddata->cur;
23017a984708SDavid Chisnall
23027a984708SDavid Chisnall assert(len >= 0);
23037a984708SDavid Chisnall assert(negative_factor == 1 || negative_factor == -1);
23047a984708SDavid Chisnall
23057a984708SDavid Chisnall *rtn = len * negative_factor;
23067a984708SDavid Chisnall
23077a984708SDavid Chisnall return (1);
23087a984708SDavid Chisnall }
23097a984708SDavid Chisnall
23107a984708SDavid Chisnall static int
cpp_demangle_read_number_as_string(struct cpp_demangle_data * ddata,char ** str)2311fa7477ceSEd Maste cpp_demangle_read_number_as_string(struct cpp_demangle_data *ddata, char **str)
2312fa7477ceSEd Maste {
2313fa7477ceSEd Maste long n;
2314fa7477ceSEd Maste
2315fa7477ceSEd Maste if (!cpp_demangle_read_number(ddata, &n)) {
2316fa7477ceSEd Maste *str = NULL;
2317fa7477ceSEd Maste return (0);
2318fa7477ceSEd Maste }
2319fa7477ceSEd Maste
2320fa7477ceSEd Maste if (asprintf(str, "%ld", n) < 0) {
2321fa7477ceSEd Maste *str = NULL;
2322fa7477ceSEd Maste return (0);
2323fa7477ceSEd Maste }
2324fa7477ceSEd Maste
2325fa7477ceSEd Maste return (1);
2326fa7477ceSEd Maste }
2327fa7477ceSEd Maste
2328fa7477ceSEd Maste static int
cpp_demangle_read_nv_offset(struct cpp_demangle_data * ddata)23297a984708SDavid Chisnall cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
23307a984708SDavid Chisnall {
23317a984708SDavid Chisnall
23327a984708SDavid Chisnall if (ddata == NULL)
23337a984708SDavid Chisnall return (0);
23347a984708SDavid Chisnall
2335a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "offset : "))
23367a984708SDavid Chisnall return (0);
23377a984708SDavid Chisnall
23387a984708SDavid Chisnall return (cpp_demangle_read_offset_number(ddata));
23397a984708SDavid Chisnall }
23407a984708SDavid Chisnall
23417a984708SDavid Chisnall /* read offset, offset are nv-offset, v-offset */
23427a984708SDavid Chisnall static int
cpp_demangle_read_offset(struct cpp_demangle_data * ddata)23437a984708SDavid Chisnall cpp_demangle_read_offset(struct cpp_demangle_data *ddata)
23447a984708SDavid Chisnall {
23457a984708SDavid Chisnall
23467a984708SDavid Chisnall if (ddata == NULL)
23477a984708SDavid Chisnall return (0);
23487a984708SDavid Chisnall
23497a984708SDavid Chisnall if (*ddata->cur == 'h') {
23507a984708SDavid Chisnall ++ddata->cur;
23517a984708SDavid Chisnall return (cpp_demangle_read_nv_offset(ddata));
23527a984708SDavid Chisnall } else if (*ddata->cur == 'v') {
23537a984708SDavid Chisnall ++ddata->cur;
23547a984708SDavid Chisnall return (cpp_demangle_read_v_offset(ddata));
23557a984708SDavid Chisnall }
23567a984708SDavid Chisnall
23577a984708SDavid Chisnall return (0);
23587a984708SDavid Chisnall }
23597a984708SDavid Chisnall
23607a984708SDavid Chisnall static int
cpp_demangle_read_offset_number(struct cpp_demangle_data * ddata)23617a984708SDavid Chisnall cpp_demangle_read_offset_number(struct cpp_demangle_data *ddata)
23627a984708SDavid Chisnall {
23637a984708SDavid Chisnall bool negative;
23647a984708SDavid Chisnall const char *start;
23657a984708SDavid Chisnall
23667a984708SDavid Chisnall if (ddata == NULL || *ddata->cur == '\0')
23677a984708SDavid Chisnall return (0);
23687a984708SDavid Chisnall
23697a984708SDavid Chisnall /* offset could be negative */
23707a984708SDavid Chisnall if (*ddata->cur == 'n') {
23717a984708SDavid Chisnall negative = true;
23727a984708SDavid Chisnall start = ddata->cur + 1;
23737a984708SDavid Chisnall } else {
23747a984708SDavid Chisnall negative = false;
23757a984708SDavid Chisnall start = ddata->cur;
23767a984708SDavid Chisnall }
23777a984708SDavid Chisnall
23787a984708SDavid Chisnall while (*ddata->cur != '_')
23797a984708SDavid Chisnall ++ddata->cur;
23807a984708SDavid Chisnall
2381a7941b33SDimitry Andric if (negative && !DEM_PUSH_STR(ddata, "-"))
23827a984708SDavid Chisnall return (0);
23837a984708SDavid Chisnall
23847a984708SDavid Chisnall assert(start != NULL);
23857a984708SDavid Chisnall
23867a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, start, ddata->cur - start))
23877a984708SDavid Chisnall return (0);
2388a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " "))
23897a984708SDavid Chisnall return (0);
23907a984708SDavid Chisnall
23917a984708SDavid Chisnall ++ddata->cur;
23927a984708SDavid Chisnall
23937a984708SDavid Chisnall return (1);
23947a984708SDavid Chisnall }
23957a984708SDavid Chisnall
23967a984708SDavid Chisnall static int
cpp_demangle_read_pointer_to_member(struct cpp_demangle_data * ddata,struct vector_type_qualifier * v)2397a7941b33SDimitry Andric cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata,
2398a7941b33SDimitry Andric struct vector_type_qualifier *v)
23997a984708SDavid Chisnall {
24007a984708SDavid Chisnall size_t class_type_len, i, idx, p_idx;
24017a984708SDavid Chisnall int p_func_type, rtn;
24027a984708SDavid Chisnall char *class_type;
24037a984708SDavid Chisnall
24047a984708SDavid Chisnall if (ddata == NULL || *ddata->cur != 'M' || *(++ddata->cur) == '\0')
24057a984708SDavid Chisnall return (0);
24067a984708SDavid Chisnall
24077a984708SDavid Chisnall p_idx = ddata->output.size;
2408a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL))
24097a984708SDavid Chisnall return (0);
24107a984708SDavid Chisnall
24117a984708SDavid Chisnall if ((class_type = vector_str_substr(&ddata->output, p_idx,
24127a984708SDavid Chisnall ddata->output.size - 1, &class_type_len)) == NULL)
24137a984708SDavid Chisnall return (0);
24147a984708SDavid Chisnall
24157a984708SDavid Chisnall rtn = 0;
24167a984708SDavid Chisnall idx = ddata->output.size;
24177a984708SDavid Chisnall for (i = p_idx; i < idx; ++i)
24187a984708SDavid Chisnall if (!vector_str_pop(&ddata->output))
24197a984708SDavid Chisnall goto clean1;
24207a984708SDavid Chisnall
2421a7941b33SDimitry Andric if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM, v))
24227a984708SDavid Chisnall goto clean1;
24237a984708SDavid Chisnall
24247a984708SDavid Chisnall if (!vector_str_push(&ddata->class_type, class_type, class_type_len))
24257a984708SDavid Chisnall goto clean2;
24267a984708SDavid Chisnall
24277a984708SDavid Chisnall p_func_type = ddata->func_type;
2428a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL))
24297a984708SDavid Chisnall goto clean3;
24307a984708SDavid Chisnall
24317a984708SDavid Chisnall if (p_func_type == ddata->func_type) {
2432a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, " "))
24337a984708SDavid Chisnall goto clean3;
24347a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, class_type, class_type_len))
24357a984708SDavid Chisnall goto clean3;
2436a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "::*"))
24377a984708SDavid Chisnall goto clean3;
24387a984708SDavid Chisnall }
24397a984708SDavid Chisnall
24407a984708SDavid Chisnall rtn = 1;
24417a984708SDavid Chisnall clean3:
24427a984708SDavid Chisnall if (!vector_str_pop(&ddata->class_type))
24437a984708SDavid Chisnall rtn = 0;
24447a984708SDavid Chisnall clean2:
24457a984708SDavid Chisnall if (!vector_read_cmd_pop(&ddata->cmd))
24467a984708SDavid Chisnall rtn = 0;
24477a984708SDavid Chisnall clean1:
24487a984708SDavid Chisnall free(class_type);
24497a984708SDavid Chisnall
2450a7941b33SDimitry Andric vector_type_qualifier_dest(v);
2451a7941b33SDimitry Andric if (!vector_type_qualifier_init(v))
2452a7941b33SDimitry Andric return (0);
2453a7941b33SDimitry Andric
24547a984708SDavid Chisnall return (rtn);
24557a984708SDavid Chisnall }
24567a984708SDavid Chisnall
24577a984708SDavid Chisnall /* read source-name, source-name is <len> <ID> */
24587a984708SDavid Chisnall static int
cpp_demangle_read_sname(struct cpp_demangle_data * ddata)24597a984708SDavid Chisnall cpp_demangle_read_sname(struct cpp_demangle_data *ddata)
24607a984708SDavid Chisnall {
24617a984708SDavid Chisnall long len;
24620f9eee39SDavid Chisnall int err;
24637a984708SDavid Chisnall
24647a984708SDavid Chisnall if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
24650f9eee39SDavid Chisnall len <= 0)
24660f9eee39SDavid Chisnall return (0);
24670f9eee39SDavid Chisnall
24680f9eee39SDavid Chisnall if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0))
2469a7941b33SDimitry Andric err = DEM_PUSH_STR(ddata, "(anonymous namespace)");
24700f9eee39SDavid Chisnall else
24710f9eee39SDavid Chisnall err = cpp_demangle_push_str(ddata, ddata->cur, len);
24720f9eee39SDavid Chisnall
24730f9eee39SDavid Chisnall if (err == 0)
24747a984708SDavid Chisnall return (0);
24757a984708SDavid Chisnall
2476a7941b33SDimitry Andric assert(ddata->cur_output->size > 0);
2477a7941b33SDimitry Andric if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == NULL)
24787a984708SDavid Chisnall ddata->last_sname =
247912be6f12SJustine Tunney ddata->cur_output->container[ddata->cur_output->size - 1];
24807a984708SDavid Chisnall
24817a984708SDavid Chisnall ddata->cur += len;
24827a984708SDavid Chisnall
24837a984708SDavid Chisnall return (1);
24847a984708SDavid Chisnall }
24857a984708SDavid Chisnall
24867a984708SDavid Chisnall static int
cpp_demangle_read_subst(struct cpp_demangle_data * ddata)24877a984708SDavid Chisnall cpp_demangle_read_subst(struct cpp_demangle_data *ddata)
24887a984708SDavid Chisnall {
24897a984708SDavid Chisnall long nth;
24907a984708SDavid Chisnall
24917a984708SDavid Chisnall if (ddata == NULL || *ddata->cur == '\0')
24927a984708SDavid Chisnall return (0);
24937a984708SDavid Chisnall
24947a984708SDavid Chisnall /* abbreviations of the form Sx */
24957a984708SDavid Chisnall switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
24967a984708SDavid Chisnall case SIMPLE_HASH('S', 'a'):
24977a984708SDavid Chisnall /* std::allocator */
2498a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "std::allocator"))
24997a984708SDavid Chisnall return (0);
25007a984708SDavid Chisnall ddata->cur += 2;
25017a984708SDavid Chisnall if (*ddata->cur == 'I')
25027a984708SDavid Chisnall return (cpp_demangle_read_subst_stdtmpl(ddata,
2503a7941b33SDimitry Andric "std::allocator"));
25047a984708SDavid Chisnall return (1);
25057a984708SDavid Chisnall
25067a984708SDavid Chisnall case SIMPLE_HASH('S', 'b'):
25077a984708SDavid Chisnall /* std::basic_string */
2508a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "std::basic_string"))
25097a984708SDavid Chisnall return (0);
25107a984708SDavid Chisnall ddata->cur += 2;
25117a984708SDavid Chisnall if (*ddata->cur == 'I')
25127a984708SDavid Chisnall return (cpp_demangle_read_subst_stdtmpl(ddata,
2513a7941b33SDimitry Andric "std::basic_string"));
25147a984708SDavid Chisnall return (1);
25157a984708SDavid Chisnall
25167a984708SDavid Chisnall case SIMPLE_HASH('S', 'd'):
25177a984708SDavid Chisnall /* std::basic_iostream<char, std::char_traits<char>> */
2518a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "std::basic_iostream<char, "
2519a7941b33SDimitry Andric "std::char_traits<char>>"))
25207a984708SDavid Chisnall return (0);
25214a1f3708SDimitry Andric ddata->last_sname = "basic_iostream";
25227a984708SDavid Chisnall ddata->cur += 2;
25237a984708SDavid Chisnall if (*ddata->cur == 'I')
25247a984708SDavid Chisnall return (cpp_demangle_read_subst_stdtmpl(ddata,
2525a7941b33SDimitry Andric "std::basic_iostream<char, std::char_traits"
2526a7941b33SDimitry Andric "<char>>"));
25277a984708SDavid Chisnall return (1);
25287a984708SDavid Chisnall
25297a984708SDavid Chisnall case SIMPLE_HASH('S', 'i'):
25307a984708SDavid Chisnall /* std::basic_istream<char, std::char_traits<char>> */
2531a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "std::basic_istream<char, "
2532a7941b33SDimitry Andric "std::char_traits<char>>"))
25337a984708SDavid Chisnall return (0);
25344a1f3708SDimitry Andric ddata->last_sname = "basic_istream";
25357a984708SDavid Chisnall ddata->cur += 2;
25367a984708SDavid Chisnall if (*ddata->cur == 'I')
25377a984708SDavid Chisnall return (cpp_demangle_read_subst_stdtmpl(ddata,
2538a7941b33SDimitry Andric "std::basic_istream<char, std::char_traits"
2539a7941b33SDimitry Andric "<char>>"));
25407a984708SDavid Chisnall return (1);
25417a984708SDavid Chisnall
25427a984708SDavid Chisnall case SIMPLE_HASH('S', 'o'):
25437a984708SDavid Chisnall /* std::basic_ostream<char, std::char_traits<char>> */
2544a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "std::basic_ostream<char, "
2545a7941b33SDimitry Andric "std::char_traits<char>>"))
25467a984708SDavid Chisnall return (0);
25474a1f3708SDimitry Andric ddata->last_sname = "basic_ostream";
25487a984708SDavid Chisnall ddata->cur += 2;
25497a984708SDavid Chisnall if (*ddata->cur == 'I')
25507a984708SDavid Chisnall return (cpp_demangle_read_subst_stdtmpl(ddata,
2551a7941b33SDimitry Andric "std::basic_ostream<char, std::char_traits"
2552a7941b33SDimitry Andric "<char>>"));
25537a984708SDavid Chisnall return (1);
25547a984708SDavid Chisnall
25557a984708SDavid Chisnall case SIMPLE_HASH('S', 's'):
25567a984708SDavid Chisnall /*
2557*13da1af1SEd Maste * std::string for consistency with libcxxabi
25587a984708SDavid Chisnall */
2559*13da1af1SEd Maste if (!DEM_PUSH_STR(ddata, "std::string"))
2560*13da1af1SEd Maste return 0;
25617a984708SDavid Chisnall ddata->last_sname = "string";
25627a984708SDavid Chisnall ddata->cur += 2;
25637a984708SDavid Chisnall if (*ddata->cur == 'I')
2564*13da1af1SEd Maste return cpp_demangle_read_subst_stdtmpl(ddata,
2565*13da1af1SEd Maste "std::string");
2566*13da1af1SEd Maste return 1;
25677a984708SDavid Chisnall
25687a984708SDavid Chisnall case SIMPLE_HASH('S', 't'):
25697a984708SDavid Chisnall /* std:: */
25707a984708SDavid Chisnall return (cpp_demangle_read_subst_std(ddata));
25714a1f3708SDimitry Andric }
25727a984708SDavid Chisnall
25737a984708SDavid Chisnall if (*(++ddata->cur) == '\0')
25747a984708SDavid Chisnall return (0);
25757a984708SDavid Chisnall
2576a7941b33SDimitry Andric /* Skip unknown substitution abbreviations. */
2577a7941b33SDimitry Andric if (!(*ddata->cur >= '0' && *ddata->cur <= '9') &&
2578a7941b33SDimitry Andric !(*ddata->cur >= 'A' && *ddata->cur <= 'Z') &&
2579a7941b33SDimitry Andric *ddata->cur != '_') {
2580a7941b33SDimitry Andric ++ddata->cur;
2581a7941b33SDimitry Andric return (1);
2582a7941b33SDimitry Andric }
2583a7941b33SDimitry Andric
25847a984708SDavid Chisnall /* substitution */
25857a984708SDavid Chisnall if (*ddata->cur == '_')
25867a984708SDavid Chisnall return (cpp_demangle_get_subst(ddata, 0));
25877a984708SDavid Chisnall else {
25887a984708SDavid Chisnall errno = 0;
25897a984708SDavid Chisnall /* substitution number is base 36 */
25907a984708SDavid Chisnall if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
25917a984708SDavid Chisnall errno != 0)
25927a984708SDavid Chisnall return (0);
25937a984708SDavid Chisnall
25947a984708SDavid Chisnall /* first was '_', so increase one */
25957a984708SDavid Chisnall ++nth;
25967a984708SDavid Chisnall
25977a984708SDavid Chisnall while (*ddata->cur != '_')
25987a984708SDavid Chisnall ++ddata->cur;
25997a984708SDavid Chisnall
26007a984708SDavid Chisnall assert(nth > 0);
26017a984708SDavid Chisnall
26027a984708SDavid Chisnall return (cpp_demangle_get_subst(ddata, nth));
26037a984708SDavid Chisnall }
26047a984708SDavid Chisnall
26057a984708SDavid Chisnall /* NOTREACHED */
26067a984708SDavid Chisnall return (0);
26077a984708SDavid Chisnall }
26087a984708SDavid Chisnall
26097a984708SDavid Chisnall static int
cpp_demangle_read_subst_std(struct cpp_demangle_data * ddata)26107a984708SDavid Chisnall cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
26117a984708SDavid Chisnall {
26127a984708SDavid Chisnall struct vector_str *output, v;
26137a984708SDavid Chisnall size_t p_idx, subst_str_len;
26147a984708SDavid Chisnall int rtn;
26157a984708SDavid Chisnall char *subst_str;
26167a984708SDavid Chisnall
26177a984708SDavid Chisnall if (ddata == NULL)
26187a984708SDavid Chisnall return (0);
26197a984708SDavid Chisnall
26207a984708SDavid Chisnall if (!vector_str_init(&v))
26217a984708SDavid Chisnall return (0);
26227a984708SDavid Chisnall
26237a984708SDavid Chisnall subst_str = NULL;
26247a984708SDavid Chisnall rtn = 0;
2625a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "std::"))
26267a984708SDavid Chisnall goto clean;
26277a984708SDavid Chisnall
2628a7941b33SDimitry Andric if (!VEC_PUSH_STR(&v, "std::"))
26297a984708SDavid Chisnall goto clean;
26307a984708SDavid Chisnall
26317a984708SDavid Chisnall ddata->cur += 2;
26327a984708SDavid Chisnall
2633a7941b33SDimitry Andric output = ddata->cur_output;
26347a984708SDavid Chisnall
26357a984708SDavid Chisnall p_idx = output->size;
26367a984708SDavid Chisnall if (!cpp_demangle_read_uqname(ddata))
26377a984708SDavid Chisnall goto clean;
26387a984708SDavid Chisnall
26397a984708SDavid Chisnall if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
26407a984708SDavid Chisnall &subst_str_len)) == NULL)
26417a984708SDavid Chisnall goto clean;
26427a984708SDavid Chisnall
26437a984708SDavid Chisnall if (!vector_str_push(&v, subst_str, subst_str_len))
26447a984708SDavid Chisnall goto clean;
26457a984708SDavid Chisnall
26467a984708SDavid Chisnall if (!cpp_demangle_push_subst_v(ddata, &v))
26477a984708SDavid Chisnall goto clean;
26487a984708SDavid Chisnall
26497a984708SDavid Chisnall if (*ddata->cur == 'I') {
26507a984708SDavid Chisnall p_idx = output->size;
26517a984708SDavid Chisnall if (!cpp_demangle_read_tmpl_args(ddata))
26527a984708SDavid Chisnall goto clean;
26537a984708SDavid Chisnall free(subst_str);
26547a984708SDavid Chisnall if ((subst_str = vector_str_substr(output, p_idx,
26557a984708SDavid Chisnall output->size - 1, &subst_str_len)) == NULL)
26567a984708SDavid Chisnall goto clean;
26577a984708SDavid Chisnall if (!vector_str_push(&v, subst_str, subst_str_len))
26587a984708SDavid Chisnall goto clean;
26597a984708SDavid Chisnall if (!cpp_demangle_push_subst_v(ddata, &v))
26607a984708SDavid Chisnall goto clean;
26617a984708SDavid Chisnall }
26627a984708SDavid Chisnall
26637a984708SDavid Chisnall rtn = 1;
26647a984708SDavid Chisnall clean:
26657a984708SDavid Chisnall free(subst_str);
26667a984708SDavid Chisnall vector_str_dest(&v);
26677a984708SDavid Chisnall
26680f9eee39SDavid Chisnall return (rtn);
26697a984708SDavid Chisnall }
26707a984708SDavid Chisnall
26717a984708SDavid Chisnall static int
cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data * ddata,const char * str)26727a984708SDavid Chisnall cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
2673a7941b33SDimitry Andric const char *str)
26747a984708SDavid Chisnall {
26757a984708SDavid Chisnall struct vector_str *output;
2676a7941b33SDimitry Andric size_t p_idx, substr_len, len;
26777a984708SDavid Chisnall int rtn;
26787a984708SDavid Chisnall char *subst_str, *substr;
26797a984708SDavid Chisnall
2680a7941b33SDimitry Andric if (ddata == NULL || str == NULL)
26817a984708SDavid Chisnall return (0);
26827a984708SDavid Chisnall
2683a7941b33SDimitry Andric if ((len = strlen(str)) == 0)
2684a7941b33SDimitry Andric return (0);
2685a7941b33SDimitry Andric
2686a7941b33SDimitry Andric output = ddata->cur_output;
26877a984708SDavid Chisnall
26887a984708SDavid Chisnall p_idx = output->size;
26897a984708SDavid Chisnall substr = NULL;
26907a984708SDavid Chisnall subst_str = NULL;
26917a984708SDavid Chisnall
26927a984708SDavid Chisnall if (!cpp_demangle_read_tmpl_args(ddata))
26937a984708SDavid Chisnall return (0);
26947a984708SDavid Chisnall if ((substr = vector_str_substr(output, p_idx, output->size - 1,
26957a984708SDavid Chisnall &substr_len)) == NULL)
26967a984708SDavid Chisnall return (0);
26977a984708SDavid Chisnall
26987a984708SDavid Chisnall rtn = 0;
26997a984708SDavid Chisnall if ((subst_str = malloc(sizeof(char) * (substr_len + len + 1))) ==
27007a984708SDavid Chisnall NULL)
27017a984708SDavid Chisnall goto clean;
27027a984708SDavid Chisnall
27037a984708SDavid Chisnall memcpy(subst_str, str, len);
27047a984708SDavid Chisnall memcpy(subst_str + len, substr, substr_len);
27057a984708SDavid Chisnall subst_str[substr_len + len] = '\0';
27067a984708SDavid Chisnall
27077a984708SDavid Chisnall if (!cpp_demangle_push_subst(ddata, subst_str, substr_len + len))
27087a984708SDavid Chisnall goto clean;
27097a984708SDavid Chisnall
27107a984708SDavid Chisnall rtn = 1;
27117a984708SDavid Chisnall clean:
27127a984708SDavid Chisnall free(subst_str);
27137a984708SDavid Chisnall free(substr);
27147a984708SDavid Chisnall
27157a984708SDavid Chisnall return (rtn);
27167a984708SDavid Chisnall }
27177a984708SDavid Chisnall
27187a984708SDavid Chisnall static int
cpp_demangle_read_tmpl_arg(struct cpp_demangle_data * ddata)27197a984708SDavid Chisnall cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *ddata)
27207a984708SDavid Chisnall {
27217a984708SDavid Chisnall
27227a984708SDavid Chisnall if (ddata == NULL || *ddata->cur == '\0')
27237a984708SDavid Chisnall return (0);
27247a984708SDavid Chisnall
27257a984708SDavid Chisnall switch (*ddata->cur) {
27267a984708SDavid Chisnall case 'L':
27277a984708SDavid Chisnall return (cpp_demangle_read_expr_primary(ddata));
27287a984708SDavid Chisnall case 'X':
2729a7941b33SDimitry Andric ++ddata->cur;
2730a7941b33SDimitry Andric if (!cpp_demangle_read_expression(ddata))
2731a7941b33SDimitry Andric return (0);
2732a7941b33SDimitry Andric return (*ddata->cur++ == 'E');
27334a1f3708SDimitry Andric }
27347a984708SDavid Chisnall
2735a7941b33SDimitry Andric return (cpp_demangle_read_type(ddata, NULL));
27367a984708SDavid Chisnall }
27377a984708SDavid Chisnall
27387a984708SDavid Chisnall static int
cpp_demangle_read_tmpl_args(struct cpp_demangle_data * ddata)27397a984708SDavid Chisnall cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
27407a984708SDavid Chisnall {
27417a984708SDavid Chisnall struct vector_str *v;
2742*13da1af1SEd Maste size_t arg_len, idx, limit;
27437a984708SDavid Chisnall char *arg;
27447a984708SDavid Chisnall
27457a984708SDavid Chisnall if (ddata == NULL || *ddata->cur == '\0')
27467a984708SDavid Chisnall return (0);
27477a984708SDavid Chisnall
27487a984708SDavid Chisnall ++ddata->cur;
27497a984708SDavid Chisnall
2750a7941b33SDimitry Andric if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL, NULL))
27517a984708SDavid Chisnall return (0);
27527a984708SDavid Chisnall
2753a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "<"))
27547a984708SDavid Chisnall return (0);
27557a984708SDavid Chisnall
27567a984708SDavid Chisnall limit = 0;
2757a7941b33SDimitry Andric v = ddata->cur_output;
27587a984708SDavid Chisnall for (;;) {
27597a984708SDavid Chisnall idx = v->size;
27607a984708SDavid Chisnall if (!cpp_demangle_read_tmpl_arg(ddata))
27617a984708SDavid Chisnall return (0);
27627a984708SDavid Chisnall if ((arg = vector_str_substr(v, idx, v->size - 1, &arg_len)) ==
27637a984708SDavid Chisnall NULL)
27647a984708SDavid Chisnall return (0);
27657a984708SDavid Chisnall if (!vector_str_find(&ddata->tmpl, arg, arg_len) &&
27667a984708SDavid Chisnall !vector_str_push(&ddata->tmpl, arg, arg_len)) {
27677a984708SDavid Chisnall free(arg);
27687a984708SDavid Chisnall return (0);
27697a984708SDavid Chisnall }
27707a984708SDavid Chisnall
27717a984708SDavid Chisnall free(arg);
27727a984708SDavid Chisnall
27737a984708SDavid Chisnall if (*ddata->cur == 'E') {
27747a984708SDavid Chisnall ++ddata->cur;
2775a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, ">"))
27767a984708SDavid Chisnall return (0);
2777a7941b33SDimitry Andric ddata->is_tmpl = true;
27787a984708SDavid Chisnall break;
27797a984708SDavid Chisnall } else if (*ddata->cur != 'I' &&
2780a7941b33SDimitry Andric !DEM_PUSH_STR(ddata, ", "))
27817a984708SDavid Chisnall return (0);
27827a984708SDavid Chisnall
27837a984708SDavid Chisnall if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
27847a984708SDavid Chisnall return (0);
27857a984708SDavid Chisnall }
27867a984708SDavid Chisnall
27877a984708SDavid Chisnall return (vector_read_cmd_pop(&ddata->cmd));
27887a984708SDavid Chisnall }
27897a984708SDavid Chisnall
27907a984708SDavid Chisnall /*
27917a984708SDavid Chisnall * Read template parameter that forms in 'T[number]_'.
27927a984708SDavid Chisnall * This function much like to read_subst but only for types.
27937a984708SDavid Chisnall */
27947a984708SDavid Chisnall static int
cpp_demangle_read_tmpl_param(struct cpp_demangle_data * ddata)27957a984708SDavid Chisnall cpp_demangle_read_tmpl_param(struct cpp_demangle_data *ddata)
27967a984708SDavid Chisnall {
27977a984708SDavid Chisnall long nth;
27987a984708SDavid Chisnall
27997a984708SDavid Chisnall if (ddata == NULL || *ddata->cur != 'T')
28007a984708SDavid Chisnall return (0);
28017a984708SDavid Chisnall
28027a984708SDavid Chisnall ++ddata->cur;
28037a984708SDavid Chisnall
28047a984708SDavid Chisnall if (*ddata->cur == '_')
28057a984708SDavid Chisnall return (cpp_demangle_get_tmpl_param(ddata, 0));
28067a984708SDavid Chisnall else {
28077a984708SDavid Chisnall
28087a984708SDavid Chisnall errno = 0;
28097a984708SDavid Chisnall if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
28107a984708SDavid Chisnall errno != 0)
28117a984708SDavid Chisnall return (0);
28127a984708SDavid Chisnall
28137a984708SDavid Chisnall /* T_ is first */
28147a984708SDavid Chisnall ++nth;
28157a984708SDavid Chisnall
28167a984708SDavid Chisnall while (*ddata->cur != '_')
28177a984708SDavid Chisnall ++ddata->cur;
28187a984708SDavid Chisnall
28197a984708SDavid Chisnall assert(nth > 0);
28207a984708SDavid Chisnall
28217a984708SDavid Chisnall return (cpp_demangle_get_tmpl_param(ddata, nth));
28227a984708SDavid Chisnall }
28237a984708SDavid Chisnall
28247a984708SDavid Chisnall /* NOTREACHED */
28257a984708SDavid Chisnall return (0);
28267a984708SDavid Chisnall }
28277a984708SDavid Chisnall
28287a984708SDavid Chisnall static int
cpp_demangle_read_type(struct cpp_demangle_data * ddata,struct type_delimit * td)2829a7941b33SDimitry Andric cpp_demangle_read_type(struct cpp_demangle_data *ddata,
2830a7941b33SDimitry Andric struct type_delimit *td)
28317a984708SDavid Chisnall {
28327a984708SDavid Chisnall struct vector_type_qualifier v;
2833a7941b33SDimitry Andric struct vector_str *output, sv;
2834a7941b33SDimitry Andric size_t p_idx, type_str_len, subst_str_len;
28357a984708SDavid Chisnall int extern_c, is_builtin;
28367a984708SDavid Chisnall long len;
2837a7941b33SDimitry Andric const char *p;
2838a7941b33SDimitry Andric char *type_str, *exp_str, *num_str, *subst_str;
2839a7941b33SDimitry Andric bool skip_ref_qualifier, omit_void;
28407a984708SDavid Chisnall
28417a984708SDavid Chisnall if (ddata == NULL)
28427a984708SDavid Chisnall return (0);
28437a984708SDavid Chisnall
2844a7941b33SDimitry Andric output = ddata->cur_output;
2845a7941b33SDimitry Andric if (td) {
2846a7941b33SDimitry Andric if (td->paren == false) {
2847a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "("))
28487a984708SDavid Chisnall return (0);
28497a984708SDavid Chisnall if (ddata->output.size < 2)
28507a984708SDavid Chisnall return (0);
2851a7941b33SDimitry Andric td->paren = true;
28527a984708SDavid Chisnall }
28537a984708SDavid Chisnall
2854a7941b33SDimitry Andric if (!td->firstp) {
2855a7941b33SDimitry Andric if (*ddata->cur != 'I') {
2856a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, ", "))
28577a984708SDavid Chisnall return (0);
28587a984708SDavid Chisnall }
2859a7941b33SDimitry Andric }
2860a7941b33SDimitry Andric }
28617a984708SDavid Chisnall
28627a984708SDavid Chisnall assert(output != NULL);
28637a984708SDavid Chisnall /*
2864a7941b33SDimitry Andric * [r, V, K] [P, R, O, C, G, U] builtin, function, class-enum, array
28657a984708SDavid Chisnall * pointer-to-member, template-param, template-template-param, subst
28667a984708SDavid Chisnall */
28677a984708SDavid Chisnall
28687a984708SDavid Chisnall if (!vector_type_qualifier_init(&v))
28697a984708SDavid Chisnall return (0);
28707a984708SDavid Chisnall
28717a984708SDavid Chisnall extern_c = 0;
28727a984708SDavid Chisnall is_builtin = 1;
28737a984708SDavid Chisnall p_idx = output->size;
2874fa7477ceSEd Maste type_str = exp_str = num_str = NULL;
2875a7941b33SDimitry Andric skip_ref_qualifier = false;
2876a7941b33SDimitry Andric
28777a984708SDavid Chisnall again:
2878a7941b33SDimitry Andric
2879a7941b33SDimitry Andric /* Clear ref-qualifier flag */
2880a7941b33SDimitry Andric if (*ddata->cur != 'R' && *ddata->cur != 'O' && *ddata->cur != 'E')
2881a7941b33SDimitry Andric ddata->ref_qualifier = false;
2882a7941b33SDimitry Andric
28837a984708SDavid Chisnall /* builtin type */
28847a984708SDavid Chisnall switch (*ddata->cur) {
28857a984708SDavid Chisnall case 'a':
28867a984708SDavid Chisnall /* signed char */
2887a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "signed char"))
28887a984708SDavid Chisnall goto clean;
28897a984708SDavid Chisnall ++ddata->cur;
28907a984708SDavid Chisnall goto rtn;
28917a984708SDavid Chisnall
28927a984708SDavid Chisnall case 'A':
28937a984708SDavid Chisnall /* array type */
28947a984708SDavid Chisnall if (!cpp_demangle_read_array(ddata))
28957a984708SDavid Chisnall goto clean;
28967a984708SDavid Chisnall is_builtin = 0;
28977a984708SDavid Chisnall goto rtn;
28987a984708SDavid Chisnall
28997a984708SDavid Chisnall case 'b':
29007a984708SDavid Chisnall /* bool */
2901a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "bool"))
29027a984708SDavid Chisnall goto clean;
29037a984708SDavid Chisnall ++ddata->cur;
29047a984708SDavid Chisnall goto rtn;
29057a984708SDavid Chisnall
29067a984708SDavid Chisnall case 'C':
29077a984708SDavid Chisnall /* complex pair */
29087a984708SDavid Chisnall if (!vector_type_qualifier_push(&v, TYPE_CMX))
29097a984708SDavid Chisnall goto clean;
29107a984708SDavid Chisnall ++ddata->cur;
2911a7941b33SDimitry Andric if (td)
2912a7941b33SDimitry Andric td->firstp = false;
29137a984708SDavid Chisnall goto again;
29147a984708SDavid Chisnall
29157a984708SDavid Chisnall case 'c':
29167a984708SDavid Chisnall /* char */
2917a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "char"))
29187a984708SDavid Chisnall goto clean;
29197a984708SDavid Chisnall ++ddata->cur;
29207a984708SDavid Chisnall goto rtn;
29217a984708SDavid Chisnall
29227a984708SDavid Chisnall case 'd':
29237a984708SDavid Chisnall /* double */
2924a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "double"))
29257a984708SDavid Chisnall goto clean;
29267a984708SDavid Chisnall ++ddata->cur;
29277a984708SDavid Chisnall goto rtn;
29287a984708SDavid Chisnall
2929fa7477ceSEd Maste case 'D':
2930fa7477ceSEd Maste ++ddata->cur;
2931fa7477ceSEd Maste switch (*ddata->cur) {
2932a7941b33SDimitry Andric case 'a':
2933a7941b33SDimitry Andric /* auto */
2934a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "auto"))
2935a7941b33SDimitry Andric goto clean;
2936a7941b33SDimitry Andric ++ddata->cur;
2937a7941b33SDimitry Andric break;
2938a7941b33SDimitry Andric case 'c':
2939a7941b33SDimitry Andric /* decltype(auto) */
2940a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "decltype(auto)"))
2941a7941b33SDimitry Andric goto clean;
2942a7941b33SDimitry Andric ++ddata->cur;
2943a7941b33SDimitry Andric break;
2944fa7477ceSEd Maste case 'd':
2945fa7477ceSEd Maste /* IEEE 754r decimal floating point (64 bits) */
2946a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "decimal64"))
2947fa7477ceSEd Maste goto clean;
2948fa7477ceSEd Maste ++ddata->cur;
2949fa7477ceSEd Maste break;
2950fa7477ceSEd Maste case 'e':
2951fa7477ceSEd Maste /* IEEE 754r decimal floating point (128 bits) */
2952a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "decimal128"))
2953fa7477ceSEd Maste goto clean;
2954fa7477ceSEd Maste ++ddata->cur;
2955fa7477ceSEd Maste break;
2956fa7477ceSEd Maste case 'f':
2957fa7477ceSEd Maste /* IEEE 754r decimal floating point (32 bits) */
2958a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "decimal32"))
2959fa7477ceSEd Maste goto clean;
2960fa7477ceSEd Maste ++ddata->cur;
2961fa7477ceSEd Maste break;
2962fa7477ceSEd Maste case 'h':
2963fa7477ceSEd Maste /* IEEE 754r half-precision floating point (16 bits) */
2964a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "half"))
2965fa7477ceSEd Maste goto clean;
2966fa7477ceSEd Maste ++ddata->cur;
2967fa7477ceSEd Maste break;
2968fa7477ceSEd Maste case 'i':
2969fa7477ceSEd Maste /* char32_t */
2970a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "char32_t"))
2971fa7477ceSEd Maste goto clean;
2972fa7477ceSEd Maste ++ddata->cur;
2973fa7477ceSEd Maste break;
2974fa7477ceSEd Maste case 'n':
2975fa7477ceSEd Maste /* std::nullptr_t (i.e., decltype(nullptr)) */
2976a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "decltype(nullptr)"))
2977fa7477ceSEd Maste goto clean;
2978fa7477ceSEd Maste ++ddata->cur;
2979fa7477ceSEd Maste break;
2980fa7477ceSEd Maste case 's':
2981fa7477ceSEd Maste /* char16_t */
2982a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "char16_t"))
2983fa7477ceSEd Maste goto clean;
2984fa7477ceSEd Maste ++ddata->cur;
2985fa7477ceSEd Maste break;
2986fa7477ceSEd Maste case 'v':
2987fa7477ceSEd Maste /* gcc vector_size extension. */
2988fa7477ceSEd Maste ++ddata->cur;
2989fa7477ceSEd Maste if (*ddata->cur == '_') {
2990fa7477ceSEd Maste ++ddata->cur;
2991fa7477ceSEd Maste if (!cpp_demangle_read_expression_flat(ddata,
2992fa7477ceSEd Maste &exp_str))
2993fa7477ceSEd Maste goto clean;
2994a7941b33SDimitry Andric if (!VEC_PUSH_STR(&v.ext_name, exp_str))
2995fa7477ceSEd Maste goto clean;
2996fa7477ceSEd Maste } else {
2997fa7477ceSEd Maste if (!cpp_demangle_read_number_as_string(ddata,
2998fa7477ceSEd Maste &num_str))
2999fa7477ceSEd Maste goto clean;
3000a7941b33SDimitry Andric if (!VEC_PUSH_STR(&v.ext_name, num_str))
3001fa7477ceSEd Maste goto clean;
3002fa7477ceSEd Maste }
3003fa7477ceSEd Maste if (*ddata->cur != '_')
3004fa7477ceSEd Maste goto clean;
3005fa7477ceSEd Maste ++ddata->cur;
3006fa7477ceSEd Maste if (!vector_type_qualifier_push(&v, TYPE_VEC))
3007fa7477ceSEd Maste goto clean;
3008a7941b33SDimitry Andric if (td)
3009a7941b33SDimitry Andric td->firstp = false;
3010fa7477ceSEd Maste goto again;
3011fa7477ceSEd Maste default:
3012fa7477ceSEd Maste goto clean;
3013fa7477ceSEd Maste }
3014fa7477ceSEd Maste goto rtn;
3015fa7477ceSEd Maste
30167a984708SDavid Chisnall case 'e':
30177a984708SDavid Chisnall /* long double */
3018a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "long double"))
30197a984708SDavid Chisnall goto clean;
30207a984708SDavid Chisnall ++ddata->cur;
30217a984708SDavid Chisnall goto rtn;
30227a984708SDavid Chisnall
3023a7941b33SDimitry Andric case 'E':
3024a7941b33SDimitry Andric /* unexpected end except ref-qualifiers */
3025a7941b33SDimitry Andric if (ddata->ref_qualifier && ddata->is_functype) {
3026a7941b33SDimitry Andric skip_ref_qualifier = true;
3027a7941b33SDimitry Andric /* Pop the delimiter. */
3028a7941b33SDimitry Andric cpp_demangle_pop_str(ddata);
3029a7941b33SDimitry Andric goto rtn;
3030a7941b33SDimitry Andric }
3031a7941b33SDimitry Andric goto clean;
3032a7941b33SDimitry Andric
30337a984708SDavid Chisnall case 'f':
30347a984708SDavid Chisnall /* float */
3035a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "float"))
30367a984708SDavid Chisnall goto clean;
30377a984708SDavid Chisnall ++ddata->cur;
30387a984708SDavid Chisnall goto rtn;
30397a984708SDavid Chisnall
30407a984708SDavid Chisnall case 'F':
30417a984708SDavid Chisnall /* function */
30427a984708SDavid Chisnall if (!cpp_demangle_read_function(ddata, &extern_c, &v))
30437a984708SDavid Chisnall goto clean;
30447a984708SDavid Chisnall is_builtin = 0;
30457a984708SDavid Chisnall goto rtn;
30467a984708SDavid Chisnall
30477a984708SDavid Chisnall case 'g':
30487a984708SDavid Chisnall /* __float128 */
3049a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "__float128"))
30507a984708SDavid Chisnall goto clean;
30517a984708SDavid Chisnall ++ddata->cur;
30527a984708SDavid Chisnall goto rtn;
30537a984708SDavid Chisnall
30547a984708SDavid Chisnall case 'G':
30557a984708SDavid Chisnall /* imaginary */
30567a984708SDavid Chisnall if (!vector_type_qualifier_push(&v, TYPE_IMG))
30577a984708SDavid Chisnall goto clean;
30587a984708SDavid Chisnall ++ddata->cur;
3059a7941b33SDimitry Andric if (td)
3060a7941b33SDimitry Andric td->firstp = false;
30617a984708SDavid Chisnall goto again;
30627a984708SDavid Chisnall
30637a984708SDavid Chisnall case 'h':
30647a984708SDavid Chisnall /* unsigned char */
3065a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "unsigned char"))
30667a984708SDavid Chisnall goto clean;
30677a984708SDavid Chisnall ++ddata->cur;
30687a984708SDavid Chisnall goto rtn;
30697a984708SDavid Chisnall
30707a984708SDavid Chisnall case 'i':
30717a984708SDavid Chisnall /* int */
3072a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "int"))
30737a984708SDavid Chisnall goto clean;
30747a984708SDavid Chisnall ++ddata->cur;
30757a984708SDavid Chisnall goto rtn;
30767a984708SDavid Chisnall
3077a7941b33SDimitry Andric case 'I':
3078a7941b33SDimitry Andric /* template args. */
3079a7941b33SDimitry Andric /* handles <substitute><template-args> */
3080a7941b33SDimitry Andric p_idx = output->size;
3081a7941b33SDimitry Andric if (!cpp_demangle_read_tmpl_args(ddata))
3082a7941b33SDimitry Andric goto clean;
3083a7941b33SDimitry Andric if ((subst_str = vector_str_substr(output, p_idx,
3084a7941b33SDimitry Andric output->size - 1, &subst_str_len)) == NULL)
3085a7941b33SDimitry Andric goto clean;
3086a7941b33SDimitry Andric if (!vector_str_init(&sv)) {
3087a7941b33SDimitry Andric free(subst_str);
3088a7941b33SDimitry Andric goto clean;
3089a7941b33SDimitry Andric }
3090a7941b33SDimitry Andric if (!vector_str_push(&sv, subst_str, subst_str_len)) {
3091a7941b33SDimitry Andric free(subst_str);
3092a7941b33SDimitry Andric vector_str_dest(&sv);
3093a7941b33SDimitry Andric goto clean;
3094a7941b33SDimitry Andric }
3095a7941b33SDimitry Andric free(subst_str);
3096a7941b33SDimitry Andric if (!cpp_demangle_push_subst_v(ddata, &sv)) {
3097a7941b33SDimitry Andric vector_str_dest(&sv);
3098a7941b33SDimitry Andric goto clean;
3099a7941b33SDimitry Andric }
3100a7941b33SDimitry Andric vector_str_dest(&sv);
3101a7941b33SDimitry Andric goto rtn;
3102a7941b33SDimitry Andric
31037a984708SDavid Chisnall case 'j':
31047a984708SDavid Chisnall /* unsigned int */
3105a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "unsigned int"))
31067a984708SDavid Chisnall goto clean;
31077a984708SDavid Chisnall ++ddata->cur;
31087a984708SDavid Chisnall goto rtn;
31097a984708SDavid Chisnall
31107a984708SDavid Chisnall case 'K':
31117a984708SDavid Chisnall /* const */
31127a984708SDavid Chisnall if (!vector_type_qualifier_push(&v, TYPE_CST))
31137a984708SDavid Chisnall goto clean;
31147a984708SDavid Chisnall ++ddata->cur;
3115a7941b33SDimitry Andric if (td)
3116a7941b33SDimitry Andric td->firstp = false;
31177a984708SDavid Chisnall goto again;
31187a984708SDavid Chisnall
31197a984708SDavid Chisnall case 'l':
31207a984708SDavid Chisnall /* long */
3121a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "long"))
31227a984708SDavid Chisnall goto clean;
31237a984708SDavid Chisnall ++ddata->cur;
31247a984708SDavid Chisnall goto rtn;
31257a984708SDavid Chisnall
31267a984708SDavid Chisnall case 'm':
31277a984708SDavid Chisnall /* unsigned long */
3128a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "unsigned long"))
31297a984708SDavid Chisnall goto clean;
31307a984708SDavid Chisnall
31317a984708SDavid Chisnall ++ddata->cur;
31327a984708SDavid Chisnall
31337a984708SDavid Chisnall goto rtn;
31347a984708SDavid Chisnall case 'M':
31357a984708SDavid Chisnall /* pointer to member */
3136a7941b33SDimitry Andric if (!cpp_demangle_read_pointer_to_member(ddata, &v))
31377a984708SDavid Chisnall goto clean;
31387a984708SDavid Chisnall is_builtin = 0;
31397a984708SDavid Chisnall goto rtn;
31407a984708SDavid Chisnall
31417a984708SDavid Chisnall case 'n':
31427a984708SDavid Chisnall /* __int128 */
3143a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "__int128"))
31447a984708SDavid Chisnall goto clean;
31457a984708SDavid Chisnall ++ddata->cur;
31467a984708SDavid Chisnall goto rtn;
31477a984708SDavid Chisnall
31487a984708SDavid Chisnall case 'o':
31497a984708SDavid Chisnall /* unsigned __int128 */
3150a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "unsigned __int128"))
31517a984708SDavid Chisnall goto clean;
31527a984708SDavid Chisnall ++ddata->cur;
31537a984708SDavid Chisnall goto rtn;
31547a984708SDavid Chisnall
3155a7941b33SDimitry Andric case 'O':
3156a7941b33SDimitry Andric /* rvalue reference */
3157a7941b33SDimitry Andric if (ddata->ref_qualifier)
3158a7941b33SDimitry Andric goto clean;
3159a7941b33SDimitry Andric if (!vector_type_qualifier_push(&v, TYPE_RREF))
3160a7941b33SDimitry Andric goto clean;
3161a7941b33SDimitry Andric ddata->ref_qualifier = true;
3162a7941b33SDimitry Andric ddata->ref_qualifier_type = TYPE_RREF;
3163a7941b33SDimitry Andric ++ddata->cur;
3164a7941b33SDimitry Andric if (td)
3165a7941b33SDimitry Andric td->firstp = false;
3166a7941b33SDimitry Andric goto again;
3167a7941b33SDimitry Andric
31687a984708SDavid Chisnall case 'P':
31697a984708SDavid Chisnall /* pointer */
31707a984708SDavid Chisnall if (!vector_type_qualifier_push(&v, TYPE_PTR))
31717a984708SDavid Chisnall goto clean;
31727a984708SDavid Chisnall ++ddata->cur;
3173a7941b33SDimitry Andric if (td)
3174a7941b33SDimitry Andric td->firstp = false;
31757a984708SDavid Chisnall goto again;
31767a984708SDavid Chisnall
31777a984708SDavid Chisnall case 'r':
31787a984708SDavid Chisnall /* restrict */
31797a984708SDavid Chisnall if (!vector_type_qualifier_push(&v, TYPE_RST))
31807a984708SDavid Chisnall goto clean;
31817a984708SDavid Chisnall ++ddata->cur;
3182a7941b33SDimitry Andric if (td)
3183a7941b33SDimitry Andric td->firstp = false;
31847a984708SDavid Chisnall goto again;
31857a984708SDavid Chisnall
31867a984708SDavid Chisnall case 'R':
31877a984708SDavid Chisnall /* reference */
3188a7941b33SDimitry Andric if (ddata->ref_qualifier)
3189a7941b33SDimitry Andric goto clean;
31907a984708SDavid Chisnall if (!vector_type_qualifier_push(&v, TYPE_REF))
31917a984708SDavid Chisnall goto clean;
3192a7941b33SDimitry Andric ddata->ref_qualifier = true;
3193a7941b33SDimitry Andric ddata->ref_qualifier_type = TYPE_REF;
31947a984708SDavid Chisnall ++ddata->cur;
3195a7941b33SDimitry Andric if (td)
3196a7941b33SDimitry Andric td->firstp = false;
31977a984708SDavid Chisnall goto again;
31987a984708SDavid Chisnall
31997a984708SDavid Chisnall case 's':
32007a984708SDavid Chisnall /* short, local string */
3201a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "short"))
32027a984708SDavid Chisnall goto clean;
32037a984708SDavid Chisnall ++ddata->cur;
32047a984708SDavid Chisnall goto rtn;
32057a984708SDavid Chisnall
32067a984708SDavid Chisnall case 'S':
32077a984708SDavid Chisnall /* substitution */
32087a984708SDavid Chisnall if (!cpp_demangle_read_subst(ddata))
32097a984708SDavid Chisnall goto clean;
32107a984708SDavid Chisnall is_builtin = 0;
32117a984708SDavid Chisnall goto rtn;
32127a984708SDavid Chisnall
32137a984708SDavid Chisnall case 't':
32147a984708SDavid Chisnall /* unsigned short */
3215a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "unsigned short"))
32167a984708SDavid Chisnall goto clean;
32177a984708SDavid Chisnall ++ddata->cur;
32187a984708SDavid Chisnall goto rtn;
32197a984708SDavid Chisnall
32207a984708SDavid Chisnall case 'T':
32217a984708SDavid Chisnall /* template parameter */
32227a984708SDavid Chisnall if (!cpp_demangle_read_tmpl_param(ddata))
32237a984708SDavid Chisnall goto clean;
32247a984708SDavid Chisnall is_builtin = 0;
32257a984708SDavid Chisnall goto rtn;
32267a984708SDavid Chisnall
32277a984708SDavid Chisnall case 'u':
32287a984708SDavid Chisnall /* vendor extended builtin */
32297a984708SDavid Chisnall ++ddata->cur;
32307a984708SDavid Chisnall if (!cpp_demangle_read_sname(ddata))
32317a984708SDavid Chisnall goto clean;
32327a984708SDavid Chisnall is_builtin = 0;
32337a984708SDavid Chisnall goto rtn;
32347a984708SDavid Chisnall
32357a984708SDavid Chisnall case 'U':
32367a984708SDavid Chisnall /* vendor extended type qualifier */
3237a7941b33SDimitry Andric ++ddata->cur;
32387a984708SDavid Chisnall if (!cpp_demangle_read_number(ddata, &len))
32397a984708SDavid Chisnall goto clean;
32407a984708SDavid Chisnall if (len <= 0)
32417a984708SDavid Chisnall goto clean;
32427a984708SDavid Chisnall if (!vector_str_push(&v.ext_name, ddata->cur, len))
3243a7941b33SDimitry Andric goto clean;
32447a984708SDavid Chisnall ddata->cur += len;
3245fa7477ceSEd Maste if (!vector_type_qualifier_push(&v, TYPE_EXT))
3246fa7477ceSEd Maste goto clean;
3247a7941b33SDimitry Andric if (td)
3248a7941b33SDimitry Andric td->firstp = false;
32497a984708SDavid Chisnall goto again;
32507a984708SDavid Chisnall
32517a984708SDavid Chisnall case 'v':
32527a984708SDavid Chisnall /* void */
3253a7941b33SDimitry Andric omit_void = false;
3254a7941b33SDimitry Andric if (td && td->firstp) {
3255a7941b33SDimitry Andric /*
3256a7941b33SDimitry Andric * peek into next bytes and see if we should omit
3257a7941b33SDimitry Andric * the "void".
3258a7941b33SDimitry Andric */
3259a7941b33SDimitry Andric omit_void = true;
3260a7941b33SDimitry Andric for (p = ddata->cur + 1; *p != '\0'; p++) {
3261a7941b33SDimitry Andric if (*p == 'E')
3262a7941b33SDimitry Andric break;
3263a7941b33SDimitry Andric if (*p != 'R' && *p != 'O') {
3264a7941b33SDimitry Andric omit_void = false;
3265a7941b33SDimitry Andric break;
3266a7941b33SDimitry Andric }
3267a7941b33SDimitry Andric }
3268a7941b33SDimitry Andric }
3269a7941b33SDimitry Andric if (!omit_void && !DEM_PUSH_STR(ddata, "void"))
32707a984708SDavid Chisnall goto clean;
32717a984708SDavid Chisnall ++ddata->cur;
32727a984708SDavid Chisnall goto rtn;
32737a984708SDavid Chisnall
32747a984708SDavid Chisnall case 'V':
32757a984708SDavid Chisnall /* volatile */
32767a984708SDavid Chisnall if (!vector_type_qualifier_push(&v, TYPE_VAT))
32777a984708SDavid Chisnall goto clean;
32787a984708SDavid Chisnall ++ddata->cur;
3279a7941b33SDimitry Andric if (td)
3280a7941b33SDimitry Andric td->firstp = false;
32817a984708SDavid Chisnall goto again;
32827a984708SDavid Chisnall
32837a984708SDavid Chisnall case 'w':
32847a984708SDavid Chisnall /* wchar_t */
3285a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "wchar_t"))
32867a984708SDavid Chisnall goto clean;
32877a984708SDavid Chisnall ++ddata->cur;
32887a984708SDavid Chisnall goto rtn;
32897a984708SDavid Chisnall
32907a984708SDavid Chisnall case 'x':
32917a984708SDavid Chisnall /* long long */
3292a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "long long"))
32937a984708SDavid Chisnall goto clean;
32947a984708SDavid Chisnall ++ddata->cur;
32957a984708SDavid Chisnall goto rtn;
32967a984708SDavid Chisnall
32977a984708SDavid Chisnall case 'y':
32987a984708SDavid Chisnall /* unsigned long long */
3299a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "unsigned long long"))
33007a984708SDavid Chisnall goto clean;
33017a984708SDavid Chisnall ++ddata->cur;
33027a984708SDavid Chisnall goto rtn;
33037a984708SDavid Chisnall
33047a984708SDavid Chisnall case 'z':
33057a984708SDavid Chisnall /* ellipsis */
3306a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "..."))
33077a984708SDavid Chisnall goto clean;
33087a984708SDavid Chisnall ++ddata->cur;
33097a984708SDavid Chisnall goto rtn;
33104a1f3708SDimitry Andric }
33117a984708SDavid Chisnall
33127a984708SDavid Chisnall if (!cpp_demangle_read_name(ddata))
33137a984708SDavid Chisnall goto clean;
33147a984708SDavid Chisnall
33157a984708SDavid Chisnall is_builtin = 0;
33167a984708SDavid Chisnall rtn:
3317a7941b33SDimitry Andric
3318a7941b33SDimitry Andric type_str = vector_str_substr(output, p_idx, output->size - 1,
3319a7941b33SDimitry Andric &type_str_len);
33207a984708SDavid Chisnall
33217a984708SDavid Chisnall if (is_builtin == 0) {
33227a984708SDavid Chisnall if (!vector_str_find(&ddata->subst, type_str, type_str_len) &&
33237a984708SDavid Chisnall !vector_str_push(&ddata->subst, type_str, type_str_len))
33247a984708SDavid Chisnall goto clean;
33257a984708SDavid Chisnall }
33267a984708SDavid Chisnall
3327a7941b33SDimitry Andric if (!skip_ref_qualifier &&
3328a7941b33SDimitry Andric !cpp_demangle_push_type_qualifier(ddata, &v, type_str))
33297a984708SDavid Chisnall goto clean;
33307a984708SDavid Chisnall
3331a7941b33SDimitry Andric if (td)
3332a7941b33SDimitry Andric td->firstp = false;
3333a7941b33SDimitry Andric
33347a984708SDavid Chisnall free(type_str);
3335fa7477ceSEd Maste free(exp_str);
3336fa7477ceSEd Maste free(num_str);
33377a984708SDavid Chisnall vector_type_qualifier_dest(&v);
33387a984708SDavid Chisnall
33397a984708SDavid Chisnall return (1);
33407a984708SDavid Chisnall clean:
33417a984708SDavid Chisnall free(type_str);
3342fa7477ceSEd Maste free(exp_str);
3343fa7477ceSEd Maste free(num_str);
33447a984708SDavid Chisnall vector_type_qualifier_dest(&v);
33457a984708SDavid Chisnall
33467a984708SDavid Chisnall return (0);
33477a984708SDavid Chisnall }
33487a984708SDavid Chisnall
3349fa7477ceSEd Maste static int
cpp_demangle_read_type_flat(struct cpp_demangle_data * ddata,char ** str)3350fa7477ceSEd Maste cpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str)
3351fa7477ceSEd Maste {
3352fa7477ceSEd Maste struct vector_str *output;
3353fa7477ceSEd Maste size_t i, p_idx, idx, type_len;
3354fa7477ceSEd Maste char *type;
3355fa7477ceSEd Maste
3356a7941b33SDimitry Andric output = ddata->cur_output;
3357fa7477ceSEd Maste
3358fa7477ceSEd Maste p_idx = output->size;
3359fa7477ceSEd Maste
3360a7941b33SDimitry Andric if (!cpp_demangle_read_type(ddata, NULL))
3361fa7477ceSEd Maste return (0);
3362fa7477ceSEd Maste
3363fa7477ceSEd Maste if ((type = vector_str_substr(output, p_idx, output->size - 1,
3364fa7477ceSEd Maste &type_len)) == NULL)
3365fa7477ceSEd Maste return (0);
3366fa7477ceSEd Maste
3367fa7477ceSEd Maste idx = output->size;
3368fa7477ceSEd Maste for (i = p_idx; i < idx; ++i) {
3369fa7477ceSEd Maste if (!vector_str_pop(output)) {
3370fa7477ceSEd Maste free(type);
3371fa7477ceSEd Maste return (0);
3372fa7477ceSEd Maste }
3373fa7477ceSEd Maste }
3374fa7477ceSEd Maste
3375fa7477ceSEd Maste *str = type;
3376fa7477ceSEd Maste
3377fa7477ceSEd Maste return (1);
3378fa7477ceSEd Maste }
3379fa7477ceSEd Maste
33807a984708SDavid Chisnall /*
33817a984708SDavid Chisnall * read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
33827a984708SDavid Chisnall * source-name
33837a984708SDavid Chisnall */
33847a984708SDavid Chisnall static int
cpp_demangle_read_uqname(struct cpp_demangle_data * ddata)33857a984708SDavid Chisnall cpp_demangle_read_uqname(struct cpp_demangle_data *ddata)
33867a984708SDavid Chisnall {
33877a984708SDavid Chisnall size_t len;
33887a984708SDavid Chisnall
33897a984708SDavid Chisnall if (ddata == NULL || *ddata->cur == '\0')
33907a984708SDavid Chisnall return (0);
33917a984708SDavid Chisnall
33927a984708SDavid Chisnall /* operator name */
33937a984708SDavid Chisnall switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
33947a984708SDavid Chisnall case SIMPLE_HASH('a', 'a'):
33957a984708SDavid Chisnall /* operator && */
3396a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator&&"))
33977a984708SDavid Chisnall return (0);
33987a984708SDavid Chisnall ddata->cur += 2;
33997a984708SDavid Chisnall return (1);
34007a984708SDavid Chisnall
34017a984708SDavid Chisnall case SIMPLE_HASH('a', 'd'):
34027a984708SDavid Chisnall /* operator & (unary) */
3403a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator&"))
34047a984708SDavid Chisnall return (0);
34057a984708SDavid Chisnall ddata->cur += 2;
34067a984708SDavid Chisnall return (1);
34077a984708SDavid Chisnall
34087a984708SDavid Chisnall case SIMPLE_HASH('a', 'n'):
34097a984708SDavid Chisnall /* operator & */
3410a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator&"))
34117a984708SDavid Chisnall return (0);
34127a984708SDavid Chisnall ddata->cur += 2;
34137a984708SDavid Chisnall return (1);
34147a984708SDavid Chisnall
34157a984708SDavid Chisnall case SIMPLE_HASH('a', 'N'):
34167a984708SDavid Chisnall /* operator &= */
3417a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator&="))
34187a984708SDavid Chisnall return (0);
34197a984708SDavid Chisnall ddata->cur += 2;
34207a984708SDavid Chisnall return (1);
34217a984708SDavid Chisnall
34227a984708SDavid Chisnall case SIMPLE_HASH('a', 'S'):
34237a984708SDavid Chisnall /* operator = */
3424a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator="))
34257a984708SDavid Chisnall return (0);
34267a984708SDavid Chisnall ddata->cur += 2;
34277a984708SDavid Chisnall return (1);
34287a984708SDavid Chisnall
34297a984708SDavid Chisnall case SIMPLE_HASH('c', 'l'):
34307a984708SDavid Chisnall /* operator () */
3431a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator()"))
34327a984708SDavid Chisnall return (0);
34337a984708SDavid Chisnall ddata->cur += 2;
34347a984708SDavid Chisnall return (1);
34357a984708SDavid Chisnall
34367a984708SDavid Chisnall case SIMPLE_HASH('c', 'm'):
34377a984708SDavid Chisnall /* operator , */
3438a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator,"))
34397a984708SDavid Chisnall return (0);
34407a984708SDavid Chisnall ddata->cur += 2;
34417a984708SDavid Chisnall return (1);
34427a984708SDavid Chisnall
34437a984708SDavid Chisnall case SIMPLE_HASH('c', 'o'):
34447a984708SDavid Chisnall /* operator ~ */
3445a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator~"))
34467a984708SDavid Chisnall return (0);
34477a984708SDavid Chisnall ddata->cur += 2;
34487a984708SDavid Chisnall return (1);
34497a984708SDavid Chisnall
34507a984708SDavid Chisnall case SIMPLE_HASH('c', 'v'):
34517a984708SDavid Chisnall /* operator (cast) */
3452a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator(cast)"))
34537a984708SDavid Chisnall return (0);
34547a984708SDavid Chisnall ddata->cur += 2;
3455a7941b33SDimitry Andric return (cpp_demangle_read_type(ddata, NULL));
34567a984708SDavid Chisnall
34577a984708SDavid Chisnall case SIMPLE_HASH('d', 'a'):
34587a984708SDavid Chisnall /* operator delete [] */
3459a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator delete []"))
34607a984708SDavid Chisnall return (0);
34617a984708SDavid Chisnall ddata->cur += 2;
34627a984708SDavid Chisnall return (1);
34637a984708SDavid Chisnall
34647a984708SDavid Chisnall case SIMPLE_HASH('d', 'e'):
34657a984708SDavid Chisnall /* operator * (unary) */
3466a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator*"))
34677a984708SDavid Chisnall return (0);
34687a984708SDavid Chisnall ddata->cur += 2;
34697a984708SDavid Chisnall return (1);
34707a984708SDavid Chisnall
34717a984708SDavid Chisnall case SIMPLE_HASH('d', 'l'):
34727a984708SDavid Chisnall /* operator delete */
3473a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator delete"))
34747a984708SDavid Chisnall return (0);
34757a984708SDavid Chisnall ddata->cur += 2;
34767a984708SDavid Chisnall return (1);
34777a984708SDavid Chisnall
34787a984708SDavid Chisnall case SIMPLE_HASH('d', 'v'):
34797a984708SDavid Chisnall /* operator / */
3480a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator/"))
34817a984708SDavid Chisnall return (0);
34827a984708SDavid Chisnall ddata->cur += 2;
34837a984708SDavid Chisnall return (1);
34847a984708SDavid Chisnall
34857a984708SDavid Chisnall case SIMPLE_HASH('d', 'V'):
34867a984708SDavid Chisnall /* operator /= */
3487a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator/="))
34887a984708SDavid Chisnall return (0);
34897a984708SDavid Chisnall ddata->cur += 2;
34907a984708SDavid Chisnall return (1);
34917a984708SDavid Chisnall
34927a984708SDavid Chisnall case SIMPLE_HASH('e', 'o'):
34937a984708SDavid Chisnall /* operator ^ */
3494a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator^"))
34957a984708SDavid Chisnall return (0);
34967a984708SDavid Chisnall ddata->cur += 2;
34977a984708SDavid Chisnall return (1);
34987a984708SDavid Chisnall
34997a984708SDavid Chisnall case SIMPLE_HASH('e', 'O'):
35007a984708SDavid Chisnall /* operator ^= */
3501a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator^="))
35027a984708SDavid Chisnall return (0);
35037a984708SDavid Chisnall ddata->cur += 2;
35047a984708SDavid Chisnall return (1);
35057a984708SDavid Chisnall
35067a984708SDavid Chisnall case SIMPLE_HASH('e', 'q'):
35077a984708SDavid Chisnall /* operator == */
3508a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator=="))
35097a984708SDavid Chisnall return (0);
35107a984708SDavid Chisnall ddata->cur += 2;
35117a984708SDavid Chisnall return (1);
35127a984708SDavid Chisnall
35137a984708SDavid Chisnall case SIMPLE_HASH('g', 'e'):
35147a984708SDavid Chisnall /* operator >= */
3515a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator>="))
35167a984708SDavid Chisnall return (0);
35177a984708SDavid Chisnall ddata->cur += 2;
35187a984708SDavid Chisnall return (1);
35197a984708SDavid Chisnall
35207a984708SDavid Chisnall case SIMPLE_HASH('g', 't'):
35217a984708SDavid Chisnall /* operator > */
3522a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator>"))
35237a984708SDavid Chisnall return (0);
35247a984708SDavid Chisnall ddata->cur += 2;
35257a984708SDavid Chisnall return (1);
35267a984708SDavid Chisnall
35277a984708SDavid Chisnall case SIMPLE_HASH('i', 'x'):
35287a984708SDavid Chisnall /* operator [] */
3529a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator[]"))
35307a984708SDavid Chisnall return (0);
35317a984708SDavid Chisnall ddata->cur += 2;
35327a984708SDavid Chisnall return (1);
35337a984708SDavid Chisnall
35347a984708SDavid Chisnall case SIMPLE_HASH('l', 'e'):
35357a984708SDavid Chisnall /* operator <= */
3536a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator<="))
35377a984708SDavid Chisnall return (0);
35387a984708SDavid Chisnall ddata->cur += 2;
35397a984708SDavid Chisnall return (1);
35407a984708SDavid Chisnall
35417a984708SDavid Chisnall case SIMPLE_HASH('l', 's'):
35427a984708SDavid Chisnall /* operator << */
3543a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator<<"))
35447a984708SDavid Chisnall return (0);
35457a984708SDavid Chisnall ddata->cur += 2;
35467a984708SDavid Chisnall return (1);
35477a984708SDavid Chisnall
35487a984708SDavid Chisnall case SIMPLE_HASH('l', 'S'):
35497a984708SDavid Chisnall /* operator <<= */
3550a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator<<="))
35517a984708SDavid Chisnall return (0);
35527a984708SDavid Chisnall ddata->cur += 2;
35537a984708SDavid Chisnall return (1);
35547a984708SDavid Chisnall
35557a984708SDavid Chisnall case SIMPLE_HASH('l', 't'):
35567a984708SDavid Chisnall /* operator < */
3557a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator<"))
35587a984708SDavid Chisnall return (0);
35597a984708SDavid Chisnall ddata->cur += 2;
35607a984708SDavid Chisnall return (1);
35617a984708SDavid Chisnall
35627a984708SDavid Chisnall case SIMPLE_HASH('m', 'i'):
35637a984708SDavid Chisnall /* operator - */
3564a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator-"))
35657a984708SDavid Chisnall return (0);
35667a984708SDavid Chisnall ddata->cur += 2;
35677a984708SDavid Chisnall return (1);
35687a984708SDavid Chisnall
35697a984708SDavid Chisnall case SIMPLE_HASH('m', 'I'):
35707a984708SDavid Chisnall /* operator -= */
3571a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator-="))
35727a984708SDavid Chisnall return (0);
35737a984708SDavid Chisnall ddata->cur += 2;
35747a984708SDavid Chisnall return (1);
35757a984708SDavid Chisnall
35767a984708SDavid Chisnall case SIMPLE_HASH('m', 'l'):
35777a984708SDavid Chisnall /* operator * */
3578a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator*"))
35797a984708SDavid Chisnall return (0);
35807a984708SDavid Chisnall ddata->cur += 2;
35817a984708SDavid Chisnall return (1);
35827a984708SDavid Chisnall
35837a984708SDavid Chisnall case SIMPLE_HASH('m', 'L'):
35847a984708SDavid Chisnall /* operator *= */
3585a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator*="))
35867a984708SDavid Chisnall return (0);
35877a984708SDavid Chisnall ddata->cur += 2;
35887a984708SDavid Chisnall return (1);
35897a984708SDavid Chisnall
35907a984708SDavid Chisnall case SIMPLE_HASH('m', 'm'):
35917a984708SDavid Chisnall /* operator -- */
3592a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator--"))
35937a984708SDavid Chisnall return (0);
35947a984708SDavid Chisnall ddata->cur += 2;
35957a984708SDavid Chisnall return (1);
35967a984708SDavid Chisnall
35977a984708SDavid Chisnall case SIMPLE_HASH('n', 'a'):
35987a984708SDavid Chisnall /* operator new[] */
3599a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator new []"))
36007a984708SDavid Chisnall return (0);
36017a984708SDavid Chisnall ddata->cur += 2;
36027a984708SDavid Chisnall return (1);
36037a984708SDavid Chisnall
36047a984708SDavid Chisnall case SIMPLE_HASH('n', 'e'):
36057a984708SDavid Chisnall /* operator != */
3606a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator!="))
36077a984708SDavid Chisnall return (0);
36087a984708SDavid Chisnall ddata->cur += 2;
36097a984708SDavid Chisnall return (1);
36107a984708SDavid Chisnall
36117a984708SDavid Chisnall case SIMPLE_HASH('n', 'g'):
36127a984708SDavid Chisnall /* operator - (unary) */
3613a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator-"))
36147a984708SDavid Chisnall return (0);
36157a984708SDavid Chisnall ddata->cur += 2;
36167a984708SDavid Chisnall return (1);
36177a984708SDavid Chisnall
36187a984708SDavid Chisnall case SIMPLE_HASH('n', 't'):
36197a984708SDavid Chisnall /* operator ! */
3620a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator!"))
36217a984708SDavid Chisnall return (0);
36227a984708SDavid Chisnall ddata->cur += 2;
36237a984708SDavid Chisnall return (1);
36247a984708SDavid Chisnall
36257a984708SDavid Chisnall case SIMPLE_HASH('n', 'w'):
36267a984708SDavid Chisnall /* operator new */
3627a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator new"))
36287a984708SDavid Chisnall return (0);
36297a984708SDavid Chisnall ddata->cur += 2;
36307a984708SDavid Chisnall return (1);
36317a984708SDavid Chisnall
36327a984708SDavid Chisnall case SIMPLE_HASH('o', 'o'):
36337a984708SDavid Chisnall /* operator || */
3634a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator||"))
36357a984708SDavid Chisnall return (0);
36367a984708SDavid Chisnall ddata->cur += 2;
36377a984708SDavid Chisnall return (1);
36387a984708SDavid Chisnall
36397a984708SDavid Chisnall case SIMPLE_HASH('o', 'r'):
36407a984708SDavid Chisnall /* operator | */
3641a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator|"))
36427a984708SDavid Chisnall return (0);
36437a984708SDavid Chisnall ddata->cur += 2;
36447a984708SDavid Chisnall return (1);
36457a984708SDavid Chisnall
36467a984708SDavid Chisnall case SIMPLE_HASH('o', 'R'):
36477a984708SDavid Chisnall /* operator |= */
3648a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator|="))
36497a984708SDavid Chisnall return (0);
36507a984708SDavid Chisnall ddata->cur += 2;
36517a984708SDavid Chisnall return (1);
36527a984708SDavid Chisnall
36537a984708SDavid Chisnall case SIMPLE_HASH('p', 'l'):
36547a984708SDavid Chisnall /* operator + */
3655a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator+"))
36567a984708SDavid Chisnall return (0);
36577a984708SDavid Chisnall ddata->cur += 2;
36587a984708SDavid Chisnall return (1);
36597a984708SDavid Chisnall
36607a984708SDavid Chisnall case SIMPLE_HASH('p', 'L'):
36617a984708SDavid Chisnall /* operator += */
3662a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator+="))
36637a984708SDavid Chisnall return (0);
36647a984708SDavid Chisnall ddata->cur += 2;
36657a984708SDavid Chisnall return (1);
36667a984708SDavid Chisnall
36677a984708SDavid Chisnall case SIMPLE_HASH('p', 'm'):
36687a984708SDavid Chisnall /* operator ->* */
3669a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator->*"))
36707a984708SDavid Chisnall return (0);
36717a984708SDavid Chisnall ddata->cur += 2;
36727a984708SDavid Chisnall return (1);
36737a984708SDavid Chisnall
36747a984708SDavid Chisnall case SIMPLE_HASH('p', 'p'):
36757a984708SDavid Chisnall /* operator ++ */
3676a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator++"))
36777a984708SDavid Chisnall return (0);
36787a984708SDavid Chisnall ddata->cur += 2;
36797a984708SDavid Chisnall return (1);
36807a984708SDavid Chisnall
36817a984708SDavid Chisnall case SIMPLE_HASH('p', 's'):
36827a984708SDavid Chisnall /* operator + (unary) */
3683a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator+"))
36847a984708SDavid Chisnall return (0);
36857a984708SDavid Chisnall ddata->cur += 2;
36867a984708SDavid Chisnall return (1);
36877a984708SDavid Chisnall
36887a984708SDavid Chisnall case SIMPLE_HASH('p', 't'):
36897a984708SDavid Chisnall /* operator -> */
3690a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator->"))
36917a984708SDavid Chisnall return (0);
36927a984708SDavid Chisnall ddata->cur += 2;
36937a984708SDavid Chisnall return (1);
36947a984708SDavid Chisnall
36957a984708SDavid Chisnall case SIMPLE_HASH('q', 'u'):
36967a984708SDavid Chisnall /* operator ? */
3697a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator?"))
36987a984708SDavid Chisnall return (0);
36997a984708SDavid Chisnall ddata->cur += 2;
37007a984708SDavid Chisnall return (1);
37017a984708SDavid Chisnall
37027a984708SDavid Chisnall case SIMPLE_HASH('r', 'm'):
37037a984708SDavid Chisnall /* operator % */
3704a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator%"))
37057a984708SDavid Chisnall return (0);
37067a984708SDavid Chisnall ddata->cur += 2;
37077a984708SDavid Chisnall return (1);
37087a984708SDavid Chisnall
37097a984708SDavid Chisnall case SIMPLE_HASH('r', 'M'):
37107a984708SDavid Chisnall /* operator %= */
3711a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator%="))
37127a984708SDavid Chisnall return (0);
37137a984708SDavid Chisnall ddata->cur += 2;
37147a984708SDavid Chisnall return (1);
37157a984708SDavid Chisnall
37167a984708SDavid Chisnall case SIMPLE_HASH('r', 's'):
37177a984708SDavid Chisnall /* operator >> */
3718a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator>>"))
37197a984708SDavid Chisnall return (0);
37207a984708SDavid Chisnall ddata->cur += 2;
37217a984708SDavid Chisnall return (1);
37227a984708SDavid Chisnall
37237a984708SDavid Chisnall case SIMPLE_HASH('r', 'S'):
37247a984708SDavid Chisnall /* operator >>= */
3725a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator>>="))
37267a984708SDavid Chisnall return (0);
37277a984708SDavid Chisnall ddata->cur += 2;
37287a984708SDavid Chisnall return (1);
37297a984708SDavid Chisnall
37307a984708SDavid Chisnall case SIMPLE_HASH('r', 'z'):
37317a984708SDavid Chisnall /* operator sizeof */
3732a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator sizeof "))
37337a984708SDavid Chisnall return (0);
37347a984708SDavid Chisnall ddata->cur += 2;
37357a984708SDavid Chisnall return (1);
37367a984708SDavid Chisnall
37377a984708SDavid Chisnall case SIMPLE_HASH('s', 'r'):
37387a984708SDavid Chisnall /* scope resolution operator */
3739a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "scope resolution operator "))
37407a984708SDavid Chisnall return (0);
37417a984708SDavid Chisnall ddata->cur += 2;
37427a984708SDavid Chisnall return (1);
37437a984708SDavid Chisnall
37447a984708SDavid Chisnall case SIMPLE_HASH('s', 'v'):
37457a984708SDavid Chisnall /* operator sizeof */
3746a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "operator sizeof "))
37477a984708SDavid Chisnall return (0);
37487a984708SDavid Chisnall ddata->cur += 2;
37497a984708SDavid Chisnall return (1);
37504a1f3708SDimitry Andric }
37517a984708SDavid Chisnall
37527a984708SDavid Chisnall /* vendor extened operator */
37537a984708SDavid Chisnall if (*ddata->cur == 'v' && ELFTC_ISDIGIT(*(ddata->cur + 1))) {
3754a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "vendor extened operator "))
37557a984708SDavid Chisnall return (0);
37567a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, ddata->cur + 1, 1))
37577a984708SDavid Chisnall return (0);
37587a984708SDavid Chisnall ddata->cur += 2;
37597a984708SDavid Chisnall return (cpp_demangle_read_sname(ddata));
37607a984708SDavid Chisnall }
37617a984708SDavid Chisnall
37627a984708SDavid Chisnall /* ctor-dtor-name */
37637a984708SDavid Chisnall switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
37647a984708SDavid Chisnall case SIMPLE_HASH('C', '1'):
37657a984708SDavid Chisnall case SIMPLE_HASH('C', '2'):
37667a984708SDavid Chisnall case SIMPLE_HASH('C', '3'):
37677a984708SDavid Chisnall if (ddata->last_sname == NULL)
37687a984708SDavid Chisnall return (0);
37697a984708SDavid Chisnall if ((len = strlen(ddata->last_sname)) == 0)
37707a984708SDavid Chisnall return (0);
3771a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "::"))
37727a984708SDavid Chisnall return (0);
37737a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
37747a984708SDavid Chisnall return (0);
37757a984708SDavid Chisnall ddata->cur +=2;
37767a984708SDavid Chisnall return (1);
37777a984708SDavid Chisnall
37787a984708SDavid Chisnall case SIMPLE_HASH('D', '0'):
37797a984708SDavid Chisnall case SIMPLE_HASH('D', '1'):
37807a984708SDavid Chisnall case SIMPLE_HASH('D', '2'):
37817a984708SDavid Chisnall if (ddata->last_sname == NULL)
37827a984708SDavid Chisnall return (0);
37837a984708SDavid Chisnall if ((len = strlen(ddata->last_sname)) == 0)
37847a984708SDavid Chisnall return (0);
3785a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "::~"))
37867a984708SDavid Chisnall return (0);
37877a984708SDavid Chisnall if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
37887a984708SDavid Chisnall return (0);
37897a984708SDavid Chisnall ddata->cur +=2;
37907a984708SDavid Chisnall return (1);
37914a1f3708SDimitry Andric }
37927a984708SDavid Chisnall
37937a984708SDavid Chisnall /* source name */
37947a984708SDavid Chisnall if (ELFTC_ISDIGIT(*ddata->cur) != 0)
37957a984708SDavid Chisnall return (cpp_demangle_read_sname(ddata));
37967a984708SDavid Chisnall
37970f9eee39SDavid Chisnall /* local source name */
37980f9eee39SDavid Chisnall if (*ddata->cur == 'L')
37990f9eee39SDavid Chisnall return (cpp_demangle_local_source_name(ddata));
38000f9eee39SDavid Chisnall
38010f9eee39SDavid Chisnall return (1);
38020f9eee39SDavid Chisnall }
38030f9eee39SDavid Chisnall
38040f9eee39SDavid Chisnall /*
38050f9eee39SDavid Chisnall * Read local source name.
38060f9eee39SDavid Chisnall *
38070f9eee39SDavid Chisnall * References:
38080f9eee39SDavid Chisnall * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
38090f9eee39SDavid Chisnall * http://gcc.gnu.org/viewcvs?view=rev&revision=124467
38100f9eee39SDavid Chisnall */
38110f9eee39SDavid Chisnall static int
cpp_demangle_local_source_name(struct cpp_demangle_data * ddata)38120f9eee39SDavid Chisnall cpp_demangle_local_source_name(struct cpp_demangle_data *ddata)
38130f9eee39SDavid Chisnall {
38140f9eee39SDavid Chisnall /* L */
38150f9eee39SDavid Chisnall if (ddata == NULL || *ddata->cur != 'L')
38160f9eee39SDavid Chisnall return (0);
38170f9eee39SDavid Chisnall ++ddata->cur;
38180f9eee39SDavid Chisnall
38190f9eee39SDavid Chisnall /* source name */
38200f9eee39SDavid Chisnall if (!cpp_demangle_read_sname(ddata))
38210f9eee39SDavid Chisnall return (0);
38220f9eee39SDavid Chisnall
38230f9eee39SDavid Chisnall /* discriminator */
38240f9eee39SDavid Chisnall if (*ddata->cur == '_') {
38250f9eee39SDavid Chisnall ++ddata->cur;
38260f9eee39SDavid Chisnall while (ELFTC_ISDIGIT(*ddata->cur) != 0)
38270f9eee39SDavid Chisnall ++ddata->cur;
38280f9eee39SDavid Chisnall }
38290f9eee39SDavid Chisnall
38307a984708SDavid Chisnall return (1);
38317a984708SDavid Chisnall }
38327a984708SDavid Chisnall
38337a984708SDavid Chisnall static int
cpp_demangle_read_v_offset(struct cpp_demangle_data * ddata)38347a984708SDavid Chisnall cpp_demangle_read_v_offset(struct cpp_demangle_data *ddata)
38357a984708SDavid Chisnall {
38367a984708SDavid Chisnall
38377a984708SDavid Chisnall if (ddata == NULL)
38387a984708SDavid Chisnall return (0);
38397a984708SDavid Chisnall
3840a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "offset : "))
38417a984708SDavid Chisnall return (0);
38427a984708SDavid Chisnall
38437a984708SDavid Chisnall if (!cpp_demangle_read_offset_number(ddata))
38447a984708SDavid Chisnall return (0);
38457a984708SDavid Chisnall
3846a7941b33SDimitry Andric if (!DEM_PUSH_STR(ddata, "virtual offset : "))
38477a984708SDavid Chisnall return (0);
38487a984708SDavid Chisnall
38497a984708SDavid Chisnall return (!cpp_demangle_read_offset_number(ddata));
38507a984708SDavid Chisnall }
38517a984708SDavid Chisnall
38527a984708SDavid Chisnall /*
38537a984708SDavid Chisnall * Decode floating point representation to string
38547a984708SDavid Chisnall * Return new allocated string or NULL
38557a984708SDavid Chisnall *
38567a984708SDavid Chisnall * Todo
38577a984708SDavid Chisnall * Replace these functions to macro.
38587a984708SDavid Chisnall */
38597a984708SDavid Chisnall static char *
decode_fp_to_double(const char * p,size_t len)38607a984708SDavid Chisnall decode_fp_to_double(const char *p, size_t len)
38617a984708SDavid Chisnall {
38627a984708SDavid Chisnall double f;
38637a984708SDavid Chisnall size_t rtn_len, limit, i;
38647a984708SDavid Chisnall int byte;
38657a984708SDavid Chisnall char *rtn;
38667a984708SDavid Chisnall
38677a984708SDavid Chisnall if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(double))
38687a984708SDavid Chisnall return (NULL);
38697a984708SDavid Chisnall
38707a984708SDavid Chisnall memset(&f, 0, sizeof(double));
38717a984708SDavid Chisnall
38727a984708SDavid Chisnall for (i = 0; i < len / 2; ++i) {
38737a984708SDavid Chisnall byte = hex_to_dec(p[len - i * 2 - 1]) +
38747a984708SDavid Chisnall hex_to_dec(p[len - i * 2 - 2]) * 16;
38757a984708SDavid Chisnall
38767a984708SDavid Chisnall if (byte < 0 || byte > 255)
38777a984708SDavid Chisnall return (NULL);
38787a984708SDavid Chisnall
38797a984708SDavid Chisnall #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
38807a984708SDavid Chisnall ((unsigned char *)&f)[i] = (unsigned char)(byte);
38817a984708SDavid Chisnall #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
38827a984708SDavid Chisnall ((unsigned char *)&f)[sizeof(double) - i - 1] =
38837a984708SDavid Chisnall (unsigned char)(byte);
38847a984708SDavid Chisnall #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
38857a984708SDavid Chisnall }
38867a984708SDavid Chisnall
38877a984708SDavid Chisnall rtn_len = 64;
38887a984708SDavid Chisnall limit = 0;
38897a984708SDavid Chisnall again:
38907a984708SDavid Chisnall if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
38917a984708SDavid Chisnall return (NULL);
38927a984708SDavid Chisnall
38937a984708SDavid Chisnall if (snprintf(rtn, rtn_len, "%fld", f) >= (int)rtn_len) {
38947a984708SDavid Chisnall free(rtn);
38957a984708SDavid Chisnall if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
38967a984708SDavid Chisnall return (NULL);
38977a984708SDavid Chisnall rtn_len *= BUFFER_GROWFACTOR;
38987a984708SDavid Chisnall goto again;
38997a984708SDavid Chisnall }
39007a984708SDavid Chisnall
39017a984708SDavid Chisnall return rtn;
39027a984708SDavid Chisnall }
39037a984708SDavid Chisnall
39047a984708SDavid Chisnall static char *
decode_fp_to_float(const char * p,size_t len)39057a984708SDavid Chisnall decode_fp_to_float(const char *p, size_t len)
39067a984708SDavid Chisnall {
39077a984708SDavid Chisnall size_t i, rtn_len, limit;
39087a984708SDavid Chisnall float f;
39097a984708SDavid Chisnall int byte;
39107a984708SDavid Chisnall char *rtn;
39117a984708SDavid Chisnall
39127a984708SDavid Chisnall if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(float))
39137a984708SDavid Chisnall return (NULL);
39147a984708SDavid Chisnall
39157a984708SDavid Chisnall memset(&f, 0, sizeof(float));
39167a984708SDavid Chisnall
39177a984708SDavid Chisnall for (i = 0; i < len / 2; ++i) {
39187a984708SDavid Chisnall byte = hex_to_dec(p[len - i * 2 - 1]) +
39197a984708SDavid Chisnall hex_to_dec(p[len - i * 2 - 2]) * 16;
39207a984708SDavid Chisnall if (byte < 0 || byte > 255)
39217a984708SDavid Chisnall return (NULL);
39227a984708SDavid Chisnall #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
39237a984708SDavid Chisnall ((unsigned char *)&f)[i] = (unsigned char)(byte);
39247a984708SDavid Chisnall #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39257a984708SDavid Chisnall ((unsigned char *)&f)[sizeof(float) - i - 1] =
39267a984708SDavid Chisnall (unsigned char)(byte);
39277a984708SDavid Chisnall #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39287a984708SDavid Chisnall }
39297a984708SDavid Chisnall
39307a984708SDavid Chisnall rtn_len = 64;
39317a984708SDavid Chisnall limit = 0;
39327a984708SDavid Chisnall again:
39337a984708SDavid Chisnall if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
39347a984708SDavid Chisnall return (NULL);
39357a984708SDavid Chisnall
39367a984708SDavid Chisnall if (snprintf(rtn, rtn_len, "%ff", f) >= (int)rtn_len) {
39377a984708SDavid Chisnall free(rtn);
39387a984708SDavid Chisnall if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
39397a984708SDavid Chisnall return (NULL);
39407a984708SDavid Chisnall rtn_len *= BUFFER_GROWFACTOR;
39417a984708SDavid Chisnall goto again;
39427a984708SDavid Chisnall }
39437a984708SDavid Chisnall
39447a984708SDavid Chisnall return rtn;
39457a984708SDavid Chisnall }
39467a984708SDavid Chisnall
39477a984708SDavid Chisnall static char *
decode_fp_to_float128(const char * p,size_t len)39487a984708SDavid Chisnall decode_fp_to_float128(const char *p, size_t len)
39497a984708SDavid Chisnall {
39507a984708SDavid Chisnall long double f;
39517a984708SDavid Chisnall size_t rtn_len, limit, i;
39527a984708SDavid Chisnall int byte;
39537a984708SDavid Chisnall unsigned char buf[FLOAT_QUADRUPLE_BYTES];
39547a984708SDavid Chisnall char *rtn;
39557a984708SDavid Chisnall
39567a984708SDavid Chisnall switch(sizeof(long double)) {
39577a984708SDavid Chisnall case FLOAT_QUADRUPLE_BYTES:
39587a984708SDavid Chisnall return (decode_fp_to_long_double(p, len));
39597a984708SDavid Chisnall case FLOAT_EXTENED_BYTES:
39607a984708SDavid Chisnall if (p == NULL || len == 0 || len % 2 != 0 ||
39617a984708SDavid Chisnall len / 2 > FLOAT_QUADRUPLE_BYTES)
39627a984708SDavid Chisnall return (NULL);
39637a984708SDavid Chisnall
39647a984708SDavid Chisnall memset(buf, 0, FLOAT_QUADRUPLE_BYTES);
39657a984708SDavid Chisnall
39667a984708SDavid Chisnall for (i = 0; i < len / 2; ++i) {
39677a984708SDavid Chisnall byte = hex_to_dec(p[len - i * 2 - 1]) +
39687a984708SDavid Chisnall hex_to_dec(p[len - i * 2 - 2]) * 16;
39697a984708SDavid Chisnall if (byte < 0 || byte > 255)
39707a984708SDavid Chisnall return (NULL);
39717a984708SDavid Chisnall #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
39727a984708SDavid Chisnall buf[i] = (unsigned char)(byte);
39737a984708SDavid Chisnall #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39747a984708SDavid Chisnall buf[FLOAT_QUADRUPLE_BYTES - i -1] =
39757a984708SDavid Chisnall (unsigned char)(byte);
39767a984708SDavid Chisnall #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39777a984708SDavid Chisnall }
39787a984708SDavid Chisnall memset(&f, 0, FLOAT_EXTENED_BYTES);
39797a984708SDavid Chisnall
39807a984708SDavid Chisnall #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
39817a984708SDavid Chisnall memcpy(&f, buf, FLOAT_EXTENED_BYTES);
39827a984708SDavid Chisnall #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39837a984708SDavid Chisnall memcpy(&f, buf + 6, FLOAT_EXTENED_BYTES);
39847a984708SDavid Chisnall #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39857a984708SDavid Chisnall
39867a984708SDavid Chisnall rtn_len = 256;
39877a984708SDavid Chisnall limit = 0;
39887a984708SDavid Chisnall again:
39897a984708SDavid Chisnall if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
39907a984708SDavid Chisnall return (NULL);
39917a984708SDavid Chisnall
39927a984708SDavid Chisnall if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
39937a984708SDavid Chisnall free(rtn);
39947a984708SDavid Chisnall if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
39957a984708SDavid Chisnall return (NULL);
39967a984708SDavid Chisnall rtn_len *= BUFFER_GROWFACTOR;
39977a984708SDavid Chisnall goto again;
39987a984708SDavid Chisnall }
39997a984708SDavid Chisnall
40007a984708SDavid Chisnall return (rtn);
40017a984708SDavid Chisnall default:
40027a984708SDavid Chisnall return (NULL);
40037a984708SDavid Chisnall }
40047a984708SDavid Chisnall }
40057a984708SDavid Chisnall
40067a984708SDavid Chisnall static char *
decode_fp_to_float80(const char * p,size_t len)40077a984708SDavid Chisnall decode_fp_to_float80(const char *p, size_t len)
40087a984708SDavid Chisnall {
40097a984708SDavid Chisnall long double f;
40107a984708SDavid Chisnall size_t rtn_len, limit, i;
40117a984708SDavid Chisnall int byte;
40127a984708SDavid Chisnall unsigned char buf[FLOAT_EXTENED_BYTES];
40137a984708SDavid Chisnall char *rtn;
40147a984708SDavid Chisnall
40157a984708SDavid Chisnall switch(sizeof(long double)) {
40167a984708SDavid Chisnall case FLOAT_QUADRUPLE_BYTES:
40177a984708SDavid Chisnall if (p == NULL || len == 0 || len % 2 != 0 ||
40187a984708SDavid Chisnall len / 2 > FLOAT_EXTENED_BYTES)
40197a984708SDavid Chisnall return (NULL);
40207a984708SDavid Chisnall
40217a984708SDavid Chisnall memset(buf, 0, FLOAT_EXTENED_BYTES);
40227a984708SDavid Chisnall
40237a984708SDavid Chisnall for (i = 0; i < len / 2; ++i) {
40247a984708SDavid Chisnall byte = hex_to_dec(p[len - i * 2 - 1]) +
40257a984708SDavid Chisnall hex_to_dec(p[len - i * 2 - 2]) * 16;
40267a984708SDavid Chisnall
40277a984708SDavid Chisnall if (byte < 0 || byte > 255)
40287a984708SDavid Chisnall return (NULL);
40297a984708SDavid Chisnall
40307a984708SDavid Chisnall #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
40317a984708SDavid Chisnall buf[i] = (unsigned char)(byte);
40327a984708SDavid Chisnall #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40337a984708SDavid Chisnall buf[FLOAT_EXTENED_BYTES - i -1] =
40347a984708SDavid Chisnall (unsigned char)(byte);
40357a984708SDavid Chisnall #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40367a984708SDavid Chisnall }
40377a984708SDavid Chisnall
40387a984708SDavid Chisnall memset(&f, 0, FLOAT_QUADRUPLE_BYTES);
40397a984708SDavid Chisnall
40407a984708SDavid Chisnall #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
40417a984708SDavid Chisnall memcpy(&f, buf, FLOAT_EXTENED_BYTES);
40427a984708SDavid Chisnall #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40437a984708SDavid Chisnall memcpy((unsigned char *)(&f) + 6, buf, FLOAT_EXTENED_BYTES);
40447a984708SDavid Chisnall #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40457a984708SDavid Chisnall
40467a984708SDavid Chisnall rtn_len = 256;
40477a984708SDavid Chisnall limit = 0;
40487a984708SDavid Chisnall again:
40497a984708SDavid Chisnall if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
40507a984708SDavid Chisnall return (NULL);
40517a984708SDavid Chisnall
40527a984708SDavid Chisnall if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
40537a984708SDavid Chisnall free(rtn);
40547a984708SDavid Chisnall if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
40557a984708SDavid Chisnall return (NULL);
40567a984708SDavid Chisnall rtn_len *= BUFFER_GROWFACTOR;
40577a984708SDavid Chisnall goto again;
40587a984708SDavid Chisnall }
40597a984708SDavid Chisnall
40607a984708SDavid Chisnall return (rtn);
40617a984708SDavid Chisnall case FLOAT_EXTENED_BYTES:
40627a984708SDavid Chisnall return (decode_fp_to_long_double(p, len));
40637a984708SDavid Chisnall default:
40647a984708SDavid Chisnall return (NULL);
40657a984708SDavid Chisnall }
40667a984708SDavid Chisnall }
40677a984708SDavid Chisnall
40687a984708SDavid Chisnall static char *
decode_fp_to_long_double(const char * p,size_t len)40697a984708SDavid Chisnall decode_fp_to_long_double(const char *p, size_t len)
40707a984708SDavid Chisnall {
40717a984708SDavid Chisnall long double f;
40727a984708SDavid Chisnall size_t rtn_len, limit, i;
40737a984708SDavid Chisnall int byte;
40747a984708SDavid Chisnall char *rtn;
40757a984708SDavid Chisnall
40767a984708SDavid Chisnall if (p == NULL || len == 0 || len % 2 != 0 ||
40777a984708SDavid Chisnall len / 2 > sizeof(long double))
40787a984708SDavid Chisnall return (NULL);
40797a984708SDavid Chisnall
40807a984708SDavid Chisnall memset(&f, 0, sizeof(long double));
40817a984708SDavid Chisnall
40827a984708SDavid Chisnall for (i = 0; i < len / 2; ++i) {
40837a984708SDavid Chisnall byte = hex_to_dec(p[len - i * 2 - 1]) +
40847a984708SDavid Chisnall hex_to_dec(p[len - i * 2 - 2]) * 16;
40857a984708SDavid Chisnall
40867a984708SDavid Chisnall if (byte < 0 || byte > 255)
40877a984708SDavid Chisnall return (NULL);
40887a984708SDavid Chisnall
40897a984708SDavid Chisnall #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
40907a984708SDavid Chisnall ((unsigned char *)&f)[i] = (unsigned char)(byte);
40917a984708SDavid Chisnall #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40927a984708SDavid Chisnall ((unsigned char *)&f)[sizeof(long double) - i - 1] =
40937a984708SDavid Chisnall (unsigned char)(byte);
40947a984708SDavid Chisnall #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40957a984708SDavid Chisnall }
40967a984708SDavid Chisnall
40977a984708SDavid Chisnall rtn_len = 256;
40987a984708SDavid Chisnall limit = 0;
40997a984708SDavid Chisnall again:
41007a984708SDavid Chisnall if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
41017a984708SDavid Chisnall return (NULL);
41027a984708SDavid Chisnall
41037a984708SDavid Chisnall if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
41047a984708SDavid Chisnall free(rtn);
41057a984708SDavid Chisnall if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
41067a984708SDavid Chisnall return (NULL);
41077a984708SDavid Chisnall rtn_len *= BUFFER_GROWFACTOR;
41087a984708SDavid Chisnall goto again;
41097a984708SDavid Chisnall }
41107a984708SDavid Chisnall
41117a984708SDavid Chisnall return (rtn);
41127a984708SDavid Chisnall }
41137a984708SDavid Chisnall
41147a984708SDavid Chisnall /* Simple hex to integer function used by decode_to_* function. */
41157a984708SDavid Chisnall static int
hex_to_dec(char c)41167a984708SDavid Chisnall hex_to_dec(char c)
41177a984708SDavid Chisnall {
41187a984708SDavid Chisnall
41197a984708SDavid Chisnall switch (c) {
41207a984708SDavid Chisnall case '0':
41217a984708SDavid Chisnall return (0);
41227a984708SDavid Chisnall case '1':
41237a984708SDavid Chisnall return (1);
41247a984708SDavid Chisnall case '2':
41257a984708SDavid Chisnall return (2);
41267a984708SDavid Chisnall case '3':
41277a984708SDavid Chisnall return (3);
41287a984708SDavid Chisnall case '4':
41297a984708SDavid Chisnall return (4);
41307a984708SDavid Chisnall case '5':
41317a984708SDavid Chisnall return (5);
41327a984708SDavid Chisnall case '6':
41337a984708SDavid Chisnall return (6);
41347a984708SDavid Chisnall case '7':
41357a984708SDavid Chisnall return (7);
41367a984708SDavid Chisnall case '8':
41377a984708SDavid Chisnall return (8);
41387a984708SDavid Chisnall case '9':
41397a984708SDavid Chisnall return (9);
41407a984708SDavid Chisnall case 'a':
41417a984708SDavid Chisnall return (10);
41427a984708SDavid Chisnall case 'b':
41437a984708SDavid Chisnall return (11);
41447a984708SDavid Chisnall case 'c':
41457a984708SDavid Chisnall return (12);
41467a984708SDavid Chisnall case 'd':
41477a984708SDavid Chisnall return (13);
41487a984708SDavid Chisnall case 'e':
41497a984708SDavid Chisnall return (14);
41507a984708SDavid Chisnall case 'f':
41517a984708SDavid Chisnall return (15);
41527a984708SDavid Chisnall default:
41537a984708SDavid Chisnall return (-1);
41544a1f3708SDimitry Andric }
41557a984708SDavid Chisnall }
41567a984708SDavid Chisnall
4157a7941b33SDimitry Andric /**
4158a7941b33SDimitry Andric * @brief Test input string is mangled by IA-64 C++ ABI style.
4159a7941b33SDimitry Andric *
4160a7941b33SDimitry Andric * Test string heads with "_Z" or "_GLOBAL__I_".
4161a7941b33SDimitry Andric * @return Return 0 at false.
4162a7941b33SDimitry Andric */
4163a7941b33SDimitry Andric bool
is_cpp_mangled_gnu3(const char * org)4164a7941b33SDimitry Andric is_cpp_mangled_gnu3(const char *org)
4165a7941b33SDimitry Andric {
4166a7941b33SDimitry Andric size_t len;
4167a7941b33SDimitry Andric
4168a7941b33SDimitry Andric len = strlen(org);
4169a7941b33SDimitry Andric return ((len > 2 && *org == '_' && *(org + 1) == 'Z') ||
4170a7941b33SDimitry Andric (len > 11 && !strncmp(org, "_GLOBAL__I_", 11)));
4171a7941b33SDimitry Andric }
4172a7941b33SDimitry Andric
41737a984708SDavid Chisnall static void
vector_read_cmd_dest(struct vector_read_cmd * v)41747a984708SDavid Chisnall vector_read_cmd_dest(struct vector_read_cmd *v)
41757a984708SDavid Chisnall {
41767a984708SDavid Chisnall
41777a984708SDavid Chisnall if (v == NULL)
41787a984708SDavid Chisnall return;
41797a984708SDavid Chisnall
41807a984708SDavid Chisnall free(v->r_container);
41817a984708SDavid Chisnall }
41827a984708SDavid Chisnall
4183a7941b33SDimitry Andric static struct read_cmd_item *
vector_read_cmd_find(struct vector_read_cmd * v,enum read_cmd dst)41847a984708SDavid Chisnall vector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst)
41857a984708SDavid Chisnall {
4186a7941b33SDimitry Andric int i;
41877a984708SDavid Chisnall
41887a984708SDavid Chisnall if (v == NULL || dst == READ_FAIL)
4189a7941b33SDimitry Andric return (NULL);
41907a984708SDavid Chisnall
4191a7941b33SDimitry Andric for (i = (int) v->size - 1; i >= 0; i--)
4192a7941b33SDimitry Andric if (v->r_container[i].cmd == dst)
4193a7941b33SDimitry Andric return (&v->r_container[i]);
41947a984708SDavid Chisnall
4195a7941b33SDimitry Andric return (NULL);
41967a984708SDavid Chisnall }
41977a984708SDavid Chisnall
41987a984708SDavid Chisnall static int
vector_read_cmd_init(struct vector_read_cmd * v)41997a984708SDavid Chisnall vector_read_cmd_init(struct vector_read_cmd *v)
42007a984708SDavid Chisnall {
42017a984708SDavid Chisnall
42027a984708SDavid Chisnall if (v == NULL)
42037a984708SDavid Chisnall return (0);
42047a984708SDavid Chisnall
42057a984708SDavid Chisnall v->size = 0;
42067a984708SDavid Chisnall v->capacity = VECTOR_DEF_CAPACITY;
42077a984708SDavid Chisnall
4208a7941b33SDimitry Andric if ((v->r_container = malloc(sizeof(*v->r_container) * v->capacity))
42097a984708SDavid Chisnall == NULL)
42107a984708SDavid Chisnall return (0);
42117a984708SDavid Chisnall
42127a984708SDavid Chisnall return (1);
42137a984708SDavid Chisnall }
42147a984708SDavid Chisnall
42157a984708SDavid Chisnall static int
vector_read_cmd_pop(struct vector_read_cmd * v)42167a984708SDavid Chisnall vector_read_cmd_pop(struct vector_read_cmd *v)
42177a984708SDavid Chisnall {
42187a984708SDavid Chisnall
42197a984708SDavid Chisnall if (v == NULL || v->size == 0)
42207a984708SDavid Chisnall return (0);
42217a984708SDavid Chisnall
42227a984708SDavid Chisnall --v->size;
4223a7941b33SDimitry Andric v->r_container[v->size].cmd = READ_FAIL;
4224a7941b33SDimitry Andric v->r_container[v->size].data = NULL;
42257a984708SDavid Chisnall
42267a984708SDavid Chisnall return (1);
42277a984708SDavid Chisnall }
42287a984708SDavid Chisnall
42297a984708SDavid Chisnall static int
vector_read_cmd_push(struct vector_read_cmd * v,enum read_cmd cmd,void * data)4230a7941b33SDimitry Andric vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd, void *data)
42317a984708SDavid Chisnall {
4232a7941b33SDimitry Andric struct read_cmd_item *tmp_r_ctn;
42337a984708SDavid Chisnall size_t tmp_cap;
42347a984708SDavid Chisnall size_t i;
42357a984708SDavid Chisnall
42367a984708SDavid Chisnall if (v == NULL)
42377a984708SDavid Chisnall return (0);
42387a984708SDavid Chisnall
42397a984708SDavid Chisnall if (v->size == v->capacity) {
4240a7941b33SDimitry Andric tmp_cap = BUFFER_GROW(v->capacity);
4241a7941b33SDimitry Andric if ((tmp_r_ctn = malloc(sizeof(*tmp_r_ctn) * tmp_cap)) == NULL)
42427a984708SDavid Chisnall return (0);
42437a984708SDavid Chisnall for (i = 0; i < v->size; ++i)
42447a984708SDavid Chisnall tmp_r_ctn[i] = v->r_container[i];
42457a984708SDavid Chisnall free(v->r_container);
42467a984708SDavid Chisnall v->r_container = tmp_r_ctn;
42477a984708SDavid Chisnall v->capacity = tmp_cap;
42487a984708SDavid Chisnall }
42497a984708SDavid Chisnall
4250a7941b33SDimitry Andric v->r_container[v->size].cmd = cmd;
4251a7941b33SDimitry Andric v->r_container[v->size].data = data;
42527a984708SDavid Chisnall ++v->size;
42537a984708SDavid Chisnall
42547a984708SDavid Chisnall return (1);
42557a984708SDavid Chisnall }
42567a984708SDavid Chisnall
42577a984708SDavid Chisnall static void
vector_type_qualifier_dest(struct vector_type_qualifier * v)42587a984708SDavid Chisnall vector_type_qualifier_dest(struct vector_type_qualifier *v)
42597a984708SDavid Chisnall {
42607a984708SDavid Chisnall
42617a984708SDavid Chisnall if (v == NULL)
42627a984708SDavid Chisnall return;
42637a984708SDavid Chisnall
42647a984708SDavid Chisnall free(v->q_container);
42657a984708SDavid Chisnall vector_str_dest(&v->ext_name);
42667a984708SDavid Chisnall }
42677a984708SDavid Chisnall
42687a984708SDavid Chisnall /* size, capacity, ext_name */
42697a984708SDavid Chisnall static int
vector_type_qualifier_init(struct vector_type_qualifier * v)42707a984708SDavid Chisnall vector_type_qualifier_init(struct vector_type_qualifier *v)
42717a984708SDavid Chisnall {
42727a984708SDavid Chisnall
42737a984708SDavid Chisnall if (v == NULL)
42747a984708SDavid Chisnall return (0);
42757a984708SDavid Chisnall
42767a984708SDavid Chisnall v->size = 0;
42777a984708SDavid Chisnall v->capacity = VECTOR_DEF_CAPACITY;
42787a984708SDavid Chisnall
42797a984708SDavid Chisnall if ((v->q_container = malloc(sizeof(enum type_qualifier) * v->capacity))
42807a984708SDavid Chisnall == NULL)
42817a984708SDavid Chisnall return (0);
42827a984708SDavid Chisnall
42837a984708SDavid Chisnall assert(v->q_container != NULL);
42847a984708SDavid Chisnall
4285a7941b33SDimitry Andric if (!vector_str_init(&v->ext_name)) {
42867a984708SDavid Chisnall free(v->q_container);
42877a984708SDavid Chisnall return (0);
42887a984708SDavid Chisnall }
42897a984708SDavid Chisnall
42907a984708SDavid Chisnall return (1);
42917a984708SDavid Chisnall }
42927a984708SDavid Chisnall
42937a984708SDavid Chisnall static int
vector_type_qualifier_push(struct vector_type_qualifier * v,enum type_qualifier t)42947a984708SDavid Chisnall vector_type_qualifier_push(struct vector_type_qualifier *v,
42957a984708SDavid Chisnall enum type_qualifier t)
42967a984708SDavid Chisnall {
42977a984708SDavid Chisnall enum type_qualifier *tmp_ctn;
42987a984708SDavid Chisnall size_t tmp_cap;
42997a984708SDavid Chisnall size_t i;
43007a984708SDavid Chisnall
43017a984708SDavid Chisnall if (v == NULL)
43027a984708SDavid Chisnall return (0);
43037a984708SDavid Chisnall
43047a984708SDavid Chisnall if (v->size == v->capacity) {
4305a7941b33SDimitry Andric tmp_cap = BUFFER_GROW(v->capacity);
43067a984708SDavid Chisnall if ((tmp_ctn = malloc(sizeof(enum type_qualifier) * tmp_cap))
43077a984708SDavid Chisnall == NULL)
43087a984708SDavid Chisnall return (0);
43097a984708SDavid Chisnall for (i = 0; i < v->size; ++i)
43107a984708SDavid Chisnall tmp_ctn[i] = v->q_container[i];
43117a984708SDavid Chisnall free(v->q_container);
43127a984708SDavid Chisnall v->q_container = tmp_ctn;
43137a984708SDavid Chisnall v->capacity = tmp_cap;
43147a984708SDavid Chisnall }
43157a984708SDavid Chisnall
43167a984708SDavid Chisnall v->q_container[v->size] = t;
43177a984708SDavid Chisnall ++v->size;
43187a984708SDavid Chisnall
43197a984708SDavid Chisnall return (1);
43207a984708SDavid Chisnall }
4321