xref: /freebsd-src/contrib/elftoolchain/libelftc/libelftc_dem_gnu2.c (revision bc02c18c486fce2ca23b428a9e89b4eb3bb48da3)
1a85fe12eSEd Maste /*-
2a85fe12eSEd Maste  * Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com>
3a85fe12eSEd Maste  * All rights reserved.
4a85fe12eSEd Maste  *
5a85fe12eSEd Maste  * Redistribution and use in source and binary forms, with or without
6a85fe12eSEd Maste  * modification, are permitted provided that the following conditions
7a85fe12eSEd Maste  * are met:
8a85fe12eSEd Maste  * 1. Redistributions of source code must retain the above copyright
9a85fe12eSEd Maste  *    notice, this list of conditions and the following disclaimer
10a85fe12eSEd Maste  *    in this position and unchanged.
11a85fe12eSEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
12a85fe12eSEd Maste  *    notice, this list of conditions and the following disclaimer in the
13a85fe12eSEd Maste  *    documentation and/or other materials provided with the distribution.
14a85fe12eSEd Maste  *
15a85fe12eSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16a85fe12eSEd Maste  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17a85fe12eSEd Maste  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18a85fe12eSEd Maste  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19a85fe12eSEd Maste  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20a85fe12eSEd Maste  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21a85fe12eSEd Maste  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22a85fe12eSEd Maste  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23a85fe12eSEd Maste  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24a85fe12eSEd Maste  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25a85fe12eSEd Maste  */
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 
40bee2765cSEd Maste ELFTC_VCSID("$Id: libelftc_dem_gnu2.c 3513 2016-12-29 07:04:22Z kaiwang27 $");
41a85fe12eSEd Maste 
42a85fe12eSEd Maste /**
43a85fe12eSEd Maste  * @file cpp_demangle_gnu2.c
44a85fe12eSEd Maste  * @brief Decode function name encoding in GNU 2.
45a85fe12eSEd Maste  *
46a85fe12eSEd Maste  * Function name encoding in GNU 2 based on ARM style.
47a85fe12eSEd Maste  */
48a85fe12eSEd Maste 
49a85fe12eSEd Maste enum encode_type {
50a85fe12eSEd Maste 	ENCODE_FUNC, ENCODE_OP, ENCODE_OP_CT, ENCODE_OP_DT, ENCODE_OP_USER,
51a85fe12eSEd Maste 	ENCODE_OP_TF, ENCODE_OP_TI, ENCODE_OP_VT
52a85fe12eSEd Maste };
53a85fe12eSEd Maste 
54a85fe12eSEd Maste struct cstring {
55a85fe12eSEd Maste 	char	*buf;
56a85fe12eSEd Maste 	size_t	size;
57a85fe12eSEd Maste };
58a85fe12eSEd Maste 
59a85fe12eSEd Maste struct demangle_data {
60a85fe12eSEd Maste 	bool	ptr, ref, cnst, array, cnst_fn, class_name;
61a85fe12eSEd Maste 	struct cstring array_str;
62a85fe12eSEd Maste 	const char *p;
63a85fe12eSEd Maste 	enum encode_type type;
64a85fe12eSEd Maste 	struct vector_str vec;
65a85fe12eSEd Maste 	struct vector_str arg;
66a85fe12eSEd Maste };
67a85fe12eSEd Maste 
68a85fe12eSEd Maste #define SIMPLE_HASH(x,y)	(64 * x + y)
69bee2765cSEd Maste #define VEC_PUSH_STR(d,s)	vector_str_push((d), (s), strlen((s)))
70a85fe12eSEd Maste #define	CPP_DEMANGLE_GNU2_TRY	128
71a85fe12eSEd Maste 
72a85fe12eSEd Maste static void	dest_cstring(struct cstring *);
73a85fe12eSEd Maste static void	dest_demangle_data(struct demangle_data *);
74a85fe12eSEd Maste static bool	init_cstring(struct cstring *, size_t);
75a85fe12eSEd Maste static bool	init_demangle_data(struct demangle_data *);
76a85fe12eSEd Maste static bool	push_CTDT(const char *, size_t, struct vector_str *);
77a85fe12eSEd Maste static bool	read_array(struct demangle_data *);
78a85fe12eSEd Maste static bool	read_class(struct demangle_data *);
79a85fe12eSEd Maste static bool	read_func(struct demangle_data *);
80a85fe12eSEd Maste static bool	read_func_name(struct demangle_data *);
81a85fe12eSEd Maste static bool	read_func_ptr(struct demangle_data *);
82a85fe12eSEd Maste static bool	read_memptr(struct demangle_data *);
83a85fe12eSEd Maste static bool	read_op(struct demangle_data *);
84a85fe12eSEd Maste static bool	read_op_user(struct demangle_data *);
85a85fe12eSEd Maste static bool	read_qual_name(struct demangle_data *);
86a85fe12eSEd Maste static int	read_subst(struct demangle_data *);
87a85fe12eSEd Maste static int	read_subst_iter(struct demangle_data *);
88a85fe12eSEd Maste static bool	read_type(struct demangle_data *);
89a85fe12eSEd Maste 
90a85fe12eSEd Maste /**
91a85fe12eSEd Maste  * @brief Decode the input string by the GNU 2 style.
92a85fe12eSEd Maste  *
93a85fe12eSEd Maste  * @return New allocated demangled string or NULL if failed.
94a85fe12eSEd Maste  */
95a85fe12eSEd Maste char *
cpp_demangle_gnu2(const char * org)96a85fe12eSEd Maste cpp_demangle_gnu2(const char *org)
97a85fe12eSEd Maste {
98a85fe12eSEd Maste 	struct demangle_data d;
99a85fe12eSEd Maste 	size_t arg_begin, arg_len;
100a85fe12eSEd Maste 	unsigned int try;
101a85fe12eSEd Maste 	char *rtn, *arg;
102a85fe12eSEd Maste 
103a85fe12eSEd Maste 	if (org == NULL)
104a85fe12eSEd Maste 		return (NULL);
105a85fe12eSEd Maste 
106a85fe12eSEd Maste 	if (init_demangle_data(&d) == false)
107a85fe12eSEd Maste 		return (NULL);
108a85fe12eSEd Maste 
109a85fe12eSEd Maste 	try = 0;
110a85fe12eSEd Maste 	rtn = NULL;
111a85fe12eSEd Maste 
112a85fe12eSEd Maste 	d.p = org;
113a85fe12eSEd Maste 	if (read_func_name(&d) == false)
114a85fe12eSEd Maste 		goto clean;
115a85fe12eSEd Maste 
116a85fe12eSEd Maste 	switch (d.type) {
117a85fe12eSEd Maste 	case ENCODE_FUNC :
118a85fe12eSEd Maste 	case ENCODE_OP :
119a85fe12eSEd Maste 		break;
120a85fe12eSEd Maste 
121a85fe12eSEd Maste 	case ENCODE_OP_CT :
122a85fe12eSEd Maste 		if (push_CTDT("::", 2, &d.vec) == false)
123a85fe12eSEd Maste 			goto clean;
124a85fe12eSEd Maste 
125a85fe12eSEd Maste                 break;
126a85fe12eSEd Maste 	case ENCODE_OP_DT :
127a85fe12eSEd Maste 		if (push_CTDT("::~", 3, &d.vec) == false)
128a85fe12eSEd Maste 			goto clean;
129a85fe12eSEd Maste 
130bee2765cSEd Maste 		if (VEC_PUSH_STR(&d.vec, "(void)") == false)
131a85fe12eSEd Maste 			goto clean;
132a85fe12eSEd Maste 
133a85fe12eSEd Maste 		goto flat;
134a85fe12eSEd Maste 	case ENCODE_OP_USER :
135a85fe12eSEd Maste 	case ENCODE_OP_TF :
136a85fe12eSEd Maste 	case ENCODE_OP_TI :
137a85fe12eSEd Maste 	case ENCODE_OP_VT :
138a85fe12eSEd Maste 		goto flat;
139b6b6f9ccSEd Maste 	}
140a85fe12eSEd Maste 
141a85fe12eSEd Maste 	if (*d.p == 'F')
142a85fe12eSEd Maste 		++d.p;
143a85fe12eSEd Maste 	else if (*d.p == '\0') {
144a85fe12eSEd Maste 		if (d.class_name == true) {
145bee2765cSEd Maste 			if (VEC_PUSH_STR(&d.vec, "(void)") == false)
146a85fe12eSEd Maste 				goto clean;
147a85fe12eSEd Maste 
148a85fe12eSEd Maste 			goto flat;
149a85fe12eSEd Maste 		} else
150a85fe12eSEd Maste 			goto clean;
151a85fe12eSEd Maste 	}
152a85fe12eSEd Maste 
153a85fe12eSEd Maste 	/* start argument types */
154bee2765cSEd Maste 	if (VEC_PUSH_STR(&d.vec, "(") == false)
155a85fe12eSEd Maste 		goto clean;
156a85fe12eSEd Maste 
157a85fe12eSEd Maste 	for (;;) {
158a85fe12eSEd Maste 		if (*d.p == 'T') {
159a85fe12eSEd Maste 			const int rtn_subst = read_subst(&d);
160a85fe12eSEd Maste 
161a85fe12eSEd Maste 			if (rtn_subst == -1)
162a85fe12eSEd Maste 				goto clean;
163a85fe12eSEd Maste 			else if (rtn_subst == 1)
164a85fe12eSEd Maste 				break;
165a85fe12eSEd Maste 
166a85fe12eSEd Maste 			continue;
167a85fe12eSEd Maste 		}
168a85fe12eSEd Maste 
169a85fe12eSEd Maste 		if (*d.p == 'N') {
170a85fe12eSEd Maste 			const int rtn_subst_iter = read_subst_iter(&d);
171a85fe12eSEd Maste 
172a85fe12eSEd Maste 			if (rtn_subst_iter == -1)
173a85fe12eSEd Maste 				goto clean;
174a85fe12eSEd Maste 			else if(rtn_subst_iter == 1)
175a85fe12eSEd Maste 				break;
176a85fe12eSEd Maste 
177a85fe12eSEd Maste 			continue;
178a85fe12eSEd Maste 		}
179a85fe12eSEd Maste 
180a85fe12eSEd Maste 		arg_begin = d.vec.size;
181a85fe12eSEd Maste 
182a85fe12eSEd Maste 		if (read_type(&d) == false)
183a85fe12eSEd Maste 			goto clean;
184a85fe12eSEd Maste 
185a85fe12eSEd Maste 		if (d.ptr == true) {
186bee2765cSEd Maste 			if (VEC_PUSH_STR(&d.vec, "*") == false)
187a85fe12eSEd Maste 				goto clean;
188a85fe12eSEd Maste 
189a85fe12eSEd Maste 			d.ptr = false;
190a85fe12eSEd Maste 		}
191a85fe12eSEd Maste 
192a85fe12eSEd Maste 		if (d.ref == true) {
193bee2765cSEd Maste 			if (VEC_PUSH_STR(&d.vec, "&") == false)
194a85fe12eSEd Maste 				goto clean;
195a85fe12eSEd Maste 
196a85fe12eSEd Maste 			d.ref = false;
197a85fe12eSEd Maste 		}
198a85fe12eSEd Maste 
199a85fe12eSEd Maste 		if (d.cnst == true) {
200bee2765cSEd Maste 			if (VEC_PUSH_STR(&d.vec, " const") == false)
201a85fe12eSEd Maste 				goto clean;
202a85fe12eSEd Maste 
203a85fe12eSEd Maste 			d.cnst = false;
204a85fe12eSEd Maste 		}
205a85fe12eSEd Maste 
206a85fe12eSEd Maste 		if (d.array == true) {
207a85fe12eSEd Maste 			if (vector_str_push(&d.vec, d.array_str.buf,
208a85fe12eSEd Maste 				d.array_str.size) == false)
209a85fe12eSEd Maste 				goto clean;
210a85fe12eSEd Maste 
211a85fe12eSEd Maste 			dest_cstring(&d.array_str);
212a85fe12eSEd Maste 			d.array = false;
213a85fe12eSEd Maste 		}
214a85fe12eSEd Maste 
215a85fe12eSEd Maste 		if (*d.p == '\0')
216a85fe12eSEd Maste 			break;
217a85fe12eSEd Maste 
218a85fe12eSEd Maste 		if ((arg = vector_str_substr(&d.vec, arg_begin, d.vec.size - 1,
219a85fe12eSEd Maste 		    &arg_len)) == NULL)
220a85fe12eSEd Maste 			goto clean;
221a85fe12eSEd Maste 
222a3c35da6SMark Johnston 		if (vector_str_push(&d.arg, arg, arg_len) == false) {
223a3c35da6SMark Johnston 			free(arg);
224a85fe12eSEd Maste 			goto clean;
225a3c35da6SMark Johnston 		}
226a85fe12eSEd Maste 
227a85fe12eSEd Maste 		free(arg);
228a85fe12eSEd Maste 
229bee2765cSEd Maste 		if (VEC_PUSH_STR(&d.vec, ", ") == false)
230a85fe12eSEd Maste 			goto clean;
231a85fe12eSEd Maste 
232a85fe12eSEd Maste 		if (++try > CPP_DEMANGLE_GNU2_TRY)
233a85fe12eSEd Maste 			goto clean;
234a85fe12eSEd Maste 	}
235a85fe12eSEd Maste 
236a85fe12eSEd Maste 	/* end argument types */
237bee2765cSEd Maste 	if (VEC_PUSH_STR(&d.vec, ")") == false)
238a85fe12eSEd Maste 		goto clean;
239a85fe12eSEd Maste flat:
240bee2765cSEd Maste 	if (d.cnst_fn == true && VEC_PUSH_STR(&d.vec, " const") == false)
241a85fe12eSEd Maste 		goto clean;
242a85fe12eSEd Maste 
243a85fe12eSEd Maste 	rtn = vector_str_get_flat(&d.vec, NULL);
244a85fe12eSEd Maste clean:
245a85fe12eSEd Maste 	dest_demangle_data(&d);
246a85fe12eSEd Maste 
247a85fe12eSEd Maste 	return (rtn);
248a85fe12eSEd Maste }
249a85fe12eSEd Maste 
250a85fe12eSEd Maste /**
251a85fe12eSEd Maste  * @brief Test input string is encoded by the GNU 2 style.
252a85fe12eSEd Maste  *
253a85fe12eSEd Maste  * @return True if input string is encoded by the GNU 2 style.
254a85fe12eSEd Maste  */
255a85fe12eSEd Maste bool
is_cpp_mangled_gnu2(const char * org)256a85fe12eSEd Maste is_cpp_mangled_gnu2(const char *org)
257a85fe12eSEd Maste {
258a85fe12eSEd Maste 	char *str;
259a85fe12eSEd Maste 	bool rtn = false;
260a85fe12eSEd Maste 
261a85fe12eSEd Maste 	if (org == NULL)
262a85fe12eSEd Maste 		return (false);
263a85fe12eSEd Maste 
264a85fe12eSEd Maste 	/* search valid text to end */
265a85fe12eSEd Maste 	str = strstr(org, "__");
266a85fe12eSEd Maste 	while (str != NULL) {
267a85fe12eSEd Maste 		if (*(str + 2) != '\0') {
268a85fe12eSEd Maste 			if (*(str + 2) == 'C' ||
269a85fe12eSEd Maste 			    *(str + 2) == 'F' ||
270a85fe12eSEd Maste 			    *(str + 2) == 'Q' ||
271a85fe12eSEd Maste 			    ELFTC_ISDIGIT(*(str + 2))) {
272a85fe12eSEd Maste 				rtn |= true;
273a85fe12eSEd Maste 
274a85fe12eSEd Maste 				break;
275a85fe12eSEd Maste 			}
276a85fe12eSEd Maste 
277a85fe12eSEd Maste 			if (*(str + 3) != '\0') {
278a85fe12eSEd Maste 				switch (SIMPLE_HASH(*(str + 2), *(str + 3))) {
279a85fe12eSEd Maste 				case SIMPLE_HASH('m', 'l') :
280a85fe12eSEd Maste 				case SIMPLE_HASH('d', 'v') :
281a85fe12eSEd Maste 				case SIMPLE_HASH('m', 'd') :
282a85fe12eSEd Maste 				case SIMPLE_HASH('p', 'l') :
283a85fe12eSEd Maste 				case SIMPLE_HASH('m', 'i') :
284a85fe12eSEd Maste 				case SIMPLE_HASH('l', 's') :
285a85fe12eSEd Maste 				case SIMPLE_HASH('r', 's') :
286a85fe12eSEd Maste 				case SIMPLE_HASH('e', 'q') :
287a85fe12eSEd Maste 				case SIMPLE_HASH('n', 'e') :
288a85fe12eSEd Maste 				case SIMPLE_HASH('l', 't') :
289a85fe12eSEd Maste 				case SIMPLE_HASH('g', 't') :
290a85fe12eSEd Maste 				case SIMPLE_HASH('l', 'e') :
291a85fe12eSEd Maste 				case SIMPLE_HASH('g', 'e') :
292a85fe12eSEd Maste 				case SIMPLE_HASH('a', 'd') :
293a85fe12eSEd Maste 				case SIMPLE_HASH('o', 'r') :
294a85fe12eSEd Maste 				case SIMPLE_HASH('e', 'r') :
295a85fe12eSEd Maste 				case SIMPLE_HASH('a', 'a') :
296a85fe12eSEd Maste 				case SIMPLE_HASH('o', 'o') :
297a85fe12eSEd Maste 				case SIMPLE_HASH('n', 't') :
298a85fe12eSEd Maste 				case SIMPLE_HASH('c', 'o') :
299a85fe12eSEd Maste 				case SIMPLE_HASH('p', 'p') :
300a85fe12eSEd Maste 				case SIMPLE_HASH('m', 'm') :
301a85fe12eSEd Maste 				case SIMPLE_HASH('a', 's') :
302a85fe12eSEd Maste 				case SIMPLE_HASH('r', 'f') :
303a85fe12eSEd Maste 				case SIMPLE_HASH('a', 'p') :
304a85fe12eSEd Maste 				case SIMPLE_HASH('a', 'm') :
305a85fe12eSEd Maste 				case SIMPLE_HASH('a', 'l') :
306a85fe12eSEd Maste 				case SIMPLE_HASH('a', 'r') :
307a85fe12eSEd Maste 				case SIMPLE_HASH('a', 'o') :
308a85fe12eSEd Maste 				case SIMPLE_HASH('a', 'e') :
309a85fe12eSEd Maste 				case SIMPLE_HASH('c', 'm') :
310a85fe12eSEd Maste 				case SIMPLE_HASH('r', 'm') :
311a85fe12eSEd Maste 				case SIMPLE_HASH('c', 'l') :
312a85fe12eSEd Maste 				case SIMPLE_HASH('v', 'c') :
313a85fe12eSEd Maste 				case SIMPLE_HASH('n', 'w') :
314a85fe12eSEd Maste 				case SIMPLE_HASH('d', 'l') :
315a85fe12eSEd Maste 				case SIMPLE_HASH('o', 'p') :
316a85fe12eSEd Maste 				case SIMPLE_HASH('t', 'f') :
317a85fe12eSEd Maste 				case SIMPLE_HASH('t', 'i') :
318a85fe12eSEd Maste 					rtn |= true;
319a85fe12eSEd Maste 
320a85fe12eSEd Maste 					break;
321b6b6f9ccSEd Maste 				}
322a85fe12eSEd Maste 			}
323a85fe12eSEd Maste 		}
324a85fe12eSEd Maste 
325a85fe12eSEd Maste 		str = strstr(str + 2, "__");
326a85fe12eSEd Maste 	}
327a85fe12eSEd Maste 
328a85fe12eSEd Maste 	rtn |= strstr(org, "_$_") != NULL;
329a85fe12eSEd Maste 	rtn |= strstr(org, "_vt$") != NULL;
330a85fe12eSEd Maste 
331a85fe12eSEd Maste 	return (rtn);
332a85fe12eSEd Maste }
333a85fe12eSEd Maste 
334a85fe12eSEd Maste static void
dest_cstring(struct cstring * s)335a85fe12eSEd Maste dest_cstring(struct cstring *s)
336a85fe12eSEd Maste {
337a85fe12eSEd Maste 
338a85fe12eSEd Maste 	if (s == NULL)
339a85fe12eSEd Maste 		return;
340a85fe12eSEd Maste 
341a85fe12eSEd Maste 	free(s->buf);
342a85fe12eSEd Maste 	s->buf = NULL;
343a85fe12eSEd Maste 	s->size = 0;
344a85fe12eSEd Maste }
345a85fe12eSEd Maste 
346a85fe12eSEd Maste static void
dest_demangle_data(struct demangle_data * d)347a85fe12eSEd Maste dest_demangle_data(struct demangle_data *d)
348a85fe12eSEd Maste {
349a85fe12eSEd Maste 
350a85fe12eSEd Maste 	if (d != NULL) {
351a85fe12eSEd Maste 		vector_str_dest(&d->arg);
352a85fe12eSEd Maste 		vector_str_dest(&d->vec);
353a85fe12eSEd Maste 
354a85fe12eSEd Maste 		dest_cstring(&d->array_str);
355a85fe12eSEd Maste 	}
356a85fe12eSEd Maste }
357a85fe12eSEd Maste 
358a85fe12eSEd Maste static bool
init_cstring(struct cstring * s,size_t len)359a85fe12eSEd Maste init_cstring(struct cstring *s, size_t len)
360a85fe12eSEd Maste {
361a85fe12eSEd Maste 
362a85fe12eSEd Maste 	if (s == NULL || len <= 1)
363a85fe12eSEd Maste 		return (false);
364a85fe12eSEd Maste 
365a85fe12eSEd Maste 	if ((s->buf = malloc(sizeof(char) * len)) == NULL)
366a85fe12eSEd Maste 		return (false);
367a85fe12eSEd Maste 
368a85fe12eSEd Maste 	s->size = len - 1;
369a85fe12eSEd Maste 
370a85fe12eSEd Maste 	return (true);
371a85fe12eSEd Maste }
372a85fe12eSEd Maste 
373a85fe12eSEd Maste static bool
init_demangle_data(struct demangle_data * d)374a85fe12eSEd Maste init_demangle_data(struct demangle_data *d)
375a85fe12eSEd Maste {
376a85fe12eSEd Maste 
377a85fe12eSEd Maste 	if (d == NULL)
378a85fe12eSEd Maste 		return (false);
379a85fe12eSEd Maste 
380a85fe12eSEd Maste 	d->ptr = false;
381a85fe12eSEd Maste 	d->ref = false;
382a85fe12eSEd Maste 	d->cnst = false;
383a85fe12eSEd Maste 	d->array = false;
384a85fe12eSEd Maste 	d->cnst_fn = false;
385a85fe12eSEd Maste 	d->class_name = false;
386a85fe12eSEd Maste 
387a85fe12eSEd Maste 	d->array_str.buf = NULL;
388a85fe12eSEd Maste 	d->array_str.size = 0;
389a85fe12eSEd Maste 
390a85fe12eSEd Maste 	d->type = ENCODE_FUNC;
391a85fe12eSEd Maste 
392*334f09a6SMark Johnston 	if (!vector_str_init(&d->vec))
393a85fe12eSEd Maste 		return (false);
394a85fe12eSEd Maste 
395*334f09a6SMark Johnston 	if (!vector_str_init(&d->arg)) {
396a85fe12eSEd Maste 		vector_str_dest(&d->vec);
397a85fe12eSEd Maste 		return (false);
398a85fe12eSEd Maste 	}
399a85fe12eSEd Maste 
400a85fe12eSEd Maste 	return (true);
401a85fe12eSEd Maste }
402a85fe12eSEd Maste 
403a85fe12eSEd Maste static bool
push_CTDT(const char * s,size_t l,struct vector_str * v)404a85fe12eSEd Maste push_CTDT(const char *s, size_t l, struct vector_str *v)
405a85fe12eSEd Maste {
406a85fe12eSEd Maste 
407a85fe12eSEd Maste 	if (s == NULL || l == 0 || v == NULL)
408a85fe12eSEd Maste 		return (false);
409a85fe12eSEd Maste 
410a85fe12eSEd Maste 	if (vector_str_push(v, s, l) == false)
411a85fe12eSEd Maste 		return (false);
412a85fe12eSEd Maste 
413a85fe12eSEd Maste 	assert(v->size > 1);
414a85fe12eSEd Maste 
415bee2765cSEd Maste 	return (VEC_PUSH_STR(v, v->container[v->size - 2]));
416a85fe12eSEd Maste }
417a85fe12eSEd Maste 
418a85fe12eSEd Maste static bool
read_array(struct demangle_data * d)419a85fe12eSEd Maste read_array(struct demangle_data *d)
420a85fe12eSEd Maste {
421a85fe12eSEd Maste 	size_t len;
422a85fe12eSEd Maste 	const char *end;
423a85fe12eSEd Maste 
424a85fe12eSEd Maste 	if (d == NULL || d->p == NULL)
425a85fe12eSEd Maste 		return (false);
426a85fe12eSEd Maste 
427a85fe12eSEd Maste 	end = d->p;
428a85fe12eSEd Maste 	assert(end != NULL);
429a85fe12eSEd Maste 
430a85fe12eSEd Maste 	for (;;) {
431a85fe12eSEd Maste 		if (*end == '\0')
432a85fe12eSEd Maste 			return (false);
433a85fe12eSEd Maste 
434a85fe12eSEd Maste 		if (ELFTC_ISDIGIT(*end) == 0)
435a85fe12eSEd Maste 			break;
436a85fe12eSEd Maste 
437a85fe12eSEd Maste 		++end;
438a85fe12eSEd Maste 	}
439a85fe12eSEd Maste 
440a85fe12eSEd Maste 	if (*end != '_')
441a85fe12eSEd Maste 		return (false);
442a85fe12eSEd Maste 
443a85fe12eSEd Maste 	len = end - d->p;
444a85fe12eSEd Maste 	assert(len > 0);
445a85fe12eSEd Maste 
446a85fe12eSEd Maste 	dest_cstring(&d->array_str);
447a85fe12eSEd Maste 	if (init_cstring(&d->array_str, len + 3) == false)
448a85fe12eSEd Maste 		return (false);
449a85fe12eSEd Maste 
450a85fe12eSEd Maste 	strncpy(d->array_str.buf + 1, d->p, len);
451a85fe12eSEd Maste 	*d->array_str.buf = '[';
452a85fe12eSEd Maste 	*(d->array_str.buf + len + 1) = ']';
453a85fe12eSEd Maste 
454a85fe12eSEd Maste 	d->array = true;
455a85fe12eSEd Maste 	d->p = end + 1;
456a85fe12eSEd Maste 
457a85fe12eSEd Maste 	return (true);
458a85fe12eSEd Maste }
459a85fe12eSEd Maste 
460a85fe12eSEd Maste static bool
read_class(struct demangle_data * d)461a85fe12eSEd Maste read_class(struct demangle_data *d)
462a85fe12eSEd Maste {
463a85fe12eSEd Maste 	size_t len;
464a85fe12eSEd Maste 	char *str;
465a85fe12eSEd Maste 
466a85fe12eSEd Maste 	if (d == NULL)
467a85fe12eSEd Maste 		return (false);
468a85fe12eSEd Maste 
469a85fe12eSEd Maste 	len = strtol(d->p, &str, 10);
470a85fe12eSEd Maste 	if (len == 0 && (errno == EINVAL || errno == ERANGE))
471a85fe12eSEd Maste 		return (false);
472a85fe12eSEd Maste 
473a85fe12eSEd Maste 	assert(len > 0);
474a85fe12eSEd Maste 	assert(str != NULL);
475a85fe12eSEd Maste 
476a85fe12eSEd Maste 	if (vector_str_push(&d->vec, str, len) == false)
477a85fe12eSEd Maste 		return (false);
478a85fe12eSEd Maste 
479a85fe12eSEd Maste 	d->p = str + len;
480a85fe12eSEd Maste 
481a85fe12eSEd Maste 	d->class_name = true;
482a85fe12eSEd Maste 
483a85fe12eSEd Maste 	return (true);
484a85fe12eSEd Maste }
485a85fe12eSEd Maste 
486a85fe12eSEd Maste static bool
read_func(struct demangle_data * d)487a85fe12eSEd Maste read_func(struct demangle_data *d)
488a85fe12eSEd Maste {
489a85fe12eSEd Maste 	size_t len;
490a85fe12eSEd Maste 	const char *name;
491a85fe12eSEd Maste 	char *delim;
492a85fe12eSEd Maste 
493a85fe12eSEd Maste 	if (d == NULL)
494a85fe12eSEd Maste 		return (false);
495a85fe12eSEd Maste 
496a85fe12eSEd Maste 	assert(d->p != NULL && "d->p (org str) is NULL");
497a85fe12eSEd Maste 	if ((delim = strstr(d->p, "__")) == NULL)
498a85fe12eSEd Maste 		return (false);
499a85fe12eSEd Maste 
500a85fe12eSEd Maste 	len = delim - d->p;
501a85fe12eSEd Maste 	assert(len != 0);
502a85fe12eSEd Maste 
503a85fe12eSEd Maste 	name = d->p;
504a85fe12eSEd Maste 
505a85fe12eSEd Maste 	d->p = delim + 2;
506a85fe12eSEd Maste 
507a85fe12eSEd Maste 	if (*d->p == 'C') {
508a85fe12eSEd Maste 		++d->p;
509a85fe12eSEd Maste 
510a85fe12eSEd Maste 		d->cnst_fn = true;
511a85fe12eSEd Maste 	}
512a85fe12eSEd Maste 
513a85fe12eSEd Maste 	if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
514a85fe12eSEd Maste 		++d->p;
515a85fe12eSEd Maste 
516a85fe12eSEd Maste 		if (read_qual_name(d) == false)
517a85fe12eSEd Maste 			return (false);
518a85fe12eSEd Maste 	} else if (ELFTC_ISDIGIT(*d->p)) {
519a85fe12eSEd Maste 		if (read_class(d) == false)
520a85fe12eSEd Maste 			return (false);
521a85fe12eSEd Maste 
522bee2765cSEd Maste 		if (VEC_PUSH_STR(&d->vec, "::") == false)
523a85fe12eSEd Maste 			return (false);
524a85fe12eSEd Maste 	}
525a85fe12eSEd Maste 
526a85fe12eSEd Maste 	return (vector_str_push(&d->vec, name, len));
527a85fe12eSEd Maste }
528a85fe12eSEd Maste 
529a85fe12eSEd Maste static bool
read_func_name(struct demangle_data * d)530a85fe12eSEd Maste read_func_name(struct demangle_data *d)
531a85fe12eSEd Maste {
532a85fe12eSEd Maste 	size_t len;
533a85fe12eSEd Maste 	bool rtn;
534a85fe12eSEd Maste 	char *op_name;
535a85fe12eSEd Maste 
536a85fe12eSEd Maste 	if (d == NULL)
537a85fe12eSEd Maste 		return (false);
538a85fe12eSEd Maste 
539a85fe12eSEd Maste 	rtn = false;
540a85fe12eSEd Maste 	op_name = NULL;
541a85fe12eSEd Maste 
542a85fe12eSEd Maste 	assert(d->p != NULL && "d->p (org str) is NULL");
543a85fe12eSEd Maste 
544a85fe12eSEd Maste 	if (*d->p == '_' && *(d->p + 1) == '_') {
545a85fe12eSEd Maste 		d->p += 2;
546a85fe12eSEd Maste 
547a85fe12eSEd Maste 		/* CTOR */
548a85fe12eSEd Maste 		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
549a85fe12eSEd Maste 			++d->p;
550a85fe12eSEd Maste 			d->type = ENCODE_OP_CT;
551a85fe12eSEd Maste 
552a85fe12eSEd Maste 			if (read_qual_name(d) == false)
553a85fe12eSEd Maste 				return (false);
554a85fe12eSEd Maste 
555a85fe12eSEd Maste 			return (vector_str_pop(&d->vec));
556a85fe12eSEd Maste 		} else if (ELFTC_ISDIGIT(*d->p)) {
557a85fe12eSEd Maste 			d->type = ENCODE_OP_CT;
558a85fe12eSEd Maste 
559a85fe12eSEd Maste 			return (read_class(d));
560a85fe12eSEd Maste 		}
561a85fe12eSEd Maste 
562a85fe12eSEd Maste 		d->type = ENCODE_OP;
563a85fe12eSEd Maste 		if (read_op(d) == false) {
564a85fe12eSEd Maste 			/* not good condition, start function name with '__' */
565a85fe12eSEd Maste 			d->type = ENCODE_FUNC;
566a85fe12eSEd Maste 
567bee2765cSEd Maste 			if (VEC_PUSH_STR(&d->vec, "__") == false)
568a85fe12eSEd Maste 				return (false);
569a85fe12eSEd Maste 
570a85fe12eSEd Maste 			return (read_func(d));
571a85fe12eSEd Maste 		}
572a85fe12eSEd Maste 
573a85fe12eSEd Maste 		if (d->type == ENCODE_OP_USER ||
574a85fe12eSEd Maste 		    d->type == ENCODE_OP_TF ||
575a85fe12eSEd Maste 		    d->type == ENCODE_OP_TI)
576a85fe12eSEd Maste 			return (true);
577a85fe12eSEd Maste 
578a85fe12eSEd Maste 		/* skip "__" */
579a85fe12eSEd Maste 		d->p += 2;
580a85fe12eSEd Maste 
581a85fe12eSEd Maste 		if (*d->p == 'C') {
582a85fe12eSEd Maste 			++d->p;
583a85fe12eSEd Maste 
584a85fe12eSEd Maste 			d->cnst_fn = true;
585a85fe12eSEd Maste 		}
586a85fe12eSEd Maste 
587a85fe12eSEd Maste 		/* assume delimiter is removed */
588a85fe12eSEd Maste 		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
589a85fe12eSEd Maste 			++d->p;
590a85fe12eSEd Maste 
591a85fe12eSEd Maste 			assert(d->vec.size > 0);
592a85fe12eSEd Maste 
593a85fe12eSEd Maste 			len = strlen(d->vec.container[d->vec.size - 1]);
594a85fe12eSEd Maste 			if ((op_name = malloc(sizeof(char) * (len + 1)))
595a85fe12eSEd Maste 			    == NULL)
596a85fe12eSEd Maste 				return (false);
597a85fe12eSEd Maste 
598a85fe12eSEd Maste 			snprintf(op_name, len + 1, "%s",
599a85fe12eSEd Maste 			    d->vec.container[d->vec.size - 1]);
600a85fe12eSEd Maste 			vector_str_pop(&d->vec);
601a85fe12eSEd Maste 
602a85fe12eSEd Maste 			if (read_qual_name(d) == false)
603a85fe12eSEd Maste 				goto clean;
604a85fe12eSEd Maste 
605bee2765cSEd Maste 			if (VEC_PUSH_STR(&d->vec, "::") == false)
606a85fe12eSEd Maste 				goto clean;
607a85fe12eSEd Maste 
608a85fe12eSEd Maste 			if (vector_str_push(&d->vec, op_name, len) == false)
609a85fe12eSEd Maste 				goto clean;
610a85fe12eSEd Maste 
611a85fe12eSEd Maste 			rtn = true;
612a85fe12eSEd Maste 		} else if (ELFTC_ISDIGIT(*d->p)) {
613a85fe12eSEd Maste 			assert(d->vec.size > 0);
614a85fe12eSEd Maste 
615a85fe12eSEd Maste 			len = strlen(d->vec.container[d->vec.size - 1]);
616a85fe12eSEd Maste 			if ((op_name = malloc(sizeof(char) * (len + 1)))
617a85fe12eSEd Maste 			    == NULL)
618a85fe12eSEd Maste 				return (false);
619a85fe12eSEd Maste 
620a85fe12eSEd Maste 			snprintf(op_name, len + 1, "%s",
621a85fe12eSEd Maste 			    d->vec.container[d->vec.size - 1]);
622a85fe12eSEd Maste 			vector_str_pop(&d->vec);
623a85fe12eSEd Maste 
624a85fe12eSEd Maste 			if (read_class(d) == false)
625a85fe12eSEd Maste 				goto clean;
626a85fe12eSEd Maste 
627bee2765cSEd Maste 			if (VEC_PUSH_STR(&d->vec, "::") == false)
628a85fe12eSEd Maste 				goto clean;
629a85fe12eSEd Maste 
630a85fe12eSEd Maste 			if (vector_str_push(&d->vec, op_name, len) == false)
631a85fe12eSEd Maste 				goto clean;
632a85fe12eSEd Maste 
633a85fe12eSEd Maste 			rtn = true;
634a85fe12eSEd Maste 		}
635a85fe12eSEd Maste 	} else if (memcmp(d->p, "_$_", 3) == 0) {
636a85fe12eSEd Maste 		/* DTOR */
637a85fe12eSEd Maste 		d->p += 3;
638a85fe12eSEd Maste 		d->type = ENCODE_OP_DT;
639a85fe12eSEd Maste 
640a85fe12eSEd Maste 		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
641a85fe12eSEd Maste 			++d->p;
642a85fe12eSEd Maste 
643a85fe12eSEd Maste 			if (read_qual_name(d) == false)
644a85fe12eSEd Maste 				return (false);
645a85fe12eSEd Maste 
646a85fe12eSEd Maste 			return (vector_str_pop(&d->vec));
647a85fe12eSEd Maste 		} else if (ELFTC_ISDIGIT(*d->p))
648a85fe12eSEd Maste 			return (read_class(d));
649a85fe12eSEd Maste 
650a85fe12eSEd Maste 		return (false);
651a85fe12eSEd Maste 	} else if (memcmp(d->p, "_vt$", 4) == 0) {
652a85fe12eSEd Maste 		/* vtable */
653a85fe12eSEd Maste 		d->p += 4;
654a85fe12eSEd Maste 		d->type = ENCODE_OP_VT;
655a85fe12eSEd Maste 
656a85fe12eSEd Maste 		if (*d->p == 'Q' && ELFTC_ISDIGIT(*(d->p + 1))) {
657a85fe12eSEd Maste 			++d->p;
658a85fe12eSEd Maste 
659a85fe12eSEd Maste 			if (read_qual_name(d) == false)
660a85fe12eSEd Maste 				return (false);
661a85fe12eSEd Maste 
662a85fe12eSEd Maste 			if (vector_str_pop(&d->vec) == false)
663a85fe12eSEd Maste 				return (false);
664a85fe12eSEd Maste 		} else if (ELFTC_ISDIGIT(*d->p)) {
665a85fe12eSEd Maste 			if (read_class(d) == false)
666a85fe12eSEd Maste 				return (false);
667a85fe12eSEd Maste 		}
668a85fe12eSEd Maste 
669bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, " virtual table"));
670a85fe12eSEd Maste 	} else
671a85fe12eSEd Maste 		return (read_func(d));
672a85fe12eSEd Maste clean:
673a85fe12eSEd Maste 	free(op_name);
674a85fe12eSEd Maste 
675a85fe12eSEd Maste 	return (rtn);
676a85fe12eSEd Maste }
677a85fe12eSEd Maste 
678a85fe12eSEd Maste /* Read function ptr type */
679a85fe12eSEd Maste static bool
read_func_ptr(struct demangle_data * d)680a85fe12eSEd Maste read_func_ptr(struct demangle_data *d)
681a85fe12eSEd Maste {
682a85fe12eSEd Maste 	struct demangle_data fptr;
683a85fe12eSEd Maste 	size_t arg_len, rtn_len;
684a85fe12eSEd Maste 	char *arg_type, *rtn_type;
685a85fe12eSEd Maste 	int lim;
686a85fe12eSEd Maste 
687a85fe12eSEd Maste 	if (d == NULL)
688a85fe12eSEd Maste 		return (false);
689a85fe12eSEd Maste 
690a85fe12eSEd Maste 	if (init_demangle_data(&fptr) == false)
691a85fe12eSEd Maste 		return (false);
692a85fe12eSEd Maste 
693a85fe12eSEd Maste 	fptr.p = d->p + 1;
694a85fe12eSEd Maste 	lim = 0;
695a85fe12eSEd Maste 	arg_type = NULL;
696a85fe12eSEd Maste 	rtn_type = NULL;
697a85fe12eSEd Maste 
698a85fe12eSEd Maste 	for (;;) {
699a85fe12eSEd Maste 		if (read_type(&fptr) == false) {
700a85fe12eSEd Maste 			dest_demangle_data(&fptr);
701a85fe12eSEd Maste 
702a85fe12eSEd Maste 			return (false);
703a85fe12eSEd Maste 		}
704a85fe12eSEd Maste 
705a85fe12eSEd Maste 		if (fptr.ptr == true) {
706bee2765cSEd Maste 			if (VEC_PUSH_STR(&fptr.vec, "*") == false) {
707a85fe12eSEd Maste 				dest_demangle_data(&fptr);
708a85fe12eSEd Maste 
709a85fe12eSEd Maste 				return (false);
710a85fe12eSEd Maste 			}
711a85fe12eSEd Maste 
712a85fe12eSEd Maste 			fptr.ptr = false;
713a85fe12eSEd Maste 		}
714a85fe12eSEd Maste 
715a85fe12eSEd Maste 		if (fptr.ref == true) {
716bee2765cSEd Maste 			if (VEC_PUSH_STR(&fptr.vec, "&") == false) {
717a85fe12eSEd Maste 				dest_demangle_data(&fptr);
718a85fe12eSEd Maste 
719a85fe12eSEd Maste 				return (false);
720a85fe12eSEd Maste 			}
721a85fe12eSEd Maste 
722a85fe12eSEd Maste 			fptr.ref = false;
723a85fe12eSEd Maste 		}
724a85fe12eSEd Maste 
725a85fe12eSEd Maste 		if (fptr.cnst == true) {
726bee2765cSEd Maste 			if (VEC_PUSH_STR(&fptr.vec, " const") == false) {
727a85fe12eSEd Maste 				dest_demangle_data(&fptr);
728a85fe12eSEd Maste 
729a85fe12eSEd Maste 				return (false);
730a85fe12eSEd Maste 			}
731a85fe12eSEd Maste 
732a85fe12eSEd Maste 			fptr.cnst = false;
733a85fe12eSEd Maste 		}
734a85fe12eSEd Maste 
735a85fe12eSEd Maste 		if (*fptr.p == '_')
736a85fe12eSEd Maste 			break;
737a85fe12eSEd Maste 
738bee2765cSEd Maste 		if (VEC_PUSH_STR(&fptr.vec, ", ") == false) {
739a85fe12eSEd Maste 			dest_demangle_data(&fptr);
740a85fe12eSEd Maste 
741a85fe12eSEd Maste 			return (false);
742a85fe12eSEd Maste 		}
743a85fe12eSEd Maste 
744a85fe12eSEd Maste 		if (++lim > CPP_DEMANGLE_GNU2_TRY) {
745a85fe12eSEd Maste 
746a85fe12eSEd Maste 			dest_demangle_data(&fptr);
747a85fe12eSEd Maste 
748a85fe12eSEd Maste 			return (false);
749a85fe12eSEd Maste 		}
750a85fe12eSEd Maste 	}
751a85fe12eSEd Maste 
752a85fe12eSEd Maste 	arg_type = vector_str_get_flat(&fptr.vec, &arg_len);
753a85fe12eSEd Maste 	/* skip '_' */
754a85fe12eSEd Maste 	d->p = fptr.p + 1;
755a85fe12eSEd Maste 
756a85fe12eSEd Maste 	dest_demangle_data(&fptr);
757a85fe12eSEd Maste 
758a85fe12eSEd Maste 	if (init_demangle_data(&fptr) == false) {
759a85fe12eSEd Maste 		free(arg_type);
760a85fe12eSEd Maste 
761a85fe12eSEd Maste 		return (false);
762a85fe12eSEd Maste 	}
763a85fe12eSEd Maste 
764a85fe12eSEd Maste 	fptr.p = d->p;
765a85fe12eSEd Maste 	lim = 0;
766a85fe12eSEd Maste 
767a85fe12eSEd Maste 	if (read_type(&fptr) == false) {
768a85fe12eSEd Maste 		free(arg_type);
769a85fe12eSEd Maste 		dest_demangle_data(&fptr);
770a85fe12eSEd Maste 
771a85fe12eSEd Maste 		return (false);
772a85fe12eSEd Maste 	}
773a85fe12eSEd Maste 
774a85fe12eSEd Maste 	rtn_type = vector_str_get_flat(&fptr.vec, &rtn_len);
775a85fe12eSEd Maste 	d->p = fptr.p;
776a85fe12eSEd Maste 
777a85fe12eSEd Maste 
778a85fe12eSEd Maste 	dest_demangle_data(&fptr);
779a85fe12eSEd Maste 
780a85fe12eSEd Maste 	if (vector_str_push(&d->vec, rtn_type, rtn_len) == false) {
781a85fe12eSEd Maste 		free(rtn_type);
782a85fe12eSEd Maste 		free(arg_type);
783a85fe12eSEd Maste 
784a85fe12eSEd Maste 		return (false);
785a85fe12eSEd Maste 	}
786a85fe12eSEd Maste 
787a85fe12eSEd Maste 	free(rtn_type);
788a85fe12eSEd Maste 
789bee2765cSEd Maste 	if (VEC_PUSH_STR(&d->vec, " (*)(") == false) {
790a85fe12eSEd Maste 		free(arg_type);
791a85fe12eSEd Maste 
792a85fe12eSEd Maste 		return (false);
793a85fe12eSEd Maste 	}
794a85fe12eSEd Maste 
795a85fe12eSEd Maste 	if (vector_str_push(&d->vec, arg_type, arg_len) == false) {
796a85fe12eSEd Maste 		free(arg_type);
797a85fe12eSEd Maste 
798a85fe12eSEd Maste 		return (false);
799a85fe12eSEd Maste 	}
800a85fe12eSEd Maste 
801a85fe12eSEd Maste 	free(arg_type);
802a85fe12eSEd Maste 
803bee2765cSEd Maste 	return (VEC_PUSH_STR(&d->vec, ")"));
804a85fe12eSEd Maste }
805a85fe12eSEd Maste 
806a85fe12eSEd Maste static bool
read_memptr(struct demangle_data * d)807a85fe12eSEd Maste read_memptr(struct demangle_data *d)
808a85fe12eSEd Maste {
809a85fe12eSEd Maste 	struct demangle_data mptr;
810a85fe12eSEd Maste 	size_t len;
811a85fe12eSEd Maste 	bool rtn;
812a85fe12eSEd Maste 	char *mptr_str;
813a85fe12eSEd Maste 
814a85fe12eSEd Maste 	if (d == NULL || d->p == NULL)
815a85fe12eSEd Maste 		return (false);
816a85fe12eSEd Maste 
817a85fe12eSEd Maste 	if (init_demangle_data(&mptr) == false)
818a85fe12eSEd Maste 		return (false);
819a85fe12eSEd Maste 
820a85fe12eSEd Maste 	rtn = false;
821a85fe12eSEd Maste 	mptr_str = NULL;
822a85fe12eSEd Maste 
823a85fe12eSEd Maste 	mptr.p = d->p;
824a85fe12eSEd Maste 	if (*mptr.p == 'Q') {
825a85fe12eSEd Maste 		++mptr.p;
826a85fe12eSEd Maste 
827a85fe12eSEd Maste 		if (read_qual_name(&mptr) == false)
828a85fe12eSEd Maste 			goto clean;
829a85fe12eSEd Maste 	} else if (read_class(&mptr) == false)
830a85fe12eSEd Maste 			goto clean;
831a85fe12eSEd Maste 
832a85fe12eSEd Maste 	d->p = mptr.p;
833a85fe12eSEd Maste 
834a85fe12eSEd Maste 	if ((mptr_str = vector_str_get_flat(&mptr.vec, &len)) == NULL)
835a85fe12eSEd Maste 		goto clean;
836a85fe12eSEd Maste 
837a85fe12eSEd Maste 	if (vector_str_push(&d->vec, mptr_str, len) == false)
838a85fe12eSEd Maste 		goto clean;
839a85fe12eSEd Maste 
840bee2765cSEd Maste 	if (VEC_PUSH_STR(&d->vec, "::*") == false)
841a85fe12eSEd Maste 		goto clean;
842a85fe12eSEd Maste 
843a85fe12eSEd Maste 	rtn = true;
844a85fe12eSEd Maste clean:
845a85fe12eSEd Maste 	free(mptr_str);
846a85fe12eSEd Maste 	dest_demangle_data(&mptr);
847a85fe12eSEd Maste 
848a85fe12eSEd Maste 	return (rtn);
849a85fe12eSEd Maste }
850a85fe12eSEd Maste 
851a85fe12eSEd Maste static bool
read_op(struct demangle_data * d)852a85fe12eSEd Maste read_op(struct demangle_data *d)
853a85fe12eSEd Maste {
854a85fe12eSEd Maste 
855a85fe12eSEd Maste 	if (d == NULL)
856a85fe12eSEd Maste 		return (false);
857a85fe12eSEd Maste 
858a85fe12eSEd Maste 	assert(d->p != NULL && "d->p (org str) is NULL");
859a85fe12eSEd Maste 
860a85fe12eSEd Maste 	switch (SIMPLE_HASH(*(d->p), *(d->p+1))) {
861a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'l') :
862a85fe12eSEd Maste 		d->p += 2;
863bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator*"));
864a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'v') :
865a85fe12eSEd Maste 		d->p += 2;
866bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator/"));
867a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'd') :
868a85fe12eSEd Maste 		d->p += 2;
869bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator%"));
870a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'l') :
871a85fe12eSEd Maste 		d->p += 2;
872bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator+"));
873a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'i') :
874a85fe12eSEd Maste 		d->p += 2;
875bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator-"));
876a85fe12eSEd Maste 	case SIMPLE_HASH('l', 's') :
877a85fe12eSEd Maste 		d->p += 2;
878bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator<<"));
879a85fe12eSEd Maste 	case SIMPLE_HASH('r', 's') :
880a85fe12eSEd Maste 		d->p += 2;
881bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator>>"));
882a85fe12eSEd Maste 	case SIMPLE_HASH('e', 'q') :
883a85fe12eSEd Maste 		d->p += 2;
884bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator=="));
885a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'e') :
886a85fe12eSEd Maste 		d->p += 2;
887bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator!="));
888a85fe12eSEd Maste 	case SIMPLE_HASH('l', 't') :
889a85fe12eSEd Maste 		d->p += 2;
890bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator<"));
891a85fe12eSEd Maste 	case SIMPLE_HASH('g', 't') :
892a85fe12eSEd Maste 		d->p += 2;
893bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator>"));
894a85fe12eSEd Maste 	case SIMPLE_HASH('l', 'e') :
895a85fe12eSEd Maste 		d->p += 2;
896bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator<="));
897a85fe12eSEd Maste 	case SIMPLE_HASH('g', 'e') :
898a85fe12eSEd Maste 		d->p += 2;
899bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator>="));
900a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'd') :
901a85fe12eSEd Maste 		d->p += 2;
902a85fe12eSEd Maste 		if (*d->p == 'v') {
903a85fe12eSEd Maste 			++d->p;
904bee2765cSEd Maste 			return (VEC_PUSH_STR(&d->vec, "operator/="));
905a85fe12eSEd Maste 		} else
906bee2765cSEd Maste 			return (VEC_PUSH_STR(&d->vec, "operator&"));
907a85fe12eSEd Maste 	case SIMPLE_HASH('o', 'r') :
908a85fe12eSEd Maste 		d->p += 2;
909bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator|"));
910a85fe12eSEd Maste 	case SIMPLE_HASH('e', 'r') :
911a85fe12eSEd Maste 		d->p += 2;
912bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator^"));
913a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'a') :
914a85fe12eSEd Maste 		d->p += 2;
915a85fe12eSEd Maste 		if (*d->p == 'd') {
916a85fe12eSEd Maste 			++d->p;
917bee2765cSEd Maste 			return (VEC_PUSH_STR(&d->vec, "operator&="));
918a85fe12eSEd Maste 		} else
919bee2765cSEd Maste 			return (VEC_PUSH_STR(&d->vec, "operator&&"));
920a85fe12eSEd Maste 	case SIMPLE_HASH('o', 'o') :
921a85fe12eSEd Maste 		d->p += 2;
922bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator||"));
923a85fe12eSEd Maste 	case SIMPLE_HASH('n', 't') :
924a85fe12eSEd Maste 		d->p += 2;
925bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator!"));
926a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'o') :
927a85fe12eSEd Maste 		d->p += 2;
928bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator~"));
929a85fe12eSEd Maste 	case SIMPLE_HASH('p', 'p') :
930a85fe12eSEd Maste 		d->p += 2;
931bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator++"));
932a85fe12eSEd Maste 	case SIMPLE_HASH('m', 'm') :
933a85fe12eSEd Maste 		d->p += 2;
934bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator--"));
935a85fe12eSEd Maste 	case SIMPLE_HASH('a', 's') :
936a85fe12eSEd Maste 		d->p += 2;
937bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator="));
938a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'f') :
939a85fe12eSEd Maste 		d->p += 2;
940bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator->"));
941a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'p') :
942a85fe12eSEd Maste 		/* apl */
943a85fe12eSEd Maste 		if (*(d->p + 2) != 'l')
944a85fe12eSEd Maste 			return (false);
945a85fe12eSEd Maste 
946a85fe12eSEd Maste 		d->p += 3;
947bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator+="));
948a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'm') :
949a85fe12eSEd Maste 		d->p += 2;
950a85fe12eSEd Maste 		if (*d->p == 'i') {
951a85fe12eSEd Maste 			++d->p;
952bee2765cSEd Maste 			return (VEC_PUSH_STR(&d->vec, "operator-="));
953a85fe12eSEd Maste 		} else if (*d->p == 'u') {
954a85fe12eSEd Maste 			++d->p;
955bee2765cSEd Maste 			return (VEC_PUSH_STR(&d->vec, "operator*="));
956a85fe12eSEd Maste 		} else if (*d->p == 'd') {
957a85fe12eSEd Maste 			++d->p;
958bee2765cSEd Maste 			return (VEC_PUSH_STR(&d->vec, "operator%="));
959a85fe12eSEd Maste 		}
960a85fe12eSEd Maste 
961a85fe12eSEd Maste 		return (false);
962a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'l') :
963a85fe12eSEd Maste 		/* als */
964a85fe12eSEd Maste 		if (*(d->p + 2) != 's')
965a85fe12eSEd Maste 			return (false);
966a85fe12eSEd Maste 
967a85fe12eSEd Maste 		d->p += 3;
968bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator<<="));
969a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'r') :
970a85fe12eSEd Maste 		/* ars */
971a85fe12eSEd Maste 		if (*(d->p + 2) != 's')
972a85fe12eSEd Maste 			return (false);
973a85fe12eSEd Maste 
974a85fe12eSEd Maste 		d->p += 3;
975bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator>>="));
976a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'o') :
977a85fe12eSEd Maste 		/* aor */
978a85fe12eSEd Maste 		if (*(d->p + 2) != 'r')
979a85fe12eSEd Maste 			return (false);
980a85fe12eSEd Maste 
981a85fe12eSEd Maste 		d->p += 3;
982bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator|="));
983a85fe12eSEd Maste 	case SIMPLE_HASH('a', 'e') :
984a85fe12eSEd Maste 		/* aer */
985a85fe12eSEd Maste 		if (*(d->p + 2) != 'r')
986a85fe12eSEd Maste 			return (false);
987a85fe12eSEd Maste 
988a85fe12eSEd Maste 		d->p += 3;
989bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator^="));
990a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'm') :
991a85fe12eSEd Maste 		d->p += 2;
992bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator,"));
993a85fe12eSEd Maste 	case SIMPLE_HASH('r', 'm') :
994a85fe12eSEd Maste 		d->p += 2;
995bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator->*"));
996a85fe12eSEd Maste 	case SIMPLE_HASH('c', 'l') :
997a85fe12eSEd Maste 		d->p += 2;
998bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "()"));
999a85fe12eSEd Maste 	case SIMPLE_HASH('v', 'c') :
1000a85fe12eSEd Maste 		d->p += 2;
1001bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "[]"));
1002a85fe12eSEd Maste 	case SIMPLE_HASH('n', 'w') :
1003a85fe12eSEd Maste 		d->p += 2;
1004bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator new()"));
1005a85fe12eSEd Maste 	case SIMPLE_HASH('d', 'l') :
1006a85fe12eSEd Maste 		d->p += 2;
1007bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "operator delete()"));
1008a85fe12eSEd Maste 	case SIMPLE_HASH('o', 'p') :
1009a85fe12eSEd Maste 		/* __op<TO_TYPE>__<FROM_TYPE> */
1010a85fe12eSEd Maste 		d->p += 2;
1011a85fe12eSEd Maste 
1012a85fe12eSEd Maste 		d->type = ENCODE_OP_USER;
1013a85fe12eSEd Maste 
1014a85fe12eSEd Maste 		return (read_op_user(d));
1015a85fe12eSEd Maste 	case SIMPLE_HASH('t', 'f') :
1016a85fe12eSEd Maste 		d->p += 2;
1017a85fe12eSEd Maste 		d->type = ENCODE_OP_TF;
1018a85fe12eSEd Maste 
1019a85fe12eSEd Maste 		if (read_type(d) == false)
1020a85fe12eSEd Maste 			return (false);
1021a85fe12eSEd Maste 
1022bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, " type_info function"));
1023a85fe12eSEd Maste 	case SIMPLE_HASH('t', 'i') :
1024a85fe12eSEd Maste 		d->p += 2;
1025a85fe12eSEd Maste 		d->type = ENCODE_OP_TI;
1026a85fe12eSEd Maste 
1027a85fe12eSEd Maste 		if (read_type(d) == false)
1028a85fe12eSEd Maste 			return (false);
1029a85fe12eSEd Maste 
1030bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, " type_info node"));
1031a85fe12eSEd Maste 	default :
1032a85fe12eSEd Maste 		return (false);
1033a85fe12eSEd Maste 	};
1034a85fe12eSEd Maste }
1035a85fe12eSEd Maste 
1036a85fe12eSEd Maste static bool
read_op_user(struct demangle_data * d)1037a85fe12eSEd Maste read_op_user(struct demangle_data *d)
1038a85fe12eSEd Maste {
1039a85fe12eSEd Maste 	struct demangle_data from, to;
1040a85fe12eSEd Maste 	size_t from_len, to_len;
1041a85fe12eSEd Maste 	bool rtn;
1042a85fe12eSEd Maste 	char *from_str, *to_str;
1043a85fe12eSEd Maste 
1044a85fe12eSEd Maste 	if (d == NULL)
1045a85fe12eSEd Maste 		return (false);
1046a85fe12eSEd Maste 
1047a85fe12eSEd Maste 	if (init_demangle_data(&from) == false)
1048a85fe12eSEd Maste 		return (false);
1049a85fe12eSEd Maste 
1050a85fe12eSEd Maste 	rtn = false;
1051a85fe12eSEd Maste 	from_str = NULL;
1052a85fe12eSEd Maste 	to_str = NULL;
1053a85fe12eSEd Maste 	if (init_demangle_data(&to) == false)
1054a85fe12eSEd Maste 		goto clean;
1055a85fe12eSEd Maste 
1056a85fe12eSEd Maste 	to.p = d->p;
1057a85fe12eSEd Maste 	if (*to.p == 'Q') {
1058a85fe12eSEd Maste 		++to.p;
1059a85fe12eSEd Maste 
1060a85fe12eSEd Maste 		if (read_qual_name(&to) == false)
1061a85fe12eSEd Maste 			goto clean;
1062a85fe12eSEd Maste 
1063a85fe12eSEd Maste 		/* pop last '::' */
1064a85fe12eSEd Maste 		if (vector_str_pop(&to.vec) == false)
1065a85fe12eSEd Maste 			goto clean;
1066a85fe12eSEd Maste 	} else {
1067a85fe12eSEd Maste 		if (read_class(&to) == false)
1068a85fe12eSEd Maste 			goto clean;
1069a85fe12eSEd Maste 
1070a85fe12eSEd Maste 		/* skip '__' */
1071a85fe12eSEd Maste 		to.p += 2;
1072a85fe12eSEd Maste 	}
1073a85fe12eSEd Maste 
1074a85fe12eSEd Maste 	if ((to_str = vector_str_get_flat(&to.vec, &to_len)) == NULL)
1075a85fe12eSEd Maste 		goto clean;
1076a85fe12eSEd Maste 
1077a85fe12eSEd Maste 	from.p = to.p;
1078a85fe12eSEd Maste 	if (*from.p == 'Q') {
1079a85fe12eSEd Maste 		++from.p;
1080a85fe12eSEd Maste 
1081a85fe12eSEd Maste 		if (read_qual_name(&from) == false)
1082a85fe12eSEd Maste 			goto clean;
1083a85fe12eSEd Maste 
1084a85fe12eSEd Maste 		/* pop last '::' */
1085a85fe12eSEd Maste 		if (vector_str_pop(&from.vec) == false)
1086a85fe12eSEd Maste 			goto clean;
1087a85fe12eSEd Maste 	} else if (read_class(&from) == false)
1088a85fe12eSEd Maste 			goto clean;
1089a85fe12eSEd Maste 
1090a85fe12eSEd Maste 	if ((from_str = vector_str_get_flat(&from.vec, &from_len)) == NULL)
1091a85fe12eSEd Maste 		goto clean;
1092a85fe12eSEd Maste 
1093a85fe12eSEd Maste 	if (vector_str_push(&d->vec, from_str, from_len) == false)
1094a85fe12eSEd Maste 		goto clean;
1095a85fe12eSEd Maste 
1096bee2765cSEd Maste 	if (VEC_PUSH_STR(&d->vec, "::operator ") == false)
1097a85fe12eSEd Maste 		goto clean;
1098a85fe12eSEd Maste 
1099a85fe12eSEd Maste 	if (vector_str_push(&d->vec, to_str, to_len) == false)
1100a85fe12eSEd Maste 		goto clean;
1101a85fe12eSEd Maste 
1102bee2765cSEd Maste 	rtn = VEC_PUSH_STR(&d->vec, "()");
1103a85fe12eSEd Maste clean:
1104a85fe12eSEd Maste 	free(to_str);
1105a85fe12eSEd Maste 	free(from_str);
1106a85fe12eSEd Maste 	dest_demangle_data(&to);
1107a85fe12eSEd Maste 	dest_demangle_data(&from);
1108a85fe12eSEd Maste 
1109a85fe12eSEd Maste 	return (rtn);
1110a85fe12eSEd Maste }
1111a85fe12eSEd Maste 
1112a85fe12eSEd Maste /* single digit + class names */
1113a85fe12eSEd Maste static bool
read_qual_name(struct demangle_data * d)1114a85fe12eSEd Maste read_qual_name(struct demangle_data *d)
1115a85fe12eSEd Maste {
1116a85fe12eSEd Maste 	int i;
1117a85fe12eSEd Maste 	char num;
1118a85fe12eSEd Maste 
1119a85fe12eSEd Maste 	if (d == NULL)
1120a85fe12eSEd Maste 		return (false);
1121a85fe12eSEd Maste 
1122a85fe12eSEd Maste 	assert(d->p != NULL && "d->p (org str) is NULL");
1123a85fe12eSEd Maste 	assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
1124a85fe12eSEd Maste 
1125a85fe12eSEd Maste 	num = *d->p - 48;
1126a85fe12eSEd Maste 
1127a85fe12eSEd Maste 	assert(num > 0);
1128a85fe12eSEd Maste 
1129a85fe12eSEd Maste 	++d->p;
1130a85fe12eSEd Maste 	for (i = 0; i < num ; ++i) {
1131a85fe12eSEd Maste 		if (read_class(d) == false)
1132a85fe12eSEd Maste 			return (false);
1133a85fe12eSEd Maste 
1134bee2765cSEd Maste 		if (VEC_PUSH_STR(&d->vec, "::") == false)
1135a85fe12eSEd Maste 			return (false);
1136a85fe12eSEd Maste 	}
1137a85fe12eSEd Maste 
1138a85fe12eSEd Maste 	if (*d->p != '\0')
1139a85fe12eSEd Maste 		d->p = d->p + 2;
1140a85fe12eSEd Maste 
1141a85fe12eSEd Maste 	return (true);
1142a85fe12eSEd Maste }
1143a85fe12eSEd Maste 
1144a85fe12eSEd Maste /* Return -1 at fail, 0 at success, and 1 at end */
1145a85fe12eSEd Maste static int
read_subst(struct demangle_data * d)1146a85fe12eSEd Maste read_subst(struct demangle_data *d)
1147a85fe12eSEd Maste {
1148a85fe12eSEd Maste 	size_t idx;
1149a85fe12eSEd Maste 	char *str;
1150a85fe12eSEd Maste 
1151a85fe12eSEd Maste 	if (d == NULL)
1152a85fe12eSEd Maste 		return (-1);
1153a85fe12eSEd Maste 
1154a85fe12eSEd Maste 	idx = strtol(d->p + 1, &str, 10);
1155a85fe12eSEd Maste 	if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1156a85fe12eSEd Maste 		return (-1);
1157a85fe12eSEd Maste 
1158a85fe12eSEd Maste 	assert(idx > 0);
1159a85fe12eSEd Maste 	assert(str != NULL);
1160a85fe12eSEd Maste 
1161a85fe12eSEd Maste 	d->p = str;
1162a85fe12eSEd Maste 
1163bee2765cSEd Maste 	if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1164a85fe12eSEd Maste 		return (-1);
1165a85fe12eSEd Maste 
1166bee2765cSEd Maste 	if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1167a85fe12eSEd Maste 		return (-1);
1168a85fe12eSEd Maste 
1169a85fe12eSEd Maste 	if (*d->p == '\0')
1170a85fe12eSEd Maste 		return (1);
1171a85fe12eSEd Maste 
1172a85fe12eSEd Maste 	return (0);
1173a85fe12eSEd Maste }
1174a85fe12eSEd Maste 
1175a85fe12eSEd Maste static int
read_subst_iter(struct demangle_data * d)1176a85fe12eSEd Maste read_subst_iter(struct demangle_data *d)
1177a85fe12eSEd Maste {
1178a85fe12eSEd Maste 	int i;
1179a85fe12eSEd Maste 	size_t idx;
1180a85fe12eSEd Maste 	char repeat;
1181a85fe12eSEd Maste 	char *str;
1182a85fe12eSEd Maste 
1183a85fe12eSEd Maste 	if (d == NULL)
1184a85fe12eSEd Maste 		return (-1);
1185a85fe12eSEd Maste 
1186a85fe12eSEd Maste 	++d->p;
1187a85fe12eSEd Maste 	assert(*d->p > 48 && *d->p < 58 && "*d->p not in ASCII numeric range");
1188a85fe12eSEd Maste 
1189a85fe12eSEd Maste 	repeat = *d->p - 48;
1190a85fe12eSEd Maste 
1191a85fe12eSEd Maste 	assert(repeat > 1);
1192a85fe12eSEd Maste 
1193a85fe12eSEd Maste 	++d->p;
1194a85fe12eSEd Maste 
1195a85fe12eSEd Maste 	idx = strtol(d->p, &str, 10);
1196a85fe12eSEd Maste 	if (idx == 0 && (errno == EINVAL || errno == ERANGE))
1197a85fe12eSEd Maste 		return (-1);
1198a85fe12eSEd Maste 
1199a85fe12eSEd Maste 	assert(idx > 0);
1200a85fe12eSEd Maste 	assert(str != NULL);
1201a85fe12eSEd Maste 
1202a85fe12eSEd Maste 	d->p = str;
1203a85fe12eSEd Maste 
1204a85fe12eSEd Maste 	for (i = 0; i < repeat ; ++i) {
1205bee2765cSEd Maste 		if (VEC_PUSH_STR(&d->vec, d->arg.container[idx - 1]) == false)
1206a85fe12eSEd Maste 			return (-1);
1207a85fe12eSEd Maste 
1208bee2765cSEd Maste 		if (VEC_PUSH_STR(&d->arg, d->arg.container[idx - 1]) == false)
1209a85fe12eSEd Maste 			return (-1);
1210a85fe12eSEd Maste 
1211a85fe12eSEd Maste 		if (i != repeat - 1 &&
1212bee2765cSEd Maste 		    VEC_PUSH_STR(&d->vec, ", ") == false)
1213a85fe12eSEd Maste 			return (-1);
1214a85fe12eSEd Maste 	}
1215a85fe12eSEd Maste 
1216a85fe12eSEd Maste 	if (*d->p == '\0')
1217a85fe12eSEd Maste 		return (1);
1218a85fe12eSEd Maste 
1219a85fe12eSEd Maste 	return (0);
1220a85fe12eSEd Maste }
1221a85fe12eSEd Maste 
1222a85fe12eSEd Maste static bool
read_type(struct demangle_data * d)1223a85fe12eSEd Maste read_type(struct demangle_data *d)
1224a85fe12eSEd Maste {
1225a85fe12eSEd Maste 
1226a85fe12eSEd Maste 	if (d == NULL)
1227a85fe12eSEd Maste 		return (false);
1228a85fe12eSEd Maste 
1229a85fe12eSEd Maste 	assert(d->p != NULL && "d->p (org str) is NULL");
1230a85fe12eSEd Maste 
1231a85fe12eSEd Maste 	while (*d->p == 'U' || *d->p == 'C' || *d->p == 'V' || *d->p == 'S' ||
1232a85fe12eSEd Maste 	       *d->p == 'P' || *d->p == 'R' || *d->p == 'A' || *d->p == 'F' ||
1233a85fe12eSEd Maste 	       *d->p == 'M') {
1234a85fe12eSEd Maste 		switch (*d->p) {
1235a85fe12eSEd Maste 		case 'U' :
1236a85fe12eSEd Maste 			++d->p;
1237a85fe12eSEd Maste 
1238bee2765cSEd Maste 			if (VEC_PUSH_STR(&d->vec, "unsigned ") == false)
1239a85fe12eSEd Maste 				return (false);
1240a85fe12eSEd Maste 
1241a85fe12eSEd Maste 			break;
1242a85fe12eSEd Maste 		case 'C' :
1243a85fe12eSEd Maste 			++d->p;
1244a85fe12eSEd Maste 
1245a85fe12eSEd Maste 			if (*d->p == 'P')
1246a85fe12eSEd Maste 				d->cnst = true;
1247a85fe12eSEd Maste 			else {
1248bee2765cSEd Maste 				if (VEC_PUSH_STR(&d->vec, "const ") ==
1249a85fe12eSEd Maste 				    false)
1250a85fe12eSEd Maste 					return (false);
1251a85fe12eSEd Maste 			}
1252a85fe12eSEd Maste 
1253a85fe12eSEd Maste 			break;
1254a85fe12eSEd Maste 		case 'V' :
1255a85fe12eSEd Maste 			++d->p;
1256a85fe12eSEd Maste 
1257bee2765cSEd Maste 			if (VEC_PUSH_STR(&d->vec, "volatile ") == false)
1258a85fe12eSEd Maste 				return (false);
1259a85fe12eSEd Maste 
1260a85fe12eSEd Maste 			break;
1261a85fe12eSEd Maste 		case 'S' :
1262a85fe12eSEd Maste 			++d->p;
1263a85fe12eSEd Maste 
1264bee2765cSEd Maste 			if (VEC_PUSH_STR(&d->vec, "signed ") == false)
1265a85fe12eSEd Maste 				return (false);
1266a85fe12eSEd Maste 
1267a85fe12eSEd Maste 			break;
1268a85fe12eSEd Maste 		case 'P' :
1269a85fe12eSEd Maste 			++d->p;
1270a85fe12eSEd Maste 
1271a85fe12eSEd Maste 			if (*d->p == 'F')
1272a85fe12eSEd Maste 				return (read_func_ptr(d));
1273a85fe12eSEd Maste 			else
1274a85fe12eSEd Maste 				d->ptr = true;
1275a85fe12eSEd Maste 
1276a85fe12eSEd Maste 			break;
1277a85fe12eSEd Maste 		case 'R' :
1278a85fe12eSEd Maste 			++d->p;
1279a85fe12eSEd Maste 
1280a85fe12eSEd Maste 			d->ref = true;
1281a85fe12eSEd Maste 
1282a85fe12eSEd Maste 			break;
1283a85fe12eSEd Maste 		case 'F' :
1284a85fe12eSEd Maste 			break;
1285a85fe12eSEd Maste 		case 'A' :
1286a85fe12eSEd Maste 			++d->p;
1287a85fe12eSEd Maste 
1288a85fe12eSEd Maste 			if (read_array(d) == false)
1289a85fe12eSEd Maste 				return (false);
1290a85fe12eSEd Maste 
1291a85fe12eSEd Maste 			break;
1292a85fe12eSEd Maste 		case 'M' :
1293a85fe12eSEd Maste 			++d->p;
1294a85fe12eSEd Maste 
1295a85fe12eSEd Maste 			if (read_memptr(d) == false)
1296a85fe12eSEd Maste 				return (false);
1297a85fe12eSEd Maste 
1298a85fe12eSEd Maste 			break;
1299a85fe12eSEd Maste 		default :
1300a85fe12eSEd Maste 			break;
1301b6b6f9ccSEd Maste 		}
1302b6b6f9ccSEd Maste 	}
1303a85fe12eSEd Maste 
1304a85fe12eSEd Maste 	if (ELFTC_ISDIGIT(*d->p))
1305a85fe12eSEd Maste 		return (read_class(d));
1306a85fe12eSEd Maste 
1307a85fe12eSEd Maste 	switch (*d->p) {
1308a85fe12eSEd Maste 	case 'Q' :
1309a85fe12eSEd Maste 		++d->p;
1310a85fe12eSEd Maste 
1311a85fe12eSEd Maste 		return (read_qual_name(d));
1312a85fe12eSEd Maste 	case 'v' :
1313a85fe12eSEd Maste 		++d->p;
1314a85fe12eSEd Maste 
1315bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "void"));
1316a85fe12eSEd Maste 	case 'b':
1317a85fe12eSEd Maste 		++d->p;
1318a85fe12eSEd Maste 
1319bee2765cSEd Maste 		return(VEC_PUSH_STR(&d->vec, "bool"));
1320a85fe12eSEd Maste 	case 'c' :
1321a85fe12eSEd Maste 		++d->p;
1322a85fe12eSEd Maste 
1323bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "char"));
1324a85fe12eSEd Maste 	case 's' :
1325a85fe12eSEd Maste 		++d->p;
1326a85fe12eSEd Maste 
1327bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "short"));
1328a85fe12eSEd Maste 	case 'i' :
1329a85fe12eSEd Maste 		++d->p;
1330a85fe12eSEd Maste 
1331bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "int"));
1332a85fe12eSEd Maste 	case 'l' :
1333a85fe12eSEd Maste 		++d->p;
1334a85fe12eSEd Maste 
1335bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "long"));
1336a85fe12eSEd Maste 	case 'f' :
1337a85fe12eSEd Maste 		++d->p;
1338a85fe12eSEd Maste 
1339bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "float"));
1340a85fe12eSEd Maste 	case 'd':
1341a85fe12eSEd Maste 		++d->p;
1342a85fe12eSEd Maste 
1343bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "double"));
1344a85fe12eSEd Maste 	case 'r':
1345a85fe12eSEd Maste 		++d->p;
1346a85fe12eSEd Maste 
1347bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "long double"));
1348a85fe12eSEd Maste 	case 'e':
1349a85fe12eSEd Maste 		++d->p;
1350a85fe12eSEd Maste 
1351bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "..."));
1352a85fe12eSEd Maste 	case 'w':
1353a85fe12eSEd Maste 		++d->p;
1354a85fe12eSEd Maste 
1355bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "wchar_t"));
1356a85fe12eSEd Maste 	case 'x':
1357a85fe12eSEd Maste 		++d->p;
1358a85fe12eSEd Maste 
1359bee2765cSEd Maste 		return (VEC_PUSH_STR(&d->vec, "long long"));
1360a85fe12eSEd Maste 	default:
1361a85fe12eSEd Maste 		return (false);
1362a85fe12eSEd Maste 	};
1363a85fe12eSEd Maste 
1364a85fe12eSEd Maste 	/* NOTREACHED */
1365a85fe12eSEd Maste 	return (false);
1366a85fe12eSEd Maste }
1367