14cc2045aSjoerg /*-
2*d678c5d4Sjoerg  * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
3*d678c5d4Sjoerg  * Copyright (c) 2015-2017 Kai Wang <kaiwang27@gmail.com>
44cc2045aSjoerg  * All rights reserved.
54cc2045aSjoerg  *
64cc2045aSjoerg  * Redistribution and use in source and binary forms, with or without
74cc2045aSjoerg  * modification, are permitted provided that the following conditions
84cc2045aSjoerg  * are met:
94cc2045aSjoerg  * 1. Redistributions of source code must retain the above copyright
104cc2045aSjoerg  *    notice, this list of conditions and the following disclaimer
114cc2045aSjoerg  *    in this position and unchanged.
124cc2045aSjoerg  * 2. Redistributions in binary form must reproduce the above copyright
134cc2045aSjoerg  *    notice, this list of conditions and the following disclaimer in the
144cc2045aSjoerg  *    documentation and/or other materials provided with the distribution.
154cc2045aSjoerg  *
164cc2045aSjoerg  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
174cc2045aSjoerg  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
184cc2045aSjoerg  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
194cc2045aSjoerg  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
204cc2045aSjoerg  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
214cc2045aSjoerg  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
224cc2045aSjoerg  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
234cc2045aSjoerg  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
244cc2045aSjoerg  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
254cc2045aSjoerg  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
264cc2045aSjoerg  */
274cc2045aSjoerg #include <sys/types.h>
284cc2045aSjoerg #include <assert.h>
294cc2045aSjoerg #include <ctype.h>
304cc2045aSjoerg #include <errno.h>
314cc2045aSjoerg #include <limits.h>
324cc2045aSjoerg #include <stdbool.h>
334cc2045aSjoerg #include <stdio.h>
344cc2045aSjoerg #include <stdlib.h>
354cc2045aSjoerg #include <string.h>
364cc2045aSjoerg 
374cc2045aSjoerg /**
384cc2045aSjoerg  * @file cpp_demangle.c
394cc2045aSjoerg  * @brief Decode IA-64 C++ ABI style implementation.
404cc2045aSjoerg  *
414cc2045aSjoerg  * IA-64 standard ABI(Itanium C++ ABI) references.
424cc2045aSjoerg  *
434cc2045aSjoerg  * http://www.codesourcery.com/cxx-abi/abi.html#mangling \n
444cc2045aSjoerg  * http://www.codesourcery.com/cxx-abi/abi-mangling.html
454cc2045aSjoerg  */
464cc2045aSjoerg 
474cc2045aSjoerg /** @brief Dynamic vector data for string. */
484cc2045aSjoerg struct vector_str {
494cc2045aSjoerg 	/** Current size */
504cc2045aSjoerg 	size_t		size;
514cc2045aSjoerg 	/** Total capacity */
524cc2045aSjoerg 	size_t		capacity;
534cc2045aSjoerg 	/** String array */
544cc2045aSjoerg 	char		**container;
554cc2045aSjoerg };
564cc2045aSjoerg 
574cc2045aSjoerg #define BUFFER_GROWFACTOR	1.618
58*d678c5d4Sjoerg #define BUFFER_GROW(x)		(((x)+0.5)*BUFFER_GROWFACTOR)
59*d678c5d4Sjoerg 
60*d678c5d4Sjoerg #define	ELFTC_FAILURE		0
614cc2045aSjoerg #define	ELFTC_ISDIGIT(C) 	(isdigit((C) & 0xFF))
62*d678c5d4Sjoerg #define	ELFTC_SUCCESS		1
63*d678c5d4Sjoerg 
64*d678c5d4Sjoerg #define VECTOR_DEF_CAPACITY	8
654cc2045aSjoerg 
664cc2045aSjoerg enum type_qualifier {
674cc2045aSjoerg 	TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
68*d678c5d4Sjoerg 	TYPE_CST, TYPE_VEC, TYPE_RREF
694cc2045aSjoerg };
704cc2045aSjoerg 
714cc2045aSjoerg struct vector_type_qualifier {
724cc2045aSjoerg 	size_t size, capacity;
734cc2045aSjoerg 	enum type_qualifier *q_container;
744cc2045aSjoerg 	struct vector_str ext_name;
754cc2045aSjoerg };
764cc2045aSjoerg 
774cc2045aSjoerg enum read_cmd {
784cc2045aSjoerg 	READ_FAIL, READ_NEST, READ_TMPL, READ_EXPR, READ_EXPL, READ_LOCAL,
794cc2045aSjoerg 	READ_TYPE, READ_FUNC, READ_PTRMEM
804cc2045aSjoerg };
814cc2045aSjoerg 
82*d678c5d4Sjoerg struct read_cmd_item {
83*d678c5d4Sjoerg 	enum read_cmd cmd;
84*d678c5d4Sjoerg 	void *data;
85*d678c5d4Sjoerg };
86*d678c5d4Sjoerg 
874cc2045aSjoerg struct vector_read_cmd {
884cc2045aSjoerg 	size_t size, capacity;
89*d678c5d4Sjoerg 	struct read_cmd_item *r_container;
90*d678c5d4Sjoerg };
91*d678c5d4Sjoerg 
92*d678c5d4Sjoerg enum push_qualifier {
93*d678c5d4Sjoerg 	PUSH_ALL_QUALIFIER,
94*d678c5d4Sjoerg 	PUSH_CV_QUALIFIER,
95*d678c5d4Sjoerg 	PUSH_NON_CV_QUALIFIER,
964cc2045aSjoerg };
974cc2045aSjoerg 
984cc2045aSjoerg struct cpp_demangle_data {
994cc2045aSjoerg 	struct vector_str	 output;	/* output string vector */
1004cc2045aSjoerg 	struct vector_str	 subst;		/* substitution string vector */
1014cc2045aSjoerg 	struct vector_str	 tmpl;
1024cc2045aSjoerg 	struct vector_str	 class_type;
103*d678c5d4Sjoerg 	struct vector_str	*cur_output;	/* ptr to current output vec */
1044cc2045aSjoerg 	struct vector_read_cmd	 cmd;
1054cc2045aSjoerg 	bool			 mem_rst;	/* restrict member function */
1064cc2045aSjoerg 	bool			 mem_vat;	/* volatile member function */
1074cc2045aSjoerg 	bool			 mem_cst;	/* const member function */
108*d678c5d4Sjoerg 	bool			 mem_ref;	/* lvalue-ref member func */
109*d678c5d4Sjoerg 	bool			 mem_rref;	/* rvalue-ref member func */
110*d678c5d4Sjoerg 	bool			 is_tmpl;	/* template args */
111*d678c5d4Sjoerg 	bool			 is_functype;	/* function type */
112*d678c5d4Sjoerg 	bool			 ref_qualifier; /* ref qualifier */
113*d678c5d4Sjoerg 	enum type_qualifier	 ref_qualifier_type; /* ref qualifier type */
114*d678c5d4Sjoerg 	enum push_qualifier	 push_qualifier; /* which qualifiers to push */
1154cc2045aSjoerg 	int			 func_type;
1164cc2045aSjoerg 	const char		*cur;		/* current mangled name ptr */
1174cc2045aSjoerg 	const char		*last_sname;	/* last source name */
118*d678c5d4Sjoerg };
119*d678c5d4Sjoerg 
120*d678c5d4Sjoerg struct type_delimit {
121*d678c5d4Sjoerg 	bool paren;
122*d678c5d4Sjoerg 	bool firstp;
1234cc2045aSjoerg };
1244cc2045aSjoerg 
1254cc2045aSjoerg #define	CPP_DEMANGLE_TRY_LIMIT	128
1264cc2045aSjoerg #define	FLOAT_SPRINTF_TRY_LIMIT	5
1274cc2045aSjoerg #define	FLOAT_QUADRUPLE_BYTES	16
1284cc2045aSjoerg #define	FLOAT_EXTENED_BYTES	10
1294cc2045aSjoerg 
1304cc2045aSjoerg #define SIMPLE_HASH(x,y)	(64 * x + y)
131*d678c5d4Sjoerg #define DEM_PUSH_STR(d,s)	cpp_demangle_push_str((d), (s), strlen((s)))
132*d678c5d4Sjoerg #define VEC_PUSH_STR(d,s)	vector_str_push((d), (s), strlen((s)))
1334cc2045aSjoerg 
1344cc2045aSjoerg static size_t	get_strlen_sum(const struct vector_str *v);
1354cc2045aSjoerg static bool	vector_str_grow(struct vector_str *v);
1364cc2045aSjoerg 
1374cc2045aSjoerg static size_t
get_strlen_sum(const struct vector_str * v)1384cc2045aSjoerg get_strlen_sum(const struct vector_str *v)
1394cc2045aSjoerg {
1404cc2045aSjoerg 	size_t i, len = 0;
1414cc2045aSjoerg 
1424cc2045aSjoerg 	if (v == NULL)
1434cc2045aSjoerg 		return (0);
1444cc2045aSjoerg 
1454cc2045aSjoerg 	assert(v->size > 0);
1464cc2045aSjoerg 
1474cc2045aSjoerg 	for (i = 0; i < v->size; ++i)
1484cc2045aSjoerg 		len += strlen(v->container[i]);
1494cc2045aSjoerg 
1504cc2045aSjoerg 	return (len);
1514cc2045aSjoerg }
1524cc2045aSjoerg 
1534cc2045aSjoerg /**
1544cc2045aSjoerg  * @brief Deallocate resource in vector_str.
1554cc2045aSjoerg  */
1564cc2045aSjoerg static void
vector_str_dest(struct vector_str * v)1574cc2045aSjoerg vector_str_dest(struct vector_str *v)
1584cc2045aSjoerg {
1594cc2045aSjoerg 	size_t i;
1604cc2045aSjoerg 
1614cc2045aSjoerg 	if (v == NULL)
1624cc2045aSjoerg 		return;
1634cc2045aSjoerg 
1644cc2045aSjoerg 	for (i = 0; i < v->size; ++i)
1654cc2045aSjoerg 		free(v->container[i]);
1664cc2045aSjoerg 
1674cc2045aSjoerg 	free(v->container);
1684cc2045aSjoerg }
1694cc2045aSjoerg 
1704cc2045aSjoerg /**
1714cc2045aSjoerg  * @brief Find string in vector_str.
1724cc2045aSjoerg  * @param v Destination vector.
1734cc2045aSjoerg  * @param o String to find.
1744cc2045aSjoerg  * @param l Length of the string.
1754cc2045aSjoerg  * @return -1 at failed, 0 at not found, 1 at found.
1764cc2045aSjoerg  */
1774cc2045aSjoerg static int
vector_str_find(const struct vector_str * v,const char * o,size_t l)1784cc2045aSjoerg vector_str_find(const struct vector_str *v, const char *o, size_t l)
1794cc2045aSjoerg {
1804cc2045aSjoerg 	size_t i;
1814cc2045aSjoerg 
1824cc2045aSjoerg 	if (v == NULL || o == NULL)
1834cc2045aSjoerg 		return (-1);
1844cc2045aSjoerg 
1854cc2045aSjoerg 	for (i = 0; i < v->size; ++i)
1864cc2045aSjoerg 		if (strncmp(v->container[i], o, l) == 0)
1874cc2045aSjoerg 			return (1);
1884cc2045aSjoerg 
1894cc2045aSjoerg 	return (0);
1904cc2045aSjoerg }
1914cc2045aSjoerg 
1924cc2045aSjoerg /**
1934cc2045aSjoerg  * @brief Get new allocated flat string from vector.
1944cc2045aSjoerg  *
1954cc2045aSjoerg  * If l is not NULL, return length of the string.
1964cc2045aSjoerg  * @param v Destination vector.
1974cc2045aSjoerg  * @param l Length of the string.
1984cc2045aSjoerg  * @return NULL at failed or NUL terminated new allocated string.
1994cc2045aSjoerg  */
2004cc2045aSjoerg static char *
vector_str_get_flat(const struct vector_str * v,size_t * l)2014cc2045aSjoerg vector_str_get_flat(const struct vector_str *v, size_t *l)
2024cc2045aSjoerg {
2034cc2045aSjoerg 	ssize_t elem_pos, elem_size, rtn_size;
2044cc2045aSjoerg 	size_t i;
2054cc2045aSjoerg 	char *rtn;
2064cc2045aSjoerg 
2074cc2045aSjoerg 	if (v == NULL || v->size == 0)
2084cc2045aSjoerg 		return (NULL);
2094cc2045aSjoerg 
2104cc2045aSjoerg 	if ((rtn_size = get_strlen_sum(v)) == 0)
2114cc2045aSjoerg 		return (NULL);
2124cc2045aSjoerg 
2134cc2045aSjoerg 	if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL)
2144cc2045aSjoerg 		return (NULL);
2154cc2045aSjoerg 
2164cc2045aSjoerg 	elem_pos = 0;
2174cc2045aSjoerg 	for (i = 0; i < v->size; ++i) {
2184cc2045aSjoerg 		elem_size = strlen(v->container[i]);
2194cc2045aSjoerg 
2204cc2045aSjoerg 		memcpy(rtn + elem_pos, v->container[i], elem_size);
2214cc2045aSjoerg 
2224cc2045aSjoerg 		elem_pos += elem_size;
2234cc2045aSjoerg 	}
2244cc2045aSjoerg 
2254cc2045aSjoerg 	rtn[rtn_size] = '\0';
2264cc2045aSjoerg 
2274cc2045aSjoerg 	if (l != NULL)
2284cc2045aSjoerg 		*l = rtn_size;
2294cc2045aSjoerg 
2304cc2045aSjoerg 	return (rtn);
2314cc2045aSjoerg }
2324cc2045aSjoerg 
2334cc2045aSjoerg static bool
vector_str_grow(struct vector_str * v)2344cc2045aSjoerg vector_str_grow(struct vector_str *v)
2354cc2045aSjoerg {
2364cc2045aSjoerg 	size_t i, tmp_cap;
2374cc2045aSjoerg 	char **tmp_ctn;
2384cc2045aSjoerg 
2394cc2045aSjoerg 	if (v == NULL)
2404cc2045aSjoerg 		return (false);
2414cc2045aSjoerg 
2424cc2045aSjoerg 	assert(v->capacity > 0);
2434cc2045aSjoerg 
244*d678c5d4Sjoerg 	tmp_cap = BUFFER_GROW(v->capacity);
2454cc2045aSjoerg 
2464cc2045aSjoerg 	assert(tmp_cap > v->capacity);
2474cc2045aSjoerg 
2484cc2045aSjoerg 	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
2494cc2045aSjoerg 		return (false);
2504cc2045aSjoerg 
2514cc2045aSjoerg 	for (i = 0; i < v->size; ++i)
2524cc2045aSjoerg 		tmp_ctn[i] = v->container[i];
2534cc2045aSjoerg 
2544cc2045aSjoerg 	free(v->container);
2554cc2045aSjoerg 
2564cc2045aSjoerg 	v->container = tmp_ctn;
2574cc2045aSjoerg 	v->capacity = tmp_cap;
2584cc2045aSjoerg 
2594cc2045aSjoerg 	return (true);
2604cc2045aSjoerg }
2614cc2045aSjoerg 
2624cc2045aSjoerg /**
2634cc2045aSjoerg  * @brief Initialize vector_str.
2644cc2045aSjoerg  * @return false at failed, true at success.
2654cc2045aSjoerg  */
2664cc2045aSjoerg static bool
vector_str_init(struct vector_str * v)2674cc2045aSjoerg vector_str_init(struct vector_str *v)
2684cc2045aSjoerg {
2694cc2045aSjoerg 
2704cc2045aSjoerg 	if (v == NULL)
2714cc2045aSjoerg 		return (false);
2724cc2045aSjoerg 
2734cc2045aSjoerg 	v->size = 0;
2744cc2045aSjoerg 	v->capacity = VECTOR_DEF_CAPACITY;
2754cc2045aSjoerg 
2764cc2045aSjoerg 	assert(v->capacity > 0);
2774cc2045aSjoerg 
2784cc2045aSjoerg 	if ((v->container = malloc(sizeof(char *) * v->capacity)) == NULL)
2794cc2045aSjoerg 		return (false);
2804cc2045aSjoerg 
2814cc2045aSjoerg 	assert(v->container != NULL);
2824cc2045aSjoerg 
2834cc2045aSjoerg 	return (true);
2844cc2045aSjoerg }
2854cc2045aSjoerg 
2864cc2045aSjoerg /**
2874cc2045aSjoerg  * @brief Remove last element in vector_str.
2884cc2045aSjoerg  * @return false at failed, true at success.
2894cc2045aSjoerg  */
2904cc2045aSjoerg static bool
vector_str_pop(struct vector_str * v)2914cc2045aSjoerg vector_str_pop(struct vector_str *v)
2924cc2045aSjoerg {
2934cc2045aSjoerg 
2944cc2045aSjoerg 	if (v == NULL)
2954cc2045aSjoerg 		return (false);
2964cc2045aSjoerg 
2974cc2045aSjoerg 	if (v->size == 0)
2984cc2045aSjoerg 		return (true);
2994cc2045aSjoerg 
3004cc2045aSjoerg 	--v->size;
3014cc2045aSjoerg 
3024cc2045aSjoerg 	free(v->container[v->size]);
3034cc2045aSjoerg 	v->container[v->size] = NULL;
3044cc2045aSjoerg 
3054cc2045aSjoerg 	return (true);
3064cc2045aSjoerg }
3074cc2045aSjoerg 
3084cc2045aSjoerg /**
3094cc2045aSjoerg  * @brief Push back string to vector.
3104cc2045aSjoerg  * @return false at failed, true at success.
3114cc2045aSjoerg  */
3124cc2045aSjoerg static bool
vector_str_push(struct vector_str * v,const char * str,size_t len)3134cc2045aSjoerg vector_str_push(struct vector_str *v, const char *str, size_t len)
3144cc2045aSjoerg {
3154cc2045aSjoerg 
3164cc2045aSjoerg 	if (v == NULL || str == NULL)
3174cc2045aSjoerg 		return (false);
3184cc2045aSjoerg 
3194cc2045aSjoerg 	if (v->size == v->capacity && vector_str_grow(v) == false)
3204cc2045aSjoerg 		return (false);
3214cc2045aSjoerg 
3224cc2045aSjoerg 	if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL)
3234cc2045aSjoerg 		return (false);
3244cc2045aSjoerg 
3254cc2045aSjoerg 	snprintf(v->container[v->size], len + 1, "%s", str);
3264cc2045aSjoerg 
3274cc2045aSjoerg 	++v->size;
3284cc2045aSjoerg 
3294cc2045aSjoerg 	return (true);
3304cc2045aSjoerg }
3314cc2045aSjoerg 
3324cc2045aSjoerg /**
3334cc2045aSjoerg  * @brief Push front org vector to det vector.
3344cc2045aSjoerg  * @return false at failed, true at success.
3354cc2045aSjoerg  */
3364cc2045aSjoerg static bool
vector_str_push_vector_head(struct vector_str * dst,struct vector_str * org)3374cc2045aSjoerg vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org)
3384cc2045aSjoerg {
3394cc2045aSjoerg 	size_t i, j, tmp_cap;
3404cc2045aSjoerg 	char **tmp_ctn;
3414cc2045aSjoerg 
3424cc2045aSjoerg 	if (dst == NULL || org == NULL)
3434cc2045aSjoerg 		return (false);
3444cc2045aSjoerg 
345*d678c5d4Sjoerg 	tmp_cap = BUFFER_GROW(dst->size + org->size);
3464cc2045aSjoerg 
3474cc2045aSjoerg 	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
3484cc2045aSjoerg 		return (false);
3494cc2045aSjoerg 
3504cc2045aSjoerg 	for (i = 0; i < org->size; ++i)
3514cc2045aSjoerg 		if ((tmp_ctn[i] = strdup(org->container[i])) == NULL) {
3524cc2045aSjoerg 			for (j = 0; j < i; ++j)
3534cc2045aSjoerg 				free(tmp_ctn[j]);
3544cc2045aSjoerg 
3554cc2045aSjoerg 			free(tmp_ctn);
3564cc2045aSjoerg 
3574cc2045aSjoerg 			return (false);
3584cc2045aSjoerg 		}
3594cc2045aSjoerg 
3604cc2045aSjoerg 	for (i = 0; i < dst->size; ++i)
3614cc2045aSjoerg 		tmp_ctn[i + org->size] = dst->container[i];
3624cc2045aSjoerg 
3634cc2045aSjoerg 	free(dst->container);
3644cc2045aSjoerg 
3654cc2045aSjoerg 	dst->container = tmp_ctn;
3664cc2045aSjoerg 	dst->capacity = tmp_cap;
3674cc2045aSjoerg 	dst->size += org->size;
3684cc2045aSjoerg 
3694cc2045aSjoerg 	return (true);
3704cc2045aSjoerg }
3714cc2045aSjoerg 
3724cc2045aSjoerg /**
373*d678c5d4Sjoerg  * @brief Push org vector to the tail of det vector.
374*d678c5d4Sjoerg  * @return false at failed, true at success.
375*d678c5d4Sjoerg  */
376*d678c5d4Sjoerg static bool
vector_str_push_vector(struct vector_str * dst,struct vector_str * org)377*d678c5d4Sjoerg vector_str_push_vector(struct vector_str *dst, struct vector_str *org)
378*d678c5d4Sjoerg {
379*d678c5d4Sjoerg 	size_t i, j, tmp_cap;
380*d678c5d4Sjoerg 	char **tmp_ctn;
381*d678c5d4Sjoerg 
382*d678c5d4Sjoerg 	if (dst == NULL || org == NULL)
383*d678c5d4Sjoerg 		return (false);
384*d678c5d4Sjoerg 
385*d678c5d4Sjoerg 	tmp_cap = BUFFER_GROW(dst->size + org->size);
386*d678c5d4Sjoerg 
387*d678c5d4Sjoerg 	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
388*d678c5d4Sjoerg 		return (false);
389*d678c5d4Sjoerg 
390*d678c5d4Sjoerg 	for (i = 0; i < dst->size; ++i)
391*d678c5d4Sjoerg 		tmp_ctn[i] = dst->container[i];
392*d678c5d4Sjoerg 
393*d678c5d4Sjoerg 	for (i = 0; i < org->size; ++i)
394*d678c5d4Sjoerg 		if ((tmp_ctn[i + dst->size] = strdup(org->container[i])) ==
395*d678c5d4Sjoerg 		    NULL) {
396*d678c5d4Sjoerg 			for (j = 0; j < i + dst->size; ++j)
397*d678c5d4Sjoerg 				free(tmp_ctn[j]);
398*d678c5d4Sjoerg 
399*d678c5d4Sjoerg 			free(tmp_ctn);
400*d678c5d4Sjoerg 
401*d678c5d4Sjoerg 			return (false);
402*d678c5d4Sjoerg 		}
403*d678c5d4Sjoerg 
404*d678c5d4Sjoerg 	free(dst->container);
405*d678c5d4Sjoerg 
406*d678c5d4Sjoerg 	dst->container = tmp_ctn;
407*d678c5d4Sjoerg 	dst->capacity = tmp_cap;
408*d678c5d4Sjoerg 	dst->size += org->size;
409*d678c5d4Sjoerg 
410*d678c5d4Sjoerg 	return (true);
411*d678c5d4Sjoerg }
412*d678c5d4Sjoerg 
413*d678c5d4Sjoerg /**
4144cc2045aSjoerg  * @brief Get new allocated flat string from vector between begin and end.
4154cc2045aSjoerg  *
4164cc2045aSjoerg  * If r_len is not NULL, string length will be returned.
4174cc2045aSjoerg  * @return NULL at failed or NUL terminated new allocated string.
4184cc2045aSjoerg  */
4194cc2045aSjoerg static char *
vector_str_substr(const struct vector_str * v,size_t begin,size_t end,size_t * r_len)4204cc2045aSjoerg vector_str_substr(const struct vector_str *v, size_t begin, size_t end,
4214cc2045aSjoerg     size_t *r_len)
4224cc2045aSjoerg {
4234cc2045aSjoerg 	size_t cur, i, len;
4244cc2045aSjoerg 	char *rtn;
4254cc2045aSjoerg 
4264cc2045aSjoerg 	if (v == NULL || begin > end)
4274cc2045aSjoerg 		return (NULL);
4284cc2045aSjoerg 
4294cc2045aSjoerg 	len = 0;
4304cc2045aSjoerg 	for (i = begin; i < end + 1; ++i)
4314cc2045aSjoerg 		len += strlen(v->container[i]);
4324cc2045aSjoerg 
4334cc2045aSjoerg 	if ((rtn = malloc(sizeof(char) * (len + 1))) == NULL)
4344cc2045aSjoerg 		return (NULL);
4354cc2045aSjoerg 
4364cc2045aSjoerg 	if (r_len != NULL)
4374cc2045aSjoerg 		*r_len = len;
4384cc2045aSjoerg 
4394cc2045aSjoerg 	cur = 0;
4404cc2045aSjoerg 	for (i = begin; i < end + 1; ++i) {
4414cc2045aSjoerg 		len = strlen(v->container[i]);
4424cc2045aSjoerg 		memcpy(rtn + cur, v->container[i], len);
4434cc2045aSjoerg 		cur += len;
4444cc2045aSjoerg 	}
4454cc2045aSjoerg 	rtn[cur] = '\0';
4464cc2045aSjoerg 
4474cc2045aSjoerg 	return (rtn);
4484cc2045aSjoerg }
4494cc2045aSjoerg 
4504cc2045aSjoerg static void	cpp_demangle_data_dest(struct cpp_demangle_data *);
4514cc2045aSjoerg static int	cpp_demangle_data_init(struct cpp_demangle_data *,
4524cc2045aSjoerg 		    const char *);
4534cc2045aSjoerg static int	cpp_demangle_get_subst(struct cpp_demangle_data *, size_t);
4544cc2045aSjoerg static int	cpp_demangle_get_tmpl_param(struct cpp_demangle_data *, size_t);
4554cc2045aSjoerg static int	cpp_demangle_push_fp(struct cpp_demangle_data *,
4564cc2045aSjoerg 		    char *(*)(const char *, size_t));
4574cc2045aSjoerg static int	cpp_demangle_push_str(struct cpp_demangle_data *, const char *,
4584cc2045aSjoerg 		    size_t);
459*d678c5d4Sjoerg static int	cpp_demangle_pop_str(struct cpp_demangle_data *);
4604cc2045aSjoerg static int	cpp_demangle_push_subst(struct cpp_demangle_data *,
4614cc2045aSjoerg 		    const char *, size_t);
4624cc2045aSjoerg static int	cpp_demangle_push_subst_v(struct cpp_demangle_data *,
4634cc2045aSjoerg 		    struct vector_str *);
4644cc2045aSjoerg static int	cpp_demangle_push_type_qualifier(struct cpp_demangle_data *,
4654cc2045aSjoerg 		    struct vector_type_qualifier *, const char *);
4664cc2045aSjoerg static int	cpp_demangle_read_array(struct cpp_demangle_data *);
4674cc2045aSjoerg static int	cpp_demangle_read_encoding(struct cpp_demangle_data *);
4684cc2045aSjoerg static int	cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
4694cc2045aSjoerg static int	cpp_demangle_read_expression(struct cpp_demangle_data *);
47086b377d0Spooka static int	cpp_demangle_read_expression_flat(struct cpp_demangle_data *,
47186b377d0Spooka 		    char **);
4724cc2045aSjoerg static int	cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
4734cc2045aSjoerg 		    const char *, size_t);
4744cc2045aSjoerg static int	cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
4754cc2045aSjoerg 		    const char *, size_t);
4764cc2045aSjoerg static int	cpp_demangle_read_expression_trinary(struct cpp_demangle_data *,
4774cc2045aSjoerg 		    const char *, size_t, const char *, size_t);
4784cc2045aSjoerg static int	cpp_demangle_read_function(struct cpp_demangle_data *, int *,
4794cc2045aSjoerg 		    struct vector_type_qualifier *);
4805192b81bSjoerg static int	cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
4814cc2045aSjoerg static int	cpp_demangle_read_local_name(struct cpp_demangle_data *);
4824cc2045aSjoerg static int	cpp_demangle_read_name(struct cpp_demangle_data *);
48386b377d0Spooka static int	cpp_demangle_read_name_flat(struct cpp_demangle_data *,
48486b377d0Spooka 		    char**);
4854cc2045aSjoerg static int	cpp_demangle_read_nested_name(struct cpp_demangle_data *);
4864cc2045aSjoerg static int	cpp_demangle_read_number(struct cpp_demangle_data *, long *);
48786b377d0Spooka static int	cpp_demangle_read_number_as_string(struct cpp_demangle_data *,
48886b377d0Spooka 		    char **);
4894cc2045aSjoerg static int	cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
4904cc2045aSjoerg static int	cpp_demangle_read_offset(struct cpp_demangle_data *);
4914cc2045aSjoerg static int	cpp_demangle_read_offset_number(struct cpp_demangle_data *);
492*d678c5d4Sjoerg static int	cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *,
493*d678c5d4Sjoerg 		    struct vector_type_qualifier *);
4944cc2045aSjoerg static int	cpp_demangle_read_sname(struct cpp_demangle_data *);
4954cc2045aSjoerg static int	cpp_demangle_read_subst(struct cpp_demangle_data *);
4964cc2045aSjoerg static int	cpp_demangle_read_subst_std(struct cpp_demangle_data *);
4974cc2045aSjoerg static int	cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *,
498*d678c5d4Sjoerg 		    const char *);
4994cc2045aSjoerg static int	cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
5004cc2045aSjoerg static int	cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
5014cc2045aSjoerg static int	cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
502*d678c5d4Sjoerg static int	cpp_demangle_read_type(struct cpp_demangle_data *,
503*d678c5d4Sjoerg 		    struct type_delimit *);
50486b377d0Spooka static int	cpp_demangle_read_type_flat(struct cpp_demangle_data *,
50586b377d0Spooka 		    char **);
5064cc2045aSjoerg static int	cpp_demangle_read_uqname(struct cpp_demangle_data *);
5074cc2045aSjoerg static int	cpp_demangle_read_v_offset(struct cpp_demangle_data *);
5084cc2045aSjoerg static char	*decode_fp_to_double(const char *, size_t);
5094cc2045aSjoerg static char	*decode_fp_to_float(const char *, size_t);
5104cc2045aSjoerg static char	*decode_fp_to_float128(const char *, size_t);
5114cc2045aSjoerg static char	*decode_fp_to_float80(const char *, size_t);
5124cc2045aSjoerg static char	*decode_fp_to_long_double(const char *, size_t);
5134cc2045aSjoerg static int	hex_to_dec(char);
5144cc2045aSjoerg static void	vector_read_cmd_dest(struct vector_read_cmd *);
515*d678c5d4Sjoerg static struct read_cmd_item *vector_read_cmd_find(struct vector_read_cmd *,
516*d678c5d4Sjoerg 		    enum read_cmd);
5174cc2045aSjoerg static int	vector_read_cmd_init(struct vector_read_cmd *);
5184cc2045aSjoerg static int	vector_read_cmd_pop(struct vector_read_cmd *);
519*d678c5d4Sjoerg static int	vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd,
520*d678c5d4Sjoerg 		    void *);
5214cc2045aSjoerg static void	vector_type_qualifier_dest(struct vector_type_qualifier *);
5224cc2045aSjoerg static int	vector_type_qualifier_init(struct vector_type_qualifier *);
5234cc2045aSjoerg static int	vector_type_qualifier_push(struct vector_type_qualifier *,
5244cc2045aSjoerg 		    enum type_qualifier);
5254cc2045aSjoerg 
5264cc2045aSjoerg /**
5274cc2045aSjoerg  * @brief Decode the input string by IA-64 C++ ABI style.
5284cc2045aSjoerg  *
5294cc2045aSjoerg  * GNU GCC v3 use IA-64 standard ABI.
5304cc2045aSjoerg  * @return New allocated demangled string or NULL if failed.
5314cc2045aSjoerg  * @todo 1. Testing and more test case. 2. Code cleaning.
5324cc2045aSjoerg  */
5334cc2045aSjoerg char *
__cxa_demangle_gnu3(const char * org)5344cc2045aSjoerg __cxa_demangle_gnu3(const char *org)
5354cc2045aSjoerg {
5364cc2045aSjoerg 	struct cpp_demangle_data ddata;
537*d678c5d4Sjoerg 	struct vector_str ret_type;
538*d678c5d4Sjoerg 	struct type_delimit td;
5394cc2045aSjoerg 	ssize_t org_len;
5404cc2045aSjoerg 	unsigned int limit;
541*d678c5d4Sjoerg 	char *rtn;
542*d678c5d4Sjoerg 	bool has_ret, more_type;
5434cc2045aSjoerg 
5444cc2045aSjoerg 	if (org == NULL)
5454cc2045aSjoerg 		return (NULL);
5464cc2045aSjoerg 
5475192b81bSjoerg 	org_len = strlen(org);
5485192b81bSjoerg 	// Try demangling as a type for short encodings
5495192b81bSjoerg 	if ((org_len < 2) || (org[0] != '_' || org[1] != 'Z' )) {
5505192b81bSjoerg 		if (!cpp_demangle_data_init(&ddata, org))
5515192b81bSjoerg 			return (NULL);
5525192b81bSjoerg 		if (!cpp_demangle_read_type(&ddata, 0))
5535192b81bSjoerg 			goto clean;
5545192b81bSjoerg 		rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
5555192b81bSjoerg 		goto clean;
5565192b81bSjoerg 	}
557*d678c5d4Sjoerg 	if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) {
558*d678c5d4Sjoerg 		if ((rtn = malloc(org_len + 19)) == NULL)
559*d678c5d4Sjoerg 			return (NULL);
560*d678c5d4Sjoerg 		snprintf(rtn, org_len + 19,
561*d678c5d4Sjoerg 		    "global constructors keyed to %s", org + 11);
562*d678c5d4Sjoerg 		return (rtn);
563*d678c5d4Sjoerg 	}
5645192b81bSjoerg 
5654cc2045aSjoerg 
5664cc2045aSjoerg 	if (!cpp_demangle_data_init(&ddata, org + 2))
5674cc2045aSjoerg 		return (NULL);
5684cc2045aSjoerg 
5694cc2045aSjoerg 	rtn = NULL;
570*d678c5d4Sjoerg 	has_ret = more_type = false;
5714cc2045aSjoerg 
5724cc2045aSjoerg 	if (!cpp_demangle_read_encoding(&ddata))
5734cc2045aSjoerg 		goto clean;
5744cc2045aSjoerg 
575*d678c5d4Sjoerg 	/*
576*d678c5d4Sjoerg 	 * Pop function name from substitution candidate list.
577*d678c5d4Sjoerg 	 */
578*d678c5d4Sjoerg 	if (*ddata.cur != 0 && ddata.subst.size >= 1) {
579*d678c5d4Sjoerg 		if (!vector_str_pop(&ddata.subst))
580*d678c5d4Sjoerg 			goto clean;
581*d678c5d4Sjoerg 	}
582*d678c5d4Sjoerg 
583*d678c5d4Sjoerg 	td.paren = false;
584*d678c5d4Sjoerg 	td.firstp = true;
5854cc2045aSjoerg 	limit = 0;
586*d678c5d4Sjoerg 
587*d678c5d4Sjoerg 	/*
588*d678c5d4Sjoerg 	 * The first type is a return type if we just demangled template
589*d678c5d4Sjoerg 	 * args. (the template args is right next to the function name,
590*d678c5d4Sjoerg 	 * which means it's a template function)
591*d678c5d4Sjoerg 	 */
592*d678c5d4Sjoerg 	if (ddata.is_tmpl) {
593*d678c5d4Sjoerg 		ddata.is_tmpl = false;
594*d678c5d4Sjoerg 		if (!vector_str_init(&ret_type))
595*d678c5d4Sjoerg 			goto clean;
596*d678c5d4Sjoerg 		ddata.cur_output = &ret_type;
597*d678c5d4Sjoerg 		has_ret = true;
598*d678c5d4Sjoerg 	}
599*d678c5d4Sjoerg 
6004cc2045aSjoerg 	while (*ddata.cur != '\0') {
6014cc2045aSjoerg 		/*
6024cc2045aSjoerg 		 * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4
6034cc2045aSjoerg 		 */
6044cc2045aSjoerg 		if (*ddata.cur == '@' && *(ddata.cur + 1) == '@')
6054cc2045aSjoerg 			break;
606*d678c5d4Sjoerg 
607*d678c5d4Sjoerg 		if (has_ret) {
608*d678c5d4Sjoerg 			/* Read return type */
609*d678c5d4Sjoerg 			if (!cpp_demangle_read_type(&ddata, NULL))
6104cc2045aSjoerg 				goto clean;
611*d678c5d4Sjoerg 		} else {
612*d678c5d4Sjoerg 			/* Read function arg type */
613*d678c5d4Sjoerg 			if (!cpp_demangle_read_type(&ddata, &td))
6144cc2045aSjoerg 				goto clean;
6154cc2045aSjoerg 		}
6164cc2045aSjoerg 
617*d678c5d4Sjoerg 		if (has_ret) {
618*d678c5d4Sjoerg 			/* Push return type to the beginning */
619*d678c5d4Sjoerg 			if (!VEC_PUSH_STR(&ret_type, " "))
620*d678c5d4Sjoerg 				goto clean;
621*d678c5d4Sjoerg 			if (!vector_str_push_vector_head(&ddata.output,
622*d678c5d4Sjoerg 			    &ret_type))
623*d678c5d4Sjoerg 				goto clean;
624*d678c5d4Sjoerg 			ddata.cur_output = &ddata.output;
625*d678c5d4Sjoerg 			vector_str_dest(&ret_type);
626*d678c5d4Sjoerg 			has_ret = false;
627*d678c5d4Sjoerg 			more_type = true;
628*d678c5d4Sjoerg 		} else if (more_type)
629*d678c5d4Sjoerg 			more_type = false;
630*d678c5d4Sjoerg 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
631*d678c5d4Sjoerg 			goto clean;
632*d678c5d4Sjoerg 	}
633*d678c5d4Sjoerg 	if (more_type)
634*d678c5d4Sjoerg 		goto clean;
635*d678c5d4Sjoerg 
6364cc2045aSjoerg 	if (ddata.output.size == 0)
6374cc2045aSjoerg 		goto clean;
638*d678c5d4Sjoerg 	if (td.paren && !VEC_PUSH_STR(&ddata.output, ")"))
6394cc2045aSjoerg 		goto clean;
640*d678c5d4Sjoerg 	if (ddata.mem_vat && !VEC_PUSH_STR(&ddata.output, " volatile"))
6414cc2045aSjoerg 		goto clean;
642*d678c5d4Sjoerg 	if (ddata.mem_cst && !VEC_PUSH_STR(&ddata.output, " const"))
6434cc2045aSjoerg 		goto clean;
644*d678c5d4Sjoerg 	if (ddata.mem_rst && !VEC_PUSH_STR(&ddata.output, " restrict"))
645*d678c5d4Sjoerg 		goto clean;
646*d678c5d4Sjoerg 	if (ddata.mem_ref && !VEC_PUSH_STR(&ddata.output, " &"))
647*d678c5d4Sjoerg 		goto clean;
648*d678c5d4Sjoerg 	if (ddata.mem_rref && !VEC_PUSH_STR(&ddata.output, " &&"))
6494cc2045aSjoerg 		goto clean;
6504cc2045aSjoerg 
6514cc2045aSjoerg 	rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
6524cc2045aSjoerg 
6534cc2045aSjoerg clean:
654*d678c5d4Sjoerg 	if (has_ret)
655*d678c5d4Sjoerg 		vector_str_dest(&ret_type);
656*d678c5d4Sjoerg 
6574cc2045aSjoerg 	cpp_demangle_data_dest(&ddata);
6584cc2045aSjoerg 
6594cc2045aSjoerg 	return (rtn);
6604cc2045aSjoerg }
6614cc2045aSjoerg 
6624cc2045aSjoerg static void
cpp_demangle_data_dest(struct cpp_demangle_data * d)6634cc2045aSjoerg cpp_demangle_data_dest(struct cpp_demangle_data *d)
6644cc2045aSjoerg {
6654cc2045aSjoerg 
6664cc2045aSjoerg 	if (d == NULL)
6674cc2045aSjoerg 		return;
6684cc2045aSjoerg 
6694cc2045aSjoerg 	vector_read_cmd_dest(&d->cmd);
6704cc2045aSjoerg 	vector_str_dest(&d->class_type);
6714cc2045aSjoerg 	vector_str_dest(&d->tmpl);
6724cc2045aSjoerg 	vector_str_dest(&d->subst);
6734cc2045aSjoerg 	vector_str_dest(&d->output);
6744cc2045aSjoerg }
6754cc2045aSjoerg 
6764cc2045aSjoerg static int
cpp_demangle_data_init(struct cpp_demangle_data * d,const char * cur)6774cc2045aSjoerg cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
6784cc2045aSjoerg {
6794cc2045aSjoerg 
6804cc2045aSjoerg 	if (d == NULL || cur == NULL)
6814cc2045aSjoerg 		return (0);
6824cc2045aSjoerg 
6834cc2045aSjoerg 	if (!vector_str_init(&d->output))
6844cc2045aSjoerg 		return (0);
6854cc2045aSjoerg 	if (!vector_str_init(&d->subst))
686*d678c5d4Sjoerg 		goto clean1;
6874cc2045aSjoerg 	if (!vector_str_init(&d->tmpl))
688*d678c5d4Sjoerg 		goto clean2;
6894cc2045aSjoerg 	if (!vector_str_init(&d->class_type))
690*d678c5d4Sjoerg 		goto clean3;
6914cc2045aSjoerg 	if (!vector_read_cmd_init(&d->cmd))
692*d678c5d4Sjoerg 		goto clean4;
6934cc2045aSjoerg 
6944cc2045aSjoerg 	assert(d->output.container != NULL);
6954cc2045aSjoerg 	assert(d->subst.container != NULL);
6964cc2045aSjoerg 	assert(d->tmpl.container != NULL);
6974cc2045aSjoerg 	assert(d->class_type.container != NULL);
6984cc2045aSjoerg 
6994cc2045aSjoerg 	d->mem_rst = false;
7004cc2045aSjoerg 	d->mem_vat = false;
7014cc2045aSjoerg 	d->mem_cst = false;
702*d678c5d4Sjoerg 	d->mem_ref = false;
703*d678c5d4Sjoerg 	d->mem_rref = false;
704*d678c5d4Sjoerg 	d->is_tmpl = false;
705*d678c5d4Sjoerg 	d->is_functype = false;
706*d678c5d4Sjoerg 	d->ref_qualifier = false;
707*d678c5d4Sjoerg 	d->push_qualifier = PUSH_ALL_QUALIFIER;
7084cc2045aSjoerg 	d->func_type = 0;
7094cc2045aSjoerg 	d->cur = cur;
710*d678c5d4Sjoerg 	d->cur_output = &d->output;
7114cc2045aSjoerg 	d->last_sname = NULL;
7124cc2045aSjoerg 
7134cc2045aSjoerg 	return (1);
7144cc2045aSjoerg 
7154cc2045aSjoerg clean4:
716*d678c5d4Sjoerg 	vector_str_dest(&d->class_type);
7174cc2045aSjoerg clean3:
718*d678c5d4Sjoerg 	vector_str_dest(&d->tmpl);
7194cc2045aSjoerg clean2:
720*d678c5d4Sjoerg 	vector_str_dest(&d->subst);
7214cc2045aSjoerg clean1:
7224cc2045aSjoerg 	vector_str_dest(&d->output);
7234cc2045aSjoerg 
7244cc2045aSjoerg 	return (0);
7254cc2045aSjoerg }
7264cc2045aSjoerg 
7274cc2045aSjoerg static int
cpp_demangle_push_fp(struct cpp_demangle_data * ddata,char * (* decoder)(const char *,size_t))7284cc2045aSjoerg cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
7294cc2045aSjoerg     char *(*decoder)(const char *, size_t))
7304cc2045aSjoerg {
7314cc2045aSjoerg 	size_t len;
7324cc2045aSjoerg 	int rtn;
7334cc2045aSjoerg 	const char *fp;
7344cc2045aSjoerg 	char *f;
7354cc2045aSjoerg 
7364cc2045aSjoerg 	if (ddata == NULL || decoder == NULL)
7374cc2045aSjoerg 		return (0);
7384cc2045aSjoerg 
7394cc2045aSjoerg 	fp = ddata->cur;
7404cc2045aSjoerg 	while (*ddata->cur != 'E')
7414cc2045aSjoerg 		++ddata->cur;
7424cc2045aSjoerg 
7434cc2045aSjoerg 	if ((f = decoder(fp, ddata->cur - fp)) == NULL)
7444cc2045aSjoerg 		return (0);
7454cc2045aSjoerg 
7464cc2045aSjoerg 	rtn = 0;
7475192b81bSjoerg 	if ((len = strlen(f)) > 0)
7485192b81bSjoerg 		rtn = cpp_demangle_push_str(ddata, f, len);
7494cc2045aSjoerg 
7504cc2045aSjoerg 	free(f);
7514cc2045aSjoerg 
75286b377d0Spooka 	++ddata->cur;
75386b377d0Spooka 
7545192b81bSjoerg 	return (rtn);
7554cc2045aSjoerg }
7564cc2045aSjoerg 
7574cc2045aSjoerg static int
cpp_demangle_push_str(struct cpp_demangle_data * ddata,const char * str,size_t len)7584cc2045aSjoerg cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
7594cc2045aSjoerg     size_t len)
7604cc2045aSjoerg {
7614cc2045aSjoerg 
7624cc2045aSjoerg 	if (ddata == NULL || str == NULL || len == 0)
7634cc2045aSjoerg 		return (0);
7644cc2045aSjoerg 
765*d678c5d4Sjoerg 	/*
766*d678c5d4Sjoerg 	 * is_tmpl is used to check if the type (function arg) is right next
767*d678c5d4Sjoerg 	 * to template args, and should always be cleared whenever new string
768*d678c5d4Sjoerg 	 * pushed.
769*d678c5d4Sjoerg 	 */
770*d678c5d4Sjoerg 	ddata->is_tmpl = false;
7714cc2045aSjoerg 
772*d678c5d4Sjoerg 	return (vector_str_push(ddata->cur_output, str, len));
773*d678c5d4Sjoerg }
774*d678c5d4Sjoerg 
775*d678c5d4Sjoerg static int
cpp_demangle_pop_str(struct cpp_demangle_data * ddata)776*d678c5d4Sjoerg cpp_demangle_pop_str(struct cpp_demangle_data *ddata)
777*d678c5d4Sjoerg {
778*d678c5d4Sjoerg 
779*d678c5d4Sjoerg 	if (ddata == NULL)
780*d678c5d4Sjoerg 		return (0);
781*d678c5d4Sjoerg 
782*d678c5d4Sjoerg 	return (vector_str_pop(ddata->cur_output));
7834cc2045aSjoerg }
7844cc2045aSjoerg 
7854cc2045aSjoerg static int
cpp_demangle_push_subst(struct cpp_demangle_data * ddata,const char * str,size_t len)7864cc2045aSjoerg cpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str,
7874cc2045aSjoerg     size_t len)
7884cc2045aSjoerg {
7894cc2045aSjoerg 
7904cc2045aSjoerg 	if (ddata == NULL || str == NULL || len == 0)
7914cc2045aSjoerg 		return (0);
7924cc2045aSjoerg 
7934cc2045aSjoerg 	if (!vector_str_find(&ddata->subst, str, len))
7944cc2045aSjoerg 		return (vector_str_push(&ddata->subst, str, len));
7954cc2045aSjoerg 
7964cc2045aSjoerg 	return (1);
7974cc2045aSjoerg }
7984cc2045aSjoerg 
7994cc2045aSjoerg static int
cpp_demangle_push_subst_v(struct cpp_demangle_data * ddata,struct vector_str * v)8004cc2045aSjoerg cpp_demangle_push_subst_v(struct cpp_demangle_data *ddata, struct vector_str *v)
8014cc2045aSjoerg {
8024cc2045aSjoerg 	size_t str_len;
8034cc2045aSjoerg 	int rtn;
8044cc2045aSjoerg 	char *str;
8054cc2045aSjoerg 
8064cc2045aSjoerg 	if (ddata == NULL || v == NULL)
8074cc2045aSjoerg 		return (0);
8084cc2045aSjoerg 
8094cc2045aSjoerg 	if ((str = vector_str_get_flat(v, &str_len)) == NULL)
8104cc2045aSjoerg 		return (0);
8114cc2045aSjoerg 
8124cc2045aSjoerg 	rtn = cpp_demangle_push_subst(ddata, str, str_len);
8135192b81bSjoerg 
8144cc2045aSjoerg 	free(str);
8154cc2045aSjoerg 
8164cc2045aSjoerg 	return (rtn);
8174cc2045aSjoerg }
8184cc2045aSjoerg 
8194cc2045aSjoerg static int
cpp_demangle_push_type_qualifier(struct cpp_demangle_data * ddata,struct vector_type_qualifier * v,const char * type_str)8204cc2045aSjoerg cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
8214cc2045aSjoerg     struct vector_type_qualifier *v, const char *type_str)
8224cc2045aSjoerg {
8234cc2045aSjoerg 	struct vector_str subst_v;
824*d678c5d4Sjoerg 	enum type_qualifier t;
8254cc2045aSjoerg 	size_t idx, e_idx, e_len;
8264cc2045aSjoerg 	char *buf;
827*d678c5d4Sjoerg 	int rtn;
828*d678c5d4Sjoerg 	bool cv;
8294cc2045aSjoerg 
8304cc2045aSjoerg 	if (ddata == NULL || v == NULL)
8314cc2045aSjoerg 		return (0);
8324cc2045aSjoerg 
8334cc2045aSjoerg 	if ((idx = v->size) == 0)
8344cc2045aSjoerg 		return (1);
8354cc2045aSjoerg 
8364cc2045aSjoerg 	rtn = 0;
8374cc2045aSjoerg 	if (type_str != NULL) {
8384cc2045aSjoerg 		if (!vector_str_init(&subst_v))
8394cc2045aSjoerg 			return (0);
840*d678c5d4Sjoerg 		if (!VEC_PUSH_STR(&subst_v, type_str))
8414cc2045aSjoerg 			goto clean;
8424cc2045aSjoerg 	}
8434cc2045aSjoerg 
844*d678c5d4Sjoerg 	cv = true;
8454cc2045aSjoerg 	e_idx = 0;
8464cc2045aSjoerg 	while (idx > 0) {
8474cc2045aSjoerg 		switch (v->q_container[idx - 1]) {
8484cc2045aSjoerg 		case TYPE_PTR:
849*d678c5d4Sjoerg 			cv = false;
850*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
851*d678c5d4Sjoerg 				break;
852*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "*"))
8534cc2045aSjoerg 				goto clean;
8544cc2045aSjoerg 			if (type_str != NULL) {
855*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, "*"))
8564cc2045aSjoerg 					goto clean;
85786b377d0Spooka 				if (!cpp_demangle_push_subst_v(ddata,
85886b377d0Spooka 				    &subst_v))
8594cc2045aSjoerg 					goto clean;
8604cc2045aSjoerg 			}
8614cc2045aSjoerg 			break;
8624cc2045aSjoerg 
8634cc2045aSjoerg 		case TYPE_REF:
864*d678c5d4Sjoerg 			cv = false;
865*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
866*d678c5d4Sjoerg 				break;
867*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "&"))
8684cc2045aSjoerg 				goto clean;
8694cc2045aSjoerg 			if (type_str != NULL) {
870*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, "&"))
871*d678c5d4Sjoerg 					goto clean;
872*d678c5d4Sjoerg 				if (!cpp_demangle_push_subst_v(ddata,
873*d678c5d4Sjoerg 				    &subst_v))
874*d678c5d4Sjoerg 					goto clean;
875*d678c5d4Sjoerg 			}
876*d678c5d4Sjoerg 			break;
877*d678c5d4Sjoerg 
878*d678c5d4Sjoerg 		case TYPE_RREF:
879*d678c5d4Sjoerg 			cv = false;
880*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
881*d678c5d4Sjoerg 				break;
882*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "&&"))
883*d678c5d4Sjoerg 				goto clean;
884*d678c5d4Sjoerg 			if (type_str != NULL) {
885*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, "&&"))
8864cc2045aSjoerg 					goto clean;
88786b377d0Spooka 				if (!cpp_demangle_push_subst_v(ddata,
88886b377d0Spooka 				    &subst_v))
8894cc2045aSjoerg 					goto clean;
8904cc2045aSjoerg 			}
8914cc2045aSjoerg 			break;
8924cc2045aSjoerg 
8934cc2045aSjoerg 		case TYPE_CMX:
894*d678c5d4Sjoerg 			cv = false;
895*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
896*d678c5d4Sjoerg 				break;
897*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, " complex"))
8984cc2045aSjoerg 				goto clean;
8994cc2045aSjoerg 			if (type_str != NULL) {
900*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, " complex"))
9014cc2045aSjoerg 					goto clean;
90286b377d0Spooka 				if (!cpp_demangle_push_subst_v(ddata,
90386b377d0Spooka 				    &subst_v))
9044cc2045aSjoerg 					goto clean;
9054cc2045aSjoerg 			}
9064cc2045aSjoerg 			break;
9074cc2045aSjoerg 
9084cc2045aSjoerg 		case TYPE_IMG:
909*d678c5d4Sjoerg 			cv = false;
910*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
911*d678c5d4Sjoerg 				break;
912*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, " imaginary"))
9134cc2045aSjoerg 				goto clean;
9144cc2045aSjoerg 			if (type_str != NULL) {
915*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, " imaginary"))
9164cc2045aSjoerg 					goto clean;
91786b377d0Spooka 				if (!cpp_demangle_push_subst_v(ddata,
91886b377d0Spooka 				    &subst_v))
9194cc2045aSjoerg 					goto clean;
9204cc2045aSjoerg 			}
9214cc2045aSjoerg 			break;
9224cc2045aSjoerg 
9234cc2045aSjoerg 		case TYPE_EXT:
924*d678c5d4Sjoerg 			cv = false;
925*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
926*d678c5d4Sjoerg 				break;
92786b377d0Spooka 			if (v->ext_name.size == 0 ||
92886b377d0Spooka 			    e_idx > v->ext_name.size - 1)
9294cc2045aSjoerg 				goto clean;
93086b377d0Spooka 			if ((e_len = strlen(v->ext_name.container[e_idx])) ==
93186b377d0Spooka 			    0)
9324cc2045aSjoerg 				goto clean;
93386b377d0Spooka 			if ((buf = malloc(e_len + 2)) == NULL)
9344cc2045aSjoerg 				goto clean;
93586b377d0Spooka 			snprintf(buf, e_len + 2, " %s",
93686b377d0Spooka 			    v->ext_name.container[e_idx]);
9374cc2045aSjoerg 
938*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, buf)) {
9394cc2045aSjoerg 				free(buf);
9404cc2045aSjoerg 				goto clean;
9414cc2045aSjoerg 			}
9424cc2045aSjoerg 
9434cc2045aSjoerg 			if (type_str != NULL) {
944*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, buf)) {
9454cc2045aSjoerg 					free(buf);
9464cc2045aSjoerg 					goto clean;
9474cc2045aSjoerg 				}
94886b377d0Spooka 				if (!cpp_demangle_push_subst_v(ddata,
94986b377d0Spooka 				    &subst_v)) {
9504cc2045aSjoerg 					free(buf);
9514cc2045aSjoerg 					goto clean;
9524cc2045aSjoerg 				}
9534cc2045aSjoerg 			}
9544cc2045aSjoerg 			free(buf);
9554cc2045aSjoerg 			++e_idx;
9564cc2045aSjoerg 			break;
9574cc2045aSjoerg 
9584cc2045aSjoerg 		case TYPE_RST:
959*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
960*d678c5d4Sjoerg 			    cv)
961*d678c5d4Sjoerg 				break;
962*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
963*d678c5d4Sjoerg 				break;
964*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, " restrict"))
9654cc2045aSjoerg 				goto clean;
9664cc2045aSjoerg 			if (type_str != NULL) {
967*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, " restrict"))
9684cc2045aSjoerg 					goto clean;
969*d678c5d4Sjoerg 				if (idx - 1 > 0) {
970*d678c5d4Sjoerg 					t = v->q_container[idx - 2];
971*d678c5d4Sjoerg 					if (t == TYPE_RST || t == TYPE_VAT ||
972*d678c5d4Sjoerg 					    t == TYPE_CST)
973*d678c5d4Sjoerg 						break;
974*d678c5d4Sjoerg 				}
97586b377d0Spooka 				if (!cpp_demangle_push_subst_v(ddata,
97686b377d0Spooka 				    &subst_v))
9774cc2045aSjoerg 					goto clean;
9784cc2045aSjoerg 			}
9794cc2045aSjoerg 			break;
9804cc2045aSjoerg 
9814cc2045aSjoerg 		case TYPE_VAT:
982*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
983*d678c5d4Sjoerg 			    cv)
984*d678c5d4Sjoerg 				break;
985*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
986*d678c5d4Sjoerg 				break;
987*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, " volatile"))
9884cc2045aSjoerg 				goto clean;
9894cc2045aSjoerg 			if (type_str != NULL) {
990*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, " volatile"))
9914cc2045aSjoerg 					goto clean;
992*d678c5d4Sjoerg 				if (idx - 1 > 0) {
993*d678c5d4Sjoerg 					t = v->q_container[idx - 2];
994*d678c5d4Sjoerg 					if (t == TYPE_RST || t == TYPE_VAT ||
995*d678c5d4Sjoerg 					    t == TYPE_CST)
996*d678c5d4Sjoerg 						break;
997*d678c5d4Sjoerg 				}
99886b377d0Spooka 				if (!cpp_demangle_push_subst_v(ddata,
99986b377d0Spooka 				    &subst_v))
10004cc2045aSjoerg 					goto clean;
10014cc2045aSjoerg 			}
10024cc2045aSjoerg 			break;
10034cc2045aSjoerg 
10044cc2045aSjoerg 		case TYPE_CST:
1005*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
1006*d678c5d4Sjoerg 			    cv)
1007*d678c5d4Sjoerg 				break;
1008*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
1009*d678c5d4Sjoerg 				break;
1010*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, " const"))
10114cc2045aSjoerg 				goto clean;
10124cc2045aSjoerg 			if (type_str != NULL) {
1013*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, " const"))
10144cc2045aSjoerg 					goto clean;
1015*d678c5d4Sjoerg 				if (idx - 1 > 0) {
1016*d678c5d4Sjoerg 					t = v->q_container[idx - 2];
1017*d678c5d4Sjoerg 					if (t == TYPE_RST || t == TYPE_VAT ||
1018*d678c5d4Sjoerg 					    t == TYPE_CST)
1019*d678c5d4Sjoerg 						break;
1020*d678c5d4Sjoerg 				}
102186b377d0Spooka 				if (!cpp_demangle_push_subst_v(ddata,
102286b377d0Spooka 				    &subst_v))
10234cc2045aSjoerg 					goto clean;
10244cc2045aSjoerg 			}
10254cc2045aSjoerg 			break;
10264cc2045aSjoerg 
102786b377d0Spooka 		case TYPE_VEC:
1028*d678c5d4Sjoerg 			cv = false;
1029*d678c5d4Sjoerg 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
1030*d678c5d4Sjoerg 				break;
103186b377d0Spooka 			if (v->ext_name.size == 0 ||
103286b377d0Spooka 			    e_idx > v->ext_name.size - 1)
103386b377d0Spooka 				goto clean;
103486b377d0Spooka 			if ((e_len = strlen(v->ext_name.container[e_idx])) ==
103586b377d0Spooka 			    0)
103686b377d0Spooka 				goto clean;
103786b377d0Spooka 			if ((buf = malloc(e_len + 12)) == NULL)
103886b377d0Spooka 				goto clean;
103986b377d0Spooka 			snprintf(buf, e_len + 12, " __vector(%s)",
104086b377d0Spooka 			    v->ext_name.container[e_idx]);
1041*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, buf)) {
104286b377d0Spooka 				free(buf);
104386b377d0Spooka 				goto clean;
104486b377d0Spooka 			}
104586b377d0Spooka 			if (type_str != NULL) {
1046*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&subst_v, buf)) {
104786b377d0Spooka 					free(buf);
104886b377d0Spooka 					goto clean;
104986b377d0Spooka 				}
105086b377d0Spooka 				if (!cpp_demangle_push_subst_v(ddata,
105186b377d0Spooka 				    &subst_v)) {
105286b377d0Spooka 					free(buf);
105386b377d0Spooka 					goto clean;
105486b377d0Spooka 				}
105586b377d0Spooka 			}
105686b377d0Spooka 			free(buf);
105786b377d0Spooka 			++e_idx;
105886b377d0Spooka 			break;
1059*d678c5d4Sjoerg 		}
10604cc2045aSjoerg 		--idx;
10614cc2045aSjoerg 	}
10624cc2045aSjoerg 
10634cc2045aSjoerg 	rtn = 1;
10644cc2045aSjoerg clean:
10654cc2045aSjoerg 	if (type_str != NULL)
10664cc2045aSjoerg 		vector_str_dest(&subst_v);
10674cc2045aSjoerg 
10684cc2045aSjoerg 	return (rtn);
10694cc2045aSjoerg }
10704cc2045aSjoerg 
10714cc2045aSjoerg static int
cpp_demangle_get_subst(struct cpp_demangle_data * ddata,size_t idx)10724cc2045aSjoerg cpp_demangle_get_subst(struct cpp_demangle_data *ddata, size_t idx)
10734cc2045aSjoerg {
10744cc2045aSjoerg 	size_t len;
10754cc2045aSjoerg 
10764cc2045aSjoerg 	if (ddata == NULL || ddata->subst.size <= idx)
10774cc2045aSjoerg 		return (0);
10784cc2045aSjoerg 	if ((len = strlen(ddata->subst.container[idx])) == 0)
10794cc2045aSjoerg 		return (0);
10804cc2045aSjoerg 	if (!cpp_demangle_push_str(ddata, ddata->subst.container[idx], len))
10814cc2045aSjoerg 		return (0);
10824cc2045aSjoerg 
10834cc2045aSjoerg 	/* skip '_' */
10844cc2045aSjoerg 	++ddata->cur;
10854cc2045aSjoerg 
10864cc2045aSjoerg 	return (1);
10874cc2045aSjoerg }
10884cc2045aSjoerg 
10894cc2045aSjoerg static int
cpp_demangle_get_tmpl_param(struct cpp_demangle_data * ddata,size_t idx)10904cc2045aSjoerg cpp_demangle_get_tmpl_param(struct cpp_demangle_data *ddata, size_t idx)
10914cc2045aSjoerg {
10924cc2045aSjoerg 	size_t len;
10934cc2045aSjoerg 
10944cc2045aSjoerg 	if (ddata == NULL || ddata->tmpl.size <= idx)
10954cc2045aSjoerg 		return (0);
10964cc2045aSjoerg 	if ((len = strlen(ddata->tmpl.container[idx])) == 0)
10974cc2045aSjoerg 		return (0);
10984cc2045aSjoerg 	if (!cpp_demangle_push_str(ddata, ddata->tmpl.container[idx], len))
10994cc2045aSjoerg 		return (0);
11004cc2045aSjoerg 
11014cc2045aSjoerg 	++ddata->cur;
11024cc2045aSjoerg 
11034cc2045aSjoerg 	return (1);
11044cc2045aSjoerg }
11054cc2045aSjoerg 
11064cc2045aSjoerg static int
cpp_demangle_read_array(struct cpp_demangle_data * ddata)11074cc2045aSjoerg cpp_demangle_read_array(struct cpp_demangle_data *ddata)
11084cc2045aSjoerg {
11094cc2045aSjoerg 	size_t i, num_len, exp_len, p_idx, idx;
11104cc2045aSjoerg 	const char *num;
11114cc2045aSjoerg 	char *exp;
11124cc2045aSjoerg 
11134cc2045aSjoerg 	if (ddata == NULL || *(++ddata->cur) == '\0')
11144cc2045aSjoerg 		return (0);
11154cc2045aSjoerg 
11164cc2045aSjoerg 	if (*ddata->cur == '_') {
11174cc2045aSjoerg 		if (*(++ddata->cur) == '\0')
11184cc2045aSjoerg 			return (0);
11194cc2045aSjoerg 
1120*d678c5d4Sjoerg 		if (!cpp_demangle_read_type(ddata, NULL))
11214cc2045aSjoerg 			return (0);
11224cc2045aSjoerg 
1123*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, " []"))
11244cc2045aSjoerg 			return (0);
11254cc2045aSjoerg 	} else {
11264cc2045aSjoerg 		if (ELFTC_ISDIGIT(*ddata->cur) != 0) {
11274cc2045aSjoerg 			num = ddata->cur;
11284cc2045aSjoerg 			while (ELFTC_ISDIGIT(*ddata->cur) != 0)
11294cc2045aSjoerg 				++ddata->cur;
11304cc2045aSjoerg 			if (*ddata->cur != '_')
11314cc2045aSjoerg 				return (0);
11324cc2045aSjoerg 			num_len = ddata->cur - num;
11334cc2045aSjoerg 			assert(num_len > 0);
11344cc2045aSjoerg 			if (*(++ddata->cur) == '\0')
11354cc2045aSjoerg 				return (0);
1136*d678c5d4Sjoerg 			if (!cpp_demangle_read_type(ddata, NULL))
11374cc2045aSjoerg 				return (0);
1138*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, " ["))
11394cc2045aSjoerg 				return (0);
11404cc2045aSjoerg 			if (!cpp_demangle_push_str(ddata, num, num_len))
11414cc2045aSjoerg 				return (0);
1142*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "]"))
11434cc2045aSjoerg 				return (0);
11444cc2045aSjoerg 		} else {
11454cc2045aSjoerg 			p_idx = ddata->output.size;
11464cc2045aSjoerg 			if (!cpp_demangle_read_expression(ddata))
11474cc2045aSjoerg 				return (0);
11484cc2045aSjoerg 			if ((exp = vector_str_substr(&ddata->output, p_idx,
11494cc2045aSjoerg 				 ddata->output.size - 1, &exp_len)) == NULL)
11504cc2045aSjoerg 				return (0);
11514cc2045aSjoerg 			idx = ddata->output.size;
11524cc2045aSjoerg 			for (i = p_idx; i < idx; ++i)
11534cc2045aSjoerg 				if (!vector_str_pop(&ddata->output)) {
11544cc2045aSjoerg 					free(exp);
11554cc2045aSjoerg 					return (0);
11564cc2045aSjoerg 				}
11574cc2045aSjoerg 			if (*ddata->cur != '_') {
11584cc2045aSjoerg 				free(exp);
11594cc2045aSjoerg 				return (0);
11604cc2045aSjoerg 			}
11614cc2045aSjoerg 			++ddata->cur;
11624cc2045aSjoerg 			if (*ddata->cur == '\0') {
11634cc2045aSjoerg 				free(exp);
11644cc2045aSjoerg 				return (0);
11654cc2045aSjoerg 			}
1166*d678c5d4Sjoerg 			if (!cpp_demangle_read_type(ddata, NULL)) {
11674cc2045aSjoerg 				free(exp);
11684cc2045aSjoerg 				return (0);
11694cc2045aSjoerg 			}
1170*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, " [")) {
11714cc2045aSjoerg 				free(exp);
11724cc2045aSjoerg 				return (0);
11734cc2045aSjoerg 			}
11744cc2045aSjoerg 			if (!cpp_demangle_push_str(ddata, exp, exp_len)) {
11754cc2045aSjoerg 				free(exp);
11764cc2045aSjoerg 				return (0);
11774cc2045aSjoerg 			}
1178*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "]")) {
11794cc2045aSjoerg 				free(exp);
11804cc2045aSjoerg 				return (0);
11814cc2045aSjoerg 			}
11824cc2045aSjoerg 			free(exp);
11834cc2045aSjoerg 		}
11844cc2045aSjoerg 	}
11854cc2045aSjoerg 
11864cc2045aSjoerg 	return (1);
11874cc2045aSjoerg }
11884cc2045aSjoerg 
11894cc2045aSjoerg static int
cpp_demangle_read_expr_primary(struct cpp_demangle_data * ddata)11904cc2045aSjoerg cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
11914cc2045aSjoerg {
11924cc2045aSjoerg 	const char *num;
11934cc2045aSjoerg 
11944cc2045aSjoerg 	if (ddata == NULL || *(++ddata->cur) == '\0')
11954cc2045aSjoerg 		return (0);
11964cc2045aSjoerg 
11974cc2045aSjoerg 	if (*ddata->cur == '_' && *(ddata->cur + 1) == 'Z') {
11984cc2045aSjoerg 		ddata->cur += 2;
11994cc2045aSjoerg 		if (*ddata->cur == '\0')
12004cc2045aSjoerg 			return (0);
12014cc2045aSjoerg 		if (!cpp_demangle_read_encoding(ddata))
12024cc2045aSjoerg 			return (0);
12034cc2045aSjoerg 		++ddata->cur;
12044cc2045aSjoerg 		return (1);
12054cc2045aSjoerg 	}
12064cc2045aSjoerg 
12074cc2045aSjoerg 	switch (*ddata->cur) {
12084cc2045aSjoerg 	case 'b':
120986b377d0Spooka 		if (*(ddata->cur + 2) != 'E')
121086b377d0Spooka 			return (0);
12114cc2045aSjoerg 		switch (*(++ddata->cur)) {
12124cc2045aSjoerg 		case '0':
121386b377d0Spooka 			ddata->cur += 2;
1214*d678c5d4Sjoerg 			return (DEM_PUSH_STR(ddata, "false"));
12154cc2045aSjoerg 		case '1':
121686b377d0Spooka 			ddata->cur += 2;
1217*d678c5d4Sjoerg 			return (DEM_PUSH_STR(ddata, "true"));
12184cc2045aSjoerg 		default:
12194cc2045aSjoerg 			return (0);
1220*d678c5d4Sjoerg 		}
12214cc2045aSjoerg 
12224cc2045aSjoerg 	case 'd':
12234cc2045aSjoerg 		++ddata->cur;
12244cc2045aSjoerg 		return (cpp_demangle_push_fp(ddata, decode_fp_to_double));
12254cc2045aSjoerg 
12264cc2045aSjoerg 	case 'e':
12274cc2045aSjoerg 		++ddata->cur;
12284cc2045aSjoerg 		if (sizeof(long double) == 10)
12294cc2045aSjoerg 			return (cpp_demangle_push_fp(ddata,
12304cc2045aSjoerg 			    decode_fp_to_double));
12314cc2045aSjoerg 		return (cpp_demangle_push_fp(ddata, decode_fp_to_float80));
12324cc2045aSjoerg 
12334cc2045aSjoerg 	case 'f':
12344cc2045aSjoerg 		++ddata->cur;
12354cc2045aSjoerg 		return (cpp_demangle_push_fp(ddata, decode_fp_to_float));
12364cc2045aSjoerg 
12374cc2045aSjoerg 	case 'g':
12384cc2045aSjoerg 		++ddata->cur;
12394cc2045aSjoerg 		if (sizeof(long double) == 16)
12404cc2045aSjoerg 			return (cpp_demangle_push_fp(ddata,
12414cc2045aSjoerg 			    decode_fp_to_double));
12424cc2045aSjoerg 		return (cpp_demangle_push_fp(ddata, decode_fp_to_float128));
12434cc2045aSjoerg 
12444cc2045aSjoerg 	case 'i':
12454cc2045aSjoerg 	case 'j':
12464cc2045aSjoerg 	case 'l':
12474cc2045aSjoerg 	case 'm':
12484cc2045aSjoerg 	case 'n':
12494cc2045aSjoerg 	case 's':
12504cc2045aSjoerg 	case 't':
12514cc2045aSjoerg 	case 'x':
12524cc2045aSjoerg 	case 'y':
12534cc2045aSjoerg 		if (*(++ddata->cur) == 'n') {
1254*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "-"))
12554cc2045aSjoerg 				return (0);
12564cc2045aSjoerg 			++ddata->cur;
12574cc2045aSjoerg 		}
12584cc2045aSjoerg 		num = ddata->cur;
12594cc2045aSjoerg 		while (*ddata->cur != 'E') {
12604cc2045aSjoerg 			if (!ELFTC_ISDIGIT(*ddata->cur))
12614cc2045aSjoerg 				return (0);
12624cc2045aSjoerg 			++ddata->cur;
12634cc2045aSjoerg 		}
12644cc2045aSjoerg 		++ddata->cur;
126586b377d0Spooka 		return (cpp_demangle_push_str(ddata, num,
126686b377d0Spooka 		    ddata->cur - num - 1));
12674cc2045aSjoerg 
12684cc2045aSjoerg 	default:
12694cc2045aSjoerg 		return (0);
1270*d678c5d4Sjoerg 	}
12714cc2045aSjoerg }
12724cc2045aSjoerg 
12734cc2045aSjoerg static int
cpp_demangle_read_expression(struct cpp_demangle_data * ddata)12744cc2045aSjoerg cpp_demangle_read_expression(struct cpp_demangle_data *ddata)
12754cc2045aSjoerg {
12764cc2045aSjoerg 
12774cc2045aSjoerg 	if (ddata == NULL || *ddata->cur == '\0')
12784cc2045aSjoerg 		return (0);
12794cc2045aSjoerg 
12804cc2045aSjoerg 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
12814cc2045aSjoerg 	case SIMPLE_HASH('s', 't'):
12824cc2045aSjoerg 		ddata->cur += 2;
1283*d678c5d4Sjoerg 		return (cpp_demangle_read_type(ddata, NULL));
12844cc2045aSjoerg 
12854cc2045aSjoerg 	case SIMPLE_HASH('s', 'r'):
12864cc2045aSjoerg 		ddata->cur += 2;
1287*d678c5d4Sjoerg 		if (!cpp_demangle_read_type(ddata, NULL))
12884cc2045aSjoerg 			return (0);
12894cc2045aSjoerg 		if (!cpp_demangle_read_uqname(ddata))
12904cc2045aSjoerg 			return (0);
12914cc2045aSjoerg 		if (*ddata->cur == 'I')
12924cc2045aSjoerg 			return (cpp_demangle_read_tmpl_args(ddata));
12934cc2045aSjoerg 		return (1);
12944cc2045aSjoerg 
12954cc2045aSjoerg 	case SIMPLE_HASH('a', 'a'):
12964cc2045aSjoerg 		/* operator && */
12974cc2045aSjoerg 		ddata->cur += 2;
12984cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "&&", 2));
12994cc2045aSjoerg 
13004cc2045aSjoerg 	case SIMPLE_HASH('a', 'd'):
13014cc2045aSjoerg 		/* operator & (unary) */
13024cc2045aSjoerg 		ddata->cur += 2;
13034cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "&", 1));
13044cc2045aSjoerg 
13054cc2045aSjoerg 	case SIMPLE_HASH('a', 'n'):
13064cc2045aSjoerg 		/* operator & */
13074cc2045aSjoerg 		ddata->cur += 2;
13084cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "&", 1));
13094cc2045aSjoerg 
13104cc2045aSjoerg 	case SIMPLE_HASH('a', 'N'):
13114cc2045aSjoerg 		/* operator &= */
13124cc2045aSjoerg 		ddata->cur += 2;
13134cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "&=", 2));
13144cc2045aSjoerg 
13154cc2045aSjoerg 	case SIMPLE_HASH('a', 'S'):
13164cc2045aSjoerg 		/* operator = */
13174cc2045aSjoerg 		ddata->cur += 2;
13184cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "=", 1));
13194cc2045aSjoerg 
13204cc2045aSjoerg 	case SIMPLE_HASH('c', 'l'):
13214cc2045aSjoerg 		/* operator () */
13224cc2045aSjoerg 		ddata->cur += 2;
13234cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "()", 2));
13244cc2045aSjoerg 
13254cc2045aSjoerg 	case SIMPLE_HASH('c', 'm'):
13264cc2045aSjoerg 		/* operator , */
13274cc2045aSjoerg 		ddata->cur += 2;
13284cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, ",", 1));
13294cc2045aSjoerg 
13304cc2045aSjoerg 	case SIMPLE_HASH('c', 'o'):
13314cc2045aSjoerg 		/* operator ~ */
13324cc2045aSjoerg 		ddata->cur += 2;
13334cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "~", 1));
13344cc2045aSjoerg 
13354cc2045aSjoerg 	case SIMPLE_HASH('c', 'v'):
13364cc2045aSjoerg 		/* operator (cast) */
13374cc2045aSjoerg 		ddata->cur += 2;
13384cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "(cast)", 6));
13394cc2045aSjoerg 
13404cc2045aSjoerg 	case SIMPLE_HASH('d', 'a'):
13414cc2045aSjoerg 		/* operator delete [] */
13424cc2045aSjoerg 		ddata->cur += 2;
13434cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "delete []", 9));
13444cc2045aSjoerg 
13454cc2045aSjoerg 	case SIMPLE_HASH('d', 'e'):
13464cc2045aSjoerg 		/* operator * (unary) */
13474cc2045aSjoerg 		ddata->cur += 2;
13484cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "*", 1));
13494cc2045aSjoerg 
13504cc2045aSjoerg 	case SIMPLE_HASH('d', 'l'):
13514cc2045aSjoerg 		/* operator delete */
13524cc2045aSjoerg 		ddata->cur += 2;
13534cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "delete", 6));
13544cc2045aSjoerg 
13554cc2045aSjoerg 	case SIMPLE_HASH('d', 'v'):
13564cc2045aSjoerg 		/* operator / */
13574cc2045aSjoerg 		ddata->cur += 2;
13584cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "/", 1));
13594cc2045aSjoerg 
13604cc2045aSjoerg 	case SIMPLE_HASH('d', 'V'):
13614cc2045aSjoerg 		/* operator /= */
13624cc2045aSjoerg 		ddata->cur += 2;
13634cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "/=", 2));
13644cc2045aSjoerg 
13654cc2045aSjoerg 	case SIMPLE_HASH('e', 'o'):
13664cc2045aSjoerg 		/* operator ^ */
13674cc2045aSjoerg 		ddata->cur += 2;
13684cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "^", 1));
13694cc2045aSjoerg 
13704cc2045aSjoerg 	case SIMPLE_HASH('e', 'O'):
13714cc2045aSjoerg 		/* operator ^= */
13724cc2045aSjoerg 		ddata->cur += 2;
13734cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "^=", 2));
13744cc2045aSjoerg 
13754cc2045aSjoerg 	case SIMPLE_HASH('e', 'q'):
13764cc2045aSjoerg 		/* operator == */
13774cc2045aSjoerg 		ddata->cur += 2;
13784cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "==", 2));
13794cc2045aSjoerg 
13804cc2045aSjoerg 	case SIMPLE_HASH('g', 'e'):
13814cc2045aSjoerg 		/* operator >= */
13824cc2045aSjoerg 		ddata->cur += 2;
13834cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, ">=", 2));
13844cc2045aSjoerg 
13854cc2045aSjoerg 	case SIMPLE_HASH('g', 't'):
13864cc2045aSjoerg 		/* operator > */
13874cc2045aSjoerg 		ddata->cur += 2;
13884cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, ">", 1));
13894cc2045aSjoerg 
13904cc2045aSjoerg 	case SIMPLE_HASH('i', 'x'):
13914cc2045aSjoerg 		/* operator [] */
13924cc2045aSjoerg 		ddata->cur += 2;
13934cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "[]", 2));
13944cc2045aSjoerg 
13954cc2045aSjoerg 	case SIMPLE_HASH('l', 'e'):
13964cc2045aSjoerg 		/* operator <= */
13974cc2045aSjoerg 		ddata->cur += 2;
13984cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "<=", 2));
13994cc2045aSjoerg 
14004cc2045aSjoerg 	case SIMPLE_HASH('l', 's'):
14014cc2045aSjoerg 		/* operator << */
14024cc2045aSjoerg 		ddata->cur += 2;
14034cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "<<", 2));
14044cc2045aSjoerg 
14054cc2045aSjoerg 	case SIMPLE_HASH('l', 'S'):
14064cc2045aSjoerg 		/* operator <<= */
14074cc2045aSjoerg 		ddata->cur += 2;
14084cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "<<=", 3));
14094cc2045aSjoerg 
14104cc2045aSjoerg 	case SIMPLE_HASH('l', 't'):
14114cc2045aSjoerg 		/* operator < */
14124cc2045aSjoerg 		ddata->cur += 2;
14134cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "<", 1));
14144cc2045aSjoerg 
14154cc2045aSjoerg 	case SIMPLE_HASH('m', 'i'):
14164cc2045aSjoerg 		/* operator - */
14174cc2045aSjoerg 		ddata->cur += 2;
14184cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "-", 1));
14194cc2045aSjoerg 
14204cc2045aSjoerg 	case SIMPLE_HASH('m', 'I'):
14214cc2045aSjoerg 		/* operator -= */
14224cc2045aSjoerg 		ddata->cur += 2;
14234cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "-=", 2));
14244cc2045aSjoerg 
14254cc2045aSjoerg 	case SIMPLE_HASH('m', 'l'):
14264cc2045aSjoerg 		/* operator * */
14274cc2045aSjoerg 		ddata->cur += 2;
14284cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "*", 1));
14294cc2045aSjoerg 
14304cc2045aSjoerg 	case SIMPLE_HASH('m', 'L'):
14314cc2045aSjoerg 		/* operator *= */
14324cc2045aSjoerg 		ddata->cur += 2;
14334cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "*=", 2));
14344cc2045aSjoerg 
14354cc2045aSjoerg 	case SIMPLE_HASH('m', 'm'):
14364cc2045aSjoerg 		/* operator -- */
14374cc2045aSjoerg 		ddata->cur += 2;
14384cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "--", 2));
14394cc2045aSjoerg 
14404cc2045aSjoerg 	case SIMPLE_HASH('n', 'a'):
14414cc2045aSjoerg 		/* operator new[] */
14424cc2045aSjoerg 		ddata->cur += 2;
14434cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "new []", 6));
14444cc2045aSjoerg 
14454cc2045aSjoerg 	case SIMPLE_HASH('n', 'e'):
14464cc2045aSjoerg 		/* operator != */
14474cc2045aSjoerg 		ddata->cur += 2;
14484cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "!=", 2));
14494cc2045aSjoerg 
14504cc2045aSjoerg 	case SIMPLE_HASH('n', 'g'):
14514cc2045aSjoerg 		/* operator - (unary) */
14524cc2045aSjoerg 		ddata->cur += 2;
14534cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "-", 1));
14544cc2045aSjoerg 
14554cc2045aSjoerg 	case SIMPLE_HASH('n', 't'):
14564cc2045aSjoerg 		/* operator ! */
14574cc2045aSjoerg 		ddata->cur += 2;
14584cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "!", 1));
14594cc2045aSjoerg 
14604cc2045aSjoerg 	case SIMPLE_HASH('n', 'w'):
14614cc2045aSjoerg 		/* operator new */
14624cc2045aSjoerg 		ddata->cur += 2;
14634cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "new", 3));
14644cc2045aSjoerg 
14654cc2045aSjoerg 	case SIMPLE_HASH('o', 'o'):
14664cc2045aSjoerg 		/* operator || */
14674cc2045aSjoerg 		ddata->cur += 2;
14684cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "||", 2));
14694cc2045aSjoerg 
14704cc2045aSjoerg 	case SIMPLE_HASH('o', 'r'):
14714cc2045aSjoerg 		/* operator | */
14724cc2045aSjoerg 		ddata->cur += 2;
14734cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "|", 1));
14744cc2045aSjoerg 
14754cc2045aSjoerg 	case SIMPLE_HASH('o', 'R'):
14764cc2045aSjoerg 		/* operator |= */
14774cc2045aSjoerg 		ddata->cur += 2;
14784cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "|=", 2));
14794cc2045aSjoerg 
14804cc2045aSjoerg 	case SIMPLE_HASH('p', 'l'):
14814cc2045aSjoerg 		/* operator + */
14824cc2045aSjoerg 		ddata->cur += 2;
14834cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "+", 1));
14844cc2045aSjoerg 
14854cc2045aSjoerg 	case SIMPLE_HASH('p', 'L'):
14864cc2045aSjoerg 		/* operator += */
14874cc2045aSjoerg 		ddata->cur += 2;
14884cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "+=", 2));
14894cc2045aSjoerg 
14904cc2045aSjoerg 	case SIMPLE_HASH('p', 'm'):
14914cc2045aSjoerg 		/* operator ->* */
14924cc2045aSjoerg 		ddata->cur += 2;
14934cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "->*", 3));
14944cc2045aSjoerg 
14954cc2045aSjoerg 	case SIMPLE_HASH('p', 'p'):
14964cc2045aSjoerg 		/* operator ++ */
14974cc2045aSjoerg 		ddata->cur += 2;
14984cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "++", 2));
14994cc2045aSjoerg 
15004cc2045aSjoerg 	case SIMPLE_HASH('p', 's'):
15014cc2045aSjoerg 		/* operator + (unary) */
15024cc2045aSjoerg 		ddata->cur += 2;
15034cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "+", 1));
15044cc2045aSjoerg 
15054cc2045aSjoerg 	case SIMPLE_HASH('p', 't'):
15064cc2045aSjoerg 		/* operator -> */
15074cc2045aSjoerg 		ddata->cur += 2;
15084cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "->", 2));
15094cc2045aSjoerg 
15104cc2045aSjoerg 	case SIMPLE_HASH('q', 'u'):
15114cc2045aSjoerg 		/* operator ? */
15124cc2045aSjoerg 		ddata->cur += 2;
15134cc2045aSjoerg 		return (cpp_demangle_read_expression_trinary(ddata, "?", 1,
15144cc2045aSjoerg 		    ":", 1));
15154cc2045aSjoerg 
15164cc2045aSjoerg 	case SIMPLE_HASH('r', 'm'):
15174cc2045aSjoerg 		/* operator % */
15184cc2045aSjoerg 		ddata->cur += 2;
15194cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "%", 1));
15204cc2045aSjoerg 
15214cc2045aSjoerg 	case SIMPLE_HASH('r', 'M'):
15224cc2045aSjoerg 		/* operator %= */
15234cc2045aSjoerg 		ddata->cur += 2;
15244cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, "%=", 2));
15254cc2045aSjoerg 
15264cc2045aSjoerg 	case SIMPLE_HASH('r', 's'):
15274cc2045aSjoerg 		/* operator >> */
15284cc2045aSjoerg 		ddata->cur += 2;
15294cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, ">>", 2));
15304cc2045aSjoerg 
15314cc2045aSjoerg 	case SIMPLE_HASH('r', 'S'):
15324cc2045aSjoerg 		/* operator >>= */
15334cc2045aSjoerg 		ddata->cur += 2;
15344cc2045aSjoerg 		return (cpp_demangle_read_expression_binary(ddata, ">>=", 3));
15354cc2045aSjoerg 
15364cc2045aSjoerg 	case SIMPLE_HASH('r', 'z'):
15374cc2045aSjoerg 		/* operator sizeof */
15384cc2045aSjoerg 		ddata->cur += 2;
15394cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
15404cc2045aSjoerg 
15414cc2045aSjoerg 	case SIMPLE_HASH('s', 'v'):
15424cc2045aSjoerg 		/* operator sizeof */
15434cc2045aSjoerg 		ddata->cur += 2;
15444cc2045aSjoerg 		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
1545*d678c5d4Sjoerg 	}
15464cc2045aSjoerg 
15474cc2045aSjoerg 	switch (*ddata->cur) {
15484cc2045aSjoerg 	case 'L':
15494cc2045aSjoerg 		return (cpp_demangle_read_expr_primary(ddata));
15504cc2045aSjoerg 	case 'T':
15514cc2045aSjoerg 		return (cpp_demangle_read_tmpl_param(ddata));
1552*d678c5d4Sjoerg 	}
15534cc2045aSjoerg 
15544cc2045aSjoerg 	return (0);
15554cc2045aSjoerg }
15564cc2045aSjoerg 
15574cc2045aSjoerg static int
cpp_demangle_read_expression_flat(struct cpp_demangle_data * ddata,char ** str)155886b377d0Spooka cpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str)
155986b377d0Spooka {
156086b377d0Spooka 	struct vector_str *output;
156186b377d0Spooka 	size_t i, p_idx, idx, exp_len;
156286b377d0Spooka 	char *exp;
156386b377d0Spooka 
1564*d678c5d4Sjoerg 	output = &ddata->output;
156586b377d0Spooka 
156686b377d0Spooka 	p_idx = output->size;
156786b377d0Spooka 
156886b377d0Spooka 	if (!cpp_demangle_read_expression(ddata))
156986b377d0Spooka 		return (0);
157086b377d0Spooka 
157186b377d0Spooka 	if ((exp = vector_str_substr(output, p_idx, output->size - 1,
157286b377d0Spooka 	    &exp_len)) == NULL)
157386b377d0Spooka 		return (0);
157486b377d0Spooka 
157586b377d0Spooka 	idx = output->size;
157686b377d0Spooka 	for (i = p_idx; i < idx; ++i) {
157786b377d0Spooka 		if (!vector_str_pop(output)) {
157886b377d0Spooka 			free(exp);
157986b377d0Spooka 			return (0);
158086b377d0Spooka 		}
158186b377d0Spooka 	}
158286b377d0Spooka 
158386b377d0Spooka 	*str = exp;
158486b377d0Spooka 
158586b377d0Spooka 	return (1);
158686b377d0Spooka }
158786b377d0Spooka 
158886b377d0Spooka static int
cpp_demangle_read_expression_binary(struct cpp_demangle_data * ddata,const char * name,size_t len)15894cc2045aSjoerg cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
15904cc2045aSjoerg     const char *name, size_t len)
15914cc2045aSjoerg {
15924cc2045aSjoerg 
15934cc2045aSjoerg 	if (ddata == NULL || name == NULL || len == 0)
15944cc2045aSjoerg 		return (0);
15954cc2045aSjoerg 	if (!cpp_demangle_read_expression(ddata))
15964cc2045aSjoerg 		return (0);
15974cc2045aSjoerg 	if (!cpp_demangle_push_str(ddata, name, len))
15984cc2045aSjoerg 		return (0);
15994cc2045aSjoerg 
16004cc2045aSjoerg 	return (cpp_demangle_read_expression(ddata));
16014cc2045aSjoerg }
16024cc2045aSjoerg 
16034cc2045aSjoerg static int
cpp_demangle_read_expression_unary(struct cpp_demangle_data * ddata,const char * name,size_t len)16044cc2045aSjoerg cpp_demangle_read_expression_unary(struct cpp_demangle_data *ddata,
16054cc2045aSjoerg     const char *name, size_t len)
16064cc2045aSjoerg {
16074cc2045aSjoerg 
16084cc2045aSjoerg 	if (ddata == NULL || name == NULL || len == 0)
16094cc2045aSjoerg 		return (0);
16104cc2045aSjoerg 	if (!cpp_demangle_read_expression(ddata))
16114cc2045aSjoerg 		return (0);
16124cc2045aSjoerg 
16134cc2045aSjoerg 	return (cpp_demangle_push_str(ddata, name, len));
16144cc2045aSjoerg }
16154cc2045aSjoerg 
16164cc2045aSjoerg static int
cpp_demangle_read_expression_trinary(struct cpp_demangle_data * ddata,const char * name1,size_t len1,const char * name2,size_t len2)16174cc2045aSjoerg cpp_demangle_read_expression_trinary(struct cpp_demangle_data *ddata,
16184cc2045aSjoerg     const char *name1, size_t len1, const char *name2, size_t len2)
16194cc2045aSjoerg {
16204cc2045aSjoerg 
16214cc2045aSjoerg 	if (ddata == NULL || name1 == NULL || len1 == 0 || name2 == NULL ||
16224cc2045aSjoerg 	    len2 == 0)
16234cc2045aSjoerg 		return (0);
16244cc2045aSjoerg 
16254cc2045aSjoerg 	if (!cpp_demangle_read_expression(ddata))
16264cc2045aSjoerg 		return (0);
16274cc2045aSjoerg 	if (!cpp_demangle_push_str(ddata, name1, len1))
16284cc2045aSjoerg 		return (0);
16294cc2045aSjoerg 	if (!cpp_demangle_read_expression(ddata))
16304cc2045aSjoerg 		return (0);
16314cc2045aSjoerg 	if (!cpp_demangle_push_str(ddata, name2, len2))
16324cc2045aSjoerg 		return (0);
16334cc2045aSjoerg 
16344cc2045aSjoerg 	return (cpp_demangle_read_expression(ddata));
16354cc2045aSjoerg }
16364cc2045aSjoerg 
16374cc2045aSjoerg static int
cpp_demangle_read_function(struct cpp_demangle_data * ddata,int * ext_c,struct vector_type_qualifier * v)16384cc2045aSjoerg cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
16394cc2045aSjoerg     struct vector_type_qualifier *v)
16404cc2045aSjoerg {
1641*d678c5d4Sjoerg 	struct type_delimit td;
1642*d678c5d4Sjoerg 	struct read_cmd_item *rc;
16434cc2045aSjoerg 	size_t class_type_size, class_type_len, limit;
16444cc2045aSjoerg 	const char *class_type;
1645*d678c5d4Sjoerg 	int i;
1646*d678c5d4Sjoerg 	bool paren, non_cv_qualifier;
16474cc2045aSjoerg 
16484cc2045aSjoerg 	if (ddata == NULL || *ddata->cur != 'F' || v == NULL)
16494cc2045aSjoerg 		return (0);
16504cc2045aSjoerg 
16514cc2045aSjoerg 	++ddata->cur;
16524cc2045aSjoerg 	if (*ddata->cur == 'Y') {
16534cc2045aSjoerg 		if (ext_c != NULL)
16544cc2045aSjoerg 			*ext_c = 1;
16554cc2045aSjoerg 		++ddata->cur;
16564cc2045aSjoerg 	}
1657*d678c5d4Sjoerg 
1658*d678c5d4Sjoerg 	/* Return type */
1659*d678c5d4Sjoerg 	if (!cpp_demangle_read_type(ddata, NULL))
16604cc2045aSjoerg 		return (0);
1661*d678c5d4Sjoerg 
16624cc2045aSjoerg 	if (*ddata->cur != 'E') {
1663*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, " "))
16644cc2045aSjoerg 			return (0);
1665*d678c5d4Sjoerg 
1666*d678c5d4Sjoerg 		non_cv_qualifier = false;
1667*d678c5d4Sjoerg 		if (v->size > 0) {
1668*d678c5d4Sjoerg 			for (i = 0; (size_t) i < v->size; i++) {
1669*d678c5d4Sjoerg 				if (v->q_container[i] != TYPE_RST &&
1670*d678c5d4Sjoerg 				    v->q_container[i] != TYPE_VAT &&
1671*d678c5d4Sjoerg 				    v->q_container[i] != TYPE_CST) {
1672*d678c5d4Sjoerg 					non_cv_qualifier = true;
1673*d678c5d4Sjoerg 					break;
1674*d678c5d4Sjoerg 				}
1675*d678c5d4Sjoerg 			}
1676*d678c5d4Sjoerg 		}
1677*d678c5d4Sjoerg 
1678*d678c5d4Sjoerg 		paren = false;
1679*d678c5d4Sjoerg 		rc = vector_read_cmd_find(&ddata->cmd, READ_PTRMEM);
1680*d678c5d4Sjoerg 		if (non_cv_qualifier || rc != NULL) {
1681*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "("))
1682*d678c5d4Sjoerg 				return (0);
1683*d678c5d4Sjoerg 			paren = true;
1684*d678c5d4Sjoerg 		}
1685*d678c5d4Sjoerg 
1686*d678c5d4Sjoerg 		/* Push non-cv qualifiers. */
1687*d678c5d4Sjoerg 		ddata->push_qualifier = PUSH_NON_CV_QUALIFIER;
1688*d678c5d4Sjoerg 		if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
1689*d678c5d4Sjoerg 			return (0);
1690*d678c5d4Sjoerg 
1691*d678c5d4Sjoerg 		if (rc) {
1692*d678c5d4Sjoerg 			if (non_cv_qualifier && !DEM_PUSH_STR(ddata, " "))
1693*d678c5d4Sjoerg 				return (0);
16944cc2045aSjoerg 			if ((class_type_size = ddata->class_type.size) == 0)
16954cc2045aSjoerg 				return (0);
16964cc2045aSjoerg 			class_type =
16974cc2045aSjoerg 			    ddata->class_type.container[class_type_size - 1];
16984cc2045aSjoerg 			if (class_type == NULL)
16994cc2045aSjoerg 				return (0);
17004cc2045aSjoerg 			if ((class_type_len = strlen(class_type)) == 0)
17014cc2045aSjoerg 				return (0);
17024cc2045aSjoerg 			if (!cpp_demangle_push_str(ddata, class_type,
17034cc2045aSjoerg 			    class_type_len))
17044cc2045aSjoerg 				return (0);
1705*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "::*"))
1706*d678c5d4Sjoerg 				return (0);
1707*d678c5d4Sjoerg 			/* Push pointer-to-member qualifiers. */
1708*d678c5d4Sjoerg 			ddata->push_qualifier = PUSH_ALL_QUALIFIER;
1709*d678c5d4Sjoerg 			if (!cpp_demangle_push_type_qualifier(ddata, rc->data,
1710*d678c5d4Sjoerg 			    NULL))
17114cc2045aSjoerg 				return (0);
17124cc2045aSjoerg 			++ddata->func_type;
17134cc2045aSjoerg 		}
17144cc2045aSjoerg 
1715*d678c5d4Sjoerg 		if (paren) {
1716*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, ")"))
17174cc2045aSjoerg 				return (0);
1718*d678c5d4Sjoerg 			paren = false;
1719*d678c5d4Sjoerg 		}
17204cc2045aSjoerg 
1721*d678c5d4Sjoerg 		td.paren = false;
1722*d678c5d4Sjoerg 		td.firstp = true;
17234cc2045aSjoerg 		limit = 0;
1724*d678c5d4Sjoerg 		ddata->is_functype = true;
17254cc2045aSjoerg 		for (;;) {
1726*d678c5d4Sjoerg 			if (!cpp_demangle_read_type(ddata, &td))
17274cc2045aSjoerg 				return (0);
17284cc2045aSjoerg 			if (*ddata->cur == 'E')
17294cc2045aSjoerg 				break;
17304cc2045aSjoerg 			if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
17314cc2045aSjoerg 				return (0);
17324cc2045aSjoerg 		}
1733*d678c5d4Sjoerg 		ddata->is_functype = false;
1734*d678c5d4Sjoerg 		if (td.paren) {
1735*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, ")"))
17364cc2045aSjoerg 				return (0);
1737*d678c5d4Sjoerg 			td.paren = false;
1738*d678c5d4Sjoerg 		}
1739*d678c5d4Sjoerg 
1740*d678c5d4Sjoerg 		/* Push CV qualifiers. */
1741*d678c5d4Sjoerg 		ddata->push_qualifier = PUSH_CV_QUALIFIER;
1742*d678c5d4Sjoerg 		if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
1743*d678c5d4Sjoerg 			return (0);
1744*d678c5d4Sjoerg 
1745*d678c5d4Sjoerg 		ddata->push_qualifier = PUSH_ALL_QUALIFIER;
1746*d678c5d4Sjoerg 
1747*d678c5d4Sjoerg 		/* Release type qualifier vector. */
17484cc2045aSjoerg 		vector_type_qualifier_dest(v);
17494cc2045aSjoerg 		if (!vector_type_qualifier_init(v))
17504cc2045aSjoerg 			return (0);
17514cc2045aSjoerg 
1752*d678c5d4Sjoerg 		/* Push ref-qualifiers. */
1753*d678c5d4Sjoerg 		if (ddata->ref_qualifier) {
1754*d678c5d4Sjoerg 			switch (ddata->ref_qualifier_type) {
1755*d678c5d4Sjoerg 			case TYPE_REF:
1756*d678c5d4Sjoerg 				if (!DEM_PUSH_STR(ddata, " &"))
17574cc2045aSjoerg 					return (0);
1758*d678c5d4Sjoerg 				break;
1759*d678c5d4Sjoerg 			case TYPE_RREF:
1760*d678c5d4Sjoerg 				if (!DEM_PUSH_STR(ddata, " &&"))
1761*d678c5d4Sjoerg 					return (0);
1762*d678c5d4Sjoerg 				break;
1763*d678c5d4Sjoerg 			default:
1764*d678c5d4Sjoerg 				return (0);
1765*d678c5d4Sjoerg 			}
1766*d678c5d4Sjoerg 			ddata->ref_qualifier = false;
1767*d678c5d4Sjoerg 		}
17684cc2045aSjoerg 	}
17694cc2045aSjoerg 
17704cc2045aSjoerg 	++ddata->cur;
17714cc2045aSjoerg 
17724cc2045aSjoerg 	return (1);
17734cc2045aSjoerg }
17744cc2045aSjoerg 
17754cc2045aSjoerg /* read encoding, encoding are function name, data name, special-name */
17764cc2045aSjoerg static int
cpp_demangle_read_encoding(struct cpp_demangle_data * ddata)17774cc2045aSjoerg cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
17784cc2045aSjoerg {
177986b377d0Spooka 	char *name, *type, *num_str;
178086b377d0Spooka 	long offset;
178186b377d0Spooka 	int rtn;
17824cc2045aSjoerg 
17834cc2045aSjoerg 	if (ddata == NULL || *ddata->cur == '\0')
17844cc2045aSjoerg 		return (0);
17854cc2045aSjoerg 
17864cc2045aSjoerg 	/* special name */
17874cc2045aSjoerg 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
178886b377d0Spooka 	case SIMPLE_HASH('G', 'A'):
1789*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "hidden alias for "))
179086b377d0Spooka 			return (0);
179186b377d0Spooka 		ddata->cur += 2;
179286b377d0Spooka 		if (*ddata->cur == '\0')
179386b377d0Spooka 			return (0);
179486b377d0Spooka 		return (cpp_demangle_read_encoding(ddata));
179586b377d0Spooka 
179686b377d0Spooka 	case SIMPLE_HASH('G', 'R'):
1797*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "reference temporary #"))
179886b377d0Spooka 			return (0);
179986b377d0Spooka 		ddata->cur += 2;
180086b377d0Spooka 		if (*ddata->cur == '\0')
180186b377d0Spooka 			return (0);
180286b377d0Spooka 		if (!cpp_demangle_read_name_flat(ddata, &name))
180386b377d0Spooka 			return (0);
180486b377d0Spooka 		rtn = 0;
180586b377d0Spooka 		if (!cpp_demangle_read_number_as_string(ddata, &num_str))
180686b377d0Spooka 			goto clean1;
1807*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, num_str))
180886b377d0Spooka 			goto clean2;
1809*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, " for "))
181086b377d0Spooka 			goto clean2;
1811*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, name))
181286b377d0Spooka 			goto clean2;
181386b377d0Spooka 		rtn = 1;
181486b377d0Spooka 	clean2:
181586b377d0Spooka 		free(num_str);
181686b377d0Spooka 	clean1:
181786b377d0Spooka 		free(name);
181886b377d0Spooka 		return (rtn);
181986b377d0Spooka 
182086b377d0Spooka 	case SIMPLE_HASH('G', 'T'):
182186b377d0Spooka 		ddata->cur += 2;
182286b377d0Spooka 		if (*ddata->cur == '\0')
182386b377d0Spooka 			return (0);
182486b377d0Spooka 		switch (*ddata->cur) {
182586b377d0Spooka 		case 'n':
1826*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "non-transaction clone for "))
182786b377d0Spooka 				return (0);
1828*d678c5d4Sjoerg 			break;
182986b377d0Spooka 		case 't':
183086b377d0Spooka 		default:
1831*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "transaction clone for "))
183286b377d0Spooka 				return (0);
1833*d678c5d4Sjoerg 			break;
183486b377d0Spooka 		}
183586b377d0Spooka 		++ddata->cur;
183686b377d0Spooka 		return (cpp_demangle_read_encoding(ddata));
183786b377d0Spooka 
18384cc2045aSjoerg 	case SIMPLE_HASH('G', 'V'):
18394cc2045aSjoerg 		/* sentry object for 1 time init */
1840*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "guard variable for "))
18414cc2045aSjoerg 			return (0);
18424cc2045aSjoerg 		ddata->cur += 2;
18434cc2045aSjoerg 		break;
18444cc2045aSjoerg 
18454cc2045aSjoerg 	case SIMPLE_HASH('T', 'c'):
18464cc2045aSjoerg 		/* virtual function covariant override thunk */
1847*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata,
1848*d678c5d4Sjoerg 		    "virtual function covariant override "))
18494cc2045aSjoerg 			return (0);
18504cc2045aSjoerg 		ddata->cur += 2;
18514cc2045aSjoerg 		if (*ddata->cur == '\0')
18524cc2045aSjoerg 			return (0);
18534cc2045aSjoerg 		if (!cpp_demangle_read_offset(ddata))
18544cc2045aSjoerg 			return (0);
18554cc2045aSjoerg 		if (!cpp_demangle_read_offset(ddata))
18564cc2045aSjoerg 			return (0);
18574cc2045aSjoerg 		return (cpp_demangle_read_encoding(ddata));
18584cc2045aSjoerg 
185986b377d0Spooka 	case SIMPLE_HASH('T', 'C'):
186086b377d0Spooka 		/* construction vtable */
1861*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "construction vtable for "))
186286b377d0Spooka 			return (0);
186386b377d0Spooka 		ddata->cur += 2;
186486b377d0Spooka 		if (*ddata->cur == '\0')
186586b377d0Spooka 			return (0);
186686b377d0Spooka 		if (!cpp_demangle_read_type_flat(ddata, &type))
186786b377d0Spooka 			return (0);
186886b377d0Spooka 		rtn = 0;
186986b377d0Spooka 		if (!cpp_demangle_read_number(ddata, &offset))
187086b377d0Spooka 			goto clean3;
187186b377d0Spooka 		if (*ddata->cur++ != '_')
187286b377d0Spooka 			goto clean3;
1873*d678c5d4Sjoerg 		if (!cpp_demangle_read_type(ddata, NULL))
187486b377d0Spooka 			goto clean3;
1875*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "-in-"))
187686b377d0Spooka 			goto clean3;
1877*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, type))
187886b377d0Spooka 			goto clean3;
187986b377d0Spooka 		rtn = 1;
188086b377d0Spooka 	clean3:
188186b377d0Spooka 		free(type);
188286b377d0Spooka 		return (rtn);
188386b377d0Spooka 
18844cc2045aSjoerg 	case SIMPLE_HASH('T', 'D'):
18854cc2045aSjoerg 		/* typeinfo common proxy */
18864cc2045aSjoerg 		break;
18874cc2045aSjoerg 
188886b377d0Spooka 	case SIMPLE_HASH('T', 'F'):
188986b377d0Spooka 		/* typeinfo fn */
1890*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "typeinfo fn for "))
189186b377d0Spooka 			return (0);
189286b377d0Spooka 		ddata->cur += 2;
189386b377d0Spooka 		if (*ddata->cur == '\0')
189486b377d0Spooka 			return (0);
1895*d678c5d4Sjoerg 		return (cpp_demangle_read_type(ddata, NULL));
189686b377d0Spooka 
18974cc2045aSjoerg 	case SIMPLE_HASH('T', 'h'):
18984cc2045aSjoerg 		/* virtual function non-virtual override thunk */
1899*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata,
1900*d678c5d4Sjoerg 		    "virtual function non-virtual override "))
19014cc2045aSjoerg 			return (0);
19024cc2045aSjoerg 		ddata->cur += 2;
19034cc2045aSjoerg 		if (*ddata->cur == '\0')
19044cc2045aSjoerg 			return (0);
19054cc2045aSjoerg 		if (!cpp_demangle_read_nv_offset(ddata))
19064cc2045aSjoerg 			return (0);
19074cc2045aSjoerg 		return (cpp_demangle_read_encoding(ddata));
19084cc2045aSjoerg 
190986b377d0Spooka 	case SIMPLE_HASH('T', 'H'):
191086b377d0Spooka 		/* TLS init function */
1911*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "TLS init function for "))
19124cc2045aSjoerg 			return (0);
19134cc2045aSjoerg 		ddata->cur += 2;
19144cc2045aSjoerg 		if (*ddata->cur == '\0')
19154cc2045aSjoerg 			return (0);
191686b377d0Spooka 		break;
191786b377d0Spooka 
191886b377d0Spooka 	case SIMPLE_HASH('T', 'I'):
191986b377d0Spooka 		/* typeinfo structure */
1920*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "typeinfo for "))
192186b377d0Spooka 			return (0);
192286b377d0Spooka 		ddata->cur += 2;
192386b377d0Spooka 		if (*ddata->cur == '\0')
192486b377d0Spooka 			return (0);
1925*d678c5d4Sjoerg 		return (cpp_demangle_read_type(ddata, NULL));
192686b377d0Spooka 
192786b377d0Spooka 	case SIMPLE_HASH('T', 'J'):
192886b377d0Spooka 		/* java class */
1929*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "java Class for "))
193086b377d0Spooka 			return (0);
193186b377d0Spooka 		ddata->cur += 2;
193286b377d0Spooka 		if (*ddata->cur == '\0')
193386b377d0Spooka 			return (0);
1934*d678c5d4Sjoerg 		return (cpp_demangle_read_type(ddata, NULL));
193586b377d0Spooka 
193686b377d0Spooka 	case SIMPLE_HASH('T', 'S'):
193786b377d0Spooka 		/* RTTI name (NTBS) */
1938*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "typeinfo name for "))
193986b377d0Spooka 			return (0);
194086b377d0Spooka 		ddata->cur += 2;
194186b377d0Spooka 		if (*ddata->cur == '\0')
194286b377d0Spooka 			return (0);
1943*d678c5d4Sjoerg 		return (cpp_demangle_read_type(ddata, NULL));
19444cc2045aSjoerg 
19454cc2045aSjoerg 	case SIMPLE_HASH('T', 'T'):
19464cc2045aSjoerg 		/* VTT table */
1947*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "VTT for "))
19484cc2045aSjoerg 			return (0);
19494cc2045aSjoerg 		ddata->cur += 2;
195086b377d0Spooka 		if (*ddata->cur == '\0')
195186b377d0Spooka 			return (0);
1952*d678c5d4Sjoerg 		return (cpp_demangle_read_type(ddata, NULL));
19534cc2045aSjoerg 
19544cc2045aSjoerg 	case SIMPLE_HASH('T', 'v'):
19554cc2045aSjoerg 		/* virtual function virtual override thunk */
1956*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "virtual function virtual override "))
19574cc2045aSjoerg 			return (0);
19584cc2045aSjoerg 		ddata->cur += 2;
19594cc2045aSjoerg 		if (*ddata->cur == '\0')
19604cc2045aSjoerg 			return (0);
19614cc2045aSjoerg 		if (!cpp_demangle_read_v_offset(ddata))
19624cc2045aSjoerg 			return (0);
19634cc2045aSjoerg 		return (cpp_demangle_read_encoding(ddata));
19644cc2045aSjoerg 
19654cc2045aSjoerg 	case SIMPLE_HASH('T', 'V'):
19664cc2045aSjoerg 		/* virtual table */
1967*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "vtable for "))
19684cc2045aSjoerg 			return (0);
19694cc2045aSjoerg 		ddata->cur += 2;
19704cc2045aSjoerg 		if (*ddata->cur == '\0')
19714cc2045aSjoerg 			return (0);
1972*d678c5d4Sjoerg 		return (cpp_demangle_read_type(ddata, NULL));
197386b377d0Spooka 
197486b377d0Spooka 	case SIMPLE_HASH('T', 'W'):
197586b377d0Spooka 		/* TLS wrapper function */
1976*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "TLS wrapper function for "))
197786b377d0Spooka 			return (0);
197886b377d0Spooka 		ddata->cur += 2;
197986b377d0Spooka 		if (*ddata->cur == '\0')
198086b377d0Spooka 			return (0);
198186b377d0Spooka 		break;
1982*d678c5d4Sjoerg 	}
19834cc2045aSjoerg 
19844cc2045aSjoerg 	return (cpp_demangle_read_name(ddata));
19854cc2045aSjoerg }
19864cc2045aSjoerg 
19874cc2045aSjoerg static int
cpp_demangle_read_local_name(struct cpp_demangle_data * ddata)19884cc2045aSjoerg cpp_demangle_read_local_name(struct cpp_demangle_data *ddata)
19894cc2045aSjoerg {
1990*d678c5d4Sjoerg 	struct vector_str local_name;
1991*d678c5d4Sjoerg 	struct type_delimit td;
19924cc2045aSjoerg 	size_t limit;
1993*d678c5d4Sjoerg 	bool  more_type;
19944cc2045aSjoerg 
19954cc2045aSjoerg 	if (ddata == NULL)
19964cc2045aSjoerg 		return (0);
19974cc2045aSjoerg 	if (*(++ddata->cur) == '\0')
19984cc2045aSjoerg 		return (0);
19994cc2045aSjoerg 
2000*d678c5d4Sjoerg 	if (!vector_str_init(&local_name))
20014cc2045aSjoerg 		return (0);
2002*d678c5d4Sjoerg 	ddata->cur_output = &local_name;
2003*d678c5d4Sjoerg 
2004*d678c5d4Sjoerg 	if (!cpp_demangle_read_encoding(ddata)) {
2005*d678c5d4Sjoerg 		vector_str_dest(&local_name);
2006*d678c5d4Sjoerg 		return (0);
2007*d678c5d4Sjoerg 	}
2008*d678c5d4Sjoerg 
2009*d678c5d4Sjoerg 	ddata->cur_output = &ddata->output;
2010*d678c5d4Sjoerg 
2011*d678c5d4Sjoerg 	td.paren = false;
2012*d678c5d4Sjoerg 	td.firstp = true;
2013*d678c5d4Sjoerg 	more_type = false;
2014*d678c5d4Sjoerg 	limit = 0;
2015*d678c5d4Sjoerg 
2016*d678c5d4Sjoerg 	/*
2017*d678c5d4Sjoerg 	 * The first type is a return type if we just demangled template
2018*d678c5d4Sjoerg 	 * args. (the template args is right next to the function name,
2019*d678c5d4Sjoerg 	 * which means it's a template function)
2020*d678c5d4Sjoerg 	 */
2021*d678c5d4Sjoerg 	if (ddata->is_tmpl) {
2022*d678c5d4Sjoerg 		ddata->is_tmpl = false;
2023*d678c5d4Sjoerg 
2024*d678c5d4Sjoerg 		/* Read return type */
2025*d678c5d4Sjoerg 		if (!cpp_demangle_read_type(ddata, NULL)) {
2026*d678c5d4Sjoerg 			vector_str_dest(&local_name);
2027*d678c5d4Sjoerg 			return (0);
2028*d678c5d4Sjoerg 		}
2029*d678c5d4Sjoerg 
2030*d678c5d4Sjoerg 		more_type = true;
2031*d678c5d4Sjoerg 	}
2032*d678c5d4Sjoerg 
2033*d678c5d4Sjoerg 	/* Now we can push the name after possible return type is handled. */
2034*d678c5d4Sjoerg 	if (!vector_str_push_vector(&ddata->output, &local_name)) {
2035*d678c5d4Sjoerg 		vector_str_dest(&local_name);
2036*d678c5d4Sjoerg 		return (0);
2037*d678c5d4Sjoerg 	}
2038*d678c5d4Sjoerg 	vector_str_dest(&local_name);
2039*d678c5d4Sjoerg 
2040*d678c5d4Sjoerg 	while (*ddata->cur != '\0') {
2041*d678c5d4Sjoerg 		if (!cpp_demangle_read_type(ddata, &td))
2042*d678c5d4Sjoerg 			return (0);
2043*d678c5d4Sjoerg 		if (more_type)
2044*d678c5d4Sjoerg 			more_type = false;
20454cc2045aSjoerg 		if (*ddata->cur == 'E')
20464cc2045aSjoerg 			break;
20474cc2045aSjoerg 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
20484cc2045aSjoerg 			return (0);
20494cc2045aSjoerg 	}
2050*d678c5d4Sjoerg 	if (more_type)
2051*d678c5d4Sjoerg 		return (0);
2052*d678c5d4Sjoerg 
20534cc2045aSjoerg 	if (*(++ddata->cur) == '\0')
20544cc2045aSjoerg 		return (0);
2055*d678c5d4Sjoerg 	if (td.paren == true) {
2056*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, ")"))
20574cc2045aSjoerg 			return (0);
2058*d678c5d4Sjoerg 		td.paren = false;
20594cc2045aSjoerg 	}
20604cc2045aSjoerg 	if (*ddata->cur == 's')
20614cc2045aSjoerg 		++ddata->cur;
20624cc2045aSjoerg 	else {
2063*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "::"))
20644cc2045aSjoerg 			return (0);
20654cc2045aSjoerg 		if (!cpp_demangle_read_name(ddata))
20664cc2045aSjoerg 			return (0);
20674cc2045aSjoerg 	}
20684cc2045aSjoerg 	if (*ddata->cur == '_') {
20694cc2045aSjoerg 		++ddata->cur;
20704cc2045aSjoerg 		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
20714cc2045aSjoerg 			++ddata->cur;
20724cc2045aSjoerg 	}
20734cc2045aSjoerg 
20744cc2045aSjoerg 	return (1);
20754cc2045aSjoerg }
20764cc2045aSjoerg 
20774cc2045aSjoerg static int
cpp_demangle_read_name(struct cpp_demangle_data * ddata)20784cc2045aSjoerg cpp_demangle_read_name(struct cpp_demangle_data *ddata)
20794cc2045aSjoerg {
20804cc2045aSjoerg 	struct vector_str *output, v;
20814cc2045aSjoerg 	size_t p_idx, subst_str_len;
20824cc2045aSjoerg 	int rtn;
20834cc2045aSjoerg 	char *subst_str;
20844cc2045aSjoerg 
20854cc2045aSjoerg 	if (ddata == NULL || *ddata->cur == '\0')
20864cc2045aSjoerg 		return (0);
20874cc2045aSjoerg 
2088*d678c5d4Sjoerg 	output = ddata->cur_output;
20894cc2045aSjoerg 
20904cc2045aSjoerg 	subst_str = NULL;
20914cc2045aSjoerg 
20924cc2045aSjoerg 	switch (*ddata->cur) {
20934cc2045aSjoerg 	case 'S':
20944cc2045aSjoerg 		return (cpp_demangle_read_subst(ddata));
20954cc2045aSjoerg 	case 'N':
20964cc2045aSjoerg 		return (cpp_demangle_read_nested_name(ddata));
20974cc2045aSjoerg 	case 'Z':
20984cc2045aSjoerg 		return (cpp_demangle_read_local_name(ddata));
2099*d678c5d4Sjoerg 	}
21004cc2045aSjoerg 
21014cc2045aSjoerg 	if (!vector_str_init(&v))
21024cc2045aSjoerg 		return (0);
21034cc2045aSjoerg 
21044cc2045aSjoerg 	p_idx = output->size;
21054cc2045aSjoerg 	rtn = 0;
21064cc2045aSjoerg 	if (!cpp_demangle_read_uqname(ddata))
21074cc2045aSjoerg 		goto clean;
21084cc2045aSjoerg 	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
21094cc2045aSjoerg 	    &subst_str_len)) == NULL)
21104cc2045aSjoerg 		goto clean;
21114cc2045aSjoerg 	if (subst_str_len > 8 && strstr(subst_str, "operator") != NULL) {
21124cc2045aSjoerg 		rtn = 1;
21134cc2045aSjoerg 		goto clean;
21144cc2045aSjoerg 	}
21154cc2045aSjoerg 	if (!vector_str_push(&v, subst_str, subst_str_len))
21164cc2045aSjoerg 		goto clean;
21174cc2045aSjoerg 	if (!cpp_demangle_push_subst_v(ddata, &v))
21184cc2045aSjoerg 		goto clean;
21194cc2045aSjoerg 
21204cc2045aSjoerg 	if (*ddata->cur == 'I') {
21214cc2045aSjoerg 		p_idx = output->size;
21224cc2045aSjoerg 		if (!cpp_demangle_read_tmpl_args(ddata))
21234cc2045aSjoerg 			goto clean;
21244cc2045aSjoerg 		free(subst_str);
21254cc2045aSjoerg 		if ((subst_str = vector_str_substr(output, p_idx,
21264cc2045aSjoerg 		    output->size - 1, &subst_str_len)) == NULL)
21274cc2045aSjoerg 			goto clean;
21284cc2045aSjoerg 		if (!vector_str_push(&v, subst_str, subst_str_len))
21294cc2045aSjoerg 			goto clean;
21304cc2045aSjoerg 		if (!cpp_demangle_push_subst_v(ddata, &v))
21314cc2045aSjoerg 			goto clean;
21324cc2045aSjoerg 	}
21334cc2045aSjoerg 
21344cc2045aSjoerg 	rtn = 1;
21354cc2045aSjoerg 
21364cc2045aSjoerg clean:
21374cc2045aSjoerg 	free(subst_str);
21384cc2045aSjoerg 	vector_str_dest(&v);
21394cc2045aSjoerg 
21404cc2045aSjoerg 	return (rtn);
21414cc2045aSjoerg }
21424cc2045aSjoerg 
21434cc2045aSjoerg static int
cpp_demangle_read_name_flat(struct cpp_demangle_data * ddata,char ** str)214486b377d0Spooka cpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str)
214586b377d0Spooka {
214686b377d0Spooka 	struct vector_str *output;
214786b377d0Spooka 	size_t i, p_idx, idx, name_len;
214886b377d0Spooka 	char *name;
214986b377d0Spooka 
2150*d678c5d4Sjoerg 	output = ddata->cur_output;
215186b377d0Spooka 
215286b377d0Spooka 	p_idx = output->size;
215386b377d0Spooka 
215486b377d0Spooka 	if (!cpp_demangle_read_name(ddata))
215586b377d0Spooka 		return (0);
215686b377d0Spooka 
215786b377d0Spooka 	if ((name = vector_str_substr(output, p_idx, output->size - 1,
215886b377d0Spooka 	    &name_len)) == NULL)
215986b377d0Spooka 		return (0);
216086b377d0Spooka 
216186b377d0Spooka 	idx = output->size;
216286b377d0Spooka 	for (i = p_idx; i < idx; ++i) {
216386b377d0Spooka 		if (!vector_str_pop(output)) {
216486b377d0Spooka 			free(name);
216586b377d0Spooka 			return (0);
216686b377d0Spooka 		}
216786b377d0Spooka 	}
216886b377d0Spooka 
216986b377d0Spooka 	*str = name;
217086b377d0Spooka 
217186b377d0Spooka 	return (1);
217286b377d0Spooka }
217386b377d0Spooka 
217486b377d0Spooka static int
cpp_demangle_read_nested_name(struct cpp_demangle_data * ddata)21754cc2045aSjoerg cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
21764cc2045aSjoerg {
21774cc2045aSjoerg 	struct vector_str *output, v;
21784cc2045aSjoerg 	size_t limit, p_idx, subst_str_len;
21794cc2045aSjoerg 	int rtn;
21804cc2045aSjoerg 	char *subst_str;
21814cc2045aSjoerg 
21824cc2045aSjoerg 	if (ddata == NULL || *ddata->cur != 'N')
21834cc2045aSjoerg 		return (0);
21844cc2045aSjoerg 	if (*(++ddata->cur) == '\0')
21854cc2045aSjoerg 		return (0);
21864cc2045aSjoerg 
2187*d678c5d4Sjoerg 	do {
21884cc2045aSjoerg 		switch (*ddata->cur) {
21894cc2045aSjoerg 		case 'r':
21904cc2045aSjoerg 			ddata->mem_rst = true;
21914cc2045aSjoerg 			break;
21924cc2045aSjoerg 		case 'V':
21934cc2045aSjoerg 			ddata->mem_vat = true;
21944cc2045aSjoerg 			break;
21954cc2045aSjoerg 		case 'K':
21964cc2045aSjoerg 			ddata->mem_cst = true;
21974cc2045aSjoerg 			break;
2198*d678c5d4Sjoerg 		case 'R':
2199*d678c5d4Sjoerg 			ddata->mem_ref = true;
2200*d678c5d4Sjoerg 			break;
2201*d678c5d4Sjoerg 		case 'O':
2202*d678c5d4Sjoerg 			ddata->mem_rref = true;
2203*d678c5d4Sjoerg 			break;
2204*d678c5d4Sjoerg 		default:
2205*d678c5d4Sjoerg 			goto next;
22064cc2045aSjoerg 		}
2207*d678c5d4Sjoerg 	} while (*(++ddata->cur));
22084cc2045aSjoerg 
2209*d678c5d4Sjoerg next:
2210*d678c5d4Sjoerg 	output = ddata->cur_output;
22114cc2045aSjoerg 	if (!vector_str_init(&v))
22124cc2045aSjoerg 		return (0);
22134cc2045aSjoerg 
22144cc2045aSjoerg 	rtn = 0;
22154cc2045aSjoerg 	limit = 0;
22164cc2045aSjoerg 	for (;;) {
22174cc2045aSjoerg 		p_idx = output->size;
22184cc2045aSjoerg 		switch (*ddata->cur) {
22194cc2045aSjoerg 		case 'I':
22204cc2045aSjoerg 			if (!cpp_demangle_read_tmpl_args(ddata))
22214cc2045aSjoerg 				goto clean;
22224cc2045aSjoerg 			break;
22234cc2045aSjoerg 		case 'S':
22244cc2045aSjoerg 			if (!cpp_demangle_read_subst(ddata))
22254cc2045aSjoerg 				goto clean;
22264cc2045aSjoerg 			break;
22274cc2045aSjoerg 		case 'T':
22284cc2045aSjoerg 			if (!cpp_demangle_read_tmpl_param(ddata))
22294cc2045aSjoerg 				goto clean;
22304cc2045aSjoerg 			break;
22314cc2045aSjoerg 		default:
22324cc2045aSjoerg 			if (!cpp_demangle_read_uqname(ddata))
22334cc2045aSjoerg 				goto clean;
2234*d678c5d4Sjoerg 		}
22354cc2045aSjoerg 
2236*d678c5d4Sjoerg 		if (p_idx == output->size)
2237*d678c5d4Sjoerg 			goto next_comp;
22384cc2045aSjoerg 		if ((subst_str = vector_str_substr(output, p_idx,
22394cc2045aSjoerg 		    output->size - 1, &subst_str_len)) == NULL)
22404cc2045aSjoerg 			goto clean;
22414cc2045aSjoerg 		if (!vector_str_push(&v, subst_str, subst_str_len)) {
22424cc2045aSjoerg 			free(subst_str);
22434cc2045aSjoerg 			goto clean;
22444cc2045aSjoerg 		}
22454cc2045aSjoerg 		free(subst_str);
22464cc2045aSjoerg 
22474cc2045aSjoerg 		if (!cpp_demangle_push_subst_v(ddata, &v))
22484cc2045aSjoerg 			goto clean;
2249*d678c5d4Sjoerg 
2250*d678c5d4Sjoerg 	next_comp:
22514cc2045aSjoerg 		if (*ddata->cur == 'E')
22524cc2045aSjoerg 			break;
2253*d678c5d4Sjoerg 		else if (*ddata->cur != 'I' && *ddata->cur != 'C' &&
2254*d678c5d4Sjoerg 		    *ddata->cur != 'D' && p_idx != output->size) {
2255*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "::"))
22564cc2045aSjoerg 				goto clean;
2257*d678c5d4Sjoerg 			if (!VEC_PUSH_STR(&v, "::"))
22584cc2045aSjoerg 				goto clean;
22594cc2045aSjoerg 		}
22604cc2045aSjoerg 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
22614cc2045aSjoerg 			goto clean;
22624cc2045aSjoerg 	}
22634cc2045aSjoerg 
22644cc2045aSjoerg 	++ddata->cur;
22654cc2045aSjoerg 	rtn = 1;
22664cc2045aSjoerg 
22674cc2045aSjoerg clean:
22684cc2045aSjoerg 	vector_str_dest(&v);
22694cc2045aSjoerg 
22704cc2045aSjoerg 	return (rtn);
22714cc2045aSjoerg }
22724cc2045aSjoerg 
22734cc2045aSjoerg /*
22744cc2045aSjoerg  * read number
22754cc2045aSjoerg  * number ::= [n] <decimal>
22764cc2045aSjoerg  */
22774cc2045aSjoerg static int
cpp_demangle_read_number(struct cpp_demangle_data * ddata,long * rtn)22784cc2045aSjoerg cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
22794cc2045aSjoerg {
22804cc2045aSjoerg 	long len, negative_factor;
22814cc2045aSjoerg 
22824cc2045aSjoerg 	if (ddata == NULL || rtn == NULL)
22834cc2045aSjoerg 		return (0);
22844cc2045aSjoerg 
22854cc2045aSjoerg 	negative_factor = 1;
22864cc2045aSjoerg 	if (*ddata->cur == 'n') {
22874cc2045aSjoerg 		negative_factor = -1;
22884cc2045aSjoerg 
22894cc2045aSjoerg 		++ddata->cur;
22904cc2045aSjoerg 	}
22914cc2045aSjoerg 	if (ELFTC_ISDIGIT(*ddata->cur) == 0)
22924cc2045aSjoerg 		return (0);
22934cc2045aSjoerg 
22944cc2045aSjoerg 	errno = 0;
22954cc2045aSjoerg 	if ((len = strtol(ddata->cur, (char **) NULL, 10)) == 0 &&
22964cc2045aSjoerg 	    errno != 0)
22974cc2045aSjoerg 		return (0);
22984cc2045aSjoerg 
22994cc2045aSjoerg 	while (ELFTC_ISDIGIT(*ddata->cur) != 0)
23004cc2045aSjoerg 		++ddata->cur;
23014cc2045aSjoerg 
23024cc2045aSjoerg 	assert(len >= 0);
23034cc2045aSjoerg 	assert(negative_factor == 1 || negative_factor == -1);
23044cc2045aSjoerg 
23054cc2045aSjoerg 	*rtn = len * negative_factor;
23064cc2045aSjoerg 
23074cc2045aSjoerg 	return (1);
23084cc2045aSjoerg }
23094cc2045aSjoerg 
23104cc2045aSjoerg static int
cpp_demangle_read_number_as_string(struct cpp_demangle_data * ddata,char ** str)231186b377d0Spooka cpp_demangle_read_number_as_string(struct cpp_demangle_data *ddata, char **str)
231286b377d0Spooka {
231386b377d0Spooka 	long n;
231486b377d0Spooka 
231586b377d0Spooka 	if (!cpp_demangle_read_number(ddata, &n)) {
231686b377d0Spooka 		*str = NULL;
231786b377d0Spooka 		return (0);
231886b377d0Spooka 	}
231986b377d0Spooka 
232086b377d0Spooka 	if (asprintf(str, "%ld", n) < 0) {
232186b377d0Spooka 		*str = NULL;
232286b377d0Spooka 		return (0);
232386b377d0Spooka 	}
232486b377d0Spooka 
232586b377d0Spooka 	return (1);
232686b377d0Spooka }
232786b377d0Spooka 
232886b377d0Spooka static int
cpp_demangle_read_nv_offset(struct cpp_demangle_data * ddata)23294cc2045aSjoerg cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
23304cc2045aSjoerg {
23314cc2045aSjoerg 
23324cc2045aSjoerg 	if (ddata == NULL)
23334cc2045aSjoerg 		return (0);
23344cc2045aSjoerg 
2335*d678c5d4Sjoerg 	if (!DEM_PUSH_STR(ddata, "offset : "))
23364cc2045aSjoerg 		return (0);
23374cc2045aSjoerg 
23384cc2045aSjoerg 	return (cpp_demangle_read_offset_number(ddata));
23394cc2045aSjoerg }
23404cc2045aSjoerg 
23414cc2045aSjoerg /* read offset, offset are nv-offset, v-offset */
23424cc2045aSjoerg static int
cpp_demangle_read_offset(struct cpp_demangle_data * ddata)23434cc2045aSjoerg cpp_demangle_read_offset(struct cpp_demangle_data *ddata)
23444cc2045aSjoerg {
23454cc2045aSjoerg 
23464cc2045aSjoerg 	if (ddata == NULL)
23474cc2045aSjoerg 		return (0);
23484cc2045aSjoerg 
23494cc2045aSjoerg 	if (*ddata->cur == 'h') {
23504cc2045aSjoerg 		++ddata->cur;
23514cc2045aSjoerg 		return (cpp_demangle_read_nv_offset(ddata));
23524cc2045aSjoerg 	} else if (*ddata->cur == 'v') {
23534cc2045aSjoerg 		++ddata->cur;
23544cc2045aSjoerg 		return (cpp_demangle_read_v_offset(ddata));
23554cc2045aSjoerg 	}
23564cc2045aSjoerg 
23574cc2045aSjoerg 	return (0);
23584cc2045aSjoerg }
23594cc2045aSjoerg 
23604cc2045aSjoerg static int
cpp_demangle_read_offset_number(struct cpp_demangle_data * ddata)23614cc2045aSjoerg cpp_demangle_read_offset_number(struct cpp_demangle_data *ddata)
23624cc2045aSjoerg {
23634cc2045aSjoerg 	bool negative;
23644cc2045aSjoerg 	const char *start;
23654cc2045aSjoerg 
23664cc2045aSjoerg 	if (ddata == NULL || *ddata->cur == '\0')
23674cc2045aSjoerg 		return (0);
23684cc2045aSjoerg 
23694cc2045aSjoerg 	/* offset could be negative */
23704cc2045aSjoerg 	if (*ddata->cur == 'n') {
23714cc2045aSjoerg 		negative = true;
23724cc2045aSjoerg 		start = ddata->cur + 1;
23734cc2045aSjoerg 	} else {
23744cc2045aSjoerg 		negative = false;
23754cc2045aSjoerg 		start = ddata->cur;
23764cc2045aSjoerg 	}
23774cc2045aSjoerg 
23784cc2045aSjoerg 	while (*ddata->cur != '_')
23794cc2045aSjoerg 		++ddata->cur;
23804cc2045aSjoerg 
2381*d678c5d4Sjoerg 	if (negative && !DEM_PUSH_STR(ddata, "-"))
23824cc2045aSjoerg 		return (0);
23834cc2045aSjoerg 
23844cc2045aSjoerg 	assert(start != NULL);
23854cc2045aSjoerg 
23864cc2045aSjoerg 	if (!cpp_demangle_push_str(ddata, start, ddata->cur - start))
23874cc2045aSjoerg 		return (0);
2388*d678c5d4Sjoerg 	if (!DEM_PUSH_STR(ddata, " "))
23894cc2045aSjoerg 		return (0);
23904cc2045aSjoerg 
23914cc2045aSjoerg 	++ddata->cur;
23924cc2045aSjoerg 
23934cc2045aSjoerg 	return (1);
23944cc2045aSjoerg }
23954cc2045aSjoerg 
23964cc2045aSjoerg static int
cpp_demangle_read_pointer_to_member(struct cpp_demangle_data * ddata,struct vector_type_qualifier * v)2397*d678c5d4Sjoerg cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata,
2398*d678c5d4Sjoerg     struct vector_type_qualifier *v)
23994cc2045aSjoerg {
24004cc2045aSjoerg 	size_t class_type_len, i, idx, p_idx;
24014cc2045aSjoerg 	int p_func_type, rtn;
24024cc2045aSjoerg 	char *class_type;
24034cc2045aSjoerg 
24044cc2045aSjoerg 	if (ddata == NULL || *ddata->cur != 'M' || *(++ddata->cur) == '\0')
24054cc2045aSjoerg 		return (0);
24064cc2045aSjoerg 
24074cc2045aSjoerg 	p_idx = ddata->output.size;
2408*d678c5d4Sjoerg 	if (!cpp_demangle_read_type(ddata, NULL))
24094cc2045aSjoerg 		return (0);
24104cc2045aSjoerg 
24114cc2045aSjoerg 	if ((class_type = vector_str_substr(&ddata->output, p_idx,
24124cc2045aSjoerg 	    ddata->output.size - 1, &class_type_len)) == NULL)
24134cc2045aSjoerg 		return (0);
24144cc2045aSjoerg 
24154cc2045aSjoerg 	rtn = 0;
24164cc2045aSjoerg 	idx = ddata->output.size;
24174cc2045aSjoerg 	for (i = p_idx; i < idx; ++i)
24184cc2045aSjoerg 		if (!vector_str_pop(&ddata->output))
24194cc2045aSjoerg 			goto clean1;
24204cc2045aSjoerg 
2421*d678c5d4Sjoerg 	if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM, v))
24224cc2045aSjoerg 		goto clean1;
24234cc2045aSjoerg 
24244cc2045aSjoerg 	if (!vector_str_push(&ddata->class_type, class_type, class_type_len))
24254cc2045aSjoerg 		goto clean2;
24264cc2045aSjoerg 
24274cc2045aSjoerg 	p_func_type = ddata->func_type;
2428*d678c5d4Sjoerg 	if (!cpp_demangle_read_type(ddata, NULL))
24294cc2045aSjoerg 		goto clean3;
24304cc2045aSjoerg 
24314cc2045aSjoerg 	if (p_func_type == ddata->func_type) {
2432*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, " "))
24334cc2045aSjoerg 			goto clean3;
24344cc2045aSjoerg 		if (!cpp_demangle_push_str(ddata, class_type, class_type_len))
24354cc2045aSjoerg 			goto clean3;
2436*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "::*"))
24374cc2045aSjoerg 			goto clean3;
24384cc2045aSjoerg 	}
24394cc2045aSjoerg 
24404cc2045aSjoerg 	rtn = 1;
24414cc2045aSjoerg clean3:
24424cc2045aSjoerg 	if (!vector_str_pop(&ddata->class_type))
24434cc2045aSjoerg 		rtn = 0;
24444cc2045aSjoerg clean2:
24454cc2045aSjoerg 	if (!vector_read_cmd_pop(&ddata->cmd))
24464cc2045aSjoerg 		rtn = 0;
24474cc2045aSjoerg clean1:
24484cc2045aSjoerg 	free(class_type);
24494cc2045aSjoerg 
2450*d678c5d4Sjoerg 	vector_type_qualifier_dest(v);
2451*d678c5d4Sjoerg 	if (!vector_type_qualifier_init(v))
2452*d678c5d4Sjoerg 		return (0);
2453*d678c5d4Sjoerg 
24544cc2045aSjoerg 	return (rtn);
24554cc2045aSjoerg }
24564cc2045aSjoerg 
24574cc2045aSjoerg /* read source-name, source-name is <len> <ID> */
24584cc2045aSjoerg static int
cpp_demangle_read_sname(struct cpp_demangle_data * ddata)24594cc2045aSjoerg cpp_demangle_read_sname(struct cpp_demangle_data *ddata)
24604cc2045aSjoerg {
24614cc2045aSjoerg 	long len;
24625192b81bSjoerg 	int err;
24634cc2045aSjoerg 
24644cc2045aSjoerg 	if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
24655192b81bSjoerg 	    len <= 0)
24665192b81bSjoerg 		return (0);
24675192b81bSjoerg 
24685192b81bSjoerg 	if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0))
2469*d678c5d4Sjoerg 		err = DEM_PUSH_STR(ddata, "(anonymous namespace)");
24705192b81bSjoerg 	else
24715192b81bSjoerg 		err = cpp_demangle_push_str(ddata, ddata->cur, len);
24725192b81bSjoerg 
24735192b81bSjoerg 	if (err == 0)
24744cc2045aSjoerg 		return (0);
24754cc2045aSjoerg 
2476*d678c5d4Sjoerg 	assert(ddata->cur_output->size > 0);
2477*d678c5d4Sjoerg 	if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == NULL)
24784cc2045aSjoerg 		ddata->last_sname =
2479*d678c5d4Sjoerg 		    ddata->cur_output->container[ddata->output.size - 1];
24804cc2045aSjoerg 
24814cc2045aSjoerg 	ddata->cur += len;
24824cc2045aSjoerg 
24834cc2045aSjoerg 	return (1);
24844cc2045aSjoerg }
24854cc2045aSjoerg 
24864cc2045aSjoerg static int
cpp_demangle_read_subst(struct cpp_demangle_data * ddata)24874cc2045aSjoerg cpp_demangle_read_subst(struct cpp_demangle_data *ddata)
24884cc2045aSjoerg {
24894cc2045aSjoerg 	long nth;
24904cc2045aSjoerg 
24914cc2045aSjoerg 	if (ddata == NULL || *ddata->cur == '\0')
24924cc2045aSjoerg 		return (0);
24934cc2045aSjoerg 
24944cc2045aSjoerg 	/* abbreviations of the form Sx */
24954cc2045aSjoerg 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
24964cc2045aSjoerg 	case SIMPLE_HASH('S', 'a'):
24974cc2045aSjoerg 		/* std::allocator */
2498*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "std::allocator"))
24994cc2045aSjoerg 			return (0);
25004cc2045aSjoerg 		ddata->cur += 2;
25014cc2045aSjoerg 		if (*ddata->cur == 'I')
25024cc2045aSjoerg 			return (cpp_demangle_read_subst_stdtmpl(ddata,
2503*d678c5d4Sjoerg 			    "std::allocator"));
25044cc2045aSjoerg 		return (1);
25054cc2045aSjoerg 
25064cc2045aSjoerg 	case SIMPLE_HASH('S', 'b'):
25074cc2045aSjoerg 		/* std::basic_string */
2508*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "std::basic_string"))
25094cc2045aSjoerg 			return (0);
25104cc2045aSjoerg 		ddata->cur += 2;
25114cc2045aSjoerg 		if (*ddata->cur == 'I')
25124cc2045aSjoerg 			return (cpp_demangle_read_subst_stdtmpl(ddata,
2513*d678c5d4Sjoerg 			    "std::basic_string"));
25144cc2045aSjoerg 		return (1);
25154cc2045aSjoerg 
25164cc2045aSjoerg 	case SIMPLE_HASH('S', 'd'):
25174cc2045aSjoerg 		/* std::basic_iostream<char, std::char_traits<char> > */
2518*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "std::basic_iostream<char, "
2519*d678c5d4Sjoerg 		    "std::char_traits<char> >"))
25204cc2045aSjoerg 			return (0);
2521*d678c5d4Sjoerg 		ddata->last_sname = "basic_iostream";
25224cc2045aSjoerg 		ddata->cur += 2;
25234cc2045aSjoerg 		if (*ddata->cur == 'I')
25244cc2045aSjoerg 			return (cpp_demangle_read_subst_stdtmpl(ddata,
2525*d678c5d4Sjoerg 			    "std::basic_iostream<char, std::char_traits"
2526*d678c5d4Sjoerg 				"<char> >"));
25274cc2045aSjoerg 		return (1);
25284cc2045aSjoerg 
25294cc2045aSjoerg 	case SIMPLE_HASH('S', 'i'):
25304cc2045aSjoerg 		/* std::basic_istream<char, std::char_traits<char> > */
2531*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "std::basic_istream<char, "
2532*d678c5d4Sjoerg 		    "std::char_traits<char> >"))
25334cc2045aSjoerg 			return (0);
2534*d678c5d4Sjoerg 		ddata->last_sname = "basic_istream";
25354cc2045aSjoerg 		ddata->cur += 2;
25364cc2045aSjoerg 		if (*ddata->cur == 'I')
25374cc2045aSjoerg 			return (cpp_demangle_read_subst_stdtmpl(ddata,
2538*d678c5d4Sjoerg 			    "std::basic_istream<char, std::char_traits"
2539*d678c5d4Sjoerg 				"<char> >"));
25404cc2045aSjoerg 		return (1);
25414cc2045aSjoerg 
25424cc2045aSjoerg 	case SIMPLE_HASH('S', 'o'):
25434cc2045aSjoerg 		/* std::basic_ostream<char, std::char_traits<char> > */
2544*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "std::basic_ostream<char, "
2545*d678c5d4Sjoerg 		    "std::char_traits<char> >"))
25464cc2045aSjoerg 			return (0);
2547*d678c5d4Sjoerg 		ddata->last_sname = "basic_ostream";
25484cc2045aSjoerg 		ddata->cur += 2;
25494cc2045aSjoerg 		if (*ddata->cur == 'I')
25504cc2045aSjoerg 			return (cpp_demangle_read_subst_stdtmpl(ddata,
2551*d678c5d4Sjoerg 			    "std::basic_ostream<char, std::char_traits"
2552*d678c5d4Sjoerg 				"<char> >"));
25534cc2045aSjoerg 		return (1);
25544cc2045aSjoerg 
25554cc2045aSjoerg 	case SIMPLE_HASH('S', 's'):
25564cc2045aSjoerg 		/*
25574cc2045aSjoerg 		 * std::basic_string<char, std::char_traits<char>,
25584cc2045aSjoerg 		 * std::allocator<char> >
25594cc2045aSjoerg 		 *
25604cc2045aSjoerg 		 * a.k.a std::string
25614cc2045aSjoerg 		 */
2562*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "std::basic_string<char, "
2563*d678c5d4Sjoerg 		    "std::char_traits<char>, std::allocator<char> >"))
25644cc2045aSjoerg 			return (0);
25654cc2045aSjoerg 		ddata->last_sname = "string";
25664cc2045aSjoerg 		ddata->cur += 2;
25674cc2045aSjoerg 		if (*ddata->cur == 'I')
25684cc2045aSjoerg 			return (cpp_demangle_read_subst_stdtmpl(ddata,
2569*d678c5d4Sjoerg 			    "std::basic_string<char, std::char_traits<char>,"
2570*d678c5d4Sjoerg 				" std::allocator<char> >"));
25714cc2045aSjoerg 		return (1);
25724cc2045aSjoerg 
25734cc2045aSjoerg 	case SIMPLE_HASH('S', 't'):
25744cc2045aSjoerg 		/* std:: */
25754cc2045aSjoerg 		return (cpp_demangle_read_subst_std(ddata));
2576*d678c5d4Sjoerg 	}
25774cc2045aSjoerg 
25784cc2045aSjoerg 	if (*(++ddata->cur) == '\0')
25794cc2045aSjoerg 		return (0);
25804cc2045aSjoerg 
2581*d678c5d4Sjoerg 	/* Skip unknown substitution abbreviations. */
2582*d678c5d4Sjoerg 	if (!(*ddata->cur >= '0' && *ddata->cur <= '9') &&
2583*d678c5d4Sjoerg 	    !(*ddata->cur >= 'A' && *ddata->cur <= 'Z') &&
2584*d678c5d4Sjoerg 	    *ddata->cur != '_') {
2585*d678c5d4Sjoerg 		++ddata->cur;
2586*d678c5d4Sjoerg 		return (1);
2587*d678c5d4Sjoerg 	}
2588*d678c5d4Sjoerg 
25894cc2045aSjoerg 	/* substitution */
25904cc2045aSjoerg 	if (*ddata->cur == '_')
25914cc2045aSjoerg 		return (cpp_demangle_get_subst(ddata, 0));
25924cc2045aSjoerg 	else {
25934cc2045aSjoerg 		errno = 0;
25944cc2045aSjoerg 		/* substitution number is base 36 */
25954cc2045aSjoerg 		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
25964cc2045aSjoerg 		    errno != 0)
25974cc2045aSjoerg 			return (0);
25984cc2045aSjoerg 
25994cc2045aSjoerg 		/* first was '_', so increase one */
26004cc2045aSjoerg 		++nth;
26014cc2045aSjoerg 
26024cc2045aSjoerg 		while (*ddata->cur != '_')
26034cc2045aSjoerg 			++ddata->cur;
26044cc2045aSjoerg 
26054cc2045aSjoerg 		assert(nth > 0);
26064cc2045aSjoerg 
26074cc2045aSjoerg 		return (cpp_demangle_get_subst(ddata, nth));
26084cc2045aSjoerg 	}
26094cc2045aSjoerg 
26104cc2045aSjoerg 	/* NOTREACHED */
26114cc2045aSjoerg 	return (0);
26124cc2045aSjoerg }
26134cc2045aSjoerg 
26144cc2045aSjoerg static int
cpp_demangle_read_subst_std(struct cpp_demangle_data * ddata)26154cc2045aSjoerg cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
26164cc2045aSjoerg {
26174cc2045aSjoerg 	struct vector_str *output, v;
26184cc2045aSjoerg 	size_t p_idx, subst_str_len;
26194cc2045aSjoerg 	int rtn;
26204cc2045aSjoerg 	char *subst_str;
26214cc2045aSjoerg 
26224cc2045aSjoerg 	if (ddata == NULL)
26234cc2045aSjoerg 		return (0);
26244cc2045aSjoerg 
26254cc2045aSjoerg 	if (!vector_str_init(&v))
26264cc2045aSjoerg 		return (0);
26274cc2045aSjoerg 
26284cc2045aSjoerg 	subst_str = NULL;
26294cc2045aSjoerg 	rtn = 0;
2630*d678c5d4Sjoerg 	if (!DEM_PUSH_STR(ddata, "std::"))
26314cc2045aSjoerg 		goto clean;
26324cc2045aSjoerg 
2633*d678c5d4Sjoerg 	if (!VEC_PUSH_STR(&v, "std::"))
26344cc2045aSjoerg 		goto clean;
26354cc2045aSjoerg 
26364cc2045aSjoerg 	ddata->cur += 2;
26374cc2045aSjoerg 
2638*d678c5d4Sjoerg 	output = ddata->cur_output;
26394cc2045aSjoerg 
26404cc2045aSjoerg 	p_idx = output->size;
26414cc2045aSjoerg 	if (!cpp_demangle_read_uqname(ddata))
26424cc2045aSjoerg 		goto clean;
26434cc2045aSjoerg 
26444cc2045aSjoerg 	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
26454cc2045aSjoerg 	    &subst_str_len)) == NULL)
26464cc2045aSjoerg 		goto clean;
26474cc2045aSjoerg 
26484cc2045aSjoerg 	if (!vector_str_push(&v, subst_str, subst_str_len))
26494cc2045aSjoerg 		goto clean;
26504cc2045aSjoerg 
26514cc2045aSjoerg 	if (!cpp_demangle_push_subst_v(ddata, &v))
26524cc2045aSjoerg 		goto clean;
26534cc2045aSjoerg 
26544cc2045aSjoerg 	if (*ddata->cur == 'I') {
26554cc2045aSjoerg 		p_idx = output->size;
26564cc2045aSjoerg 		if (!cpp_demangle_read_tmpl_args(ddata))
26574cc2045aSjoerg 			goto clean;
26584cc2045aSjoerg 		free(subst_str);
26594cc2045aSjoerg 		if ((subst_str = vector_str_substr(output, p_idx,
26604cc2045aSjoerg 		    output->size - 1, &subst_str_len)) == NULL)
26614cc2045aSjoerg 			goto clean;
26624cc2045aSjoerg 		if (!vector_str_push(&v, subst_str, subst_str_len))
26634cc2045aSjoerg 			goto clean;
26644cc2045aSjoerg 		if (!cpp_demangle_push_subst_v(ddata, &v))
26654cc2045aSjoerg 			goto clean;
26664cc2045aSjoerg 	}
26674cc2045aSjoerg 
26684cc2045aSjoerg 	rtn = 1;
26694cc2045aSjoerg clean:
26704cc2045aSjoerg 	free(subst_str);
26714cc2045aSjoerg 	vector_str_dest(&v);
26724cc2045aSjoerg 
26735192b81bSjoerg 	return (rtn);
26744cc2045aSjoerg }
26754cc2045aSjoerg 
26764cc2045aSjoerg static int
cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data * ddata,const char * str)26774cc2045aSjoerg cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
2678*d678c5d4Sjoerg     const char *str)
26794cc2045aSjoerg {
26804cc2045aSjoerg 	struct vector_str *output;
2681*d678c5d4Sjoerg 	size_t p_idx, substr_len, len;
26824cc2045aSjoerg 	int rtn;
26834cc2045aSjoerg 	char *subst_str, *substr;
26844cc2045aSjoerg 
2685*d678c5d4Sjoerg 	if (ddata == NULL || str == NULL)
26864cc2045aSjoerg 		return (0);
26874cc2045aSjoerg 
2688*d678c5d4Sjoerg 	if ((len = strlen(str)) == 0)
2689*d678c5d4Sjoerg 		return (0);
2690*d678c5d4Sjoerg 
2691*d678c5d4Sjoerg 	output = ddata->cur_output;
26924cc2045aSjoerg 
26934cc2045aSjoerg 	p_idx = output->size;
26944cc2045aSjoerg 	substr = NULL;
26954cc2045aSjoerg 	subst_str = NULL;
26964cc2045aSjoerg 
26974cc2045aSjoerg 	if (!cpp_demangle_read_tmpl_args(ddata))
26984cc2045aSjoerg 		return (0);
26994cc2045aSjoerg 	if ((substr = vector_str_substr(output, p_idx, output->size - 1,
27004cc2045aSjoerg 	    &substr_len)) == NULL)
27014cc2045aSjoerg 		return (0);
27024cc2045aSjoerg 
27034cc2045aSjoerg 	rtn = 0;
27044cc2045aSjoerg 	if ((subst_str = malloc(sizeof(char) * (substr_len + len + 1))) ==
27054cc2045aSjoerg 	    NULL)
27064cc2045aSjoerg 		goto clean;
27074cc2045aSjoerg 
27084cc2045aSjoerg 	memcpy(subst_str, str, len);
27094cc2045aSjoerg 	memcpy(subst_str + len, substr, substr_len);
27104cc2045aSjoerg 	subst_str[substr_len + len] = '\0';
27114cc2045aSjoerg 
27124cc2045aSjoerg 	if (!cpp_demangle_push_subst(ddata, subst_str, substr_len + len))
27134cc2045aSjoerg 		goto clean;
27144cc2045aSjoerg 
27154cc2045aSjoerg 	rtn = 1;
27164cc2045aSjoerg clean:
27174cc2045aSjoerg 	free(subst_str);
27184cc2045aSjoerg 	free(substr);
27194cc2045aSjoerg 
27204cc2045aSjoerg 	return (rtn);
27214cc2045aSjoerg }
27224cc2045aSjoerg 
27234cc2045aSjoerg static int
cpp_demangle_read_tmpl_arg(struct cpp_demangle_data * ddata)27244cc2045aSjoerg cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *ddata)
27254cc2045aSjoerg {
27264cc2045aSjoerg 
27274cc2045aSjoerg 	if (ddata == NULL || *ddata->cur == '\0')
27284cc2045aSjoerg 		return (0);
27294cc2045aSjoerg 
27304cc2045aSjoerg 	switch (*ddata->cur) {
27314cc2045aSjoerg 	case 'L':
27324cc2045aSjoerg 		return (cpp_demangle_read_expr_primary(ddata));
27334cc2045aSjoerg 	case 'X':
2734*d678c5d4Sjoerg 		++ddata->cur;
2735*d678c5d4Sjoerg 		if (!cpp_demangle_read_expression(ddata))
2736*d678c5d4Sjoerg 			return (0);
2737*d678c5d4Sjoerg 		return (*ddata->cur++ == 'E');
2738*d678c5d4Sjoerg 	}
27394cc2045aSjoerg 
2740*d678c5d4Sjoerg 	return (cpp_demangle_read_type(ddata, NULL));
27414cc2045aSjoerg }
27424cc2045aSjoerg 
27434cc2045aSjoerg static int
cpp_demangle_read_tmpl_args(struct cpp_demangle_data * ddata)27444cc2045aSjoerg cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
27454cc2045aSjoerg {
27464cc2045aSjoerg 	struct vector_str *v;
27474cc2045aSjoerg 	size_t arg_len, idx, limit, size;
27484cc2045aSjoerg 	char *arg;
27494cc2045aSjoerg 
27504cc2045aSjoerg 	if (ddata == NULL || *ddata->cur == '\0')
27514cc2045aSjoerg 		return (0);
27524cc2045aSjoerg 
27534cc2045aSjoerg 	++ddata->cur;
27544cc2045aSjoerg 
2755*d678c5d4Sjoerg 	if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL, NULL))
27564cc2045aSjoerg 		return (0);
27574cc2045aSjoerg 
2758*d678c5d4Sjoerg 	if (!DEM_PUSH_STR(ddata, "<"))
27594cc2045aSjoerg 		return (0);
27604cc2045aSjoerg 
27614cc2045aSjoerg 	limit = 0;
2762*d678c5d4Sjoerg 	v = ddata->cur_output;
27634cc2045aSjoerg 	for (;;) {
27644cc2045aSjoerg 		idx = v->size;
27654cc2045aSjoerg 		if (!cpp_demangle_read_tmpl_arg(ddata))
27664cc2045aSjoerg 			return (0);
27674cc2045aSjoerg 		if ((arg = vector_str_substr(v, idx, v->size - 1, &arg_len)) ==
27684cc2045aSjoerg 		    NULL)
27694cc2045aSjoerg 			return (0);
27704cc2045aSjoerg 		if (!vector_str_find(&ddata->tmpl, arg, arg_len) &&
27714cc2045aSjoerg 		    !vector_str_push(&ddata->tmpl, arg, arg_len)) {
27724cc2045aSjoerg 			free(arg);
27734cc2045aSjoerg 			return (0);
27744cc2045aSjoerg 		}
27754cc2045aSjoerg 
27764cc2045aSjoerg 		free(arg);
27774cc2045aSjoerg 
27784cc2045aSjoerg 		if (*ddata->cur == 'E') {
27794cc2045aSjoerg 			++ddata->cur;
27804cc2045aSjoerg 			size = v->size;
27814cc2045aSjoerg 			assert(size > 0);
27824cc2045aSjoerg 			if (!strncmp(v->container[size - 1], ">", 1)) {
2783*d678c5d4Sjoerg 				if (!DEM_PUSH_STR(ddata, " >"))
27844cc2045aSjoerg 					return (0);
2785*d678c5d4Sjoerg 			} else if (!DEM_PUSH_STR(ddata, ">"))
27864cc2045aSjoerg 				return (0);
2787*d678c5d4Sjoerg 			ddata->is_tmpl = true;
27884cc2045aSjoerg 			break;
27894cc2045aSjoerg 		} else if (*ddata->cur != 'I' &&
2790*d678c5d4Sjoerg 		    !DEM_PUSH_STR(ddata, ", "))
27914cc2045aSjoerg 			return (0);
27924cc2045aSjoerg 
27934cc2045aSjoerg 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
27944cc2045aSjoerg 			return (0);
27954cc2045aSjoerg 	}
27964cc2045aSjoerg 
27974cc2045aSjoerg 	return (vector_read_cmd_pop(&ddata->cmd));
27984cc2045aSjoerg }
27994cc2045aSjoerg 
28004cc2045aSjoerg /*
28014cc2045aSjoerg  * Read template parameter that forms in 'T[number]_'.
28024cc2045aSjoerg  * This function much like to read_subst but only for types.
28034cc2045aSjoerg  */
28044cc2045aSjoerg static int
cpp_demangle_read_tmpl_param(struct cpp_demangle_data * ddata)28054cc2045aSjoerg cpp_demangle_read_tmpl_param(struct cpp_demangle_data *ddata)
28064cc2045aSjoerg {
28074cc2045aSjoerg 	long nth;
28084cc2045aSjoerg 
28094cc2045aSjoerg 	if (ddata == NULL || *ddata->cur != 'T')
28104cc2045aSjoerg 		return (0);
28114cc2045aSjoerg 
28124cc2045aSjoerg 	++ddata->cur;
28134cc2045aSjoerg 
28144cc2045aSjoerg 	if (*ddata->cur == '_')
28154cc2045aSjoerg 		return (cpp_demangle_get_tmpl_param(ddata, 0));
28164cc2045aSjoerg 	else {
28174cc2045aSjoerg 
28184cc2045aSjoerg 		errno = 0;
28194cc2045aSjoerg 		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
28204cc2045aSjoerg 		    errno != 0)
28214cc2045aSjoerg 			return (0);
28224cc2045aSjoerg 
28234cc2045aSjoerg 		/* T_ is first */
28244cc2045aSjoerg 		++nth;
28254cc2045aSjoerg 
28264cc2045aSjoerg 		while (*ddata->cur != '_')
28274cc2045aSjoerg 			++ddata->cur;
28284cc2045aSjoerg 
28294cc2045aSjoerg 		assert(nth > 0);
28304cc2045aSjoerg 
28314cc2045aSjoerg 		return (cpp_demangle_get_tmpl_param(ddata, nth));
28324cc2045aSjoerg 	}
28334cc2045aSjoerg 
28344cc2045aSjoerg 	/* NOTREACHED */
28354cc2045aSjoerg 	return (0);
28364cc2045aSjoerg }
28374cc2045aSjoerg 
28384cc2045aSjoerg static int
cpp_demangle_read_type(struct cpp_demangle_data * ddata,struct type_delimit * td)2839*d678c5d4Sjoerg cpp_demangle_read_type(struct cpp_demangle_data *ddata,
2840*d678c5d4Sjoerg     struct type_delimit *td)
28414cc2045aSjoerg {
28424cc2045aSjoerg 	struct vector_type_qualifier v;
2843*d678c5d4Sjoerg 	struct vector_str *output, sv;
2844*d678c5d4Sjoerg 	size_t p_idx, type_str_len, subst_str_len;
28454cc2045aSjoerg 	int extern_c, is_builtin;
28464cc2045aSjoerg 	long len;
2847*d678c5d4Sjoerg 	const char *p;
2848*d678c5d4Sjoerg 	char *type_str, *exp_str, *num_str, *subst_str;
2849*d678c5d4Sjoerg 	bool skip_ref_qualifier, omit_void;
28504cc2045aSjoerg 
28514cc2045aSjoerg 	if (ddata == NULL)
28524cc2045aSjoerg 		return (0);
28534cc2045aSjoerg 
2854*d678c5d4Sjoerg 	output = ddata->cur_output;
2855*d678c5d4Sjoerg 	if (td) {
2856*d678c5d4Sjoerg 		if (td->paren == false) {
2857*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "("))
28584cc2045aSjoerg 				return (0);
28594cc2045aSjoerg 			if (ddata->output.size < 2)
28604cc2045aSjoerg 				return (0);
2861*d678c5d4Sjoerg 			td->paren = true;
28624cc2045aSjoerg 		}
28634cc2045aSjoerg 
2864*d678c5d4Sjoerg 		if (!td->firstp) {
2865*d678c5d4Sjoerg 			if (*ddata->cur != 'I') {
2866*d678c5d4Sjoerg 				if (!DEM_PUSH_STR(ddata, ", "))
28674cc2045aSjoerg 					return (0);
28684cc2045aSjoerg 			}
2869*d678c5d4Sjoerg 		}
2870*d678c5d4Sjoerg 	}
28714cc2045aSjoerg 
28724cc2045aSjoerg 	assert(output != NULL);
28734cc2045aSjoerg 	/*
2874*d678c5d4Sjoerg 	 * [r, V, K] [P, R, O, C, G, U] builtin, function, class-enum, array
28754cc2045aSjoerg 	 * pointer-to-member, template-param, template-template-param, subst
28764cc2045aSjoerg 	 */
28774cc2045aSjoerg 
28784cc2045aSjoerg 	if (!vector_type_qualifier_init(&v))
28794cc2045aSjoerg 		return (0);
28804cc2045aSjoerg 
28814cc2045aSjoerg 	extern_c = 0;
28824cc2045aSjoerg 	is_builtin = 1;
28834cc2045aSjoerg 	p_idx = output->size;
288486b377d0Spooka 	type_str = exp_str = num_str = NULL;
2885*d678c5d4Sjoerg 	skip_ref_qualifier = false;
2886*d678c5d4Sjoerg 
28874cc2045aSjoerg again:
2888*d678c5d4Sjoerg 
2889*d678c5d4Sjoerg 	/* Clear ref-qualifier flag */
2890*d678c5d4Sjoerg 	if (*ddata->cur != 'R' && *ddata->cur != 'O' && *ddata->cur != 'E')
2891*d678c5d4Sjoerg 		ddata->ref_qualifier = false;
2892*d678c5d4Sjoerg 
28934cc2045aSjoerg 	/* builtin type */
28944cc2045aSjoerg 	switch (*ddata->cur) {
28954cc2045aSjoerg 	case 'a':
28964cc2045aSjoerg 		/* signed char */
2897*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "signed char"))
28984cc2045aSjoerg 			goto clean;
28994cc2045aSjoerg 		++ddata->cur;
29004cc2045aSjoerg 		goto rtn;
29014cc2045aSjoerg 
29024cc2045aSjoerg 	case 'A':
29034cc2045aSjoerg 		/* array type */
29044cc2045aSjoerg 		if (!cpp_demangle_read_array(ddata))
29054cc2045aSjoerg 			goto clean;
29064cc2045aSjoerg 		is_builtin = 0;
29074cc2045aSjoerg 		goto rtn;
29084cc2045aSjoerg 
29094cc2045aSjoerg 	case 'b':
29104cc2045aSjoerg 		/* bool */
2911*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "bool"))
29124cc2045aSjoerg 			goto clean;
29134cc2045aSjoerg 		++ddata->cur;
29144cc2045aSjoerg 		goto rtn;
29154cc2045aSjoerg 
29164cc2045aSjoerg 	case 'C':
29174cc2045aSjoerg 		/* complex pair */
29184cc2045aSjoerg 		if (!vector_type_qualifier_push(&v, TYPE_CMX))
29194cc2045aSjoerg 			goto clean;
29204cc2045aSjoerg 		++ddata->cur;
2921*d678c5d4Sjoerg 		if (td)
2922*d678c5d4Sjoerg 			td->firstp = false;
29234cc2045aSjoerg 		goto again;
29244cc2045aSjoerg 
29254cc2045aSjoerg 	case 'c':
29264cc2045aSjoerg 		/* char */
2927*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "char"))
29284cc2045aSjoerg 			goto clean;
29294cc2045aSjoerg 		++ddata->cur;
29304cc2045aSjoerg 		goto rtn;
29314cc2045aSjoerg 
29324cc2045aSjoerg 	case 'd':
29334cc2045aSjoerg 		/* double */
2934*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "double"))
29354cc2045aSjoerg 			goto clean;
29364cc2045aSjoerg 		++ddata->cur;
29374cc2045aSjoerg 		goto rtn;
29384cc2045aSjoerg 
293986b377d0Spooka 	case 'D':
294086b377d0Spooka 		++ddata->cur;
294186b377d0Spooka 		switch (*ddata->cur) {
2942*d678c5d4Sjoerg 		case 'a':
2943*d678c5d4Sjoerg 			/* auto */
2944*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "auto"))
2945*d678c5d4Sjoerg 				goto clean;
2946*d678c5d4Sjoerg 			++ddata->cur;
2947*d678c5d4Sjoerg 			break;
2948*d678c5d4Sjoerg 		case 'c':
2949*d678c5d4Sjoerg 			/* decltype(auto) */
2950*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "decltype(auto)"))
2951*d678c5d4Sjoerg 				goto clean;
2952*d678c5d4Sjoerg 			++ddata->cur;
2953*d678c5d4Sjoerg 			break;
295486b377d0Spooka 		case 'd':
295586b377d0Spooka 			/* IEEE 754r decimal floating point (64 bits) */
2956*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "decimal64"))
295786b377d0Spooka 				goto clean;
295886b377d0Spooka 			++ddata->cur;
295986b377d0Spooka 			break;
296086b377d0Spooka 		case 'e':
296186b377d0Spooka 			/* IEEE 754r decimal floating point (128 bits) */
2962*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "decimal128"))
296386b377d0Spooka 				goto clean;
296486b377d0Spooka 			++ddata->cur;
296586b377d0Spooka 			break;
296686b377d0Spooka 		case 'f':
296786b377d0Spooka 			/* IEEE 754r decimal floating point (32 bits) */
2968*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "decimal32"))
296986b377d0Spooka 				goto clean;
297086b377d0Spooka 			++ddata->cur;
297186b377d0Spooka 			break;
297286b377d0Spooka 		case 'h':
297386b377d0Spooka 			/* IEEE 754r half-precision floating point (16 bits) */
2974*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "half"))
297586b377d0Spooka 				goto clean;
297686b377d0Spooka 			++ddata->cur;
297786b377d0Spooka 			break;
297886b377d0Spooka 		case 'i':
297986b377d0Spooka 			/* char32_t */
2980*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "char32_t"))
298186b377d0Spooka 				goto clean;
298286b377d0Spooka 			++ddata->cur;
298386b377d0Spooka 			break;
298486b377d0Spooka 		case 'n':
298586b377d0Spooka 			/* std::nullptr_t (i.e., decltype(nullptr)) */
2986*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "decltype(nullptr)"))
298786b377d0Spooka 				goto clean;
298886b377d0Spooka 			++ddata->cur;
298986b377d0Spooka 			break;
299086b377d0Spooka 		case 's':
299186b377d0Spooka 			/* char16_t */
2992*d678c5d4Sjoerg 			if (!DEM_PUSH_STR(ddata, "char16_t"))
299386b377d0Spooka 				goto clean;
299486b377d0Spooka 			++ddata->cur;
299586b377d0Spooka 			break;
299686b377d0Spooka 		case 'v':
299786b377d0Spooka 			/* gcc vector_size extension. */
299886b377d0Spooka 			++ddata->cur;
299986b377d0Spooka 			if (*ddata->cur == '_') {
300086b377d0Spooka 				++ddata->cur;
300186b377d0Spooka 				if (!cpp_demangle_read_expression_flat(ddata,
300286b377d0Spooka 				    &exp_str))
300386b377d0Spooka 					goto clean;
3004*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&v.ext_name, exp_str))
300586b377d0Spooka 					goto clean;
300686b377d0Spooka 			} else {
300786b377d0Spooka 				if (!cpp_demangle_read_number_as_string(ddata,
300886b377d0Spooka 				    &num_str))
300986b377d0Spooka 					goto clean;
3010*d678c5d4Sjoerg 				if (!VEC_PUSH_STR(&v.ext_name, num_str))
301186b377d0Spooka 					goto clean;
301286b377d0Spooka 			}
301386b377d0Spooka 			if (*ddata->cur != '_')
301486b377d0Spooka 				goto clean;
301586b377d0Spooka 			++ddata->cur;
301686b377d0Spooka 			if (!vector_type_qualifier_push(&v, TYPE_VEC))
301786b377d0Spooka 				goto clean;
3018*d678c5d4Sjoerg 			if (td)
3019*d678c5d4Sjoerg 				td->firstp = false;
302086b377d0Spooka 			goto again;
302186b377d0Spooka 		default:
302286b377d0Spooka 			goto clean;
302386b377d0Spooka 		}
302486b377d0Spooka 		goto rtn;
302586b377d0Spooka 
30264cc2045aSjoerg 	case 'e':
30274cc2045aSjoerg 		/* long double */
3028*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "long double"))
30294cc2045aSjoerg 			goto clean;
30304cc2045aSjoerg 		++ddata->cur;
30314cc2045aSjoerg 		goto rtn;
30324cc2045aSjoerg 
3033*d678c5d4Sjoerg 	case 'E':
3034*d678c5d4Sjoerg 		/* unexpected end except ref-qualifiers */
3035*d678c5d4Sjoerg 		if (ddata->ref_qualifier && ddata->is_functype) {
3036*d678c5d4Sjoerg 			skip_ref_qualifier = true;
3037*d678c5d4Sjoerg 			/* Pop the delimiter. */
3038*d678c5d4Sjoerg 			cpp_demangle_pop_str(ddata);
3039*d678c5d4Sjoerg 			goto rtn;
3040*d678c5d4Sjoerg 		}
3041*d678c5d4Sjoerg 		goto clean;
3042*d678c5d4Sjoerg 
30434cc2045aSjoerg 	case 'f':
30444cc2045aSjoerg 		/* float */
3045*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "float"))
30464cc2045aSjoerg 			goto clean;
30474cc2045aSjoerg 		++ddata->cur;
30484cc2045aSjoerg 		goto rtn;
30494cc2045aSjoerg 
30504cc2045aSjoerg 	case 'F':
30514cc2045aSjoerg 		/* function */
30524cc2045aSjoerg 		if (!cpp_demangle_read_function(ddata, &extern_c, &v))
30534cc2045aSjoerg 			goto clean;
30544cc2045aSjoerg 		is_builtin = 0;
30554cc2045aSjoerg 		goto rtn;
30564cc2045aSjoerg 
30574cc2045aSjoerg 	case 'g':
30584cc2045aSjoerg 		/* __float128 */
3059*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "__float128"))
30604cc2045aSjoerg 			goto clean;
30614cc2045aSjoerg 		++ddata->cur;
30624cc2045aSjoerg 		goto rtn;
30634cc2045aSjoerg 
30644cc2045aSjoerg 	case 'G':
30654cc2045aSjoerg 		/* imaginary */
30664cc2045aSjoerg 		if (!vector_type_qualifier_push(&v, TYPE_IMG))
30674cc2045aSjoerg 			goto clean;
30684cc2045aSjoerg 		++ddata->cur;
3069*d678c5d4Sjoerg 		if (td)
3070*d678c5d4Sjoerg 			td->firstp = false;
30714cc2045aSjoerg 		goto again;
30724cc2045aSjoerg 
30734cc2045aSjoerg 	case 'h':
30744cc2045aSjoerg 		/* unsigned char */
3075*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "unsigned char"))
30764cc2045aSjoerg 			goto clean;
30774cc2045aSjoerg 		++ddata->cur;
30784cc2045aSjoerg 		goto rtn;
30794cc2045aSjoerg 
30804cc2045aSjoerg 	case 'i':
30814cc2045aSjoerg 		/* int */
3082*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "int"))
30834cc2045aSjoerg 			goto clean;
30844cc2045aSjoerg 		++ddata->cur;
30854cc2045aSjoerg 		goto rtn;
30864cc2045aSjoerg 
3087*d678c5d4Sjoerg 	case 'I':
3088*d678c5d4Sjoerg 		/* template args. */
3089*d678c5d4Sjoerg 		/* handles <substitute><template-args> */
3090*d678c5d4Sjoerg 		p_idx = output->size;
3091*d678c5d4Sjoerg 		if (!cpp_demangle_read_tmpl_args(ddata))
3092*d678c5d4Sjoerg 			goto clean;
3093*d678c5d4Sjoerg 		if ((subst_str = vector_str_substr(output, p_idx,
3094*d678c5d4Sjoerg 		    output->size - 1, &subst_str_len)) == NULL)
3095*d678c5d4Sjoerg 			goto clean;
3096*d678c5d4Sjoerg 		if (!vector_str_init(&sv)) {
3097*d678c5d4Sjoerg 			free(subst_str);
3098*d678c5d4Sjoerg 			goto clean;
3099*d678c5d4Sjoerg 		}
3100*d678c5d4Sjoerg 		if (!vector_str_push(&sv, subst_str, subst_str_len)) {
3101*d678c5d4Sjoerg 			free(subst_str);
3102*d678c5d4Sjoerg 			vector_str_dest(&sv);
3103*d678c5d4Sjoerg 			goto clean;
3104*d678c5d4Sjoerg 		}
3105*d678c5d4Sjoerg 		free(subst_str);
3106*d678c5d4Sjoerg 		if (!cpp_demangle_push_subst_v(ddata, &sv)) {
3107*d678c5d4Sjoerg 			vector_str_dest(&sv);
3108*d678c5d4Sjoerg 			goto clean;
3109*d678c5d4Sjoerg 		}
3110*d678c5d4Sjoerg 		vector_str_dest(&sv);
3111*d678c5d4Sjoerg 		goto rtn;
3112*d678c5d4Sjoerg 
31134cc2045aSjoerg 	case 'j':
31144cc2045aSjoerg 		/* unsigned int */
3115*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "unsigned int"))
31164cc2045aSjoerg 			goto clean;
31174cc2045aSjoerg 		++ddata->cur;
31184cc2045aSjoerg 		goto rtn;
31194cc2045aSjoerg 
31204cc2045aSjoerg 	case 'K':
31214cc2045aSjoerg 		/* const */
31224cc2045aSjoerg 		if (!vector_type_qualifier_push(&v, TYPE_CST))
31234cc2045aSjoerg 			goto clean;
31244cc2045aSjoerg 		++ddata->cur;
3125*d678c5d4Sjoerg 		if (td)
3126*d678c5d4Sjoerg 			td->firstp = false;
31274cc2045aSjoerg 		goto again;
31284cc2045aSjoerg 
31294cc2045aSjoerg 	case 'l':
31304cc2045aSjoerg 		/* long */
3131*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "long"))
31324cc2045aSjoerg 			goto clean;
31334cc2045aSjoerg 		++ddata->cur;
31344cc2045aSjoerg 		goto rtn;
31354cc2045aSjoerg 
31364cc2045aSjoerg 	case 'm':
31374cc2045aSjoerg 		/* unsigned long */
3138*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "unsigned long"))
31394cc2045aSjoerg 			goto clean;
31404cc2045aSjoerg 
31414cc2045aSjoerg 		++ddata->cur;
31424cc2045aSjoerg 
31434cc2045aSjoerg 		goto rtn;
31444cc2045aSjoerg 	case 'M':
31454cc2045aSjoerg 		/* pointer to member */
3146*d678c5d4Sjoerg 		if (!cpp_demangle_read_pointer_to_member(ddata, &v))
31474cc2045aSjoerg 			goto clean;
31484cc2045aSjoerg 		is_builtin = 0;
31494cc2045aSjoerg 		goto rtn;
31504cc2045aSjoerg 
31514cc2045aSjoerg 	case 'n':
31524cc2045aSjoerg 		/* __int128 */
3153*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "__int128"))
31544cc2045aSjoerg 			goto clean;
31554cc2045aSjoerg 		++ddata->cur;
31564cc2045aSjoerg 		goto rtn;
31574cc2045aSjoerg 
31584cc2045aSjoerg 	case 'o':
31594cc2045aSjoerg 		/* unsigned __int128 */
3160*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "unsigned __int128"))
31614cc2045aSjoerg 			goto clean;
31624cc2045aSjoerg 		++ddata->cur;
31634cc2045aSjoerg 		goto rtn;
31644cc2045aSjoerg 
3165*d678c5d4Sjoerg 	case 'O':
3166*d678c5d4Sjoerg 		/* rvalue reference */
3167*d678c5d4Sjoerg 		if (ddata->ref_qualifier)
3168*d678c5d4Sjoerg 			goto clean;
3169*d678c5d4Sjoerg 		if (!vector_type_qualifier_push(&v, TYPE_RREF))
3170*d678c5d4Sjoerg 			goto clean;
3171*d678c5d4Sjoerg 		ddata->ref_qualifier = true;
3172*d678c5d4Sjoerg 		ddata->ref_qualifier_type = TYPE_RREF;
3173*d678c5d4Sjoerg 		++ddata->cur;
3174*d678c5d4Sjoerg 		if (td)
3175*d678c5d4Sjoerg 			td->firstp = false;
3176*d678c5d4Sjoerg 		goto again;
3177*d678c5d4Sjoerg 
31784cc2045aSjoerg 	case 'P':
31794cc2045aSjoerg 		/* pointer */
31804cc2045aSjoerg 		if (!vector_type_qualifier_push(&v, TYPE_PTR))
31814cc2045aSjoerg 			goto clean;
31824cc2045aSjoerg 		++ddata->cur;
3183*d678c5d4Sjoerg 		if (td)
3184*d678c5d4Sjoerg 			td->firstp = false;
31854cc2045aSjoerg 		goto again;
31864cc2045aSjoerg 
31874cc2045aSjoerg 	case 'r':
31884cc2045aSjoerg 		/* restrict */
31894cc2045aSjoerg 		if (!vector_type_qualifier_push(&v, TYPE_RST))
31904cc2045aSjoerg 			goto clean;
31914cc2045aSjoerg 		++ddata->cur;
3192*d678c5d4Sjoerg 		if (td)
3193*d678c5d4Sjoerg 			td->firstp = false;
31944cc2045aSjoerg 		goto again;
31954cc2045aSjoerg 
31964cc2045aSjoerg 	case 'R':
31974cc2045aSjoerg 		/* reference */
3198*d678c5d4Sjoerg 		if (ddata->ref_qualifier)
3199*d678c5d4Sjoerg 			goto clean;
32004cc2045aSjoerg 		if (!vector_type_qualifier_push(&v, TYPE_REF))
32014cc2045aSjoerg 			goto clean;
3202*d678c5d4Sjoerg 		ddata->ref_qualifier = true;
3203*d678c5d4Sjoerg 		ddata->ref_qualifier_type = TYPE_REF;
32044cc2045aSjoerg 		++ddata->cur;
3205*d678c5d4Sjoerg 		if (td)
3206*d678c5d4Sjoerg 			td->firstp = false;
32074cc2045aSjoerg 		goto again;
32084cc2045aSjoerg 
32094cc2045aSjoerg 	case 's':
32104cc2045aSjoerg 		/* short, local string */
3211*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "short"))
32124cc2045aSjoerg 			goto clean;
32134cc2045aSjoerg 		++ddata->cur;
32144cc2045aSjoerg 		goto rtn;
32154cc2045aSjoerg 
32164cc2045aSjoerg 	case 'S':
32174cc2045aSjoerg 		/* substitution */
32184cc2045aSjoerg 		if (!cpp_demangle_read_subst(ddata))
32194cc2045aSjoerg 			goto clean;
32204cc2045aSjoerg 		is_builtin = 0;
32214cc2045aSjoerg 		goto rtn;
32224cc2045aSjoerg 
32234cc2045aSjoerg 	case 't':
32244cc2045aSjoerg 		/* unsigned short */
3225*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "unsigned short"))
32264cc2045aSjoerg 			goto clean;
32274cc2045aSjoerg 		++ddata->cur;
32284cc2045aSjoerg 		goto rtn;
32294cc2045aSjoerg 
32304cc2045aSjoerg 	case 'T':
32314cc2045aSjoerg 		/* template parameter */
32324cc2045aSjoerg 		if (!cpp_demangle_read_tmpl_param(ddata))
32334cc2045aSjoerg 			goto clean;
32344cc2045aSjoerg 		is_builtin = 0;
32354cc2045aSjoerg 		goto rtn;
32364cc2045aSjoerg 
32374cc2045aSjoerg 	case 'u':
32384cc2045aSjoerg 		/* vendor extended builtin */
32394cc2045aSjoerg 		++ddata->cur;
32404cc2045aSjoerg 		if (!cpp_demangle_read_sname(ddata))
32414cc2045aSjoerg 			goto clean;
32424cc2045aSjoerg 		is_builtin = 0;
32434cc2045aSjoerg 		goto rtn;
32444cc2045aSjoerg 
32454cc2045aSjoerg 	case 'U':
32464cc2045aSjoerg 		/* vendor extended type qualifier */
3247*d678c5d4Sjoerg 		++ddata->cur;
32484cc2045aSjoerg 		if (!cpp_demangle_read_number(ddata, &len))
32494cc2045aSjoerg 			goto clean;
32504cc2045aSjoerg 		if (len <= 0)
32514cc2045aSjoerg 			goto clean;
32524cc2045aSjoerg 		if (!vector_str_push(&v.ext_name, ddata->cur, len))
3253*d678c5d4Sjoerg 			goto clean;
32544cc2045aSjoerg 		ddata->cur += len;
325586b377d0Spooka 		if (!vector_type_qualifier_push(&v, TYPE_EXT))
325686b377d0Spooka 			goto clean;
3257*d678c5d4Sjoerg 		if (td)
3258*d678c5d4Sjoerg 			td->firstp = false;
32594cc2045aSjoerg 		goto again;
32604cc2045aSjoerg 
32614cc2045aSjoerg 	case 'v':
32624cc2045aSjoerg 		/* void */
3263*d678c5d4Sjoerg 		omit_void = false;
3264*d678c5d4Sjoerg 		if (td && td->firstp) {
3265*d678c5d4Sjoerg 			/*
3266*d678c5d4Sjoerg 			 * peek into next bytes and see if we should omit
3267*d678c5d4Sjoerg 			 * the "void".
3268*d678c5d4Sjoerg 			 */
3269*d678c5d4Sjoerg 			omit_void = true;
3270*d678c5d4Sjoerg 			for (p = ddata->cur + 1; *p != '\0'; p++) {
3271*d678c5d4Sjoerg 				if (*p == 'E')
3272*d678c5d4Sjoerg 					break;
3273*d678c5d4Sjoerg 				if (*p != 'R' && *p != 'O') {
3274*d678c5d4Sjoerg 					omit_void = false;
3275*d678c5d4Sjoerg 					break;
3276*d678c5d4Sjoerg 				}
3277*d678c5d4Sjoerg 			}
3278*d678c5d4Sjoerg 		}
3279*d678c5d4Sjoerg 		if (!omit_void && !DEM_PUSH_STR(ddata, "void"))
32804cc2045aSjoerg 			goto clean;
32814cc2045aSjoerg 		++ddata->cur;
32824cc2045aSjoerg 		goto rtn;
32834cc2045aSjoerg 
32844cc2045aSjoerg 	case 'V':
32854cc2045aSjoerg 		/* volatile */
32864cc2045aSjoerg 		if (!vector_type_qualifier_push(&v, TYPE_VAT))
32874cc2045aSjoerg 			goto clean;
32884cc2045aSjoerg 		++ddata->cur;
3289*d678c5d4Sjoerg 		if (td)
3290*d678c5d4Sjoerg 			td->firstp = false;
32914cc2045aSjoerg 		goto again;
32924cc2045aSjoerg 
32934cc2045aSjoerg 	case 'w':
32944cc2045aSjoerg 		/* wchar_t */
3295*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "wchar_t"))
32964cc2045aSjoerg 			goto clean;
32974cc2045aSjoerg 		++ddata->cur;
32984cc2045aSjoerg 		goto rtn;
32994cc2045aSjoerg 
33004cc2045aSjoerg 	case 'x':
33014cc2045aSjoerg 		/* long long */
3302*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "long long"))
33034cc2045aSjoerg 			goto clean;
33044cc2045aSjoerg 		++ddata->cur;
33054cc2045aSjoerg 		goto rtn;
33064cc2045aSjoerg 
33074cc2045aSjoerg 	case 'y':
33084cc2045aSjoerg 		/* unsigned long long */
3309*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "unsigned long long"))
33104cc2045aSjoerg 			goto clean;
33114cc2045aSjoerg 		++ddata->cur;
33124cc2045aSjoerg 		goto rtn;
33134cc2045aSjoerg 
33144cc2045aSjoerg 	case 'z':
33154cc2045aSjoerg 		/* ellipsis */
3316*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "..."))
33174cc2045aSjoerg 			goto clean;
33184cc2045aSjoerg 		++ddata->cur;
33194cc2045aSjoerg 		goto rtn;
3320*d678c5d4Sjoerg 	}
33214cc2045aSjoerg 
33224cc2045aSjoerg 	if (!cpp_demangle_read_name(ddata))
33234cc2045aSjoerg 		goto clean;
33244cc2045aSjoerg 
33254cc2045aSjoerg 	is_builtin = 0;
33264cc2045aSjoerg rtn:
3327*d678c5d4Sjoerg 
3328*d678c5d4Sjoerg 	type_str = vector_str_substr(output, p_idx, output->size - 1,
3329*d678c5d4Sjoerg 	    &type_str_len);
33304cc2045aSjoerg 
33314cc2045aSjoerg 	if (is_builtin == 0) {
33324cc2045aSjoerg 		if (!vector_str_find(&ddata->subst, type_str, type_str_len) &&
33334cc2045aSjoerg 		    !vector_str_push(&ddata->subst, type_str, type_str_len))
33344cc2045aSjoerg 			goto clean;
33354cc2045aSjoerg 	}
33364cc2045aSjoerg 
3337*d678c5d4Sjoerg 	if (!skip_ref_qualifier &&
3338*d678c5d4Sjoerg 	    !cpp_demangle_push_type_qualifier(ddata, &v, type_str))
33394cc2045aSjoerg 		goto clean;
33404cc2045aSjoerg 
3341*d678c5d4Sjoerg 	if (td)
3342*d678c5d4Sjoerg 		td->firstp = false;
3343*d678c5d4Sjoerg 
33444cc2045aSjoerg 	free(type_str);
334586b377d0Spooka 	free(exp_str);
334686b377d0Spooka 	free(num_str);
33474cc2045aSjoerg 	vector_type_qualifier_dest(&v);
33484cc2045aSjoerg 
33494cc2045aSjoerg 	return (1);
33504cc2045aSjoerg clean:
33514cc2045aSjoerg 	free(type_str);
335286b377d0Spooka 	free(exp_str);
335386b377d0Spooka 	free(num_str);
33544cc2045aSjoerg 	vector_type_qualifier_dest(&v);
33554cc2045aSjoerg 
33564cc2045aSjoerg 	return (0);
33574cc2045aSjoerg }
33584cc2045aSjoerg 
335986b377d0Spooka static int
cpp_demangle_read_type_flat(struct cpp_demangle_data * ddata,char ** str)336086b377d0Spooka cpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str)
336186b377d0Spooka {
336286b377d0Spooka 	struct vector_str *output;
336386b377d0Spooka 	size_t i, p_idx, idx, type_len;
336486b377d0Spooka 	char *type;
336586b377d0Spooka 
3366*d678c5d4Sjoerg 	output = ddata->cur_output;
336786b377d0Spooka 
336886b377d0Spooka 	p_idx = output->size;
336986b377d0Spooka 
3370*d678c5d4Sjoerg 	if (!cpp_demangle_read_type(ddata, NULL))
337186b377d0Spooka 		return (0);
337286b377d0Spooka 
337386b377d0Spooka 	if ((type = vector_str_substr(output, p_idx, output->size - 1,
337486b377d0Spooka 	    &type_len)) == NULL)
337586b377d0Spooka 		return (0);
337686b377d0Spooka 
337786b377d0Spooka 	idx = output->size;
337886b377d0Spooka 	for (i = p_idx; i < idx; ++i) {
337986b377d0Spooka 		if (!vector_str_pop(output)) {
338086b377d0Spooka 			free(type);
338186b377d0Spooka 			return (0);
338286b377d0Spooka 		}
338386b377d0Spooka 	}
338486b377d0Spooka 
338586b377d0Spooka 	*str = type;
338686b377d0Spooka 
338786b377d0Spooka 	return (1);
338886b377d0Spooka }
338986b377d0Spooka 
33904cc2045aSjoerg /*
33914cc2045aSjoerg  * read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
33924cc2045aSjoerg  * source-name
33934cc2045aSjoerg  */
33944cc2045aSjoerg static int
cpp_demangle_read_uqname(struct cpp_demangle_data * ddata)33954cc2045aSjoerg cpp_demangle_read_uqname(struct cpp_demangle_data *ddata)
33964cc2045aSjoerg {
33974cc2045aSjoerg 	size_t len;
33984cc2045aSjoerg 
33994cc2045aSjoerg 	if (ddata == NULL || *ddata->cur == '\0')
34004cc2045aSjoerg 		return (0);
34014cc2045aSjoerg 
34024cc2045aSjoerg 	/* operator name */
34034cc2045aSjoerg 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
34044cc2045aSjoerg 	case SIMPLE_HASH('a', 'a'):
34054cc2045aSjoerg 		/* operator && */
3406*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator&&"))
34074cc2045aSjoerg 			return (0);
34084cc2045aSjoerg 		ddata->cur += 2;
34094cc2045aSjoerg 		return (1);
34104cc2045aSjoerg 
34114cc2045aSjoerg 	case SIMPLE_HASH('a', 'd'):
34124cc2045aSjoerg 		/* operator & (unary) */
3413*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator&"))
34144cc2045aSjoerg 			return (0);
34154cc2045aSjoerg 		ddata->cur += 2;
34164cc2045aSjoerg 		return (1);
34174cc2045aSjoerg 
34184cc2045aSjoerg 	case SIMPLE_HASH('a', 'n'):
34194cc2045aSjoerg 		/* operator & */
3420*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator&"))
34214cc2045aSjoerg 			return (0);
34224cc2045aSjoerg 		ddata->cur += 2;
34234cc2045aSjoerg 		return (1);
34244cc2045aSjoerg 
34254cc2045aSjoerg 	case SIMPLE_HASH('a', 'N'):
34264cc2045aSjoerg 		/* operator &= */
3427*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator&="))
34284cc2045aSjoerg 			return (0);
34294cc2045aSjoerg 		ddata->cur += 2;
34304cc2045aSjoerg 		return (1);
34314cc2045aSjoerg 
34324cc2045aSjoerg 	case SIMPLE_HASH('a', 'S'):
34334cc2045aSjoerg 		/* operator = */
3434*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator="))
34354cc2045aSjoerg 			return (0);
34364cc2045aSjoerg 		ddata->cur += 2;
34374cc2045aSjoerg 		return (1);
34384cc2045aSjoerg 
34394cc2045aSjoerg 	case SIMPLE_HASH('c', 'l'):
34404cc2045aSjoerg 		/* operator () */
3441*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator()"))
34424cc2045aSjoerg 			return (0);
34434cc2045aSjoerg 		ddata->cur += 2;
34444cc2045aSjoerg 		return (1);
34454cc2045aSjoerg 
34464cc2045aSjoerg 	case SIMPLE_HASH('c', 'm'):
34474cc2045aSjoerg 		/* operator , */
3448*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator,"))
34494cc2045aSjoerg 			return (0);
34504cc2045aSjoerg 		ddata->cur += 2;
34514cc2045aSjoerg 		return (1);
34524cc2045aSjoerg 
34534cc2045aSjoerg 	case SIMPLE_HASH('c', 'o'):
34544cc2045aSjoerg 		/* operator ~ */
3455*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator~"))
34564cc2045aSjoerg 			return (0);
34574cc2045aSjoerg 		ddata->cur += 2;
34584cc2045aSjoerg 		return (1);
34594cc2045aSjoerg 
34604cc2045aSjoerg 	case SIMPLE_HASH('c', 'v'):
34614cc2045aSjoerg 		/* operator (cast) */
3462*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator(cast)"))
34634cc2045aSjoerg 			return (0);
34644cc2045aSjoerg 		ddata->cur += 2;
3465*d678c5d4Sjoerg 		return (cpp_demangle_read_type(ddata, NULL));
34664cc2045aSjoerg 
34674cc2045aSjoerg 	case SIMPLE_HASH('d', 'a'):
34684cc2045aSjoerg 		/* operator delete [] */
3469*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator delete []"))
34704cc2045aSjoerg 			return (0);
34714cc2045aSjoerg 		ddata->cur += 2;
34724cc2045aSjoerg 		return (1);
34734cc2045aSjoerg 
34744cc2045aSjoerg 	case SIMPLE_HASH('d', 'e'):
34754cc2045aSjoerg 		/* operator * (unary) */
3476*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator*"))
34774cc2045aSjoerg 			return (0);
34784cc2045aSjoerg 		ddata->cur += 2;
34794cc2045aSjoerg 		return (1);
34804cc2045aSjoerg 
34814cc2045aSjoerg 	case SIMPLE_HASH('d', 'l'):
34824cc2045aSjoerg 		/* operator delete */
3483*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator delete"))
34844cc2045aSjoerg 			return (0);
34854cc2045aSjoerg 		ddata->cur += 2;
34864cc2045aSjoerg 		return (1);
34874cc2045aSjoerg 
34884cc2045aSjoerg 	case SIMPLE_HASH('d', 'v'):
34894cc2045aSjoerg 		/* operator / */
3490*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator/"))
34914cc2045aSjoerg 			return (0);
34924cc2045aSjoerg 		ddata->cur += 2;
34934cc2045aSjoerg 		return (1);
34944cc2045aSjoerg 
34954cc2045aSjoerg 	case SIMPLE_HASH('d', 'V'):
34964cc2045aSjoerg 		/* operator /= */
3497*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator/="))
34984cc2045aSjoerg 			return (0);
34994cc2045aSjoerg 		ddata->cur += 2;
35004cc2045aSjoerg 		return (1);
35014cc2045aSjoerg 
35024cc2045aSjoerg 	case SIMPLE_HASH('e', 'o'):
35034cc2045aSjoerg 		/* operator ^ */
3504*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator^"))
35054cc2045aSjoerg 			return (0);
35064cc2045aSjoerg 		ddata->cur += 2;
35074cc2045aSjoerg 		return (1);
35084cc2045aSjoerg 
35094cc2045aSjoerg 	case SIMPLE_HASH('e', 'O'):
35104cc2045aSjoerg 		/* operator ^= */
3511*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator^="))
35124cc2045aSjoerg 			return (0);
35134cc2045aSjoerg 		ddata->cur += 2;
35144cc2045aSjoerg 		return (1);
35154cc2045aSjoerg 
35164cc2045aSjoerg 	case SIMPLE_HASH('e', 'q'):
35174cc2045aSjoerg 		/* operator == */
3518*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator=="))
35194cc2045aSjoerg 			return (0);
35204cc2045aSjoerg 		ddata->cur += 2;
35214cc2045aSjoerg 		return (1);
35224cc2045aSjoerg 
35234cc2045aSjoerg 	case SIMPLE_HASH('g', 'e'):
35244cc2045aSjoerg 		/* operator >= */
3525*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator>="))
35264cc2045aSjoerg 			return (0);
35274cc2045aSjoerg 		ddata->cur += 2;
35284cc2045aSjoerg 		return (1);
35294cc2045aSjoerg 
35304cc2045aSjoerg 	case SIMPLE_HASH('g', 't'):
35314cc2045aSjoerg 		/* operator > */
3532*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator>"))
35334cc2045aSjoerg 			return (0);
35344cc2045aSjoerg 		ddata->cur += 2;
35354cc2045aSjoerg 		return (1);
35364cc2045aSjoerg 
35374cc2045aSjoerg 	case SIMPLE_HASH('i', 'x'):
35384cc2045aSjoerg 		/* operator [] */
3539*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator[]"))
35404cc2045aSjoerg 			return (0);
35414cc2045aSjoerg 		ddata->cur += 2;
35424cc2045aSjoerg 		return (1);
35434cc2045aSjoerg 
35444cc2045aSjoerg 	case SIMPLE_HASH('l', 'e'):
35454cc2045aSjoerg 		/* operator <= */
3546*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator<="))
35474cc2045aSjoerg 			return (0);
35484cc2045aSjoerg 		ddata->cur += 2;
35494cc2045aSjoerg 		return (1);
35504cc2045aSjoerg 
35514cc2045aSjoerg 	case SIMPLE_HASH('l', 's'):
35524cc2045aSjoerg 		/* operator << */
3553*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator<<"))
35544cc2045aSjoerg 			return (0);
35554cc2045aSjoerg 		ddata->cur += 2;
35564cc2045aSjoerg 		return (1);
35574cc2045aSjoerg 
35584cc2045aSjoerg 	case SIMPLE_HASH('l', 'S'):
35594cc2045aSjoerg 		/* operator <<= */
3560*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator<<="))
35614cc2045aSjoerg 			return (0);
35624cc2045aSjoerg 		ddata->cur += 2;
35634cc2045aSjoerg 		return (1);
35644cc2045aSjoerg 
35654cc2045aSjoerg 	case SIMPLE_HASH('l', 't'):
35664cc2045aSjoerg 		/* operator < */
3567*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator<"))
35684cc2045aSjoerg 			return (0);
35694cc2045aSjoerg 		ddata->cur += 2;
35704cc2045aSjoerg 		return (1);
35714cc2045aSjoerg 
35724cc2045aSjoerg 	case SIMPLE_HASH('m', 'i'):
35734cc2045aSjoerg 		/* operator - */
3574*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator-"))
35754cc2045aSjoerg 			return (0);
35764cc2045aSjoerg 		ddata->cur += 2;
35774cc2045aSjoerg 		return (1);
35784cc2045aSjoerg 
35794cc2045aSjoerg 	case SIMPLE_HASH('m', 'I'):
35804cc2045aSjoerg 		/* operator -= */
3581*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator-="))
35824cc2045aSjoerg 			return (0);
35834cc2045aSjoerg 		ddata->cur += 2;
35844cc2045aSjoerg 		return (1);
35854cc2045aSjoerg 
35864cc2045aSjoerg 	case SIMPLE_HASH('m', 'l'):
35874cc2045aSjoerg 		/* operator * */
3588*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator*"))
35894cc2045aSjoerg 			return (0);
35904cc2045aSjoerg 		ddata->cur += 2;
35914cc2045aSjoerg 		return (1);
35924cc2045aSjoerg 
35934cc2045aSjoerg 	case SIMPLE_HASH('m', 'L'):
35944cc2045aSjoerg 		/* operator *= */
3595*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator*="))
35964cc2045aSjoerg 			return (0);
35974cc2045aSjoerg 		ddata->cur += 2;
35984cc2045aSjoerg 		return (1);
35994cc2045aSjoerg 
36004cc2045aSjoerg 	case SIMPLE_HASH('m', 'm'):
36014cc2045aSjoerg 		/* operator -- */
3602*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator--"))
36034cc2045aSjoerg 			return (0);
36044cc2045aSjoerg 		ddata->cur += 2;
36054cc2045aSjoerg 		return (1);
36064cc2045aSjoerg 
36074cc2045aSjoerg 	case SIMPLE_HASH('n', 'a'):
36084cc2045aSjoerg 		/* operator new[] */
3609*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator new []"))
36104cc2045aSjoerg 			return (0);
36114cc2045aSjoerg 		ddata->cur += 2;
36124cc2045aSjoerg 		return (1);
36134cc2045aSjoerg 
36144cc2045aSjoerg 	case SIMPLE_HASH('n', 'e'):
36154cc2045aSjoerg 		/* operator != */
3616*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator!="))
36174cc2045aSjoerg 			return (0);
36184cc2045aSjoerg 		ddata->cur += 2;
36194cc2045aSjoerg 		return (1);
36204cc2045aSjoerg 
36214cc2045aSjoerg 	case SIMPLE_HASH('n', 'g'):
36224cc2045aSjoerg 		/* operator - (unary) */
3623*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator-"))
36244cc2045aSjoerg 			return (0);
36254cc2045aSjoerg 		ddata->cur += 2;
36264cc2045aSjoerg 		return (1);
36274cc2045aSjoerg 
36284cc2045aSjoerg 	case SIMPLE_HASH('n', 't'):
36294cc2045aSjoerg 		/* operator ! */
3630*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator!"))
36314cc2045aSjoerg 			return (0);
36324cc2045aSjoerg 		ddata->cur += 2;
36334cc2045aSjoerg 		return (1);
36344cc2045aSjoerg 
36354cc2045aSjoerg 	case SIMPLE_HASH('n', 'w'):
36364cc2045aSjoerg 		/* operator new */
3637*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator new"))
36384cc2045aSjoerg 			return (0);
36394cc2045aSjoerg 		ddata->cur += 2;
36404cc2045aSjoerg 		return (1);
36414cc2045aSjoerg 
36424cc2045aSjoerg 	case SIMPLE_HASH('o', 'o'):
36434cc2045aSjoerg 		/* operator || */
3644*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator||"))
36454cc2045aSjoerg 			return (0);
36464cc2045aSjoerg 		ddata->cur += 2;
36474cc2045aSjoerg 		return (1);
36484cc2045aSjoerg 
36494cc2045aSjoerg 	case SIMPLE_HASH('o', 'r'):
36504cc2045aSjoerg 		/* operator | */
3651*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator|"))
36524cc2045aSjoerg 			return (0);
36534cc2045aSjoerg 		ddata->cur += 2;
36544cc2045aSjoerg 		return (1);
36554cc2045aSjoerg 
36564cc2045aSjoerg 	case SIMPLE_HASH('o', 'R'):
36574cc2045aSjoerg 		/* operator |= */
3658*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator|="))
36594cc2045aSjoerg 			return (0);
36604cc2045aSjoerg 		ddata->cur += 2;
36614cc2045aSjoerg 		return (1);
36624cc2045aSjoerg 
36634cc2045aSjoerg 	case SIMPLE_HASH('p', 'l'):
36644cc2045aSjoerg 		/* operator + */
3665*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator+"))
36664cc2045aSjoerg 			return (0);
36674cc2045aSjoerg 		ddata->cur += 2;
36684cc2045aSjoerg 		return (1);
36694cc2045aSjoerg 
36704cc2045aSjoerg 	case SIMPLE_HASH('p', 'L'):
36714cc2045aSjoerg 		/* operator += */
3672*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator+="))
36734cc2045aSjoerg 			return (0);
36744cc2045aSjoerg 		ddata->cur += 2;
36754cc2045aSjoerg 		return (1);
36764cc2045aSjoerg 
36774cc2045aSjoerg 	case SIMPLE_HASH('p', 'm'):
36784cc2045aSjoerg 		/* operator ->* */
3679*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator->*"))
36804cc2045aSjoerg 			return (0);
36814cc2045aSjoerg 		ddata->cur += 2;
36824cc2045aSjoerg 		return (1);
36834cc2045aSjoerg 
36844cc2045aSjoerg 	case SIMPLE_HASH('p', 'p'):
36854cc2045aSjoerg 		/* operator ++ */
3686*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator++"))
36874cc2045aSjoerg 			return (0);
36884cc2045aSjoerg 		ddata->cur += 2;
36894cc2045aSjoerg 		return (1);
36904cc2045aSjoerg 
36914cc2045aSjoerg 	case SIMPLE_HASH('p', 's'):
36924cc2045aSjoerg 		/* operator + (unary) */
3693*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator+"))
36944cc2045aSjoerg 			return (0);
36954cc2045aSjoerg 		ddata->cur += 2;
36964cc2045aSjoerg 		return (1);
36974cc2045aSjoerg 
36984cc2045aSjoerg 	case SIMPLE_HASH('p', 't'):
36994cc2045aSjoerg 		/* operator -> */
3700*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator->"))
37014cc2045aSjoerg 			return (0);
37024cc2045aSjoerg 		ddata->cur += 2;
37034cc2045aSjoerg 		return (1);
37044cc2045aSjoerg 
37054cc2045aSjoerg 	case SIMPLE_HASH('q', 'u'):
37064cc2045aSjoerg 		/* operator ? */
3707*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator?"))
37084cc2045aSjoerg 			return (0);
37094cc2045aSjoerg 		ddata->cur += 2;
37104cc2045aSjoerg 		return (1);
37114cc2045aSjoerg 
37124cc2045aSjoerg 	case SIMPLE_HASH('r', 'm'):
37134cc2045aSjoerg 		/* operator % */
3714*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator%"))
37154cc2045aSjoerg 			return (0);
37164cc2045aSjoerg 		ddata->cur += 2;
37174cc2045aSjoerg 		return (1);
37184cc2045aSjoerg 
37194cc2045aSjoerg 	case SIMPLE_HASH('r', 'M'):
37204cc2045aSjoerg 		/* operator %= */
3721*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator%="))
37224cc2045aSjoerg 			return (0);
37234cc2045aSjoerg 		ddata->cur += 2;
37244cc2045aSjoerg 		return (1);
37254cc2045aSjoerg 
37264cc2045aSjoerg 	case SIMPLE_HASH('r', 's'):
37274cc2045aSjoerg 		/* operator >> */
3728*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator>>"))
37294cc2045aSjoerg 			return (0);
37304cc2045aSjoerg 		ddata->cur += 2;
37314cc2045aSjoerg 		return (1);
37324cc2045aSjoerg 
37334cc2045aSjoerg 	case SIMPLE_HASH('r', 'S'):
37344cc2045aSjoerg 		/* operator >>= */
3735*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator>>="))
37364cc2045aSjoerg 			return (0);
37374cc2045aSjoerg 		ddata->cur += 2;
37384cc2045aSjoerg 		return (1);
37394cc2045aSjoerg 
37404cc2045aSjoerg 	case SIMPLE_HASH('r', 'z'):
37414cc2045aSjoerg 		/* operator sizeof */
3742*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator sizeof "))
37434cc2045aSjoerg 			return (0);
37444cc2045aSjoerg 		ddata->cur += 2;
37454cc2045aSjoerg 		return (1);
37464cc2045aSjoerg 
37474cc2045aSjoerg 	case SIMPLE_HASH('s', 'r'):
37484cc2045aSjoerg 		/* scope resolution operator */
3749*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "scope resolution operator "))
37504cc2045aSjoerg 			return (0);
37514cc2045aSjoerg 		ddata->cur += 2;
37524cc2045aSjoerg 		return (1);
37534cc2045aSjoerg 
37544cc2045aSjoerg 	case SIMPLE_HASH('s', 'v'):
37554cc2045aSjoerg 		/* operator sizeof */
3756*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "operator sizeof "))
37574cc2045aSjoerg 			return (0);
37584cc2045aSjoerg 		ddata->cur += 2;
37594cc2045aSjoerg 		return (1);
3760*d678c5d4Sjoerg 	}
37614cc2045aSjoerg 
37624cc2045aSjoerg 	/* vendor extened operator */
37634cc2045aSjoerg 	if (*ddata->cur == 'v' && ELFTC_ISDIGIT(*(ddata->cur + 1))) {
3764*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "vendor extened operator "))
37654cc2045aSjoerg 			return (0);
37664cc2045aSjoerg 		if (!cpp_demangle_push_str(ddata, ddata->cur + 1, 1))
37674cc2045aSjoerg 			return (0);
37684cc2045aSjoerg 		ddata->cur += 2;
37694cc2045aSjoerg 		return (cpp_demangle_read_sname(ddata));
37704cc2045aSjoerg 	}
37714cc2045aSjoerg 
37724cc2045aSjoerg 	/* ctor-dtor-name */
37734cc2045aSjoerg 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
37744cc2045aSjoerg 	case SIMPLE_HASH('C', '1'):
37754cc2045aSjoerg 	case SIMPLE_HASH('C', '2'):
37764cc2045aSjoerg 	case SIMPLE_HASH('C', '3'):
37774cc2045aSjoerg 		if (ddata->last_sname == NULL)
37784cc2045aSjoerg 			return (0);
37794cc2045aSjoerg 		if ((len = strlen(ddata->last_sname)) == 0)
37804cc2045aSjoerg 			return (0);
3781*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "::"))
37824cc2045aSjoerg 			return (0);
37834cc2045aSjoerg 		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
37844cc2045aSjoerg 			return (0);
37854cc2045aSjoerg 		ddata->cur +=2;
37864cc2045aSjoerg 		return (1);
37874cc2045aSjoerg 
37884cc2045aSjoerg 	case SIMPLE_HASH('D', '0'):
37894cc2045aSjoerg 	case SIMPLE_HASH('D', '1'):
37904cc2045aSjoerg 	case SIMPLE_HASH('D', '2'):
37914cc2045aSjoerg 		if (ddata->last_sname == NULL)
37924cc2045aSjoerg 			return (0);
37934cc2045aSjoerg 		if ((len = strlen(ddata->last_sname)) == 0)
37944cc2045aSjoerg 			return (0);
3795*d678c5d4Sjoerg 		if (!DEM_PUSH_STR(ddata, "::~"))
37964cc2045aSjoerg 			return (0);
37974cc2045aSjoerg 		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
37984cc2045aSjoerg 			return (0);
37994cc2045aSjoerg 		ddata->cur +=2;
38004cc2045aSjoerg 		return (1);
3801*d678c5d4Sjoerg 	}
38024cc2045aSjoerg 
38034cc2045aSjoerg 	/* source name */
38044cc2045aSjoerg 	if (ELFTC_ISDIGIT(*ddata->cur) != 0)
38054cc2045aSjoerg 		return (cpp_demangle_read_sname(ddata));
38064cc2045aSjoerg 
38075192b81bSjoerg 	/* local source name */
38085192b81bSjoerg 	if (*ddata->cur == 'L')
38095192b81bSjoerg 		return (cpp_demangle_local_source_name(ddata));
38105192b81bSjoerg 
38115192b81bSjoerg 	return (1);
38125192b81bSjoerg }
38135192b81bSjoerg 
38145192b81bSjoerg /*
38155192b81bSjoerg  * Read local source name.
38165192b81bSjoerg  *
38175192b81bSjoerg  * References:
38185192b81bSjoerg  *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
38195192b81bSjoerg  *   http://gcc.gnu.org/viewcvs?view=rev&revision=124467
38205192b81bSjoerg  */
38215192b81bSjoerg static int
cpp_demangle_local_source_name(struct cpp_demangle_data * ddata)38225192b81bSjoerg cpp_demangle_local_source_name(struct cpp_demangle_data *ddata)
38235192b81bSjoerg {
38245192b81bSjoerg 	/* L */
38255192b81bSjoerg 	if (ddata == NULL || *ddata->cur != 'L')
38265192b81bSjoerg 		return (0);
38275192b81bSjoerg 	++ddata->cur;
38285192b81bSjoerg 
38295192b81bSjoerg 	/* source name */
38305192b81bSjoerg 	if (!cpp_demangle_read_sname(ddata))
38315192b81bSjoerg 		return (0);
38325192b81bSjoerg 
38335192b81bSjoerg 	/* discriminator */
38345192b81bSjoerg 	if (*ddata->cur == '_') {
38355192b81bSjoerg 		++ddata->cur;
38365192b81bSjoerg 		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
38375192b81bSjoerg 			++ddata->cur;
38385192b81bSjoerg 	}
38395192b81bSjoerg 
38404cc2045aSjoerg 	return (1);
38414cc2045aSjoerg }
38424cc2045aSjoerg 
38434cc2045aSjoerg static int
cpp_demangle_read_v_offset(struct cpp_demangle_data * ddata)38444cc2045aSjoerg cpp_demangle_read_v_offset(struct cpp_demangle_data *ddata)
38454cc2045aSjoerg {
38464cc2045aSjoerg 
38474cc2045aSjoerg 	if (ddata == NULL)
38484cc2045aSjoerg 		return (0);
38494cc2045aSjoerg 
3850*d678c5d4Sjoerg 	if (!DEM_PUSH_STR(ddata, "offset : "))
38514cc2045aSjoerg 		return (0);
38524cc2045aSjoerg 
38534cc2045aSjoerg 	if (!cpp_demangle_read_offset_number(ddata))
38544cc2045aSjoerg 		return (0);
38554cc2045aSjoerg 
3856*d678c5d4Sjoerg 	if (!DEM_PUSH_STR(ddata, "virtual offset : "))
38574cc2045aSjoerg 		return (0);
38584cc2045aSjoerg 
38594cc2045aSjoerg 	return (!cpp_demangle_read_offset_number(ddata));
38604cc2045aSjoerg }
38614cc2045aSjoerg 
38624cc2045aSjoerg /*
38634cc2045aSjoerg  * Decode floating point representation to string
38644cc2045aSjoerg  * Return new allocated string or NULL
38654cc2045aSjoerg  *
38664cc2045aSjoerg  * Todo
38674cc2045aSjoerg  * Replace these functions to macro.
38684cc2045aSjoerg  */
38694cc2045aSjoerg static char *
decode_fp_to_double(const char * p,size_t len)38704cc2045aSjoerg decode_fp_to_double(const char *p, size_t len)
38714cc2045aSjoerg {
38724cc2045aSjoerg 	double f;
38734cc2045aSjoerg 	size_t rtn_len, limit, i;
38744cc2045aSjoerg 	int byte;
38754cc2045aSjoerg 	char *rtn;
38764cc2045aSjoerg 
38774cc2045aSjoerg 	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(double))
38784cc2045aSjoerg 		return (NULL);
38794cc2045aSjoerg 
38804cc2045aSjoerg 	memset(&f, 0, sizeof(double));
38814cc2045aSjoerg 
38824cc2045aSjoerg 	for (i = 0; i < len / 2; ++i) {
38834cc2045aSjoerg 		byte = hex_to_dec(p[len - i * 2 - 1]) +
38844cc2045aSjoerg 		    hex_to_dec(p[len - i * 2 - 2]) * 16;
38854cc2045aSjoerg 
38864cc2045aSjoerg 		if (byte < 0 || byte > 255)
38874cc2045aSjoerg 			return (NULL);
38884cc2045aSjoerg 
38894cc2045aSjoerg #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
38904cc2045aSjoerg 		((unsigned char *)&f)[i] = (unsigned char)(byte);
38914cc2045aSjoerg #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
38924cc2045aSjoerg 		((unsigned char *)&f)[sizeof(double) - i - 1] =
38934cc2045aSjoerg 		    (unsigned char)(byte);
38944cc2045aSjoerg #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
38954cc2045aSjoerg 	}
38964cc2045aSjoerg 
38974cc2045aSjoerg 	rtn_len = 64;
38984cc2045aSjoerg 	limit = 0;
38994cc2045aSjoerg again:
39004cc2045aSjoerg 	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
39014cc2045aSjoerg 		return (NULL);
39024cc2045aSjoerg 
39034cc2045aSjoerg 	if (snprintf(rtn, rtn_len, "%fld", f) >= (int)rtn_len) {
39044cc2045aSjoerg 		free(rtn);
39054cc2045aSjoerg 		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
39064cc2045aSjoerg 			return (NULL);
39074cc2045aSjoerg 		rtn_len *= BUFFER_GROWFACTOR;
39084cc2045aSjoerg 		goto again;
39094cc2045aSjoerg 	}
39104cc2045aSjoerg 
39114cc2045aSjoerg 	return rtn;
39124cc2045aSjoerg }
39134cc2045aSjoerg 
39144cc2045aSjoerg static char *
decode_fp_to_float(const char * p,size_t len)39154cc2045aSjoerg decode_fp_to_float(const char *p, size_t len)
39164cc2045aSjoerg {
39174cc2045aSjoerg 	size_t i, rtn_len, limit;
39184cc2045aSjoerg 	float f;
39194cc2045aSjoerg 	int byte;
39204cc2045aSjoerg 	char *rtn;
39214cc2045aSjoerg 
39224cc2045aSjoerg 	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(float))
39234cc2045aSjoerg 		return (NULL);
39244cc2045aSjoerg 
39254cc2045aSjoerg 	memset(&f, 0, sizeof(float));
39264cc2045aSjoerg 
39274cc2045aSjoerg 	for (i = 0; i < len / 2; ++i) {
39284cc2045aSjoerg 		byte = hex_to_dec(p[len - i * 2 - 1]) +
39294cc2045aSjoerg 		    hex_to_dec(p[len - i * 2 - 2]) * 16;
39304cc2045aSjoerg 		if (byte < 0 || byte > 255)
39314cc2045aSjoerg 			return (NULL);
39324cc2045aSjoerg #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
39334cc2045aSjoerg 		((unsigned char *)&f)[i] = (unsigned char)(byte);
39344cc2045aSjoerg #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39354cc2045aSjoerg 		((unsigned char *)&f)[sizeof(float) - i - 1] =
39364cc2045aSjoerg 		    (unsigned char)(byte);
39374cc2045aSjoerg #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39384cc2045aSjoerg 	}
39394cc2045aSjoerg 
39404cc2045aSjoerg 	rtn_len = 64;
39414cc2045aSjoerg 	limit = 0;
39424cc2045aSjoerg again:
39434cc2045aSjoerg 	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
39444cc2045aSjoerg 		return (NULL);
39454cc2045aSjoerg 
39464cc2045aSjoerg 	if (snprintf(rtn, rtn_len, "%ff", f) >= (int)rtn_len) {
39474cc2045aSjoerg 		free(rtn);
39484cc2045aSjoerg 		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
39494cc2045aSjoerg 			return (NULL);
39504cc2045aSjoerg 		rtn_len *= BUFFER_GROWFACTOR;
39514cc2045aSjoerg 		goto again;
39524cc2045aSjoerg 	}
39534cc2045aSjoerg 
39544cc2045aSjoerg 	return rtn;
39554cc2045aSjoerg }
39564cc2045aSjoerg 
39574cc2045aSjoerg static char *
decode_fp_to_float128(const char * p,size_t len)39584cc2045aSjoerg decode_fp_to_float128(const char *p, size_t len)
39594cc2045aSjoerg {
39604cc2045aSjoerg 	long double f;
39614cc2045aSjoerg 	size_t rtn_len, limit, i;
39624cc2045aSjoerg 	int byte;
39634cc2045aSjoerg 	unsigned char buf[FLOAT_QUADRUPLE_BYTES];
39644cc2045aSjoerg 	char *rtn;
39654cc2045aSjoerg 
39664cc2045aSjoerg 	switch(sizeof(long double)) {
39674cc2045aSjoerg 	case FLOAT_QUADRUPLE_BYTES:
39684cc2045aSjoerg 		return (decode_fp_to_long_double(p, len));
39694cc2045aSjoerg 	case FLOAT_EXTENED_BYTES:
39704cc2045aSjoerg 		if (p == NULL || len == 0 || len % 2 != 0 ||
39714cc2045aSjoerg 		    len / 2 > FLOAT_QUADRUPLE_BYTES)
39724cc2045aSjoerg 			return (NULL);
39734cc2045aSjoerg 
39744cc2045aSjoerg 		memset(buf, 0, FLOAT_QUADRUPLE_BYTES);
39754cc2045aSjoerg 
39764cc2045aSjoerg 		for (i = 0; i < len / 2; ++i) {
39774cc2045aSjoerg 			byte = hex_to_dec(p[len - i * 2 - 1]) +
39784cc2045aSjoerg 			    hex_to_dec(p[len - i * 2 - 2]) * 16;
39794cc2045aSjoerg 			if (byte < 0 || byte > 255)
39804cc2045aSjoerg 				return (NULL);
39814cc2045aSjoerg #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
39824cc2045aSjoerg 			buf[i] = (unsigned char)(byte);
39834cc2045aSjoerg #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39844cc2045aSjoerg 			buf[FLOAT_QUADRUPLE_BYTES - i -1] =
39854cc2045aSjoerg 			    (unsigned char)(byte);
39864cc2045aSjoerg #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39874cc2045aSjoerg 		}
39884cc2045aSjoerg 		memset(&f, 0, FLOAT_EXTENED_BYTES);
39894cc2045aSjoerg 
39904cc2045aSjoerg #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
39914cc2045aSjoerg 		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
39924cc2045aSjoerg #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39934cc2045aSjoerg 		memcpy(&f, buf + 6, FLOAT_EXTENED_BYTES);
39944cc2045aSjoerg #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
39954cc2045aSjoerg 
39964cc2045aSjoerg 		rtn_len = 256;
39974cc2045aSjoerg 		limit = 0;
39984cc2045aSjoerg again:
39994cc2045aSjoerg 		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
40004cc2045aSjoerg 			return (NULL);
40014cc2045aSjoerg 
40024cc2045aSjoerg 		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
40034cc2045aSjoerg 			free(rtn);
40044cc2045aSjoerg 			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
40054cc2045aSjoerg 				return (NULL);
40064cc2045aSjoerg 			rtn_len *= BUFFER_GROWFACTOR;
40074cc2045aSjoerg 			goto again;
40084cc2045aSjoerg 		}
40094cc2045aSjoerg 
40104cc2045aSjoerg 		return (rtn);
40114cc2045aSjoerg 	default:
40124cc2045aSjoerg 		return (NULL);
40134cc2045aSjoerg 	}
40144cc2045aSjoerg }
40154cc2045aSjoerg 
40164cc2045aSjoerg static char *
decode_fp_to_float80(const char * p,size_t len)40174cc2045aSjoerg decode_fp_to_float80(const char *p, size_t len)
40184cc2045aSjoerg {
40194cc2045aSjoerg 	long double f;
40204cc2045aSjoerg 	size_t rtn_len, limit, i;
40214cc2045aSjoerg 	int byte;
40224cc2045aSjoerg 	unsigned char buf[FLOAT_EXTENED_BYTES];
40234cc2045aSjoerg 	char *rtn;
40244cc2045aSjoerg 
40254cc2045aSjoerg 	switch(sizeof(long double)) {
40264cc2045aSjoerg 	case FLOAT_QUADRUPLE_BYTES:
40274cc2045aSjoerg 		if (p == NULL || len == 0 || len % 2 != 0 ||
40284cc2045aSjoerg 		    len / 2 > FLOAT_EXTENED_BYTES)
40294cc2045aSjoerg 			return (NULL);
40304cc2045aSjoerg 
40314cc2045aSjoerg 		memset(buf, 0, FLOAT_EXTENED_BYTES);
40324cc2045aSjoerg 
40334cc2045aSjoerg 		for (i = 0; i < len / 2; ++i) {
40344cc2045aSjoerg 			byte = hex_to_dec(p[len - i * 2 - 1]) +
40354cc2045aSjoerg 			    hex_to_dec(p[len - i * 2 - 2]) * 16;
40364cc2045aSjoerg 
40374cc2045aSjoerg 			if (byte < 0 || byte > 255)
40384cc2045aSjoerg 				return (NULL);
40394cc2045aSjoerg 
40404cc2045aSjoerg #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
40414cc2045aSjoerg 			buf[i] = (unsigned char)(byte);
40424cc2045aSjoerg #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40434cc2045aSjoerg 			buf[FLOAT_EXTENED_BYTES - i -1] =
40444cc2045aSjoerg 			    (unsigned char)(byte);
40454cc2045aSjoerg #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40464cc2045aSjoerg 		}
40474cc2045aSjoerg 
4048*d678c5d4Sjoerg 		memset(&f, 0, FLOAT_QUADRUPLE_BYTES);
40494cc2045aSjoerg 
40504cc2045aSjoerg #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
40514cc2045aSjoerg 		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
40524cc2045aSjoerg #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40534cc2045aSjoerg 		memcpy((unsigned char *)(&f) + 6, buf, FLOAT_EXTENED_BYTES);
40544cc2045aSjoerg #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
40554cc2045aSjoerg 
40564cc2045aSjoerg 		rtn_len = 256;
40574cc2045aSjoerg 		limit = 0;
40584cc2045aSjoerg again:
40594cc2045aSjoerg 		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
40604cc2045aSjoerg 			return (NULL);
40614cc2045aSjoerg 
40624cc2045aSjoerg 		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
40634cc2045aSjoerg 			free(rtn);
40644cc2045aSjoerg 			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
40654cc2045aSjoerg 				return (NULL);
40664cc2045aSjoerg 			rtn_len *= BUFFER_GROWFACTOR;
40674cc2045aSjoerg 			goto again;
40684cc2045aSjoerg 		}
40694cc2045aSjoerg 
40704cc2045aSjoerg 		return (rtn);
40714cc2045aSjoerg 	case FLOAT_EXTENED_BYTES:
40724cc2045aSjoerg 		return (decode_fp_to_long_double(p, len));
40734cc2045aSjoerg 	default:
40744cc2045aSjoerg 		return (NULL);
40754cc2045aSjoerg 	}
40764cc2045aSjoerg }
40774cc2045aSjoerg 
40784cc2045aSjoerg static char *
decode_fp_to_long_double(const char * p,size_t len)40794cc2045aSjoerg decode_fp_to_long_double(const char *p, size_t len)
40804cc2045aSjoerg {
40814cc2045aSjoerg 	long double f;
40824cc2045aSjoerg 	size_t rtn_len, limit, i;
40834cc2045aSjoerg 	int byte;
40844cc2045aSjoerg 	char *rtn;
40854cc2045aSjoerg 
40864cc2045aSjoerg 	if (p == NULL || len == 0 || len % 2 != 0 ||
40874cc2045aSjoerg 	    len / 2 > sizeof(long double))
40884cc2045aSjoerg 		return (NULL);
40894cc2045aSjoerg 
40904cc2045aSjoerg 	memset(&f, 0, sizeof(long double));
40914cc2045aSjoerg 
40924cc2045aSjoerg 	for (i = 0; i < len / 2; ++i) {
40934cc2045aSjoerg 		byte = hex_to_dec(p[len - i * 2 - 1]) +
40944cc2045aSjoerg 		    hex_to_dec(p[len - i * 2 - 2]) * 16;
40954cc2045aSjoerg 
40964cc2045aSjoerg 		if (byte < 0 || byte > 255)
40974cc2045aSjoerg 			return (NULL);
40984cc2045aSjoerg 
40994cc2045aSjoerg #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
41004cc2045aSjoerg 		((unsigned char *)&f)[i] = (unsigned char)(byte);
41014cc2045aSjoerg #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
41024cc2045aSjoerg 		((unsigned char *)&f)[sizeof(long double) - i - 1] =
41034cc2045aSjoerg 		    (unsigned char)(byte);
41044cc2045aSjoerg #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
41054cc2045aSjoerg 	}
41064cc2045aSjoerg 
41074cc2045aSjoerg 	rtn_len = 256;
41084cc2045aSjoerg 	limit = 0;
41094cc2045aSjoerg again:
41104cc2045aSjoerg 	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
41114cc2045aSjoerg 		return (NULL);
41124cc2045aSjoerg 
41134cc2045aSjoerg 	if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
41144cc2045aSjoerg 		free(rtn);
41154cc2045aSjoerg 		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
41164cc2045aSjoerg 			return (NULL);
41174cc2045aSjoerg 		rtn_len *= BUFFER_GROWFACTOR;
41184cc2045aSjoerg 		goto again;
41194cc2045aSjoerg 	}
41204cc2045aSjoerg 
41214cc2045aSjoerg 	return (rtn);
41224cc2045aSjoerg }
41234cc2045aSjoerg 
41244cc2045aSjoerg /* Simple hex to integer function used by decode_to_* function. */
41254cc2045aSjoerg static int
hex_to_dec(char c)41264cc2045aSjoerg hex_to_dec(char c)
41274cc2045aSjoerg {
41284cc2045aSjoerg 
41294cc2045aSjoerg 	switch (c) {
41304cc2045aSjoerg 	case '0':
41314cc2045aSjoerg 		return (0);
41324cc2045aSjoerg 	case '1':
41334cc2045aSjoerg 		return (1);
41344cc2045aSjoerg 	case '2':
41354cc2045aSjoerg 		return (2);
41364cc2045aSjoerg 	case '3':
41374cc2045aSjoerg 		return (3);
41384cc2045aSjoerg 	case '4':
41394cc2045aSjoerg 		return (4);
41404cc2045aSjoerg 	case '5':
41414cc2045aSjoerg 		return (5);
41424cc2045aSjoerg 	case '6':
41434cc2045aSjoerg 		return (6);
41444cc2045aSjoerg 	case '7':
41454cc2045aSjoerg 		return (7);
41464cc2045aSjoerg 	case '8':
41474cc2045aSjoerg 		return (8);
41484cc2045aSjoerg 	case '9':
41494cc2045aSjoerg 		return (9);
41504cc2045aSjoerg 	case 'a':
41514cc2045aSjoerg 		return (10);
41524cc2045aSjoerg 	case 'b':
41534cc2045aSjoerg 		return (11);
41544cc2045aSjoerg 	case 'c':
41554cc2045aSjoerg 		return (12);
41564cc2045aSjoerg 	case 'd':
41574cc2045aSjoerg 		return (13);
41584cc2045aSjoerg 	case 'e':
41594cc2045aSjoerg 		return (14);
41604cc2045aSjoerg 	case 'f':
41614cc2045aSjoerg 		return (15);
41624cc2045aSjoerg 	default:
41634cc2045aSjoerg 		return (-1);
4164*d678c5d4Sjoerg 	}
4165*d678c5d4Sjoerg }
4166*d678c5d4Sjoerg 
4167*d678c5d4Sjoerg /**
4168*d678c5d4Sjoerg  * @brief Test input string is mangled by IA-64 C++ ABI style.
4169*d678c5d4Sjoerg  *
4170*d678c5d4Sjoerg  * Test string heads with "_Z" or "_GLOBAL__I_".
4171*d678c5d4Sjoerg  * @return Return 0 at false.
4172*d678c5d4Sjoerg  */
4173*d678c5d4Sjoerg bool
is_cpp_mangled_gnu3(const char * org)4174*d678c5d4Sjoerg is_cpp_mangled_gnu3(const char *org)
4175*d678c5d4Sjoerg {
4176*d678c5d4Sjoerg 	size_t len;
4177*d678c5d4Sjoerg 
4178*d678c5d4Sjoerg 	len = strlen(org);
4179*d678c5d4Sjoerg 	return ((len > 2 && *org == '_' && *(org + 1) == 'Z') ||
4180*d678c5d4Sjoerg 	    (len > 11 && !strncmp(org, "_GLOBAL__I_", 11)));
41814cc2045aSjoerg }
41824cc2045aSjoerg 
41834cc2045aSjoerg static void
vector_read_cmd_dest(struct vector_read_cmd * v)41844cc2045aSjoerg vector_read_cmd_dest(struct vector_read_cmd *v)
41854cc2045aSjoerg {
41864cc2045aSjoerg 
41874cc2045aSjoerg 	if (v == NULL)
41884cc2045aSjoerg 		return;
41894cc2045aSjoerg 
41904cc2045aSjoerg 	free(v->r_container);
41914cc2045aSjoerg }
41924cc2045aSjoerg 
4193*d678c5d4Sjoerg static struct read_cmd_item *
vector_read_cmd_find(struct vector_read_cmd * v,enum read_cmd dst)41944cc2045aSjoerg vector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst)
41954cc2045aSjoerg {
4196*d678c5d4Sjoerg 	int i;
41974cc2045aSjoerg 
41984cc2045aSjoerg 	if (v == NULL || dst == READ_FAIL)
4199*d678c5d4Sjoerg 		return (NULL);
42004cc2045aSjoerg 
4201*d678c5d4Sjoerg 	for (i = (int) v->size - 1; i >= 0; i--)
4202*d678c5d4Sjoerg 		if (v->r_container[i].cmd == dst)
4203*d678c5d4Sjoerg 			return (&v->r_container[i]);
42044cc2045aSjoerg 
4205*d678c5d4Sjoerg 	return (NULL);
42064cc2045aSjoerg }
42074cc2045aSjoerg 
42084cc2045aSjoerg static int
vector_read_cmd_init(struct vector_read_cmd * v)42094cc2045aSjoerg vector_read_cmd_init(struct vector_read_cmd *v)
42104cc2045aSjoerg {
42114cc2045aSjoerg 
42124cc2045aSjoerg 	if (v == NULL)
42134cc2045aSjoerg 		return (0);
42144cc2045aSjoerg 
42154cc2045aSjoerg 	v->size = 0;
42164cc2045aSjoerg 	v->capacity = VECTOR_DEF_CAPACITY;
42174cc2045aSjoerg 
4218*d678c5d4Sjoerg 	if ((v->r_container = malloc(sizeof(*v->r_container) * v->capacity))
42194cc2045aSjoerg 	    == NULL)
42204cc2045aSjoerg 		return (0);
42214cc2045aSjoerg 
42224cc2045aSjoerg 	return (1);
42234cc2045aSjoerg }
42244cc2045aSjoerg 
42254cc2045aSjoerg static int
vector_read_cmd_pop(struct vector_read_cmd * v)42264cc2045aSjoerg vector_read_cmd_pop(struct vector_read_cmd *v)
42274cc2045aSjoerg {
42284cc2045aSjoerg 
42294cc2045aSjoerg 	if (v == NULL || v->size == 0)
42304cc2045aSjoerg 		return (0);
42314cc2045aSjoerg 
42324cc2045aSjoerg 	--v->size;
4233*d678c5d4Sjoerg 	v->r_container[v->size].cmd = READ_FAIL;
4234*d678c5d4Sjoerg 	v->r_container[v->size].data = NULL;
42354cc2045aSjoerg 
42364cc2045aSjoerg 	return (1);
42374cc2045aSjoerg }
42384cc2045aSjoerg 
42394cc2045aSjoerg static int
vector_read_cmd_push(struct vector_read_cmd * v,enum read_cmd cmd,void * data)4240*d678c5d4Sjoerg vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd, void *data)
42414cc2045aSjoerg {
4242*d678c5d4Sjoerg 	struct read_cmd_item *tmp_r_ctn;
42434cc2045aSjoerg 	size_t tmp_cap;
42444cc2045aSjoerg 	size_t i;
42454cc2045aSjoerg 
42464cc2045aSjoerg 	if (v == NULL)
42474cc2045aSjoerg 		return (0);
42484cc2045aSjoerg 
42494cc2045aSjoerg 	if (v->size == v->capacity) {
4250*d678c5d4Sjoerg 		tmp_cap = BUFFER_GROW(v->capacity);
4251*d678c5d4Sjoerg 		if ((tmp_r_ctn = malloc(sizeof(*tmp_r_ctn) * tmp_cap)) == NULL)
42524cc2045aSjoerg 			return (0);
42534cc2045aSjoerg 		for (i = 0; i < v->size; ++i)
42544cc2045aSjoerg 			tmp_r_ctn[i] = v->r_container[i];
42554cc2045aSjoerg 		free(v->r_container);
42564cc2045aSjoerg 		v->r_container = tmp_r_ctn;
42574cc2045aSjoerg 		v->capacity = tmp_cap;
42584cc2045aSjoerg 	}
42594cc2045aSjoerg 
4260*d678c5d4Sjoerg 	v->r_container[v->size].cmd = cmd;
4261*d678c5d4Sjoerg 	v->r_container[v->size].data = data;
42624cc2045aSjoerg 	++v->size;
42634cc2045aSjoerg 
42644cc2045aSjoerg 	return (1);
42654cc2045aSjoerg }
42664cc2045aSjoerg 
42674cc2045aSjoerg static void
vector_type_qualifier_dest(struct vector_type_qualifier * v)42684cc2045aSjoerg vector_type_qualifier_dest(struct vector_type_qualifier *v)
42694cc2045aSjoerg {
42704cc2045aSjoerg 
42714cc2045aSjoerg 	if (v == NULL)
42724cc2045aSjoerg 		return;
42734cc2045aSjoerg 
42744cc2045aSjoerg 	free(v->q_container);
42754cc2045aSjoerg 	vector_str_dest(&v->ext_name);
42764cc2045aSjoerg }
42774cc2045aSjoerg 
42784cc2045aSjoerg /* size, capacity, ext_name */
42794cc2045aSjoerg static int
vector_type_qualifier_init(struct vector_type_qualifier * v)42804cc2045aSjoerg vector_type_qualifier_init(struct vector_type_qualifier *v)
42814cc2045aSjoerg {
42824cc2045aSjoerg 
42834cc2045aSjoerg 	if (v == NULL)
42844cc2045aSjoerg 		return (0);
42854cc2045aSjoerg 
42864cc2045aSjoerg 	v->size = 0;
42874cc2045aSjoerg 	v->capacity = VECTOR_DEF_CAPACITY;
42884cc2045aSjoerg 
42894cc2045aSjoerg 	if ((v->q_container = malloc(sizeof(enum type_qualifier) * v->capacity))
42904cc2045aSjoerg 	    == NULL)
42914cc2045aSjoerg 		return (0);
42924cc2045aSjoerg 
42934cc2045aSjoerg 	assert(v->q_container != NULL);
42944cc2045aSjoerg 
4295*d678c5d4Sjoerg 	if (!vector_str_init(&v->ext_name)) {
42964cc2045aSjoerg 		free(v->q_container);
42974cc2045aSjoerg 		return (0);
42984cc2045aSjoerg 	}
42994cc2045aSjoerg 
43004cc2045aSjoerg 	return (1);
43014cc2045aSjoerg }
43024cc2045aSjoerg 
43034cc2045aSjoerg static int
vector_type_qualifier_push(struct vector_type_qualifier * v,enum type_qualifier t)43044cc2045aSjoerg vector_type_qualifier_push(struct vector_type_qualifier *v,
43054cc2045aSjoerg     enum type_qualifier t)
43064cc2045aSjoerg {
43074cc2045aSjoerg 	enum type_qualifier *tmp_ctn;
43084cc2045aSjoerg 	size_t tmp_cap;
43094cc2045aSjoerg 	size_t i;
43104cc2045aSjoerg 
43114cc2045aSjoerg 	if (v == NULL)
43124cc2045aSjoerg 		return (0);
43134cc2045aSjoerg 
43144cc2045aSjoerg 	if (v->size == v->capacity) {
4315*d678c5d4Sjoerg 		tmp_cap = BUFFER_GROW(v->capacity);
43164cc2045aSjoerg 		if ((tmp_ctn = malloc(sizeof(enum type_qualifier) * tmp_cap))
43174cc2045aSjoerg 		    == NULL)
43184cc2045aSjoerg 			return (0);
43194cc2045aSjoerg 		for (i = 0; i < v->size; ++i)
43204cc2045aSjoerg 			tmp_ctn[i] = v->q_container[i];
43214cc2045aSjoerg 		free(v->q_container);
43224cc2045aSjoerg 		v->q_container = tmp_ctn;
43234cc2045aSjoerg 		v->capacity = tmp_cap;
43244cc2045aSjoerg 	}
43254cc2045aSjoerg 
43264cc2045aSjoerg 	v->q_container[v->size] = t;
43274cc2045aSjoerg 	++v->size;
43284cc2045aSjoerg 
43294cc2045aSjoerg 	return (1);
43304cc2045aSjoerg }
4331