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