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