1a85fe12eSEd Maste /*-
2a85fe12eSEd Maste  * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
318f4c9dbSEd Maste  * Copyright (c) 2015-2017 Kai Wang <kaiwang27@gmail.com>
4a85fe12eSEd Maste  * All rights reserved.
5a85fe12eSEd Maste  *
6a85fe12eSEd Maste  * Redistribution and use in source and binary forms, with or without
7a85fe12eSEd Maste  * modification, are permitted provided that the following conditions
8a85fe12eSEd Maste  * are met:
9a85fe12eSEd Maste  * 1. Redistributions of source code must retain the above copyright
10a85fe12eSEd Maste  *    notice, this list of conditions and the following disclaimer
11a85fe12eSEd Maste  *    in this position and unchanged.
12a85fe12eSEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
13a85fe12eSEd Maste  *    notice, this list of conditions and the following disclaimer in the
14a85fe12eSEd Maste  *    documentation and/or other materials provided with the distribution.
15a85fe12eSEd Maste  *
16a85fe12eSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17a85fe12eSEd Maste  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18a85fe12eSEd Maste  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19a85fe12eSEd Maste  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20a85fe12eSEd Maste  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21a85fe12eSEd Maste  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22a85fe12eSEd Maste  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23a85fe12eSEd Maste  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24a85fe12eSEd Maste  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25a85fe12eSEd Maste  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26a85fe12eSEd Maste  */
27a85fe12eSEd Maste #include <sys/types.h>
28a85fe12eSEd Maste #include <assert.h>
29a85fe12eSEd Maste #include <ctype.h>
30a85fe12eSEd Maste #include <errno.h>
31a85fe12eSEd Maste #include <libelftc.h>
32a85fe12eSEd Maste #include <limits.h>
33a85fe12eSEd Maste #include <stdbool.h>
34a85fe12eSEd Maste #include <stdio.h>
35a85fe12eSEd Maste #include <stdlib.h>
36a85fe12eSEd Maste #include <string.h>
37a85fe12eSEd Maste 
38a85fe12eSEd Maste #include "_libelftc.h"
39a85fe12eSEd Maste 
40715d1396SEd Maste ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3583 2017-10-15 15:38:47Z emaste $");
41a85fe12eSEd Maste 
42a85fe12eSEd Maste /**
43a85fe12eSEd Maste  * @file cpp_demangle.c
44a85fe12eSEd Maste  * @brief Decode IA-64 C++ ABI style implementation.
45a85fe12eSEd Maste  *
46a85fe12eSEd Maste  * IA-64 standard ABI(Itanium C++ ABI) references.
47a85fe12eSEd Maste  *
48a85fe12eSEd Maste  * http://www.codesourcery.com/cxx-abi/abi.html#mangling \n
49a85fe12eSEd Maste  * http://www.codesourcery.com/cxx-abi/abi-mangling.html
50a85fe12eSEd Maste  */
51a85fe12eSEd Maste 
52a85fe12eSEd Maste enum type_qualifier {
53a85fe12eSEd Maste 	TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
5418f4c9dbSEd Maste 	TYPE_CST, TYPE_VEC, TYPE_RREF
55a85fe12eSEd Maste };
56a85fe12eSEd Maste 
57a85fe12eSEd Maste struct vector_type_qualifier {
58a85fe12eSEd Maste 	size_t size, capacity;
59a85fe12eSEd Maste 	enum type_qualifier *q_container;
60a85fe12eSEd Maste 	struct vector_str ext_name;
61a85fe12eSEd Maste };
62a85fe12eSEd Maste 
63a85fe12eSEd Maste enum read_cmd {
64a85fe12eSEd Maste 	READ_FAIL, READ_NEST, READ_TMPL, READ_EXPR, READ_EXPL, READ_LOCAL,
65a85fe12eSEd Maste 	READ_TYPE, READ_FUNC, READ_PTRMEM
66a85fe12eSEd Maste };
67a85fe12eSEd Maste 
6818f4c9dbSEd Maste struct read_cmd_item {
6918f4c9dbSEd Maste 	enum read_cmd cmd;
7018f4c9dbSEd Maste 	void *data;
7118f4c9dbSEd Maste };
7218f4c9dbSEd Maste 
73a85fe12eSEd Maste struct vector_read_cmd {
74a85fe12eSEd Maste 	size_t size, capacity;
7518f4c9dbSEd Maste 	struct read_cmd_item *r_container;
7618f4c9dbSEd Maste };
7718f4c9dbSEd Maste 
7818f4c9dbSEd Maste enum push_qualifier {
7918f4c9dbSEd Maste 	PUSH_ALL_QUALIFIER,
8018f4c9dbSEd Maste 	PUSH_CV_QUALIFIER,
8118f4c9dbSEd Maste 	PUSH_NON_CV_QUALIFIER,
82a85fe12eSEd Maste };
83a85fe12eSEd Maste 
84a85fe12eSEd Maste struct cpp_demangle_data {
85a85fe12eSEd Maste 	struct vector_str	 output;	/* output string vector */
86a85fe12eSEd Maste 	struct vector_str	 subst;		/* substitution string vector */
87a85fe12eSEd Maste 	struct vector_str	 tmpl;
88a85fe12eSEd Maste 	struct vector_str	 class_type;
8918f4c9dbSEd Maste 	struct vector_str	*cur_output;	/* ptr to current output vec */
90a85fe12eSEd Maste 	struct vector_read_cmd	 cmd;
91a85fe12eSEd Maste 	bool			 mem_rst;	/* restrict member function */
92a85fe12eSEd Maste 	bool			 mem_vat;	/* volatile member function */
93a85fe12eSEd Maste 	bool			 mem_cst;	/* const member function */
9418f4c9dbSEd Maste 	bool			 mem_ref;	/* lvalue-ref member func */
9518f4c9dbSEd Maste 	bool			 mem_rref;	/* rvalue-ref member func */
9618f4c9dbSEd Maste 	bool			 is_tmpl;	/* template args */
9718f4c9dbSEd Maste 	bool			 is_functype;	/* function type */
9818f4c9dbSEd Maste 	bool			 ref_qualifier; /* ref qualifier */
9918f4c9dbSEd Maste 	enum type_qualifier	 ref_qualifier_type; /* ref qualifier type */
10018f4c9dbSEd Maste 	enum push_qualifier	 push_qualifier; /* which qualifiers to push */
101a85fe12eSEd Maste 	int			 func_type;
102a85fe12eSEd Maste 	const char		*cur;		/* current mangled name ptr */
103a85fe12eSEd Maste 	const char		*last_sname;	/* last source name */
10418f4c9dbSEd Maste };
10518f4c9dbSEd Maste 
10618f4c9dbSEd Maste struct type_delimit {
10718f4c9dbSEd Maste 	bool paren;
10818f4c9dbSEd Maste 	bool firstp;
109a85fe12eSEd Maste };
110a85fe12eSEd Maste 
111a85fe12eSEd Maste #define	CPP_DEMANGLE_TRY_LIMIT	128
112a85fe12eSEd Maste #define	FLOAT_SPRINTF_TRY_LIMIT	5
113a85fe12eSEd Maste #define	FLOAT_QUADRUPLE_BYTES	16
114a85fe12eSEd Maste #define	FLOAT_EXTENED_BYTES	10
115a85fe12eSEd Maste 
116a85fe12eSEd Maste #define SIMPLE_HASH(x,y)	(64 * x + y)
117bee2765cSEd Maste #define DEM_PUSH_STR(d,s)	cpp_demangle_push_str((d), (s), strlen((s)))
118bee2765cSEd Maste #define VEC_PUSH_STR(d,s)	vector_str_push((d), (s), strlen((s)))
119a85fe12eSEd Maste 
120a85fe12eSEd Maste static void	cpp_demangle_data_dest(struct cpp_demangle_data *);
121a85fe12eSEd Maste static int	cpp_demangle_data_init(struct cpp_demangle_data *,
122a85fe12eSEd Maste 		    const char *);
123a85fe12eSEd Maste static int	cpp_demangle_get_subst(struct cpp_demangle_data *, size_t);
124a85fe12eSEd Maste static int	cpp_demangle_get_tmpl_param(struct cpp_demangle_data *, size_t);
125a85fe12eSEd Maste static int	cpp_demangle_push_fp(struct cpp_demangle_data *,
126a85fe12eSEd Maste 		    char *(*)(const char *, size_t));
127a85fe12eSEd Maste static int	cpp_demangle_push_str(struct cpp_demangle_data *, const char *,
128a85fe12eSEd Maste 		    size_t);
12918f4c9dbSEd Maste static int	cpp_demangle_pop_str(struct cpp_demangle_data *);
130a85fe12eSEd Maste static int	cpp_demangle_push_subst(struct cpp_demangle_data *,
131a85fe12eSEd Maste 		    const char *, size_t);
132a85fe12eSEd Maste static int	cpp_demangle_push_subst_v(struct cpp_demangle_data *,
133a85fe12eSEd Maste 		    struct vector_str *);
134a85fe12eSEd Maste static int	cpp_demangle_push_type_qualifier(struct cpp_demangle_data *,
135a85fe12eSEd Maste 		    struct vector_type_qualifier *, const char *);
136a85fe12eSEd Maste static int	cpp_demangle_read_array(struct cpp_demangle_data *);
137a85fe12eSEd Maste static int	cpp_demangle_read_encoding(struct cpp_demangle_data *);
138a85fe12eSEd Maste static int	cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
139a85fe12eSEd Maste static int	cpp_demangle_read_expression(struct cpp_demangle_data *);
1403ef90571SEd Maste static int	cpp_demangle_read_expression_flat(struct cpp_demangle_data *,
1413ef90571SEd Maste 		    char **);
142a85fe12eSEd Maste static int	cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
143a85fe12eSEd Maste 		    const char *, size_t);
144a85fe12eSEd Maste static int	cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
145a85fe12eSEd Maste 		    const char *, size_t);
146a85fe12eSEd Maste static int	cpp_demangle_read_expression_trinary(struct cpp_demangle_data *,
147a85fe12eSEd Maste 		    const char *, size_t, const char *, size_t);
148a85fe12eSEd Maste static int	cpp_demangle_read_function(struct cpp_demangle_data *, int *,
149a85fe12eSEd Maste 		    struct vector_type_qualifier *);
150a85fe12eSEd Maste static int	cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
151a85fe12eSEd Maste static int	cpp_demangle_read_local_name(struct cpp_demangle_data *);
152a85fe12eSEd Maste static int	cpp_demangle_read_name(struct cpp_demangle_data *);
1533ef90571SEd Maste static int	cpp_demangle_read_name_flat(struct cpp_demangle_data *,
1543ef90571SEd Maste 		    char**);
155a85fe12eSEd Maste static int	cpp_demangle_read_nested_name(struct cpp_demangle_data *);
156a85fe12eSEd Maste static int	cpp_demangle_read_number(struct cpp_demangle_data *, long *);
1573ef90571SEd Maste static int	cpp_demangle_read_number_as_string(struct cpp_demangle_data *,
1583ef90571SEd Maste 		    char **);
159a85fe12eSEd Maste static int	cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
160a85fe12eSEd Maste static int	cpp_demangle_read_offset(struct cpp_demangle_data *);
161a85fe12eSEd Maste static int	cpp_demangle_read_offset_number(struct cpp_demangle_data *);
16218f4c9dbSEd Maste static int	cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *,
16318f4c9dbSEd Maste 		    struct vector_type_qualifier *);
164a85fe12eSEd Maste static int	cpp_demangle_read_sname(struct cpp_demangle_data *);
165a85fe12eSEd Maste static int	cpp_demangle_read_subst(struct cpp_demangle_data *);
166a85fe12eSEd Maste static int	cpp_demangle_read_subst_std(struct cpp_demangle_data *);
167a85fe12eSEd Maste static int	cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *,
16818f4c9dbSEd Maste 		    const char *);
169a85fe12eSEd Maste static int	cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
170a85fe12eSEd Maste static int	cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
171a85fe12eSEd Maste static int	cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
17218f4c9dbSEd Maste static int	cpp_demangle_read_type(struct cpp_demangle_data *,
17318f4c9dbSEd Maste 		    struct type_delimit *);
1743ef90571SEd Maste static int	cpp_demangle_read_type_flat(struct cpp_demangle_data *,
1753ef90571SEd Maste 		    char **);
176a85fe12eSEd Maste static int	cpp_demangle_read_uqname(struct cpp_demangle_data *);
177a85fe12eSEd Maste static int	cpp_demangle_read_v_offset(struct cpp_demangle_data *);
178a85fe12eSEd Maste static char	*decode_fp_to_double(const char *, size_t);
179a85fe12eSEd Maste static char	*decode_fp_to_float(const char *, size_t);
180a85fe12eSEd Maste static char	*decode_fp_to_float128(const char *, size_t);
181a85fe12eSEd Maste static char	*decode_fp_to_float80(const char *, size_t);
182a85fe12eSEd Maste static char	*decode_fp_to_long_double(const char *, size_t);
183a85fe12eSEd Maste static int	hex_to_dec(char);
184a85fe12eSEd Maste static void	vector_read_cmd_dest(struct vector_read_cmd *);
18518f4c9dbSEd Maste static struct read_cmd_item *vector_read_cmd_find(struct vector_read_cmd *,
18618f4c9dbSEd Maste 		    enum read_cmd);
187a85fe12eSEd Maste static int	vector_read_cmd_init(struct vector_read_cmd *);
188a85fe12eSEd Maste static int	vector_read_cmd_pop(struct vector_read_cmd *);
18918f4c9dbSEd Maste static int	vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd,
19018f4c9dbSEd Maste 		    void *);
191a85fe12eSEd Maste static void	vector_type_qualifier_dest(struct vector_type_qualifier *);
192a85fe12eSEd Maste static int	vector_type_qualifier_init(struct vector_type_qualifier *);
193a85fe12eSEd Maste static int	vector_type_qualifier_push(struct vector_type_qualifier *,
194a85fe12eSEd Maste 		    enum type_qualifier);
195a85fe12eSEd Maste 
196a85fe12eSEd Maste /**
197a85fe12eSEd Maste  * @brief Decode the input string by IA-64 C++ ABI style.
198a85fe12eSEd Maste  *
199a85fe12eSEd Maste  * GNU GCC v3 use IA-64 standard ABI.
200a85fe12eSEd Maste  * @return New allocated demangled string or NULL if failed.
201a85fe12eSEd Maste  * @todo 1. Testing and more test case. 2. Code cleaning.
202a85fe12eSEd Maste  */
203a85fe12eSEd Maste char *
cpp_demangle_gnu3(const char * org)204a85fe12eSEd Maste cpp_demangle_gnu3(const char *org)
205a85fe12eSEd Maste {
206a85fe12eSEd Maste 	struct cpp_demangle_data ddata;
20718f4c9dbSEd Maste 	struct vector_str ret_type;
20818f4c9dbSEd Maste 	struct type_delimit td;
209a85fe12eSEd Maste 	ssize_t org_len;
210a85fe12eSEd Maste 	unsigned int limit;
211a85fe12eSEd Maste 	char *rtn;
21218f4c9dbSEd Maste 	bool has_ret, more_type;
213a85fe12eSEd Maste 
214a85fe12eSEd Maste 	if (org == NULL || (org_len = strlen(org)) < 2)
215a85fe12eSEd Maste 		return (NULL);
216a85fe12eSEd Maste 
217a85fe12eSEd Maste 	if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) {
218a85fe12eSEd Maste 		if ((rtn = malloc(org_len + 19)) == NULL)
219a85fe12eSEd Maste 			return (NULL);
220a85fe12eSEd Maste 		snprintf(rtn, org_len + 19,
221a85fe12eSEd Maste 		    "global constructors keyed to %s", org + 11);
222a85fe12eSEd Maste 		return (rtn);
223a85fe12eSEd Maste 	}
224a85fe12eSEd Maste 
225a85fe12eSEd Maste 	if (org[0] != '_' || org[1] != 'Z')
226a85fe12eSEd Maste 		return (NULL);
227a85fe12eSEd Maste 
228a85fe12eSEd Maste 	if (!cpp_demangle_data_init(&ddata, org + 2))
229a85fe12eSEd Maste 		return (NULL);
230a85fe12eSEd Maste 
231a85fe12eSEd Maste 	rtn = NULL;
23218f4c9dbSEd Maste 	has_ret = more_type = false;
233a85fe12eSEd Maste 
234a85fe12eSEd Maste 	if (!cpp_demangle_read_encoding(&ddata))
235a85fe12eSEd Maste 		goto clean;
236a85fe12eSEd Maste 
23718f4c9dbSEd Maste 	/*
23818f4c9dbSEd Maste 	 * Pop function name from substitution candidate list.
23918f4c9dbSEd Maste 	 */
24018f4c9dbSEd Maste 	if (*ddata.cur != 0 && ddata.subst.size >= 1) {
24118f4c9dbSEd Maste 		if (!vector_str_pop(&ddata.subst))
24218f4c9dbSEd Maste 			goto clean;
24318f4c9dbSEd Maste 	}
24418f4c9dbSEd Maste 
24518f4c9dbSEd Maste 	td.paren = false;
24618f4c9dbSEd Maste 	td.firstp = true;
247a85fe12eSEd Maste 	limit = 0;
24818f4c9dbSEd Maste 
24918f4c9dbSEd Maste 	/*
25018f4c9dbSEd Maste 	 * The first type is a return type if we just demangled template
25118f4c9dbSEd Maste 	 * args. (the template args is right next to the function name,
25218f4c9dbSEd Maste 	 * which means it's a template function)
25318f4c9dbSEd Maste 	 */
25418f4c9dbSEd Maste 	if (ddata.is_tmpl) {
25518f4c9dbSEd Maste 		ddata.is_tmpl = false;
25618f4c9dbSEd Maste 		if (!vector_str_init(&ret_type))
25718f4c9dbSEd Maste 			goto clean;
25818f4c9dbSEd Maste 		ddata.cur_output = &ret_type;
25918f4c9dbSEd Maste 		has_ret = true;
26018f4c9dbSEd Maste 	}
26118f4c9dbSEd Maste 
262a85fe12eSEd Maste 	while (*ddata.cur != '\0') {
263a85fe12eSEd Maste 		/*
264a85fe12eSEd Maste 		 * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4
265a85fe12eSEd Maste 		 */
266a85fe12eSEd Maste 		if (*ddata.cur == '@' && *(ddata.cur + 1) == '@')
267a85fe12eSEd Maste 			break;
26818f4c9dbSEd Maste 
26918f4c9dbSEd Maste 		if (has_ret) {
27018f4c9dbSEd Maste 			/* Read return type */
27118f4c9dbSEd Maste 			if (!cpp_demangle_read_type(&ddata, NULL))
272a85fe12eSEd Maste 				goto clean;
27318f4c9dbSEd Maste 		} else {
27418f4c9dbSEd Maste 			/* Read function arg type */
27518f4c9dbSEd Maste 			if (!cpp_demangle_read_type(&ddata, &td))
276a85fe12eSEd Maste 				goto clean;
277a85fe12eSEd Maste 		}
278a85fe12eSEd Maste 
27918f4c9dbSEd Maste 		if (has_ret) {
28018f4c9dbSEd Maste 			/* Push return type to the beginning */
28118f4c9dbSEd Maste 			if (!VEC_PUSH_STR(&ret_type, " "))
28218f4c9dbSEd Maste 				goto clean;
28318f4c9dbSEd Maste 			if (!vector_str_push_vector_head(&ddata.output,
28418f4c9dbSEd Maste 			    &ret_type))
28518f4c9dbSEd Maste 				goto clean;
28618f4c9dbSEd Maste 			ddata.cur_output = &ddata.output;
28718f4c9dbSEd Maste 			vector_str_dest(&ret_type);
28818f4c9dbSEd Maste 			has_ret = false;
28918f4c9dbSEd Maste 			more_type = true;
29018f4c9dbSEd Maste 		} else if (more_type)
29118f4c9dbSEd Maste 			more_type = false;
29218f4c9dbSEd Maste 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
29318f4c9dbSEd Maste 			goto clean;
29418f4c9dbSEd Maste 	}
29518f4c9dbSEd Maste 	if (more_type)
29618f4c9dbSEd Maste 		goto clean;
29718f4c9dbSEd Maste 
298a85fe12eSEd Maste 	if (ddata.output.size == 0)
299a85fe12eSEd Maste 		goto clean;
30018f4c9dbSEd Maste 	if (td.paren && !VEC_PUSH_STR(&ddata.output, ")"))
301a85fe12eSEd Maste 		goto clean;
302bee2765cSEd Maste 	if (ddata.mem_vat && !VEC_PUSH_STR(&ddata.output, " volatile"))
303a85fe12eSEd Maste 		goto clean;
304bee2765cSEd Maste 	if (ddata.mem_cst && !VEC_PUSH_STR(&ddata.output, " const"))
305a85fe12eSEd Maste 		goto clean;
306bee2765cSEd Maste 	if (ddata.mem_rst && !VEC_PUSH_STR(&ddata.output, " restrict"))
307a85fe12eSEd Maste 		goto clean;
30818f4c9dbSEd Maste 	if (ddata.mem_ref && !VEC_PUSH_STR(&ddata.output, " &"))
30918f4c9dbSEd Maste 		goto clean;
31018f4c9dbSEd Maste 	if (ddata.mem_rref && !VEC_PUSH_STR(&ddata.output, " &&"))
31118f4c9dbSEd Maste 		goto clean;
312a85fe12eSEd Maste 
313a85fe12eSEd Maste 	rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
314a85fe12eSEd Maste 
315a85fe12eSEd Maste clean:
31618f4c9dbSEd Maste 	if (has_ret)
31718f4c9dbSEd Maste 		vector_str_dest(&ret_type);
31818f4c9dbSEd Maste 
319a85fe12eSEd Maste 	cpp_demangle_data_dest(&ddata);
320a85fe12eSEd Maste 
321a85fe12eSEd Maste 	return (rtn);
322a85fe12eSEd Maste }
323a85fe12eSEd Maste 
324a85fe12eSEd Maste static void
cpp_demangle_data_dest(struct cpp_demangle_data * d)325a85fe12eSEd Maste cpp_demangle_data_dest(struct cpp_demangle_data *d)
326a85fe12eSEd Maste {
327a85fe12eSEd Maste 
328a85fe12eSEd Maste 	if (d == NULL)
329a85fe12eSEd Maste 		return;
330a85fe12eSEd Maste 
331a85fe12eSEd Maste 	vector_read_cmd_dest(&d->cmd);
332a85fe12eSEd Maste 	vector_str_dest(&d->class_type);
333a85fe12eSEd Maste 	vector_str_dest(&d->tmpl);
334a85fe12eSEd Maste 	vector_str_dest(&d->subst);
335a85fe12eSEd Maste 	vector_str_dest(&d->output);
336a85fe12eSEd Maste }
337a85fe12eSEd Maste 
338a85fe12eSEd Maste static int
cpp_demangle_data_init(struct cpp_demangle_data * d,const char * cur)339a85fe12eSEd Maste cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
340a85fe12eSEd Maste {
341a85fe12eSEd Maste 
342a85fe12eSEd Maste 	if (d == NULL || cur == NULL)
343a85fe12eSEd Maste 		return (0);
344a85fe12eSEd Maste 
345a85fe12eSEd Maste 	if (!vector_str_init(&d->output))
346a85fe12eSEd Maste 		return (0);
347a85fe12eSEd Maste 	if (!vector_str_init(&d->subst))
34818f4c9dbSEd Maste 		goto clean1;
349a85fe12eSEd Maste 	if (!vector_str_init(&d->tmpl))
35018f4c9dbSEd Maste 		goto clean2;
351a85fe12eSEd Maste 	if (!vector_str_init(&d->class_type))
35218f4c9dbSEd Maste 		goto clean3;
353a85fe12eSEd Maste 	if (!vector_read_cmd_init(&d->cmd))
35418f4c9dbSEd Maste 		goto clean4;
355a85fe12eSEd Maste 
356a85fe12eSEd Maste 	assert(d->output.container != NULL);
357a85fe12eSEd Maste 	assert(d->subst.container != NULL);
358a85fe12eSEd Maste 	assert(d->tmpl.container != NULL);
359a85fe12eSEd Maste 	assert(d->class_type.container != NULL);
360a85fe12eSEd Maste 
361a85fe12eSEd Maste 	d->mem_rst = false;
362a85fe12eSEd Maste 	d->mem_vat = false;
363a85fe12eSEd Maste 	d->mem_cst = false;
36418f4c9dbSEd Maste 	d->mem_ref = false;
36518f4c9dbSEd Maste 	d->mem_rref = false;
36618f4c9dbSEd Maste 	d->is_tmpl = false;
36718f4c9dbSEd Maste 	d->is_functype = false;
36818f4c9dbSEd Maste 	d->ref_qualifier = false;
36918f4c9dbSEd Maste 	d->push_qualifier = PUSH_ALL_QUALIFIER;
370a85fe12eSEd Maste 	d->func_type = 0;
371a85fe12eSEd Maste 	d->cur = cur;
37218f4c9dbSEd Maste 	d->cur_output = &d->output;
373a85fe12eSEd Maste 	d->last_sname = NULL;
374a85fe12eSEd Maste 
375a85fe12eSEd Maste 	return (1);
376a85fe12eSEd Maste 
377a85fe12eSEd Maste clean4:
37818f4c9dbSEd Maste 	vector_str_dest(&d->class_type);
379a85fe12eSEd Maste clean3:
38018f4c9dbSEd Maste 	vector_str_dest(&d->tmpl);
381a85fe12eSEd Maste clean2:
38218f4c9dbSEd Maste 	vector_str_dest(&d->subst);
383a85fe12eSEd Maste clean1:
384a85fe12eSEd Maste 	vector_str_dest(&d->output);
385a85fe12eSEd Maste 
386a85fe12eSEd Maste 	return (0);
387a85fe12eSEd Maste }
388a85fe12eSEd Maste 
389a85fe12eSEd Maste static int
cpp_demangle_push_fp(struct cpp_demangle_data * ddata,char * (* decoder)(const char *,size_t))390a85fe12eSEd Maste cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
391a85fe12eSEd Maste     char *(*decoder)(const char *, size_t))
392a85fe12eSEd Maste {
393a85fe12eSEd Maste 	size_t len;
394a85fe12eSEd Maste 	int rtn;
395a85fe12eSEd Maste 	const char *fp;
396a85fe12eSEd Maste 	char *f;
397a85fe12eSEd Maste 
398a85fe12eSEd Maste 	if (ddata == NULL || decoder == NULL)
399a85fe12eSEd Maste 		return (0);
400a85fe12eSEd Maste 
401a85fe12eSEd Maste 	fp = ddata->cur;
402a85fe12eSEd Maste 	while (*ddata->cur != 'E')
403a85fe12eSEd Maste 		++ddata->cur;
404a85fe12eSEd Maste 
405a85fe12eSEd Maste 	if ((f = decoder(fp, ddata->cur - fp)) == NULL)
406a85fe12eSEd Maste 		return (0);
407a85fe12eSEd Maste 
408a85fe12eSEd Maste 	rtn = 0;
409a85fe12eSEd Maste 	if ((len = strlen(f)) > 0)
410a85fe12eSEd Maste 		rtn = cpp_demangle_push_str(ddata, f, len);
411a85fe12eSEd Maste 
412a85fe12eSEd Maste 	free(f);
413a85fe12eSEd Maste 
4143ef90571SEd Maste 	++ddata->cur;
4153ef90571SEd Maste 
416a85fe12eSEd Maste 	return (rtn);
417a85fe12eSEd Maste }
418a85fe12eSEd Maste 
419a85fe12eSEd Maste static int
cpp_demangle_push_str(struct cpp_demangle_data * ddata,const char * str,size_t len)420a85fe12eSEd Maste cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
421a85fe12eSEd Maste     size_t len)
422a85fe12eSEd Maste {
423a85fe12eSEd Maste 
424a85fe12eSEd Maste 	if (ddata == NULL || str == NULL || len == 0)
425a85fe12eSEd Maste 		return (0);
426a85fe12eSEd Maste 
42718f4c9dbSEd Maste 	/*
42818f4c9dbSEd Maste 	 * is_tmpl is used to check if the type (function arg) is right next
42918f4c9dbSEd Maste 	 * to template args, and should always be cleared whenever new string
43018f4c9dbSEd Maste 	 * pushed.
43118f4c9dbSEd Maste 	 */
43218f4c9dbSEd Maste 	ddata->is_tmpl = false;
433a85fe12eSEd Maste 
43418f4c9dbSEd Maste 	return (vector_str_push(ddata->cur_output, str, len));
43518f4c9dbSEd Maste }
43618f4c9dbSEd Maste 
43718f4c9dbSEd Maste static int
cpp_demangle_pop_str(struct cpp_demangle_data * ddata)43818f4c9dbSEd Maste cpp_demangle_pop_str(struct cpp_demangle_data *ddata)
43918f4c9dbSEd Maste {
44018f4c9dbSEd Maste 
44118f4c9dbSEd Maste 	if (ddata == NULL)
44218f4c9dbSEd Maste 		return (0);
44318f4c9dbSEd Maste 
44418f4c9dbSEd Maste 	return (vector_str_pop(ddata->cur_output));
445a85fe12eSEd Maste }
446a85fe12eSEd Maste 
447a85fe12eSEd Maste static int
cpp_demangle_push_subst(struct cpp_demangle_data * ddata,const char * str,size_t len)448a85fe12eSEd Maste cpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str,
449a85fe12eSEd Maste     size_t len)
450a85fe12eSEd Maste {
451a85fe12eSEd Maste 
452a85fe12eSEd Maste 	if (ddata == NULL || str == NULL || len == 0)
453a85fe12eSEd Maste 		return (0);
454a85fe12eSEd Maste 
455a85fe12eSEd Maste 	if (!vector_str_find(&ddata->subst, str, len))
456a85fe12eSEd Maste 		return (vector_str_push(&ddata->subst, str, len));
457a85fe12eSEd Maste 
458a85fe12eSEd Maste 	return (1);
459a85fe12eSEd Maste }
460a85fe12eSEd Maste 
461a85fe12eSEd Maste static int
cpp_demangle_push_subst_v(struct cpp_demangle_data * ddata,struct vector_str * v)462a85fe12eSEd Maste cpp_demangle_push_subst_v(struct cpp_demangle_data *ddata, struct vector_str *v)
463a85fe12eSEd Maste {
464a85fe12eSEd Maste 	size_t str_len;
465a85fe12eSEd Maste 	int rtn;
466a85fe12eSEd Maste 	char *str;
467a85fe12eSEd Maste 
468a85fe12eSEd Maste 	if (ddata == NULL || v == NULL)
469a85fe12eSEd Maste 		return (0);
470a85fe12eSEd Maste 
471a85fe12eSEd Maste 	if ((str = vector_str_get_flat(v, &str_len)) == NULL)
472a85fe12eSEd Maste 		return (0);
473a85fe12eSEd Maste 
474a85fe12eSEd Maste 	rtn = cpp_demangle_push_subst(ddata, str, str_len);
475a85fe12eSEd Maste 
476a85fe12eSEd Maste 	free(str);
477a85fe12eSEd Maste 
478a85fe12eSEd Maste 	return (rtn);
479a85fe12eSEd Maste }
480a85fe12eSEd Maste 
481a85fe12eSEd Maste static int
cpp_demangle_push_type_qualifier(struct cpp_demangle_data * ddata,struct vector_type_qualifier * v,const char * type_str)482a85fe12eSEd Maste cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
483a85fe12eSEd Maste     struct vector_type_qualifier *v, const char *type_str)
484a85fe12eSEd Maste {
485a85fe12eSEd Maste 	struct vector_str subst_v;
48618f4c9dbSEd Maste 	enum type_qualifier t;
487a85fe12eSEd Maste 	size_t idx, e_idx, e_len;
488a85fe12eSEd Maste 	char *buf;
48918f4c9dbSEd Maste 	int rtn;
49018f4c9dbSEd Maste 	bool cv;
491a85fe12eSEd Maste 
492a85fe12eSEd Maste 	if (ddata == NULL || v == NULL)
493a85fe12eSEd Maste 		return (0);
494a85fe12eSEd Maste 
495a85fe12eSEd Maste 	if ((idx = v->size) == 0)
496a85fe12eSEd Maste 		return (1);
497a85fe12eSEd Maste 
498a85fe12eSEd Maste 	rtn = 0;
499a85fe12eSEd Maste 	if (type_str != NULL) {
500a85fe12eSEd Maste 		if (!vector_str_init(&subst_v))
501a85fe12eSEd Maste 			return (0);
502bee2765cSEd Maste 		if (!VEC_PUSH_STR(&subst_v, type_str))
503a85fe12eSEd Maste 			goto clean;
504a85fe12eSEd Maste 	}
505a85fe12eSEd Maste 
50618f4c9dbSEd Maste 	cv = true;
507a85fe12eSEd Maste 	e_idx = 0;
508a85fe12eSEd Maste 	while (idx > 0) {
509a85fe12eSEd Maste 		switch (v->q_container[idx - 1]) {
510a85fe12eSEd Maste 		case TYPE_PTR:
51118f4c9dbSEd Maste 			cv = false;
51218f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
51318f4c9dbSEd Maste 				break;
514bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "*"))
515a85fe12eSEd Maste 				goto clean;
516a85fe12eSEd Maste 			if (type_str != NULL) {
517bee2765cSEd Maste 				if (!VEC_PUSH_STR(&subst_v, "*"))
518a85fe12eSEd Maste 					goto clean;
5193ef90571SEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
5203ef90571SEd Maste 				    &subst_v))
521a85fe12eSEd Maste 					goto clean;
522a85fe12eSEd Maste 			}
523a85fe12eSEd Maste 			break;
524a85fe12eSEd Maste 
525a85fe12eSEd Maste 		case TYPE_REF:
52618f4c9dbSEd Maste 			cv = false;
52718f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
52818f4c9dbSEd Maste 				break;
529bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "&"))
530a85fe12eSEd Maste 				goto clean;
531a85fe12eSEd Maste 			if (type_str != NULL) {
532bee2765cSEd Maste 				if (!VEC_PUSH_STR(&subst_v, "&"))
533a85fe12eSEd Maste 					goto clean;
5343ef90571SEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
5353ef90571SEd Maste 				    &subst_v))
536a85fe12eSEd Maste 					goto clean;
537a85fe12eSEd Maste 			}
538a85fe12eSEd Maste 			break;
539a85fe12eSEd Maste 
54018f4c9dbSEd Maste 		case TYPE_RREF:
54118f4c9dbSEd Maste 			cv = false;
54218f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
54318f4c9dbSEd Maste 				break;
54418f4c9dbSEd Maste 			if (!DEM_PUSH_STR(ddata, "&&"))
54518f4c9dbSEd Maste 				goto clean;
54618f4c9dbSEd Maste 			if (type_str != NULL) {
54718f4c9dbSEd Maste 				if (!VEC_PUSH_STR(&subst_v, "&&"))
54818f4c9dbSEd Maste 					goto clean;
54918f4c9dbSEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
55018f4c9dbSEd Maste 				    &subst_v))
55118f4c9dbSEd Maste 					goto clean;
55218f4c9dbSEd Maste 			}
55318f4c9dbSEd Maste 			break;
55418f4c9dbSEd Maste 
555a85fe12eSEd Maste 		case TYPE_CMX:
55618f4c9dbSEd Maste 			cv = false;
55718f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
55818f4c9dbSEd Maste 				break;
559bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, " complex"))
560a85fe12eSEd Maste 				goto clean;
561a85fe12eSEd Maste 			if (type_str != NULL) {
562bee2765cSEd Maste 				if (!VEC_PUSH_STR(&subst_v, " complex"))
563a85fe12eSEd Maste 					goto clean;
5643ef90571SEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
5653ef90571SEd Maste 				    &subst_v))
566a85fe12eSEd Maste 					goto clean;
567a85fe12eSEd Maste 			}
568a85fe12eSEd Maste 			break;
569a85fe12eSEd Maste 
570a85fe12eSEd Maste 		case TYPE_IMG:
57118f4c9dbSEd Maste 			cv = false;
57218f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
57318f4c9dbSEd Maste 				break;
574bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, " imaginary"))
575a85fe12eSEd Maste 				goto clean;
576a85fe12eSEd Maste 			if (type_str != NULL) {
577715d1396SEd Maste 				if (!VEC_PUSH_STR(&subst_v, " imaginary"))
578a85fe12eSEd Maste 					goto clean;
5793ef90571SEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
5803ef90571SEd Maste 				    &subst_v))
581a85fe12eSEd Maste 					goto clean;
582a85fe12eSEd Maste 			}
583a85fe12eSEd Maste 			break;
584a85fe12eSEd Maste 
585a85fe12eSEd Maste 		case TYPE_EXT:
58618f4c9dbSEd Maste 			cv = false;
58718f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
58818f4c9dbSEd Maste 				break;
5893ef90571SEd Maste 			if (v->ext_name.size == 0 ||
5903ef90571SEd Maste 			    e_idx > v->ext_name.size - 1)
591a85fe12eSEd Maste 				goto clean;
5923ef90571SEd Maste 			if ((e_len = strlen(v->ext_name.container[e_idx])) ==
5933ef90571SEd Maste 			    0)
594a85fe12eSEd Maste 				goto clean;
5953ef90571SEd Maste 			if ((buf = malloc(e_len + 2)) == NULL)
596a85fe12eSEd Maste 				goto clean;
5973ef90571SEd Maste 			snprintf(buf, e_len + 2, " %s",
5983ef90571SEd Maste 			    v->ext_name.container[e_idx]);
599a85fe12eSEd Maste 
600bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, buf)) {
601a85fe12eSEd Maste 				free(buf);
602a85fe12eSEd Maste 				goto clean;
603a85fe12eSEd Maste 			}
604a85fe12eSEd Maste 
605a85fe12eSEd Maste 			if (type_str != NULL) {
606bee2765cSEd Maste 				if (!VEC_PUSH_STR(&subst_v, buf)) {
607a85fe12eSEd Maste 					free(buf);
608a85fe12eSEd Maste 					goto clean;
609a85fe12eSEd Maste 				}
6103ef90571SEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
6113ef90571SEd Maste 				    &subst_v)) {
612a85fe12eSEd Maste 					free(buf);
613a85fe12eSEd Maste 					goto clean;
614a85fe12eSEd Maste 				}
615a85fe12eSEd Maste 			}
616a85fe12eSEd Maste 			free(buf);
617a85fe12eSEd Maste 			++e_idx;
618a85fe12eSEd Maste 			break;
619a85fe12eSEd Maste 
620a85fe12eSEd Maste 		case TYPE_RST:
62118f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
62218f4c9dbSEd Maste 			    cv)
62318f4c9dbSEd Maste 				break;
62418f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
62518f4c9dbSEd Maste 				break;
626bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, " restrict"))
627a85fe12eSEd Maste 				goto clean;
628a85fe12eSEd Maste 			if (type_str != NULL) {
629bee2765cSEd Maste 				if (!VEC_PUSH_STR(&subst_v, " restrict"))
630a85fe12eSEd Maste 					goto clean;
63118f4c9dbSEd Maste 				if (idx - 1 > 0) {
63218f4c9dbSEd Maste 					t = v->q_container[idx - 2];
63318f4c9dbSEd Maste 					if (t == TYPE_RST || t == TYPE_VAT ||
63418f4c9dbSEd Maste 					    t == TYPE_CST)
63518f4c9dbSEd Maste 						break;
63618f4c9dbSEd Maste 				}
6373ef90571SEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
6383ef90571SEd Maste 				    &subst_v))
639a85fe12eSEd Maste 					goto clean;
640a85fe12eSEd Maste 			}
641a85fe12eSEd Maste 			break;
642a85fe12eSEd Maste 
643a85fe12eSEd Maste 		case TYPE_VAT:
64418f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
64518f4c9dbSEd Maste 			    cv)
64618f4c9dbSEd Maste 				break;
64718f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
64818f4c9dbSEd Maste 				break;
649bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, " volatile"))
650a85fe12eSEd Maste 				goto clean;
651a85fe12eSEd Maste 			if (type_str != NULL) {
652bee2765cSEd Maste 				if (!VEC_PUSH_STR(&subst_v, " volatile"))
653a85fe12eSEd Maste 					goto clean;
65418f4c9dbSEd Maste 				if (idx - 1 > 0) {
65518f4c9dbSEd Maste 					t = v->q_container[idx - 2];
65618f4c9dbSEd Maste 					if (t == TYPE_RST || t == TYPE_VAT ||
65718f4c9dbSEd Maste 					    t == TYPE_CST)
65818f4c9dbSEd Maste 						break;
65918f4c9dbSEd Maste 				}
6603ef90571SEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
6613ef90571SEd Maste 				    &subst_v))
662a85fe12eSEd Maste 					goto clean;
663a85fe12eSEd Maste 			}
664a85fe12eSEd Maste 			break;
665a85fe12eSEd Maste 
666a85fe12eSEd Maste 		case TYPE_CST:
66718f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_NON_CV_QUALIFIER &&
66818f4c9dbSEd Maste 			    cv)
66918f4c9dbSEd Maste 				break;
67018f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER && !cv)
67118f4c9dbSEd Maste 				break;
672bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, " const"))
673a85fe12eSEd Maste 				goto clean;
674a85fe12eSEd Maste 			if (type_str != NULL) {
675bee2765cSEd Maste 				if (!VEC_PUSH_STR(&subst_v, " const"))
676a85fe12eSEd Maste 					goto clean;
67718f4c9dbSEd Maste 				if (idx - 1 > 0) {
67818f4c9dbSEd Maste 					t = v->q_container[idx - 2];
67918f4c9dbSEd Maste 					if (t == TYPE_RST || t == TYPE_VAT ||
68018f4c9dbSEd Maste 					    t == TYPE_CST)
68118f4c9dbSEd Maste 						break;
68218f4c9dbSEd Maste 				}
6833ef90571SEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
6843ef90571SEd Maste 				    &subst_v))
685a85fe12eSEd Maste 					goto clean;
686a85fe12eSEd Maste 			}
687a85fe12eSEd Maste 			break;
688a85fe12eSEd Maste 
6893ef90571SEd Maste 		case TYPE_VEC:
69018f4c9dbSEd Maste 			cv = false;
69118f4c9dbSEd Maste 			if (ddata->push_qualifier == PUSH_CV_QUALIFIER)
69218f4c9dbSEd Maste 				break;
6933ef90571SEd Maste 			if (v->ext_name.size == 0 ||
6943ef90571SEd Maste 			    e_idx > v->ext_name.size - 1)
6953ef90571SEd Maste 				goto clean;
6963ef90571SEd Maste 			if ((e_len = strlen(v->ext_name.container[e_idx])) ==
6973ef90571SEd Maste 			    0)
6983ef90571SEd Maste 				goto clean;
6993ef90571SEd Maste 			if ((buf = malloc(e_len + 12)) == NULL)
7003ef90571SEd Maste 				goto clean;
7013ef90571SEd Maste 			snprintf(buf, e_len + 12, " __vector(%s)",
7023ef90571SEd Maste 			    v->ext_name.container[e_idx]);
703bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, buf)) {
7043ef90571SEd Maste 				free(buf);
7053ef90571SEd Maste 				goto clean;
7063ef90571SEd Maste 			}
7073ef90571SEd Maste 			if (type_str != NULL) {
708bee2765cSEd Maste 				if (!VEC_PUSH_STR(&subst_v, buf)) {
7093ef90571SEd Maste 					free(buf);
7103ef90571SEd Maste 					goto clean;
7113ef90571SEd Maste 				}
7123ef90571SEd Maste 				if (!cpp_demangle_push_subst_v(ddata,
7133ef90571SEd Maste 				    &subst_v)) {
7143ef90571SEd Maste 					free(buf);
7153ef90571SEd Maste 					goto clean;
7163ef90571SEd Maste 				}
7173ef90571SEd Maste 			}
7183ef90571SEd Maste 			free(buf);
7193ef90571SEd Maste 			++e_idx;
7203ef90571SEd Maste 			break;
721b6b6f9ccSEd Maste 		}
722a85fe12eSEd Maste 		--idx;
723a85fe12eSEd Maste 	}
724a85fe12eSEd Maste 
725a85fe12eSEd Maste 	rtn = 1;
726a85fe12eSEd Maste clean:
727a85fe12eSEd Maste 	if (type_str != NULL)
728a85fe12eSEd Maste 		vector_str_dest(&subst_v);
729a85fe12eSEd Maste 
730a85fe12eSEd Maste 	return (rtn);
731a85fe12eSEd Maste }
732a85fe12eSEd Maste 
733a85fe12eSEd Maste static int
cpp_demangle_get_subst(struct cpp_demangle_data * ddata,size_t idx)734a85fe12eSEd Maste cpp_demangle_get_subst(struct cpp_demangle_data *ddata, size_t idx)
735a85fe12eSEd Maste {
736a85fe12eSEd Maste 	size_t len;
737a85fe12eSEd Maste 
738a85fe12eSEd Maste 	if (ddata == NULL || ddata->subst.size <= idx)
739a85fe12eSEd Maste 		return (0);
740a85fe12eSEd Maste 	if ((len = strlen(ddata->subst.container[idx])) == 0)
741a85fe12eSEd Maste 		return (0);
742a85fe12eSEd Maste 	if (!cpp_demangle_push_str(ddata, ddata->subst.container[idx], len))
743a85fe12eSEd Maste 		return (0);
744a85fe12eSEd Maste 
745a85fe12eSEd Maste 	/* skip '_' */
746a85fe12eSEd Maste 	++ddata->cur;
747a85fe12eSEd Maste 
748a85fe12eSEd Maste 	return (1);
749a85fe12eSEd Maste }
750a85fe12eSEd Maste 
751a85fe12eSEd Maste static int
cpp_demangle_get_tmpl_param(struct cpp_demangle_data * ddata,size_t idx)752a85fe12eSEd Maste cpp_demangle_get_tmpl_param(struct cpp_demangle_data *ddata, size_t idx)
753a85fe12eSEd Maste {
754a85fe12eSEd Maste 	size_t len;
755a85fe12eSEd Maste 
756a85fe12eSEd Maste 	if (ddata == NULL || ddata->tmpl.size <= idx)
757a85fe12eSEd Maste 		return (0);
758a85fe12eSEd Maste 	if ((len = strlen(ddata->tmpl.container[idx])) == 0)
759a85fe12eSEd Maste 		return (0);
760a85fe12eSEd Maste 	if (!cpp_demangle_push_str(ddata, ddata->tmpl.container[idx], len))
761a85fe12eSEd Maste 		return (0);
762a85fe12eSEd Maste 
763a85fe12eSEd Maste 	++ddata->cur;
764a85fe12eSEd Maste 
765a85fe12eSEd Maste 	return (1);
766a85fe12eSEd Maste }
767a85fe12eSEd Maste 
768a85fe12eSEd Maste static int
cpp_demangle_read_array(struct cpp_demangle_data * ddata)769a85fe12eSEd Maste cpp_demangle_read_array(struct cpp_demangle_data *ddata)
770a85fe12eSEd Maste {
771a85fe12eSEd Maste 	size_t i, num_len, exp_len, p_idx, idx;
772a85fe12eSEd Maste 	const char *num;
773a85fe12eSEd Maste 	char *exp;
774a85fe12eSEd Maste 
775a85fe12eSEd Maste 	if (ddata == NULL || *(++ddata->cur) == '\0')
776a85fe12eSEd Maste 		return (0);
777a85fe12eSEd Maste 
778a85fe12eSEd Maste 	if (*ddata->cur == '_') {
779a85fe12eSEd Maste 		if (*(++ddata->cur) == '\0')
780a85fe12eSEd Maste 			return (0);
781a85fe12eSEd Maste 
78218f4c9dbSEd Maste 		if (!cpp_demangle_read_type(ddata, NULL))
783a85fe12eSEd Maste 			return (0);
784a85fe12eSEd Maste 
785bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "[]"))
786a85fe12eSEd Maste 			return (0);
787a85fe12eSEd Maste 	} else {
788a85fe12eSEd Maste 		if (ELFTC_ISDIGIT(*ddata->cur) != 0) {
789a85fe12eSEd Maste 			num = ddata->cur;
790a85fe12eSEd Maste 			while (ELFTC_ISDIGIT(*ddata->cur) != 0)
791a85fe12eSEd Maste 				++ddata->cur;
792a85fe12eSEd Maste 			if (*ddata->cur != '_')
793a85fe12eSEd Maste 				return (0);
794a85fe12eSEd Maste 			num_len = ddata->cur - num;
795a85fe12eSEd Maste 			assert(num_len > 0);
796a85fe12eSEd Maste 			if (*(++ddata->cur) == '\0')
797a85fe12eSEd Maste 				return (0);
79818f4c9dbSEd Maste 			if (!cpp_demangle_read_type(ddata, NULL))
799a85fe12eSEd Maste 				return (0);
800bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "["))
801a85fe12eSEd Maste 				return (0);
802a85fe12eSEd Maste 			if (!cpp_demangle_push_str(ddata, num, num_len))
803a85fe12eSEd Maste 				return (0);
804bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "]"))
805a85fe12eSEd Maste 				return (0);
806a85fe12eSEd Maste 		} else {
807a85fe12eSEd Maste 			p_idx = ddata->output.size;
808a85fe12eSEd Maste 			if (!cpp_demangle_read_expression(ddata))
809a85fe12eSEd Maste 				return (0);
810a85fe12eSEd Maste 			if ((exp = vector_str_substr(&ddata->output, p_idx,
811a85fe12eSEd Maste 				 ddata->output.size - 1, &exp_len)) == NULL)
812a85fe12eSEd Maste 				return (0);
813a85fe12eSEd Maste 			idx = ddata->output.size;
814a85fe12eSEd Maste 			for (i = p_idx; i < idx; ++i)
815a85fe12eSEd Maste 				if (!vector_str_pop(&ddata->output)) {
816a85fe12eSEd Maste 					free(exp);
817a85fe12eSEd Maste 					return (0);
818a85fe12eSEd Maste 				}
819a85fe12eSEd Maste 			if (*ddata->cur != '_') {
820a85fe12eSEd Maste 				free(exp);
821a85fe12eSEd Maste 				return (0);
822a85fe12eSEd Maste 			}
823a85fe12eSEd Maste 			++ddata->cur;
824a85fe12eSEd Maste 			if (*ddata->cur == '\0') {
825a85fe12eSEd Maste 				free(exp);
826a85fe12eSEd Maste 				return (0);
827a85fe12eSEd Maste 			}
82818f4c9dbSEd Maste 			if (!cpp_demangle_read_type(ddata, NULL)) {
829a85fe12eSEd Maste 				free(exp);
830a85fe12eSEd Maste 				return (0);
831a85fe12eSEd Maste 			}
832bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "[")) {
833a85fe12eSEd Maste 				free(exp);
834a85fe12eSEd Maste 				return (0);
835a85fe12eSEd Maste 			}
836a85fe12eSEd Maste 			if (!cpp_demangle_push_str(ddata, exp, exp_len)) {
837a85fe12eSEd Maste 				free(exp);
838a85fe12eSEd Maste 				return (0);
839a85fe12eSEd Maste 			}
840bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "]")) {
841a85fe12eSEd Maste 				free(exp);
842a85fe12eSEd Maste 				return (0);
843a85fe12eSEd Maste 			}
844a85fe12eSEd Maste 			free(exp);
845a85fe12eSEd Maste 		}
846a85fe12eSEd Maste 	}
847a85fe12eSEd Maste 
848a85fe12eSEd Maste 	return (1);
849a85fe12eSEd Maste }
850a85fe12eSEd Maste 
851a85fe12eSEd Maste static int
cpp_demangle_read_expr_primary(struct cpp_demangle_data * ddata)852a85fe12eSEd Maste cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
853a85fe12eSEd Maste {
854a85fe12eSEd Maste 	const char *num;
855a85fe12eSEd Maste 
856a85fe12eSEd Maste 	if (ddata == NULL || *(++ddata->cur) == '\0')
857a85fe12eSEd Maste 		return (0);
858a85fe12eSEd Maste 
859a85fe12eSEd Maste 	if (*ddata->cur == '_' && *(ddata->cur + 1) == 'Z') {
860a85fe12eSEd Maste 		ddata->cur += 2;
861a85fe12eSEd Maste 		if (*ddata->cur == '\0')
862a85fe12eSEd Maste 			return (0);
863a85fe12eSEd Maste 		if (!cpp_demangle_read_encoding(ddata))
864a85fe12eSEd Maste 			return (0);
865a85fe12eSEd Maste 		++ddata->cur;
866a85fe12eSEd Maste 		return (1);
867a85fe12eSEd Maste 	}
868a85fe12eSEd Maste 
869a85fe12eSEd Maste 	switch (*ddata->cur) {
870a85fe12eSEd Maste 	case 'b':
8713ef90571SEd Maste 		if (*(ddata->cur + 2) != 'E')
8723ef90571SEd Maste 			return (0);
873a85fe12eSEd Maste 		switch (*(++ddata->cur)) {
874a85fe12eSEd Maste 		case '0':
8753ef90571SEd Maste 			ddata->cur += 2;
876bee2765cSEd Maste 			return (DEM_PUSH_STR(ddata, "false"));
877a85fe12eSEd Maste 		case '1':
8783ef90571SEd Maste 			ddata->cur += 2;
879bee2765cSEd Maste 			return (DEM_PUSH_STR(ddata, "true"));
880a85fe12eSEd Maste 		default:
881a85fe12eSEd Maste 			return (0);
882b6b6f9ccSEd Maste 		}
883a85fe12eSEd Maste 
884a85fe12eSEd Maste 	case 'd':
885a85fe12eSEd Maste 		++ddata->cur;
886a85fe12eSEd Maste 		return (cpp_demangle_push_fp(ddata, decode_fp_to_double));
887a85fe12eSEd Maste 
888a85fe12eSEd Maste 	case 'e':
889a85fe12eSEd Maste 		++ddata->cur;
890a85fe12eSEd Maste 		if (sizeof(long double) == 10)
891a85fe12eSEd Maste 			return (cpp_demangle_push_fp(ddata,
892a85fe12eSEd Maste 			    decode_fp_to_double));
893a85fe12eSEd Maste 		return (cpp_demangle_push_fp(ddata, decode_fp_to_float80));
894a85fe12eSEd Maste 
895a85fe12eSEd Maste 	case 'f':
896a85fe12eSEd Maste 		++ddata->cur;
897a85fe12eSEd Maste 		return (cpp_demangle_push_fp(ddata, decode_fp_to_float));
898a85fe12eSEd Maste 
899a85fe12eSEd Maste 	case 'g':
900a85fe12eSEd Maste 		++ddata->cur;
901a85fe12eSEd Maste 		if (sizeof(long double) == 16)
902a85fe12eSEd Maste 			return (cpp_demangle_push_fp(ddata,
903a85fe12eSEd Maste 			    decode_fp_to_double));
904a85fe12eSEd Maste 		return (cpp_demangle_push_fp(ddata, decode_fp_to_float128));
905a85fe12eSEd Maste 
906a85fe12eSEd Maste 	case 'i':
907a85fe12eSEd Maste 	case 'j':
908a85fe12eSEd Maste 	case 'l':
909a85fe12eSEd Maste 	case 'm':
910a85fe12eSEd Maste 	case 'n':
911a85fe12eSEd Maste 	case 's':
912a85fe12eSEd Maste 	case 't':
913a85fe12eSEd Maste 	case 'x':
914a85fe12eSEd Maste 	case 'y':
915a85fe12eSEd Maste 		if (*(++ddata->cur) == 'n') {
916bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "-"))
917a85fe12eSEd Maste 				return (0);
918a85fe12eSEd Maste 			++ddata->cur;
919a85fe12eSEd Maste 		}
920a85fe12eSEd Maste 		num = ddata->cur;
921a85fe12eSEd Maste 		while (*ddata->cur != 'E') {
922a85fe12eSEd Maste 			if (!ELFTC_ISDIGIT(*ddata->cur))
923a85fe12eSEd Maste 				return (0);
924a85fe12eSEd Maste 			++ddata->cur;
925a85fe12eSEd Maste 		}
926a85fe12eSEd Maste 		++ddata->cur;
9273ef90571SEd Maste 		return (cpp_demangle_push_str(ddata, num,
9283ef90571SEd Maste 		    ddata->cur - num - 1));
929a85fe12eSEd Maste 
930a85fe12eSEd Maste 	default:
931a85fe12eSEd Maste 		return (0);
932b6b6f9ccSEd Maste 	}
933a85fe12eSEd Maste }
934a85fe12eSEd Maste 
935a85fe12eSEd Maste static int
cpp_demangle_read_expression(struct cpp_demangle_data * ddata)936a85fe12eSEd Maste cpp_demangle_read_expression(struct cpp_demangle_data *ddata)
937a85fe12eSEd Maste {
938a85fe12eSEd Maste 
939a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur == '\0')
940a85fe12eSEd Maste 		return (0);
941a85fe12eSEd Maste 
942a85fe12eSEd Maste 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
943a85fe12eSEd Maste 	case SIMPLE_HASH('s', 't'):
944a85fe12eSEd Maste 		ddata->cur += 2;
94518f4c9dbSEd Maste 		return (cpp_demangle_read_type(ddata, NULL));
946a85fe12eSEd Maste 
947a85fe12eSEd Maste 	case SIMPLE_HASH('s', 'r'):
948a85fe12eSEd Maste 		ddata->cur += 2;
94918f4c9dbSEd Maste 		if (!cpp_demangle_read_type(ddata, NULL))
950a85fe12eSEd Maste 			return (0);
951a85fe12eSEd Maste 		if (!cpp_demangle_read_uqname(ddata))
952a85fe12eSEd Maste 			return (0);
953a85fe12eSEd Maste 		if (*ddata->cur == 'I')
954a85fe12eSEd Maste 			return (cpp_demangle_read_tmpl_args(ddata));
955a85fe12eSEd Maste 		return (1);
956a85fe12eSEd Maste 
957a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'a'):
958a85fe12eSEd Maste 		/* operator && */
959a85fe12eSEd Maste 		ddata->cur += 2;
960a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "&&", 2));
961a85fe12eSEd Maste 
962a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'd'):
963a85fe12eSEd Maste 		/* operator & (unary) */
964a85fe12eSEd Maste 		ddata->cur += 2;
965a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "&", 1));
966a85fe12eSEd Maste 
967a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'n'):
968a85fe12eSEd Maste 		/* operator & */
969a85fe12eSEd Maste 		ddata->cur += 2;
970a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "&", 1));
971a85fe12eSEd Maste 
972a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'N'):
973a85fe12eSEd Maste 		/* operator &= */
974a85fe12eSEd Maste 		ddata->cur += 2;
975a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "&=", 2));
976a85fe12eSEd Maste 
977a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'S'):
978a85fe12eSEd Maste 		/* operator = */
979a85fe12eSEd Maste 		ddata->cur += 2;
980a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "=", 1));
981a85fe12eSEd Maste 
982a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'l'):
983a85fe12eSEd Maste 		/* operator () */
984a85fe12eSEd Maste 		ddata->cur += 2;
985a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "()", 2));
986a85fe12eSEd Maste 
987a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'm'):
988a85fe12eSEd Maste 		/* operator , */
989a85fe12eSEd Maste 		ddata->cur += 2;
990a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, ",", 1));
991a85fe12eSEd Maste 
992a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'o'):
993a85fe12eSEd Maste 		/* operator ~ */
994a85fe12eSEd Maste 		ddata->cur += 2;
995a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "~", 1));
996a85fe12eSEd Maste 
997a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'v'):
998a85fe12eSEd Maste 		/* operator (cast) */
999a85fe12eSEd Maste 		ddata->cur += 2;
1000a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "(cast)", 6));
1001a85fe12eSEd Maste 
1002a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'a'):
1003a85fe12eSEd Maste 		/* operator delete [] */
1004a85fe12eSEd Maste 		ddata->cur += 2;
1005a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "delete []", 9));
1006a85fe12eSEd Maste 
1007a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'e'):
1008a85fe12eSEd Maste 		/* operator * (unary) */
1009a85fe12eSEd Maste 		ddata->cur += 2;
1010a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "*", 1));
1011a85fe12eSEd Maste 
1012a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'l'):
1013a85fe12eSEd Maste 		/* operator delete */
1014a85fe12eSEd Maste 		ddata->cur += 2;
1015a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "delete", 6));
1016a85fe12eSEd Maste 
1017a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'v'):
1018a85fe12eSEd Maste 		/* operator / */
1019a85fe12eSEd Maste 		ddata->cur += 2;
1020a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "/", 1));
1021a85fe12eSEd Maste 
1022a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'V'):
1023a85fe12eSEd Maste 		/* operator /= */
1024a85fe12eSEd Maste 		ddata->cur += 2;
1025a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "/=", 2));
1026a85fe12eSEd Maste 
1027a85fe12eSEd Maste 	case SIMPLE_HASH('e', 'o'):
1028a85fe12eSEd Maste 		/* operator ^ */
1029a85fe12eSEd Maste 		ddata->cur += 2;
1030a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "^", 1));
1031a85fe12eSEd Maste 
1032a85fe12eSEd Maste 	case SIMPLE_HASH('e', 'O'):
1033a85fe12eSEd Maste 		/* operator ^= */
1034a85fe12eSEd Maste 		ddata->cur += 2;
1035a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "^=", 2));
1036a85fe12eSEd Maste 
1037a85fe12eSEd Maste 	case SIMPLE_HASH('e', 'q'):
1038a85fe12eSEd Maste 		/* operator == */
1039a85fe12eSEd Maste 		ddata->cur += 2;
1040a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "==", 2));
1041a85fe12eSEd Maste 
1042a85fe12eSEd Maste 	case SIMPLE_HASH('g', 'e'):
1043a85fe12eSEd Maste 		/* operator >= */
1044a85fe12eSEd Maste 		ddata->cur += 2;
1045a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, ">=", 2));
1046a85fe12eSEd Maste 
1047a85fe12eSEd Maste 	case SIMPLE_HASH('g', 't'):
1048a85fe12eSEd Maste 		/* operator > */
1049a85fe12eSEd Maste 		ddata->cur += 2;
1050a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, ">", 1));
1051a85fe12eSEd Maste 
1052a85fe12eSEd Maste 	case SIMPLE_HASH('i', 'x'):
1053a85fe12eSEd Maste 		/* operator [] */
1054a85fe12eSEd Maste 		ddata->cur += 2;
1055a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "[]", 2));
1056a85fe12eSEd Maste 
1057a85fe12eSEd Maste 	case SIMPLE_HASH('l', 'e'):
1058a85fe12eSEd Maste 		/* operator <= */
1059a85fe12eSEd Maste 		ddata->cur += 2;
1060a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "<=", 2));
1061a85fe12eSEd Maste 
1062a85fe12eSEd Maste 	case SIMPLE_HASH('l', 's'):
1063a85fe12eSEd Maste 		/* operator << */
1064a85fe12eSEd Maste 		ddata->cur += 2;
1065a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "<<", 2));
1066a85fe12eSEd Maste 
1067a85fe12eSEd Maste 	case SIMPLE_HASH('l', 'S'):
1068a85fe12eSEd Maste 		/* operator <<= */
1069a85fe12eSEd Maste 		ddata->cur += 2;
1070a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "<<=", 3));
1071a85fe12eSEd Maste 
1072a85fe12eSEd Maste 	case SIMPLE_HASH('l', 't'):
1073a85fe12eSEd Maste 		/* operator < */
1074a85fe12eSEd Maste 		ddata->cur += 2;
1075a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "<", 1));
1076a85fe12eSEd Maste 
1077a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'i'):
1078a85fe12eSEd Maste 		/* operator - */
1079a85fe12eSEd Maste 		ddata->cur += 2;
1080a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "-", 1));
1081a85fe12eSEd Maste 
1082a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'I'):
1083a85fe12eSEd Maste 		/* operator -= */
1084a85fe12eSEd Maste 		ddata->cur += 2;
1085a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "-=", 2));
1086a85fe12eSEd Maste 
1087a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'l'):
1088a85fe12eSEd Maste 		/* operator * */
1089a85fe12eSEd Maste 		ddata->cur += 2;
1090a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "*", 1));
1091a85fe12eSEd Maste 
1092a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'L'):
1093a85fe12eSEd Maste 		/* operator *= */
1094a85fe12eSEd Maste 		ddata->cur += 2;
1095a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "*=", 2));
1096a85fe12eSEd Maste 
1097a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'm'):
1098a85fe12eSEd Maste 		/* operator -- */
1099a85fe12eSEd Maste 		ddata->cur += 2;
1100a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "--", 2));
1101a85fe12eSEd Maste 
1102a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'a'):
1103a85fe12eSEd Maste 		/* operator new[] */
1104a85fe12eSEd Maste 		ddata->cur += 2;
1105a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "new []", 6));
1106a85fe12eSEd Maste 
1107a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'e'):
1108a85fe12eSEd Maste 		/* operator != */
1109a85fe12eSEd Maste 		ddata->cur += 2;
1110a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "!=", 2));
1111a85fe12eSEd Maste 
1112a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'g'):
1113a85fe12eSEd Maste 		/* operator - (unary) */
1114a85fe12eSEd Maste 		ddata->cur += 2;
1115a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "-", 1));
1116a85fe12eSEd Maste 
1117a85fe12eSEd Maste 	case SIMPLE_HASH('n', 't'):
1118a85fe12eSEd Maste 		/* operator ! */
1119a85fe12eSEd Maste 		ddata->cur += 2;
1120a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "!", 1));
1121a85fe12eSEd Maste 
1122a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'w'):
1123a85fe12eSEd Maste 		/* operator new */
1124a85fe12eSEd Maste 		ddata->cur += 2;
1125a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "new", 3));
1126a85fe12eSEd Maste 
1127a85fe12eSEd Maste 	case SIMPLE_HASH('o', 'o'):
1128a85fe12eSEd Maste 		/* operator || */
1129a85fe12eSEd Maste 		ddata->cur += 2;
1130a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "||", 2));
1131a85fe12eSEd Maste 
1132a85fe12eSEd Maste 	case SIMPLE_HASH('o', 'r'):
1133a85fe12eSEd Maste 		/* operator | */
1134a85fe12eSEd Maste 		ddata->cur += 2;
1135a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "|", 1));
1136a85fe12eSEd Maste 
1137a85fe12eSEd Maste 	case SIMPLE_HASH('o', 'R'):
1138a85fe12eSEd Maste 		/* operator |= */
1139a85fe12eSEd Maste 		ddata->cur += 2;
1140a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "|=", 2));
1141a85fe12eSEd Maste 
1142a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'l'):
1143a85fe12eSEd Maste 		/* operator + */
1144a85fe12eSEd Maste 		ddata->cur += 2;
1145a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "+", 1));
1146a85fe12eSEd Maste 
1147a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'L'):
1148a85fe12eSEd Maste 		/* operator += */
1149a85fe12eSEd Maste 		ddata->cur += 2;
1150a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "+=", 2));
1151a85fe12eSEd Maste 
1152a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'm'):
1153a85fe12eSEd Maste 		/* operator ->* */
1154a85fe12eSEd Maste 		ddata->cur += 2;
1155a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "->*", 3));
1156a85fe12eSEd Maste 
1157a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'p'):
1158a85fe12eSEd Maste 		/* operator ++ */
1159a85fe12eSEd Maste 		ddata->cur += 2;
1160a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "++", 2));
1161a85fe12eSEd Maste 
1162a85fe12eSEd Maste 	case SIMPLE_HASH('p', 's'):
1163a85fe12eSEd Maste 		/* operator + (unary) */
1164a85fe12eSEd Maste 		ddata->cur += 2;
1165a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "+", 1));
1166a85fe12eSEd Maste 
1167a85fe12eSEd Maste 	case SIMPLE_HASH('p', 't'):
1168a85fe12eSEd Maste 		/* operator -> */
1169a85fe12eSEd Maste 		ddata->cur += 2;
1170a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "->", 2));
1171a85fe12eSEd Maste 
1172a85fe12eSEd Maste 	case SIMPLE_HASH('q', 'u'):
1173a85fe12eSEd Maste 		/* operator ? */
1174a85fe12eSEd Maste 		ddata->cur += 2;
1175a85fe12eSEd Maste 		return (cpp_demangle_read_expression_trinary(ddata, "?", 1,
1176a85fe12eSEd Maste 		    ":", 1));
1177a85fe12eSEd Maste 
1178a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'm'):
1179a85fe12eSEd Maste 		/* operator % */
1180a85fe12eSEd Maste 		ddata->cur += 2;
1181a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "%", 1));
1182a85fe12eSEd Maste 
1183a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'M'):
1184a85fe12eSEd Maste 		/* operator %= */
1185a85fe12eSEd Maste 		ddata->cur += 2;
1186a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, "%=", 2));
1187a85fe12eSEd Maste 
1188a85fe12eSEd Maste 	case SIMPLE_HASH('r', 's'):
1189a85fe12eSEd Maste 		/* operator >> */
1190a85fe12eSEd Maste 		ddata->cur += 2;
1191a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, ">>", 2));
1192a85fe12eSEd Maste 
1193a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'S'):
1194a85fe12eSEd Maste 		/* operator >>= */
1195a85fe12eSEd Maste 		ddata->cur += 2;
1196a85fe12eSEd Maste 		return (cpp_demangle_read_expression_binary(ddata, ">>=", 3));
1197a85fe12eSEd Maste 
1198a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'z'):
1199a85fe12eSEd Maste 		/* operator sizeof */
1200a85fe12eSEd Maste 		ddata->cur += 2;
1201a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
1202a85fe12eSEd Maste 
1203a85fe12eSEd Maste 	case SIMPLE_HASH('s', 'v'):
1204a85fe12eSEd Maste 		/* operator sizeof */
1205a85fe12eSEd Maste 		ddata->cur += 2;
1206a85fe12eSEd Maste 		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
1207b6b6f9ccSEd Maste 	}
1208a85fe12eSEd Maste 
1209a85fe12eSEd Maste 	switch (*ddata->cur) {
1210a85fe12eSEd Maste 	case 'L':
1211a85fe12eSEd Maste 		return (cpp_demangle_read_expr_primary(ddata));
1212a85fe12eSEd Maste 	case 'T':
1213a85fe12eSEd Maste 		return (cpp_demangle_read_tmpl_param(ddata));
1214b6b6f9ccSEd Maste 	}
1215a85fe12eSEd Maste 
1216a85fe12eSEd Maste 	return (0);
1217a85fe12eSEd Maste }
1218a85fe12eSEd Maste 
1219a85fe12eSEd Maste static int
cpp_demangle_read_expression_flat(struct cpp_demangle_data * ddata,char ** str)12203ef90571SEd Maste cpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str)
12213ef90571SEd Maste {
12223ef90571SEd Maste 	struct vector_str *output;
12233ef90571SEd Maste 	size_t i, p_idx, idx, exp_len;
12243ef90571SEd Maste 	char *exp;
12253ef90571SEd Maste 
122618f4c9dbSEd Maste 	output = &ddata->output;
12273ef90571SEd Maste 
12283ef90571SEd Maste 	p_idx = output->size;
12293ef90571SEd Maste 
12303ef90571SEd Maste 	if (!cpp_demangle_read_expression(ddata))
12313ef90571SEd Maste 		return (0);
12323ef90571SEd Maste 
12333ef90571SEd Maste 	if ((exp = vector_str_substr(output, p_idx, output->size - 1,
12343ef90571SEd Maste 	    &exp_len)) == NULL)
12353ef90571SEd Maste 		return (0);
12363ef90571SEd Maste 
12373ef90571SEd Maste 	idx = output->size;
12383ef90571SEd Maste 	for (i = p_idx; i < idx; ++i) {
12393ef90571SEd Maste 		if (!vector_str_pop(output)) {
12403ef90571SEd Maste 			free(exp);
12413ef90571SEd Maste 			return (0);
12423ef90571SEd Maste 		}
12433ef90571SEd Maste 	}
12443ef90571SEd Maste 
12453ef90571SEd Maste 	*str = exp;
12463ef90571SEd Maste 
12473ef90571SEd Maste 	return (1);
12483ef90571SEd Maste }
12493ef90571SEd Maste 
12503ef90571SEd Maste static int
cpp_demangle_read_expression_binary(struct cpp_demangle_data * ddata,const char * name,size_t len)1251a85fe12eSEd Maste cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
1252a85fe12eSEd Maste     const char *name, size_t len)
1253a85fe12eSEd Maste {
1254a85fe12eSEd Maste 
1255a85fe12eSEd Maste 	if (ddata == NULL || name == NULL || len == 0)
1256a85fe12eSEd Maste 		return (0);
1257a85fe12eSEd Maste 	if (!cpp_demangle_read_expression(ddata))
1258a85fe12eSEd Maste 		return (0);
1259a85fe12eSEd Maste 	if (!cpp_demangle_push_str(ddata, name, len))
1260a85fe12eSEd Maste 		return (0);
1261a85fe12eSEd Maste 
1262a85fe12eSEd Maste 	return (cpp_demangle_read_expression(ddata));
1263a85fe12eSEd Maste }
1264a85fe12eSEd Maste 
1265a85fe12eSEd Maste static int
cpp_demangle_read_expression_unary(struct cpp_demangle_data * ddata,const char * name,size_t len)1266a85fe12eSEd Maste cpp_demangle_read_expression_unary(struct cpp_demangle_data *ddata,
1267a85fe12eSEd Maste     const char *name, size_t len)
1268a85fe12eSEd Maste {
1269a85fe12eSEd Maste 
1270a85fe12eSEd Maste 	if (ddata == NULL || name == NULL || len == 0)
1271a85fe12eSEd Maste 		return (0);
1272a85fe12eSEd Maste 	if (!cpp_demangle_read_expression(ddata))
1273a85fe12eSEd Maste 		return (0);
1274a85fe12eSEd Maste 
1275a85fe12eSEd Maste 	return (cpp_demangle_push_str(ddata, name, len));
1276a85fe12eSEd Maste }
1277a85fe12eSEd Maste 
1278a85fe12eSEd Maste static int
cpp_demangle_read_expression_trinary(struct cpp_demangle_data * ddata,const char * name1,size_t len1,const char * name2,size_t len2)1279a85fe12eSEd Maste cpp_demangle_read_expression_trinary(struct cpp_demangle_data *ddata,
1280a85fe12eSEd Maste     const char *name1, size_t len1, const char *name2, size_t len2)
1281a85fe12eSEd Maste {
1282a85fe12eSEd Maste 
1283a85fe12eSEd Maste 	if (ddata == NULL || name1 == NULL || len1 == 0 || name2 == NULL ||
1284a85fe12eSEd Maste 	    len2 == 0)
1285a85fe12eSEd Maste 		return (0);
1286a85fe12eSEd Maste 
1287a85fe12eSEd Maste 	if (!cpp_demangle_read_expression(ddata))
1288a85fe12eSEd Maste 		return (0);
1289a85fe12eSEd Maste 	if (!cpp_demangle_push_str(ddata, name1, len1))
1290a85fe12eSEd Maste 		return (0);
1291a85fe12eSEd Maste 	if (!cpp_demangle_read_expression(ddata))
1292a85fe12eSEd Maste 		return (0);
1293a85fe12eSEd Maste 	if (!cpp_demangle_push_str(ddata, name2, len2))
1294a85fe12eSEd Maste 		return (0);
1295a85fe12eSEd Maste 
1296a85fe12eSEd Maste 	return (cpp_demangle_read_expression(ddata));
1297a85fe12eSEd Maste }
1298a85fe12eSEd Maste 
1299a85fe12eSEd Maste static int
cpp_demangle_read_function(struct cpp_demangle_data * ddata,int * ext_c,struct vector_type_qualifier * v)1300a85fe12eSEd Maste cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
1301a85fe12eSEd Maste     struct vector_type_qualifier *v)
1302a85fe12eSEd Maste {
130318f4c9dbSEd Maste 	struct type_delimit td;
130418f4c9dbSEd Maste 	struct read_cmd_item *rc;
1305a85fe12eSEd Maste 	size_t class_type_size, class_type_len, limit;
1306a85fe12eSEd Maste 	const char *class_type;
130718f4c9dbSEd Maste 	int i;
130818f4c9dbSEd Maste 	bool paren, non_cv_qualifier;
1309a85fe12eSEd Maste 
1310a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur != 'F' || v == NULL)
1311a85fe12eSEd Maste 		return (0);
1312a85fe12eSEd Maste 
1313a85fe12eSEd Maste 	++ddata->cur;
1314a85fe12eSEd Maste 	if (*ddata->cur == 'Y') {
1315a85fe12eSEd Maste 		if (ext_c != NULL)
1316a85fe12eSEd Maste 			*ext_c = 1;
1317a85fe12eSEd Maste 		++ddata->cur;
1318a85fe12eSEd Maste 	}
131918f4c9dbSEd Maste 
132018f4c9dbSEd Maste 	/* Return type */
132118f4c9dbSEd Maste 	if (!cpp_demangle_read_type(ddata, NULL))
1322a85fe12eSEd Maste 		return (0);
132318f4c9dbSEd Maste 
1324a85fe12eSEd Maste 	if (*ddata->cur != 'E') {
132518f4c9dbSEd Maste 		if (!DEM_PUSH_STR(ddata, " "))
132618f4c9dbSEd Maste 			return (0);
132718f4c9dbSEd Maste 
132818f4c9dbSEd Maste 		non_cv_qualifier = false;
132918f4c9dbSEd Maste 		if (v->size > 0) {
133018f4c9dbSEd Maste 			for (i = 0; (size_t) i < v->size; i++) {
133118f4c9dbSEd Maste 				if (v->q_container[i] != TYPE_RST &&
133218f4c9dbSEd Maste 				    v->q_container[i] != TYPE_VAT &&
133318f4c9dbSEd Maste 				    v->q_container[i] != TYPE_CST) {
133418f4c9dbSEd Maste 					non_cv_qualifier = true;
133518f4c9dbSEd Maste 					break;
133618f4c9dbSEd Maste 				}
133718f4c9dbSEd Maste 			}
133818f4c9dbSEd Maste 		}
133918f4c9dbSEd Maste 
134018f4c9dbSEd Maste 		paren = false;
134118f4c9dbSEd Maste 		rc = vector_read_cmd_find(&ddata->cmd, READ_PTRMEM);
134218f4c9dbSEd Maste 		if (non_cv_qualifier || rc != NULL) {
1343bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "("))
1344a85fe12eSEd Maste 				return (0);
134518f4c9dbSEd Maste 			paren = true;
134618f4c9dbSEd Maste 		}
134718f4c9dbSEd Maste 
134818f4c9dbSEd Maste 		/* Push non-cv qualifiers. */
134918f4c9dbSEd Maste 		ddata->push_qualifier = PUSH_NON_CV_QUALIFIER;
135018f4c9dbSEd Maste 		if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
135118f4c9dbSEd Maste 			return (0);
135218f4c9dbSEd Maste 
135318f4c9dbSEd Maste 		if (rc) {
135418f4c9dbSEd Maste 			if (non_cv_qualifier && !DEM_PUSH_STR(ddata, " "))
135518f4c9dbSEd Maste 				return (0);
1356a85fe12eSEd Maste 			if ((class_type_size = ddata->class_type.size) == 0)
1357a85fe12eSEd Maste 				return (0);
1358a85fe12eSEd Maste 			class_type =
1359a85fe12eSEd Maste 			    ddata->class_type.container[class_type_size - 1];
1360a85fe12eSEd Maste 			if (class_type == NULL)
1361a85fe12eSEd Maste 				return (0);
1362a85fe12eSEd Maste 			if ((class_type_len = strlen(class_type)) == 0)
1363a85fe12eSEd Maste 				return (0);
1364a85fe12eSEd Maste 			if (!cpp_demangle_push_str(ddata, class_type,
1365a85fe12eSEd Maste 			    class_type_len))
1366a85fe12eSEd Maste 				return (0);
1367bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "::*"))
1368a85fe12eSEd Maste 				return (0);
136918f4c9dbSEd Maste 			/* Push pointer-to-member qualifiers. */
137018f4c9dbSEd Maste 			ddata->push_qualifier = PUSH_ALL_QUALIFIER;
137118f4c9dbSEd Maste 			if (!cpp_demangle_push_type_qualifier(ddata, rc->data,
137218f4c9dbSEd Maste 			    NULL))
137318f4c9dbSEd Maste 				return (0);
1374a85fe12eSEd Maste 			++ddata->func_type;
1375a85fe12eSEd Maste 		}
1376a85fe12eSEd Maste 
137718f4c9dbSEd Maste 		if (paren) {
137818f4c9dbSEd Maste 			if (!DEM_PUSH_STR(ddata, ")"))
1379a85fe12eSEd Maste 				return (0);
138018f4c9dbSEd Maste 			paren = false;
138118f4c9dbSEd Maste 		}
1382a85fe12eSEd Maste 
138318f4c9dbSEd Maste 		td.paren = false;
138418f4c9dbSEd Maste 		td.firstp = true;
1385a85fe12eSEd Maste 		limit = 0;
138618f4c9dbSEd Maste 		ddata->is_functype = true;
1387a85fe12eSEd Maste 		for (;;) {
138818f4c9dbSEd Maste 			if (!cpp_demangle_read_type(ddata, &td))
1389a85fe12eSEd Maste 				return (0);
1390a85fe12eSEd Maste 			if (*ddata->cur == 'E')
1391a85fe12eSEd Maste 				break;
1392a85fe12eSEd Maste 			if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1393a85fe12eSEd Maste 				return (0);
1394a85fe12eSEd Maste 		}
139518f4c9dbSEd Maste 		ddata->is_functype = false;
139618f4c9dbSEd Maste 		if (td.paren) {
139718f4c9dbSEd Maste 			if (!DEM_PUSH_STR(ddata, ")"))
1398a85fe12eSEd Maste 				return (0);
139918f4c9dbSEd Maste 			td.paren = false;
140018f4c9dbSEd Maste 		}
140118f4c9dbSEd Maste 
140218f4c9dbSEd Maste 		/* Push CV qualifiers. */
140318f4c9dbSEd Maste 		ddata->push_qualifier = PUSH_CV_QUALIFIER;
140418f4c9dbSEd Maste 		if (!cpp_demangle_push_type_qualifier(ddata, v, NULL))
140518f4c9dbSEd Maste 			return (0);
140618f4c9dbSEd Maste 
140718f4c9dbSEd Maste 		ddata->push_qualifier = PUSH_ALL_QUALIFIER;
140818f4c9dbSEd Maste 
140918f4c9dbSEd Maste 		/* Release type qualifier vector. */
1410a85fe12eSEd Maste 		vector_type_qualifier_dest(v);
1411a85fe12eSEd Maste 		if (!vector_type_qualifier_init(v))
1412a85fe12eSEd Maste 			return (0);
1413a85fe12eSEd Maste 
141418f4c9dbSEd Maste 		/* Push ref-qualifiers. */
141518f4c9dbSEd Maste 		if (ddata->ref_qualifier) {
141618f4c9dbSEd Maste 			switch (ddata->ref_qualifier_type) {
141718f4c9dbSEd Maste 			case TYPE_REF:
141818f4c9dbSEd Maste 				if (!DEM_PUSH_STR(ddata, " &"))
1419a85fe12eSEd Maste 					return (0);
142018f4c9dbSEd Maste 				break;
142118f4c9dbSEd Maste 			case TYPE_RREF:
142218f4c9dbSEd Maste 				if (!DEM_PUSH_STR(ddata, " &&"))
142318f4c9dbSEd Maste 					return (0);
142418f4c9dbSEd Maste 				break;
142518f4c9dbSEd Maste 			default:
142618f4c9dbSEd Maste 				return (0);
142718f4c9dbSEd Maste 			}
142818f4c9dbSEd Maste 			ddata->ref_qualifier = false;
142918f4c9dbSEd Maste 		}
1430a85fe12eSEd Maste 	}
1431a85fe12eSEd Maste 
1432a85fe12eSEd Maste 	++ddata->cur;
1433a85fe12eSEd Maste 
1434a85fe12eSEd Maste 	return (1);
1435a85fe12eSEd Maste }
1436a85fe12eSEd Maste 
1437a85fe12eSEd Maste /* read encoding, encoding are function name, data name, special-name */
1438a85fe12eSEd Maste static int
cpp_demangle_read_encoding(struct cpp_demangle_data * ddata)1439a85fe12eSEd Maste cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
1440a85fe12eSEd Maste {
14413ef90571SEd Maste 	char *name, *type, *num_str;
14423ef90571SEd Maste 	long offset;
14433ef90571SEd Maste 	int rtn;
1444a85fe12eSEd Maste 
1445a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur == '\0')
1446a85fe12eSEd Maste 		return (0);
1447a85fe12eSEd Maste 
1448a85fe12eSEd Maste 	/* special name */
1449a85fe12eSEd Maste 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
14503ef90571SEd Maste 	case SIMPLE_HASH('G', 'A'):
1451bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "hidden alias for "))
14523ef90571SEd Maste 			return (0);
14533ef90571SEd Maste 		ddata->cur += 2;
14543ef90571SEd Maste 		if (*ddata->cur == '\0')
14553ef90571SEd Maste 			return (0);
14563ef90571SEd Maste 		return (cpp_demangle_read_encoding(ddata));
14573ef90571SEd Maste 
14583ef90571SEd Maste 	case SIMPLE_HASH('G', 'R'):
1459bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "reference temporary #"))
14603ef90571SEd Maste 			return (0);
14613ef90571SEd Maste 		ddata->cur += 2;
14623ef90571SEd Maste 		if (*ddata->cur == '\0')
14633ef90571SEd Maste 			return (0);
14643ef90571SEd Maste 		if (!cpp_demangle_read_name_flat(ddata, &name))
14653ef90571SEd Maste 			return (0);
14663ef90571SEd Maste 		rtn = 0;
14673ef90571SEd Maste 		if (!cpp_demangle_read_number_as_string(ddata, &num_str))
14683ef90571SEd Maste 			goto clean1;
1469bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, num_str))
14703ef90571SEd Maste 			goto clean2;
1471bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, " for "))
14723ef90571SEd Maste 			goto clean2;
1473bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, name))
14743ef90571SEd Maste 			goto clean2;
14753ef90571SEd Maste 		rtn = 1;
14763ef90571SEd Maste 	clean2:
14773ef90571SEd Maste 		free(num_str);
14783ef90571SEd Maste 	clean1:
14793ef90571SEd Maste 		free(name);
14803ef90571SEd Maste 		return (rtn);
14813ef90571SEd Maste 
14823ef90571SEd Maste 	case SIMPLE_HASH('G', 'T'):
14833ef90571SEd Maste 		ddata->cur += 2;
14843ef90571SEd Maste 		if (*ddata->cur == '\0')
14853ef90571SEd Maste 			return (0);
14863ef90571SEd Maste 		switch (*ddata->cur) {
14873ef90571SEd Maste 		case 'n':
1488bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "non-transaction clone for "))
14893ef90571SEd Maste 				return (0);
1490839529caSEd Maste 			break;
14913ef90571SEd Maste 		case 't':
14923ef90571SEd Maste 		default:
1493bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "transaction clone for "))
14943ef90571SEd Maste 				return (0);
1495839529caSEd Maste 			break;
14963ef90571SEd Maste 		}
14973ef90571SEd Maste 		++ddata->cur;
14983ef90571SEd Maste 		return (cpp_demangle_read_encoding(ddata));
14993ef90571SEd Maste 
1500a85fe12eSEd Maste 	case SIMPLE_HASH('G', 'V'):
1501a85fe12eSEd Maste 		/* sentry object for 1 time init */
1502bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "guard variable for "))
1503a85fe12eSEd Maste 			return (0);
1504a85fe12eSEd Maste 		ddata->cur += 2;
1505a85fe12eSEd Maste 		break;
1506a85fe12eSEd Maste 
1507a85fe12eSEd Maste 	case SIMPLE_HASH('T', 'c'):
1508a85fe12eSEd Maste 		/* virtual function covariant override thunk */
1509bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata,
1510bee2765cSEd Maste 		    "virtual function covariant override "))
1511a85fe12eSEd Maste 			return (0);
1512a85fe12eSEd Maste 		ddata->cur += 2;
1513a85fe12eSEd Maste 		if (*ddata->cur == '\0')
1514a85fe12eSEd Maste 			return (0);
1515a85fe12eSEd Maste 		if (!cpp_demangle_read_offset(ddata))
1516a85fe12eSEd Maste 			return (0);
1517a85fe12eSEd Maste 		if (!cpp_demangle_read_offset(ddata))
1518a85fe12eSEd Maste 			return (0);
1519a85fe12eSEd Maste 		return (cpp_demangle_read_encoding(ddata));
1520a85fe12eSEd Maste 
15213ef90571SEd Maste 	case SIMPLE_HASH('T', 'C'):
15223ef90571SEd Maste 		/* construction vtable */
1523bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "construction vtable for "))
15243ef90571SEd Maste 			return (0);
15253ef90571SEd Maste 		ddata->cur += 2;
15263ef90571SEd Maste 		if (*ddata->cur == '\0')
15273ef90571SEd Maste 			return (0);
15283ef90571SEd Maste 		if (!cpp_demangle_read_type_flat(ddata, &type))
15293ef90571SEd Maste 			return (0);
15303ef90571SEd Maste 		rtn = 0;
15313ef90571SEd Maste 		if (!cpp_demangle_read_number(ddata, &offset))
15323ef90571SEd Maste 			goto clean3;
15333ef90571SEd Maste 		if (*ddata->cur++ != '_')
15343ef90571SEd Maste 			goto clean3;
153518f4c9dbSEd Maste 		if (!cpp_demangle_read_type(ddata, NULL))
15363ef90571SEd Maste 			goto clean3;
1537bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "-in-"))
15383ef90571SEd Maste 			goto clean3;
1539bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, type))
15403ef90571SEd Maste 			goto clean3;
15413ef90571SEd Maste 		rtn = 1;
15423ef90571SEd Maste 	clean3:
15433ef90571SEd Maste 		free(type);
15443ef90571SEd Maste 		return (rtn);
15453ef90571SEd Maste 
1546a85fe12eSEd Maste 	case SIMPLE_HASH('T', 'D'):
1547a85fe12eSEd Maste 		/* typeinfo common proxy */
1548a85fe12eSEd Maste 		break;
1549a85fe12eSEd Maste 
15503ef90571SEd Maste 	case SIMPLE_HASH('T', 'F'):
15513ef90571SEd Maste 		/* typeinfo fn */
1552bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "typeinfo fn for "))
15533ef90571SEd Maste 			return (0);
15543ef90571SEd Maste 		ddata->cur += 2;
15553ef90571SEd Maste 		if (*ddata->cur == '\0')
15563ef90571SEd Maste 			return (0);
155718f4c9dbSEd Maste 		return (cpp_demangle_read_type(ddata, NULL));
15583ef90571SEd Maste 
1559a85fe12eSEd Maste 	case SIMPLE_HASH('T', 'h'):
1560a85fe12eSEd Maste 		/* virtual function non-virtual override thunk */
1561bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata,
1562bee2765cSEd Maste 		    "virtual function non-virtual override "))
1563a85fe12eSEd Maste 			return (0);
1564a85fe12eSEd Maste 		ddata->cur += 2;
1565a85fe12eSEd Maste 		if (*ddata->cur == '\0')
1566a85fe12eSEd Maste 			return (0);
1567a85fe12eSEd Maste 		if (!cpp_demangle_read_nv_offset(ddata))
1568a85fe12eSEd Maste 			return (0);
1569a85fe12eSEd Maste 		return (cpp_demangle_read_encoding(ddata));
1570a85fe12eSEd Maste 
15713ef90571SEd Maste 	case SIMPLE_HASH('T', 'H'):
15723ef90571SEd Maste 		/* TLS init function */
1573bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "TLS init function for "))
1574a85fe12eSEd Maste 			return (0);
1575a85fe12eSEd Maste 		ddata->cur += 2;
1576a85fe12eSEd Maste 		if (*ddata->cur == '\0')
1577a85fe12eSEd Maste 			return (0);
15783ef90571SEd Maste 		break;
15793ef90571SEd Maste 
15803ef90571SEd Maste 	case SIMPLE_HASH('T', 'I'):
15813ef90571SEd Maste 		/* typeinfo structure */
1582bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "typeinfo for "))
15833ef90571SEd Maste 			return (0);
15843ef90571SEd Maste 		ddata->cur += 2;
15853ef90571SEd Maste 		if (*ddata->cur == '\0')
15863ef90571SEd Maste 			return (0);
158718f4c9dbSEd Maste 		return (cpp_demangle_read_type(ddata, NULL));
15883ef90571SEd Maste 
15893ef90571SEd Maste 	case SIMPLE_HASH('T', 'J'):
15903ef90571SEd Maste 		/* java class */
1591bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "java Class for "))
15923ef90571SEd Maste 			return (0);
15933ef90571SEd Maste 		ddata->cur += 2;
15943ef90571SEd Maste 		if (*ddata->cur == '\0')
15953ef90571SEd Maste 			return (0);
159618f4c9dbSEd Maste 		return (cpp_demangle_read_type(ddata, NULL));
15973ef90571SEd Maste 
15983ef90571SEd Maste 	case SIMPLE_HASH('T', 'S'):
15993ef90571SEd Maste 		/* RTTI name (NTBS) */
1600bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "typeinfo name for "))
16013ef90571SEd Maste 			return (0);
16023ef90571SEd Maste 		ddata->cur += 2;
16033ef90571SEd Maste 		if (*ddata->cur == '\0')
16043ef90571SEd Maste 			return (0);
160518f4c9dbSEd Maste 		return (cpp_demangle_read_type(ddata, NULL));
1606a85fe12eSEd Maste 
1607a85fe12eSEd Maste 	case SIMPLE_HASH('T', 'T'):
1608a85fe12eSEd Maste 		/* VTT table */
1609bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "VTT for "))
1610a85fe12eSEd Maste 			return (0);
1611a85fe12eSEd Maste 		ddata->cur += 2;
16123ef90571SEd Maste 		if (*ddata->cur == '\0')
16133ef90571SEd Maste 			return (0);
161418f4c9dbSEd Maste 		return (cpp_demangle_read_type(ddata, NULL));
1615a85fe12eSEd Maste 
1616a85fe12eSEd Maste 	case SIMPLE_HASH('T', 'v'):
1617a85fe12eSEd Maste 		/* virtual function virtual override thunk */
1618715d1396SEd Maste 		if (!DEM_PUSH_STR(ddata, "virtual function virtual override "))
1619a85fe12eSEd Maste 			return (0);
1620a85fe12eSEd Maste 		ddata->cur += 2;
1621a85fe12eSEd Maste 		if (*ddata->cur == '\0')
1622a85fe12eSEd Maste 			return (0);
1623a85fe12eSEd Maste 		if (!cpp_demangle_read_v_offset(ddata))
1624a85fe12eSEd Maste 			return (0);
1625a85fe12eSEd Maste 		return (cpp_demangle_read_encoding(ddata));
1626a85fe12eSEd Maste 
1627a85fe12eSEd Maste 	case SIMPLE_HASH('T', 'V'):
1628a85fe12eSEd Maste 		/* virtual table */
1629bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "vtable for "))
1630a85fe12eSEd Maste 			return (0);
1631a85fe12eSEd Maste 		ddata->cur += 2;
1632a85fe12eSEd Maste 		if (*ddata->cur == '\0')
1633a85fe12eSEd Maste 			return (0);
163418f4c9dbSEd Maste 		return (cpp_demangle_read_type(ddata, NULL));
16353ef90571SEd Maste 
16363ef90571SEd Maste 	case SIMPLE_HASH('T', 'W'):
16373ef90571SEd Maste 		/* TLS wrapper function */
1638bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "TLS wrapper function for "))
16393ef90571SEd Maste 			return (0);
16403ef90571SEd Maste 		ddata->cur += 2;
16413ef90571SEd Maste 		if (*ddata->cur == '\0')
16423ef90571SEd Maste 			return (0);
16433ef90571SEd Maste 		break;
1644b6b6f9ccSEd Maste 	}
1645a85fe12eSEd Maste 
1646a85fe12eSEd Maste 	return (cpp_demangle_read_name(ddata));
1647a85fe12eSEd Maste }
1648a85fe12eSEd Maste 
1649a85fe12eSEd Maste static int
cpp_demangle_read_local_name(struct cpp_demangle_data * ddata)1650a85fe12eSEd Maste cpp_demangle_read_local_name(struct cpp_demangle_data *ddata)
1651a85fe12eSEd Maste {
165218f4c9dbSEd Maste 	struct vector_str local_name;
165318f4c9dbSEd Maste 	struct type_delimit td;
1654a85fe12eSEd Maste 	size_t limit;
165518f4c9dbSEd Maste 	bool  more_type;
1656a85fe12eSEd Maste 
1657a85fe12eSEd Maste 	if (ddata == NULL)
1658a85fe12eSEd Maste 		return (0);
1659a85fe12eSEd Maste 	if (*(++ddata->cur) == '\0')
1660a85fe12eSEd Maste 		return (0);
1661a85fe12eSEd Maste 
1662334f09a6SMark Johnston 	if (!vector_str_init(&local_name))
1663334f09a6SMark Johnston 		return (0);
166418f4c9dbSEd Maste 	ddata->cur_output = &local_name;
166518f4c9dbSEd Maste 
166618f4c9dbSEd Maste 	if (!cpp_demangle_read_encoding(ddata)) {
166718f4c9dbSEd Maste 		vector_str_dest(&local_name);
1668a85fe12eSEd Maste 		return (0);
166918f4c9dbSEd Maste 	}
167018f4c9dbSEd Maste 
167118f4c9dbSEd Maste 	ddata->cur_output = &ddata->output;
167218f4c9dbSEd Maste 
167318f4c9dbSEd Maste 	td.paren = false;
167418f4c9dbSEd Maste 	td.firstp = true;
167518f4c9dbSEd Maste 	more_type = false;
167618f4c9dbSEd Maste 	limit = 0;
167718f4c9dbSEd Maste 
167818f4c9dbSEd Maste 	/*
167918f4c9dbSEd Maste 	 * The first type is a return type if we just demangled template
168018f4c9dbSEd Maste 	 * args. (the template args is right next to the function name,
168118f4c9dbSEd Maste 	 * which means it's a template function)
168218f4c9dbSEd Maste 	 */
168318f4c9dbSEd Maste 	if (ddata->is_tmpl) {
168418f4c9dbSEd Maste 		ddata->is_tmpl = false;
168518f4c9dbSEd Maste 
168618f4c9dbSEd Maste 		/* Read return type */
168718f4c9dbSEd Maste 		if (!cpp_demangle_read_type(ddata, NULL)) {
168818f4c9dbSEd Maste 			vector_str_dest(&local_name);
168918f4c9dbSEd Maste 			return (0);
169018f4c9dbSEd Maste 		}
169118f4c9dbSEd Maste 
169218f4c9dbSEd Maste 		more_type = true;
169318f4c9dbSEd Maste 	}
169418f4c9dbSEd Maste 
169518f4c9dbSEd Maste 	/* Now we can push the name after possible return type is handled. */
169618f4c9dbSEd Maste 	if (!vector_str_push_vector(&ddata->output, &local_name)) {
169718f4c9dbSEd Maste 		vector_str_dest(&local_name);
169818f4c9dbSEd Maste 		return (0);
169918f4c9dbSEd Maste 	}
170018f4c9dbSEd Maste 	vector_str_dest(&local_name);
170118f4c9dbSEd Maste 
170218f4c9dbSEd Maste 	while (*ddata->cur != '\0') {
170318f4c9dbSEd Maste 		if (!cpp_demangle_read_type(ddata, &td))
170418f4c9dbSEd Maste 			return (0);
170518f4c9dbSEd Maste 		if (more_type)
170618f4c9dbSEd Maste 			more_type = false;
1707a85fe12eSEd Maste 		if (*ddata->cur == 'E')
1708a85fe12eSEd Maste 			break;
1709a85fe12eSEd Maste 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1710a85fe12eSEd Maste 			return (0);
1711a85fe12eSEd Maste 	}
171218f4c9dbSEd Maste 	if (more_type)
171318f4c9dbSEd Maste 		return (0);
171418f4c9dbSEd Maste 
1715a85fe12eSEd Maste 	if (*(++ddata->cur) == '\0')
1716a85fe12eSEd Maste 		return (0);
171718f4c9dbSEd Maste 	if (td.paren == true) {
1718bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, ")"))
1719a85fe12eSEd Maste 			return (0);
172018f4c9dbSEd Maste 		td.paren = false;
1721a85fe12eSEd Maste 	}
1722a85fe12eSEd Maste 	if (*ddata->cur == 's')
1723a85fe12eSEd Maste 		++ddata->cur;
1724a85fe12eSEd Maste 	else {
1725bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "::"))
1726a85fe12eSEd Maste 			return (0);
1727a85fe12eSEd Maste 		if (!cpp_demangle_read_name(ddata))
1728a85fe12eSEd Maste 			return (0);
1729a85fe12eSEd Maste 	}
1730a85fe12eSEd Maste 	if (*ddata->cur == '_') {
1731a85fe12eSEd Maste 		++ddata->cur;
1732a85fe12eSEd Maste 		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
1733a85fe12eSEd Maste 			++ddata->cur;
1734a85fe12eSEd Maste 	}
1735a85fe12eSEd Maste 
1736a85fe12eSEd Maste 	return (1);
1737a85fe12eSEd Maste }
1738a85fe12eSEd Maste 
1739a85fe12eSEd Maste static int
cpp_demangle_read_name(struct cpp_demangle_data * ddata)1740a85fe12eSEd Maste cpp_demangle_read_name(struct cpp_demangle_data *ddata)
1741a85fe12eSEd Maste {
1742a85fe12eSEd Maste 	struct vector_str *output, v;
1743a85fe12eSEd Maste 	size_t p_idx, subst_str_len;
1744a85fe12eSEd Maste 	int rtn;
1745a85fe12eSEd Maste 	char *subst_str;
1746a85fe12eSEd Maste 
1747a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur == '\0')
1748a85fe12eSEd Maste 		return (0);
1749a85fe12eSEd Maste 
175018f4c9dbSEd Maste 	output = ddata->cur_output;
1751a85fe12eSEd Maste 
1752a85fe12eSEd Maste 	subst_str = NULL;
1753a85fe12eSEd Maste 
1754a85fe12eSEd Maste 	switch (*ddata->cur) {
1755a85fe12eSEd Maste 	case 'S':
1756a85fe12eSEd Maste 		return (cpp_demangle_read_subst(ddata));
1757a85fe12eSEd Maste 	case 'N':
1758a85fe12eSEd Maste 		return (cpp_demangle_read_nested_name(ddata));
1759a85fe12eSEd Maste 	case 'Z':
1760a85fe12eSEd Maste 		return (cpp_demangle_read_local_name(ddata));
1761b6b6f9ccSEd Maste 	}
1762a85fe12eSEd Maste 
1763a85fe12eSEd Maste 	if (!vector_str_init(&v))
1764a85fe12eSEd Maste 		return (0);
1765a85fe12eSEd Maste 
1766a85fe12eSEd Maste 	p_idx = output->size;
1767a85fe12eSEd Maste 	rtn = 0;
1768a85fe12eSEd Maste 	if (!cpp_demangle_read_uqname(ddata))
1769a85fe12eSEd Maste 		goto clean;
1770a85fe12eSEd Maste 	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
1771a85fe12eSEd Maste 	    &subst_str_len)) == NULL)
1772a85fe12eSEd Maste 		goto clean;
1773a85fe12eSEd Maste 	if (subst_str_len > 8 && strstr(subst_str, "operator") != NULL) {
1774a85fe12eSEd Maste 		rtn = 1;
1775a85fe12eSEd Maste 		goto clean;
1776a85fe12eSEd Maste 	}
1777a85fe12eSEd Maste 	if (!vector_str_push(&v, subst_str, subst_str_len))
1778a85fe12eSEd Maste 		goto clean;
1779a85fe12eSEd Maste 	if (!cpp_demangle_push_subst_v(ddata, &v))
1780a85fe12eSEd Maste 		goto clean;
1781a85fe12eSEd Maste 
1782a85fe12eSEd Maste 	if (*ddata->cur == 'I') {
1783a85fe12eSEd Maste 		p_idx = output->size;
1784a85fe12eSEd Maste 		if (!cpp_demangle_read_tmpl_args(ddata))
1785a85fe12eSEd Maste 			goto clean;
1786a85fe12eSEd Maste 		free(subst_str);
1787a85fe12eSEd Maste 		if ((subst_str = vector_str_substr(output, p_idx,
1788a85fe12eSEd Maste 		    output->size - 1, &subst_str_len)) == NULL)
1789a85fe12eSEd Maste 			goto clean;
1790a85fe12eSEd Maste 		if (!vector_str_push(&v, subst_str, subst_str_len))
1791a85fe12eSEd Maste 			goto clean;
1792a85fe12eSEd Maste 		if (!cpp_demangle_push_subst_v(ddata, &v))
1793a85fe12eSEd Maste 			goto clean;
1794a85fe12eSEd Maste 	}
1795a85fe12eSEd Maste 
1796a85fe12eSEd Maste 	rtn = 1;
1797a85fe12eSEd Maste 
1798a85fe12eSEd Maste clean:
1799a85fe12eSEd Maste 	free(subst_str);
1800a85fe12eSEd Maste 	vector_str_dest(&v);
1801a85fe12eSEd Maste 
1802a85fe12eSEd Maste 	return (rtn);
1803a85fe12eSEd Maste }
1804a85fe12eSEd Maste 
1805a85fe12eSEd Maste static int
cpp_demangle_read_name_flat(struct cpp_demangle_data * ddata,char ** str)18063ef90571SEd Maste cpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str)
18073ef90571SEd Maste {
18083ef90571SEd Maste 	struct vector_str *output;
18093ef90571SEd Maste 	size_t i, p_idx, idx, name_len;
18103ef90571SEd Maste 	char *name;
18113ef90571SEd Maste 
181218f4c9dbSEd Maste 	output = ddata->cur_output;
18133ef90571SEd Maste 
18143ef90571SEd Maste 	p_idx = output->size;
18153ef90571SEd Maste 
18163ef90571SEd Maste 	if (!cpp_demangle_read_name(ddata))
18173ef90571SEd Maste 		return (0);
18183ef90571SEd Maste 
18193ef90571SEd Maste 	if ((name = vector_str_substr(output, p_idx, output->size - 1,
18203ef90571SEd Maste 	    &name_len)) == NULL)
18213ef90571SEd Maste 		return (0);
18223ef90571SEd Maste 
18233ef90571SEd Maste 	idx = output->size;
18243ef90571SEd Maste 	for (i = p_idx; i < idx; ++i) {
18253ef90571SEd Maste 		if (!vector_str_pop(output)) {
18263ef90571SEd Maste 			free(name);
18273ef90571SEd Maste 			return (0);
18283ef90571SEd Maste 		}
18293ef90571SEd Maste 	}
18303ef90571SEd Maste 
18313ef90571SEd Maste 	*str = name;
18323ef90571SEd Maste 
18333ef90571SEd Maste 	return (1);
18343ef90571SEd Maste }
18353ef90571SEd Maste 
18363ef90571SEd Maste static int
cpp_demangle_read_nested_name(struct cpp_demangle_data * ddata)1837a85fe12eSEd Maste cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
1838a85fe12eSEd Maste {
1839a85fe12eSEd Maste 	struct vector_str *output, v;
1840a85fe12eSEd Maste 	size_t limit, p_idx, subst_str_len;
1841a85fe12eSEd Maste 	int rtn;
1842a85fe12eSEd Maste 	char *subst_str;
1843a85fe12eSEd Maste 
1844a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur != 'N')
1845a85fe12eSEd Maste 		return (0);
1846a85fe12eSEd Maste 	if (*(++ddata->cur) == '\0')
1847a85fe12eSEd Maste 		return (0);
1848a85fe12eSEd Maste 
184918f4c9dbSEd Maste 	do {
1850a85fe12eSEd Maste 		switch (*ddata->cur) {
1851a85fe12eSEd Maste 		case 'r':
1852a85fe12eSEd Maste 			ddata->mem_rst = true;
1853a85fe12eSEd Maste 			break;
1854a85fe12eSEd Maste 		case 'V':
1855a85fe12eSEd Maste 			ddata->mem_vat = true;
1856a85fe12eSEd Maste 			break;
1857a85fe12eSEd Maste 		case 'K':
1858a85fe12eSEd Maste 			ddata->mem_cst = true;
1859a85fe12eSEd Maste 			break;
186018f4c9dbSEd Maste 		case 'R':
186118f4c9dbSEd Maste 			ddata->mem_ref = true;
186218f4c9dbSEd Maste 			break;
186318f4c9dbSEd Maste 		case 'O':
186418f4c9dbSEd Maste 			ddata->mem_rref = true;
186518f4c9dbSEd Maste 			break;
186618f4c9dbSEd Maste 		default:
186718f4c9dbSEd Maste 			goto next;
1868b6b6f9ccSEd Maste 		}
186918f4c9dbSEd Maste 	} while (*(++ddata->cur));
1870a85fe12eSEd Maste 
187118f4c9dbSEd Maste next:
187218f4c9dbSEd Maste 	output = ddata->cur_output;
1873a85fe12eSEd Maste 	if (!vector_str_init(&v))
1874a85fe12eSEd Maste 		return (0);
1875a85fe12eSEd Maste 
1876a85fe12eSEd Maste 	rtn = 0;
1877a85fe12eSEd Maste 	limit = 0;
1878a85fe12eSEd Maste 	for (;;) {
1879a85fe12eSEd Maste 		p_idx = output->size;
1880a85fe12eSEd Maste 		switch (*ddata->cur) {
1881a85fe12eSEd Maste 		case 'I':
1882a85fe12eSEd Maste 			if (!cpp_demangle_read_tmpl_args(ddata))
1883a85fe12eSEd Maste 				goto clean;
1884a85fe12eSEd Maste 			break;
1885a85fe12eSEd Maste 		case 'S':
1886a85fe12eSEd Maste 			if (!cpp_demangle_read_subst(ddata))
1887a85fe12eSEd Maste 				goto clean;
1888a85fe12eSEd Maste 			break;
1889a85fe12eSEd Maste 		case 'T':
1890a85fe12eSEd Maste 			if (!cpp_demangle_read_tmpl_param(ddata))
1891a85fe12eSEd Maste 				goto clean;
1892a85fe12eSEd Maste 			break;
1893a85fe12eSEd Maste 		default:
1894a85fe12eSEd Maste 			if (!cpp_demangle_read_uqname(ddata))
1895a85fe12eSEd Maste 				goto clean;
1896b6b6f9ccSEd Maste 		}
1897a85fe12eSEd Maste 
189818f4c9dbSEd Maste 		if (p_idx == output->size)
189918f4c9dbSEd Maste 			goto next_comp;
1900a85fe12eSEd Maste 		if ((subst_str = vector_str_substr(output, p_idx,
1901a85fe12eSEd Maste 		    output->size - 1, &subst_str_len)) == NULL)
1902a85fe12eSEd Maste 			goto clean;
1903a85fe12eSEd Maste 		if (!vector_str_push(&v, subst_str, subst_str_len)) {
1904a85fe12eSEd Maste 			free(subst_str);
1905a85fe12eSEd Maste 			goto clean;
1906a85fe12eSEd Maste 		}
1907a85fe12eSEd Maste 		free(subst_str);
1908a85fe12eSEd Maste 
1909a85fe12eSEd Maste 		if (!cpp_demangle_push_subst_v(ddata, &v))
1910a85fe12eSEd Maste 			goto clean;
191118f4c9dbSEd Maste 
191218f4c9dbSEd Maste 	next_comp:
1913a85fe12eSEd Maste 		if (*ddata->cur == 'E')
1914a85fe12eSEd Maste 			break;
191518f4c9dbSEd Maste 		else if (*ddata->cur != 'I' && *ddata->cur != 'C' &&
191618f4c9dbSEd Maste 		    *ddata->cur != 'D' && p_idx != output->size) {
1917bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "::"))
1918a85fe12eSEd Maste 				goto clean;
1919bee2765cSEd Maste 			if (!VEC_PUSH_STR(&v, "::"))
1920a85fe12eSEd Maste 				goto clean;
1921a85fe12eSEd Maste 		}
1922a85fe12eSEd Maste 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1923a85fe12eSEd Maste 			goto clean;
1924a85fe12eSEd Maste 	}
1925a85fe12eSEd Maste 
1926a85fe12eSEd Maste 	++ddata->cur;
1927a85fe12eSEd Maste 	rtn = 1;
1928a85fe12eSEd Maste 
1929a85fe12eSEd Maste clean:
1930a85fe12eSEd Maste 	vector_str_dest(&v);
1931a85fe12eSEd Maste 
1932a85fe12eSEd Maste 	return (rtn);
1933a85fe12eSEd Maste }
1934a85fe12eSEd Maste 
1935a85fe12eSEd Maste /*
1936a85fe12eSEd Maste  * read number
1937a85fe12eSEd Maste  * number ::= [n] <decimal>
1938a85fe12eSEd Maste  */
1939a85fe12eSEd Maste static int
cpp_demangle_read_number(struct cpp_demangle_data * ddata,long * rtn)1940a85fe12eSEd Maste cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
1941a85fe12eSEd Maste {
1942a85fe12eSEd Maste 	long len, negative_factor;
1943a85fe12eSEd Maste 
1944a85fe12eSEd Maste 	if (ddata == NULL || rtn == NULL)
1945a85fe12eSEd Maste 		return (0);
1946a85fe12eSEd Maste 
1947a85fe12eSEd Maste 	negative_factor = 1;
1948a85fe12eSEd Maste 	if (*ddata->cur == 'n') {
1949a85fe12eSEd Maste 		negative_factor = -1;
1950a85fe12eSEd Maste 
1951a85fe12eSEd Maste 		++ddata->cur;
1952a85fe12eSEd Maste 	}
1953a85fe12eSEd Maste 	if (ELFTC_ISDIGIT(*ddata->cur) == 0)
1954a85fe12eSEd Maste 		return (0);
1955a85fe12eSEd Maste 
1956a85fe12eSEd Maste 	errno = 0;
1957a85fe12eSEd Maste 	if ((len = strtol(ddata->cur, (char **) NULL, 10)) == 0 &&
1958a85fe12eSEd Maste 	    errno != 0)
1959a85fe12eSEd Maste 		return (0);
1960a85fe12eSEd Maste 
1961a85fe12eSEd Maste 	while (ELFTC_ISDIGIT(*ddata->cur) != 0)
1962a85fe12eSEd Maste 		++ddata->cur;
1963a85fe12eSEd Maste 
1964a85fe12eSEd Maste 	assert(len >= 0);
1965a85fe12eSEd Maste 	assert(negative_factor == 1 || negative_factor == -1);
1966a85fe12eSEd Maste 
1967a85fe12eSEd Maste 	*rtn = len * negative_factor;
1968a85fe12eSEd Maste 
1969a85fe12eSEd Maste 	return (1);
1970a85fe12eSEd Maste }
1971a85fe12eSEd Maste 
1972a85fe12eSEd Maste static int
cpp_demangle_read_number_as_string(struct cpp_demangle_data * ddata,char ** str)19733ef90571SEd Maste cpp_demangle_read_number_as_string(struct cpp_demangle_data *ddata, char **str)
19743ef90571SEd Maste {
19753ef90571SEd Maste 	long n;
19763ef90571SEd Maste 
19773ef90571SEd Maste 	if (!cpp_demangle_read_number(ddata, &n)) {
19783ef90571SEd Maste 		*str = NULL;
19793ef90571SEd Maste 		return (0);
19803ef90571SEd Maste 	}
19813ef90571SEd Maste 
19823ef90571SEd Maste 	if (asprintf(str, "%ld", n) < 0) {
19833ef90571SEd Maste 		*str = NULL;
19843ef90571SEd Maste 		return (0);
19853ef90571SEd Maste 	}
19863ef90571SEd Maste 
19873ef90571SEd Maste 	return (1);
19883ef90571SEd Maste }
19893ef90571SEd Maste 
19903ef90571SEd Maste static int
cpp_demangle_read_nv_offset(struct cpp_demangle_data * ddata)1991a85fe12eSEd Maste cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
1992a85fe12eSEd Maste {
1993a85fe12eSEd Maste 
1994a85fe12eSEd Maste 	if (ddata == NULL)
1995a85fe12eSEd Maste 		return (0);
1996a85fe12eSEd Maste 
1997bee2765cSEd Maste 	if (!DEM_PUSH_STR(ddata, "offset : "))
1998a85fe12eSEd Maste 		return (0);
1999a85fe12eSEd Maste 
2000a85fe12eSEd Maste 	return (cpp_demangle_read_offset_number(ddata));
2001a85fe12eSEd Maste }
2002a85fe12eSEd Maste 
2003a85fe12eSEd Maste /* read offset, offset are nv-offset, v-offset */
2004a85fe12eSEd Maste static int
cpp_demangle_read_offset(struct cpp_demangle_data * ddata)2005a85fe12eSEd Maste cpp_demangle_read_offset(struct cpp_demangle_data *ddata)
2006a85fe12eSEd Maste {
2007a85fe12eSEd Maste 
2008a85fe12eSEd Maste 	if (ddata == NULL)
2009a85fe12eSEd Maste 		return (0);
2010a85fe12eSEd Maste 
2011a85fe12eSEd Maste 	if (*ddata->cur == 'h') {
2012a85fe12eSEd Maste 		++ddata->cur;
2013a85fe12eSEd Maste 		return (cpp_demangle_read_nv_offset(ddata));
2014a85fe12eSEd Maste 	} else if (*ddata->cur == 'v') {
2015a85fe12eSEd Maste 		++ddata->cur;
2016a85fe12eSEd Maste 		return (cpp_demangle_read_v_offset(ddata));
2017a85fe12eSEd Maste 	}
2018a85fe12eSEd Maste 
2019a85fe12eSEd Maste 	return (0);
2020a85fe12eSEd Maste }
2021a85fe12eSEd Maste 
2022a85fe12eSEd Maste static int
cpp_demangle_read_offset_number(struct cpp_demangle_data * ddata)2023a85fe12eSEd Maste cpp_demangle_read_offset_number(struct cpp_demangle_data *ddata)
2024a85fe12eSEd Maste {
2025a85fe12eSEd Maste 	bool negative;
2026a85fe12eSEd Maste 	const char *start;
2027a85fe12eSEd Maste 
2028a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur == '\0')
2029a85fe12eSEd Maste 		return (0);
2030a85fe12eSEd Maste 
2031a85fe12eSEd Maste 	/* offset could be negative */
2032a85fe12eSEd Maste 	if (*ddata->cur == 'n') {
2033a85fe12eSEd Maste 		negative = true;
2034a85fe12eSEd Maste 		start = ddata->cur + 1;
2035a85fe12eSEd Maste 	} else {
2036a85fe12eSEd Maste 		negative = false;
2037a85fe12eSEd Maste 		start = ddata->cur;
2038a85fe12eSEd Maste 	}
2039a85fe12eSEd Maste 
2040a85fe12eSEd Maste 	while (*ddata->cur != '_')
2041a85fe12eSEd Maste 		++ddata->cur;
2042a85fe12eSEd Maste 
2043bee2765cSEd Maste 	if (negative && !DEM_PUSH_STR(ddata, "-"))
2044a85fe12eSEd Maste 		return (0);
2045a85fe12eSEd Maste 
2046a85fe12eSEd Maste 	assert(start != NULL);
2047a85fe12eSEd Maste 
2048a85fe12eSEd Maste 	if (!cpp_demangle_push_str(ddata, start, ddata->cur - start))
2049a85fe12eSEd Maste 		return (0);
2050bee2765cSEd Maste 	if (!DEM_PUSH_STR(ddata, " "))
2051a85fe12eSEd Maste 		return (0);
2052a85fe12eSEd Maste 
2053a85fe12eSEd Maste 	++ddata->cur;
2054a85fe12eSEd Maste 
2055a85fe12eSEd Maste 	return (1);
2056a85fe12eSEd Maste }
2057a85fe12eSEd Maste 
2058a85fe12eSEd Maste static int
cpp_demangle_read_pointer_to_member(struct cpp_demangle_data * ddata,struct vector_type_qualifier * v)205918f4c9dbSEd Maste cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata,
206018f4c9dbSEd Maste     struct vector_type_qualifier *v)
2061a85fe12eSEd Maste {
2062a85fe12eSEd Maste 	size_t class_type_len, i, idx, p_idx;
2063a85fe12eSEd Maste 	int p_func_type, rtn;
2064a85fe12eSEd Maste 	char *class_type;
2065a85fe12eSEd Maste 
2066a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur != 'M' || *(++ddata->cur) == '\0')
2067a85fe12eSEd Maste 		return (0);
2068a85fe12eSEd Maste 
2069a85fe12eSEd Maste 	p_idx = ddata->output.size;
207018f4c9dbSEd Maste 	if (!cpp_demangle_read_type(ddata, NULL))
2071a85fe12eSEd Maste 		return (0);
2072a85fe12eSEd Maste 
2073a85fe12eSEd Maste 	if ((class_type = vector_str_substr(&ddata->output, p_idx,
2074a85fe12eSEd Maste 	    ddata->output.size - 1, &class_type_len)) == NULL)
2075a85fe12eSEd Maste 		return (0);
2076a85fe12eSEd Maste 
2077a85fe12eSEd Maste 	rtn = 0;
2078a85fe12eSEd Maste 	idx = ddata->output.size;
2079a85fe12eSEd Maste 	for (i = p_idx; i < idx; ++i)
2080a85fe12eSEd Maste 		if (!vector_str_pop(&ddata->output))
2081a85fe12eSEd Maste 			goto clean1;
2082a85fe12eSEd Maste 
208318f4c9dbSEd Maste 	if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM, v))
2084a85fe12eSEd Maste 		goto clean1;
2085a85fe12eSEd Maste 
2086a85fe12eSEd Maste 	if (!vector_str_push(&ddata->class_type, class_type, class_type_len))
2087a85fe12eSEd Maste 		goto clean2;
2088a85fe12eSEd Maste 
2089a85fe12eSEd Maste 	p_func_type = ddata->func_type;
209018f4c9dbSEd Maste 	if (!cpp_demangle_read_type(ddata, NULL))
2091a85fe12eSEd Maste 		goto clean3;
2092a85fe12eSEd Maste 
2093a85fe12eSEd Maste 	if (p_func_type == ddata->func_type) {
2094bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, " "))
2095a85fe12eSEd Maste 			goto clean3;
2096a85fe12eSEd Maste 		if (!cpp_demangle_push_str(ddata, class_type, class_type_len))
2097a85fe12eSEd Maste 			goto clean3;
2098bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "::*"))
2099a85fe12eSEd Maste 			goto clean3;
2100a85fe12eSEd Maste 	}
2101a85fe12eSEd Maste 
2102a85fe12eSEd Maste 	rtn = 1;
2103a85fe12eSEd Maste clean3:
2104a85fe12eSEd Maste 	if (!vector_str_pop(&ddata->class_type))
2105a85fe12eSEd Maste 		rtn = 0;
2106a85fe12eSEd Maste clean2:
2107a85fe12eSEd Maste 	if (!vector_read_cmd_pop(&ddata->cmd))
2108a85fe12eSEd Maste 		rtn = 0;
2109a85fe12eSEd Maste clean1:
2110a85fe12eSEd Maste 	free(class_type);
2111a85fe12eSEd Maste 
211218f4c9dbSEd Maste 	vector_type_qualifier_dest(v);
211318f4c9dbSEd Maste 	if (!vector_type_qualifier_init(v))
211418f4c9dbSEd Maste 		return (0);
211518f4c9dbSEd Maste 
2116a85fe12eSEd Maste 	return (rtn);
2117a85fe12eSEd Maste }
2118a85fe12eSEd Maste 
2119a85fe12eSEd Maste /* read source-name, source-name is <len> <ID> */
2120a85fe12eSEd Maste static int
cpp_demangle_read_sname(struct cpp_demangle_data * ddata)2121a85fe12eSEd Maste cpp_demangle_read_sname(struct cpp_demangle_data *ddata)
2122a85fe12eSEd Maste {
2123a85fe12eSEd Maste 	long len;
21243ef90571SEd Maste 	int err;
2125a85fe12eSEd Maste 
2126a85fe12eSEd Maste 	if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
21273ef90571SEd Maste 	    len <= 0)
21283ef90571SEd Maste 		return (0);
21293ef90571SEd Maste 
21303ef90571SEd Maste 	if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0))
2131bee2765cSEd Maste 		err = DEM_PUSH_STR(ddata, "(anonymous namespace)");
21323ef90571SEd Maste 	else
21333ef90571SEd Maste 		err = cpp_demangle_push_str(ddata, ddata->cur, len);
21343ef90571SEd Maste 
21353ef90571SEd Maste 	if (err == 0)
2136a85fe12eSEd Maste 		return (0);
2137a85fe12eSEd Maste 
2138c2bffd0aSDimitry Andric 	assert(ddata->cur_output->size > 0);
213918f4c9dbSEd Maste 	if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == NULL)
2140a85fe12eSEd Maste 		ddata->last_sname =
2141*12be6f12SJustine Tunney 		    ddata->cur_output->container[ddata->cur_output->size - 1];
2142a85fe12eSEd Maste 
2143a85fe12eSEd Maste 	ddata->cur += len;
2144a85fe12eSEd Maste 
2145a85fe12eSEd Maste 	return (1);
2146a85fe12eSEd Maste }
2147a85fe12eSEd Maste 
2148a85fe12eSEd Maste static int
cpp_demangle_read_subst(struct cpp_demangle_data * ddata)2149a85fe12eSEd Maste cpp_demangle_read_subst(struct cpp_demangle_data *ddata)
2150a85fe12eSEd Maste {
2151a85fe12eSEd Maste 	long nth;
2152a85fe12eSEd Maste 
2153a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur == '\0')
2154a85fe12eSEd Maste 		return (0);
2155a85fe12eSEd Maste 
2156a85fe12eSEd Maste 	/* abbreviations of the form Sx */
2157a85fe12eSEd Maste 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
2158a85fe12eSEd Maste 	case SIMPLE_HASH('S', 'a'):
2159a85fe12eSEd Maste 		/* std::allocator */
2160bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "std::allocator"))
2161a85fe12eSEd Maste 			return (0);
2162a85fe12eSEd Maste 		ddata->cur += 2;
2163a85fe12eSEd Maste 		if (*ddata->cur == 'I')
2164a85fe12eSEd Maste 			return (cpp_demangle_read_subst_stdtmpl(ddata,
216518f4c9dbSEd Maste 			    "std::allocator"));
2166a85fe12eSEd Maste 		return (1);
2167a85fe12eSEd Maste 
2168a85fe12eSEd Maste 	case SIMPLE_HASH('S', 'b'):
2169a85fe12eSEd Maste 		/* std::basic_string */
2170bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "std::basic_string"))
2171a85fe12eSEd Maste 			return (0);
2172a85fe12eSEd Maste 		ddata->cur += 2;
2173a85fe12eSEd Maste 		if (*ddata->cur == 'I')
2174a85fe12eSEd Maste 			return (cpp_demangle_read_subst_stdtmpl(ddata,
217518f4c9dbSEd Maste 			    "std::basic_string"));
2176a85fe12eSEd Maste 		return (1);
2177a85fe12eSEd Maste 
2178a85fe12eSEd Maste 	case SIMPLE_HASH('S', 'd'):
2179a85fe12eSEd Maste 		/* std::basic_iostream<char, std::char_traits<char> > */
218018f4c9dbSEd Maste 		if (!DEM_PUSH_STR(ddata, "std::basic_iostream<char, "
218118f4c9dbSEd Maste 		    "std::char_traits<char> >"))
2182a85fe12eSEd Maste 			return (0);
2183839529caSEd Maste 		ddata->last_sname = "basic_iostream";
2184a85fe12eSEd Maste 		ddata->cur += 2;
2185a85fe12eSEd Maste 		if (*ddata->cur == 'I')
2186a85fe12eSEd Maste 			return (cpp_demangle_read_subst_stdtmpl(ddata,
218718f4c9dbSEd Maste 			    "std::basic_iostream<char, std::char_traits"
218818f4c9dbSEd Maste 				"<char> >"));
2189a85fe12eSEd Maste 		return (1);
2190a85fe12eSEd Maste 
2191a85fe12eSEd Maste 	case SIMPLE_HASH('S', 'i'):
2192a85fe12eSEd Maste 		/* std::basic_istream<char, std::char_traits<char> > */
219318f4c9dbSEd Maste 		if (!DEM_PUSH_STR(ddata, "std::basic_istream<char, "
219418f4c9dbSEd Maste 		    "std::char_traits<char> >"))
2195a85fe12eSEd Maste 			return (0);
2196839529caSEd Maste 		ddata->last_sname = "basic_istream";
2197a85fe12eSEd Maste 		ddata->cur += 2;
2198a85fe12eSEd Maste 		if (*ddata->cur == 'I')
2199a85fe12eSEd Maste 			return (cpp_demangle_read_subst_stdtmpl(ddata,
220018f4c9dbSEd Maste 			    "std::basic_istream<char, std::char_traits"
220118f4c9dbSEd Maste 				"<char> >"));
2202a85fe12eSEd Maste 		return (1);
2203a85fe12eSEd Maste 
2204a85fe12eSEd Maste 	case SIMPLE_HASH('S', 'o'):
2205a85fe12eSEd Maste 		/* std::basic_ostream<char, std::char_traits<char> > */
220618f4c9dbSEd Maste 		if (!DEM_PUSH_STR(ddata, "std::basic_ostream<char, "
220718f4c9dbSEd Maste 		    "std::char_traits<char> >"))
2208a85fe12eSEd Maste 			return (0);
2209839529caSEd Maste 		ddata->last_sname = "basic_ostream";
2210a85fe12eSEd Maste 		ddata->cur += 2;
2211a85fe12eSEd Maste 		if (*ddata->cur == 'I')
2212a85fe12eSEd Maste 			return (cpp_demangle_read_subst_stdtmpl(ddata,
221318f4c9dbSEd Maste 			    "std::basic_ostream<char, std::char_traits"
221418f4c9dbSEd Maste 				"<char> >"));
2215a85fe12eSEd Maste 		return (1);
2216a85fe12eSEd Maste 
2217a85fe12eSEd Maste 	case SIMPLE_HASH('S', 's'):
2218a85fe12eSEd Maste 		/*
2219a85fe12eSEd Maste 		 * std::basic_string<char, std::char_traits<char>,
2220a85fe12eSEd Maste 		 * std::allocator<char> >
2221a85fe12eSEd Maste 		 *
2222a85fe12eSEd Maste 		 * a.k.a std::string
2223a85fe12eSEd Maste 		 */
222418f4c9dbSEd Maste 		if (!DEM_PUSH_STR(ddata, "std::basic_string<char, "
222518f4c9dbSEd Maste 		    "std::char_traits<char>, std::allocator<char> >"))
2226a85fe12eSEd Maste 			return (0);
2227a85fe12eSEd Maste 		ddata->last_sname = "string";
2228a85fe12eSEd Maste 		ddata->cur += 2;
2229a85fe12eSEd Maste 		if (*ddata->cur == 'I')
2230a85fe12eSEd Maste 			return (cpp_demangle_read_subst_stdtmpl(ddata,
223118f4c9dbSEd Maste 			    "std::basic_string<char, std::char_traits<char>,"
223218f4c9dbSEd Maste 				" std::allocator<char> >"));
2233a85fe12eSEd Maste 		return (1);
2234a85fe12eSEd Maste 
2235a85fe12eSEd Maste 	case SIMPLE_HASH('S', 't'):
2236a85fe12eSEd Maste 		/* std:: */
2237a85fe12eSEd Maste 		return (cpp_demangle_read_subst_std(ddata));
2238b6b6f9ccSEd Maste 	}
2239a85fe12eSEd Maste 
2240a85fe12eSEd Maste 	if (*(++ddata->cur) == '\0')
2241a85fe12eSEd Maste 		return (0);
2242a85fe12eSEd Maste 
224318f4c9dbSEd Maste 	/* Skip unknown substitution abbreviations. */
224418f4c9dbSEd Maste 	if (!(*ddata->cur >= '0' && *ddata->cur <= '9') &&
224518f4c9dbSEd Maste 	    !(*ddata->cur >= 'A' && *ddata->cur <= 'Z') &&
224618f4c9dbSEd Maste 	    *ddata->cur != '_') {
224718f4c9dbSEd Maste 		++ddata->cur;
224818f4c9dbSEd Maste 		return (1);
224918f4c9dbSEd Maste 	}
225018f4c9dbSEd Maste 
2251a85fe12eSEd Maste 	/* substitution */
2252a85fe12eSEd Maste 	if (*ddata->cur == '_')
2253a85fe12eSEd Maste 		return (cpp_demangle_get_subst(ddata, 0));
2254a85fe12eSEd Maste 	else {
2255a85fe12eSEd Maste 		errno = 0;
2256a85fe12eSEd Maste 		/* substitution number is base 36 */
2257a85fe12eSEd Maste 		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
2258a85fe12eSEd Maste 		    errno != 0)
2259a85fe12eSEd Maste 			return (0);
2260a85fe12eSEd Maste 
2261a85fe12eSEd Maste 		/* first was '_', so increase one */
2262a85fe12eSEd Maste 		++nth;
2263a85fe12eSEd Maste 
2264a85fe12eSEd Maste 		while (*ddata->cur != '_')
2265a85fe12eSEd Maste 			++ddata->cur;
2266a85fe12eSEd Maste 
2267a85fe12eSEd Maste 		assert(nth > 0);
2268a85fe12eSEd Maste 
2269a85fe12eSEd Maste 		return (cpp_demangle_get_subst(ddata, nth));
2270a85fe12eSEd Maste 	}
2271a85fe12eSEd Maste 
2272a85fe12eSEd Maste 	/* NOTREACHED */
2273a85fe12eSEd Maste 	return (0);
2274a85fe12eSEd Maste }
2275a85fe12eSEd Maste 
2276a85fe12eSEd Maste static int
cpp_demangle_read_subst_std(struct cpp_demangle_data * ddata)2277a85fe12eSEd Maste cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
2278a85fe12eSEd Maste {
2279a85fe12eSEd Maste 	struct vector_str *output, v;
2280a85fe12eSEd Maste 	size_t p_idx, subst_str_len;
2281a85fe12eSEd Maste 	int rtn;
2282a85fe12eSEd Maste 	char *subst_str;
2283a85fe12eSEd Maste 
2284a85fe12eSEd Maste 	if (ddata == NULL)
2285a85fe12eSEd Maste 		return (0);
2286a85fe12eSEd Maste 
2287a85fe12eSEd Maste 	if (!vector_str_init(&v))
2288a85fe12eSEd Maste 		return (0);
2289a85fe12eSEd Maste 
2290a85fe12eSEd Maste 	subst_str = NULL;
2291a85fe12eSEd Maste 	rtn = 0;
2292bee2765cSEd Maste 	if (!DEM_PUSH_STR(ddata, "std::"))
2293a85fe12eSEd Maste 		goto clean;
2294a85fe12eSEd Maste 
2295bee2765cSEd Maste 	if (!VEC_PUSH_STR(&v, "std::"))
2296a85fe12eSEd Maste 		goto clean;
2297a85fe12eSEd Maste 
2298a85fe12eSEd Maste 	ddata->cur += 2;
2299a85fe12eSEd Maste 
230018f4c9dbSEd Maste 	output = ddata->cur_output;
2301a85fe12eSEd Maste 
2302a85fe12eSEd Maste 	p_idx = output->size;
2303a85fe12eSEd Maste 	if (!cpp_demangle_read_uqname(ddata))
2304a85fe12eSEd Maste 		goto clean;
2305a85fe12eSEd Maste 
2306a85fe12eSEd Maste 	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
2307a85fe12eSEd Maste 	    &subst_str_len)) == NULL)
2308a85fe12eSEd Maste 		goto clean;
2309a85fe12eSEd Maste 
2310a85fe12eSEd Maste 	if (!vector_str_push(&v, subst_str, subst_str_len))
2311a85fe12eSEd Maste 		goto clean;
2312a85fe12eSEd Maste 
2313a85fe12eSEd Maste 	if (!cpp_demangle_push_subst_v(ddata, &v))
2314a85fe12eSEd Maste 		goto clean;
2315a85fe12eSEd Maste 
2316a85fe12eSEd Maste 	if (*ddata->cur == 'I') {
2317a85fe12eSEd Maste 		p_idx = output->size;
2318a85fe12eSEd Maste 		if (!cpp_demangle_read_tmpl_args(ddata))
2319a85fe12eSEd Maste 			goto clean;
2320a85fe12eSEd Maste 		free(subst_str);
2321a85fe12eSEd Maste 		if ((subst_str = vector_str_substr(output, p_idx,
2322a85fe12eSEd Maste 		    output->size - 1, &subst_str_len)) == NULL)
2323a85fe12eSEd Maste 			goto clean;
2324a85fe12eSEd Maste 		if (!vector_str_push(&v, subst_str, subst_str_len))
2325a85fe12eSEd Maste 			goto clean;
2326a85fe12eSEd Maste 		if (!cpp_demangle_push_subst_v(ddata, &v))
2327a85fe12eSEd Maste 			goto clean;
2328a85fe12eSEd Maste 	}
2329a85fe12eSEd Maste 
2330a85fe12eSEd Maste 	rtn = 1;
2331a85fe12eSEd Maste clean:
2332a85fe12eSEd Maste 	free(subst_str);
2333a85fe12eSEd Maste 	vector_str_dest(&v);
2334a85fe12eSEd Maste 
2335a85fe12eSEd Maste 	return (rtn);
2336a85fe12eSEd Maste }
2337a85fe12eSEd Maste 
2338a85fe12eSEd Maste static int
cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data * ddata,const char * str)2339a85fe12eSEd Maste cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
234018f4c9dbSEd Maste     const char *str)
2341a85fe12eSEd Maste {
2342a85fe12eSEd Maste 	struct vector_str *output;
234318f4c9dbSEd Maste 	size_t p_idx, substr_len, len;
2344a85fe12eSEd Maste 	int rtn;
2345a85fe12eSEd Maste 	char *subst_str, *substr;
2346a85fe12eSEd Maste 
234718f4c9dbSEd Maste 	if (ddata == NULL || str == NULL)
2348a85fe12eSEd Maste 		return (0);
2349a85fe12eSEd Maste 
235018f4c9dbSEd Maste 	if ((len = strlen(str)) == 0)
235118f4c9dbSEd Maste 		return (0);
235218f4c9dbSEd Maste 
235318f4c9dbSEd Maste 	output = ddata->cur_output;
2354a85fe12eSEd Maste 
2355a85fe12eSEd Maste 	p_idx = output->size;
2356a85fe12eSEd Maste 	substr = NULL;
2357a85fe12eSEd Maste 	subst_str = NULL;
2358a85fe12eSEd Maste 
2359a85fe12eSEd Maste 	if (!cpp_demangle_read_tmpl_args(ddata))
2360a85fe12eSEd Maste 		return (0);
2361a85fe12eSEd Maste 	if ((substr = vector_str_substr(output, p_idx, output->size - 1,
2362a85fe12eSEd Maste 	    &substr_len)) == NULL)
2363a85fe12eSEd Maste 		return (0);
2364a85fe12eSEd Maste 
2365a85fe12eSEd Maste 	rtn = 0;
2366a85fe12eSEd Maste 	if ((subst_str = malloc(sizeof(char) * (substr_len + len + 1))) ==
2367a85fe12eSEd Maste 	    NULL)
2368a85fe12eSEd Maste 		goto clean;
2369a85fe12eSEd Maste 
2370a85fe12eSEd Maste 	memcpy(subst_str, str, len);
2371a85fe12eSEd Maste 	memcpy(subst_str + len, substr, substr_len);
2372a85fe12eSEd Maste 	subst_str[substr_len + len] = '\0';
2373a85fe12eSEd Maste 
2374a85fe12eSEd Maste 	if (!cpp_demangle_push_subst(ddata, subst_str, substr_len + len))
2375a85fe12eSEd Maste 		goto clean;
2376a85fe12eSEd Maste 
2377a85fe12eSEd Maste 	rtn = 1;
2378a85fe12eSEd Maste clean:
2379a85fe12eSEd Maste 	free(subst_str);
2380a85fe12eSEd Maste 	free(substr);
2381a85fe12eSEd Maste 
2382a85fe12eSEd Maste 	return (rtn);
2383a85fe12eSEd Maste }
2384a85fe12eSEd Maste 
2385a85fe12eSEd Maste static int
cpp_demangle_read_tmpl_arg(struct cpp_demangle_data * ddata)2386a85fe12eSEd Maste cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *ddata)
2387a85fe12eSEd Maste {
2388a85fe12eSEd Maste 
2389a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur == '\0')
2390a85fe12eSEd Maste 		return (0);
2391a85fe12eSEd Maste 
2392a85fe12eSEd Maste 	switch (*ddata->cur) {
2393a85fe12eSEd Maste 	case 'L':
2394a85fe12eSEd Maste 		return (cpp_demangle_read_expr_primary(ddata));
2395a85fe12eSEd Maste 	case 'X':
239618f4c9dbSEd Maste 		++ddata->cur;
239718f4c9dbSEd Maste 		if (!cpp_demangle_read_expression(ddata))
239818f4c9dbSEd Maste 			return (0);
239918f4c9dbSEd Maste 		return (*ddata->cur++ == 'E');
2400b6b6f9ccSEd Maste 	}
2401a85fe12eSEd Maste 
240218f4c9dbSEd Maste 	return (cpp_demangle_read_type(ddata, NULL));
2403a85fe12eSEd Maste }
2404a85fe12eSEd Maste 
2405a85fe12eSEd Maste static int
cpp_demangle_read_tmpl_args(struct cpp_demangle_data * ddata)2406a85fe12eSEd Maste cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
2407a85fe12eSEd Maste {
2408a85fe12eSEd Maste 	struct vector_str *v;
2409a85fe12eSEd Maste 	size_t arg_len, idx, limit, size;
2410a85fe12eSEd Maste 	char *arg;
2411a85fe12eSEd Maste 
2412a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur == '\0')
2413a85fe12eSEd Maste 		return (0);
2414a85fe12eSEd Maste 
2415a85fe12eSEd Maste 	++ddata->cur;
2416a85fe12eSEd Maste 
241718f4c9dbSEd Maste 	if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL, NULL))
2418a85fe12eSEd Maste 		return (0);
2419a85fe12eSEd Maste 
2420bee2765cSEd Maste 	if (!DEM_PUSH_STR(ddata, "<"))
2421a85fe12eSEd Maste 		return (0);
2422a85fe12eSEd Maste 
2423a85fe12eSEd Maste 	limit = 0;
2424c2bffd0aSDimitry Andric 	v = ddata->cur_output;
2425a85fe12eSEd Maste 	for (;;) {
2426a85fe12eSEd Maste 		idx = v->size;
2427a85fe12eSEd Maste 		if (!cpp_demangle_read_tmpl_arg(ddata))
2428a85fe12eSEd Maste 			return (0);
2429a85fe12eSEd Maste 		if ((arg = vector_str_substr(v, idx, v->size - 1, &arg_len)) ==
2430a85fe12eSEd Maste 		    NULL)
2431a85fe12eSEd Maste 			return (0);
2432a85fe12eSEd Maste 		if (!vector_str_find(&ddata->tmpl, arg, arg_len) &&
2433a85fe12eSEd Maste 		    !vector_str_push(&ddata->tmpl, arg, arg_len)) {
2434a85fe12eSEd Maste 			free(arg);
2435a85fe12eSEd Maste 			return (0);
2436a85fe12eSEd Maste 		}
2437a85fe12eSEd Maste 
2438a85fe12eSEd Maste 		free(arg);
2439a85fe12eSEd Maste 
2440a85fe12eSEd Maste 		if (*ddata->cur == 'E') {
2441a85fe12eSEd Maste 			++ddata->cur;
2442a85fe12eSEd Maste 			size = v->size;
2443a85fe12eSEd Maste 			assert(size > 0);
2444a85fe12eSEd Maste 			if (!strncmp(v->container[size - 1], ">", 1)) {
2445bee2765cSEd Maste 				if (!DEM_PUSH_STR(ddata, " >"))
2446a85fe12eSEd Maste 					return (0);
2447bee2765cSEd Maste 			} else if (!DEM_PUSH_STR(ddata, ">"))
2448a85fe12eSEd Maste 				return (0);
244918f4c9dbSEd Maste 			ddata->is_tmpl = true;
2450a85fe12eSEd Maste 			break;
2451a85fe12eSEd Maste 		} else if (*ddata->cur != 'I' &&
2452bee2765cSEd Maste 		    !DEM_PUSH_STR(ddata, ", "))
2453a85fe12eSEd Maste 			return (0);
2454a85fe12eSEd Maste 
2455a85fe12eSEd Maste 		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
2456a85fe12eSEd Maste 			return (0);
2457a85fe12eSEd Maste 	}
2458a85fe12eSEd Maste 
2459a85fe12eSEd Maste 	return (vector_read_cmd_pop(&ddata->cmd));
2460a85fe12eSEd Maste }
2461a85fe12eSEd Maste 
2462a85fe12eSEd Maste /*
2463a85fe12eSEd Maste  * Read template parameter that forms in 'T[number]_'.
2464a85fe12eSEd Maste  * This function much like to read_subst but only for types.
2465a85fe12eSEd Maste  */
2466a85fe12eSEd Maste static int
cpp_demangle_read_tmpl_param(struct cpp_demangle_data * ddata)2467a85fe12eSEd Maste cpp_demangle_read_tmpl_param(struct cpp_demangle_data *ddata)
2468a85fe12eSEd Maste {
2469a85fe12eSEd Maste 	long nth;
2470a85fe12eSEd Maste 
2471a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur != 'T')
2472a85fe12eSEd Maste 		return (0);
2473a85fe12eSEd Maste 
2474a85fe12eSEd Maste 	++ddata->cur;
2475a85fe12eSEd Maste 
2476a85fe12eSEd Maste 	if (*ddata->cur == '_')
2477a85fe12eSEd Maste 		return (cpp_demangle_get_tmpl_param(ddata, 0));
2478a85fe12eSEd Maste 	else {
2479a85fe12eSEd Maste 
2480a85fe12eSEd Maste 		errno = 0;
2481a85fe12eSEd Maste 		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
2482a85fe12eSEd Maste 		    errno != 0)
2483a85fe12eSEd Maste 			return (0);
2484a85fe12eSEd Maste 
2485a85fe12eSEd Maste 		/* T_ is first */
2486a85fe12eSEd Maste 		++nth;
2487a85fe12eSEd Maste 
2488a85fe12eSEd Maste 		while (*ddata->cur != '_')
2489a85fe12eSEd Maste 			++ddata->cur;
2490a85fe12eSEd Maste 
2491a85fe12eSEd Maste 		assert(nth > 0);
2492a85fe12eSEd Maste 
2493a85fe12eSEd Maste 		return (cpp_demangle_get_tmpl_param(ddata, nth));
2494a85fe12eSEd Maste 	}
2495a85fe12eSEd Maste 
2496a85fe12eSEd Maste 	/* NOTREACHED */
2497a85fe12eSEd Maste 	return (0);
2498a85fe12eSEd Maste }
2499a85fe12eSEd Maste 
2500a85fe12eSEd Maste static int
cpp_demangle_read_type(struct cpp_demangle_data * ddata,struct type_delimit * td)250118f4c9dbSEd Maste cpp_demangle_read_type(struct cpp_demangle_data *ddata,
250218f4c9dbSEd Maste     struct type_delimit *td)
2503a85fe12eSEd Maste {
2504a85fe12eSEd Maste 	struct vector_type_qualifier v;
250518f4c9dbSEd Maste 	struct vector_str *output, sv;
250618f4c9dbSEd Maste 	size_t p_idx, type_str_len, subst_str_len;
2507a85fe12eSEd Maste 	int extern_c, is_builtin;
2508a85fe12eSEd Maste 	long len;
250918f4c9dbSEd Maste 	const char *p;
251018f4c9dbSEd Maste 	char *type_str, *exp_str, *num_str, *subst_str;
251118f4c9dbSEd Maste 	bool skip_ref_qualifier, omit_void;
2512a85fe12eSEd Maste 
2513a85fe12eSEd Maste 	if (ddata == NULL)
2514a85fe12eSEd Maste 		return (0);
2515a85fe12eSEd Maste 
251618f4c9dbSEd Maste 	output = ddata->cur_output;
251718f4c9dbSEd Maste 	if (td) {
251818f4c9dbSEd Maste 		if (td->paren == false) {
2519bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "("))
2520a85fe12eSEd Maste 				return (0);
2521a85fe12eSEd Maste 			if (ddata->output.size < 2)
2522a85fe12eSEd Maste 				return (0);
252318f4c9dbSEd Maste 			td->paren = true;
2524a85fe12eSEd Maste 		}
2525a85fe12eSEd Maste 
252618f4c9dbSEd Maste 		if (!td->firstp) {
252718f4c9dbSEd Maste 			if (*ddata->cur != 'I') {
252818f4c9dbSEd Maste 				if (!DEM_PUSH_STR(ddata, ", "))
2529a85fe12eSEd Maste 					return (0);
2530a85fe12eSEd Maste 			}
253118f4c9dbSEd Maste 		}
253218f4c9dbSEd Maste 	}
2533a85fe12eSEd Maste 
2534a85fe12eSEd Maste 	assert(output != NULL);
2535a85fe12eSEd Maste 	/*
253618f4c9dbSEd Maste 	 * [r, V, K] [P, R, O, C, G, U] builtin, function, class-enum, array
2537a85fe12eSEd Maste 	 * pointer-to-member, template-param, template-template-param, subst
2538a85fe12eSEd Maste 	 */
2539a85fe12eSEd Maste 
2540a85fe12eSEd Maste 	if (!vector_type_qualifier_init(&v))
2541a85fe12eSEd Maste 		return (0);
2542a85fe12eSEd Maste 
2543a85fe12eSEd Maste 	extern_c = 0;
2544a85fe12eSEd Maste 	is_builtin = 1;
2545a85fe12eSEd Maste 	p_idx = output->size;
25463ef90571SEd Maste 	type_str = exp_str = num_str = NULL;
254718f4c9dbSEd Maste 	skip_ref_qualifier = false;
254818f4c9dbSEd Maste 
2549a85fe12eSEd Maste again:
255018f4c9dbSEd Maste 
255118f4c9dbSEd Maste 	/* Clear ref-qualifier flag */
255218f4c9dbSEd Maste 	if (*ddata->cur != 'R' && *ddata->cur != 'O' && *ddata->cur != 'E')
255318f4c9dbSEd Maste 		ddata->ref_qualifier = false;
255418f4c9dbSEd Maste 
2555a85fe12eSEd Maste 	/* builtin type */
2556a85fe12eSEd Maste 	switch (*ddata->cur) {
2557a85fe12eSEd Maste 	case 'a':
2558a85fe12eSEd Maste 		/* signed char */
2559bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "signed char"))
2560a85fe12eSEd Maste 			goto clean;
2561a85fe12eSEd Maste 		++ddata->cur;
2562a85fe12eSEd Maste 		goto rtn;
2563a85fe12eSEd Maste 
2564a85fe12eSEd Maste 	case 'A':
2565a85fe12eSEd Maste 		/* array type */
2566a85fe12eSEd Maste 		if (!cpp_demangle_read_array(ddata))
2567a85fe12eSEd Maste 			goto clean;
2568a85fe12eSEd Maste 		is_builtin = 0;
2569a85fe12eSEd Maste 		goto rtn;
2570a85fe12eSEd Maste 
2571a85fe12eSEd Maste 	case 'b':
2572a85fe12eSEd Maste 		/* bool */
2573bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "bool"))
2574a85fe12eSEd Maste 			goto clean;
2575a85fe12eSEd Maste 		++ddata->cur;
2576a85fe12eSEd Maste 		goto rtn;
2577a85fe12eSEd Maste 
2578a85fe12eSEd Maste 	case 'C':
2579a85fe12eSEd Maste 		/* complex pair */
2580a85fe12eSEd Maste 		if (!vector_type_qualifier_push(&v, TYPE_CMX))
2581a85fe12eSEd Maste 			goto clean;
2582a85fe12eSEd Maste 		++ddata->cur;
258318f4c9dbSEd Maste 		if (td)
258418f4c9dbSEd Maste 			td->firstp = false;
2585a85fe12eSEd Maste 		goto again;
2586a85fe12eSEd Maste 
2587a85fe12eSEd Maste 	case 'c':
2588a85fe12eSEd Maste 		/* char */
2589bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "char"))
2590a85fe12eSEd Maste 			goto clean;
2591a85fe12eSEd Maste 		++ddata->cur;
2592a85fe12eSEd Maste 		goto rtn;
2593a85fe12eSEd Maste 
2594a85fe12eSEd Maste 	case 'd':
2595a85fe12eSEd Maste 		/* double */
2596bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "double"))
2597a85fe12eSEd Maste 			goto clean;
2598a85fe12eSEd Maste 		++ddata->cur;
2599a85fe12eSEd Maste 		goto rtn;
2600a85fe12eSEd Maste 
26013ef90571SEd Maste 	case 'D':
26023ef90571SEd Maste 		++ddata->cur;
26033ef90571SEd Maste 		switch (*ddata->cur) {
260418f4c9dbSEd Maste 		case 'a':
260518f4c9dbSEd Maste 			/* auto */
260618f4c9dbSEd Maste 			if (!DEM_PUSH_STR(ddata, "auto"))
260718f4c9dbSEd Maste 				goto clean;
260818f4c9dbSEd Maste 			++ddata->cur;
260918f4c9dbSEd Maste 			break;
261018f4c9dbSEd Maste 		case 'c':
261118f4c9dbSEd Maste 			/* decltype(auto) */
261218f4c9dbSEd Maste 			if (!DEM_PUSH_STR(ddata, "decltype(auto)"))
261318f4c9dbSEd Maste 				goto clean;
261418f4c9dbSEd Maste 			++ddata->cur;
261518f4c9dbSEd Maste 			break;
26163ef90571SEd Maste 		case 'd':
26173ef90571SEd Maste 			/* IEEE 754r decimal floating point (64 bits) */
2618bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "decimal64"))
26193ef90571SEd Maste 				goto clean;
26203ef90571SEd Maste 			++ddata->cur;
26213ef90571SEd Maste 			break;
26223ef90571SEd Maste 		case 'e':
26233ef90571SEd Maste 			/* IEEE 754r decimal floating point (128 bits) */
2624bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "decimal128"))
26253ef90571SEd Maste 				goto clean;
26263ef90571SEd Maste 			++ddata->cur;
26273ef90571SEd Maste 			break;
26283ef90571SEd Maste 		case 'f':
26293ef90571SEd Maste 			/* IEEE 754r decimal floating point (32 bits) */
2630bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "decimal32"))
26313ef90571SEd Maste 				goto clean;
26323ef90571SEd Maste 			++ddata->cur;
26333ef90571SEd Maste 			break;
26343ef90571SEd Maste 		case 'h':
26353ef90571SEd Maste 			/* IEEE 754r half-precision floating point (16 bits) */
2636bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "half"))
26373ef90571SEd Maste 				goto clean;
26383ef90571SEd Maste 			++ddata->cur;
26393ef90571SEd Maste 			break;
26403ef90571SEd Maste 		case 'i':
26413ef90571SEd Maste 			/* char32_t */
2642bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "char32_t"))
26433ef90571SEd Maste 				goto clean;
26443ef90571SEd Maste 			++ddata->cur;
26453ef90571SEd Maste 			break;
26463ef90571SEd Maste 		case 'n':
26473ef90571SEd Maste 			/* std::nullptr_t (i.e., decltype(nullptr)) */
2648bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "decltype(nullptr)"))
26493ef90571SEd Maste 				goto clean;
26503ef90571SEd Maste 			++ddata->cur;
26513ef90571SEd Maste 			break;
26523ef90571SEd Maste 		case 's':
26533ef90571SEd Maste 			/* char16_t */
2654bee2765cSEd Maste 			if (!DEM_PUSH_STR(ddata, "char16_t"))
26553ef90571SEd Maste 				goto clean;
26563ef90571SEd Maste 			++ddata->cur;
26573ef90571SEd Maste 			break;
26583ef90571SEd Maste 		case 'v':
26593ef90571SEd Maste 			/* gcc vector_size extension. */
26603ef90571SEd Maste 			++ddata->cur;
26613ef90571SEd Maste 			if (*ddata->cur == '_') {
26623ef90571SEd Maste 				++ddata->cur;
26633ef90571SEd Maste 				if (!cpp_demangle_read_expression_flat(ddata,
26643ef90571SEd Maste 				    &exp_str))
26653ef90571SEd Maste 					goto clean;
2666bee2765cSEd Maste 				if (!VEC_PUSH_STR(&v.ext_name, exp_str))
26673ef90571SEd Maste 					goto clean;
26683ef90571SEd Maste 			} else {
26693ef90571SEd Maste 				if (!cpp_demangle_read_number_as_string(ddata,
26703ef90571SEd Maste 				    &num_str))
26713ef90571SEd Maste 					goto clean;
2672bee2765cSEd Maste 				if (!VEC_PUSH_STR(&v.ext_name, num_str))
26733ef90571SEd Maste 					goto clean;
26743ef90571SEd Maste 			}
26753ef90571SEd Maste 			if (*ddata->cur != '_')
26763ef90571SEd Maste 				goto clean;
26773ef90571SEd Maste 			++ddata->cur;
26783ef90571SEd Maste 			if (!vector_type_qualifier_push(&v, TYPE_VEC))
26793ef90571SEd Maste 				goto clean;
268018f4c9dbSEd Maste 			if (td)
268118f4c9dbSEd Maste 				td->firstp = false;
26823ef90571SEd Maste 			goto again;
26833ef90571SEd Maste 		default:
26843ef90571SEd Maste 			goto clean;
26853ef90571SEd Maste 		}
26863ef90571SEd Maste 		goto rtn;
26873ef90571SEd Maste 
2688a85fe12eSEd Maste 	case 'e':
2689a85fe12eSEd Maste 		/* long double */
2690bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "long double"))
2691a85fe12eSEd Maste 			goto clean;
2692a85fe12eSEd Maste 		++ddata->cur;
2693a85fe12eSEd Maste 		goto rtn;
2694a85fe12eSEd Maste 
269518f4c9dbSEd Maste 	case 'E':
269618f4c9dbSEd Maste 		/* unexpected end except ref-qualifiers */
269718f4c9dbSEd Maste 		if (ddata->ref_qualifier && ddata->is_functype) {
269818f4c9dbSEd Maste 			skip_ref_qualifier = true;
269918f4c9dbSEd Maste 			/* Pop the delimiter. */
270018f4c9dbSEd Maste 			cpp_demangle_pop_str(ddata);
270118f4c9dbSEd Maste 			goto rtn;
270218f4c9dbSEd Maste 		}
270318f4c9dbSEd Maste 		goto clean;
270418f4c9dbSEd Maste 
2705a85fe12eSEd Maste 	case 'f':
2706a85fe12eSEd Maste 		/* float */
2707bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "float"))
2708a85fe12eSEd Maste 			goto clean;
2709a85fe12eSEd Maste 		++ddata->cur;
2710a85fe12eSEd Maste 		goto rtn;
2711a85fe12eSEd Maste 
2712a85fe12eSEd Maste 	case 'F':
2713a85fe12eSEd Maste 		/* function */
2714a85fe12eSEd Maste 		if (!cpp_demangle_read_function(ddata, &extern_c, &v))
2715a85fe12eSEd Maste 			goto clean;
2716a85fe12eSEd Maste 		is_builtin = 0;
2717a85fe12eSEd Maste 		goto rtn;
2718a85fe12eSEd Maste 
2719a85fe12eSEd Maste 	case 'g':
2720a85fe12eSEd Maste 		/* __float128 */
2721bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "__float128"))
2722a85fe12eSEd Maste 			goto clean;
2723a85fe12eSEd Maste 		++ddata->cur;
2724a85fe12eSEd Maste 		goto rtn;
2725a85fe12eSEd Maste 
2726a85fe12eSEd Maste 	case 'G':
2727a85fe12eSEd Maste 		/* imaginary */
2728a85fe12eSEd Maste 		if (!vector_type_qualifier_push(&v, TYPE_IMG))
2729a85fe12eSEd Maste 			goto clean;
2730a85fe12eSEd Maste 		++ddata->cur;
273118f4c9dbSEd Maste 		if (td)
273218f4c9dbSEd Maste 			td->firstp = false;
2733a85fe12eSEd Maste 		goto again;
2734a85fe12eSEd Maste 
2735a85fe12eSEd Maste 	case 'h':
2736a85fe12eSEd Maste 		/* unsigned char */
2737bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "unsigned char"))
2738a85fe12eSEd Maste 			goto clean;
2739a85fe12eSEd Maste 		++ddata->cur;
2740a85fe12eSEd Maste 		goto rtn;
2741a85fe12eSEd Maste 
2742a85fe12eSEd Maste 	case 'i':
2743a85fe12eSEd Maste 		/* int */
2744bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "int"))
2745a85fe12eSEd Maste 			goto clean;
2746a85fe12eSEd Maste 		++ddata->cur;
2747a85fe12eSEd Maste 		goto rtn;
2748a85fe12eSEd Maste 
274918f4c9dbSEd Maste 	case 'I':
275018f4c9dbSEd Maste 		/* template args. */
275118f4c9dbSEd Maste 		/* handles <substitute><template-args> */
275218f4c9dbSEd Maste 		p_idx = output->size;
275318f4c9dbSEd Maste 		if (!cpp_demangle_read_tmpl_args(ddata))
275418f4c9dbSEd Maste 			goto clean;
275518f4c9dbSEd Maste 		if ((subst_str = vector_str_substr(output, p_idx,
275618f4c9dbSEd Maste 		    output->size - 1, &subst_str_len)) == NULL)
275718f4c9dbSEd Maste 			goto clean;
275818f4c9dbSEd Maste 		if (!vector_str_init(&sv)) {
275918f4c9dbSEd Maste 			free(subst_str);
276018f4c9dbSEd Maste 			goto clean;
276118f4c9dbSEd Maste 		}
276218f4c9dbSEd Maste 		if (!vector_str_push(&sv, subst_str, subst_str_len)) {
276318f4c9dbSEd Maste 			free(subst_str);
276418f4c9dbSEd Maste 			vector_str_dest(&sv);
276518f4c9dbSEd Maste 			goto clean;
276618f4c9dbSEd Maste 		}
276718f4c9dbSEd Maste 		free(subst_str);
276818f4c9dbSEd Maste 		if (!cpp_demangle_push_subst_v(ddata, &sv)) {
276918f4c9dbSEd Maste 			vector_str_dest(&sv);
277018f4c9dbSEd Maste 			goto clean;
277118f4c9dbSEd Maste 		}
277218f4c9dbSEd Maste 		vector_str_dest(&sv);
277318f4c9dbSEd Maste 		goto rtn;
277418f4c9dbSEd Maste 
2775a85fe12eSEd Maste 	case 'j':
2776a85fe12eSEd Maste 		/* unsigned int */
2777bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "unsigned int"))
2778a85fe12eSEd Maste 			goto clean;
2779a85fe12eSEd Maste 		++ddata->cur;
2780a85fe12eSEd Maste 		goto rtn;
2781a85fe12eSEd Maste 
2782a85fe12eSEd Maste 	case 'K':
2783a85fe12eSEd Maste 		/* const */
2784a85fe12eSEd Maste 		if (!vector_type_qualifier_push(&v, TYPE_CST))
2785a85fe12eSEd Maste 			goto clean;
2786a85fe12eSEd Maste 		++ddata->cur;
278718f4c9dbSEd Maste 		if (td)
278818f4c9dbSEd Maste 			td->firstp = false;
2789a85fe12eSEd Maste 		goto again;
2790a85fe12eSEd Maste 
2791a85fe12eSEd Maste 	case 'l':
2792a85fe12eSEd Maste 		/* long */
2793bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "long"))
2794a85fe12eSEd Maste 			goto clean;
2795a85fe12eSEd Maste 		++ddata->cur;
2796a85fe12eSEd Maste 		goto rtn;
2797a85fe12eSEd Maste 
2798a85fe12eSEd Maste 	case 'm':
2799a85fe12eSEd Maste 		/* unsigned long */
2800bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "unsigned long"))
2801a85fe12eSEd Maste 			goto clean;
2802a85fe12eSEd Maste 
2803a85fe12eSEd Maste 		++ddata->cur;
2804a85fe12eSEd Maste 
2805a85fe12eSEd Maste 		goto rtn;
2806a85fe12eSEd Maste 	case 'M':
2807a85fe12eSEd Maste 		/* pointer to member */
280818f4c9dbSEd Maste 		if (!cpp_demangle_read_pointer_to_member(ddata, &v))
2809a85fe12eSEd Maste 			goto clean;
2810a85fe12eSEd Maste 		is_builtin = 0;
2811a85fe12eSEd Maste 		goto rtn;
2812a85fe12eSEd Maste 
2813a85fe12eSEd Maste 	case 'n':
2814a85fe12eSEd Maste 		/* __int128 */
2815bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "__int128"))
2816a85fe12eSEd Maste 			goto clean;
2817a85fe12eSEd Maste 		++ddata->cur;
2818a85fe12eSEd Maste 		goto rtn;
2819a85fe12eSEd Maste 
2820a85fe12eSEd Maste 	case 'o':
2821a85fe12eSEd Maste 		/* unsigned __int128 */
2822bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "unsigned __int128"))
2823a85fe12eSEd Maste 			goto clean;
2824a85fe12eSEd Maste 		++ddata->cur;
2825a85fe12eSEd Maste 		goto rtn;
2826a85fe12eSEd Maste 
282718f4c9dbSEd Maste 	case 'O':
282818f4c9dbSEd Maste 		/* rvalue reference */
282918f4c9dbSEd Maste 		if (ddata->ref_qualifier)
283018f4c9dbSEd Maste 			goto clean;
283118f4c9dbSEd Maste 		if (!vector_type_qualifier_push(&v, TYPE_RREF))
283218f4c9dbSEd Maste 			goto clean;
283318f4c9dbSEd Maste 		ddata->ref_qualifier = true;
283418f4c9dbSEd Maste 		ddata->ref_qualifier_type = TYPE_RREF;
283518f4c9dbSEd Maste 		++ddata->cur;
283618f4c9dbSEd Maste 		if (td)
283718f4c9dbSEd Maste 			td->firstp = false;
283818f4c9dbSEd Maste 		goto again;
283918f4c9dbSEd Maste 
2840a85fe12eSEd Maste 	case 'P':
2841a85fe12eSEd Maste 		/* pointer */
2842a85fe12eSEd Maste 		if (!vector_type_qualifier_push(&v, TYPE_PTR))
2843a85fe12eSEd Maste 			goto clean;
2844a85fe12eSEd Maste 		++ddata->cur;
284518f4c9dbSEd Maste 		if (td)
284618f4c9dbSEd Maste 			td->firstp = false;
2847a85fe12eSEd Maste 		goto again;
2848a85fe12eSEd Maste 
2849a85fe12eSEd Maste 	case 'r':
2850a85fe12eSEd Maste 		/* restrict */
2851a85fe12eSEd Maste 		if (!vector_type_qualifier_push(&v, TYPE_RST))
2852a85fe12eSEd Maste 			goto clean;
2853a85fe12eSEd Maste 		++ddata->cur;
285418f4c9dbSEd Maste 		if (td)
285518f4c9dbSEd Maste 			td->firstp = false;
2856a85fe12eSEd Maste 		goto again;
2857a85fe12eSEd Maste 
2858a85fe12eSEd Maste 	case 'R':
2859a85fe12eSEd Maste 		/* reference */
286018f4c9dbSEd Maste 		if (ddata->ref_qualifier)
286118f4c9dbSEd Maste 			goto clean;
2862a85fe12eSEd Maste 		if (!vector_type_qualifier_push(&v, TYPE_REF))
2863a85fe12eSEd Maste 			goto clean;
286418f4c9dbSEd Maste 		ddata->ref_qualifier = true;
286518f4c9dbSEd Maste 		ddata->ref_qualifier_type = TYPE_REF;
2866a85fe12eSEd Maste 		++ddata->cur;
286718f4c9dbSEd Maste 		if (td)
286818f4c9dbSEd Maste 			td->firstp = false;
2869a85fe12eSEd Maste 		goto again;
2870a85fe12eSEd Maste 
2871a85fe12eSEd Maste 	case 's':
2872a85fe12eSEd Maste 		/* short, local string */
2873bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "short"))
2874a85fe12eSEd Maste 			goto clean;
2875a85fe12eSEd Maste 		++ddata->cur;
2876a85fe12eSEd Maste 		goto rtn;
2877a85fe12eSEd Maste 
2878a85fe12eSEd Maste 	case 'S':
2879a85fe12eSEd Maste 		/* substitution */
2880a85fe12eSEd Maste 		if (!cpp_demangle_read_subst(ddata))
2881a85fe12eSEd Maste 			goto clean;
2882a85fe12eSEd Maste 		is_builtin = 0;
2883a85fe12eSEd Maste 		goto rtn;
2884a85fe12eSEd Maste 
2885a85fe12eSEd Maste 	case 't':
2886a85fe12eSEd Maste 		/* unsigned short */
2887bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "unsigned short"))
2888a85fe12eSEd Maste 			goto clean;
2889a85fe12eSEd Maste 		++ddata->cur;
2890a85fe12eSEd Maste 		goto rtn;
2891a85fe12eSEd Maste 
2892a85fe12eSEd Maste 	case 'T':
2893a85fe12eSEd Maste 		/* template parameter */
2894a85fe12eSEd Maste 		if (!cpp_demangle_read_tmpl_param(ddata))
2895a85fe12eSEd Maste 			goto clean;
2896a85fe12eSEd Maste 		is_builtin = 0;
2897a85fe12eSEd Maste 		goto rtn;
2898a85fe12eSEd Maste 
2899a85fe12eSEd Maste 	case 'u':
2900a85fe12eSEd Maste 		/* vendor extended builtin */
2901a85fe12eSEd Maste 		++ddata->cur;
2902a85fe12eSEd Maste 		if (!cpp_demangle_read_sname(ddata))
2903a85fe12eSEd Maste 			goto clean;
2904a85fe12eSEd Maste 		is_builtin = 0;
2905a85fe12eSEd Maste 		goto rtn;
2906a85fe12eSEd Maste 
2907a85fe12eSEd Maste 	case 'U':
2908a85fe12eSEd Maste 		/* vendor extended type qualifier */
290918f4c9dbSEd Maste 		++ddata->cur;
2910a85fe12eSEd Maste 		if (!cpp_demangle_read_number(ddata, &len))
2911a85fe12eSEd Maste 			goto clean;
2912a85fe12eSEd Maste 		if (len <= 0)
2913a85fe12eSEd Maste 			goto clean;
2914a85fe12eSEd Maste 		if (!vector_str_push(&v.ext_name, ddata->cur, len))
2915c364ccf9SMark Johnston 			goto clean;
2916a85fe12eSEd Maste 		ddata->cur += len;
29173ef90571SEd Maste 		if (!vector_type_qualifier_push(&v, TYPE_EXT))
29183ef90571SEd Maste 			goto clean;
291918f4c9dbSEd Maste 		if (td)
292018f4c9dbSEd Maste 			td->firstp = false;
2921a85fe12eSEd Maste 		goto again;
2922a85fe12eSEd Maste 
2923a85fe12eSEd Maste 	case 'v':
2924a85fe12eSEd Maste 		/* void */
292518f4c9dbSEd Maste 		omit_void = false;
292618f4c9dbSEd Maste 		if (td && td->firstp) {
292718f4c9dbSEd Maste 			/*
292818f4c9dbSEd Maste 			 * peek into next bytes and see if we should omit
292918f4c9dbSEd Maste 			 * the "void".
293018f4c9dbSEd Maste 			 */
293118f4c9dbSEd Maste 			omit_void = true;
293218f4c9dbSEd Maste 			for (p = ddata->cur + 1; *p != '\0'; p++) {
293318f4c9dbSEd Maste 				if (*p == 'E')
293418f4c9dbSEd Maste 					break;
293518f4c9dbSEd Maste 				if (*p != 'R' && *p != 'O') {
293618f4c9dbSEd Maste 					omit_void = false;
293718f4c9dbSEd Maste 					break;
293818f4c9dbSEd Maste 				}
293918f4c9dbSEd Maste 			}
294018f4c9dbSEd Maste 		}
294118f4c9dbSEd Maste 		if (!omit_void && !DEM_PUSH_STR(ddata, "void"))
2942a85fe12eSEd Maste 			goto clean;
2943a85fe12eSEd Maste 		++ddata->cur;
2944a85fe12eSEd Maste 		goto rtn;
2945a85fe12eSEd Maste 
2946a85fe12eSEd Maste 	case 'V':
2947a85fe12eSEd Maste 		/* volatile */
2948a85fe12eSEd Maste 		if (!vector_type_qualifier_push(&v, TYPE_VAT))
2949a85fe12eSEd Maste 			goto clean;
2950a85fe12eSEd Maste 		++ddata->cur;
295118f4c9dbSEd Maste 		if (td)
295218f4c9dbSEd Maste 			td->firstp = false;
2953a85fe12eSEd Maste 		goto again;
2954a85fe12eSEd Maste 
2955a85fe12eSEd Maste 	case 'w':
2956a85fe12eSEd Maste 		/* wchar_t */
2957bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "wchar_t"))
2958a85fe12eSEd Maste 			goto clean;
2959a85fe12eSEd Maste 		++ddata->cur;
2960a85fe12eSEd Maste 		goto rtn;
2961a85fe12eSEd Maste 
2962a85fe12eSEd Maste 	case 'x':
2963a85fe12eSEd Maste 		/* long long */
2964bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "long long"))
2965a85fe12eSEd Maste 			goto clean;
2966a85fe12eSEd Maste 		++ddata->cur;
2967a85fe12eSEd Maste 		goto rtn;
2968a85fe12eSEd Maste 
2969a85fe12eSEd Maste 	case 'y':
2970a85fe12eSEd Maste 		/* unsigned long long */
2971bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "unsigned long long"))
2972a85fe12eSEd Maste 			goto clean;
2973a85fe12eSEd Maste 		++ddata->cur;
2974a85fe12eSEd Maste 		goto rtn;
2975a85fe12eSEd Maste 
2976a85fe12eSEd Maste 	case 'z':
2977a85fe12eSEd Maste 		/* ellipsis */
2978bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "..."))
2979a85fe12eSEd Maste 			goto clean;
2980a85fe12eSEd Maste 		++ddata->cur;
2981a85fe12eSEd Maste 		goto rtn;
2982b6b6f9ccSEd Maste 	}
2983a85fe12eSEd Maste 
2984a85fe12eSEd Maste 	if (!cpp_demangle_read_name(ddata))
2985a85fe12eSEd Maste 		goto clean;
2986a85fe12eSEd Maste 
2987a85fe12eSEd Maste 	is_builtin = 0;
2988a85fe12eSEd Maste rtn:
298918f4c9dbSEd Maste 
299018f4c9dbSEd Maste 	type_str = vector_str_substr(output, p_idx, output->size - 1,
299118f4c9dbSEd Maste 	    &type_str_len);
2992a85fe12eSEd Maste 
2993a85fe12eSEd Maste 	if (is_builtin == 0) {
2994a85fe12eSEd Maste 		if (!vector_str_find(&ddata->subst, type_str, type_str_len) &&
2995a85fe12eSEd Maste 		    !vector_str_push(&ddata->subst, type_str, type_str_len))
2996a85fe12eSEd Maste 			goto clean;
2997a85fe12eSEd Maste 	}
2998a85fe12eSEd Maste 
299918f4c9dbSEd Maste 	if (!skip_ref_qualifier &&
300018f4c9dbSEd Maste 	    !cpp_demangle_push_type_qualifier(ddata, &v, type_str))
3001a85fe12eSEd Maste 		goto clean;
3002a85fe12eSEd Maste 
300318f4c9dbSEd Maste 	if (td)
300418f4c9dbSEd Maste 		td->firstp = false;
300518f4c9dbSEd Maste 
3006a85fe12eSEd Maste 	free(type_str);
30073ef90571SEd Maste 	free(exp_str);
30083ef90571SEd Maste 	free(num_str);
3009a85fe12eSEd Maste 	vector_type_qualifier_dest(&v);
3010a85fe12eSEd Maste 
3011a85fe12eSEd Maste 	return (1);
3012a85fe12eSEd Maste clean:
3013a85fe12eSEd Maste 	free(type_str);
30143ef90571SEd Maste 	free(exp_str);
30153ef90571SEd Maste 	free(num_str);
3016a85fe12eSEd Maste 	vector_type_qualifier_dest(&v);
3017a85fe12eSEd Maste 
3018a85fe12eSEd Maste 	return (0);
3019a85fe12eSEd Maste }
3020a85fe12eSEd Maste 
30213ef90571SEd Maste static int
cpp_demangle_read_type_flat(struct cpp_demangle_data * ddata,char ** str)30223ef90571SEd Maste cpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str)
30233ef90571SEd Maste {
30243ef90571SEd Maste 	struct vector_str *output;
30253ef90571SEd Maste 	size_t i, p_idx, idx, type_len;
30263ef90571SEd Maste 	char *type;
30273ef90571SEd Maste 
302818f4c9dbSEd Maste 	output = ddata->cur_output;
30293ef90571SEd Maste 
30303ef90571SEd Maste 	p_idx = output->size;
30313ef90571SEd Maste 
303218f4c9dbSEd Maste 	if (!cpp_demangle_read_type(ddata, NULL))
30333ef90571SEd Maste 		return (0);
30343ef90571SEd Maste 
30353ef90571SEd Maste 	if ((type = vector_str_substr(output, p_idx, output->size - 1,
30363ef90571SEd Maste 	    &type_len)) == NULL)
30373ef90571SEd Maste 		return (0);
30383ef90571SEd Maste 
30393ef90571SEd Maste 	idx = output->size;
30403ef90571SEd Maste 	for (i = p_idx; i < idx; ++i) {
30413ef90571SEd Maste 		if (!vector_str_pop(output)) {
30423ef90571SEd Maste 			free(type);
30433ef90571SEd Maste 			return (0);
30443ef90571SEd Maste 		}
30453ef90571SEd Maste 	}
30463ef90571SEd Maste 
30473ef90571SEd Maste 	*str = type;
30483ef90571SEd Maste 
30493ef90571SEd Maste 	return (1);
30503ef90571SEd Maste }
30513ef90571SEd Maste 
3052a85fe12eSEd Maste /*
3053a85fe12eSEd Maste  * read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
3054a85fe12eSEd Maste  * source-name
3055a85fe12eSEd Maste  */
3056a85fe12eSEd Maste static int
cpp_demangle_read_uqname(struct cpp_demangle_data * ddata)3057a85fe12eSEd Maste cpp_demangle_read_uqname(struct cpp_demangle_data *ddata)
3058a85fe12eSEd Maste {
3059a85fe12eSEd Maste 	size_t len;
3060a85fe12eSEd Maste 
3061a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur == '\0')
3062a85fe12eSEd Maste 		return (0);
3063a85fe12eSEd Maste 
3064a85fe12eSEd Maste 	/* operator name */
3065a85fe12eSEd Maste 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
3066a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'a'):
3067a85fe12eSEd Maste 		/* operator && */
3068bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator&&"))
3069a85fe12eSEd Maste 			return (0);
3070a85fe12eSEd Maste 		ddata->cur += 2;
3071a85fe12eSEd Maste 		return (1);
3072a85fe12eSEd Maste 
3073a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'd'):
3074a85fe12eSEd Maste 		/* operator & (unary) */
3075bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator&"))
3076a85fe12eSEd Maste 			return (0);
3077a85fe12eSEd Maste 		ddata->cur += 2;
3078a85fe12eSEd Maste 		return (1);
3079a85fe12eSEd Maste 
3080a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'n'):
3081a85fe12eSEd Maste 		/* operator & */
3082bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator&"))
3083a85fe12eSEd Maste 			return (0);
3084a85fe12eSEd Maste 		ddata->cur += 2;
3085a85fe12eSEd Maste 		return (1);
3086a85fe12eSEd Maste 
3087a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'N'):
3088a85fe12eSEd Maste 		/* operator &= */
3089bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator&="))
3090a85fe12eSEd Maste 			return (0);
3091a85fe12eSEd Maste 		ddata->cur += 2;
3092a85fe12eSEd Maste 		return (1);
3093a85fe12eSEd Maste 
3094a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'S'):
3095a85fe12eSEd Maste 		/* operator = */
3096bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator="))
3097a85fe12eSEd Maste 			return (0);
3098a85fe12eSEd Maste 		ddata->cur += 2;
3099a85fe12eSEd Maste 		return (1);
3100a85fe12eSEd Maste 
3101a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'l'):
3102a85fe12eSEd Maste 		/* operator () */
3103bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator()"))
3104a85fe12eSEd Maste 			return (0);
3105a85fe12eSEd Maste 		ddata->cur += 2;
3106a85fe12eSEd Maste 		return (1);
3107a85fe12eSEd Maste 
3108a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'm'):
3109a85fe12eSEd Maste 		/* operator , */
3110bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator,"))
3111a85fe12eSEd Maste 			return (0);
3112a85fe12eSEd Maste 		ddata->cur += 2;
3113a85fe12eSEd Maste 		return (1);
3114a85fe12eSEd Maste 
3115a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'o'):
3116a85fe12eSEd Maste 		/* operator ~ */
3117bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator~"))
3118a85fe12eSEd Maste 			return (0);
3119a85fe12eSEd Maste 		ddata->cur += 2;
3120a85fe12eSEd Maste 		return (1);
3121a85fe12eSEd Maste 
3122a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'v'):
3123a85fe12eSEd Maste 		/* operator (cast) */
3124bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator(cast)"))
3125a85fe12eSEd Maste 			return (0);
3126a85fe12eSEd Maste 		ddata->cur += 2;
312718f4c9dbSEd Maste 		return (cpp_demangle_read_type(ddata, NULL));
3128a85fe12eSEd Maste 
3129a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'a'):
3130a85fe12eSEd Maste 		/* operator delete [] */
3131bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator delete []"))
3132a85fe12eSEd Maste 			return (0);
3133a85fe12eSEd Maste 		ddata->cur += 2;
3134a85fe12eSEd Maste 		return (1);
3135a85fe12eSEd Maste 
3136a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'e'):
3137a85fe12eSEd Maste 		/* operator * (unary) */
3138bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator*"))
3139a85fe12eSEd Maste 			return (0);
3140a85fe12eSEd Maste 		ddata->cur += 2;
3141a85fe12eSEd Maste 		return (1);
3142a85fe12eSEd Maste 
3143a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'l'):
3144a85fe12eSEd Maste 		/* operator delete */
3145bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator delete"))
3146a85fe12eSEd Maste 			return (0);
3147a85fe12eSEd Maste 		ddata->cur += 2;
3148a85fe12eSEd Maste 		return (1);
3149a85fe12eSEd Maste 
3150a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'v'):
3151a85fe12eSEd Maste 		/* operator / */
3152bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator/"))
3153a85fe12eSEd Maste 			return (0);
3154a85fe12eSEd Maste 		ddata->cur += 2;
3155a85fe12eSEd Maste 		return (1);
3156a85fe12eSEd Maste 
3157a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'V'):
3158a85fe12eSEd Maste 		/* operator /= */
3159bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator/="))
3160a85fe12eSEd Maste 			return (0);
3161a85fe12eSEd Maste 		ddata->cur += 2;
3162a85fe12eSEd Maste 		return (1);
3163a85fe12eSEd Maste 
3164a85fe12eSEd Maste 	case SIMPLE_HASH('e', 'o'):
3165a85fe12eSEd Maste 		/* operator ^ */
3166bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator^"))
3167a85fe12eSEd Maste 			return (0);
3168a85fe12eSEd Maste 		ddata->cur += 2;
3169a85fe12eSEd Maste 		return (1);
3170a85fe12eSEd Maste 
3171a85fe12eSEd Maste 	case SIMPLE_HASH('e', 'O'):
3172a85fe12eSEd Maste 		/* operator ^= */
3173bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator^="))
3174a85fe12eSEd Maste 			return (0);
3175a85fe12eSEd Maste 		ddata->cur += 2;
3176a85fe12eSEd Maste 		return (1);
3177a85fe12eSEd Maste 
3178a85fe12eSEd Maste 	case SIMPLE_HASH('e', 'q'):
3179a85fe12eSEd Maste 		/* operator == */
3180bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator=="))
3181a85fe12eSEd Maste 			return (0);
3182a85fe12eSEd Maste 		ddata->cur += 2;
3183a85fe12eSEd Maste 		return (1);
3184a85fe12eSEd Maste 
3185a85fe12eSEd Maste 	case SIMPLE_HASH('g', 'e'):
3186a85fe12eSEd Maste 		/* operator >= */
3187bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator>="))
3188a85fe12eSEd Maste 			return (0);
3189a85fe12eSEd Maste 		ddata->cur += 2;
3190a85fe12eSEd Maste 		return (1);
3191a85fe12eSEd Maste 
3192a85fe12eSEd Maste 	case SIMPLE_HASH('g', 't'):
3193a85fe12eSEd Maste 		/* operator > */
3194bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator>"))
3195a85fe12eSEd Maste 			return (0);
3196a85fe12eSEd Maste 		ddata->cur += 2;
3197a85fe12eSEd Maste 		return (1);
3198a85fe12eSEd Maste 
3199a85fe12eSEd Maste 	case SIMPLE_HASH('i', 'x'):
3200a85fe12eSEd Maste 		/* operator [] */
3201bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator[]"))
3202a85fe12eSEd Maste 			return (0);
3203a85fe12eSEd Maste 		ddata->cur += 2;
3204a85fe12eSEd Maste 		return (1);
3205a85fe12eSEd Maste 
3206a85fe12eSEd Maste 	case SIMPLE_HASH('l', 'e'):
3207a85fe12eSEd Maste 		/* operator <= */
3208bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator<="))
3209a85fe12eSEd Maste 			return (0);
3210a85fe12eSEd Maste 		ddata->cur += 2;
3211a85fe12eSEd Maste 		return (1);
3212a85fe12eSEd Maste 
3213a85fe12eSEd Maste 	case SIMPLE_HASH('l', 's'):
3214a85fe12eSEd Maste 		/* operator << */
3215bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator<<"))
3216a85fe12eSEd Maste 			return (0);
3217a85fe12eSEd Maste 		ddata->cur += 2;
3218a85fe12eSEd Maste 		return (1);
3219a85fe12eSEd Maste 
3220a85fe12eSEd Maste 	case SIMPLE_HASH('l', 'S'):
3221a85fe12eSEd Maste 		/* operator <<= */
3222bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator<<="))
3223a85fe12eSEd Maste 			return (0);
3224a85fe12eSEd Maste 		ddata->cur += 2;
3225a85fe12eSEd Maste 		return (1);
3226a85fe12eSEd Maste 
3227a85fe12eSEd Maste 	case SIMPLE_HASH('l', 't'):
3228a85fe12eSEd Maste 		/* operator < */
3229bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator<"))
3230a85fe12eSEd Maste 			return (0);
3231a85fe12eSEd Maste 		ddata->cur += 2;
3232a85fe12eSEd Maste 		return (1);
3233a85fe12eSEd Maste 
3234a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'i'):
3235a85fe12eSEd Maste 		/* operator - */
3236bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator-"))
3237a85fe12eSEd Maste 			return (0);
3238a85fe12eSEd Maste 		ddata->cur += 2;
3239a85fe12eSEd Maste 		return (1);
3240a85fe12eSEd Maste 
3241a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'I'):
3242a85fe12eSEd Maste 		/* operator -= */
3243bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator-="))
3244a85fe12eSEd Maste 			return (0);
3245a85fe12eSEd Maste 		ddata->cur += 2;
3246a85fe12eSEd Maste 		return (1);
3247a85fe12eSEd Maste 
3248a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'l'):
3249a85fe12eSEd Maste 		/* operator * */
3250bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator*"))
3251a85fe12eSEd Maste 			return (0);
3252a85fe12eSEd Maste 		ddata->cur += 2;
3253a85fe12eSEd Maste 		return (1);
3254a85fe12eSEd Maste 
3255a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'L'):
3256a85fe12eSEd Maste 		/* operator *= */
3257bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator*="))
3258a85fe12eSEd Maste 			return (0);
3259a85fe12eSEd Maste 		ddata->cur += 2;
3260a85fe12eSEd Maste 		return (1);
3261a85fe12eSEd Maste 
3262a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'm'):
3263a85fe12eSEd Maste 		/* operator -- */
3264bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator--"))
3265a85fe12eSEd Maste 			return (0);
3266a85fe12eSEd Maste 		ddata->cur += 2;
3267a85fe12eSEd Maste 		return (1);
3268a85fe12eSEd Maste 
3269a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'a'):
3270a85fe12eSEd Maste 		/* operator new[] */
3271bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator new []"))
3272a85fe12eSEd Maste 			return (0);
3273a85fe12eSEd Maste 		ddata->cur += 2;
3274a85fe12eSEd Maste 		return (1);
3275a85fe12eSEd Maste 
3276a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'e'):
3277a85fe12eSEd Maste 		/* operator != */
3278bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator!="))
3279a85fe12eSEd Maste 			return (0);
3280a85fe12eSEd Maste 		ddata->cur += 2;
3281a85fe12eSEd Maste 		return (1);
3282a85fe12eSEd Maste 
3283a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'g'):
3284a85fe12eSEd Maste 		/* operator - (unary) */
3285bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator-"))
3286a85fe12eSEd Maste 			return (0);
3287a85fe12eSEd Maste 		ddata->cur += 2;
3288a85fe12eSEd Maste 		return (1);
3289a85fe12eSEd Maste 
3290a85fe12eSEd Maste 	case SIMPLE_HASH('n', 't'):
3291a85fe12eSEd Maste 		/* operator ! */
3292bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator!"))
3293a85fe12eSEd Maste 			return (0);
3294a85fe12eSEd Maste 		ddata->cur += 2;
3295a85fe12eSEd Maste 		return (1);
3296a85fe12eSEd Maste 
3297a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'w'):
3298a85fe12eSEd Maste 		/* operator new */
3299bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator new"))
3300a85fe12eSEd Maste 			return (0);
3301a85fe12eSEd Maste 		ddata->cur += 2;
3302a85fe12eSEd Maste 		return (1);
3303a85fe12eSEd Maste 
3304a85fe12eSEd Maste 	case SIMPLE_HASH('o', 'o'):
3305a85fe12eSEd Maste 		/* operator || */
3306bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator||"))
3307a85fe12eSEd Maste 			return (0);
3308a85fe12eSEd Maste 		ddata->cur += 2;
3309a85fe12eSEd Maste 		return (1);
3310a85fe12eSEd Maste 
3311a85fe12eSEd Maste 	case SIMPLE_HASH('o', 'r'):
3312a85fe12eSEd Maste 		/* operator | */
3313bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator|"))
3314a85fe12eSEd Maste 			return (0);
3315a85fe12eSEd Maste 		ddata->cur += 2;
3316a85fe12eSEd Maste 		return (1);
3317a85fe12eSEd Maste 
3318a85fe12eSEd Maste 	case SIMPLE_HASH('o', 'R'):
3319a85fe12eSEd Maste 		/* operator |= */
3320bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator|="))
3321a85fe12eSEd Maste 			return (0);
3322a85fe12eSEd Maste 		ddata->cur += 2;
3323a85fe12eSEd Maste 		return (1);
3324a85fe12eSEd Maste 
3325a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'l'):
3326a85fe12eSEd Maste 		/* operator + */
3327bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator+"))
3328a85fe12eSEd Maste 			return (0);
3329a85fe12eSEd Maste 		ddata->cur += 2;
3330a85fe12eSEd Maste 		return (1);
3331a85fe12eSEd Maste 
3332a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'L'):
3333a85fe12eSEd Maste 		/* operator += */
3334bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator+="))
3335a85fe12eSEd Maste 			return (0);
3336a85fe12eSEd Maste 		ddata->cur += 2;
3337a85fe12eSEd Maste 		return (1);
3338a85fe12eSEd Maste 
3339a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'm'):
3340a85fe12eSEd Maste 		/* operator ->* */
3341bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator->*"))
3342a85fe12eSEd Maste 			return (0);
3343a85fe12eSEd Maste 		ddata->cur += 2;
3344a85fe12eSEd Maste 		return (1);
3345a85fe12eSEd Maste 
3346a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'p'):
3347a85fe12eSEd Maste 		/* operator ++ */
3348bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator++"))
3349a85fe12eSEd Maste 			return (0);
3350a85fe12eSEd Maste 		ddata->cur += 2;
3351a85fe12eSEd Maste 		return (1);
3352a85fe12eSEd Maste 
3353a85fe12eSEd Maste 	case SIMPLE_HASH('p', 's'):
3354a85fe12eSEd Maste 		/* operator + (unary) */
3355bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator+"))
3356a85fe12eSEd Maste 			return (0);
3357a85fe12eSEd Maste 		ddata->cur += 2;
3358a85fe12eSEd Maste 		return (1);
3359a85fe12eSEd Maste 
3360a85fe12eSEd Maste 	case SIMPLE_HASH('p', 't'):
3361a85fe12eSEd Maste 		/* operator -> */
3362bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator->"))
3363a85fe12eSEd Maste 			return (0);
3364a85fe12eSEd Maste 		ddata->cur += 2;
3365a85fe12eSEd Maste 		return (1);
3366a85fe12eSEd Maste 
3367a85fe12eSEd Maste 	case SIMPLE_HASH('q', 'u'):
3368a85fe12eSEd Maste 		/* operator ? */
3369bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator?"))
3370a85fe12eSEd Maste 			return (0);
3371a85fe12eSEd Maste 		ddata->cur += 2;
3372a85fe12eSEd Maste 		return (1);
3373a85fe12eSEd Maste 
3374a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'm'):
3375a85fe12eSEd Maste 		/* operator % */
3376bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator%"))
3377a85fe12eSEd Maste 			return (0);
3378a85fe12eSEd Maste 		ddata->cur += 2;
3379a85fe12eSEd Maste 		return (1);
3380a85fe12eSEd Maste 
3381a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'M'):
3382a85fe12eSEd Maste 		/* operator %= */
3383bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator%="))
3384a85fe12eSEd Maste 			return (0);
3385a85fe12eSEd Maste 		ddata->cur += 2;
3386a85fe12eSEd Maste 		return (1);
3387a85fe12eSEd Maste 
3388a85fe12eSEd Maste 	case SIMPLE_HASH('r', 's'):
3389a85fe12eSEd Maste 		/* operator >> */
3390bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator>>"))
3391a85fe12eSEd Maste 			return (0);
3392a85fe12eSEd Maste 		ddata->cur += 2;
3393a85fe12eSEd Maste 		return (1);
3394a85fe12eSEd Maste 
3395a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'S'):
3396a85fe12eSEd Maste 		/* operator >>= */
3397bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator>>="))
3398a85fe12eSEd Maste 			return (0);
3399a85fe12eSEd Maste 		ddata->cur += 2;
3400a85fe12eSEd Maste 		return (1);
3401a85fe12eSEd Maste 
3402a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'z'):
3403a85fe12eSEd Maste 		/* operator sizeof */
3404bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator sizeof "))
3405a85fe12eSEd Maste 			return (0);
3406a85fe12eSEd Maste 		ddata->cur += 2;
3407a85fe12eSEd Maste 		return (1);
3408a85fe12eSEd Maste 
3409a85fe12eSEd Maste 	case SIMPLE_HASH('s', 'r'):
3410a85fe12eSEd Maste 		/* scope resolution operator */
3411bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "scope resolution operator "))
3412a85fe12eSEd Maste 			return (0);
3413a85fe12eSEd Maste 		ddata->cur += 2;
3414a85fe12eSEd Maste 		return (1);
3415a85fe12eSEd Maste 
3416a85fe12eSEd Maste 	case SIMPLE_HASH('s', 'v'):
3417a85fe12eSEd Maste 		/* operator sizeof */
3418bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "operator sizeof "))
3419a85fe12eSEd Maste 			return (0);
3420a85fe12eSEd Maste 		ddata->cur += 2;
3421a85fe12eSEd Maste 		return (1);
3422b6b6f9ccSEd Maste 	}
3423a85fe12eSEd Maste 
3424a85fe12eSEd Maste 	/* vendor extened operator */
3425a85fe12eSEd Maste 	if (*ddata->cur == 'v' && ELFTC_ISDIGIT(*(ddata->cur + 1))) {
3426bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "vendor extened operator "))
3427a85fe12eSEd Maste 			return (0);
3428a85fe12eSEd Maste 		if (!cpp_demangle_push_str(ddata, ddata->cur + 1, 1))
3429a85fe12eSEd Maste 			return (0);
3430a85fe12eSEd Maste 		ddata->cur += 2;
3431a85fe12eSEd Maste 		return (cpp_demangle_read_sname(ddata));
3432a85fe12eSEd Maste 	}
3433a85fe12eSEd Maste 
3434a85fe12eSEd Maste 	/* ctor-dtor-name */
3435a85fe12eSEd Maste 	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
3436a85fe12eSEd Maste 	case SIMPLE_HASH('C', '1'):
3437a85fe12eSEd Maste 	case SIMPLE_HASH('C', '2'):
3438a85fe12eSEd Maste 	case SIMPLE_HASH('C', '3'):
3439a85fe12eSEd Maste 		if (ddata->last_sname == NULL)
3440a85fe12eSEd Maste 			return (0);
3441a85fe12eSEd Maste 		if ((len = strlen(ddata->last_sname)) == 0)
3442a85fe12eSEd Maste 			return (0);
3443bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "::"))
3444a85fe12eSEd Maste 			return (0);
3445a85fe12eSEd Maste 		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
3446a85fe12eSEd Maste 			return (0);
3447a85fe12eSEd Maste 		ddata->cur +=2;
3448a85fe12eSEd Maste 		return (1);
3449a85fe12eSEd Maste 
3450a85fe12eSEd Maste 	case SIMPLE_HASH('D', '0'):
3451a85fe12eSEd Maste 	case SIMPLE_HASH('D', '1'):
3452a85fe12eSEd Maste 	case SIMPLE_HASH('D', '2'):
3453a85fe12eSEd Maste 		if (ddata->last_sname == NULL)
3454a85fe12eSEd Maste 			return (0);
3455a85fe12eSEd Maste 		if ((len = strlen(ddata->last_sname)) == 0)
3456a85fe12eSEd Maste 			return (0);
3457bee2765cSEd Maste 		if (!DEM_PUSH_STR(ddata, "::~"))
3458a85fe12eSEd Maste 			return (0);
3459a85fe12eSEd Maste 		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
3460a85fe12eSEd Maste 			return (0);
3461a85fe12eSEd Maste 		ddata->cur +=2;
3462a85fe12eSEd Maste 		return (1);
3463b6b6f9ccSEd Maste 	}
3464a85fe12eSEd Maste 
3465a85fe12eSEd Maste 	/* source name */
3466a85fe12eSEd Maste 	if (ELFTC_ISDIGIT(*ddata->cur) != 0)
3467a85fe12eSEd Maste 		return (cpp_demangle_read_sname(ddata));
3468a85fe12eSEd Maste 
3469a85fe12eSEd Maste 	/* local source name */
3470a85fe12eSEd Maste 	if (*ddata->cur == 'L')
3471a85fe12eSEd Maste 		return (cpp_demangle_local_source_name(ddata));
3472a85fe12eSEd Maste 
3473a85fe12eSEd Maste 	return (1);
3474a85fe12eSEd Maste }
3475a85fe12eSEd Maste 
3476a85fe12eSEd Maste /*
3477a85fe12eSEd Maste  * Read local source name.
3478a85fe12eSEd Maste  *
3479a85fe12eSEd Maste  * References:
3480a85fe12eSEd Maste  *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
3481a85fe12eSEd Maste  *   http://gcc.gnu.org/viewcvs?view=rev&revision=124467
3482a85fe12eSEd Maste  */
3483a85fe12eSEd Maste static int
cpp_demangle_local_source_name(struct cpp_demangle_data * ddata)3484a85fe12eSEd Maste cpp_demangle_local_source_name(struct cpp_demangle_data *ddata)
3485a85fe12eSEd Maste {
3486a85fe12eSEd Maste 	/* L */
3487a85fe12eSEd Maste 	if (ddata == NULL || *ddata->cur != 'L')
3488a85fe12eSEd Maste 		return (0);
3489a85fe12eSEd Maste 	++ddata->cur;
3490a85fe12eSEd Maste 
3491a85fe12eSEd Maste 	/* source name */
3492a85fe12eSEd Maste 	if (!cpp_demangle_read_sname(ddata))
3493a85fe12eSEd Maste 		return (0);
3494a85fe12eSEd Maste 
3495a85fe12eSEd Maste 	/* discriminator */
3496a85fe12eSEd Maste 	if (*ddata->cur == '_') {
3497a85fe12eSEd Maste 		++ddata->cur;
3498a85fe12eSEd Maste 		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
3499a85fe12eSEd Maste 			++ddata->cur;
3500a85fe12eSEd Maste 	}
3501a85fe12eSEd Maste 
3502a85fe12eSEd Maste 	return (1);
3503a85fe12eSEd Maste }
3504a85fe12eSEd Maste 
3505a85fe12eSEd Maste static int
cpp_demangle_read_v_offset(struct cpp_demangle_data * ddata)3506a85fe12eSEd Maste cpp_demangle_read_v_offset(struct cpp_demangle_data *ddata)
3507a85fe12eSEd Maste {
3508a85fe12eSEd Maste 
3509a85fe12eSEd Maste 	if (ddata == NULL)
3510a85fe12eSEd Maste 		return (0);
3511a85fe12eSEd Maste 
3512bee2765cSEd Maste 	if (!DEM_PUSH_STR(ddata, "offset : "))
3513a85fe12eSEd Maste 		return (0);
3514a85fe12eSEd Maste 
3515a85fe12eSEd Maste 	if (!cpp_demangle_read_offset_number(ddata))
3516a85fe12eSEd Maste 		return (0);
3517a85fe12eSEd Maste 
3518bee2765cSEd Maste 	if (!DEM_PUSH_STR(ddata, "virtual offset : "))
3519a85fe12eSEd Maste 		return (0);
3520a85fe12eSEd Maste 
3521a85fe12eSEd Maste 	return (!cpp_demangle_read_offset_number(ddata));
3522a85fe12eSEd Maste }
3523a85fe12eSEd Maste 
3524a85fe12eSEd Maste /*
3525a85fe12eSEd Maste  * Decode floating point representation to string
3526a85fe12eSEd Maste  * Return new allocated string or NULL
3527a85fe12eSEd Maste  *
3528a85fe12eSEd Maste  * Todo
3529a85fe12eSEd Maste  * Replace these functions to macro.
3530a85fe12eSEd Maste  */
3531a85fe12eSEd Maste static char *
decode_fp_to_double(const char * p,size_t len)3532a85fe12eSEd Maste decode_fp_to_double(const char *p, size_t len)
3533a85fe12eSEd Maste {
3534a85fe12eSEd Maste 	double f;
3535a85fe12eSEd Maste 	size_t rtn_len, limit, i;
3536a85fe12eSEd Maste 	int byte;
3537a85fe12eSEd Maste 	char *rtn;
3538a85fe12eSEd Maste 
3539a85fe12eSEd Maste 	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(double))
3540a85fe12eSEd Maste 		return (NULL);
3541a85fe12eSEd Maste 
3542a85fe12eSEd Maste 	memset(&f, 0, sizeof(double));
3543a85fe12eSEd Maste 
3544a85fe12eSEd Maste 	for (i = 0; i < len / 2; ++i) {
3545a85fe12eSEd Maste 		byte = hex_to_dec(p[len - i * 2 - 1]) +
3546a85fe12eSEd Maste 		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3547a85fe12eSEd Maste 
3548a85fe12eSEd Maste 		if (byte < 0 || byte > 255)
3549a85fe12eSEd Maste 			return (NULL);
3550a85fe12eSEd Maste 
3551a85fe12eSEd Maste #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3552a85fe12eSEd Maste 		((unsigned char *)&f)[i] = (unsigned char)(byte);
3553a85fe12eSEd Maste #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3554a85fe12eSEd Maste 		((unsigned char *)&f)[sizeof(double) - i - 1] =
3555a85fe12eSEd Maste 		    (unsigned char)(byte);
3556a85fe12eSEd Maste #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3557a85fe12eSEd Maste 	}
3558a85fe12eSEd Maste 
3559a85fe12eSEd Maste 	rtn_len = 64;
3560a85fe12eSEd Maste 	limit = 0;
3561a85fe12eSEd Maste again:
3562a85fe12eSEd Maste 	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3563a85fe12eSEd Maste 		return (NULL);
3564a85fe12eSEd Maste 
3565a85fe12eSEd Maste 	if (snprintf(rtn, rtn_len, "%fld", f) >= (int)rtn_len) {
3566a85fe12eSEd Maste 		free(rtn);
3567a85fe12eSEd Maste 		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3568a85fe12eSEd Maste 			return (NULL);
3569a85fe12eSEd Maste 		rtn_len *= BUFFER_GROWFACTOR;
3570a85fe12eSEd Maste 		goto again;
3571a85fe12eSEd Maste 	}
3572a85fe12eSEd Maste 
3573a85fe12eSEd Maste 	return rtn;
3574a85fe12eSEd Maste }
3575a85fe12eSEd Maste 
3576a85fe12eSEd Maste static char *
decode_fp_to_float(const char * p,size_t len)3577a85fe12eSEd Maste decode_fp_to_float(const char *p, size_t len)
3578a85fe12eSEd Maste {
3579a85fe12eSEd Maste 	size_t i, rtn_len, limit;
3580a85fe12eSEd Maste 	float f;
3581a85fe12eSEd Maste 	int byte;
3582a85fe12eSEd Maste 	char *rtn;
3583a85fe12eSEd Maste 
3584a85fe12eSEd Maste 	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(float))
3585a85fe12eSEd Maste 		return (NULL);
3586a85fe12eSEd Maste 
3587a85fe12eSEd Maste 	memset(&f, 0, sizeof(float));
3588a85fe12eSEd Maste 
3589a85fe12eSEd Maste 	for (i = 0; i < len / 2; ++i) {
3590a85fe12eSEd Maste 		byte = hex_to_dec(p[len - i * 2 - 1]) +
3591a85fe12eSEd Maste 		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3592a85fe12eSEd Maste 		if (byte < 0 || byte > 255)
3593a85fe12eSEd Maste 			return (NULL);
3594a85fe12eSEd Maste #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3595a85fe12eSEd Maste 		((unsigned char *)&f)[i] = (unsigned char)(byte);
3596a85fe12eSEd Maste #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3597a85fe12eSEd Maste 		((unsigned char *)&f)[sizeof(float) - i - 1] =
3598a85fe12eSEd Maste 		    (unsigned char)(byte);
3599a85fe12eSEd Maste #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3600a85fe12eSEd Maste 	}
3601a85fe12eSEd Maste 
3602a85fe12eSEd Maste 	rtn_len = 64;
3603a85fe12eSEd Maste 	limit = 0;
3604a85fe12eSEd Maste again:
3605a85fe12eSEd Maste 	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3606a85fe12eSEd Maste 		return (NULL);
3607a85fe12eSEd Maste 
3608a85fe12eSEd Maste 	if (snprintf(rtn, rtn_len, "%ff", f) >= (int)rtn_len) {
3609a85fe12eSEd Maste 		free(rtn);
3610a85fe12eSEd Maste 		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3611a85fe12eSEd Maste 			return (NULL);
3612a85fe12eSEd Maste 		rtn_len *= BUFFER_GROWFACTOR;
3613a85fe12eSEd Maste 		goto again;
3614a85fe12eSEd Maste 	}
3615a85fe12eSEd Maste 
3616a85fe12eSEd Maste 	return rtn;
3617a85fe12eSEd Maste }
3618a85fe12eSEd Maste 
3619a85fe12eSEd Maste static char *
decode_fp_to_float128(const char * p,size_t len)3620a85fe12eSEd Maste decode_fp_to_float128(const char *p, size_t len)
3621a85fe12eSEd Maste {
3622a85fe12eSEd Maste 	long double f;
3623a85fe12eSEd Maste 	size_t rtn_len, limit, i;
3624a85fe12eSEd Maste 	int byte;
3625a85fe12eSEd Maste 	unsigned char buf[FLOAT_QUADRUPLE_BYTES];
3626a85fe12eSEd Maste 	char *rtn;
3627a85fe12eSEd Maste 
3628a85fe12eSEd Maste 	switch(sizeof(long double)) {
3629a85fe12eSEd Maste 	case FLOAT_QUADRUPLE_BYTES:
3630a85fe12eSEd Maste 		return (decode_fp_to_long_double(p, len));
3631a85fe12eSEd Maste 	case FLOAT_EXTENED_BYTES:
3632a85fe12eSEd Maste 		if (p == NULL || len == 0 || len % 2 != 0 ||
3633a85fe12eSEd Maste 		    len / 2 > FLOAT_QUADRUPLE_BYTES)
3634a85fe12eSEd Maste 			return (NULL);
3635a85fe12eSEd Maste 
3636a85fe12eSEd Maste 		memset(buf, 0, FLOAT_QUADRUPLE_BYTES);
3637a85fe12eSEd Maste 
3638a85fe12eSEd Maste 		for (i = 0; i < len / 2; ++i) {
3639a85fe12eSEd Maste 			byte = hex_to_dec(p[len - i * 2 - 1]) +
3640a85fe12eSEd Maste 			    hex_to_dec(p[len - i * 2 - 2]) * 16;
3641a85fe12eSEd Maste 			if (byte < 0 || byte > 255)
3642a85fe12eSEd Maste 				return (NULL);
3643a85fe12eSEd Maste #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3644a85fe12eSEd Maste 			buf[i] = (unsigned char)(byte);
3645a85fe12eSEd Maste #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3646a85fe12eSEd Maste 			buf[FLOAT_QUADRUPLE_BYTES - i -1] =
3647a85fe12eSEd Maste 			    (unsigned char)(byte);
3648a85fe12eSEd Maste #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3649a85fe12eSEd Maste 		}
3650a85fe12eSEd Maste 		memset(&f, 0, FLOAT_EXTENED_BYTES);
3651a85fe12eSEd Maste 
3652a85fe12eSEd Maste #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3653a85fe12eSEd Maste 		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
3654a85fe12eSEd Maste #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3655a85fe12eSEd Maste 		memcpy(&f, buf + 6, FLOAT_EXTENED_BYTES);
3656a85fe12eSEd Maste #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3657a85fe12eSEd Maste 
3658a85fe12eSEd Maste 		rtn_len = 256;
3659a85fe12eSEd Maste 		limit = 0;
3660a85fe12eSEd Maste again:
3661a85fe12eSEd Maste 		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3662a85fe12eSEd Maste 			return (NULL);
3663a85fe12eSEd Maste 
3664a85fe12eSEd Maste 		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3665a85fe12eSEd Maste 			free(rtn);
3666a85fe12eSEd Maste 			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3667a85fe12eSEd Maste 				return (NULL);
3668a85fe12eSEd Maste 			rtn_len *= BUFFER_GROWFACTOR;
3669a85fe12eSEd Maste 			goto again;
3670a85fe12eSEd Maste 		}
3671a85fe12eSEd Maste 
3672a85fe12eSEd Maste 		return (rtn);
3673a85fe12eSEd Maste 	default:
3674a85fe12eSEd Maste 		return (NULL);
3675a85fe12eSEd Maste 	}
3676a85fe12eSEd Maste }
3677a85fe12eSEd Maste 
3678a85fe12eSEd Maste static char *
decode_fp_to_float80(const char * p,size_t len)3679a85fe12eSEd Maste decode_fp_to_float80(const char *p, size_t len)
3680a85fe12eSEd Maste {
3681a85fe12eSEd Maste 	long double f;
3682a85fe12eSEd Maste 	size_t rtn_len, limit, i;
3683a85fe12eSEd Maste 	int byte;
3684a85fe12eSEd Maste 	unsigned char buf[FLOAT_EXTENED_BYTES];
3685a85fe12eSEd Maste 	char *rtn;
3686a85fe12eSEd Maste 
3687a85fe12eSEd Maste 	switch(sizeof(long double)) {
3688a85fe12eSEd Maste 	case FLOAT_QUADRUPLE_BYTES:
3689a85fe12eSEd Maste 		if (p == NULL || len == 0 || len % 2 != 0 ||
3690a85fe12eSEd Maste 		    len / 2 > FLOAT_EXTENED_BYTES)
3691a85fe12eSEd Maste 			return (NULL);
3692a85fe12eSEd Maste 
3693a85fe12eSEd Maste 		memset(buf, 0, FLOAT_EXTENED_BYTES);
3694a85fe12eSEd Maste 
3695a85fe12eSEd Maste 		for (i = 0; i < len / 2; ++i) {
3696a85fe12eSEd Maste 			byte = hex_to_dec(p[len - i * 2 - 1]) +
3697a85fe12eSEd Maste 			    hex_to_dec(p[len - i * 2 - 2]) * 16;
3698a85fe12eSEd Maste 
3699a85fe12eSEd Maste 			if (byte < 0 || byte > 255)
3700a85fe12eSEd Maste 				return (NULL);
3701a85fe12eSEd Maste 
3702a85fe12eSEd Maste #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3703a85fe12eSEd Maste 			buf[i] = (unsigned char)(byte);
3704a85fe12eSEd Maste #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3705a85fe12eSEd Maste 			buf[FLOAT_EXTENED_BYTES - i -1] =
3706a85fe12eSEd Maste 			    (unsigned char)(byte);
3707a85fe12eSEd Maste #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3708a85fe12eSEd Maste 		}
3709a85fe12eSEd Maste 
3710a85fe12eSEd Maste 		memset(&f, 0, FLOAT_QUADRUPLE_BYTES);
3711a85fe12eSEd Maste 
3712a85fe12eSEd Maste #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3713a85fe12eSEd Maste 		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
3714a85fe12eSEd Maste #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3715a85fe12eSEd Maste 		memcpy((unsigned char *)(&f) + 6, buf, FLOAT_EXTENED_BYTES);
3716a85fe12eSEd Maste #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3717a85fe12eSEd Maste 
3718a85fe12eSEd Maste 		rtn_len = 256;
3719a85fe12eSEd Maste 		limit = 0;
3720a85fe12eSEd Maste again:
3721a85fe12eSEd Maste 		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3722a85fe12eSEd Maste 			return (NULL);
3723a85fe12eSEd Maste 
3724a85fe12eSEd Maste 		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3725a85fe12eSEd Maste 			free(rtn);
3726a85fe12eSEd Maste 			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3727a85fe12eSEd Maste 				return (NULL);
3728a85fe12eSEd Maste 			rtn_len *= BUFFER_GROWFACTOR;
3729a85fe12eSEd Maste 			goto again;
3730a85fe12eSEd Maste 		}
3731a85fe12eSEd Maste 
3732a85fe12eSEd Maste 		return (rtn);
3733a85fe12eSEd Maste 	case FLOAT_EXTENED_BYTES:
3734a85fe12eSEd Maste 		return (decode_fp_to_long_double(p, len));
3735a85fe12eSEd Maste 	default:
3736a85fe12eSEd Maste 		return (NULL);
3737a85fe12eSEd Maste 	}
3738a85fe12eSEd Maste }
3739a85fe12eSEd Maste 
3740a85fe12eSEd Maste static char *
decode_fp_to_long_double(const char * p,size_t len)3741a85fe12eSEd Maste decode_fp_to_long_double(const char *p, size_t len)
3742a85fe12eSEd Maste {
3743a85fe12eSEd Maste 	long double f;
3744a85fe12eSEd Maste 	size_t rtn_len, limit, i;
3745a85fe12eSEd Maste 	int byte;
3746a85fe12eSEd Maste 	char *rtn;
3747a85fe12eSEd Maste 
3748a85fe12eSEd Maste 	if (p == NULL || len == 0 || len % 2 != 0 ||
3749a85fe12eSEd Maste 	    len / 2 > sizeof(long double))
3750a85fe12eSEd Maste 		return (NULL);
3751a85fe12eSEd Maste 
3752a85fe12eSEd Maste 	memset(&f, 0, sizeof(long double));
3753a85fe12eSEd Maste 
3754a85fe12eSEd Maste 	for (i = 0; i < len / 2; ++i) {
3755a85fe12eSEd Maste 		byte = hex_to_dec(p[len - i * 2 - 1]) +
3756a85fe12eSEd Maste 		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3757a85fe12eSEd Maste 
3758a85fe12eSEd Maste 		if (byte < 0 || byte > 255)
3759a85fe12eSEd Maste 			return (NULL);
3760a85fe12eSEd Maste 
3761a85fe12eSEd Maste #if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3762a85fe12eSEd Maste 		((unsigned char *)&f)[i] = (unsigned char)(byte);
3763a85fe12eSEd Maste #else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3764a85fe12eSEd Maste 		((unsigned char *)&f)[sizeof(long double) - i - 1] =
3765a85fe12eSEd Maste 		    (unsigned char)(byte);
3766a85fe12eSEd Maste #endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3767a85fe12eSEd Maste 	}
3768a85fe12eSEd Maste 
3769a85fe12eSEd Maste 	rtn_len = 256;
3770a85fe12eSEd Maste 	limit = 0;
3771a85fe12eSEd Maste again:
3772a85fe12eSEd Maste 	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3773a85fe12eSEd Maste 		return (NULL);
3774a85fe12eSEd Maste 
3775a85fe12eSEd Maste 	if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3776a85fe12eSEd Maste 		free(rtn);
3777a85fe12eSEd Maste 		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3778a85fe12eSEd Maste 			return (NULL);
3779a85fe12eSEd Maste 		rtn_len *= BUFFER_GROWFACTOR;
3780a85fe12eSEd Maste 		goto again;
3781a85fe12eSEd Maste 	}
3782a85fe12eSEd Maste 
3783a85fe12eSEd Maste 	return (rtn);
3784a85fe12eSEd Maste }
3785a85fe12eSEd Maste 
3786a85fe12eSEd Maste /* Simple hex to integer function used by decode_to_* function. */
3787a85fe12eSEd Maste static int
hex_to_dec(char c)3788a85fe12eSEd Maste hex_to_dec(char c)
3789a85fe12eSEd Maste {
3790a85fe12eSEd Maste 
3791a85fe12eSEd Maste 	switch (c) {
3792a85fe12eSEd Maste 	case '0':
3793a85fe12eSEd Maste 		return (0);
3794a85fe12eSEd Maste 	case '1':
3795a85fe12eSEd Maste 		return (1);
3796a85fe12eSEd Maste 	case '2':
3797a85fe12eSEd Maste 		return (2);
3798a85fe12eSEd Maste 	case '3':
3799a85fe12eSEd Maste 		return (3);
3800a85fe12eSEd Maste 	case '4':
3801a85fe12eSEd Maste 		return (4);
3802a85fe12eSEd Maste 	case '5':
3803a85fe12eSEd Maste 		return (5);
3804a85fe12eSEd Maste 	case '6':
3805a85fe12eSEd Maste 		return (6);
3806a85fe12eSEd Maste 	case '7':
3807a85fe12eSEd Maste 		return (7);
3808a85fe12eSEd Maste 	case '8':
3809a85fe12eSEd Maste 		return (8);
3810a85fe12eSEd Maste 	case '9':
3811a85fe12eSEd Maste 		return (9);
3812a85fe12eSEd Maste 	case 'a':
3813a85fe12eSEd Maste 		return (10);
3814a85fe12eSEd Maste 	case 'b':
3815a85fe12eSEd Maste 		return (11);
3816a85fe12eSEd Maste 	case 'c':
3817a85fe12eSEd Maste 		return (12);
3818a85fe12eSEd Maste 	case 'd':
3819a85fe12eSEd Maste 		return (13);
3820a85fe12eSEd Maste 	case 'e':
3821a85fe12eSEd Maste 		return (14);
3822a85fe12eSEd Maste 	case 'f':
3823a85fe12eSEd Maste 		return (15);
3824a85fe12eSEd Maste 	default:
3825a85fe12eSEd Maste 		return (-1);
3826b6b6f9ccSEd Maste 	}
3827a85fe12eSEd Maste }
3828a85fe12eSEd Maste 
3829a85fe12eSEd Maste /**
3830a85fe12eSEd Maste  * @brief Test input string is mangled by IA-64 C++ ABI style.
3831a85fe12eSEd Maste  *
3832a85fe12eSEd Maste  * Test string heads with "_Z" or "_GLOBAL__I_".
3833a85fe12eSEd Maste  * @return Return 0 at false.
3834a85fe12eSEd Maste  */
3835a85fe12eSEd Maste bool
is_cpp_mangled_gnu3(const char * org)3836a85fe12eSEd Maste is_cpp_mangled_gnu3(const char *org)
3837a85fe12eSEd Maste {
3838a85fe12eSEd Maste 	size_t len;
3839a85fe12eSEd Maste 
3840a85fe12eSEd Maste 	len = strlen(org);
3841a85fe12eSEd Maste 	return ((len > 2 && *org == '_' && *(org + 1) == 'Z') ||
3842a85fe12eSEd Maste 	    (len > 11 && !strncmp(org, "_GLOBAL__I_", 11)));
3843a85fe12eSEd Maste }
3844a85fe12eSEd Maste 
3845a85fe12eSEd Maste static void
vector_read_cmd_dest(struct vector_read_cmd * v)3846a85fe12eSEd Maste vector_read_cmd_dest(struct vector_read_cmd *v)
3847a85fe12eSEd Maste {
3848a85fe12eSEd Maste 
3849a85fe12eSEd Maste 	if (v == NULL)
3850a85fe12eSEd Maste 		return;
3851a85fe12eSEd Maste 
3852a85fe12eSEd Maste 	free(v->r_container);
3853a85fe12eSEd Maste }
3854a85fe12eSEd Maste 
385518f4c9dbSEd Maste static struct read_cmd_item *
vector_read_cmd_find(struct vector_read_cmd * v,enum read_cmd dst)3856a85fe12eSEd Maste vector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst)
3857a85fe12eSEd Maste {
385818f4c9dbSEd Maste 	int i;
3859a85fe12eSEd Maste 
3860a85fe12eSEd Maste 	if (v == NULL || dst == READ_FAIL)
386118f4c9dbSEd Maste 		return (NULL);
3862a85fe12eSEd Maste 
386318f4c9dbSEd Maste 	for (i = (int) v->size - 1; i >= 0; i--)
386418f4c9dbSEd Maste 		if (v->r_container[i].cmd == dst)
386518f4c9dbSEd Maste 			return (&v->r_container[i]);
3866a85fe12eSEd Maste 
386718f4c9dbSEd Maste 	return (NULL);
3868a85fe12eSEd Maste }
3869a85fe12eSEd Maste 
3870a85fe12eSEd Maste static int
vector_read_cmd_init(struct vector_read_cmd * v)3871a85fe12eSEd Maste vector_read_cmd_init(struct vector_read_cmd *v)
3872a85fe12eSEd Maste {
3873a85fe12eSEd Maste 
3874a85fe12eSEd Maste 	if (v == NULL)
3875a85fe12eSEd Maste 		return (0);
3876a85fe12eSEd Maste 
3877a85fe12eSEd Maste 	v->size = 0;
3878a85fe12eSEd Maste 	v->capacity = VECTOR_DEF_CAPACITY;
3879a85fe12eSEd Maste 
388018f4c9dbSEd Maste 	if ((v->r_container = malloc(sizeof(*v->r_container) * v->capacity))
3881a85fe12eSEd Maste 	    == NULL)
3882a85fe12eSEd Maste 		return (0);
3883a85fe12eSEd Maste 
3884a85fe12eSEd Maste 	return (1);
3885a85fe12eSEd Maste }
3886a85fe12eSEd Maste 
3887a85fe12eSEd Maste static int
vector_read_cmd_pop(struct vector_read_cmd * v)3888a85fe12eSEd Maste vector_read_cmd_pop(struct vector_read_cmd *v)
3889a85fe12eSEd Maste {
3890a85fe12eSEd Maste 
3891a85fe12eSEd Maste 	if (v == NULL || v->size == 0)
3892a85fe12eSEd Maste 		return (0);
3893a85fe12eSEd Maste 
3894a85fe12eSEd Maste 	--v->size;
389518f4c9dbSEd Maste 	v->r_container[v->size].cmd = READ_FAIL;
389618f4c9dbSEd Maste 	v->r_container[v->size].data = NULL;
3897a85fe12eSEd Maste 
3898a85fe12eSEd Maste 	return (1);
3899a85fe12eSEd Maste }
3900a85fe12eSEd Maste 
3901a85fe12eSEd Maste static int
vector_read_cmd_push(struct vector_read_cmd * v,enum read_cmd cmd,void * data)390218f4c9dbSEd Maste vector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd, void *data)
3903a85fe12eSEd Maste {
390418f4c9dbSEd Maste 	struct read_cmd_item *tmp_r_ctn;
3905a85fe12eSEd Maste 	size_t tmp_cap;
3906a85fe12eSEd Maste 	size_t i;
3907a85fe12eSEd Maste 
3908a85fe12eSEd Maste 	if (v == NULL)
3909a85fe12eSEd Maste 		return (0);
3910a85fe12eSEd Maste 
3911a85fe12eSEd Maste 	if (v->size == v->capacity) {
3912c2bffd0aSDimitry Andric 		tmp_cap = BUFFER_GROW(v->capacity);
391318f4c9dbSEd Maste 		if ((tmp_r_ctn = malloc(sizeof(*tmp_r_ctn) * tmp_cap)) == NULL)
3914a85fe12eSEd Maste 			return (0);
3915a85fe12eSEd Maste 		for (i = 0; i < v->size; ++i)
3916a85fe12eSEd Maste 			tmp_r_ctn[i] = v->r_container[i];
3917a85fe12eSEd Maste 		free(v->r_container);
3918a85fe12eSEd Maste 		v->r_container = tmp_r_ctn;
3919a85fe12eSEd Maste 		v->capacity = tmp_cap;
3920a85fe12eSEd Maste 	}
3921a85fe12eSEd Maste 
392218f4c9dbSEd Maste 	v->r_container[v->size].cmd = cmd;
392318f4c9dbSEd Maste 	v->r_container[v->size].data = data;
3924a85fe12eSEd Maste 	++v->size;
3925a85fe12eSEd Maste 
3926a85fe12eSEd Maste 	return (1);
3927a85fe12eSEd Maste }
3928a85fe12eSEd Maste 
3929a85fe12eSEd Maste static void
vector_type_qualifier_dest(struct vector_type_qualifier * v)3930a85fe12eSEd Maste vector_type_qualifier_dest(struct vector_type_qualifier *v)
3931a85fe12eSEd Maste {
3932a85fe12eSEd Maste 
3933a85fe12eSEd Maste 	if (v == NULL)
3934a85fe12eSEd Maste 		return;
3935a85fe12eSEd Maste 
3936a85fe12eSEd Maste 	free(v->q_container);
3937a85fe12eSEd Maste 	vector_str_dest(&v->ext_name);
3938a85fe12eSEd Maste }
3939a85fe12eSEd Maste 
3940a85fe12eSEd Maste /* size, capacity, ext_name */
3941a85fe12eSEd Maste static int
vector_type_qualifier_init(struct vector_type_qualifier * v)3942a85fe12eSEd Maste vector_type_qualifier_init(struct vector_type_qualifier *v)
3943a85fe12eSEd Maste {
3944a85fe12eSEd Maste 
3945a85fe12eSEd Maste 	if (v == NULL)
3946a85fe12eSEd Maste 		return (0);
3947a85fe12eSEd Maste 
3948a85fe12eSEd Maste 	v->size = 0;
3949a85fe12eSEd Maste 	v->capacity = VECTOR_DEF_CAPACITY;
3950a85fe12eSEd Maste 
3951a85fe12eSEd Maste 	if ((v->q_container = malloc(sizeof(enum type_qualifier) * v->capacity))
3952a85fe12eSEd Maste 	    == NULL)
3953a85fe12eSEd Maste 		return (0);
3954a85fe12eSEd Maste 
3955a85fe12eSEd Maste 	assert(v->q_container != NULL);
3956a85fe12eSEd Maste 
3957334f09a6SMark Johnston 	if (!vector_str_init(&v->ext_name)) {
3958a85fe12eSEd Maste 		free(v->q_container);
3959a85fe12eSEd Maste 		return (0);
3960a85fe12eSEd Maste 	}
3961a85fe12eSEd Maste 
3962a85fe12eSEd Maste 	return (1);
3963a85fe12eSEd Maste }
3964a85fe12eSEd Maste 
3965a85fe12eSEd Maste static int
vector_type_qualifier_push(struct vector_type_qualifier * v,enum type_qualifier t)3966a85fe12eSEd Maste vector_type_qualifier_push(struct vector_type_qualifier *v,
3967a85fe12eSEd Maste     enum type_qualifier t)
3968a85fe12eSEd Maste {
3969a85fe12eSEd Maste 	enum type_qualifier *tmp_ctn;
3970a85fe12eSEd Maste 	size_t tmp_cap;
3971a85fe12eSEd Maste 	size_t i;
3972a85fe12eSEd Maste 
3973a85fe12eSEd Maste 	if (v == NULL)
3974a85fe12eSEd Maste 		return (0);
3975a85fe12eSEd Maste 
3976a85fe12eSEd Maste 	if (v->size == v->capacity) {
3977c2bffd0aSDimitry Andric 		tmp_cap = BUFFER_GROW(v->capacity);
3978a85fe12eSEd Maste 		if ((tmp_ctn = malloc(sizeof(enum type_qualifier) * tmp_cap))
3979a85fe12eSEd Maste 		    == NULL)
3980a85fe12eSEd Maste 			return (0);
3981a85fe12eSEd Maste 		for (i = 0; i < v->size; ++i)
3982a85fe12eSEd Maste 			tmp_ctn[i] = v->q_container[i];
3983a85fe12eSEd Maste 		free(v->q_container);
3984a85fe12eSEd Maste 		v->q_container = tmp_ctn;
3985a85fe12eSEd Maste 		v->capacity = tmp_cap;
3986a85fe12eSEd Maste 	}
3987a85fe12eSEd Maste 
3988a85fe12eSEd Maste 	v->q_container[v->size] = t;
3989a85fe12eSEd Maste 	++v->size;
3990a85fe12eSEd Maste 
3991a85fe12eSEd Maste 	return (1);
3992a85fe12eSEd Maste }
3993