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