1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2007 Hyogeol Lee <hyogeollee@gmail.com>
3260684Skaiw * All rights reserved.
4260684Skaiw *
5260684Skaiw * Redistribution and use in source and binary forms, with or without
6260684Skaiw * modification, are permitted provided that the following conditions
7260684Skaiw * are met:
8260684Skaiw * 1. Redistributions of source code must retain the above copyright
9260684Skaiw *    notice, this list of conditions and the following disclaimer
10260684Skaiw *    in this position and unchanged.
11260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
12260684Skaiw *    notice, this list of conditions and the following disclaimer in the
13260684Skaiw *    documentation and/or other materials provided with the distribution.
14260684Skaiw *
15260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16260684Skaiw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17260684Skaiw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18260684Skaiw * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19260684Skaiw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20260684Skaiw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21260684Skaiw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22260684Skaiw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23260684Skaiw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24260684Skaiw * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25260684Skaiw */
26260684Skaiw#include <sys/types.h>
27260684Skaiw#include <assert.h>
28260684Skaiw#include <ctype.h>
29260684Skaiw#include <errno.h>
30260684Skaiw#include <libelftc.h>
31260684Skaiw#include <limits.h>
32260684Skaiw#include <stdbool.h>
33260684Skaiw#include <stdio.h>
34260684Skaiw#include <stdlib.h>
35260684Skaiw#include <string.h>
36260684Skaiw
37260684Skaiw#include "_libelftc.h"
38260684Skaiw
39300311SemasteELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3447 2016-05-03 13:32:23Z emaste $");
40260684Skaiw
41260684Skaiw/**
42260684Skaiw * @file cpp_demangle.c
43260684Skaiw * @brief Decode IA-64 C++ ABI style implementation.
44260684Skaiw *
45260684Skaiw * IA-64 standard ABI(Itanium C++ ABI) references.
46260684Skaiw *
47260684Skaiw * http://www.codesourcery.com/cxx-abi/abi.html#mangling \n
48260684Skaiw * http://www.codesourcery.com/cxx-abi/abi-mangling.html
49260684Skaiw */
50260684Skaiw
51260684Skaiwenum type_qualifier {
52260684Skaiw	TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
53283616Semaste	TYPE_CST, TYPE_VEC
54260684Skaiw};
55260684Skaiw
56260684Skaiwstruct vector_type_qualifier {
57260684Skaiw	size_t size, capacity;
58260684Skaiw	enum type_qualifier *q_container;
59260684Skaiw	struct vector_str ext_name;
60260684Skaiw};
61260684Skaiw
62260684Skaiwenum read_cmd {
63260684Skaiw	READ_FAIL, READ_NEST, READ_TMPL, READ_EXPR, READ_EXPL, READ_LOCAL,
64260684Skaiw	READ_TYPE, READ_FUNC, READ_PTRMEM
65260684Skaiw};
66260684Skaiw
67260684Skaiwstruct vector_read_cmd {
68260684Skaiw	size_t size, capacity;
69260684Skaiw	enum read_cmd *r_container;
70260684Skaiw};
71260684Skaiw
72260684Skaiwstruct cpp_demangle_data {
73260684Skaiw	struct vector_str	 output;	/* output string vector */
74260684Skaiw	struct vector_str	 output_tmp;
75260684Skaiw	struct vector_str	 subst;		/* substitution string vector */
76260684Skaiw	struct vector_str	 tmpl;
77260684Skaiw	struct vector_str	 class_type;
78260684Skaiw	struct vector_read_cmd	 cmd;
79260684Skaiw	bool			 paren;		/* parenthesis opened */
80260684Skaiw	bool			 pfirst;	/* first element of parameter */
81260684Skaiw	bool			 mem_rst;	/* restrict member function */
82260684Skaiw	bool			 mem_vat;	/* volatile member function */
83260684Skaiw	bool			 mem_cst;	/* const member function */
84260684Skaiw	int			 func_type;
85260684Skaiw	const char		*cur;		/* current mangled name ptr */
86260684Skaiw	const char		*last_sname;	/* last source name */
87283616Semaste	int			 push_head;
88260684Skaiw};
89260684Skaiw
90260684Skaiw#define	CPP_DEMANGLE_TRY_LIMIT	128
91260684Skaiw#define	FLOAT_SPRINTF_TRY_LIMIT	5
92260684Skaiw#define	FLOAT_QUADRUPLE_BYTES	16
93260684Skaiw#define	FLOAT_EXTENED_BYTES	10
94260684Skaiw
95260684Skaiw#define SIMPLE_HASH(x,y)	(64 * x + y)
96260684Skaiw
97260684Skaiwstatic void	cpp_demangle_data_dest(struct cpp_demangle_data *);
98260684Skaiwstatic int	cpp_demangle_data_init(struct cpp_demangle_data *,
99260684Skaiw		    const char *);
100260684Skaiwstatic int	cpp_demangle_get_subst(struct cpp_demangle_data *, size_t);
101260684Skaiwstatic int	cpp_demangle_get_tmpl_param(struct cpp_demangle_data *, size_t);
102260684Skaiwstatic int	cpp_demangle_push_fp(struct cpp_demangle_data *,
103260684Skaiw		    char *(*)(const char *, size_t));
104260684Skaiwstatic int	cpp_demangle_push_str(struct cpp_demangle_data *, const char *,
105260684Skaiw		    size_t);
106260684Skaiwstatic int	cpp_demangle_push_subst(struct cpp_demangle_data *,
107260684Skaiw		    const char *, size_t);
108260684Skaiwstatic int	cpp_demangle_push_subst_v(struct cpp_demangle_data *,
109260684Skaiw		    struct vector_str *);
110260684Skaiwstatic int	cpp_demangle_push_type_qualifier(struct cpp_demangle_data *,
111260684Skaiw		    struct vector_type_qualifier *, const char *);
112260684Skaiwstatic int	cpp_demangle_read_array(struct cpp_demangle_data *);
113260684Skaiwstatic int	cpp_demangle_read_encoding(struct cpp_demangle_data *);
114260684Skaiwstatic int	cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
115260684Skaiwstatic int	cpp_demangle_read_expression(struct cpp_demangle_data *);
116283616Semastestatic int	cpp_demangle_read_expression_flat(struct cpp_demangle_data *,
117283616Semaste		    char **);
118260684Skaiwstatic int	cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
119260684Skaiw		    const char *, size_t);
120260684Skaiwstatic int	cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
121260684Skaiw		    const char *, size_t);
122260684Skaiwstatic int	cpp_demangle_read_expression_trinary(struct cpp_demangle_data *,
123260684Skaiw		    const char *, size_t, const char *, size_t);
124260684Skaiwstatic int	cpp_demangle_read_function(struct cpp_demangle_data *, int *,
125260684Skaiw		    struct vector_type_qualifier *);
126260684Skaiwstatic int	cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
127260684Skaiwstatic int	cpp_demangle_read_local_name(struct cpp_demangle_data *);
128260684Skaiwstatic int	cpp_demangle_read_name(struct cpp_demangle_data *);
129283616Semastestatic int	cpp_demangle_read_name_flat(struct cpp_demangle_data *,
130283616Semaste		    char**);
131260684Skaiwstatic int	cpp_demangle_read_nested_name(struct cpp_demangle_data *);
132260684Skaiwstatic int	cpp_demangle_read_number(struct cpp_demangle_data *, long *);
133283616Semastestatic int	cpp_demangle_read_number_as_string(struct cpp_demangle_data *,
134283616Semaste		    char **);
135260684Skaiwstatic int	cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
136260684Skaiwstatic int	cpp_demangle_read_offset(struct cpp_demangle_data *);
137260684Skaiwstatic int	cpp_demangle_read_offset_number(struct cpp_demangle_data *);
138260684Skaiwstatic int	cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *);
139260684Skaiwstatic int	cpp_demangle_read_sname(struct cpp_demangle_data *);
140260684Skaiwstatic int	cpp_demangle_read_subst(struct cpp_demangle_data *);
141260684Skaiwstatic int	cpp_demangle_read_subst_std(struct cpp_demangle_data *);
142260684Skaiwstatic int	cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *,
143260684Skaiw		    const char *, size_t);
144260684Skaiwstatic int	cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
145260684Skaiwstatic int	cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
146260684Skaiwstatic int	cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
147260684Skaiwstatic int	cpp_demangle_read_type(struct cpp_demangle_data *, int);
148283616Semastestatic int	cpp_demangle_read_type_flat(struct cpp_demangle_data *,
149283616Semaste		    char **);
150260684Skaiwstatic int	cpp_demangle_read_uqname(struct cpp_demangle_data *);
151260684Skaiwstatic int	cpp_demangle_read_v_offset(struct cpp_demangle_data *);
152260684Skaiwstatic char	*decode_fp_to_double(const char *, size_t);
153260684Skaiwstatic char	*decode_fp_to_float(const char *, size_t);
154260684Skaiwstatic char	*decode_fp_to_float128(const char *, size_t);
155260684Skaiwstatic char	*decode_fp_to_float80(const char *, size_t);
156260684Skaiwstatic char	*decode_fp_to_long_double(const char *, size_t);
157260684Skaiwstatic int	hex_to_dec(char);
158260684Skaiwstatic void	vector_read_cmd_dest(struct vector_read_cmd *);
159260684Skaiwstatic int	vector_read_cmd_find(struct vector_read_cmd *, enum read_cmd);
160260684Skaiwstatic int	vector_read_cmd_init(struct vector_read_cmd *);
161260684Skaiwstatic int	vector_read_cmd_pop(struct vector_read_cmd *);
162260684Skaiwstatic int	vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd);
163260684Skaiwstatic void	vector_type_qualifier_dest(struct vector_type_qualifier *);
164260684Skaiwstatic int	vector_type_qualifier_init(struct vector_type_qualifier *);
165260684Skaiwstatic int	vector_type_qualifier_push(struct vector_type_qualifier *,
166260684Skaiw		    enum type_qualifier);
167260684Skaiw
168260684Skaiw/**
169260684Skaiw * @brief Decode the input string by IA-64 C++ ABI style.
170260684Skaiw *
171260684Skaiw * GNU GCC v3 use IA-64 standard ABI.
172260684Skaiw * @return New allocated demangled string or NULL if failed.
173260684Skaiw * @todo 1. Testing and more test case. 2. Code cleaning.
174260684Skaiw */
175260684Skaiwchar *
176260684Skaiwcpp_demangle_gnu3(const char *org)
177260684Skaiw{
178260684Skaiw	struct cpp_demangle_data ddata;
179260684Skaiw	ssize_t org_len;
180260684Skaiw	unsigned int limit;
181260684Skaiw	char *rtn;
182260684Skaiw
183260684Skaiw	if (org == NULL || (org_len = strlen(org)) < 2)
184260684Skaiw		return (NULL);
185260684Skaiw
186260684Skaiw	if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) {
187260684Skaiw		if ((rtn = malloc(org_len + 19)) == NULL)
188260684Skaiw			return (NULL);
189260684Skaiw		snprintf(rtn, org_len + 19,
190260684Skaiw		    "global constructors keyed to %s", org + 11);
191260684Skaiw		return (rtn);
192260684Skaiw	}
193260684Skaiw
194260684Skaiw	if (org[0] != '_' || org[1] != 'Z')
195260684Skaiw		return (NULL);
196260684Skaiw
197260684Skaiw	if (!cpp_demangle_data_init(&ddata, org + 2))
198260684Skaiw		return (NULL);
199260684Skaiw
200260684Skaiw	rtn = NULL;
201260684Skaiw
202260684Skaiw	if (!cpp_demangle_read_encoding(&ddata))
203260684Skaiw		goto clean;
204260684Skaiw
205260684Skaiw	limit = 0;
206260684Skaiw	while (*ddata.cur != '\0') {
207260684Skaiw		/*
208260684Skaiw		 * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4
209260684Skaiw		 */
210260684Skaiw		if (*ddata.cur == '@' && *(ddata.cur + 1) == '@')
211260684Skaiw			break;
212260684Skaiw		if (!cpp_demangle_read_type(&ddata, 1))
213260684Skaiw			goto clean;
214260684Skaiw		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
215260684Skaiw			goto clean;
216260684Skaiw	}
217260684Skaiw
218260684Skaiw	if (ddata.output.size == 0)
219260684Skaiw		goto clean;
220260684Skaiw	if (ddata.paren && !vector_str_push(&ddata.output, ")", 1))
221260684Skaiw		goto clean;
222260684Skaiw	if (ddata.mem_vat && !vector_str_push(&ddata.output, " volatile", 9))
223260684Skaiw		goto clean;
224260684Skaiw	if (ddata.mem_cst && !vector_str_push(&ddata.output, " const", 6))
225260684Skaiw		goto clean;
226260684Skaiw	if (ddata.mem_rst && !vector_str_push(&ddata.output, " restrict", 9))
227260684Skaiw		goto clean;
228260684Skaiw
229260684Skaiw	rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
230260684Skaiw
231260684Skaiwclean:
232260684Skaiw	cpp_demangle_data_dest(&ddata);
233260684Skaiw
234260684Skaiw	return (rtn);
235260684Skaiw}
236260684Skaiw
237260684Skaiwstatic void
238260684Skaiwcpp_demangle_data_dest(struct cpp_demangle_data *d)
239260684Skaiw{
240260684Skaiw
241260684Skaiw	if (d == NULL)
242260684Skaiw		return;
243260684Skaiw
244260684Skaiw	vector_read_cmd_dest(&d->cmd);
245260684Skaiw	vector_str_dest(&d->class_type);
246260684Skaiw	vector_str_dest(&d->tmpl);
247260684Skaiw	vector_str_dest(&d->subst);
248260684Skaiw	vector_str_dest(&d->output_tmp);
249260684Skaiw	vector_str_dest(&d->output);
250260684Skaiw}
251260684Skaiw
252260684Skaiwstatic int
253260684Skaiwcpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
254260684Skaiw{
255260684Skaiw
256260684Skaiw	if (d == NULL || cur == NULL)
257260684Skaiw		return (0);
258260684Skaiw
259260684Skaiw	if (!vector_str_init(&d->output))
260260684Skaiw		return (0);
261260684Skaiw	if (!vector_str_init(&d->output_tmp))
262260684Skaiw		goto clean1;
263260684Skaiw	if (!vector_str_init(&d->subst))
264260684Skaiw		goto clean2;
265260684Skaiw	if (!vector_str_init(&d->tmpl))
266260684Skaiw		goto clean3;
267260684Skaiw	if (!vector_str_init(&d->class_type))
268260684Skaiw		goto clean4;
269260684Skaiw	if (!vector_read_cmd_init(&d->cmd))
270260684Skaiw		goto clean5;
271260684Skaiw
272260684Skaiw	assert(d->output.container != NULL);
273260684Skaiw	assert(d->output_tmp.container != NULL);
274260684Skaiw	assert(d->subst.container != NULL);
275260684Skaiw	assert(d->tmpl.container != NULL);
276260684Skaiw	assert(d->class_type.container != NULL);
277260684Skaiw
278260684Skaiw	d->paren = false;
279260684Skaiw	d->pfirst = false;
280260684Skaiw	d->mem_rst = false;
281260684Skaiw	d->mem_vat = false;
282260684Skaiw	d->mem_cst = false;
283260684Skaiw	d->func_type = 0;
284260684Skaiw	d->cur = cur;
285260684Skaiw	d->last_sname = NULL;
286283616Semaste	d->push_head = 0;
287260684Skaiw
288260684Skaiw	return (1);
289260684Skaiw
290260684Skaiwclean5:
291260684Skaiw	vector_str_dest(&d->class_type);
292260684Skaiwclean4:
293260684Skaiw	vector_str_dest(&d->tmpl);
294260684Skaiwclean3:
295260684Skaiw	vector_str_dest(&d->subst);
296260684Skaiwclean2:
297260684Skaiw	vector_str_dest(&d->output_tmp);
298260684Skaiwclean1:
299260684Skaiw	vector_str_dest(&d->output);
300260684Skaiw
301260684Skaiw	return (0);
302260684Skaiw}
303260684Skaiw
304260684Skaiwstatic int
305260684Skaiwcpp_demangle_push_fp(struct cpp_demangle_data *ddata,
306260684Skaiw    char *(*decoder)(const char *, size_t))
307260684Skaiw{
308260684Skaiw	size_t len;
309260684Skaiw	int rtn;
310260684Skaiw	const char *fp;
311260684Skaiw	char *f;
312260684Skaiw
313260684Skaiw	if (ddata == NULL || decoder == NULL)
314260684Skaiw		return (0);
315260684Skaiw
316260684Skaiw	fp = ddata->cur;
317260684Skaiw	while (*ddata->cur != 'E')
318260684Skaiw		++ddata->cur;
319260684Skaiw
320260684Skaiw	if ((f = decoder(fp, ddata->cur - fp)) == NULL)
321260684Skaiw		return (0);
322260684Skaiw
323260684Skaiw	rtn = 0;
324260684Skaiw	if ((len = strlen(f)) > 0)
325282918Semaste		rtn = cpp_demangle_push_str(ddata, f, len);
326260684Skaiw
327260684Skaiw	free(f);
328260684Skaiw
329283616Semaste	++ddata->cur;
330283616Semaste
331260684Skaiw	return (rtn);
332260684Skaiw}
333260684Skaiw
334260684Skaiwstatic int
335260684Skaiwcpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
336260684Skaiw    size_t len)
337260684Skaiw{
338260684Skaiw
339260684Skaiw	if (ddata == NULL || str == NULL || len == 0)
340260684Skaiw		return (0);
341260684Skaiw
342283616Semaste	if (ddata->push_head > 0)
343260684Skaiw		return (vector_str_push(&ddata->output_tmp, str, len));
344260684Skaiw
345260684Skaiw	return (vector_str_push(&ddata->output, str, len));
346260684Skaiw}
347260684Skaiw
348260684Skaiwstatic int
349260684Skaiwcpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str,
350260684Skaiw    size_t len)
351260684Skaiw{
352260684Skaiw
353260684Skaiw	if (ddata == NULL || str == NULL || len == 0)
354260684Skaiw		return (0);
355260684Skaiw
356260684Skaiw	if (!vector_str_find(&ddata->subst, str, len))
357260684Skaiw		return (vector_str_push(&ddata->subst, str, len));
358260684Skaiw
359260684Skaiw	return (1);
360260684Skaiw}
361260684Skaiw
362260684Skaiwstatic int
363260684Skaiwcpp_demangle_push_subst_v(struct cpp_demangle_data *ddata, struct vector_str *v)
364260684Skaiw{
365260684Skaiw	size_t str_len;
366260684Skaiw	int rtn;
367260684Skaiw	char *str;
368260684Skaiw
369260684Skaiw	if (ddata == NULL || v == NULL)
370260684Skaiw		return (0);
371260684Skaiw
372260684Skaiw	if ((str = vector_str_get_flat(v, &str_len)) == NULL)
373260684Skaiw		return (0);
374260684Skaiw
375260684Skaiw	rtn = cpp_demangle_push_subst(ddata, str, str_len);
376260684Skaiw
377260684Skaiw	free(str);
378260684Skaiw
379260684Skaiw	return (rtn);
380260684Skaiw}
381260684Skaiw
382260684Skaiwstatic int
383260684Skaiwcpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
384260684Skaiw    struct vector_type_qualifier *v, const char *type_str)
385260684Skaiw{
386260684Skaiw	struct vector_str subst_v;
387260684Skaiw	size_t idx, e_idx, e_len;
388260684Skaiw	int rtn;
389260684Skaiw	char *buf;
390260684Skaiw
391260684Skaiw	if (ddata == NULL || v == NULL)
392260684Skaiw		return (0);
393260684Skaiw
394260684Skaiw	if ((idx = v->size) == 0)
395260684Skaiw		return (1);
396260684Skaiw
397260684Skaiw	rtn = 0;
398260684Skaiw	if (type_str != NULL) {
399260684Skaiw		if (!vector_str_init(&subst_v))
400260684Skaiw			return (0);
401260684Skaiw		if (!vector_str_push(&subst_v, type_str, strlen(type_str)))
402260684Skaiw			goto clean;
403260684Skaiw	}
404260684Skaiw
405260684Skaiw	e_idx = 0;
406260684Skaiw	while (idx > 0) {
407260684Skaiw		switch (v->q_container[idx - 1]) {
408260684Skaiw		case TYPE_PTR:
409260684Skaiw			if (!cpp_demangle_push_str(ddata, "*", 1))
410260684Skaiw				goto clean;
411260684Skaiw			if (type_str != NULL) {
412260684Skaiw				if (!vector_str_push(&subst_v, "*", 1))
413260684Skaiw					goto clean;
414283616Semaste				if (!cpp_demangle_push_subst_v(ddata,
415283616Semaste				    &subst_v))
416260684Skaiw					goto clean;
417260684Skaiw			}
418260684Skaiw			break;
419260684Skaiw
420260684Skaiw		case TYPE_REF:
421260684Skaiw			if (!cpp_demangle_push_str(ddata, "&", 1))
422260684Skaiw				goto clean;
423260684Skaiw			if (type_str != NULL) {
424260684Skaiw				if (!vector_str_push(&subst_v, "&", 1))
425260684Skaiw					goto clean;
426283616Semaste				if (!cpp_demangle_push_subst_v(ddata,
427283616Semaste				    &subst_v))
428260684Skaiw					goto clean;
429260684Skaiw			}
430260684Skaiw			break;
431260684Skaiw
432260684Skaiw		case TYPE_CMX:
433260684Skaiw			if (!cpp_demangle_push_str(ddata, " complex", 8))
434260684Skaiw				goto clean;
435260684Skaiw			if (type_str != NULL) {
436260684Skaiw				if (!vector_str_push(&subst_v, " complex", 8))
437260684Skaiw					goto clean;
438283616Semaste				if (!cpp_demangle_push_subst_v(ddata,
439283616Semaste				    &subst_v))
440260684Skaiw					goto clean;
441260684Skaiw			}
442260684Skaiw			break;
443260684Skaiw
444260684Skaiw		case TYPE_IMG:
445260684Skaiw			if (!cpp_demangle_push_str(ddata, " imaginary", 10))
446260684Skaiw				goto clean;
447260684Skaiw			if (type_str != NULL) {
448283616Semaste				if (!vector_str_push(&subst_v, " imaginary",
449283616Semaste				    10))
450260684Skaiw					goto clean;
451283616Semaste				if (!cpp_demangle_push_subst_v(ddata,
452283616Semaste				    &subst_v))
453260684Skaiw					goto clean;
454260684Skaiw			}
455260684Skaiw			break;
456260684Skaiw
457260684Skaiw		case TYPE_EXT:
458283616Semaste			if (v->ext_name.size == 0 ||
459283616Semaste			    e_idx > v->ext_name.size - 1)
460260684Skaiw				goto clean;
461283616Semaste			if ((e_len = strlen(v->ext_name.container[e_idx])) ==
462283616Semaste			    0)
463260684Skaiw				goto clean;
464283616Semaste			if ((buf = malloc(e_len + 2)) == NULL)
465260684Skaiw				goto clean;
466283616Semaste			snprintf(buf, e_len + 2, " %s",
467283616Semaste			    v->ext_name.container[e_idx]);
468260684Skaiw
469260684Skaiw			if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) {
470260684Skaiw				free(buf);
471260684Skaiw				goto clean;
472260684Skaiw			}
473260684Skaiw
474260684Skaiw			if (type_str != NULL) {
475260684Skaiw				if (!vector_str_push(&subst_v, buf,
476260684Skaiw				    e_len + 1)) {
477260684Skaiw					free(buf);
478260684Skaiw					goto clean;
479260684Skaiw				}
480283616Semaste				if (!cpp_demangle_push_subst_v(ddata,
481283616Semaste				    &subst_v)) {
482260684Skaiw					free(buf);
483260684Skaiw					goto clean;
484260684Skaiw				}
485260684Skaiw			}
486260684Skaiw			free(buf);
487260684Skaiw			++e_idx;
488260684Skaiw			break;
489260684Skaiw
490260684Skaiw		case TYPE_RST:
491260684Skaiw			if (!cpp_demangle_push_str(ddata, " restrict", 9))
492260684Skaiw				goto clean;
493260684Skaiw			if (type_str != NULL) {
494260684Skaiw				if (!vector_str_push(&subst_v, " restrict", 9))
495260684Skaiw					goto clean;
496283616Semaste				if (!cpp_demangle_push_subst_v(ddata,
497283616Semaste				    &subst_v))
498260684Skaiw					goto clean;
499260684Skaiw			}
500260684Skaiw			break;
501260684Skaiw
502260684Skaiw		case TYPE_VAT:
503260684Skaiw			if (!cpp_demangle_push_str(ddata, " volatile", 9))
504260684Skaiw				goto clean;
505260684Skaiw			if (type_str != NULL) {
506260684Skaiw				if (!vector_str_push(&subst_v, " volatile", 9))
507260684Skaiw					goto clean;
508283616Semaste				if (!cpp_demangle_push_subst_v(ddata,
509283616Semaste				    &subst_v))
510260684Skaiw					goto clean;
511260684Skaiw			}
512260684Skaiw			break;
513260684Skaiw
514260684Skaiw		case TYPE_CST:
515260684Skaiw			if (!cpp_demangle_push_str(ddata, " const", 6))
516260684Skaiw				goto clean;
517260684Skaiw			if (type_str != NULL) {
518260684Skaiw				if (!vector_str_push(&subst_v, " const", 6))
519260684Skaiw					goto clean;
520283616Semaste				if (!cpp_demangle_push_subst_v(ddata,
521283616Semaste				    &subst_v))
522260684Skaiw					goto clean;
523260684Skaiw			}
524260684Skaiw			break;
525260684Skaiw
526283616Semaste		case TYPE_VEC:
527283616Semaste			if (v->ext_name.size == 0 ||
528283616Semaste			    e_idx > v->ext_name.size - 1)
529283616Semaste				goto clean;
530283616Semaste			if ((e_len = strlen(v->ext_name.container[e_idx])) ==
531283616Semaste			    0)
532283616Semaste				goto clean;
533283616Semaste			if ((buf = malloc(e_len + 12)) == NULL)
534283616Semaste				goto clean;
535283616Semaste			snprintf(buf, e_len + 12, " __vector(%s)",
536283616Semaste			    v->ext_name.container[e_idx]);
537283616Semaste			if (!cpp_demangle_push_str(ddata, buf, e_len + 11)) {
538283616Semaste				free(buf);
539283616Semaste				goto clean;
540283616Semaste			}
541283616Semaste			if (type_str != NULL) {
542283616Semaste				if (!vector_str_push(&subst_v, buf,
543283616Semaste				    e_len + 11)) {
544283616Semaste					free(buf);
545283616Semaste					goto clean;
546283616Semaste				}
547283616Semaste				if (!cpp_demangle_push_subst_v(ddata,
548283616Semaste				    &subst_v)) {
549283616Semaste					free(buf);
550283616Semaste					goto clean;
551283616Semaste				}
552283616Semaste			}
553283616Semaste			free(buf);
554283616Semaste			++e_idx;
555283616Semaste			break;
556300311Semaste		}
557260684Skaiw		--idx;
558260684Skaiw	}
559260684Skaiw
560260684Skaiw	rtn = 1;
561260684Skaiwclean:
562260684Skaiw	if (type_str != NULL)
563260684Skaiw		vector_str_dest(&subst_v);
564260684Skaiw
565260684Skaiw	return (rtn);
566260684Skaiw}
567260684Skaiw
568260684Skaiwstatic int
569260684Skaiwcpp_demangle_get_subst(struct cpp_demangle_data *ddata, size_t idx)
570260684Skaiw{
571260684Skaiw	size_t len;
572260684Skaiw
573260684Skaiw	if (ddata == NULL || ddata->subst.size <= idx)
574260684Skaiw		return (0);
575260684Skaiw	if ((len = strlen(ddata->subst.container[idx])) == 0)
576260684Skaiw		return (0);
577260684Skaiw	if (!cpp_demangle_push_str(ddata, ddata->subst.container[idx], len))
578260684Skaiw		return (0);
579260684Skaiw
580260684Skaiw	/* skip '_' */
581260684Skaiw	++ddata->cur;
582260684Skaiw
583260684Skaiw	return (1);
584260684Skaiw}
585260684Skaiw
586260684Skaiwstatic int
587260684Skaiwcpp_demangle_get_tmpl_param(struct cpp_demangle_data *ddata, size_t idx)
588260684Skaiw{
589260684Skaiw	size_t len;
590260684Skaiw
591260684Skaiw	if (ddata == NULL || ddata->tmpl.size <= idx)
592260684Skaiw		return (0);
593260684Skaiw	if ((len = strlen(ddata->tmpl.container[idx])) == 0)
594260684Skaiw		return (0);
595260684Skaiw	if (!cpp_demangle_push_str(ddata, ddata->tmpl.container[idx], len))
596260684Skaiw		return (0);
597260684Skaiw
598260684Skaiw	++ddata->cur;
599260684Skaiw
600260684Skaiw	return (1);
601260684Skaiw}
602260684Skaiw
603260684Skaiwstatic int
604260684Skaiwcpp_demangle_read_array(struct cpp_demangle_data *ddata)
605260684Skaiw{
606260684Skaiw	size_t i, num_len, exp_len, p_idx, idx;
607260684Skaiw	const char *num;
608260684Skaiw	char *exp;
609260684Skaiw
610260684Skaiw	if (ddata == NULL || *(++ddata->cur) == '\0')
611260684Skaiw		return (0);
612260684Skaiw
613260684Skaiw	if (*ddata->cur == '_') {
614260684Skaiw		if (*(++ddata->cur) == '\0')
615260684Skaiw			return (0);
616260684Skaiw
617260684Skaiw		if (!cpp_demangle_read_type(ddata, 0))
618260684Skaiw			return (0);
619260684Skaiw
620260684Skaiw		if (!cpp_demangle_push_str(ddata, "[]", 2))
621260684Skaiw			return (0);
622260684Skaiw	} else {
623260684Skaiw		if (ELFTC_ISDIGIT(*ddata->cur) != 0) {
624260684Skaiw			num = ddata->cur;
625260684Skaiw			while (ELFTC_ISDIGIT(*ddata->cur) != 0)
626260684Skaiw				++ddata->cur;
627260684Skaiw			if (*ddata->cur != '_')
628260684Skaiw				return (0);
629260684Skaiw			num_len = ddata->cur - num;
630260684Skaiw			assert(num_len > 0);
631260684Skaiw			if (*(++ddata->cur) == '\0')
632260684Skaiw				return (0);
633260684Skaiw			if (!cpp_demangle_read_type(ddata, 0))
634260684Skaiw				return (0);
635260684Skaiw			if (!cpp_demangle_push_str(ddata, "[", 1))
636260684Skaiw				return (0);
637260684Skaiw			if (!cpp_demangle_push_str(ddata, num, num_len))
638260684Skaiw				return (0);
639260684Skaiw			if (!cpp_demangle_push_str(ddata, "]", 1))
640260684Skaiw				return (0);
641260684Skaiw		} else {
642260684Skaiw			p_idx = ddata->output.size;
643260684Skaiw			if (!cpp_demangle_read_expression(ddata))
644260684Skaiw				return (0);
645260684Skaiw			if ((exp = vector_str_substr(&ddata->output, p_idx,
646260684Skaiw				 ddata->output.size - 1, &exp_len)) == NULL)
647260684Skaiw				return (0);
648260684Skaiw			idx = ddata->output.size;
649260684Skaiw			for (i = p_idx; i < idx; ++i)
650260684Skaiw				if (!vector_str_pop(&ddata->output)) {
651260684Skaiw					free(exp);
652260684Skaiw					return (0);
653260684Skaiw				}
654260684Skaiw			if (*ddata->cur != '_') {
655260684Skaiw				free(exp);
656260684Skaiw				return (0);
657260684Skaiw			}
658260684Skaiw			++ddata->cur;
659260684Skaiw			if (*ddata->cur == '\0') {
660260684Skaiw				free(exp);
661260684Skaiw				return (0);
662260684Skaiw			}
663260684Skaiw			if (!cpp_demangle_read_type(ddata, 0)) {
664260684Skaiw				free(exp);
665260684Skaiw				return (0);
666260684Skaiw			}
667260684Skaiw			if (!cpp_demangle_push_str(ddata, "[", 1)) {
668260684Skaiw				free(exp);
669260684Skaiw				return (0);
670260684Skaiw			}
671260684Skaiw			if (!cpp_demangle_push_str(ddata, exp, exp_len)) {
672260684Skaiw				free(exp);
673260684Skaiw				return (0);
674260684Skaiw			}
675260684Skaiw			if (!cpp_demangle_push_str(ddata, "]", 1)) {
676260684Skaiw				free(exp);
677260684Skaiw				return (0);
678260684Skaiw			}
679260684Skaiw			free(exp);
680260684Skaiw		}
681260684Skaiw	}
682260684Skaiw
683260684Skaiw	return (1);
684260684Skaiw}
685260684Skaiw
686260684Skaiwstatic int
687260684Skaiwcpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
688260684Skaiw{
689260684Skaiw	const char *num;
690260684Skaiw
691260684Skaiw	if (ddata == NULL || *(++ddata->cur) == '\0')
692260684Skaiw		return (0);
693260684Skaiw
694260684Skaiw	if (*ddata->cur == '_' && *(ddata->cur + 1) == 'Z') {
695260684Skaiw		ddata->cur += 2;
696260684Skaiw		if (*ddata->cur == '\0')
697260684Skaiw			return (0);
698260684Skaiw		if (!cpp_demangle_read_encoding(ddata))
699260684Skaiw			return (0);
700260684Skaiw		++ddata->cur;
701260684Skaiw		return (1);
702260684Skaiw	}
703260684Skaiw
704260684Skaiw	switch (*ddata->cur) {
705260684Skaiw	case 'b':
706283616Semaste		if (*(ddata->cur + 2) != 'E')
707283616Semaste			return (0);
708260684Skaiw		switch (*(++ddata->cur)) {
709260684Skaiw		case '0':
710283616Semaste			ddata->cur += 2;
711260684Skaiw			return (cpp_demangle_push_str(ddata, "false", 5));
712260684Skaiw		case '1':
713283616Semaste			ddata->cur += 2;
714260684Skaiw			return (cpp_demangle_push_str(ddata, "true", 4));
715260684Skaiw		default:
716260684Skaiw			return (0);
717300311Semaste		}
718260684Skaiw
719260684Skaiw	case 'd':
720260684Skaiw		++ddata->cur;
721260684Skaiw		return (cpp_demangle_push_fp(ddata, decode_fp_to_double));
722260684Skaiw
723260684Skaiw	case 'e':
724260684Skaiw		++ddata->cur;
725260684Skaiw		if (sizeof(long double) == 10)
726260684Skaiw			return (cpp_demangle_push_fp(ddata,
727260684Skaiw			    decode_fp_to_double));
728260684Skaiw		return (cpp_demangle_push_fp(ddata, decode_fp_to_float80));
729260684Skaiw
730260684Skaiw	case 'f':
731260684Skaiw		++ddata->cur;
732260684Skaiw		return (cpp_demangle_push_fp(ddata, decode_fp_to_float));
733260684Skaiw
734260684Skaiw	case 'g':
735260684Skaiw		++ddata->cur;
736260684Skaiw		if (sizeof(long double) == 16)
737260684Skaiw			return (cpp_demangle_push_fp(ddata,
738260684Skaiw			    decode_fp_to_double));
739260684Skaiw		return (cpp_demangle_push_fp(ddata, decode_fp_to_float128));
740260684Skaiw
741260684Skaiw	case 'i':
742260684Skaiw	case 'j':
743260684Skaiw	case 'l':
744260684Skaiw	case 'm':
745260684Skaiw	case 'n':
746260684Skaiw	case 's':
747260684Skaiw	case 't':
748260684Skaiw	case 'x':
749260684Skaiw	case 'y':
750260684Skaiw		if (*(++ddata->cur) == 'n') {
751260684Skaiw			if (!cpp_demangle_push_str(ddata, "-", 1))
752260684Skaiw				return (0);
753260684Skaiw			++ddata->cur;
754260684Skaiw		}
755260684Skaiw		num = ddata->cur;
756260684Skaiw		while (*ddata->cur != 'E') {
757260684Skaiw			if (!ELFTC_ISDIGIT(*ddata->cur))
758260684Skaiw				return (0);
759260684Skaiw			++ddata->cur;
760260684Skaiw		}
761260684Skaiw		++ddata->cur;
762283616Semaste		return (cpp_demangle_push_str(ddata, num,
763283616Semaste		    ddata->cur - num - 1));
764260684Skaiw
765260684Skaiw	default:
766260684Skaiw		return (0);
767300311Semaste	}
768260684Skaiw}
769260684Skaiw
770260684Skaiwstatic int
771260684Skaiwcpp_demangle_read_expression(struct cpp_demangle_data *ddata)
772260684Skaiw{
773260684Skaiw
774260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
775260684Skaiw		return (0);
776260684Skaiw
777260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
778260684Skaiw	case SIMPLE_HASH('s', 't'):
779260684Skaiw		ddata->cur += 2;
780260684Skaiw		return (cpp_demangle_read_type(ddata, 0));
781260684Skaiw
782260684Skaiw	case SIMPLE_HASH('s', 'r'):
783260684Skaiw		ddata->cur += 2;
784260684Skaiw		if (!cpp_demangle_read_type(ddata, 0))
785260684Skaiw			return (0);
786260684Skaiw		if (!cpp_demangle_read_uqname(ddata))
787260684Skaiw			return (0);
788260684Skaiw		if (*ddata->cur == 'I')
789260684Skaiw			return (cpp_demangle_read_tmpl_args(ddata));
790260684Skaiw		return (1);
791260684Skaiw
792260684Skaiw	case SIMPLE_HASH('a', 'a'):
793260684Skaiw		/* operator && */
794260684Skaiw		ddata->cur += 2;
795260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "&&", 2));
796260684Skaiw
797260684Skaiw	case SIMPLE_HASH('a', 'd'):
798260684Skaiw		/* operator & (unary) */
799260684Skaiw		ddata->cur += 2;
800260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "&", 1));
801260684Skaiw
802260684Skaiw	case SIMPLE_HASH('a', 'n'):
803260684Skaiw		/* operator & */
804260684Skaiw		ddata->cur += 2;
805260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "&", 1));
806260684Skaiw
807260684Skaiw	case SIMPLE_HASH('a', 'N'):
808260684Skaiw		/* operator &= */
809260684Skaiw		ddata->cur += 2;
810260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "&=", 2));
811260684Skaiw
812260684Skaiw	case SIMPLE_HASH('a', 'S'):
813260684Skaiw		/* operator = */
814260684Skaiw		ddata->cur += 2;
815260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "=", 1));
816260684Skaiw
817260684Skaiw	case SIMPLE_HASH('c', 'l'):
818260684Skaiw		/* operator () */
819260684Skaiw		ddata->cur += 2;
820260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "()", 2));
821260684Skaiw
822260684Skaiw	case SIMPLE_HASH('c', 'm'):
823260684Skaiw		/* operator , */
824260684Skaiw		ddata->cur += 2;
825260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ",", 1));
826260684Skaiw
827260684Skaiw	case SIMPLE_HASH('c', 'o'):
828260684Skaiw		/* operator ~ */
829260684Skaiw		ddata->cur += 2;
830260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "~", 1));
831260684Skaiw
832260684Skaiw	case SIMPLE_HASH('c', 'v'):
833260684Skaiw		/* operator (cast) */
834260684Skaiw		ddata->cur += 2;
835260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "(cast)", 6));
836260684Skaiw
837260684Skaiw	case SIMPLE_HASH('d', 'a'):
838260684Skaiw		/* operator delete [] */
839260684Skaiw		ddata->cur += 2;
840260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "delete []", 9));
841260684Skaiw
842260684Skaiw	case SIMPLE_HASH('d', 'e'):
843260684Skaiw		/* operator * (unary) */
844260684Skaiw		ddata->cur += 2;
845260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "*", 1));
846260684Skaiw
847260684Skaiw	case SIMPLE_HASH('d', 'l'):
848260684Skaiw		/* operator delete */
849260684Skaiw		ddata->cur += 2;
850260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "delete", 6));
851260684Skaiw
852260684Skaiw	case SIMPLE_HASH('d', 'v'):
853260684Skaiw		/* operator / */
854260684Skaiw		ddata->cur += 2;
855260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "/", 1));
856260684Skaiw
857260684Skaiw	case SIMPLE_HASH('d', 'V'):
858260684Skaiw		/* operator /= */
859260684Skaiw		ddata->cur += 2;
860260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "/=", 2));
861260684Skaiw
862260684Skaiw	case SIMPLE_HASH('e', 'o'):
863260684Skaiw		/* operator ^ */
864260684Skaiw		ddata->cur += 2;
865260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "^", 1));
866260684Skaiw
867260684Skaiw	case SIMPLE_HASH('e', 'O'):
868260684Skaiw		/* operator ^= */
869260684Skaiw		ddata->cur += 2;
870260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "^=", 2));
871260684Skaiw
872260684Skaiw	case SIMPLE_HASH('e', 'q'):
873260684Skaiw		/* operator == */
874260684Skaiw		ddata->cur += 2;
875260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "==", 2));
876260684Skaiw
877260684Skaiw	case SIMPLE_HASH('g', 'e'):
878260684Skaiw		/* operator >= */
879260684Skaiw		ddata->cur += 2;
880260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ">=", 2));
881260684Skaiw
882260684Skaiw	case SIMPLE_HASH('g', 't'):
883260684Skaiw		/* operator > */
884260684Skaiw		ddata->cur += 2;
885260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ">", 1));
886260684Skaiw
887260684Skaiw	case SIMPLE_HASH('i', 'x'):
888260684Skaiw		/* operator [] */
889260684Skaiw		ddata->cur += 2;
890260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "[]", 2));
891260684Skaiw
892260684Skaiw	case SIMPLE_HASH('l', 'e'):
893260684Skaiw		/* operator <= */
894260684Skaiw		ddata->cur += 2;
895260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "<=", 2));
896260684Skaiw
897260684Skaiw	case SIMPLE_HASH('l', 's'):
898260684Skaiw		/* operator << */
899260684Skaiw		ddata->cur += 2;
900260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "<<", 2));
901260684Skaiw
902260684Skaiw	case SIMPLE_HASH('l', 'S'):
903260684Skaiw		/* operator <<= */
904260684Skaiw		ddata->cur += 2;
905260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "<<=", 3));
906260684Skaiw
907260684Skaiw	case SIMPLE_HASH('l', 't'):
908260684Skaiw		/* operator < */
909260684Skaiw		ddata->cur += 2;
910260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "<", 1));
911260684Skaiw
912260684Skaiw	case SIMPLE_HASH('m', 'i'):
913260684Skaiw		/* operator - */
914260684Skaiw		ddata->cur += 2;
915260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "-", 1));
916260684Skaiw
917260684Skaiw	case SIMPLE_HASH('m', 'I'):
918260684Skaiw		/* operator -= */
919260684Skaiw		ddata->cur += 2;
920260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "-=", 2));
921260684Skaiw
922260684Skaiw	case SIMPLE_HASH('m', 'l'):
923260684Skaiw		/* operator * */
924260684Skaiw		ddata->cur += 2;
925260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "*", 1));
926260684Skaiw
927260684Skaiw	case SIMPLE_HASH('m', 'L'):
928260684Skaiw		/* operator *= */
929260684Skaiw		ddata->cur += 2;
930260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "*=", 2));
931260684Skaiw
932260684Skaiw	case SIMPLE_HASH('m', 'm'):
933260684Skaiw		/* operator -- */
934260684Skaiw		ddata->cur += 2;
935260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "--", 2));
936260684Skaiw
937260684Skaiw	case SIMPLE_HASH('n', 'a'):
938260684Skaiw		/* operator new[] */
939260684Skaiw		ddata->cur += 2;
940260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "new []", 6));
941260684Skaiw
942260684Skaiw	case SIMPLE_HASH('n', 'e'):
943260684Skaiw		/* operator != */
944260684Skaiw		ddata->cur += 2;
945260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "!=", 2));
946260684Skaiw
947260684Skaiw	case SIMPLE_HASH('n', 'g'):
948260684Skaiw		/* operator - (unary) */
949260684Skaiw		ddata->cur += 2;
950260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "-", 1));
951260684Skaiw
952260684Skaiw	case SIMPLE_HASH('n', 't'):
953260684Skaiw		/* operator ! */
954260684Skaiw		ddata->cur += 2;
955260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "!", 1));
956260684Skaiw
957260684Skaiw	case SIMPLE_HASH('n', 'w'):
958260684Skaiw		/* operator new */
959260684Skaiw		ddata->cur += 2;
960260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "new", 3));
961260684Skaiw
962260684Skaiw	case SIMPLE_HASH('o', 'o'):
963260684Skaiw		/* operator || */
964260684Skaiw		ddata->cur += 2;
965260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "||", 2));
966260684Skaiw
967260684Skaiw	case SIMPLE_HASH('o', 'r'):
968260684Skaiw		/* operator | */
969260684Skaiw		ddata->cur += 2;
970260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "|", 1));
971260684Skaiw
972260684Skaiw	case SIMPLE_HASH('o', 'R'):
973260684Skaiw		/* operator |= */
974260684Skaiw		ddata->cur += 2;
975260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "|=", 2));
976260684Skaiw
977260684Skaiw	case SIMPLE_HASH('p', 'l'):
978260684Skaiw		/* operator + */
979260684Skaiw		ddata->cur += 2;
980260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "+", 1));
981260684Skaiw
982260684Skaiw	case SIMPLE_HASH('p', 'L'):
983260684Skaiw		/* operator += */
984260684Skaiw		ddata->cur += 2;
985260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "+=", 2));
986260684Skaiw
987260684Skaiw	case SIMPLE_HASH('p', 'm'):
988260684Skaiw		/* operator ->* */
989260684Skaiw		ddata->cur += 2;
990260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "->*", 3));
991260684Skaiw
992260684Skaiw	case SIMPLE_HASH('p', 'p'):
993260684Skaiw		/* operator ++ */
994260684Skaiw		ddata->cur += 2;
995260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "++", 2));
996260684Skaiw
997260684Skaiw	case SIMPLE_HASH('p', 's'):
998260684Skaiw		/* operator + (unary) */
999260684Skaiw		ddata->cur += 2;
1000260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "+", 1));
1001260684Skaiw
1002260684Skaiw	case SIMPLE_HASH('p', 't'):
1003260684Skaiw		/* operator -> */
1004260684Skaiw		ddata->cur += 2;
1005260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "->", 2));
1006260684Skaiw
1007260684Skaiw	case SIMPLE_HASH('q', 'u'):
1008260684Skaiw		/* operator ? */
1009260684Skaiw		ddata->cur += 2;
1010260684Skaiw		return (cpp_demangle_read_expression_trinary(ddata, "?", 1,
1011260684Skaiw		    ":", 1));
1012260684Skaiw
1013260684Skaiw	case SIMPLE_HASH('r', 'm'):
1014260684Skaiw		/* operator % */
1015260684Skaiw		ddata->cur += 2;
1016260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "%", 1));
1017260684Skaiw
1018260684Skaiw	case SIMPLE_HASH('r', 'M'):
1019260684Skaiw		/* operator %= */
1020260684Skaiw		ddata->cur += 2;
1021260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "%=", 2));
1022260684Skaiw
1023260684Skaiw	case SIMPLE_HASH('r', 's'):
1024260684Skaiw		/* operator >> */
1025260684Skaiw		ddata->cur += 2;
1026260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ">>", 2));
1027260684Skaiw
1028260684Skaiw	case SIMPLE_HASH('r', 'S'):
1029260684Skaiw		/* operator >>= */
1030260684Skaiw		ddata->cur += 2;
1031260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ">>=", 3));
1032260684Skaiw
1033260684Skaiw	case SIMPLE_HASH('r', 'z'):
1034260684Skaiw		/* operator sizeof */
1035260684Skaiw		ddata->cur += 2;
1036260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
1037260684Skaiw
1038260684Skaiw	case SIMPLE_HASH('s', 'v'):
1039260684Skaiw		/* operator sizeof */
1040260684Skaiw		ddata->cur += 2;
1041260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
1042300311Semaste	}
1043260684Skaiw
1044260684Skaiw	switch (*ddata->cur) {
1045260684Skaiw	case 'L':
1046260684Skaiw		return (cpp_demangle_read_expr_primary(ddata));
1047260684Skaiw	case 'T':
1048260684Skaiw		return (cpp_demangle_read_tmpl_param(ddata));
1049300311Semaste	}
1050260684Skaiw
1051260684Skaiw	return (0);
1052260684Skaiw}
1053260684Skaiw
1054260684Skaiwstatic int
1055283616Semastecpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str)
1056283616Semaste{
1057283616Semaste	struct vector_str *output;
1058283616Semaste	size_t i, p_idx, idx, exp_len;
1059283616Semaste	char *exp;
1060283616Semaste
1061283616Semaste	output = ddata->push_head > 0 ? &ddata->output_tmp :
1062283616Semaste	    &ddata->output;
1063283616Semaste
1064283616Semaste	p_idx = output->size;
1065283616Semaste
1066283616Semaste	if (!cpp_demangle_read_expression(ddata))
1067283616Semaste		return (0);
1068283616Semaste
1069283616Semaste	if ((exp = vector_str_substr(output, p_idx, output->size - 1,
1070283616Semaste	    &exp_len)) == NULL)
1071283616Semaste		return (0);
1072283616Semaste
1073283616Semaste	idx = output->size;
1074283616Semaste	for (i = p_idx; i < idx; ++i) {
1075283616Semaste		if (!vector_str_pop(output)) {
1076283616Semaste			free(exp);
1077283616Semaste			return (0);
1078283616Semaste		}
1079283616Semaste	}
1080283616Semaste
1081283616Semaste	*str = exp;
1082283616Semaste
1083283616Semaste	return (1);
1084283616Semaste}
1085283616Semaste
1086283616Semastestatic int
1087260684Skaiwcpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
1088260684Skaiw    const char *name, size_t len)
1089260684Skaiw{
1090260684Skaiw
1091260684Skaiw	if (ddata == NULL || name == NULL || len == 0)
1092260684Skaiw		return (0);
1093260684Skaiw	if (!cpp_demangle_read_expression(ddata))
1094260684Skaiw		return (0);
1095260684Skaiw	if (!cpp_demangle_push_str(ddata, name, len))
1096260684Skaiw		return (0);
1097260684Skaiw
1098260684Skaiw	return (cpp_demangle_read_expression(ddata));
1099260684Skaiw}
1100260684Skaiw
1101260684Skaiwstatic int
1102260684Skaiwcpp_demangle_read_expression_unary(struct cpp_demangle_data *ddata,
1103260684Skaiw    const char *name, size_t len)
1104260684Skaiw{
1105260684Skaiw
1106260684Skaiw	if (ddata == NULL || name == NULL || len == 0)
1107260684Skaiw		return (0);
1108260684Skaiw	if (!cpp_demangle_read_expression(ddata))
1109260684Skaiw		return (0);
1110260684Skaiw
1111260684Skaiw	return (cpp_demangle_push_str(ddata, name, len));
1112260684Skaiw}
1113260684Skaiw
1114260684Skaiwstatic int
1115260684Skaiwcpp_demangle_read_expression_trinary(struct cpp_demangle_data *ddata,
1116260684Skaiw    const char *name1, size_t len1, const char *name2, size_t len2)
1117260684Skaiw{
1118260684Skaiw
1119260684Skaiw	if (ddata == NULL || name1 == NULL || len1 == 0 || name2 == NULL ||
1120260684Skaiw	    len2 == 0)
1121260684Skaiw		return (0);
1122260684Skaiw
1123260684Skaiw	if (!cpp_demangle_read_expression(ddata))
1124260684Skaiw		return (0);
1125260684Skaiw	if (!cpp_demangle_push_str(ddata, name1, len1))
1126260684Skaiw		return (0);
1127260684Skaiw	if (!cpp_demangle_read_expression(ddata))
1128260684Skaiw		return (0);
1129260684Skaiw	if (!cpp_demangle_push_str(ddata, name2, len2))
1130260684Skaiw		return (0);
1131260684Skaiw
1132260684Skaiw	return (cpp_demangle_read_expression(ddata));
1133260684Skaiw}
1134260684Skaiw
1135260684Skaiwstatic int
1136260684Skaiwcpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
1137260684Skaiw    struct vector_type_qualifier *v)
1138260684Skaiw{
1139260684Skaiw	size_t class_type_size, class_type_len, limit;
1140260684Skaiw	const char *class_type;
1141260684Skaiw
1142260684Skaiw	if (ddata == NULL || *ddata->cur != 'F' || v == NULL)
1143260684Skaiw		return (0);
1144260684Skaiw
1145260684Skaiw	++ddata->cur;
1146260684Skaiw	if (*ddata->cur == 'Y') {
1147260684Skaiw		if (ext_c != NULL)
1148260684Skaiw			*ext_c = 1;
1149260684Skaiw		++ddata->cur;
1150260684Skaiw	}
1151260684Skaiw	if (!cpp_demangle_read_type(ddata, 0))
1152260684Skaiw		return (0);
1153260684Skaiw	if (*ddata->cur != 'E') {
1154260684Skaiw		if (!cpp_demangle_push_str(ddata, "(", 1))
1155260684Skaiw			return (0);
1156260684Skaiw		if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM)) {
1157260684Skaiw			if ((class_type_size = ddata->class_type.size) == 0)
1158260684Skaiw				return (0);
1159260684Skaiw			class_type =
1160260684Skaiw			    ddata->class_type.container[class_type_size - 1];
1161260684Skaiw			if (class_type == NULL)
1162260684Skaiw				return (0);
1163260684Skaiw			if ((class_type_len = strlen(class_type)) == 0)
1164260684Skaiw				return (0);
1165260684Skaiw			if (!cpp_demangle_push_str(ddata, class_type,
1166260684Skaiw			    class_type_len))
1167260684Skaiw				return (0);
1168260684Skaiw			if (!cpp_demangle_push_str(ddata, "::*", 3))
1169260684Skaiw				return (0);
1170260684Skaiw			++ddata->func_type;
1171260684Skaiw		} else {
1172260684Skaiw			if (!cpp_demangle_push_type_qualifier(ddata, v,
1173260684Skaiw			    (const char *) NULL))
1174260684Skaiw				return (0);
1175260684Skaiw			vector_type_qualifier_dest(v);
1176260684Skaiw			if (!vector_type_qualifier_init(v))
1177260684Skaiw				return (0);
1178260684Skaiw		}
1179260684Skaiw
1180260684Skaiw		if (!cpp_demangle_push_str(ddata, ")(", 2))
1181260684Skaiw			return (0);
1182260684Skaiw
1183260684Skaiw		limit = 0;
1184260684Skaiw		for (;;) {
1185260684Skaiw			if (!cpp_demangle_read_type(ddata, 0))
1186260684Skaiw				return (0);
1187260684Skaiw			if (*ddata->cur == 'E')
1188260684Skaiw				break;
1189260684Skaiw			if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1190260684Skaiw				return (0);
1191260684Skaiw		}
1192260684Skaiw
1193260684Skaiw		if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM) == 1) {
1194260684Skaiw			if (!cpp_demangle_push_type_qualifier(ddata, v,
1195260684Skaiw			    (const char *) NULL))
1196260684Skaiw				return (0);
1197260684Skaiw			vector_type_qualifier_dest(v);
1198260684Skaiw			if (!vector_type_qualifier_init(v))
1199260684Skaiw				return (0);
1200260684Skaiw		}
1201260684Skaiw
1202260684Skaiw		if (!cpp_demangle_push_str(ddata, ")", 1))
1203260684Skaiw			return (0);
1204260684Skaiw	}
1205260684Skaiw
1206260684Skaiw	++ddata->cur;
1207260684Skaiw
1208260684Skaiw	return (1);
1209260684Skaiw}
1210260684Skaiw
1211260684Skaiw/* read encoding, encoding are function name, data name, special-name */
1212260684Skaiwstatic int
1213260684Skaiwcpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
1214260684Skaiw{
1215283616Semaste	char *name, *type, *num_str;
1216283616Semaste	long offset;
1217283616Semaste	int rtn;
1218260684Skaiw
1219260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1220260684Skaiw		return (0);
1221260684Skaiw
1222260684Skaiw	/* special name */
1223260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
1224283616Semaste	case SIMPLE_HASH('G', 'A'):
1225283616Semaste		if (!cpp_demangle_push_str(ddata, "hidden alias for ", 17))
1226283616Semaste			return (0);
1227283616Semaste		ddata->cur += 2;
1228283616Semaste		if (*ddata->cur == '\0')
1229283616Semaste			return (0);
1230283616Semaste		return (cpp_demangle_read_encoding(ddata));
1231283616Semaste
1232283616Semaste	case SIMPLE_HASH('G', 'R'):
1233283616Semaste		if (!cpp_demangle_push_str(ddata, "reference temporary #", 21))
1234283616Semaste			return (0);
1235283616Semaste		ddata->cur += 2;
1236283616Semaste		if (*ddata->cur == '\0')
1237283616Semaste			return (0);
1238283616Semaste		if (!cpp_demangle_read_name_flat(ddata, &name))
1239283616Semaste			return (0);
1240283616Semaste		rtn = 0;
1241283616Semaste		if (!cpp_demangle_read_number_as_string(ddata, &num_str))
1242283616Semaste			goto clean1;
1243283616Semaste		if (!cpp_demangle_push_str(ddata, num_str, strlen(num_str)))
1244283616Semaste			goto clean2;
1245283616Semaste		if (!cpp_demangle_push_str(ddata, " for ", 5))
1246283616Semaste			goto clean2;
1247283616Semaste		if (!cpp_demangle_push_str(ddata, name, strlen(name)))
1248283616Semaste			goto clean2;
1249283616Semaste		rtn = 1;
1250283616Semaste	clean2:
1251283616Semaste		free(num_str);
1252283616Semaste	clean1:
1253283616Semaste		free(name);
1254283616Semaste		return (rtn);
1255283616Semaste
1256283616Semaste	case SIMPLE_HASH('G', 'T'):
1257283616Semaste		ddata->cur += 2;
1258283616Semaste		if (*ddata->cur == '\0')
1259283616Semaste			return (0);
1260283616Semaste		switch (*ddata->cur) {
1261283616Semaste		case 'n':
1262283616Semaste			if (!cpp_demangle_push_str(ddata,
1263283616Semaste			    "non-transaction clone for ", 26))
1264283616Semaste				return (0);
1265295577Semaste			break;
1266283616Semaste		case 't':
1267283616Semaste		default:
1268283616Semaste			if (!cpp_demangle_push_str(ddata,
1269283616Semaste			    "transaction clone for ", 22))
1270283616Semaste				return (0);
1271295577Semaste			break;
1272283616Semaste		}
1273283616Semaste		++ddata->cur;
1274283616Semaste		return (cpp_demangle_read_encoding(ddata));
1275283616Semaste
1276260684Skaiw	case SIMPLE_HASH('G', 'V'):
1277260684Skaiw		/* sentry object for 1 time init */
1278260684Skaiw		if (!cpp_demangle_push_str(ddata, "guard variable for ", 20))
1279260684Skaiw			return (0);
1280260684Skaiw		ddata->cur += 2;
1281260684Skaiw		break;
1282260684Skaiw
1283260684Skaiw	case SIMPLE_HASH('T', 'c'):
1284260684Skaiw		/* virtual function covariant override thunk */
1285260684Skaiw		if (!cpp_demangle_push_str(ddata,
1286260684Skaiw		    "virtual function covariant override ", 36))
1287260684Skaiw			return (0);
1288260684Skaiw		ddata->cur += 2;
1289260684Skaiw		if (*ddata->cur == '\0')
1290260684Skaiw			return (0);
1291260684Skaiw		if (!cpp_demangle_read_offset(ddata))
1292260684Skaiw			return (0);
1293260684Skaiw		if (!cpp_demangle_read_offset(ddata))
1294260684Skaiw			return (0);
1295260684Skaiw		return (cpp_demangle_read_encoding(ddata));
1296260684Skaiw
1297283616Semaste	case SIMPLE_HASH('T', 'C'):
1298283616Semaste		/* construction vtable */
1299283616Semaste		if (!cpp_demangle_push_str(ddata, "construction vtable for ",
1300283616Semaste		    24))
1301283616Semaste			return (0);
1302283616Semaste		ddata->cur += 2;
1303283616Semaste		if (*ddata->cur == '\0')
1304283616Semaste			return (0);
1305283616Semaste		if (!cpp_demangle_read_type_flat(ddata, &type))
1306283616Semaste			return (0);
1307283616Semaste		rtn = 0;
1308283616Semaste		if (!cpp_demangle_read_number(ddata, &offset))
1309283616Semaste			goto clean3;
1310283616Semaste		if (*ddata->cur++ != '_')
1311283616Semaste			goto clean3;
1312283616Semaste		if (!cpp_demangle_read_type(ddata, 0))
1313283616Semaste			goto clean3;
1314283616Semaste		if (!cpp_demangle_push_str(ddata, "-in-", 4))
1315283616Semaste			goto clean3;
1316283616Semaste		if (!cpp_demangle_push_str(ddata, type, strlen(type)))
1317283616Semaste			goto clean3;
1318283616Semaste		rtn = 1;
1319283616Semaste	clean3:
1320283616Semaste		free(type);
1321283616Semaste		return (rtn);
1322283616Semaste
1323260684Skaiw	case SIMPLE_HASH('T', 'D'):
1324260684Skaiw		/* typeinfo common proxy */
1325260684Skaiw		break;
1326260684Skaiw
1327283616Semaste	case SIMPLE_HASH('T', 'F'):
1328283616Semaste		/* typeinfo fn */
1329283616Semaste		if (!cpp_demangle_push_str(ddata, "typeinfo fn for ", 16))
1330283616Semaste			return (0);
1331283616Semaste		ddata->cur += 2;
1332283616Semaste		if (*ddata->cur == '\0')
1333283616Semaste			return (0);
1334283616Semaste		return (cpp_demangle_read_type(ddata, 0));
1335283616Semaste
1336260684Skaiw	case SIMPLE_HASH('T', 'h'):
1337260684Skaiw		/* virtual function non-virtual override thunk */
1338283616Semaste		if (!cpp_demangle_push_str(ddata,
1339283616Semaste		    "virtual function non-virtual override ", 38))
1340260684Skaiw			return (0);
1341260684Skaiw		ddata->cur += 2;
1342260684Skaiw		if (*ddata->cur == '\0')
1343260684Skaiw			return (0);
1344260684Skaiw		if (!cpp_demangle_read_nv_offset(ddata))
1345260684Skaiw			return (0);
1346260684Skaiw		return (cpp_demangle_read_encoding(ddata));
1347260684Skaiw
1348283616Semaste	case SIMPLE_HASH('T', 'H'):
1349283616Semaste		/* TLS init function */
1350283616Semaste		if (!cpp_demangle_push_str(ddata, "TLS init function for ",
1351283616Semaste		    22))
1352283616Semaste			return (0);
1353283616Semaste		ddata->cur += 2;
1354283616Semaste		if (*ddata->cur == '\0')
1355283616Semaste			return (0);
1356283616Semaste		break;
1357283616Semaste
1358260684Skaiw	case SIMPLE_HASH('T', 'I'):
1359260684Skaiw		/* typeinfo structure */
1360283616Semaste		if (!cpp_demangle_push_str(ddata, "typeinfo for ", 13))
1361283616Semaste			return (0);
1362283616Semaste		ddata->cur += 2;
1363283616Semaste		if (*ddata->cur == '\0')
1364283616Semaste			return (0);
1365283616Semaste		return (cpp_demangle_read_type(ddata, 0));
1366283616Semaste
1367283616Semaste	case SIMPLE_HASH('T', 'J'):
1368283616Semaste		/* java class */
1369283616Semaste		if (!cpp_demangle_push_str(ddata, "java Class for ", 15))
1370283616Semaste			return (0);
1371283616Semaste		ddata->cur += 2;
1372283616Semaste		if (*ddata->cur == '\0')
1373283616Semaste			return (0);
1374283616Semaste		return (cpp_demangle_read_type(ddata, 0));
1375283616Semaste
1376260684Skaiw	case SIMPLE_HASH('T', 'S'):
1377260684Skaiw		/* RTTI name (NTBS) */
1378283616Semaste		if (!cpp_demangle_push_str(ddata, "typeinfo name for ", 18))
1379260684Skaiw			return (0);
1380260684Skaiw		ddata->cur += 2;
1381260684Skaiw		if (*ddata->cur == '\0')
1382260684Skaiw			return (0);
1383283616Semaste		return (cpp_demangle_read_type(ddata, 0));
1384260684Skaiw
1385260684Skaiw	case SIMPLE_HASH('T', 'T'):
1386260684Skaiw		/* VTT table */
1387260684Skaiw		if (!cpp_demangle_push_str(ddata, "VTT for ", 8))
1388260684Skaiw			return (0);
1389260684Skaiw		ddata->cur += 2;
1390283616Semaste		if (*ddata->cur == '\0')
1391283616Semaste			return (0);
1392283616Semaste		return (cpp_demangle_read_type(ddata, 0));
1393260684Skaiw
1394260684Skaiw	case SIMPLE_HASH('T', 'v'):
1395260684Skaiw		/* virtual function virtual override thunk */
1396260684Skaiw		if (!cpp_demangle_push_str(ddata,
1397260684Skaiw		    "virtual function virtual override ", 34))
1398260684Skaiw			return (0);
1399260684Skaiw		ddata->cur += 2;
1400260684Skaiw		if (*ddata->cur == '\0')
1401260684Skaiw			return (0);
1402260684Skaiw		if (!cpp_demangle_read_v_offset(ddata))
1403260684Skaiw			return (0);
1404260684Skaiw		return (cpp_demangle_read_encoding(ddata));
1405260684Skaiw
1406260684Skaiw	case SIMPLE_HASH('T', 'V'):
1407260684Skaiw		/* virtual table */
1408260684Skaiw		if (!cpp_demangle_push_str(ddata, "vtable for ", 12))
1409260684Skaiw			return (0);
1410260684Skaiw		ddata->cur += 2;
1411260684Skaiw		if (*ddata->cur == '\0')
1412260684Skaiw			return (0);
1413283616Semaste		return (cpp_demangle_read_type(ddata, 0));
1414283616Semaste
1415283616Semaste	case SIMPLE_HASH('T', 'W'):
1416283616Semaste		/* TLS wrapper function */
1417283616Semaste		if (!cpp_demangle_push_str(ddata, "TLS wrapper function for ",
1418283616Semaste		    25))
1419283616Semaste			return (0);
1420283616Semaste		ddata->cur += 2;
1421283616Semaste		if (*ddata->cur == '\0')
1422283616Semaste			return (0);
1423283616Semaste		break;
1424300311Semaste	}
1425260684Skaiw
1426260684Skaiw	return (cpp_demangle_read_name(ddata));
1427260684Skaiw}
1428260684Skaiw
1429260684Skaiwstatic int
1430260684Skaiwcpp_demangle_read_local_name(struct cpp_demangle_data *ddata)
1431260684Skaiw{
1432260684Skaiw	size_t limit;
1433260684Skaiw
1434260684Skaiw	if (ddata == NULL)
1435260684Skaiw		return (0);
1436260684Skaiw	if (*(++ddata->cur) == '\0')
1437260684Skaiw		return (0);
1438260684Skaiw	if (!cpp_demangle_read_encoding(ddata))
1439260684Skaiw		return (0);
1440260684Skaiw
1441260684Skaiw	limit = 0;
1442260684Skaiw	for (;;) {
1443260684Skaiw		if (!cpp_demangle_read_type(ddata, 1))
1444260684Skaiw			return (0);
1445260684Skaiw		if (*ddata->cur == 'E')
1446260684Skaiw			break;
1447260684Skaiw		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1448260684Skaiw			return (0);
1449260684Skaiw	}
1450260684Skaiw	if (*(++ddata->cur) == '\0')
1451260684Skaiw		return (0);
1452260684Skaiw	if (ddata->paren == true) {
1453260684Skaiw		if (!cpp_demangle_push_str(ddata, ")", 1))
1454260684Skaiw			return (0);
1455260684Skaiw		ddata->paren = false;
1456260684Skaiw	}
1457260684Skaiw	if (*ddata->cur == 's')
1458260684Skaiw		++ddata->cur;
1459260684Skaiw	else {
1460260684Skaiw		if (!cpp_demangle_push_str(ddata, "::", 2))
1461260684Skaiw			return (0);
1462260684Skaiw		if (!cpp_demangle_read_name(ddata))
1463260684Skaiw			return (0);
1464260684Skaiw	}
1465260684Skaiw	if (*ddata->cur == '_') {
1466260684Skaiw		++ddata->cur;
1467260684Skaiw		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
1468260684Skaiw			++ddata->cur;
1469260684Skaiw	}
1470260684Skaiw
1471260684Skaiw	return (1);
1472260684Skaiw}
1473260684Skaiw
1474260684Skaiwstatic int
1475260684Skaiwcpp_demangle_read_name(struct cpp_demangle_data *ddata)
1476260684Skaiw{
1477260684Skaiw	struct vector_str *output, v;
1478260684Skaiw	size_t p_idx, subst_str_len;
1479260684Skaiw	int rtn;
1480260684Skaiw	char *subst_str;
1481260684Skaiw
1482260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1483260684Skaiw		return (0);
1484260684Skaiw
1485283616Semaste	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
1486260684Skaiw
1487260684Skaiw	subst_str = NULL;
1488260684Skaiw
1489260684Skaiw	switch (*ddata->cur) {
1490260684Skaiw	case 'S':
1491260684Skaiw		return (cpp_demangle_read_subst(ddata));
1492260684Skaiw	case 'N':
1493260684Skaiw		return (cpp_demangle_read_nested_name(ddata));
1494260684Skaiw	case 'Z':
1495260684Skaiw		return (cpp_demangle_read_local_name(ddata));
1496300311Semaste	}
1497260684Skaiw
1498260684Skaiw	if (!vector_str_init(&v))
1499260684Skaiw		return (0);
1500260684Skaiw
1501260684Skaiw	p_idx = output->size;
1502260684Skaiw	rtn = 0;
1503260684Skaiw	if (!cpp_demangle_read_uqname(ddata))
1504260684Skaiw		goto clean;
1505260684Skaiw	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
1506260684Skaiw	    &subst_str_len)) == NULL)
1507260684Skaiw		goto clean;
1508260684Skaiw	if (subst_str_len > 8 && strstr(subst_str, "operator") != NULL) {
1509260684Skaiw		rtn = 1;
1510260684Skaiw		goto clean;
1511260684Skaiw	}
1512260684Skaiw	if (!vector_str_push(&v, subst_str, subst_str_len))
1513260684Skaiw		goto clean;
1514260684Skaiw	if (!cpp_demangle_push_subst_v(ddata, &v))
1515260684Skaiw		goto clean;
1516260684Skaiw
1517260684Skaiw	if (*ddata->cur == 'I') {
1518260684Skaiw		p_idx = output->size;
1519260684Skaiw		if (!cpp_demangle_read_tmpl_args(ddata))
1520260684Skaiw			goto clean;
1521260684Skaiw		free(subst_str);
1522260684Skaiw		if ((subst_str = vector_str_substr(output, p_idx,
1523260684Skaiw		    output->size - 1, &subst_str_len)) == NULL)
1524260684Skaiw			goto clean;
1525260684Skaiw		if (!vector_str_push(&v, subst_str, subst_str_len))
1526260684Skaiw			goto clean;
1527260684Skaiw		if (!cpp_demangle_push_subst_v(ddata, &v))
1528260684Skaiw			goto clean;
1529260684Skaiw	}
1530260684Skaiw
1531260684Skaiw	rtn = 1;
1532260684Skaiw
1533260684Skaiwclean:
1534260684Skaiw	free(subst_str);
1535260684Skaiw	vector_str_dest(&v);
1536260684Skaiw
1537260684Skaiw	return (rtn);
1538260684Skaiw}
1539260684Skaiw
1540260684Skaiwstatic int
1541283616Semastecpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str)
1542283616Semaste{
1543283616Semaste	struct vector_str *output;
1544283616Semaste	size_t i, p_idx, idx, name_len;
1545283616Semaste	char *name;
1546283616Semaste
1547283616Semaste	output = ddata->push_head > 0 ? &ddata->output_tmp :
1548283616Semaste	    &ddata->output;
1549283616Semaste
1550283616Semaste	p_idx = output->size;
1551283616Semaste
1552283616Semaste	if (!cpp_demangle_read_name(ddata))
1553283616Semaste		return (0);
1554283616Semaste
1555283616Semaste	if ((name = vector_str_substr(output, p_idx, output->size - 1,
1556283616Semaste	    &name_len)) == NULL)
1557283616Semaste		return (0);
1558283616Semaste
1559283616Semaste	idx = output->size;
1560283616Semaste	for (i = p_idx; i < idx; ++i) {
1561283616Semaste		if (!vector_str_pop(output)) {
1562283616Semaste			free(name);
1563283616Semaste			return (0);
1564283616Semaste		}
1565283616Semaste	}
1566283616Semaste
1567283616Semaste	*str = name;
1568283616Semaste
1569283616Semaste	return (1);
1570283616Semaste}
1571283616Semaste
1572283616Semastestatic int
1573260684Skaiwcpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
1574260684Skaiw{
1575260684Skaiw	struct vector_str *output, v;
1576260684Skaiw	size_t limit, p_idx, subst_str_len;
1577260684Skaiw	int rtn;
1578260684Skaiw	char *subst_str;
1579260684Skaiw
1580260684Skaiw	if (ddata == NULL || *ddata->cur != 'N')
1581260684Skaiw		return (0);
1582260684Skaiw	if (*(++ddata->cur) == '\0')
1583260684Skaiw		return (0);
1584260684Skaiw
1585260684Skaiw	while (*ddata->cur == 'r' || *ddata->cur == 'V' ||
1586260684Skaiw	    *ddata->cur == 'K') {
1587260684Skaiw		switch (*ddata->cur) {
1588260684Skaiw		case 'r':
1589260684Skaiw			ddata->mem_rst = true;
1590260684Skaiw			break;
1591260684Skaiw		case 'V':
1592260684Skaiw			ddata->mem_vat = true;
1593260684Skaiw			break;
1594260684Skaiw		case 'K':
1595260684Skaiw			ddata->mem_cst = true;
1596260684Skaiw			break;
1597300311Semaste		}
1598260684Skaiw		++ddata->cur;
1599260684Skaiw	}
1600260684Skaiw
1601283616Semaste	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
1602260684Skaiw	if (!vector_str_init(&v))
1603260684Skaiw		return (0);
1604260684Skaiw
1605260684Skaiw	rtn = 0;
1606260684Skaiw	limit = 0;
1607260684Skaiw	for (;;) {
1608260684Skaiw		p_idx = output->size;
1609260684Skaiw		switch (*ddata->cur) {
1610260684Skaiw		case 'I':
1611260684Skaiw			if (!cpp_demangle_read_tmpl_args(ddata))
1612260684Skaiw				goto clean;
1613260684Skaiw			break;
1614260684Skaiw		case 'S':
1615260684Skaiw			if (!cpp_demangle_read_subst(ddata))
1616260684Skaiw				goto clean;
1617260684Skaiw			break;
1618260684Skaiw		case 'T':
1619260684Skaiw			if (!cpp_demangle_read_tmpl_param(ddata))
1620260684Skaiw				goto clean;
1621260684Skaiw			break;
1622260684Skaiw		default:
1623260684Skaiw			if (!cpp_demangle_read_uqname(ddata))
1624260684Skaiw				goto clean;
1625300311Semaste		}
1626260684Skaiw
1627260684Skaiw		if ((subst_str = vector_str_substr(output, p_idx,
1628260684Skaiw		    output->size - 1, &subst_str_len)) == NULL)
1629260684Skaiw			goto clean;
1630260684Skaiw		if (!vector_str_push(&v, subst_str, subst_str_len)) {
1631260684Skaiw			free(subst_str);
1632260684Skaiw			goto clean;
1633260684Skaiw		}
1634260684Skaiw		free(subst_str);
1635260684Skaiw
1636260684Skaiw		if (!cpp_demangle_push_subst_v(ddata, &v))
1637260684Skaiw			goto clean;
1638260684Skaiw		if (*ddata->cur == 'E')
1639260684Skaiw			break;
1640260684Skaiw		else if (*ddata->cur != 'I' &&
1641260684Skaiw		    *ddata->cur != 'C' && *ddata->cur != 'D') {
1642260684Skaiw			if (!cpp_demangle_push_str(ddata, "::", 2))
1643260684Skaiw				goto clean;
1644260684Skaiw			if (!vector_str_push(&v, "::", 2))
1645260684Skaiw				goto clean;
1646260684Skaiw		}
1647260684Skaiw		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1648260684Skaiw			goto clean;
1649260684Skaiw	}
1650260684Skaiw
1651260684Skaiw	++ddata->cur;
1652260684Skaiw	rtn = 1;
1653260684Skaiw
1654260684Skaiwclean:
1655260684Skaiw	vector_str_dest(&v);
1656260684Skaiw
1657260684Skaiw	return (rtn);
1658260684Skaiw}
1659260684Skaiw
1660260684Skaiw/*
1661260684Skaiw * read number
1662260684Skaiw * number ::= [n] <decimal>
1663260684Skaiw */
1664260684Skaiwstatic int
1665260684Skaiwcpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
1666260684Skaiw{
1667260684Skaiw	long len, negative_factor;
1668260684Skaiw
1669260684Skaiw	if (ddata == NULL || rtn == NULL)
1670260684Skaiw		return (0);
1671260684Skaiw
1672260684Skaiw	negative_factor = 1;
1673260684Skaiw	if (*ddata->cur == 'n') {
1674260684Skaiw		negative_factor = -1;
1675260684Skaiw
1676260684Skaiw		++ddata->cur;
1677260684Skaiw	}
1678260684Skaiw	if (ELFTC_ISDIGIT(*ddata->cur) == 0)
1679260684Skaiw		return (0);
1680260684Skaiw
1681260684Skaiw	errno = 0;
1682260684Skaiw	if ((len = strtol(ddata->cur, (char **) NULL, 10)) == 0 &&
1683260684Skaiw	    errno != 0)
1684260684Skaiw		return (0);
1685260684Skaiw
1686260684Skaiw	while (ELFTC_ISDIGIT(*ddata->cur) != 0)
1687260684Skaiw		++ddata->cur;
1688260684Skaiw
1689260684Skaiw	assert(len >= 0);
1690260684Skaiw	assert(negative_factor == 1 || negative_factor == -1);
1691260684Skaiw
1692260684Skaiw	*rtn = len * negative_factor;
1693260684Skaiw
1694260684Skaiw	return (1);
1695260684Skaiw}
1696260684Skaiw
1697260684Skaiwstatic int
1698283616Semastecpp_demangle_read_number_as_string(struct cpp_demangle_data *ddata, char **str)
1699283616Semaste{
1700283616Semaste	long n;
1701283616Semaste
1702283616Semaste	if (!cpp_demangle_read_number(ddata, &n)) {
1703283616Semaste		*str = NULL;
1704283616Semaste		return (0);
1705283616Semaste	}
1706283616Semaste
1707283616Semaste	if (asprintf(str, "%ld", n) < 0) {
1708283616Semaste		*str = NULL;
1709283616Semaste		return (0);
1710283616Semaste	}
1711283616Semaste
1712283616Semaste	return (1);
1713283616Semaste}
1714283616Semaste
1715283616Semastestatic int
1716260684Skaiwcpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
1717260684Skaiw{
1718260684Skaiw
1719260684Skaiw	if (ddata == NULL)
1720260684Skaiw		return (0);
1721260684Skaiw
1722260684Skaiw	if (!cpp_demangle_push_str(ddata, "offset : ", 9))
1723260684Skaiw		return (0);
1724260684Skaiw
1725260684Skaiw	return (cpp_demangle_read_offset_number(ddata));
1726260684Skaiw}
1727260684Skaiw
1728260684Skaiw/* read offset, offset are nv-offset, v-offset */
1729260684Skaiwstatic int
1730260684Skaiwcpp_demangle_read_offset(struct cpp_demangle_data *ddata)
1731260684Skaiw{
1732260684Skaiw
1733260684Skaiw	if (ddata == NULL)
1734260684Skaiw		return (0);
1735260684Skaiw
1736260684Skaiw	if (*ddata->cur == 'h') {
1737260684Skaiw		++ddata->cur;
1738260684Skaiw		return (cpp_demangle_read_nv_offset(ddata));
1739260684Skaiw	} else if (*ddata->cur == 'v') {
1740260684Skaiw		++ddata->cur;
1741260684Skaiw		return (cpp_demangle_read_v_offset(ddata));
1742260684Skaiw	}
1743260684Skaiw
1744260684Skaiw	return (0);
1745260684Skaiw}
1746260684Skaiw
1747260684Skaiwstatic int
1748260684Skaiwcpp_demangle_read_offset_number(struct cpp_demangle_data *ddata)
1749260684Skaiw{
1750260684Skaiw	bool negative;
1751260684Skaiw	const char *start;
1752260684Skaiw
1753260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1754260684Skaiw		return (0);
1755260684Skaiw
1756260684Skaiw	/* offset could be negative */
1757260684Skaiw	if (*ddata->cur == 'n') {
1758260684Skaiw		negative = true;
1759260684Skaiw		start = ddata->cur + 1;
1760260684Skaiw	} else {
1761260684Skaiw		negative = false;
1762260684Skaiw		start = ddata->cur;
1763260684Skaiw	}
1764260684Skaiw
1765260684Skaiw	while (*ddata->cur != '_')
1766260684Skaiw		++ddata->cur;
1767260684Skaiw
1768260684Skaiw	if (negative && !cpp_demangle_push_str(ddata, "-", 1))
1769260684Skaiw		return (0);
1770260684Skaiw
1771260684Skaiw	assert(start != NULL);
1772260684Skaiw
1773260684Skaiw	if (!cpp_demangle_push_str(ddata, start, ddata->cur - start))
1774260684Skaiw		return (0);
1775260684Skaiw	if (!cpp_demangle_push_str(ddata, " ", 1))
1776260684Skaiw		return (0);
1777260684Skaiw
1778260684Skaiw	++ddata->cur;
1779260684Skaiw
1780260684Skaiw	return (1);
1781260684Skaiw}
1782260684Skaiw
1783260684Skaiwstatic int
1784260684Skaiwcpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata)
1785260684Skaiw{
1786260684Skaiw	size_t class_type_len, i, idx, p_idx;
1787260684Skaiw	int p_func_type, rtn;
1788260684Skaiw	char *class_type;
1789260684Skaiw
1790260684Skaiw	if (ddata == NULL || *ddata->cur != 'M' || *(++ddata->cur) == '\0')
1791260684Skaiw		return (0);
1792260684Skaiw
1793260684Skaiw	p_idx = ddata->output.size;
1794260684Skaiw	if (!cpp_demangle_read_type(ddata, 0))
1795260684Skaiw		return (0);
1796260684Skaiw
1797260684Skaiw	if ((class_type = vector_str_substr(&ddata->output, p_idx,
1798260684Skaiw	    ddata->output.size - 1, &class_type_len)) == NULL)
1799260684Skaiw		return (0);
1800260684Skaiw
1801260684Skaiw	rtn = 0;
1802260684Skaiw	idx = ddata->output.size;
1803260684Skaiw	for (i = p_idx; i < idx; ++i)
1804260684Skaiw		if (!vector_str_pop(&ddata->output))
1805260684Skaiw			goto clean1;
1806260684Skaiw
1807260684Skaiw	if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM))
1808260684Skaiw		goto clean1;
1809260684Skaiw
1810260684Skaiw	if (!vector_str_push(&ddata->class_type, class_type, class_type_len))
1811260684Skaiw		goto clean2;
1812260684Skaiw
1813260684Skaiw	p_func_type = ddata->func_type;
1814260684Skaiw	if (!cpp_demangle_read_type(ddata, 0))
1815260684Skaiw		goto clean3;
1816260684Skaiw
1817260684Skaiw	if (p_func_type == ddata->func_type) {
1818260684Skaiw		if (!cpp_demangle_push_str(ddata, " ", 1))
1819260684Skaiw			goto clean3;
1820260684Skaiw		if (!cpp_demangle_push_str(ddata, class_type, class_type_len))
1821260684Skaiw			goto clean3;
1822260684Skaiw		if (!cpp_demangle_push_str(ddata, "::*", 3))
1823260684Skaiw			goto clean3;
1824260684Skaiw	}
1825260684Skaiw
1826260684Skaiw	rtn = 1;
1827260684Skaiwclean3:
1828260684Skaiw	if (!vector_str_pop(&ddata->class_type))
1829260684Skaiw		rtn = 0;
1830260684Skaiwclean2:
1831260684Skaiw	if (!vector_read_cmd_pop(&ddata->cmd))
1832260684Skaiw		rtn = 0;
1833260684Skaiwclean1:
1834260684Skaiw	free(class_type);
1835260684Skaiw
1836260684Skaiw	return (rtn);
1837260684Skaiw}
1838260684Skaiw
1839260684Skaiw/* read source-name, source-name is <len> <ID> */
1840260684Skaiwstatic int
1841260684Skaiwcpp_demangle_read_sname(struct cpp_demangle_data *ddata)
1842260684Skaiw{
1843260684Skaiw	long len;
1844283616Semaste	int err;
1845260684Skaiw
1846260684Skaiw	if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
1847283616Semaste	    len <= 0)
1848260684Skaiw		return (0);
1849260684Skaiw
1850283616Semaste	if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0))
1851283616Semaste		err = cpp_demangle_push_str(ddata, "(anonymous namespace)", 21);
1852283616Semaste	else
1853283616Semaste		err = cpp_demangle_push_str(ddata, ddata->cur, len);
1854283616Semaste
1855283616Semaste	if (err == 0)
1856283616Semaste		return (0);
1857283616Semaste
1858260684Skaiw	assert(ddata->output.size > 0);
1859260684Skaiw	if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == 0)
1860260684Skaiw		ddata->last_sname =
1861260684Skaiw		    ddata->output.container[ddata->output.size - 1];
1862260684Skaiw
1863260684Skaiw	ddata->cur += len;
1864260684Skaiw
1865260684Skaiw	return (1);
1866260684Skaiw}
1867260684Skaiw
1868260684Skaiwstatic int
1869260684Skaiwcpp_demangle_read_subst(struct cpp_demangle_data *ddata)
1870260684Skaiw{
1871260684Skaiw	long nth;
1872260684Skaiw
1873260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1874260684Skaiw		return (0);
1875260684Skaiw
1876260684Skaiw	/* abbreviations of the form Sx */
1877260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
1878260684Skaiw	case SIMPLE_HASH('S', 'a'):
1879260684Skaiw		/* std::allocator */
1880260684Skaiw		if (cpp_demangle_push_str(ddata, "std::allocator", 14) == 0)
1881260684Skaiw			return (0);
1882260684Skaiw		ddata->cur += 2;
1883260684Skaiw		if (*ddata->cur == 'I')
1884260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1885260684Skaiw			    "std::allocator", 14));
1886260684Skaiw		return (1);
1887260684Skaiw
1888260684Skaiw	case SIMPLE_HASH('S', 'b'):
1889260684Skaiw		/* std::basic_string */
1890260684Skaiw		if (!cpp_demangle_push_str(ddata, "std::basic_string", 17))
1891260684Skaiw			return (0);
1892260684Skaiw		ddata->cur += 2;
1893260684Skaiw		if (*ddata->cur == 'I')
1894260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1895260684Skaiw			    "std::basic_string", 17));
1896260684Skaiw		return (1);
1897260684Skaiw
1898260684Skaiw	case SIMPLE_HASH('S', 'd'):
1899260684Skaiw		/* std::basic_iostream<char, std::char_traits<char> > */
1900295577Semaste		if (!cpp_demangle_push_str(ddata, "std::basic_iostream", 19))
1901260684Skaiw			return (0);
1902295577Semaste		ddata->last_sname = "basic_iostream";
1903260684Skaiw		ddata->cur += 2;
1904260684Skaiw		if (*ddata->cur == 'I')
1905260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1906295577Semaste			    "std::basic_iostream", 19));
1907260684Skaiw		return (1);
1908260684Skaiw
1909260684Skaiw	case SIMPLE_HASH('S', 'i'):
1910260684Skaiw		/* std::basic_istream<char, std::char_traits<char> > */
1911295577Semaste		if (!cpp_demangle_push_str(ddata, "std::basic_istream", 18))
1912260684Skaiw			return (0);
1913295577Semaste		ddata->last_sname = "basic_istream";
1914260684Skaiw		ddata->cur += 2;
1915260684Skaiw		if (*ddata->cur == 'I')
1916260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1917295577Semaste			    "std::basic_istream", 18));
1918260684Skaiw		return (1);
1919260684Skaiw
1920260684Skaiw	case SIMPLE_HASH('S', 'o'):
1921260684Skaiw		/* std::basic_ostream<char, std::char_traits<char> > */
1922295577Semaste		if (!cpp_demangle_push_str(ddata, "std::basic_ostream", 18))
1923260684Skaiw			return (0);
1924295577Semaste		ddata->last_sname = "basic_ostream";
1925260684Skaiw		ddata->cur += 2;
1926260684Skaiw		if (*ddata->cur == 'I')
1927260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1928295577Semaste			    "std::basic_ostream", 18));
1929260684Skaiw		return (1);
1930260684Skaiw
1931260684Skaiw	case SIMPLE_HASH('S', 's'):
1932260684Skaiw		/*
1933260684Skaiw		 * std::basic_string<char, std::char_traits<char>,
1934260684Skaiw		 * std::allocator<char> >
1935260684Skaiw		 *
1936260684Skaiw		 * a.k.a std::string
1937260684Skaiw		 */
1938260684Skaiw		if (!cpp_demangle_push_str(ddata, "std::string", 11))
1939260684Skaiw			return (0);
1940260684Skaiw		ddata->last_sname = "string";
1941260684Skaiw		ddata->cur += 2;
1942260684Skaiw		if (*ddata->cur == 'I')
1943260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1944260684Skaiw			    "std::string", 11));
1945260684Skaiw		return (1);
1946260684Skaiw
1947260684Skaiw	case SIMPLE_HASH('S', 't'):
1948260684Skaiw		/* std:: */
1949260684Skaiw		return (cpp_demangle_read_subst_std(ddata));
1950300311Semaste	}
1951260684Skaiw
1952260684Skaiw	if (*(++ddata->cur) == '\0')
1953260684Skaiw		return (0);
1954260684Skaiw
1955260684Skaiw	/* substitution */
1956260684Skaiw	if (*ddata->cur == '_')
1957260684Skaiw		return (cpp_demangle_get_subst(ddata, 0));
1958260684Skaiw	else {
1959260684Skaiw		errno = 0;
1960260684Skaiw		/* substitution number is base 36 */
1961260684Skaiw		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
1962260684Skaiw		    errno != 0)
1963260684Skaiw			return (0);
1964260684Skaiw
1965260684Skaiw		/* first was '_', so increase one */
1966260684Skaiw		++nth;
1967260684Skaiw
1968260684Skaiw		while (*ddata->cur != '_')
1969260684Skaiw			++ddata->cur;
1970260684Skaiw
1971260684Skaiw		assert(nth > 0);
1972260684Skaiw
1973260684Skaiw		return (cpp_demangle_get_subst(ddata, nth));
1974260684Skaiw	}
1975260684Skaiw
1976260684Skaiw	/* NOTREACHED */
1977260684Skaiw	return (0);
1978260684Skaiw}
1979260684Skaiw
1980260684Skaiwstatic int
1981260684Skaiwcpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
1982260684Skaiw{
1983260684Skaiw	struct vector_str *output, v;
1984260684Skaiw	size_t p_idx, subst_str_len;
1985260684Skaiw	int rtn;
1986260684Skaiw	char *subst_str;
1987260684Skaiw
1988260684Skaiw	if (ddata == NULL)
1989260684Skaiw		return (0);
1990260684Skaiw
1991260684Skaiw	if (!vector_str_init(&v))
1992260684Skaiw		return (0);
1993260684Skaiw
1994260684Skaiw	subst_str = NULL;
1995260684Skaiw	rtn = 0;
1996260684Skaiw	if (!cpp_demangle_push_str(ddata, "std::", 5))
1997260684Skaiw		goto clean;
1998260684Skaiw
1999260684Skaiw	if (!vector_str_push(&v, "std::", 5))
2000260684Skaiw		goto clean;
2001260684Skaiw
2002260684Skaiw	ddata->cur += 2;
2003260684Skaiw
2004283616Semaste	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
2005260684Skaiw
2006260684Skaiw	p_idx = output->size;
2007260684Skaiw	if (!cpp_demangle_read_uqname(ddata))
2008260684Skaiw		goto clean;
2009260684Skaiw
2010260684Skaiw	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
2011260684Skaiw	    &subst_str_len)) == NULL)
2012260684Skaiw		goto clean;
2013260684Skaiw
2014260684Skaiw	if (!vector_str_push(&v, subst_str, subst_str_len))
2015260684Skaiw		goto clean;
2016260684Skaiw
2017260684Skaiw	if (!cpp_demangle_push_subst_v(ddata, &v))
2018260684Skaiw		goto clean;
2019260684Skaiw
2020260684Skaiw	if (*ddata->cur == 'I') {
2021260684Skaiw		p_idx = output->size;
2022260684Skaiw		if (!cpp_demangle_read_tmpl_args(ddata))
2023260684Skaiw			goto clean;
2024260684Skaiw		free(subst_str);
2025260684Skaiw		if ((subst_str = vector_str_substr(output, p_idx,
2026260684Skaiw		    output->size - 1, &subst_str_len)) == NULL)
2027260684Skaiw			goto clean;
2028260684Skaiw		if (!vector_str_push(&v, subst_str, subst_str_len))
2029260684Skaiw			goto clean;
2030260684Skaiw		if (!cpp_demangle_push_subst_v(ddata, &v))
2031260684Skaiw			goto clean;
2032260684Skaiw	}
2033260684Skaiw
2034260684Skaiw	rtn = 1;
2035260684Skaiwclean:
2036260684Skaiw	free(subst_str);
2037260684Skaiw	vector_str_dest(&v);
2038260684Skaiw
2039260684Skaiw	return (rtn);
2040260684Skaiw}
2041260684Skaiw
2042260684Skaiwstatic int
2043260684Skaiwcpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
2044260684Skaiw    const char *str, size_t len)
2045260684Skaiw{
2046260684Skaiw	struct vector_str *output;
2047260684Skaiw	size_t p_idx, substr_len;
2048260684Skaiw	int rtn;
2049260684Skaiw	char *subst_str, *substr;
2050260684Skaiw
2051260684Skaiw	if (ddata == NULL || str == NULL || len == 0)
2052260684Skaiw		return (0);
2053260684Skaiw
2054283616Semaste	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
2055260684Skaiw
2056260684Skaiw	p_idx = output->size;
2057260684Skaiw	substr = NULL;
2058260684Skaiw	subst_str = NULL;
2059260684Skaiw
2060260684Skaiw	if (!cpp_demangle_read_tmpl_args(ddata))
2061260684Skaiw		return (0);
2062260684Skaiw	if ((substr = vector_str_substr(output, p_idx, output->size - 1,
2063260684Skaiw	    &substr_len)) == NULL)
2064260684Skaiw		return (0);
2065260684Skaiw
2066260684Skaiw	rtn = 0;
2067260684Skaiw	if ((subst_str = malloc(sizeof(char) * (substr_len + len + 1))) ==
2068260684Skaiw	    NULL)
2069260684Skaiw		goto clean;
2070260684Skaiw
2071260684Skaiw	memcpy(subst_str, str, len);
2072260684Skaiw	memcpy(subst_str + len, substr, substr_len);
2073260684Skaiw	subst_str[substr_len + len] = '\0';
2074260684Skaiw
2075260684Skaiw	if (!cpp_demangle_push_subst(ddata, subst_str, substr_len + len))
2076260684Skaiw		goto clean;
2077260684Skaiw
2078260684Skaiw	rtn = 1;
2079260684Skaiwclean:
2080260684Skaiw	free(subst_str);
2081260684Skaiw	free(substr);
2082260684Skaiw
2083260684Skaiw	return (rtn);
2084260684Skaiw}
2085260684Skaiw
2086260684Skaiwstatic int
2087260684Skaiwcpp_demangle_read_tmpl_arg(struct cpp_demangle_data *ddata)
2088260684Skaiw{
2089260684Skaiw
2090260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
2091260684Skaiw		return (0);
2092260684Skaiw
2093260684Skaiw	switch (*ddata->cur) {
2094260684Skaiw	case 'L':
2095260684Skaiw		return (cpp_demangle_read_expr_primary(ddata));
2096260684Skaiw	case 'X':
2097260684Skaiw		return (cpp_demangle_read_expression(ddata));
2098300311Semaste	}
2099260684Skaiw
2100260684Skaiw	return (cpp_demangle_read_type(ddata, 0));
2101260684Skaiw}
2102260684Skaiw
2103260684Skaiwstatic int
2104260684Skaiwcpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
2105260684Skaiw{
2106260684Skaiw	struct vector_str *v;
2107260684Skaiw	size_t arg_len, idx, limit, size;
2108260684Skaiw	char *arg;
2109260684Skaiw
2110260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
2111260684Skaiw		return (0);
2112260684Skaiw
2113260684Skaiw	++ddata->cur;
2114260684Skaiw
2115260684Skaiw	if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL))
2116260684Skaiw		return (0);
2117260684Skaiw
2118260684Skaiw	if (!cpp_demangle_push_str(ddata, "<", 1))
2119260684Skaiw		return (0);
2120260684Skaiw
2121260684Skaiw	limit = 0;
2122283616Semaste	v = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
2123260684Skaiw	for (;;) {
2124260684Skaiw		idx = v->size;
2125260684Skaiw		if (!cpp_demangle_read_tmpl_arg(ddata))
2126260684Skaiw			return (0);
2127260684Skaiw		if ((arg = vector_str_substr(v, idx, v->size - 1, &arg_len)) ==
2128260684Skaiw		    NULL)
2129260684Skaiw			return (0);
2130260684Skaiw		if (!vector_str_find(&ddata->tmpl, arg, arg_len) &&
2131260684Skaiw		    !vector_str_push(&ddata->tmpl, arg, arg_len)) {
2132260684Skaiw			free(arg);
2133260684Skaiw			return (0);
2134260684Skaiw		}
2135260684Skaiw
2136260684Skaiw		free(arg);
2137260684Skaiw
2138260684Skaiw		if (*ddata->cur == 'E') {
2139260684Skaiw			++ddata->cur;
2140260684Skaiw			size = v->size;
2141260684Skaiw			assert(size > 0);
2142260684Skaiw			if (!strncmp(v->container[size - 1], ">", 1)) {
2143260684Skaiw				if (!cpp_demangle_push_str(ddata, " >", 2))
2144260684Skaiw					return (0);
2145260684Skaiw			} else if (!cpp_demangle_push_str(ddata, ">", 1))
2146260684Skaiw				return (0);
2147260684Skaiw			break;
2148260684Skaiw		} else if (*ddata->cur != 'I' &&
2149260684Skaiw		    !cpp_demangle_push_str(ddata, ", ", 2))
2150260684Skaiw			return (0);
2151260684Skaiw
2152260684Skaiw		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
2153260684Skaiw			return (0);
2154260684Skaiw	}
2155260684Skaiw
2156260684Skaiw	return (vector_read_cmd_pop(&ddata->cmd));
2157260684Skaiw}
2158260684Skaiw
2159260684Skaiw/*
2160260684Skaiw * Read template parameter that forms in 'T[number]_'.
2161260684Skaiw * This function much like to read_subst but only for types.
2162260684Skaiw */
2163260684Skaiwstatic int
2164260684Skaiwcpp_demangle_read_tmpl_param(struct cpp_demangle_data *ddata)
2165260684Skaiw{
2166260684Skaiw	long nth;
2167260684Skaiw
2168260684Skaiw	if (ddata == NULL || *ddata->cur != 'T')
2169260684Skaiw		return (0);
2170260684Skaiw
2171260684Skaiw	++ddata->cur;
2172260684Skaiw
2173260684Skaiw	if (*ddata->cur == '_')
2174260684Skaiw		return (cpp_demangle_get_tmpl_param(ddata, 0));
2175260684Skaiw	else {
2176260684Skaiw
2177260684Skaiw		errno = 0;
2178260684Skaiw		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
2179260684Skaiw		    errno != 0)
2180260684Skaiw			return (0);
2181260684Skaiw
2182260684Skaiw		/* T_ is first */
2183260684Skaiw		++nth;
2184260684Skaiw
2185260684Skaiw		while (*ddata->cur != '_')
2186260684Skaiw			++ddata->cur;
2187260684Skaiw
2188260684Skaiw		assert(nth > 0);
2189260684Skaiw
2190260684Skaiw		return (cpp_demangle_get_tmpl_param(ddata, nth));
2191260684Skaiw	}
2192260684Skaiw
2193260684Skaiw	/* NOTREACHED */
2194260684Skaiw	return (0);
2195260684Skaiw}
2196260684Skaiw
2197260684Skaiwstatic int
2198260684Skaiwcpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
2199260684Skaiw{
2200260684Skaiw	struct vector_type_qualifier v;
2201260684Skaiw	struct vector_str *output;
2202260684Skaiw	size_t p_idx, type_str_len;
2203260684Skaiw	int extern_c, is_builtin;
2204260684Skaiw	long len;
2205283616Semaste	char *type_str, *exp_str, *num_str;
2206260684Skaiw
2207260684Skaiw	if (ddata == NULL)
2208260684Skaiw		return (0);
2209260684Skaiw
2210260684Skaiw	output = &ddata->output;
2211260684Skaiw	if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) {
2212283616Semaste		ddata->push_head++;
2213260684Skaiw		output = &ddata->output_tmp;
2214260684Skaiw	} else if (delimit == 1) {
2215260684Skaiw		if (ddata->paren == false) {
2216260684Skaiw			if (!cpp_demangle_push_str(ddata, "(", 1))
2217260684Skaiw				return (0);
2218260684Skaiw			if (ddata->output.size < 2)
2219260684Skaiw				return (0);
2220260684Skaiw			ddata->paren = true;
2221260684Skaiw			ddata->pfirst = true;
2222260684Skaiw			/* Need pop function name */
2223260684Skaiw			if (ddata->subst.size == 1 &&
2224260684Skaiw			    !vector_str_pop(&ddata->subst))
2225260684Skaiw				return (0);
2226260684Skaiw		}
2227260684Skaiw
2228260684Skaiw		if (ddata->pfirst)
2229260684Skaiw			ddata->pfirst = false;
2230260684Skaiw		else if (*ddata->cur != 'I' &&
2231260684Skaiw		    !cpp_demangle_push_str(ddata, ", ", 2))
2232260684Skaiw			return (0);
2233260684Skaiw	}
2234260684Skaiw
2235260684Skaiw	assert(output != NULL);
2236260684Skaiw	/*
2237260684Skaiw	 * [r, V, K] [P, R, C, G, U] builtin, function, class-enum, array
2238260684Skaiw	 * pointer-to-member, template-param, template-template-param, subst
2239260684Skaiw	 */
2240260684Skaiw
2241260684Skaiw	if (!vector_type_qualifier_init(&v))
2242260684Skaiw		return (0);
2243260684Skaiw
2244260684Skaiw	extern_c = 0;
2245260684Skaiw	is_builtin = 1;
2246260684Skaiw	p_idx = output->size;
2247283616Semaste	type_str = exp_str = num_str = NULL;
2248260684Skaiwagain:
2249260684Skaiw	/* builtin type */
2250260684Skaiw	switch (*ddata->cur) {
2251260684Skaiw	case 'a':
2252260684Skaiw		/* signed char */
2253260684Skaiw		if (!cpp_demangle_push_str(ddata, "signed char", 11))
2254260684Skaiw			goto clean;
2255260684Skaiw		++ddata->cur;
2256260684Skaiw		goto rtn;
2257260684Skaiw
2258260684Skaiw	case 'A':
2259260684Skaiw		/* array type */
2260260684Skaiw		if (!cpp_demangle_read_array(ddata))
2261260684Skaiw			goto clean;
2262260684Skaiw		is_builtin = 0;
2263260684Skaiw		goto rtn;
2264260684Skaiw
2265260684Skaiw	case 'b':
2266260684Skaiw		/* bool */
2267260684Skaiw		if (!cpp_demangle_push_str(ddata, "bool", 4))
2268260684Skaiw			goto clean;
2269260684Skaiw		++ddata->cur;
2270260684Skaiw		goto rtn;
2271260684Skaiw
2272260684Skaiw	case 'C':
2273260684Skaiw		/* complex pair */
2274260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_CMX))
2275260684Skaiw			goto clean;
2276260684Skaiw		++ddata->cur;
2277260684Skaiw		goto again;
2278260684Skaiw
2279260684Skaiw	case 'c':
2280260684Skaiw		/* char */
2281260684Skaiw		if (!cpp_demangle_push_str(ddata, "char", 4))
2282260684Skaiw			goto clean;
2283260684Skaiw		++ddata->cur;
2284260684Skaiw		goto rtn;
2285260684Skaiw
2286260684Skaiw	case 'd':
2287260684Skaiw		/* double */
2288260684Skaiw		if (!cpp_demangle_push_str(ddata, "double", 6))
2289260684Skaiw			goto clean;
2290260684Skaiw		++ddata->cur;
2291260684Skaiw		goto rtn;
2292260684Skaiw
2293283616Semaste	case 'D':
2294283616Semaste		++ddata->cur;
2295283616Semaste		switch (*ddata->cur) {
2296283616Semaste		case 'd':
2297283616Semaste			/* IEEE 754r decimal floating point (64 bits) */
2298283616Semaste			if (!cpp_demangle_push_str(ddata, "decimal64", 9))
2299283616Semaste				goto clean;
2300283616Semaste			++ddata->cur;
2301283616Semaste			break;
2302283616Semaste		case 'e':
2303283616Semaste			/* IEEE 754r decimal floating point (128 bits) */
2304283616Semaste			if (!cpp_demangle_push_str(ddata, "decimal128", 10))
2305283616Semaste				goto clean;
2306283616Semaste			++ddata->cur;
2307283616Semaste			break;
2308283616Semaste		case 'f':
2309283616Semaste			/* IEEE 754r decimal floating point (32 bits) */
2310283616Semaste			if (!cpp_demangle_push_str(ddata, "decimal32", 9))
2311283616Semaste				goto clean;
2312283616Semaste			++ddata->cur;
2313283616Semaste			break;
2314283616Semaste		case 'h':
2315283616Semaste			/* IEEE 754r half-precision floating point (16 bits) */
2316283616Semaste			if (!cpp_demangle_push_str(ddata, "half", 4))
2317283616Semaste				goto clean;
2318283616Semaste			++ddata->cur;
2319283616Semaste			break;
2320283616Semaste		case 'i':
2321283616Semaste			/* char32_t */
2322283616Semaste			if (!cpp_demangle_push_str(ddata, "char32_t", 8))
2323283616Semaste				goto clean;
2324283616Semaste			++ddata->cur;
2325283616Semaste			break;
2326283616Semaste		case 'n':
2327283616Semaste			/* std::nullptr_t (i.e., decltype(nullptr)) */
2328283616Semaste			if (!cpp_demangle_push_str(ddata, "decltype(nullptr)",
2329283616Semaste			    17))
2330283616Semaste				goto clean;
2331283616Semaste			++ddata->cur;
2332283616Semaste			break;
2333283616Semaste		case 's':
2334283616Semaste			/* char16_t */
2335283616Semaste			if (!cpp_demangle_push_str(ddata, "char16_t", 8))
2336283616Semaste				goto clean;
2337283616Semaste			++ddata->cur;
2338283616Semaste			break;
2339283616Semaste		case 'v':
2340283616Semaste			/* gcc vector_size extension. */
2341283616Semaste			++ddata->cur;
2342283616Semaste			if (*ddata->cur == '_') {
2343283616Semaste				++ddata->cur;
2344283616Semaste				if (!cpp_demangle_read_expression_flat(ddata,
2345283616Semaste				    &exp_str))
2346283616Semaste					goto clean;
2347283616Semaste				if (!vector_str_push(&v.ext_name, exp_str,
2348283616Semaste				    strlen(exp_str)))
2349283616Semaste					goto clean;
2350283616Semaste			} else {
2351283616Semaste				if (!cpp_demangle_read_number_as_string(ddata,
2352283616Semaste				    &num_str))
2353283616Semaste					goto clean;
2354283616Semaste				if (!vector_str_push(&v.ext_name, num_str,
2355283616Semaste				    strlen(num_str)))
2356283616Semaste					goto clean;
2357283616Semaste			}
2358283616Semaste			if (*ddata->cur != '_')
2359283616Semaste				goto clean;
2360283616Semaste			++ddata->cur;
2361283616Semaste			if (!vector_type_qualifier_push(&v, TYPE_VEC))
2362283616Semaste				goto clean;
2363283616Semaste			goto again;
2364283616Semaste		default:
2365283616Semaste			goto clean;
2366283616Semaste		}
2367283616Semaste		goto rtn;
2368283616Semaste
2369260684Skaiw	case 'e':
2370260684Skaiw		/* long double */
2371260684Skaiw		if (!cpp_demangle_push_str(ddata, "long double", 11))
2372260684Skaiw			goto clean;
2373260684Skaiw		++ddata->cur;
2374260684Skaiw		goto rtn;
2375260684Skaiw
2376260684Skaiw	case 'f':
2377260684Skaiw		/* float */
2378260684Skaiw		if (!cpp_demangle_push_str(ddata, "float", 5))
2379260684Skaiw			goto clean;
2380260684Skaiw		++ddata->cur;
2381260684Skaiw		goto rtn;
2382260684Skaiw
2383260684Skaiw	case 'F':
2384260684Skaiw		/* function */
2385260684Skaiw		if (!cpp_demangle_read_function(ddata, &extern_c, &v))
2386260684Skaiw			goto clean;
2387260684Skaiw		is_builtin = 0;
2388260684Skaiw		goto rtn;
2389260684Skaiw
2390260684Skaiw	case 'g':
2391260684Skaiw		/* __float128 */
2392260684Skaiw		if (!cpp_demangle_push_str(ddata, "__float128", 10))
2393260684Skaiw			goto clean;
2394260684Skaiw		++ddata->cur;
2395260684Skaiw		goto rtn;
2396260684Skaiw
2397260684Skaiw	case 'G':
2398260684Skaiw		/* imaginary */
2399260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_IMG))
2400260684Skaiw			goto clean;
2401260684Skaiw		++ddata->cur;
2402260684Skaiw		goto again;
2403260684Skaiw
2404260684Skaiw	case 'h':
2405260684Skaiw		/* unsigned char */
2406260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned char", 13))
2407260684Skaiw			goto clean;
2408260684Skaiw		++ddata->cur;
2409260684Skaiw		goto rtn;
2410260684Skaiw
2411260684Skaiw	case 'i':
2412260684Skaiw		/* int */
2413260684Skaiw		if (!cpp_demangle_push_str(ddata, "int", 3))
2414260684Skaiw			goto clean;
2415260684Skaiw		++ddata->cur;
2416260684Skaiw		goto rtn;
2417260684Skaiw
2418260684Skaiw	case 'j':
2419260684Skaiw		/* unsigned int */
2420260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned int", 12))
2421260684Skaiw			goto clean;
2422260684Skaiw		++ddata->cur;
2423260684Skaiw		goto rtn;
2424260684Skaiw
2425260684Skaiw	case 'K':
2426260684Skaiw		/* const */
2427260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_CST))
2428260684Skaiw			goto clean;
2429260684Skaiw		++ddata->cur;
2430260684Skaiw		goto again;
2431260684Skaiw
2432260684Skaiw	case 'l':
2433260684Skaiw		/* long */
2434260684Skaiw		if (!cpp_demangle_push_str(ddata, "long", 4))
2435260684Skaiw			goto clean;
2436260684Skaiw		++ddata->cur;
2437260684Skaiw		goto rtn;
2438260684Skaiw
2439260684Skaiw	case 'm':
2440260684Skaiw		/* unsigned long */
2441260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned long", 13))
2442260684Skaiw			goto clean;
2443260684Skaiw
2444260684Skaiw		++ddata->cur;
2445260684Skaiw
2446260684Skaiw		goto rtn;
2447260684Skaiw	case 'M':
2448260684Skaiw		/* pointer to member */
2449260684Skaiw		if (!cpp_demangle_read_pointer_to_member(ddata))
2450260684Skaiw			goto clean;
2451260684Skaiw		is_builtin = 0;
2452260684Skaiw		goto rtn;
2453260684Skaiw
2454260684Skaiw	case 'n':
2455260684Skaiw		/* __int128 */
2456260684Skaiw		if (!cpp_demangle_push_str(ddata, "__int128", 8))
2457260684Skaiw			goto clean;
2458260684Skaiw		++ddata->cur;
2459260684Skaiw		goto rtn;
2460260684Skaiw
2461260684Skaiw	case 'o':
2462260684Skaiw		/* unsigned __int128 */
2463283616Semaste		if (!cpp_demangle_push_str(ddata, "unsigned __int128", 17))
2464260684Skaiw			goto clean;
2465260684Skaiw		++ddata->cur;
2466260684Skaiw		goto rtn;
2467260684Skaiw
2468260684Skaiw	case 'P':
2469260684Skaiw		/* pointer */
2470260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_PTR))
2471260684Skaiw			goto clean;
2472260684Skaiw		++ddata->cur;
2473260684Skaiw		goto again;
2474260684Skaiw
2475260684Skaiw	case 'r':
2476260684Skaiw		/* restrict */
2477260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_RST))
2478260684Skaiw			goto clean;
2479260684Skaiw		++ddata->cur;
2480260684Skaiw		goto again;
2481260684Skaiw
2482260684Skaiw	case 'R':
2483260684Skaiw		/* reference */
2484260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_REF))
2485260684Skaiw			goto clean;
2486260684Skaiw		++ddata->cur;
2487260684Skaiw		goto again;
2488260684Skaiw
2489260684Skaiw	case 's':
2490260684Skaiw		/* short, local string */
2491260684Skaiw		if (!cpp_demangle_push_str(ddata, "short", 5))
2492260684Skaiw			goto clean;
2493260684Skaiw		++ddata->cur;
2494260684Skaiw		goto rtn;
2495260684Skaiw
2496260684Skaiw	case 'S':
2497260684Skaiw		/* substitution */
2498260684Skaiw		if (!cpp_demangle_read_subst(ddata))
2499260684Skaiw			goto clean;
2500260684Skaiw		is_builtin = 0;
2501260684Skaiw		goto rtn;
2502260684Skaiw
2503260684Skaiw	case 't':
2504260684Skaiw		/* unsigned short */
2505260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned short", 14))
2506260684Skaiw			goto clean;
2507260684Skaiw		++ddata->cur;
2508260684Skaiw		goto rtn;
2509260684Skaiw
2510260684Skaiw	case 'T':
2511260684Skaiw		/* template parameter */
2512260684Skaiw		if (!cpp_demangle_read_tmpl_param(ddata))
2513260684Skaiw			goto clean;
2514260684Skaiw		is_builtin = 0;
2515260684Skaiw		goto rtn;
2516260684Skaiw
2517260684Skaiw	case 'u':
2518260684Skaiw		/* vendor extended builtin */
2519260684Skaiw		++ddata->cur;
2520260684Skaiw		if (!cpp_demangle_read_sname(ddata))
2521260684Skaiw			goto clean;
2522260684Skaiw		is_builtin = 0;
2523260684Skaiw		goto rtn;
2524260684Skaiw
2525260684Skaiw	case 'U':
2526260684Skaiw		/* vendor extended type qualifier */
2527260684Skaiw		if (!cpp_demangle_read_number(ddata, &len))
2528260684Skaiw			goto clean;
2529260684Skaiw		if (len <= 0)
2530260684Skaiw			goto clean;
2531260684Skaiw		if (!vector_str_push(&v.ext_name, ddata->cur, len))
2532260684Skaiw			return (0);
2533260684Skaiw		ddata->cur += len;
2534283616Semaste		if (!vector_type_qualifier_push(&v, TYPE_EXT))
2535283616Semaste			goto clean;
2536260684Skaiw		goto again;
2537260684Skaiw
2538260684Skaiw	case 'v':
2539260684Skaiw		/* void */
2540260684Skaiw		if (!cpp_demangle_push_str(ddata, "void", 4))
2541260684Skaiw			goto clean;
2542260684Skaiw		++ddata->cur;
2543260684Skaiw		goto rtn;
2544260684Skaiw
2545260684Skaiw	case 'V':
2546260684Skaiw		/* volatile */
2547260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_VAT))
2548260684Skaiw			goto clean;
2549260684Skaiw		++ddata->cur;
2550260684Skaiw		goto again;
2551260684Skaiw
2552260684Skaiw	case 'w':
2553260684Skaiw		/* wchar_t */
2554303398Semaste		if (!cpp_demangle_push_str(ddata, "wchar_t", 7))
2555260684Skaiw			goto clean;
2556260684Skaiw		++ddata->cur;
2557260684Skaiw		goto rtn;
2558260684Skaiw
2559260684Skaiw	case 'x':
2560260684Skaiw		/* long long */
2561260684Skaiw		if (!cpp_demangle_push_str(ddata, "long long", 9))
2562260684Skaiw			goto clean;
2563260684Skaiw		++ddata->cur;
2564260684Skaiw		goto rtn;
2565260684Skaiw
2566260684Skaiw	case 'y':
2567260684Skaiw		/* unsigned long long */
2568260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned long long", 18))
2569260684Skaiw			goto clean;
2570260684Skaiw		++ddata->cur;
2571260684Skaiw		goto rtn;
2572260684Skaiw
2573260684Skaiw	case 'z':
2574260684Skaiw		/* ellipsis */
2575260684Skaiw		if (!cpp_demangle_push_str(ddata, "ellipsis", 8))
2576260684Skaiw			goto clean;
2577260684Skaiw		++ddata->cur;
2578260684Skaiw		goto rtn;
2579300311Semaste	}
2580260684Skaiw
2581260684Skaiw	if (!cpp_demangle_read_name(ddata))
2582260684Skaiw		goto clean;
2583260684Skaiw
2584260684Skaiw	is_builtin = 0;
2585260684Skaiwrtn:
2586260684Skaiw	if ((type_str = vector_str_substr(output, p_idx, output->size - 1,
2587260684Skaiw	    &type_str_len)) == NULL)
2588260684Skaiw		goto clean;
2589260684Skaiw
2590260684Skaiw	if (is_builtin == 0) {
2591260684Skaiw		if (!vector_str_find(&ddata->subst, type_str, type_str_len) &&
2592260684Skaiw		    !vector_str_push(&ddata->subst, type_str, type_str_len))
2593260684Skaiw			goto clean;
2594260684Skaiw	}
2595260684Skaiw
2596260684Skaiw	if (!cpp_demangle_push_type_qualifier(ddata, &v, type_str))
2597260684Skaiw		goto clean;
2598260684Skaiw
2599260684Skaiw	free(type_str);
2600283616Semaste	free(exp_str);
2601283616Semaste	free(num_str);
2602260684Skaiw	vector_type_qualifier_dest(&v);
2603260684Skaiw
2604283616Semaste	if (ddata->push_head > 0) {
2605260684Skaiw		if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata)
2606260684Skaiw		    == 0)
2607260684Skaiw			return (0);
2608260684Skaiw
2609283616Semaste		if (--ddata->push_head > 0)
2610260684Skaiw			return (1);
2611260684Skaiw
2612260684Skaiw		if (!vector_str_push(&ddata->output_tmp, " ", 1))
2613260684Skaiw			return (0);
2614260684Skaiw
2615260684Skaiw		if (!vector_str_push_vector_head(&ddata->output,
2616260684Skaiw		    &ddata->output_tmp))
2617260684Skaiw			return (0);
2618260684Skaiw
2619260684Skaiw		vector_str_dest(&ddata->output_tmp);
2620260684Skaiw		if (!vector_str_init(&ddata->output_tmp))
2621260684Skaiw			return (0);
2622260684Skaiw
2623260684Skaiw		if (!cpp_demangle_push_str(ddata, "(", 1))
2624260684Skaiw			return (0);
2625260684Skaiw
2626260684Skaiw		ddata->paren = true;
2627260684Skaiw		ddata->pfirst = true;
2628260684Skaiw	}
2629260684Skaiw
2630260684Skaiw	return (1);
2631260684Skaiwclean:
2632260684Skaiw	free(type_str);
2633283616Semaste	free(exp_str);
2634283616Semaste	free(num_str);
2635260684Skaiw	vector_type_qualifier_dest(&v);
2636260684Skaiw
2637260684Skaiw	return (0);
2638260684Skaiw}
2639260684Skaiw
2640283616Semastestatic int
2641283616Semastecpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str)
2642283616Semaste{
2643283616Semaste	struct vector_str *output;
2644283616Semaste	size_t i, p_idx, idx, type_len;
2645283616Semaste	char *type;
2646283616Semaste
2647283616Semaste	output = ddata->push_head > 0 ? &ddata->output_tmp :
2648283616Semaste	    &ddata->output;
2649283616Semaste
2650283616Semaste	p_idx = output->size;
2651283616Semaste
2652283616Semaste	if (!cpp_demangle_read_type(ddata, 0))
2653283616Semaste		return (0);
2654283616Semaste
2655283616Semaste	if ((type = vector_str_substr(output, p_idx, output->size - 1,
2656283616Semaste	    &type_len)) == NULL)
2657283616Semaste		return (0);
2658283616Semaste
2659283616Semaste	idx = output->size;
2660283616Semaste	for (i = p_idx; i < idx; ++i) {
2661283616Semaste		if (!vector_str_pop(output)) {
2662283616Semaste			free(type);
2663283616Semaste			return (0);
2664283616Semaste		}
2665283616Semaste	}
2666283616Semaste
2667283616Semaste	*str = type;
2668283616Semaste
2669283616Semaste	return (1);
2670283616Semaste}
2671283616Semaste
2672260684Skaiw/*
2673260684Skaiw * read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
2674260684Skaiw * source-name
2675260684Skaiw */
2676260684Skaiwstatic int
2677260684Skaiwcpp_demangle_read_uqname(struct cpp_demangle_data *ddata)
2678260684Skaiw{
2679260684Skaiw	size_t len;
2680260684Skaiw
2681260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
2682260684Skaiw		return (0);
2683260684Skaiw
2684260684Skaiw	/* operator name */
2685260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
2686260684Skaiw	case SIMPLE_HASH('a', 'a'):
2687260684Skaiw		/* operator && */
2688260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator&&", 10))
2689260684Skaiw			return (0);
2690260684Skaiw		ddata->cur += 2;
2691260684Skaiw		return (1);
2692260684Skaiw
2693260684Skaiw	case SIMPLE_HASH('a', 'd'):
2694260684Skaiw		/* operator & (unary) */
2695260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator&", 9))
2696260684Skaiw			return (0);
2697260684Skaiw		ddata->cur += 2;
2698260684Skaiw		return (1);
2699260684Skaiw
2700260684Skaiw	case SIMPLE_HASH('a', 'n'):
2701260684Skaiw		/* operator & */
2702260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator&", 9))
2703260684Skaiw			return (0);
2704260684Skaiw		ddata->cur += 2;
2705260684Skaiw		return (1);
2706260684Skaiw
2707260684Skaiw	case SIMPLE_HASH('a', 'N'):
2708260684Skaiw		/* operator &= */
2709260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator&=", 10))
2710260684Skaiw			return (0);
2711260684Skaiw		ddata->cur += 2;
2712260684Skaiw		return (1);
2713260684Skaiw
2714260684Skaiw	case SIMPLE_HASH('a', 'S'):
2715260684Skaiw		/* operator = */
2716260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator=", 9))
2717260684Skaiw			return (0);
2718260684Skaiw		ddata->cur += 2;
2719260684Skaiw		return (1);
2720260684Skaiw
2721260684Skaiw	case SIMPLE_HASH('c', 'l'):
2722260684Skaiw		/* operator () */
2723260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator()", 10))
2724260684Skaiw			return (0);
2725260684Skaiw		ddata->cur += 2;
2726260684Skaiw		return (1);
2727260684Skaiw
2728260684Skaiw	case SIMPLE_HASH('c', 'm'):
2729260684Skaiw		/* operator , */
2730260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator,", 9))
2731260684Skaiw			return (0);
2732260684Skaiw		ddata->cur += 2;
2733260684Skaiw		return (1);
2734260684Skaiw
2735260684Skaiw	case SIMPLE_HASH('c', 'o'):
2736260684Skaiw		/* operator ~ */
2737260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator~", 9))
2738260684Skaiw			return (0);
2739260684Skaiw		ddata->cur += 2;
2740260684Skaiw		return (1);
2741260684Skaiw
2742260684Skaiw	case SIMPLE_HASH('c', 'v'):
2743260684Skaiw		/* operator (cast) */
2744260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator(cast)", 14))
2745260684Skaiw			return (0);
2746260684Skaiw		ddata->cur += 2;
2747260684Skaiw		return (cpp_demangle_read_type(ddata, 1));
2748260684Skaiw
2749260684Skaiw	case SIMPLE_HASH('d', 'a'):
2750260684Skaiw		/* operator delete [] */
2751260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator delete []", 18))
2752260684Skaiw			return (0);
2753260684Skaiw		ddata->cur += 2;
2754260684Skaiw		return (1);
2755260684Skaiw
2756260684Skaiw	case SIMPLE_HASH('d', 'e'):
2757260684Skaiw		/* operator * (unary) */
2758260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator*", 9))
2759260684Skaiw			return (0);
2760260684Skaiw		ddata->cur += 2;
2761260684Skaiw		return (1);
2762260684Skaiw
2763260684Skaiw	case SIMPLE_HASH('d', 'l'):
2764260684Skaiw		/* operator delete */
2765260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator delete", 15))
2766260684Skaiw			return (0);
2767260684Skaiw		ddata->cur += 2;
2768260684Skaiw		return (1);
2769260684Skaiw
2770260684Skaiw	case SIMPLE_HASH('d', 'v'):
2771260684Skaiw		/* operator / */
2772260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator/", 9))
2773260684Skaiw			return (0);
2774260684Skaiw		ddata->cur += 2;
2775260684Skaiw		return (1);
2776260684Skaiw
2777260684Skaiw	case SIMPLE_HASH('d', 'V'):
2778260684Skaiw		/* operator /= */
2779260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator/=", 10))
2780260684Skaiw			return (0);
2781260684Skaiw		ddata->cur += 2;
2782260684Skaiw		return (1);
2783260684Skaiw
2784260684Skaiw	case SIMPLE_HASH('e', 'o'):
2785260684Skaiw		/* operator ^ */
2786260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator^", 9))
2787260684Skaiw			return (0);
2788260684Skaiw		ddata->cur += 2;
2789260684Skaiw		return (1);
2790260684Skaiw
2791260684Skaiw	case SIMPLE_HASH('e', 'O'):
2792260684Skaiw		/* operator ^= */
2793260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator^=", 10))
2794260684Skaiw			return (0);
2795260684Skaiw		ddata->cur += 2;
2796260684Skaiw		return (1);
2797260684Skaiw
2798260684Skaiw	case SIMPLE_HASH('e', 'q'):
2799260684Skaiw		/* operator == */
2800260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator==", 10))
2801260684Skaiw			return (0);
2802260684Skaiw		ddata->cur += 2;
2803260684Skaiw		return (1);
2804260684Skaiw
2805260684Skaiw	case SIMPLE_HASH('g', 'e'):
2806260684Skaiw		/* operator >= */
2807260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator>=", 10))
2808260684Skaiw			return (0);
2809260684Skaiw		ddata->cur += 2;
2810260684Skaiw		return (1);
2811260684Skaiw
2812260684Skaiw	case SIMPLE_HASH('g', 't'):
2813260684Skaiw		/* operator > */
2814260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator>", 9))
2815260684Skaiw			return (0);
2816260684Skaiw		ddata->cur += 2;
2817260684Skaiw		return (1);
2818260684Skaiw
2819260684Skaiw	case SIMPLE_HASH('i', 'x'):
2820260684Skaiw		/* operator [] */
2821260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator[]", 10))
2822260684Skaiw			return (0);
2823260684Skaiw		ddata->cur += 2;
2824260684Skaiw		return (1);
2825260684Skaiw
2826260684Skaiw	case SIMPLE_HASH('l', 'e'):
2827260684Skaiw		/* operator <= */
2828260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator<=", 10))
2829260684Skaiw			return (0);
2830260684Skaiw		ddata->cur += 2;
2831260684Skaiw		return (1);
2832260684Skaiw
2833260684Skaiw	case SIMPLE_HASH('l', 's'):
2834260684Skaiw		/* operator << */
2835260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator<<", 10))
2836260684Skaiw			return (0);
2837260684Skaiw		ddata->cur += 2;
2838260684Skaiw		return (1);
2839260684Skaiw
2840260684Skaiw	case SIMPLE_HASH('l', 'S'):
2841260684Skaiw		/* operator <<= */
2842260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator<<=", 11))
2843260684Skaiw			return (0);
2844260684Skaiw		ddata->cur += 2;
2845260684Skaiw		return (1);
2846260684Skaiw
2847260684Skaiw	case SIMPLE_HASH('l', 't'):
2848260684Skaiw		/* operator < */
2849260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator<", 9))
2850260684Skaiw			return (0);
2851260684Skaiw		ddata->cur += 2;
2852260684Skaiw		return (1);
2853260684Skaiw
2854260684Skaiw	case SIMPLE_HASH('m', 'i'):
2855260684Skaiw		/* operator - */
2856260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator-", 9))
2857260684Skaiw			return (0);
2858260684Skaiw		ddata->cur += 2;
2859260684Skaiw		return (1);
2860260684Skaiw
2861260684Skaiw	case SIMPLE_HASH('m', 'I'):
2862260684Skaiw		/* operator -= */
2863260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator-=", 10))
2864260684Skaiw			return (0);
2865260684Skaiw		ddata->cur += 2;
2866260684Skaiw		return (1);
2867260684Skaiw
2868260684Skaiw	case SIMPLE_HASH('m', 'l'):
2869260684Skaiw		/* operator * */
2870260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator*", 9))
2871260684Skaiw			return (0);
2872260684Skaiw		ddata->cur += 2;
2873260684Skaiw		return (1);
2874260684Skaiw
2875260684Skaiw	case SIMPLE_HASH('m', 'L'):
2876260684Skaiw		/* operator *= */
2877260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator*=", 10))
2878260684Skaiw			return (0);
2879260684Skaiw		ddata->cur += 2;
2880260684Skaiw		return (1);
2881260684Skaiw
2882260684Skaiw	case SIMPLE_HASH('m', 'm'):
2883260684Skaiw		/* operator -- */
2884260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator--", 10))
2885260684Skaiw			return (0);
2886260684Skaiw		ddata->cur += 2;
2887260684Skaiw		return (1);
2888260684Skaiw
2889260684Skaiw	case SIMPLE_HASH('n', 'a'):
2890260684Skaiw		/* operator new[] */
2891260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator new []", 15))
2892260684Skaiw			return (0);
2893260684Skaiw		ddata->cur += 2;
2894260684Skaiw		return (1);
2895260684Skaiw
2896260684Skaiw	case SIMPLE_HASH('n', 'e'):
2897260684Skaiw		/* operator != */
2898260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator!=", 10))
2899260684Skaiw			return (0);
2900260684Skaiw		ddata->cur += 2;
2901260684Skaiw		return (1);
2902260684Skaiw
2903260684Skaiw	case SIMPLE_HASH('n', 'g'):
2904260684Skaiw		/* operator - (unary) */
2905260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator-", 9))
2906260684Skaiw			return (0);
2907260684Skaiw		ddata->cur += 2;
2908260684Skaiw		return (1);
2909260684Skaiw
2910260684Skaiw	case SIMPLE_HASH('n', 't'):
2911260684Skaiw		/* operator ! */
2912260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator!", 9))
2913260684Skaiw			return (0);
2914260684Skaiw		ddata->cur += 2;
2915260684Skaiw		return (1);
2916260684Skaiw
2917260684Skaiw	case SIMPLE_HASH('n', 'w'):
2918260684Skaiw		/* operator new */
2919260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator new", 12))
2920260684Skaiw			return (0);
2921260684Skaiw		ddata->cur += 2;
2922260684Skaiw		return (1);
2923260684Skaiw
2924260684Skaiw	case SIMPLE_HASH('o', 'o'):
2925260684Skaiw		/* operator || */
2926260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator||", 10))
2927260684Skaiw			return (0);
2928260684Skaiw		ddata->cur += 2;
2929260684Skaiw		return (1);
2930260684Skaiw
2931260684Skaiw	case SIMPLE_HASH('o', 'r'):
2932260684Skaiw		/* operator | */
2933260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator|", 9))
2934260684Skaiw			return (0);
2935260684Skaiw		ddata->cur += 2;
2936260684Skaiw		return (1);
2937260684Skaiw
2938260684Skaiw	case SIMPLE_HASH('o', 'R'):
2939260684Skaiw		/* operator |= */
2940260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator|=", 10))
2941260684Skaiw			return (0);
2942260684Skaiw		ddata->cur += 2;
2943260684Skaiw		return (1);
2944260684Skaiw
2945260684Skaiw	case SIMPLE_HASH('p', 'l'):
2946260684Skaiw		/* operator + */
2947260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator+", 9))
2948260684Skaiw			return (0);
2949260684Skaiw		ddata->cur += 2;
2950260684Skaiw		return (1);
2951260684Skaiw
2952260684Skaiw	case SIMPLE_HASH('p', 'L'):
2953260684Skaiw		/* operator += */
2954260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator+=", 10))
2955260684Skaiw			return (0);
2956260684Skaiw		ddata->cur += 2;
2957260684Skaiw		return (1);
2958260684Skaiw
2959260684Skaiw	case SIMPLE_HASH('p', 'm'):
2960260684Skaiw		/* operator ->* */
2961260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator->*", 11))
2962260684Skaiw			return (0);
2963260684Skaiw		ddata->cur += 2;
2964260684Skaiw		return (1);
2965260684Skaiw
2966260684Skaiw	case SIMPLE_HASH('p', 'p'):
2967260684Skaiw		/* operator ++ */
2968260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator++", 10))
2969260684Skaiw			return (0);
2970260684Skaiw		ddata->cur += 2;
2971260684Skaiw		return (1);
2972260684Skaiw
2973260684Skaiw	case SIMPLE_HASH('p', 's'):
2974260684Skaiw		/* operator + (unary) */
2975260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator+", 9))
2976260684Skaiw			return (0);
2977260684Skaiw		ddata->cur += 2;
2978260684Skaiw		return (1);
2979260684Skaiw
2980260684Skaiw	case SIMPLE_HASH('p', 't'):
2981260684Skaiw		/* operator -> */
2982260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator->", 10))
2983260684Skaiw			return (0);
2984260684Skaiw		ddata->cur += 2;
2985260684Skaiw		return (1);
2986260684Skaiw
2987260684Skaiw	case SIMPLE_HASH('q', 'u'):
2988260684Skaiw		/* operator ? */
2989260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator?", 9))
2990260684Skaiw			return (0);
2991260684Skaiw		ddata->cur += 2;
2992260684Skaiw		return (1);
2993260684Skaiw
2994260684Skaiw	case SIMPLE_HASH('r', 'm'):
2995260684Skaiw		/* operator % */
2996260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator%", 9))
2997260684Skaiw			return (0);
2998260684Skaiw		ddata->cur += 2;
2999260684Skaiw		return (1);
3000260684Skaiw
3001260684Skaiw	case SIMPLE_HASH('r', 'M'):
3002260684Skaiw		/* operator %= */
3003260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator%=", 10))
3004260684Skaiw			return (0);
3005260684Skaiw		ddata->cur += 2;
3006260684Skaiw		return (1);
3007260684Skaiw
3008260684Skaiw	case SIMPLE_HASH('r', 's'):
3009260684Skaiw		/* operator >> */
3010260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator>>", 10))
3011260684Skaiw			return (0);
3012260684Skaiw		ddata->cur += 2;
3013260684Skaiw		return (1);
3014260684Skaiw
3015260684Skaiw	case SIMPLE_HASH('r', 'S'):
3016260684Skaiw		/* operator >>= */
3017260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator>>=", 11))
3018260684Skaiw			return (0);
3019260684Skaiw		ddata->cur += 2;
3020260684Skaiw		return (1);
3021260684Skaiw
3022260684Skaiw	case SIMPLE_HASH('r', 'z'):
3023260684Skaiw		/* operator sizeof */
3024260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16))
3025260684Skaiw			return (0);
3026260684Skaiw		ddata->cur += 2;
3027260684Skaiw		return (1);
3028260684Skaiw
3029260684Skaiw	case SIMPLE_HASH('s', 'r'):
3030260684Skaiw		/* scope resolution operator */
3031260684Skaiw		if (!cpp_demangle_push_str(ddata, "scope resolution operator ",
3032260684Skaiw		    26))
3033260684Skaiw			return (0);
3034260684Skaiw		ddata->cur += 2;
3035260684Skaiw		return (1);
3036260684Skaiw
3037260684Skaiw	case SIMPLE_HASH('s', 'v'):
3038260684Skaiw		/* operator sizeof */
3039260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16))
3040260684Skaiw			return (0);
3041260684Skaiw		ddata->cur += 2;
3042260684Skaiw		return (1);
3043300311Semaste	}
3044260684Skaiw
3045260684Skaiw	/* vendor extened operator */
3046260684Skaiw	if (*ddata->cur == 'v' && ELFTC_ISDIGIT(*(ddata->cur + 1))) {
3047260684Skaiw		if (!cpp_demangle_push_str(ddata, "vendor extened operator ",
3048260684Skaiw		    24))
3049260684Skaiw			return (0);
3050260684Skaiw		if (!cpp_demangle_push_str(ddata, ddata->cur + 1, 1))
3051260684Skaiw			return (0);
3052260684Skaiw		ddata->cur += 2;
3053260684Skaiw		return (cpp_demangle_read_sname(ddata));
3054260684Skaiw	}
3055260684Skaiw
3056260684Skaiw	/* ctor-dtor-name */
3057260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
3058260684Skaiw	case SIMPLE_HASH('C', '1'):
3059260684Skaiw		/* FALLTHROUGH */
3060260684Skaiw	case SIMPLE_HASH('C', '2'):
3061260684Skaiw		/* FALLTHROUGH */
3062260684Skaiw	case SIMPLE_HASH('C', '3'):
3063260684Skaiw		if (ddata->last_sname == NULL)
3064260684Skaiw			return (0);
3065260684Skaiw		if ((len = strlen(ddata->last_sname)) == 0)
3066260684Skaiw			return (0);
3067260684Skaiw		if (!cpp_demangle_push_str(ddata, "::", 2))
3068260684Skaiw			return (0);
3069260684Skaiw		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
3070260684Skaiw			return (0);
3071260684Skaiw		ddata->cur +=2;
3072260684Skaiw		return (1);
3073260684Skaiw
3074260684Skaiw	case SIMPLE_HASH('D', '0'):
3075260684Skaiw		/* FALLTHROUGH */
3076260684Skaiw	case SIMPLE_HASH('D', '1'):
3077260684Skaiw		/* FALLTHROUGH */
3078260684Skaiw	case SIMPLE_HASH('D', '2'):
3079260684Skaiw		if (ddata->last_sname == NULL)
3080260684Skaiw			return (0);
3081260684Skaiw		if ((len = strlen(ddata->last_sname)) == 0)
3082260684Skaiw			return (0);
3083260684Skaiw		if (!cpp_demangle_push_str(ddata, "::~", 3))
3084260684Skaiw			return (0);
3085260684Skaiw		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
3086260684Skaiw			return (0);
3087260684Skaiw		ddata->cur +=2;
3088260684Skaiw		return (1);
3089300311Semaste	}
3090260684Skaiw
3091260684Skaiw	/* source name */
3092260684Skaiw	if (ELFTC_ISDIGIT(*ddata->cur) != 0)
3093260684Skaiw		return (cpp_demangle_read_sname(ddata));
3094260684Skaiw
3095260684Skaiw	/* local source name */
3096260684Skaiw	if (*ddata->cur == 'L')
3097260684Skaiw		return (cpp_demangle_local_source_name(ddata));
3098260684Skaiw
3099260684Skaiw	return (1);
3100260684Skaiw}
3101260684Skaiw
3102260684Skaiw/*
3103260684Skaiw * Read local source name.
3104260684Skaiw *
3105260684Skaiw * References:
3106260684Skaiw *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
3107260684Skaiw *   http://gcc.gnu.org/viewcvs?view=rev&revision=124467
3108260684Skaiw */
3109260684Skaiwstatic int
3110260684Skaiwcpp_demangle_local_source_name(struct cpp_demangle_data *ddata)
3111260684Skaiw{
3112260684Skaiw	/* L */
3113260684Skaiw	if (ddata == NULL || *ddata->cur != 'L')
3114260684Skaiw		return (0);
3115260684Skaiw	++ddata->cur;
3116260684Skaiw
3117260684Skaiw	/* source name */
3118260684Skaiw	if (!cpp_demangle_read_sname(ddata))
3119260684Skaiw		return (0);
3120260684Skaiw
3121260684Skaiw	/* discriminator */
3122260684Skaiw	if (*ddata->cur == '_') {
3123260684Skaiw		++ddata->cur;
3124260684Skaiw		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
3125260684Skaiw			++ddata->cur;
3126260684Skaiw	}
3127260684Skaiw
3128260684Skaiw	return (1);
3129260684Skaiw}
3130260684Skaiw
3131260684Skaiwstatic int
3132260684Skaiwcpp_demangle_read_v_offset(struct cpp_demangle_data *ddata)
3133260684Skaiw{
3134260684Skaiw
3135260684Skaiw	if (ddata == NULL)
3136260684Skaiw		return (0);
3137260684Skaiw
3138260684Skaiw	if (!cpp_demangle_push_str(ddata, "offset : ", 9))
3139260684Skaiw		return (0);
3140260684Skaiw
3141260684Skaiw	if (!cpp_demangle_read_offset_number(ddata))
3142260684Skaiw		return (0);
3143260684Skaiw
3144260684Skaiw	if (!cpp_demangle_push_str(ddata, "virtual offset : ", 17))
3145260684Skaiw		return (0);
3146260684Skaiw
3147260684Skaiw	return (!cpp_demangle_read_offset_number(ddata));
3148260684Skaiw}
3149260684Skaiw
3150260684Skaiw/*
3151260684Skaiw * Decode floating point representation to string
3152260684Skaiw * Return new allocated string or NULL
3153260684Skaiw *
3154260684Skaiw * Todo
3155260684Skaiw * Replace these functions to macro.
3156260684Skaiw */
3157260684Skaiwstatic char *
3158260684Skaiwdecode_fp_to_double(const char *p, size_t len)
3159260684Skaiw{
3160260684Skaiw	double f;
3161260684Skaiw	size_t rtn_len, limit, i;
3162260684Skaiw	int byte;
3163260684Skaiw	char *rtn;
3164260684Skaiw
3165260684Skaiw	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(double))
3166260684Skaiw		return (NULL);
3167260684Skaiw
3168260684Skaiw	memset(&f, 0, sizeof(double));
3169260684Skaiw
3170260684Skaiw	for (i = 0; i < len / 2; ++i) {
3171260684Skaiw		byte = hex_to_dec(p[len - i * 2 - 1]) +
3172260684Skaiw		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3173260684Skaiw
3174260684Skaiw		if (byte < 0 || byte > 255)
3175260684Skaiw			return (NULL);
3176260684Skaiw
3177260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3178260684Skaiw		((unsigned char *)&f)[i] = (unsigned char)(byte);
3179260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3180260684Skaiw		((unsigned char *)&f)[sizeof(double) - i - 1] =
3181260684Skaiw		    (unsigned char)(byte);
3182260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3183260684Skaiw	}
3184260684Skaiw
3185260684Skaiw	rtn_len = 64;
3186260684Skaiw	limit = 0;
3187260684Skaiwagain:
3188260684Skaiw	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3189260684Skaiw		return (NULL);
3190260684Skaiw
3191260684Skaiw	if (snprintf(rtn, rtn_len, "%fld", f) >= (int)rtn_len) {
3192260684Skaiw		free(rtn);
3193260684Skaiw		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3194260684Skaiw			return (NULL);
3195260684Skaiw		rtn_len *= BUFFER_GROWFACTOR;
3196260684Skaiw		goto again;
3197260684Skaiw	}
3198260684Skaiw
3199260684Skaiw	return rtn;
3200260684Skaiw}
3201260684Skaiw
3202260684Skaiwstatic char *
3203260684Skaiwdecode_fp_to_float(const char *p, size_t len)
3204260684Skaiw{
3205260684Skaiw	size_t i, rtn_len, limit;
3206260684Skaiw	float f;
3207260684Skaiw	int byte;
3208260684Skaiw	char *rtn;
3209260684Skaiw
3210260684Skaiw	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(float))
3211260684Skaiw		return (NULL);
3212260684Skaiw
3213260684Skaiw	memset(&f, 0, sizeof(float));
3214260684Skaiw
3215260684Skaiw	for (i = 0; i < len / 2; ++i) {
3216260684Skaiw		byte = hex_to_dec(p[len - i * 2 - 1]) +
3217260684Skaiw		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3218260684Skaiw		if (byte < 0 || byte > 255)
3219260684Skaiw			return (NULL);
3220260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3221260684Skaiw		((unsigned char *)&f)[i] = (unsigned char)(byte);
3222260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3223260684Skaiw		((unsigned char *)&f)[sizeof(float) - i - 1] =
3224260684Skaiw		    (unsigned char)(byte);
3225260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3226260684Skaiw	}
3227260684Skaiw
3228260684Skaiw	rtn_len = 64;
3229260684Skaiw	limit = 0;
3230260684Skaiwagain:
3231260684Skaiw	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3232260684Skaiw		return (NULL);
3233260684Skaiw
3234260684Skaiw	if (snprintf(rtn, rtn_len, "%ff", f) >= (int)rtn_len) {
3235260684Skaiw		free(rtn);
3236260684Skaiw		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3237260684Skaiw			return (NULL);
3238260684Skaiw		rtn_len *= BUFFER_GROWFACTOR;
3239260684Skaiw		goto again;
3240260684Skaiw	}
3241260684Skaiw
3242260684Skaiw	return rtn;
3243260684Skaiw}
3244260684Skaiw
3245260684Skaiwstatic char *
3246260684Skaiwdecode_fp_to_float128(const char *p, size_t len)
3247260684Skaiw{
3248260684Skaiw	long double f;
3249260684Skaiw	size_t rtn_len, limit, i;
3250260684Skaiw	int byte;
3251260684Skaiw	unsigned char buf[FLOAT_QUADRUPLE_BYTES];
3252260684Skaiw	char *rtn;
3253260684Skaiw
3254260684Skaiw	switch(sizeof(long double)) {
3255260684Skaiw	case FLOAT_QUADRUPLE_BYTES:
3256260684Skaiw		return (decode_fp_to_long_double(p, len));
3257260684Skaiw	case FLOAT_EXTENED_BYTES:
3258260684Skaiw		if (p == NULL || len == 0 || len % 2 != 0 ||
3259260684Skaiw		    len / 2 > FLOAT_QUADRUPLE_BYTES)
3260260684Skaiw			return (NULL);
3261260684Skaiw
3262260684Skaiw		memset(buf, 0, FLOAT_QUADRUPLE_BYTES);
3263260684Skaiw
3264260684Skaiw		for (i = 0; i < len / 2; ++i) {
3265260684Skaiw			byte = hex_to_dec(p[len - i * 2 - 1]) +
3266260684Skaiw			    hex_to_dec(p[len - i * 2 - 2]) * 16;
3267260684Skaiw			if (byte < 0 || byte > 255)
3268260684Skaiw				return (NULL);
3269260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3270260684Skaiw			buf[i] = (unsigned char)(byte);
3271260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3272260684Skaiw			buf[FLOAT_QUADRUPLE_BYTES - i -1] =
3273260684Skaiw			    (unsigned char)(byte);
3274260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3275260684Skaiw		}
3276260684Skaiw		memset(&f, 0, FLOAT_EXTENED_BYTES);
3277260684Skaiw
3278260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3279260684Skaiw		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
3280260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3281260684Skaiw		memcpy(&f, buf + 6, FLOAT_EXTENED_BYTES);
3282260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3283260684Skaiw
3284260684Skaiw		rtn_len = 256;
3285260684Skaiw		limit = 0;
3286260684Skaiwagain:
3287260684Skaiw		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3288260684Skaiw			return (NULL);
3289260684Skaiw
3290260684Skaiw		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3291260684Skaiw			free(rtn);
3292260684Skaiw			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3293260684Skaiw				return (NULL);
3294260684Skaiw			rtn_len *= BUFFER_GROWFACTOR;
3295260684Skaiw			goto again;
3296260684Skaiw		}
3297260684Skaiw
3298260684Skaiw		return (rtn);
3299260684Skaiw	default:
3300260684Skaiw		return (NULL);
3301260684Skaiw	}
3302260684Skaiw}
3303260684Skaiw
3304260684Skaiwstatic char *
3305260684Skaiwdecode_fp_to_float80(const char *p, size_t len)
3306260684Skaiw{
3307260684Skaiw	long double f;
3308260684Skaiw	size_t rtn_len, limit, i;
3309260684Skaiw	int byte;
3310260684Skaiw	unsigned char buf[FLOAT_EXTENED_BYTES];
3311260684Skaiw	char *rtn;
3312260684Skaiw
3313260684Skaiw	switch(sizeof(long double)) {
3314260684Skaiw	case FLOAT_QUADRUPLE_BYTES:
3315260684Skaiw		if (p == NULL || len == 0 || len % 2 != 0 ||
3316260684Skaiw		    len / 2 > FLOAT_EXTENED_BYTES)
3317260684Skaiw			return (NULL);
3318260684Skaiw
3319260684Skaiw		memset(buf, 0, FLOAT_EXTENED_BYTES);
3320260684Skaiw
3321260684Skaiw		for (i = 0; i < len / 2; ++i) {
3322260684Skaiw			byte = hex_to_dec(p[len - i * 2 - 1]) +
3323260684Skaiw			    hex_to_dec(p[len - i * 2 - 2]) * 16;
3324260684Skaiw
3325260684Skaiw			if (byte < 0 || byte > 255)
3326260684Skaiw				return (NULL);
3327260684Skaiw
3328260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3329260684Skaiw			buf[i] = (unsigned char)(byte);
3330260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3331260684Skaiw			buf[FLOAT_EXTENED_BYTES - i -1] =
3332260684Skaiw			    (unsigned char)(byte);
3333260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3334260684Skaiw		}
3335260684Skaiw
3336260684Skaiw		memset(&f, 0, FLOAT_QUADRUPLE_BYTES);
3337260684Skaiw
3338260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3339260684Skaiw		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
3340260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3341260684Skaiw		memcpy((unsigned char *)(&f) + 6, buf, FLOAT_EXTENED_BYTES);
3342260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3343260684Skaiw
3344260684Skaiw		rtn_len = 256;
3345260684Skaiw		limit = 0;
3346260684Skaiwagain:
3347260684Skaiw		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3348260684Skaiw			return (NULL);
3349260684Skaiw
3350260684Skaiw		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3351260684Skaiw			free(rtn);
3352260684Skaiw			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3353260684Skaiw				return (NULL);
3354260684Skaiw			rtn_len *= BUFFER_GROWFACTOR;
3355260684Skaiw			goto again;
3356260684Skaiw		}
3357260684Skaiw
3358260684Skaiw		return (rtn);
3359260684Skaiw	case FLOAT_EXTENED_BYTES:
3360260684Skaiw		return (decode_fp_to_long_double(p, len));
3361260684Skaiw	default:
3362260684Skaiw		return (NULL);
3363260684Skaiw	}
3364260684Skaiw}
3365260684Skaiw
3366260684Skaiwstatic char *
3367260684Skaiwdecode_fp_to_long_double(const char *p, size_t len)
3368260684Skaiw{
3369260684Skaiw	long double f;
3370260684Skaiw	size_t rtn_len, limit, i;
3371260684Skaiw	int byte;
3372260684Skaiw	char *rtn;
3373260684Skaiw
3374260684Skaiw	if (p == NULL || len == 0 || len % 2 != 0 ||
3375260684Skaiw	    len / 2 > sizeof(long double))
3376260684Skaiw		return (NULL);
3377260684Skaiw
3378260684Skaiw	memset(&f, 0, sizeof(long double));
3379260684Skaiw
3380260684Skaiw	for (i = 0; i < len / 2; ++i) {
3381260684Skaiw		byte = hex_to_dec(p[len - i * 2 - 1]) +
3382260684Skaiw		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3383260684Skaiw
3384260684Skaiw		if (byte < 0 || byte > 255)
3385260684Skaiw			return (NULL);
3386260684Skaiw
3387260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3388260684Skaiw		((unsigned char *)&f)[i] = (unsigned char)(byte);
3389260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3390260684Skaiw		((unsigned char *)&f)[sizeof(long double) - i - 1] =
3391260684Skaiw		    (unsigned char)(byte);
3392260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3393260684Skaiw	}
3394260684Skaiw
3395260684Skaiw	rtn_len = 256;
3396260684Skaiw	limit = 0;
3397260684Skaiwagain:
3398260684Skaiw	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3399260684Skaiw		return (NULL);
3400260684Skaiw
3401260684Skaiw	if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3402260684Skaiw		free(rtn);
3403260684Skaiw		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3404260684Skaiw			return (NULL);
3405260684Skaiw		rtn_len *= BUFFER_GROWFACTOR;
3406260684Skaiw		goto again;
3407260684Skaiw	}
3408260684Skaiw
3409260684Skaiw	return (rtn);
3410260684Skaiw}
3411260684Skaiw
3412260684Skaiw/* Simple hex to integer function used by decode_to_* function. */
3413260684Skaiwstatic int
3414260684Skaiwhex_to_dec(char c)
3415260684Skaiw{
3416260684Skaiw
3417260684Skaiw	switch (c) {
3418260684Skaiw	case '0':
3419260684Skaiw		return (0);
3420260684Skaiw	case '1':
3421260684Skaiw		return (1);
3422260684Skaiw	case '2':
3423260684Skaiw		return (2);
3424260684Skaiw	case '3':
3425260684Skaiw		return (3);
3426260684Skaiw	case '4':
3427260684Skaiw		return (4);
3428260684Skaiw	case '5':
3429260684Skaiw		return (5);
3430260684Skaiw	case '6':
3431260684Skaiw		return (6);
3432260684Skaiw	case '7':
3433260684Skaiw		return (7);
3434260684Skaiw	case '8':
3435260684Skaiw		return (8);
3436260684Skaiw	case '9':
3437260684Skaiw		return (9);
3438260684Skaiw	case 'a':
3439260684Skaiw		return (10);
3440260684Skaiw	case 'b':
3441260684Skaiw		return (11);
3442260684Skaiw	case 'c':
3443260684Skaiw		return (12);
3444260684Skaiw	case 'd':
3445260684Skaiw		return (13);
3446260684Skaiw	case 'e':
3447260684Skaiw		return (14);
3448260684Skaiw	case 'f':
3449260684Skaiw		return (15);
3450260684Skaiw	default:
3451260684Skaiw		return (-1);
3452300311Semaste	}
3453260684Skaiw}
3454260684Skaiw
3455260684Skaiw/**
3456260684Skaiw * @brief Test input string is mangled by IA-64 C++ ABI style.
3457260684Skaiw *
3458260684Skaiw * Test string heads with "_Z" or "_GLOBAL__I_".
3459260684Skaiw * @return Return 0 at false.
3460260684Skaiw */
3461260684Skaiwbool
3462260684Skaiwis_cpp_mangled_gnu3(const char *org)
3463260684Skaiw{
3464260684Skaiw	size_t len;
3465260684Skaiw
3466260684Skaiw	len = strlen(org);
3467260684Skaiw	return ((len > 2 && *org == '_' && *(org + 1) == 'Z') ||
3468260684Skaiw	    (len > 11 && !strncmp(org, "_GLOBAL__I_", 11)));
3469260684Skaiw}
3470260684Skaiw
3471260684Skaiwstatic void
3472260684Skaiwvector_read_cmd_dest(struct vector_read_cmd *v)
3473260684Skaiw{
3474260684Skaiw
3475260684Skaiw	if (v == NULL)
3476260684Skaiw		return;
3477260684Skaiw
3478260684Skaiw	free(v->r_container);
3479260684Skaiw}
3480260684Skaiw
3481260684Skaiw/* return -1 at failed, 0 at not found, 1 at found. */
3482260684Skaiwstatic int
3483260684Skaiwvector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst)
3484260684Skaiw{
3485260684Skaiw	size_t i;
3486260684Skaiw
3487260684Skaiw	if (v == NULL || dst == READ_FAIL)
3488260684Skaiw		return (-1);
3489260684Skaiw
3490260684Skaiw	for (i = 0; i < v->size; ++i)
3491260684Skaiw		if (v->r_container[i] == dst)
3492260684Skaiw			return (1);
3493260684Skaiw
3494260684Skaiw	return (0);
3495260684Skaiw}
3496260684Skaiw
3497260684Skaiwstatic int
3498260684Skaiwvector_read_cmd_init(struct vector_read_cmd *v)
3499260684Skaiw{
3500260684Skaiw
3501260684Skaiw	if (v == NULL)
3502260684Skaiw		return (0);
3503260684Skaiw
3504260684Skaiw	v->size = 0;
3505260684Skaiw	v->capacity = VECTOR_DEF_CAPACITY;
3506260684Skaiw
3507260684Skaiw	if ((v->r_container = malloc(sizeof(enum read_cmd) * v->capacity))
3508260684Skaiw	    == NULL)
3509260684Skaiw		return (0);
3510260684Skaiw
3511260684Skaiw	return (1);
3512260684Skaiw}
3513260684Skaiw
3514260684Skaiwstatic int
3515260684Skaiwvector_read_cmd_pop(struct vector_read_cmd *v)
3516260684Skaiw{
3517260684Skaiw
3518260684Skaiw	if (v == NULL || v->size == 0)
3519260684Skaiw		return (0);
3520260684Skaiw
3521260684Skaiw	--v->size;
3522260684Skaiw	v->r_container[v->size] = READ_FAIL;
3523260684Skaiw
3524260684Skaiw	return (1);
3525260684Skaiw}
3526260684Skaiw
3527260684Skaiwstatic int
3528260684Skaiwvector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd)
3529260684Skaiw{
3530260684Skaiw	enum read_cmd *tmp_r_ctn;
3531260684Skaiw	size_t tmp_cap;
3532260684Skaiw	size_t i;
3533260684Skaiw
3534260684Skaiw	if (v == NULL)
3535260684Skaiw		return (0);
3536260684Skaiw
3537260684Skaiw	if (v->size == v->capacity) {
3538260684Skaiw		tmp_cap = v->capacity * BUFFER_GROWFACTOR;
3539260684Skaiw		if ((tmp_r_ctn = malloc(sizeof(enum read_cmd) * tmp_cap))
3540260684Skaiw		    == NULL)
3541260684Skaiw			return (0);
3542260684Skaiw		for (i = 0; i < v->size; ++i)
3543260684Skaiw			tmp_r_ctn[i] = v->r_container[i];
3544260684Skaiw		free(v->r_container);
3545260684Skaiw		v->r_container = tmp_r_ctn;
3546260684Skaiw		v->capacity = tmp_cap;
3547260684Skaiw	}
3548260684Skaiw
3549260684Skaiw	v->r_container[v->size] = cmd;
3550260684Skaiw	++v->size;
3551260684Skaiw
3552260684Skaiw	return (1);
3553260684Skaiw}
3554260684Skaiw
3555260684Skaiwstatic void
3556260684Skaiwvector_type_qualifier_dest(struct vector_type_qualifier *v)
3557260684Skaiw{
3558260684Skaiw
3559260684Skaiw	if (v == NULL)
3560260684Skaiw		return;
3561260684Skaiw
3562260684Skaiw	free(v->q_container);
3563260684Skaiw	vector_str_dest(&v->ext_name);
3564260684Skaiw}
3565260684Skaiw
3566260684Skaiw/* size, capacity, ext_name */
3567260684Skaiwstatic int
3568260684Skaiwvector_type_qualifier_init(struct vector_type_qualifier *v)
3569260684Skaiw{
3570260684Skaiw
3571260684Skaiw	if (v == NULL)
3572260684Skaiw		return (0);
3573260684Skaiw
3574260684Skaiw	v->size = 0;
3575260684Skaiw	v->capacity = VECTOR_DEF_CAPACITY;
3576260684Skaiw
3577260684Skaiw	if ((v->q_container = malloc(sizeof(enum type_qualifier) * v->capacity))
3578260684Skaiw	    == NULL)
3579260684Skaiw		return (0);
3580260684Skaiw
3581260684Skaiw	assert(v->q_container != NULL);
3582260684Skaiw
3583260684Skaiw	if (vector_str_init(&v->ext_name) == false) {
3584260684Skaiw		free(v->q_container);
3585260684Skaiw		return (0);
3586260684Skaiw	}
3587260684Skaiw
3588260684Skaiw	return (1);
3589260684Skaiw}
3590260684Skaiw
3591260684Skaiwstatic int
3592260684Skaiwvector_type_qualifier_push(struct vector_type_qualifier *v,
3593260684Skaiw    enum type_qualifier t)
3594260684Skaiw{
3595260684Skaiw	enum type_qualifier *tmp_ctn;
3596260684Skaiw	size_t tmp_cap;
3597260684Skaiw	size_t i;
3598260684Skaiw
3599260684Skaiw	if (v == NULL)
3600260684Skaiw		return (0);
3601260684Skaiw
3602260684Skaiw	if (v->size == v->capacity) {
3603260684Skaiw		tmp_cap = v->capacity * BUFFER_GROWFACTOR;
3604260684Skaiw		if ((tmp_ctn = malloc(sizeof(enum type_qualifier) * tmp_cap))
3605260684Skaiw		    == NULL)
3606260684Skaiw			return (0);
3607260684Skaiw		for (i = 0; i < v->size; ++i)
3608260684Skaiw			tmp_ctn[i] = v->q_container[i];
3609260684Skaiw		free(v->q_container);
3610260684Skaiw		v->q_container = tmp_ctn;
3611260684Skaiw		v->capacity = tmp_cap;
3612260684Skaiw	}
3613260684Skaiw
3614260684Skaiw	v->q_container[v->size] = t;
3615260684Skaiw	++v->size;
3616260684Skaiw
3617260684Skaiw	return (1);
3618260684Skaiw}
3619