libelftc_dem_gnu3.c revision 260684
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
39260684SkaiwELFTC_VCSID("$Id: libelftc_dem_gnu3.c 2179 2011-11-18 03:05:47Z jkoshy $");
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,
53260684Skaiw	TYPE_CST
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 */
87260684Skaiw};
88260684Skaiw
89260684Skaiw#define	CPP_DEMANGLE_TRY_LIMIT	128
90260684Skaiw#define	FLOAT_SPRINTF_TRY_LIMIT	5
91260684Skaiw#define	FLOAT_QUADRUPLE_BYTES	16
92260684Skaiw#define	FLOAT_EXTENED_BYTES	10
93260684Skaiw
94260684Skaiw#define SIMPLE_HASH(x,y)	(64 * x + y)
95260684Skaiw
96260684Skaiwstatic void	cpp_demangle_data_dest(struct cpp_demangle_data *);
97260684Skaiwstatic int	cpp_demangle_data_init(struct cpp_demangle_data *,
98260684Skaiw		    const char *);
99260684Skaiwstatic int	cpp_demangle_get_subst(struct cpp_demangle_data *, size_t);
100260684Skaiwstatic int	cpp_demangle_get_tmpl_param(struct cpp_demangle_data *, size_t);
101260684Skaiwstatic int	cpp_demangle_push_fp(struct cpp_demangle_data *,
102260684Skaiw		    char *(*)(const char *, size_t));
103260684Skaiwstatic int	cpp_demangle_push_str(struct cpp_demangle_data *, const char *,
104260684Skaiw		    size_t);
105260684Skaiwstatic int	cpp_demangle_push_subst(struct cpp_demangle_data *,
106260684Skaiw		    const char *, size_t);
107260684Skaiwstatic int	cpp_demangle_push_subst_v(struct cpp_demangle_data *,
108260684Skaiw		    struct vector_str *);
109260684Skaiwstatic int	cpp_demangle_push_type_qualifier(struct cpp_demangle_data *,
110260684Skaiw		    struct vector_type_qualifier *, const char *);
111260684Skaiwstatic int	cpp_demangle_read_array(struct cpp_demangle_data *);
112260684Skaiwstatic int	cpp_demangle_read_encoding(struct cpp_demangle_data *);
113260684Skaiwstatic int	cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
114260684Skaiwstatic int	cpp_demangle_read_expression(struct cpp_demangle_data *);
115260684Skaiwstatic int	cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
116260684Skaiw		    const char *, size_t);
117260684Skaiwstatic int	cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
118260684Skaiw		    const char *, size_t);
119260684Skaiwstatic int	cpp_demangle_read_expression_trinary(struct cpp_demangle_data *,
120260684Skaiw		    const char *, size_t, const char *, size_t);
121260684Skaiwstatic int	cpp_demangle_read_function(struct cpp_demangle_data *, int *,
122260684Skaiw		    struct vector_type_qualifier *);
123260684Skaiwstatic int	cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
124260684Skaiwstatic int	cpp_demangle_read_local_name(struct cpp_demangle_data *);
125260684Skaiwstatic int	cpp_demangle_read_name(struct cpp_demangle_data *);
126260684Skaiwstatic int	cpp_demangle_read_nested_name(struct cpp_demangle_data *);
127260684Skaiwstatic int	cpp_demangle_read_number(struct cpp_demangle_data *, long *);
128260684Skaiwstatic int	cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
129260684Skaiwstatic int	cpp_demangle_read_offset(struct cpp_demangle_data *);
130260684Skaiwstatic int	cpp_demangle_read_offset_number(struct cpp_demangle_data *);
131260684Skaiwstatic int	cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *);
132260684Skaiwstatic int	cpp_demangle_read_sname(struct cpp_demangle_data *);
133260684Skaiwstatic int	cpp_demangle_read_subst(struct cpp_demangle_data *);
134260684Skaiwstatic int	cpp_demangle_read_subst_std(struct cpp_demangle_data *);
135260684Skaiwstatic int	cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *,
136260684Skaiw		    const char *, size_t);
137260684Skaiwstatic int	cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
138260684Skaiwstatic int	cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
139260684Skaiwstatic int	cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
140260684Skaiwstatic int	cpp_demangle_read_type(struct cpp_demangle_data *, int);
141260684Skaiwstatic int	cpp_demangle_read_uqname(struct cpp_demangle_data *);
142260684Skaiwstatic int	cpp_demangle_read_v_offset(struct cpp_demangle_data *);
143260684Skaiwstatic char	*decode_fp_to_double(const char *, size_t);
144260684Skaiwstatic char	*decode_fp_to_float(const char *, size_t);
145260684Skaiwstatic char	*decode_fp_to_float128(const char *, size_t);
146260684Skaiwstatic char	*decode_fp_to_float80(const char *, size_t);
147260684Skaiwstatic char	*decode_fp_to_long_double(const char *, size_t);
148260684Skaiwstatic int	hex_to_dec(char);
149260684Skaiwstatic void	vector_read_cmd_dest(struct vector_read_cmd *);
150260684Skaiwstatic int	vector_read_cmd_find(struct vector_read_cmd *, enum read_cmd);
151260684Skaiwstatic int	vector_read_cmd_init(struct vector_read_cmd *);
152260684Skaiwstatic int	vector_read_cmd_pop(struct vector_read_cmd *);
153260684Skaiwstatic int	vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd);
154260684Skaiwstatic void	vector_type_qualifier_dest(struct vector_type_qualifier *);
155260684Skaiwstatic int	vector_type_qualifier_init(struct vector_type_qualifier *);
156260684Skaiwstatic int	vector_type_qualifier_push(struct vector_type_qualifier *,
157260684Skaiw		    enum type_qualifier);
158260684Skaiw
159260684Skaiwint cpp_demangle_gnu3_push_head;
160260684Skaiw
161260684Skaiw/**
162260684Skaiw * @brief Decode the input string by IA-64 C++ ABI style.
163260684Skaiw *
164260684Skaiw * GNU GCC v3 use IA-64 standard ABI.
165260684Skaiw * @return New allocated demangled string or NULL if failed.
166260684Skaiw * @todo 1. Testing and more test case. 2. Code cleaning.
167260684Skaiw */
168260684Skaiwchar *
169260684Skaiwcpp_demangle_gnu3(const char *org)
170260684Skaiw{
171260684Skaiw	struct cpp_demangle_data ddata;
172260684Skaiw	ssize_t org_len;
173260684Skaiw	unsigned int limit;
174260684Skaiw	char *rtn;
175260684Skaiw
176260684Skaiw	if (org == NULL || (org_len = strlen(org)) < 2)
177260684Skaiw		return (NULL);
178260684Skaiw
179260684Skaiw	if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) {
180260684Skaiw		if ((rtn = malloc(org_len + 19)) == NULL)
181260684Skaiw			return (NULL);
182260684Skaiw		snprintf(rtn, org_len + 19,
183260684Skaiw		    "global constructors keyed to %s", org + 11);
184260684Skaiw		return (rtn);
185260684Skaiw	}
186260684Skaiw
187260684Skaiw	if (org[0] != '_' || org[1] != 'Z')
188260684Skaiw		return (NULL);
189260684Skaiw
190260684Skaiw	if (!cpp_demangle_data_init(&ddata, org + 2))
191260684Skaiw		return (NULL);
192260684Skaiw
193260684Skaiw	cpp_demangle_gnu3_push_head = 0;
194260684Skaiw	rtn = NULL;
195260684Skaiw
196260684Skaiw	if (!cpp_demangle_read_encoding(&ddata))
197260684Skaiw		goto clean;
198260684Skaiw
199260684Skaiw	limit = 0;
200260684Skaiw	while (*ddata.cur != '\0') {
201260684Skaiw		/*
202260684Skaiw		 * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4
203260684Skaiw		 */
204260684Skaiw		if (*ddata.cur == '@' && *(ddata.cur + 1) == '@')
205260684Skaiw			break;
206260684Skaiw		if (!cpp_demangle_read_type(&ddata, 1))
207260684Skaiw			goto clean;
208260684Skaiw		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
209260684Skaiw			goto clean;
210260684Skaiw	}
211260684Skaiw
212260684Skaiw	if (ddata.output.size == 0)
213260684Skaiw		goto clean;
214260684Skaiw	if (ddata.paren && !vector_str_push(&ddata.output, ")", 1))
215260684Skaiw		goto clean;
216260684Skaiw	if (ddata.mem_vat && !vector_str_push(&ddata.output, " volatile", 9))
217260684Skaiw		goto clean;
218260684Skaiw	if (ddata.mem_cst && !vector_str_push(&ddata.output, " const", 6))
219260684Skaiw		goto clean;
220260684Skaiw	if (ddata.mem_rst && !vector_str_push(&ddata.output, " restrict", 9))
221260684Skaiw		goto clean;
222260684Skaiw
223260684Skaiw	rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
224260684Skaiw
225260684Skaiwclean:
226260684Skaiw	cpp_demangle_data_dest(&ddata);
227260684Skaiw
228260684Skaiw	return (rtn);
229260684Skaiw}
230260684Skaiw
231260684Skaiwstatic void
232260684Skaiwcpp_demangle_data_dest(struct cpp_demangle_data *d)
233260684Skaiw{
234260684Skaiw
235260684Skaiw	if (d == NULL)
236260684Skaiw		return;
237260684Skaiw
238260684Skaiw	vector_read_cmd_dest(&d->cmd);
239260684Skaiw	vector_str_dest(&d->class_type);
240260684Skaiw	vector_str_dest(&d->tmpl);
241260684Skaiw	vector_str_dest(&d->subst);
242260684Skaiw	vector_str_dest(&d->output_tmp);
243260684Skaiw	vector_str_dest(&d->output);
244260684Skaiw}
245260684Skaiw
246260684Skaiwstatic int
247260684Skaiwcpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
248260684Skaiw{
249260684Skaiw
250260684Skaiw	if (d == NULL || cur == NULL)
251260684Skaiw		return (0);
252260684Skaiw
253260684Skaiw	if (!vector_str_init(&d->output))
254260684Skaiw		return (0);
255260684Skaiw	if (!vector_str_init(&d->output_tmp))
256260684Skaiw		goto clean1;
257260684Skaiw	if (!vector_str_init(&d->subst))
258260684Skaiw		goto clean2;
259260684Skaiw	if (!vector_str_init(&d->tmpl))
260260684Skaiw		goto clean3;
261260684Skaiw	if (!vector_str_init(&d->class_type))
262260684Skaiw		goto clean4;
263260684Skaiw	if (!vector_read_cmd_init(&d->cmd))
264260684Skaiw		goto clean5;
265260684Skaiw
266260684Skaiw	assert(d->output.container != NULL);
267260684Skaiw	assert(d->output_tmp.container != NULL);
268260684Skaiw	assert(d->subst.container != NULL);
269260684Skaiw	assert(d->tmpl.container != NULL);
270260684Skaiw	assert(d->class_type.container != NULL);
271260684Skaiw
272260684Skaiw	d->paren = false;
273260684Skaiw	d->pfirst = false;
274260684Skaiw	d->mem_rst = false;
275260684Skaiw	d->mem_vat = false;
276260684Skaiw	d->mem_cst = false;
277260684Skaiw	d->func_type = 0;
278260684Skaiw	d->cur = cur;
279260684Skaiw	d->last_sname = NULL;
280260684Skaiw
281260684Skaiw	return (1);
282260684Skaiw
283260684Skaiwclean5:
284260684Skaiw	vector_str_dest(&d->class_type);
285260684Skaiwclean4:
286260684Skaiw	vector_str_dest(&d->tmpl);
287260684Skaiwclean3:
288260684Skaiw	vector_str_dest(&d->subst);
289260684Skaiwclean2:
290260684Skaiw	vector_str_dest(&d->output_tmp);
291260684Skaiwclean1:
292260684Skaiw	vector_str_dest(&d->output);
293260684Skaiw
294260684Skaiw	return (0);
295260684Skaiw}
296260684Skaiw
297260684Skaiwstatic int
298260684Skaiwcpp_demangle_push_fp(struct cpp_demangle_data *ddata,
299260684Skaiw    char *(*decoder)(const char *, size_t))
300260684Skaiw{
301260684Skaiw	size_t len;
302260684Skaiw	int rtn;
303260684Skaiw	const char *fp;
304260684Skaiw	char *f;
305260684Skaiw
306260684Skaiw	if (ddata == NULL || decoder == NULL)
307260684Skaiw		return (0);
308260684Skaiw
309260684Skaiw	fp = ddata->cur;
310260684Skaiw	while (*ddata->cur != 'E')
311260684Skaiw		++ddata->cur;
312260684Skaiw	++ddata->cur;
313260684Skaiw
314260684Skaiw	if ((f = decoder(fp, ddata->cur - fp)) == NULL)
315260684Skaiw		return (0);
316260684Skaiw
317260684Skaiw	rtn = 0;
318260684Skaiw	if ((len = strlen(f)) > 0)
319260684Skaiw	    rtn = cpp_demangle_push_str(ddata, f, len);
320260684Skaiw
321260684Skaiw	free(f);
322260684Skaiw
323260684Skaiw	return (rtn);
324260684Skaiw}
325260684Skaiw
326260684Skaiwstatic int
327260684Skaiwcpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
328260684Skaiw    size_t len)
329260684Skaiw{
330260684Skaiw
331260684Skaiw	if (ddata == NULL || str == NULL || len == 0)
332260684Skaiw		return (0);
333260684Skaiw
334260684Skaiw	if (cpp_demangle_gnu3_push_head > 0)
335260684Skaiw		return (vector_str_push(&ddata->output_tmp, str, len));
336260684Skaiw
337260684Skaiw	return (vector_str_push(&ddata->output, str, len));
338260684Skaiw}
339260684Skaiw
340260684Skaiwstatic int
341260684Skaiwcpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str,
342260684Skaiw    size_t len)
343260684Skaiw{
344260684Skaiw
345260684Skaiw	if (ddata == NULL || str == NULL || len == 0)
346260684Skaiw		return (0);
347260684Skaiw
348260684Skaiw	if (!vector_str_find(&ddata->subst, str, len))
349260684Skaiw		return (vector_str_push(&ddata->subst, str, len));
350260684Skaiw
351260684Skaiw	return (1);
352260684Skaiw}
353260684Skaiw
354260684Skaiwstatic int
355260684Skaiwcpp_demangle_push_subst_v(struct cpp_demangle_data *ddata, struct vector_str *v)
356260684Skaiw{
357260684Skaiw	size_t str_len;
358260684Skaiw	int rtn;
359260684Skaiw	char *str;
360260684Skaiw
361260684Skaiw	if (ddata == NULL || v == NULL)
362260684Skaiw		return (0);
363260684Skaiw
364260684Skaiw	if ((str = vector_str_get_flat(v, &str_len)) == NULL)
365260684Skaiw		return (0);
366260684Skaiw
367260684Skaiw	rtn = cpp_demangle_push_subst(ddata, str, str_len);
368260684Skaiw
369260684Skaiw	free(str);
370260684Skaiw
371260684Skaiw	return (rtn);
372260684Skaiw}
373260684Skaiw
374260684Skaiwstatic int
375260684Skaiwcpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
376260684Skaiw    struct vector_type_qualifier *v, const char *type_str)
377260684Skaiw{
378260684Skaiw	struct vector_str subst_v;
379260684Skaiw	size_t idx, e_idx, e_len;
380260684Skaiw	int rtn;
381260684Skaiw	char *buf;
382260684Skaiw
383260684Skaiw	if (ddata == NULL || v == NULL)
384260684Skaiw		return (0);
385260684Skaiw
386260684Skaiw	if ((idx = v->size) == 0)
387260684Skaiw		return (1);
388260684Skaiw
389260684Skaiw	rtn = 0;
390260684Skaiw	if (type_str != NULL) {
391260684Skaiw		if (!vector_str_init(&subst_v))
392260684Skaiw			return (0);
393260684Skaiw		if (!vector_str_push(&subst_v, type_str, strlen(type_str)))
394260684Skaiw			goto clean;
395260684Skaiw	}
396260684Skaiw
397260684Skaiw	e_idx = 0;
398260684Skaiw	while (idx > 0) {
399260684Skaiw		switch (v->q_container[idx - 1]) {
400260684Skaiw		case TYPE_PTR:
401260684Skaiw			if (!cpp_demangle_push_str(ddata, "*", 1))
402260684Skaiw				goto clean;
403260684Skaiw			if (type_str != NULL) {
404260684Skaiw				if (!vector_str_push(&subst_v, "*", 1))
405260684Skaiw					goto clean;
406260684Skaiw				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
407260684Skaiw					goto clean;
408260684Skaiw			}
409260684Skaiw			break;
410260684Skaiw
411260684Skaiw		case TYPE_REF:
412260684Skaiw			if (!cpp_demangle_push_str(ddata, "&", 1))
413260684Skaiw				goto clean;
414260684Skaiw			if (type_str != NULL) {
415260684Skaiw				if (!vector_str_push(&subst_v, "&", 1))
416260684Skaiw					goto clean;
417260684Skaiw				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
418260684Skaiw					goto clean;
419260684Skaiw			}
420260684Skaiw			break;
421260684Skaiw
422260684Skaiw		case TYPE_CMX:
423260684Skaiw			if (!cpp_demangle_push_str(ddata, " complex", 8))
424260684Skaiw				goto clean;
425260684Skaiw			if (type_str != NULL) {
426260684Skaiw				if (!vector_str_push(&subst_v, " complex", 8))
427260684Skaiw					goto clean;
428260684Skaiw				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
429260684Skaiw					goto clean;
430260684Skaiw			}
431260684Skaiw			break;
432260684Skaiw
433260684Skaiw		case TYPE_IMG:
434260684Skaiw			if (!cpp_demangle_push_str(ddata, " imaginary", 10))
435260684Skaiw				goto clean;
436260684Skaiw			if (type_str != NULL) {
437260684Skaiw				if (!vector_str_push(&subst_v, " imaginary", 10))
438260684Skaiw					goto clean;
439260684Skaiw				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
440260684Skaiw					goto clean;
441260684Skaiw			}
442260684Skaiw			break;
443260684Skaiw
444260684Skaiw		case TYPE_EXT:
445260684Skaiw			if (e_idx > v->ext_name.size - 1)
446260684Skaiw				goto clean;
447260684Skaiw			if ((e_len = strlen(v->ext_name.container[e_idx])) == 0)
448260684Skaiw				goto clean;
449260684Skaiw			if ((buf = malloc(sizeof(char) * (e_len + 1))) == NULL)
450260684Skaiw				goto clean;
451260684Skaiw
452260684Skaiw			memcpy(buf, " ", 1);
453260684Skaiw			memcpy(buf + 1, v->ext_name.container[e_idx], e_len);
454260684Skaiw
455260684Skaiw			if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) {
456260684Skaiw				free(buf);
457260684Skaiw				goto clean;
458260684Skaiw			}
459260684Skaiw
460260684Skaiw			if (type_str != NULL) {
461260684Skaiw				if (!vector_str_push(&subst_v, buf,
462260684Skaiw				    e_len + 1)) {
463260684Skaiw					free(buf);
464260684Skaiw					goto clean;
465260684Skaiw				}
466260684Skaiw				if (!cpp_demangle_push_subst_v(ddata, &subst_v)) {
467260684Skaiw					free(buf);
468260684Skaiw					goto clean;
469260684Skaiw				}
470260684Skaiw			}
471260684Skaiw			free(buf);
472260684Skaiw			++e_idx;
473260684Skaiw			break;
474260684Skaiw
475260684Skaiw		case TYPE_RST:
476260684Skaiw			if (!cpp_demangle_push_str(ddata, " restrict", 9))
477260684Skaiw				goto clean;
478260684Skaiw			if (type_str != NULL) {
479260684Skaiw				if (!vector_str_push(&subst_v, " restrict", 9))
480260684Skaiw					goto clean;
481260684Skaiw				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
482260684Skaiw					goto clean;
483260684Skaiw			}
484260684Skaiw			break;
485260684Skaiw
486260684Skaiw		case TYPE_VAT:
487260684Skaiw			if (!cpp_demangle_push_str(ddata, " volatile", 9))
488260684Skaiw				goto clean;
489260684Skaiw			if (type_str != NULL) {
490260684Skaiw				if (!vector_str_push(&subst_v, " volatile", 9))
491260684Skaiw					goto clean;
492260684Skaiw				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
493260684Skaiw					goto clean;
494260684Skaiw			}
495260684Skaiw			break;
496260684Skaiw
497260684Skaiw		case TYPE_CST:
498260684Skaiw			if (!cpp_demangle_push_str(ddata, " const", 6))
499260684Skaiw				goto clean;
500260684Skaiw			if (type_str != NULL) {
501260684Skaiw				if (!vector_str_push(&subst_v, " const", 6))
502260684Skaiw					goto clean;
503260684Skaiw				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
504260684Skaiw					goto clean;
505260684Skaiw			}
506260684Skaiw			break;
507260684Skaiw
508260684Skaiw		};
509260684Skaiw		--idx;
510260684Skaiw	}
511260684Skaiw
512260684Skaiw	rtn = 1;
513260684Skaiwclean:
514260684Skaiw	if (type_str != NULL)
515260684Skaiw		vector_str_dest(&subst_v);
516260684Skaiw
517260684Skaiw	return (rtn);
518260684Skaiw}
519260684Skaiw
520260684Skaiwstatic int
521260684Skaiwcpp_demangle_get_subst(struct cpp_demangle_data *ddata, size_t idx)
522260684Skaiw{
523260684Skaiw	size_t len;
524260684Skaiw
525260684Skaiw	if (ddata == NULL || ddata->subst.size <= idx)
526260684Skaiw		return (0);
527260684Skaiw	if ((len = strlen(ddata->subst.container[idx])) == 0)
528260684Skaiw		return (0);
529260684Skaiw	if (!cpp_demangle_push_str(ddata, ddata->subst.container[idx], len))
530260684Skaiw		return (0);
531260684Skaiw
532260684Skaiw	/* skip '_' */
533260684Skaiw	++ddata->cur;
534260684Skaiw
535260684Skaiw	return (1);
536260684Skaiw}
537260684Skaiw
538260684Skaiwstatic int
539260684Skaiwcpp_demangle_get_tmpl_param(struct cpp_demangle_data *ddata, size_t idx)
540260684Skaiw{
541260684Skaiw	size_t len;
542260684Skaiw
543260684Skaiw	if (ddata == NULL || ddata->tmpl.size <= idx)
544260684Skaiw		return (0);
545260684Skaiw	if ((len = strlen(ddata->tmpl.container[idx])) == 0)
546260684Skaiw		return (0);
547260684Skaiw	if (!cpp_demangle_push_str(ddata, ddata->tmpl.container[idx], len))
548260684Skaiw		return (0);
549260684Skaiw
550260684Skaiw	++ddata->cur;
551260684Skaiw
552260684Skaiw	return (1);
553260684Skaiw}
554260684Skaiw
555260684Skaiwstatic int
556260684Skaiwcpp_demangle_read_array(struct cpp_demangle_data *ddata)
557260684Skaiw{
558260684Skaiw	size_t i, num_len, exp_len, p_idx, idx;
559260684Skaiw	const char *num;
560260684Skaiw	char *exp;
561260684Skaiw
562260684Skaiw	if (ddata == NULL || *(++ddata->cur) == '\0')
563260684Skaiw		return (0);
564260684Skaiw
565260684Skaiw	if (*ddata->cur == '_') {
566260684Skaiw		if (*(++ddata->cur) == '\0')
567260684Skaiw			return (0);
568260684Skaiw
569260684Skaiw		if (!cpp_demangle_read_type(ddata, 0))
570260684Skaiw			return (0);
571260684Skaiw
572260684Skaiw		if (!cpp_demangle_push_str(ddata, "[]", 2))
573260684Skaiw			return (0);
574260684Skaiw	} else {
575260684Skaiw		if (ELFTC_ISDIGIT(*ddata->cur) != 0) {
576260684Skaiw			num = ddata->cur;
577260684Skaiw			while (ELFTC_ISDIGIT(*ddata->cur) != 0)
578260684Skaiw				++ddata->cur;
579260684Skaiw			if (*ddata->cur != '_')
580260684Skaiw				return (0);
581260684Skaiw			num_len = ddata->cur - num;
582260684Skaiw			assert(num_len > 0);
583260684Skaiw			if (*(++ddata->cur) == '\0')
584260684Skaiw				return (0);
585260684Skaiw			if (!cpp_demangle_read_type(ddata, 0))
586260684Skaiw				return (0);
587260684Skaiw			if (!cpp_demangle_push_str(ddata, "[", 1))
588260684Skaiw				return (0);
589260684Skaiw			if (!cpp_demangle_push_str(ddata, num, num_len))
590260684Skaiw				return (0);
591260684Skaiw			if (!cpp_demangle_push_str(ddata, "]", 1))
592260684Skaiw				return (0);
593260684Skaiw		} else {
594260684Skaiw			p_idx = ddata->output.size;
595260684Skaiw			if (!cpp_demangle_read_expression(ddata))
596260684Skaiw				return (0);
597260684Skaiw			if ((exp = vector_str_substr(&ddata->output, p_idx,
598260684Skaiw				 ddata->output.size - 1, &exp_len)) == NULL)
599260684Skaiw				return (0);
600260684Skaiw			idx = ddata->output.size;
601260684Skaiw			for (i = p_idx; i < idx; ++i)
602260684Skaiw				if (!vector_str_pop(&ddata->output)) {
603260684Skaiw					free(exp);
604260684Skaiw					return (0);
605260684Skaiw				}
606260684Skaiw			if (*ddata->cur != '_') {
607260684Skaiw				free(exp);
608260684Skaiw				return (0);
609260684Skaiw			}
610260684Skaiw			++ddata->cur;
611260684Skaiw			if (*ddata->cur == '\0') {
612260684Skaiw				free(exp);
613260684Skaiw				return (0);
614260684Skaiw			}
615260684Skaiw			if (!cpp_demangle_read_type(ddata, 0)) {
616260684Skaiw				free(exp);
617260684Skaiw				return (0);
618260684Skaiw			}
619260684Skaiw			if (!cpp_demangle_push_str(ddata, "[", 1)) {
620260684Skaiw				free(exp);
621260684Skaiw				return (0);
622260684Skaiw			}
623260684Skaiw			if (!cpp_demangle_push_str(ddata, exp, exp_len)) {
624260684Skaiw				free(exp);
625260684Skaiw				return (0);
626260684Skaiw			}
627260684Skaiw			if (!cpp_demangle_push_str(ddata, "]", 1)) {
628260684Skaiw				free(exp);
629260684Skaiw				return (0);
630260684Skaiw			}
631260684Skaiw			free(exp);
632260684Skaiw		}
633260684Skaiw	}
634260684Skaiw
635260684Skaiw	return (1);
636260684Skaiw}
637260684Skaiw
638260684Skaiwstatic int
639260684Skaiwcpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
640260684Skaiw{
641260684Skaiw	const char *num;
642260684Skaiw
643260684Skaiw	if (ddata == NULL || *(++ddata->cur) == '\0')
644260684Skaiw		return (0);
645260684Skaiw
646260684Skaiw	if (*ddata->cur == '_' && *(ddata->cur + 1) == 'Z') {
647260684Skaiw		ddata->cur += 2;
648260684Skaiw		if (*ddata->cur == '\0')
649260684Skaiw			return (0);
650260684Skaiw		if (!cpp_demangle_read_encoding(ddata))
651260684Skaiw			return (0);
652260684Skaiw		++ddata->cur;
653260684Skaiw		return (1);
654260684Skaiw	}
655260684Skaiw
656260684Skaiw	switch (*ddata->cur) {
657260684Skaiw	case 'b':
658260684Skaiw		switch (*(++ddata->cur)) {
659260684Skaiw		case '0':
660260684Skaiw			return (cpp_demangle_push_str(ddata, "false", 5));
661260684Skaiw		case '1':
662260684Skaiw			return (cpp_demangle_push_str(ddata, "true", 4));
663260684Skaiw		default:
664260684Skaiw			return (0);
665260684Skaiw		};
666260684Skaiw
667260684Skaiw	case 'd':
668260684Skaiw		++ddata->cur;
669260684Skaiw		return (cpp_demangle_push_fp(ddata, decode_fp_to_double));
670260684Skaiw
671260684Skaiw	case 'e':
672260684Skaiw		++ddata->cur;
673260684Skaiw		if (sizeof(long double) == 10)
674260684Skaiw			return (cpp_demangle_push_fp(ddata,
675260684Skaiw			    decode_fp_to_double));
676260684Skaiw		return (cpp_demangle_push_fp(ddata, decode_fp_to_float80));
677260684Skaiw
678260684Skaiw	case 'f':
679260684Skaiw		++ddata->cur;
680260684Skaiw		return (cpp_demangle_push_fp(ddata, decode_fp_to_float));
681260684Skaiw
682260684Skaiw	case 'g':
683260684Skaiw		++ddata->cur;
684260684Skaiw		if (sizeof(long double) == 16)
685260684Skaiw			return (cpp_demangle_push_fp(ddata,
686260684Skaiw			    decode_fp_to_double));
687260684Skaiw		return (cpp_demangle_push_fp(ddata, decode_fp_to_float128));
688260684Skaiw
689260684Skaiw	case 'i':
690260684Skaiw	case 'j':
691260684Skaiw	case 'l':
692260684Skaiw	case 'm':
693260684Skaiw	case 'n':
694260684Skaiw	case 's':
695260684Skaiw	case 't':
696260684Skaiw	case 'x':
697260684Skaiw	case 'y':
698260684Skaiw		if (*(++ddata->cur) == 'n') {
699260684Skaiw			if (!cpp_demangle_push_str(ddata, "-", 1))
700260684Skaiw				return (0);
701260684Skaiw			++ddata->cur;
702260684Skaiw		}
703260684Skaiw		num = ddata->cur;
704260684Skaiw		while (*ddata->cur != 'E') {
705260684Skaiw			if (!ELFTC_ISDIGIT(*ddata->cur))
706260684Skaiw				return (0);
707260684Skaiw			++ddata->cur;
708260684Skaiw		}
709260684Skaiw		++ddata->cur;
710260684Skaiw		return (cpp_demangle_push_str(ddata, num, ddata->cur - num));
711260684Skaiw
712260684Skaiw	default:
713260684Skaiw		return (0);
714260684Skaiw	};
715260684Skaiw}
716260684Skaiw
717260684Skaiwstatic int
718260684Skaiwcpp_demangle_read_expression(struct cpp_demangle_data *ddata)
719260684Skaiw{
720260684Skaiw
721260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
722260684Skaiw		return (0);
723260684Skaiw
724260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
725260684Skaiw	case SIMPLE_HASH('s', 't'):
726260684Skaiw		ddata->cur += 2;
727260684Skaiw		return (cpp_demangle_read_type(ddata, 0));
728260684Skaiw
729260684Skaiw	case SIMPLE_HASH('s', 'r'):
730260684Skaiw		ddata->cur += 2;
731260684Skaiw		if (!cpp_demangle_read_type(ddata, 0))
732260684Skaiw			return (0);
733260684Skaiw		if (!cpp_demangle_read_uqname(ddata))
734260684Skaiw			return (0);
735260684Skaiw		if (*ddata->cur == 'I')
736260684Skaiw			return (cpp_demangle_read_tmpl_args(ddata));
737260684Skaiw		return (1);
738260684Skaiw
739260684Skaiw	case SIMPLE_HASH('a', 'a'):
740260684Skaiw		/* operator && */
741260684Skaiw		ddata->cur += 2;
742260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "&&", 2));
743260684Skaiw
744260684Skaiw	case SIMPLE_HASH('a', 'd'):
745260684Skaiw		/* operator & (unary) */
746260684Skaiw		ddata->cur += 2;
747260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "&", 1));
748260684Skaiw
749260684Skaiw	case SIMPLE_HASH('a', 'n'):
750260684Skaiw		/* operator & */
751260684Skaiw		ddata->cur += 2;
752260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "&", 1));
753260684Skaiw
754260684Skaiw	case SIMPLE_HASH('a', 'N'):
755260684Skaiw		/* operator &= */
756260684Skaiw		ddata->cur += 2;
757260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "&=", 2));
758260684Skaiw
759260684Skaiw	case SIMPLE_HASH('a', 'S'):
760260684Skaiw		/* operator = */
761260684Skaiw		ddata->cur += 2;
762260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "=", 1));
763260684Skaiw
764260684Skaiw	case SIMPLE_HASH('c', 'l'):
765260684Skaiw		/* operator () */
766260684Skaiw		ddata->cur += 2;
767260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "()", 2));
768260684Skaiw
769260684Skaiw	case SIMPLE_HASH('c', 'm'):
770260684Skaiw		/* operator , */
771260684Skaiw		ddata->cur += 2;
772260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ",", 1));
773260684Skaiw
774260684Skaiw	case SIMPLE_HASH('c', 'o'):
775260684Skaiw		/* operator ~ */
776260684Skaiw		ddata->cur += 2;
777260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "~", 1));
778260684Skaiw
779260684Skaiw	case SIMPLE_HASH('c', 'v'):
780260684Skaiw		/* operator (cast) */
781260684Skaiw		ddata->cur += 2;
782260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "(cast)", 6));
783260684Skaiw
784260684Skaiw	case SIMPLE_HASH('d', 'a'):
785260684Skaiw		/* operator delete [] */
786260684Skaiw		ddata->cur += 2;
787260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "delete []", 9));
788260684Skaiw
789260684Skaiw	case SIMPLE_HASH('d', 'e'):
790260684Skaiw		/* operator * (unary) */
791260684Skaiw		ddata->cur += 2;
792260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "*", 1));
793260684Skaiw
794260684Skaiw	case SIMPLE_HASH('d', 'l'):
795260684Skaiw		/* operator delete */
796260684Skaiw		ddata->cur += 2;
797260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "delete", 6));
798260684Skaiw
799260684Skaiw	case SIMPLE_HASH('d', 'v'):
800260684Skaiw		/* operator / */
801260684Skaiw		ddata->cur += 2;
802260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "/", 1));
803260684Skaiw
804260684Skaiw	case SIMPLE_HASH('d', 'V'):
805260684Skaiw		/* operator /= */
806260684Skaiw		ddata->cur += 2;
807260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "/=", 2));
808260684Skaiw
809260684Skaiw	case SIMPLE_HASH('e', 'o'):
810260684Skaiw		/* operator ^ */
811260684Skaiw		ddata->cur += 2;
812260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "^", 1));
813260684Skaiw
814260684Skaiw	case SIMPLE_HASH('e', 'O'):
815260684Skaiw		/* operator ^= */
816260684Skaiw		ddata->cur += 2;
817260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "^=", 2));
818260684Skaiw
819260684Skaiw	case SIMPLE_HASH('e', 'q'):
820260684Skaiw		/* operator == */
821260684Skaiw		ddata->cur += 2;
822260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "==", 2));
823260684Skaiw
824260684Skaiw	case SIMPLE_HASH('g', 'e'):
825260684Skaiw		/* operator >= */
826260684Skaiw		ddata->cur += 2;
827260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ">=", 2));
828260684Skaiw
829260684Skaiw	case SIMPLE_HASH('g', 't'):
830260684Skaiw		/* operator > */
831260684Skaiw		ddata->cur += 2;
832260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ">", 1));
833260684Skaiw
834260684Skaiw	case SIMPLE_HASH('i', 'x'):
835260684Skaiw		/* operator [] */
836260684Skaiw		ddata->cur += 2;
837260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "[]", 2));
838260684Skaiw
839260684Skaiw	case SIMPLE_HASH('l', 'e'):
840260684Skaiw		/* operator <= */
841260684Skaiw		ddata->cur += 2;
842260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "<=", 2));
843260684Skaiw
844260684Skaiw	case SIMPLE_HASH('l', 's'):
845260684Skaiw		/* operator << */
846260684Skaiw		ddata->cur += 2;
847260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "<<", 2));
848260684Skaiw
849260684Skaiw	case SIMPLE_HASH('l', 'S'):
850260684Skaiw		/* operator <<= */
851260684Skaiw		ddata->cur += 2;
852260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "<<=", 3));
853260684Skaiw
854260684Skaiw	case SIMPLE_HASH('l', 't'):
855260684Skaiw		/* operator < */
856260684Skaiw		ddata->cur += 2;
857260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "<", 1));
858260684Skaiw
859260684Skaiw	case SIMPLE_HASH('m', 'i'):
860260684Skaiw		/* operator - */
861260684Skaiw		ddata->cur += 2;
862260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "-", 1));
863260684Skaiw
864260684Skaiw	case SIMPLE_HASH('m', 'I'):
865260684Skaiw		/* operator -= */
866260684Skaiw		ddata->cur += 2;
867260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "-=", 2));
868260684Skaiw
869260684Skaiw	case SIMPLE_HASH('m', 'l'):
870260684Skaiw		/* operator * */
871260684Skaiw		ddata->cur += 2;
872260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "*", 1));
873260684Skaiw
874260684Skaiw	case SIMPLE_HASH('m', 'L'):
875260684Skaiw		/* operator *= */
876260684Skaiw		ddata->cur += 2;
877260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "*=", 2));
878260684Skaiw
879260684Skaiw	case SIMPLE_HASH('m', 'm'):
880260684Skaiw		/* operator -- */
881260684Skaiw		ddata->cur += 2;
882260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "--", 2));
883260684Skaiw
884260684Skaiw	case SIMPLE_HASH('n', 'a'):
885260684Skaiw		/* operator new[] */
886260684Skaiw		ddata->cur += 2;
887260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "new []", 6));
888260684Skaiw
889260684Skaiw	case SIMPLE_HASH('n', 'e'):
890260684Skaiw		/* operator != */
891260684Skaiw		ddata->cur += 2;
892260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "!=", 2));
893260684Skaiw
894260684Skaiw	case SIMPLE_HASH('n', 'g'):
895260684Skaiw		/* operator - (unary) */
896260684Skaiw		ddata->cur += 2;
897260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "-", 1));
898260684Skaiw
899260684Skaiw	case SIMPLE_HASH('n', 't'):
900260684Skaiw		/* operator ! */
901260684Skaiw		ddata->cur += 2;
902260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "!", 1));
903260684Skaiw
904260684Skaiw	case SIMPLE_HASH('n', 'w'):
905260684Skaiw		/* operator new */
906260684Skaiw		ddata->cur += 2;
907260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "new", 3));
908260684Skaiw
909260684Skaiw	case SIMPLE_HASH('o', 'o'):
910260684Skaiw		/* operator || */
911260684Skaiw		ddata->cur += 2;
912260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "||", 2));
913260684Skaiw
914260684Skaiw	case SIMPLE_HASH('o', 'r'):
915260684Skaiw		/* operator | */
916260684Skaiw		ddata->cur += 2;
917260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "|", 1));
918260684Skaiw
919260684Skaiw	case SIMPLE_HASH('o', 'R'):
920260684Skaiw		/* operator |= */
921260684Skaiw		ddata->cur += 2;
922260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "|=", 2));
923260684Skaiw
924260684Skaiw	case SIMPLE_HASH('p', 'l'):
925260684Skaiw		/* operator + */
926260684Skaiw		ddata->cur += 2;
927260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "+", 1));
928260684Skaiw
929260684Skaiw	case SIMPLE_HASH('p', 'L'):
930260684Skaiw		/* operator += */
931260684Skaiw		ddata->cur += 2;
932260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "+=", 2));
933260684Skaiw
934260684Skaiw	case SIMPLE_HASH('p', 'm'):
935260684Skaiw		/* operator ->* */
936260684Skaiw		ddata->cur += 2;
937260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "->*", 3));
938260684Skaiw
939260684Skaiw	case SIMPLE_HASH('p', 'p'):
940260684Skaiw		/* operator ++ */
941260684Skaiw		ddata->cur += 2;
942260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "++", 2));
943260684Skaiw
944260684Skaiw	case SIMPLE_HASH('p', 's'):
945260684Skaiw		/* operator + (unary) */
946260684Skaiw		ddata->cur += 2;
947260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "+", 1));
948260684Skaiw
949260684Skaiw	case SIMPLE_HASH('p', 't'):
950260684Skaiw		/* operator -> */
951260684Skaiw		ddata->cur += 2;
952260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "->", 2));
953260684Skaiw
954260684Skaiw	case SIMPLE_HASH('q', 'u'):
955260684Skaiw		/* operator ? */
956260684Skaiw		ddata->cur += 2;
957260684Skaiw		return (cpp_demangle_read_expression_trinary(ddata, "?", 1,
958260684Skaiw		    ":", 1));
959260684Skaiw
960260684Skaiw	case SIMPLE_HASH('r', 'm'):
961260684Skaiw		/* operator % */
962260684Skaiw		ddata->cur += 2;
963260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "%", 1));
964260684Skaiw
965260684Skaiw	case SIMPLE_HASH('r', 'M'):
966260684Skaiw		/* operator %= */
967260684Skaiw		ddata->cur += 2;
968260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, "%=", 2));
969260684Skaiw
970260684Skaiw	case SIMPLE_HASH('r', 's'):
971260684Skaiw		/* operator >> */
972260684Skaiw		ddata->cur += 2;
973260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ">>", 2));
974260684Skaiw
975260684Skaiw	case SIMPLE_HASH('r', 'S'):
976260684Skaiw		/* operator >>= */
977260684Skaiw		ddata->cur += 2;
978260684Skaiw		return (cpp_demangle_read_expression_binary(ddata, ">>=", 3));
979260684Skaiw
980260684Skaiw	case SIMPLE_HASH('r', 'z'):
981260684Skaiw		/* operator sizeof */
982260684Skaiw		ddata->cur += 2;
983260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
984260684Skaiw
985260684Skaiw	case SIMPLE_HASH('s', 'v'):
986260684Skaiw		/* operator sizeof */
987260684Skaiw		ddata->cur += 2;
988260684Skaiw		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
989260684Skaiw	};
990260684Skaiw
991260684Skaiw	switch (*ddata->cur) {
992260684Skaiw	case 'L':
993260684Skaiw		return (cpp_demangle_read_expr_primary(ddata));
994260684Skaiw	case 'T':
995260684Skaiw		return (cpp_demangle_read_tmpl_param(ddata));
996260684Skaiw	};
997260684Skaiw
998260684Skaiw	return (0);
999260684Skaiw}
1000260684Skaiw
1001260684Skaiwstatic int
1002260684Skaiwcpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
1003260684Skaiw    const char *name, size_t len)
1004260684Skaiw{
1005260684Skaiw
1006260684Skaiw	if (ddata == NULL || name == NULL || len == 0)
1007260684Skaiw		return (0);
1008260684Skaiw	if (!cpp_demangle_read_expression(ddata))
1009260684Skaiw		return (0);
1010260684Skaiw	if (!cpp_demangle_push_str(ddata, name, len))
1011260684Skaiw		return (0);
1012260684Skaiw
1013260684Skaiw	return (cpp_demangle_read_expression(ddata));
1014260684Skaiw}
1015260684Skaiw
1016260684Skaiwstatic int
1017260684Skaiwcpp_demangle_read_expression_unary(struct cpp_demangle_data *ddata,
1018260684Skaiw    const char *name, size_t len)
1019260684Skaiw{
1020260684Skaiw
1021260684Skaiw	if (ddata == NULL || name == NULL || len == 0)
1022260684Skaiw		return (0);
1023260684Skaiw	if (!cpp_demangle_read_expression(ddata))
1024260684Skaiw		return (0);
1025260684Skaiw
1026260684Skaiw	return (cpp_demangle_push_str(ddata, name, len));
1027260684Skaiw}
1028260684Skaiw
1029260684Skaiwstatic int
1030260684Skaiwcpp_demangle_read_expression_trinary(struct cpp_demangle_data *ddata,
1031260684Skaiw    const char *name1, size_t len1, const char *name2, size_t len2)
1032260684Skaiw{
1033260684Skaiw
1034260684Skaiw	if (ddata == NULL || name1 == NULL || len1 == 0 || name2 == NULL ||
1035260684Skaiw	    len2 == 0)
1036260684Skaiw		return (0);
1037260684Skaiw
1038260684Skaiw	if (!cpp_demangle_read_expression(ddata))
1039260684Skaiw		return (0);
1040260684Skaiw	if (!cpp_demangle_push_str(ddata, name1, len1))
1041260684Skaiw		return (0);
1042260684Skaiw	if (!cpp_demangle_read_expression(ddata))
1043260684Skaiw		return (0);
1044260684Skaiw	if (!cpp_demangle_push_str(ddata, name2, len2))
1045260684Skaiw		return (0);
1046260684Skaiw
1047260684Skaiw	return (cpp_demangle_read_expression(ddata));
1048260684Skaiw}
1049260684Skaiw
1050260684Skaiwstatic int
1051260684Skaiwcpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
1052260684Skaiw    struct vector_type_qualifier *v)
1053260684Skaiw{
1054260684Skaiw	size_t class_type_size, class_type_len, limit;
1055260684Skaiw	const char *class_type;
1056260684Skaiw
1057260684Skaiw	if (ddata == NULL || *ddata->cur != 'F' || v == NULL)
1058260684Skaiw		return (0);
1059260684Skaiw
1060260684Skaiw	++ddata->cur;
1061260684Skaiw	if (*ddata->cur == 'Y') {
1062260684Skaiw		if (ext_c != NULL)
1063260684Skaiw			*ext_c = 1;
1064260684Skaiw		++ddata->cur;
1065260684Skaiw	}
1066260684Skaiw	if (!cpp_demangle_read_type(ddata, 0))
1067260684Skaiw		return (0);
1068260684Skaiw	if (*ddata->cur != 'E') {
1069260684Skaiw		if (!cpp_demangle_push_str(ddata, "(", 1))
1070260684Skaiw			return (0);
1071260684Skaiw		if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM)) {
1072260684Skaiw			if ((class_type_size = ddata->class_type.size) == 0)
1073260684Skaiw				return (0);
1074260684Skaiw			class_type =
1075260684Skaiw			    ddata->class_type.container[class_type_size - 1];
1076260684Skaiw			if (class_type == NULL)
1077260684Skaiw				return (0);
1078260684Skaiw			if ((class_type_len = strlen(class_type)) == 0)
1079260684Skaiw				return (0);
1080260684Skaiw			if (!cpp_demangle_push_str(ddata, class_type,
1081260684Skaiw			    class_type_len))
1082260684Skaiw				return (0);
1083260684Skaiw			if (!cpp_demangle_push_str(ddata, "::*", 3))
1084260684Skaiw				return (0);
1085260684Skaiw			++ddata->func_type;
1086260684Skaiw		} else {
1087260684Skaiw			if (!cpp_demangle_push_type_qualifier(ddata, v,
1088260684Skaiw			    (const char *) NULL))
1089260684Skaiw				return (0);
1090260684Skaiw			vector_type_qualifier_dest(v);
1091260684Skaiw			if (!vector_type_qualifier_init(v))
1092260684Skaiw				return (0);
1093260684Skaiw		}
1094260684Skaiw
1095260684Skaiw		if (!cpp_demangle_push_str(ddata, ")(", 2))
1096260684Skaiw			return (0);
1097260684Skaiw
1098260684Skaiw		limit = 0;
1099260684Skaiw		for (;;) {
1100260684Skaiw			if (!cpp_demangle_read_type(ddata, 0))
1101260684Skaiw				return (0);
1102260684Skaiw			if (*ddata->cur == 'E')
1103260684Skaiw				break;
1104260684Skaiw			if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1105260684Skaiw				return (0);
1106260684Skaiw		}
1107260684Skaiw
1108260684Skaiw		if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM) == 1) {
1109260684Skaiw			if (!cpp_demangle_push_type_qualifier(ddata, v,
1110260684Skaiw			    (const char *) NULL))
1111260684Skaiw				return (0);
1112260684Skaiw			vector_type_qualifier_dest(v);
1113260684Skaiw			if (!vector_type_qualifier_init(v))
1114260684Skaiw				return (0);
1115260684Skaiw		}
1116260684Skaiw
1117260684Skaiw		if (!cpp_demangle_push_str(ddata, ")", 1))
1118260684Skaiw			return (0);
1119260684Skaiw	}
1120260684Skaiw
1121260684Skaiw	++ddata->cur;
1122260684Skaiw
1123260684Skaiw	return (1);
1124260684Skaiw}
1125260684Skaiw
1126260684Skaiw/* read encoding, encoding are function name, data name, special-name */
1127260684Skaiwstatic int
1128260684Skaiwcpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
1129260684Skaiw{
1130260684Skaiw
1131260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1132260684Skaiw		return (0);
1133260684Skaiw
1134260684Skaiw	/* special name */
1135260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
1136260684Skaiw	case SIMPLE_HASH('G', 'V'):
1137260684Skaiw		/* sentry object for 1 time init */
1138260684Skaiw		if (!cpp_demangle_push_str(ddata, "guard variable for ", 20))
1139260684Skaiw			return (0);
1140260684Skaiw		ddata->cur += 2;
1141260684Skaiw		break;
1142260684Skaiw
1143260684Skaiw	case SIMPLE_HASH('T', 'c'):
1144260684Skaiw		/* virtual function covariant override thunk */
1145260684Skaiw		if (!cpp_demangle_push_str(ddata,
1146260684Skaiw		    "virtual function covariant override ", 36))
1147260684Skaiw			return (0);
1148260684Skaiw		ddata->cur += 2;
1149260684Skaiw		if (*ddata->cur == '\0')
1150260684Skaiw			return (0);
1151260684Skaiw		if (!cpp_demangle_read_offset(ddata))
1152260684Skaiw			return (0);
1153260684Skaiw		if (!cpp_demangle_read_offset(ddata))
1154260684Skaiw			return (0);
1155260684Skaiw		return (cpp_demangle_read_encoding(ddata));
1156260684Skaiw
1157260684Skaiw	case SIMPLE_HASH('T', 'D'):
1158260684Skaiw		/* typeinfo common proxy */
1159260684Skaiw		break;
1160260684Skaiw
1161260684Skaiw	case SIMPLE_HASH('T', 'h'):
1162260684Skaiw		/* virtual function non-virtual override thunk */
1163260684Skaiw		if (cpp_demangle_push_str(ddata,
1164260684Skaiw		    "virtual function non-virtual override ", 38) == 0)
1165260684Skaiw			return (0);
1166260684Skaiw		ddata->cur += 2;
1167260684Skaiw		if (*ddata->cur == '\0')
1168260684Skaiw			return (0);
1169260684Skaiw		if (!cpp_demangle_read_nv_offset(ddata))
1170260684Skaiw			return (0);
1171260684Skaiw		return (cpp_demangle_read_encoding(ddata));
1172260684Skaiw
1173260684Skaiw	case SIMPLE_HASH('T', 'I'):
1174260684Skaiw		/* typeinfo structure */
1175260684Skaiw		/* FALLTHROUGH */
1176260684Skaiw	case SIMPLE_HASH('T', 'S'):
1177260684Skaiw		/* RTTI name (NTBS) */
1178260684Skaiw		if (!cpp_demangle_push_str(ddata, "typeinfo for ", 14))
1179260684Skaiw			return (0);
1180260684Skaiw		ddata->cur += 2;
1181260684Skaiw		if (*ddata->cur == '\0')
1182260684Skaiw			return (0);
1183260684Skaiw		return (cpp_demangle_read_type(ddata, 1));
1184260684Skaiw
1185260684Skaiw	case SIMPLE_HASH('T', 'T'):
1186260684Skaiw		/* VTT table */
1187260684Skaiw		if (!cpp_demangle_push_str(ddata, "VTT for ", 8))
1188260684Skaiw			return (0);
1189260684Skaiw		ddata->cur += 2;
1190260684Skaiw		return (cpp_demangle_read_type(ddata, 1));
1191260684Skaiw
1192260684Skaiw	case SIMPLE_HASH('T', 'v'):
1193260684Skaiw		/* virtual function virtual override thunk */
1194260684Skaiw		if (!cpp_demangle_push_str(ddata,
1195260684Skaiw		    "virtual function virtual override ", 34))
1196260684Skaiw			return (0);
1197260684Skaiw		ddata->cur += 2;
1198260684Skaiw		if (*ddata->cur == '\0')
1199260684Skaiw			return (0);
1200260684Skaiw		if (!cpp_demangle_read_v_offset(ddata))
1201260684Skaiw			return (0);
1202260684Skaiw		return (cpp_demangle_read_encoding(ddata));
1203260684Skaiw
1204260684Skaiw	case SIMPLE_HASH('T', 'V'):
1205260684Skaiw		/* virtual table */
1206260684Skaiw		if (!cpp_demangle_push_str(ddata, "vtable for ", 12))
1207260684Skaiw			return (0);
1208260684Skaiw		ddata->cur += 2;
1209260684Skaiw		if (*ddata->cur == '\0')
1210260684Skaiw			return (0);
1211260684Skaiw		return (cpp_demangle_read_type(ddata, 1));
1212260684Skaiw	};
1213260684Skaiw
1214260684Skaiw	return (cpp_demangle_read_name(ddata));
1215260684Skaiw}
1216260684Skaiw
1217260684Skaiwstatic int
1218260684Skaiwcpp_demangle_read_local_name(struct cpp_demangle_data *ddata)
1219260684Skaiw{
1220260684Skaiw	size_t limit;
1221260684Skaiw
1222260684Skaiw	if (ddata == NULL)
1223260684Skaiw		return (0);
1224260684Skaiw	if (*(++ddata->cur) == '\0')
1225260684Skaiw		return (0);
1226260684Skaiw	if (!cpp_demangle_read_encoding(ddata))
1227260684Skaiw		return (0);
1228260684Skaiw
1229260684Skaiw	limit = 0;
1230260684Skaiw	for (;;) {
1231260684Skaiw		if (!cpp_demangle_read_type(ddata, 1))
1232260684Skaiw			return (0);
1233260684Skaiw		if (*ddata->cur == 'E')
1234260684Skaiw			break;
1235260684Skaiw		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1236260684Skaiw			return (0);
1237260684Skaiw	}
1238260684Skaiw	if (*(++ddata->cur) == '\0')
1239260684Skaiw		return (0);
1240260684Skaiw	if (ddata->paren == true) {
1241260684Skaiw		if (!cpp_demangle_push_str(ddata, ")", 1))
1242260684Skaiw			return (0);
1243260684Skaiw		ddata->paren = false;
1244260684Skaiw	}
1245260684Skaiw	if (*ddata->cur == 's')
1246260684Skaiw		++ddata->cur;
1247260684Skaiw	else {
1248260684Skaiw		if (!cpp_demangle_push_str(ddata, "::", 2))
1249260684Skaiw			return (0);
1250260684Skaiw		if (!cpp_demangle_read_name(ddata))
1251260684Skaiw			return (0);
1252260684Skaiw	}
1253260684Skaiw	if (*ddata->cur == '_') {
1254260684Skaiw		++ddata->cur;
1255260684Skaiw		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
1256260684Skaiw			++ddata->cur;
1257260684Skaiw	}
1258260684Skaiw
1259260684Skaiw	return (1);
1260260684Skaiw}
1261260684Skaiw
1262260684Skaiwstatic int
1263260684Skaiwcpp_demangle_read_name(struct cpp_demangle_data *ddata)
1264260684Skaiw{
1265260684Skaiw	struct vector_str *output, v;
1266260684Skaiw	size_t p_idx, subst_str_len;
1267260684Skaiw	int rtn;
1268260684Skaiw	char *subst_str;
1269260684Skaiw
1270260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1271260684Skaiw		return (0);
1272260684Skaiw
1273260684Skaiw	output = cpp_demangle_gnu3_push_head > 0 ?
1274260684Skaiw	    &ddata->output_tmp : &ddata->output;
1275260684Skaiw
1276260684Skaiw	subst_str = NULL;
1277260684Skaiw
1278260684Skaiw	switch (*ddata->cur) {
1279260684Skaiw	case 'S':
1280260684Skaiw		return (cpp_demangle_read_subst(ddata));
1281260684Skaiw	case 'N':
1282260684Skaiw		return (cpp_demangle_read_nested_name(ddata));
1283260684Skaiw	case 'Z':
1284260684Skaiw		return (cpp_demangle_read_local_name(ddata));
1285260684Skaiw	};
1286260684Skaiw
1287260684Skaiw	if (!vector_str_init(&v))
1288260684Skaiw		return (0);
1289260684Skaiw
1290260684Skaiw	p_idx = output->size;
1291260684Skaiw	rtn = 0;
1292260684Skaiw	if (!cpp_demangle_read_uqname(ddata))
1293260684Skaiw		goto clean;
1294260684Skaiw	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
1295260684Skaiw	    &subst_str_len)) == NULL)
1296260684Skaiw		goto clean;
1297260684Skaiw	if (subst_str_len > 8 && strstr(subst_str, "operator") != NULL) {
1298260684Skaiw		rtn = 1;
1299260684Skaiw		goto clean;
1300260684Skaiw	}
1301260684Skaiw	if (!vector_str_push(&v, subst_str, subst_str_len))
1302260684Skaiw		goto clean;
1303260684Skaiw	if (!cpp_demangle_push_subst_v(ddata, &v))
1304260684Skaiw		goto clean;
1305260684Skaiw
1306260684Skaiw	if (*ddata->cur == 'I') {
1307260684Skaiw		p_idx = output->size;
1308260684Skaiw		if (!cpp_demangle_read_tmpl_args(ddata))
1309260684Skaiw			goto clean;
1310260684Skaiw		free(subst_str);
1311260684Skaiw		if ((subst_str = vector_str_substr(output, p_idx,
1312260684Skaiw		    output->size - 1, &subst_str_len)) == NULL)
1313260684Skaiw			goto clean;
1314260684Skaiw		if (!vector_str_push(&v, subst_str, subst_str_len))
1315260684Skaiw			goto clean;
1316260684Skaiw		if (!cpp_demangle_push_subst_v(ddata, &v))
1317260684Skaiw			goto clean;
1318260684Skaiw	}
1319260684Skaiw
1320260684Skaiw	rtn = 1;
1321260684Skaiw
1322260684Skaiwclean:
1323260684Skaiw	free(subst_str);
1324260684Skaiw	vector_str_dest(&v);
1325260684Skaiw
1326260684Skaiw	return (rtn);
1327260684Skaiw}
1328260684Skaiw
1329260684Skaiwstatic int
1330260684Skaiwcpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
1331260684Skaiw{
1332260684Skaiw	struct vector_str *output, v;
1333260684Skaiw	size_t limit, p_idx, subst_str_len;
1334260684Skaiw	int rtn;
1335260684Skaiw	char *subst_str;
1336260684Skaiw
1337260684Skaiw	if (ddata == NULL || *ddata->cur != 'N')
1338260684Skaiw		return (0);
1339260684Skaiw	if (*(++ddata->cur) == '\0')
1340260684Skaiw		return (0);
1341260684Skaiw
1342260684Skaiw	while (*ddata->cur == 'r' || *ddata->cur == 'V' ||
1343260684Skaiw	    *ddata->cur == 'K') {
1344260684Skaiw		switch (*ddata->cur) {
1345260684Skaiw		case 'r':
1346260684Skaiw			ddata->mem_rst = true;
1347260684Skaiw			break;
1348260684Skaiw		case 'V':
1349260684Skaiw			ddata->mem_vat = true;
1350260684Skaiw			break;
1351260684Skaiw		case 'K':
1352260684Skaiw			ddata->mem_cst = true;
1353260684Skaiw			break;
1354260684Skaiw		};
1355260684Skaiw		++ddata->cur;
1356260684Skaiw	}
1357260684Skaiw
1358260684Skaiw	output = cpp_demangle_gnu3_push_head > 0 ?
1359260684Skaiw	    &ddata->output_tmp : &ddata->output;
1360260684Skaiw	if (!vector_str_init(&v))
1361260684Skaiw		return (0);
1362260684Skaiw
1363260684Skaiw	rtn = 0;
1364260684Skaiw	limit = 0;
1365260684Skaiw	for (;;) {
1366260684Skaiw		p_idx = output->size;
1367260684Skaiw		switch (*ddata->cur) {
1368260684Skaiw		case 'I':
1369260684Skaiw			if (!cpp_demangle_read_tmpl_args(ddata))
1370260684Skaiw				goto clean;
1371260684Skaiw			break;
1372260684Skaiw		case 'S':
1373260684Skaiw			if (!cpp_demangle_read_subst(ddata))
1374260684Skaiw				goto clean;
1375260684Skaiw			break;
1376260684Skaiw		case 'T':
1377260684Skaiw			if (!cpp_demangle_read_tmpl_param(ddata))
1378260684Skaiw				goto clean;
1379260684Skaiw			break;
1380260684Skaiw		default:
1381260684Skaiw			if (!cpp_demangle_read_uqname(ddata))
1382260684Skaiw				goto clean;
1383260684Skaiw		};
1384260684Skaiw
1385260684Skaiw		if ((subst_str = vector_str_substr(output, p_idx,
1386260684Skaiw		    output->size - 1, &subst_str_len)) == NULL)
1387260684Skaiw			goto clean;
1388260684Skaiw		if (!vector_str_push(&v, subst_str, subst_str_len)) {
1389260684Skaiw			free(subst_str);
1390260684Skaiw			goto clean;
1391260684Skaiw		}
1392260684Skaiw		free(subst_str);
1393260684Skaiw
1394260684Skaiw		if (!cpp_demangle_push_subst_v(ddata, &v))
1395260684Skaiw			goto clean;
1396260684Skaiw		if (*ddata->cur == 'E')
1397260684Skaiw			break;
1398260684Skaiw		else if (*ddata->cur != 'I' &&
1399260684Skaiw		    *ddata->cur != 'C' && *ddata->cur != 'D') {
1400260684Skaiw			if (!cpp_demangle_push_str(ddata, "::", 2))
1401260684Skaiw				goto clean;
1402260684Skaiw			if (!vector_str_push(&v, "::", 2))
1403260684Skaiw				goto clean;
1404260684Skaiw		}
1405260684Skaiw		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1406260684Skaiw			goto clean;
1407260684Skaiw	}
1408260684Skaiw
1409260684Skaiw	++ddata->cur;
1410260684Skaiw	rtn = 1;
1411260684Skaiw
1412260684Skaiwclean:
1413260684Skaiw	vector_str_dest(&v);
1414260684Skaiw
1415260684Skaiw	return (rtn);
1416260684Skaiw}
1417260684Skaiw
1418260684Skaiw/*
1419260684Skaiw * read number
1420260684Skaiw * number ::= [n] <decimal>
1421260684Skaiw */
1422260684Skaiwstatic int
1423260684Skaiwcpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
1424260684Skaiw{
1425260684Skaiw	long len, negative_factor;
1426260684Skaiw
1427260684Skaiw	if (ddata == NULL || rtn == NULL)
1428260684Skaiw		return (0);
1429260684Skaiw
1430260684Skaiw	negative_factor = 1;
1431260684Skaiw	if (*ddata->cur == 'n') {
1432260684Skaiw		negative_factor = -1;
1433260684Skaiw
1434260684Skaiw		++ddata->cur;
1435260684Skaiw	}
1436260684Skaiw	if (ELFTC_ISDIGIT(*ddata->cur) == 0)
1437260684Skaiw		return (0);
1438260684Skaiw
1439260684Skaiw	errno = 0;
1440260684Skaiw	if ((len = strtol(ddata->cur, (char **) NULL, 10)) == 0 &&
1441260684Skaiw	    errno != 0)
1442260684Skaiw		return (0);
1443260684Skaiw
1444260684Skaiw	while (ELFTC_ISDIGIT(*ddata->cur) != 0)
1445260684Skaiw		++ddata->cur;
1446260684Skaiw
1447260684Skaiw	assert(len >= 0);
1448260684Skaiw	assert(negative_factor == 1 || negative_factor == -1);
1449260684Skaiw
1450260684Skaiw	*rtn = len * negative_factor;
1451260684Skaiw
1452260684Skaiw	return (1);
1453260684Skaiw}
1454260684Skaiw
1455260684Skaiwstatic int
1456260684Skaiwcpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
1457260684Skaiw{
1458260684Skaiw
1459260684Skaiw	if (ddata == NULL)
1460260684Skaiw		return (0);
1461260684Skaiw
1462260684Skaiw	if (!cpp_demangle_push_str(ddata, "offset : ", 9))
1463260684Skaiw		return (0);
1464260684Skaiw
1465260684Skaiw	return (cpp_demangle_read_offset_number(ddata));
1466260684Skaiw}
1467260684Skaiw
1468260684Skaiw/* read offset, offset are nv-offset, v-offset */
1469260684Skaiwstatic int
1470260684Skaiwcpp_demangle_read_offset(struct cpp_demangle_data *ddata)
1471260684Skaiw{
1472260684Skaiw
1473260684Skaiw	if (ddata == NULL)
1474260684Skaiw		return (0);
1475260684Skaiw
1476260684Skaiw	if (*ddata->cur == 'h') {
1477260684Skaiw		++ddata->cur;
1478260684Skaiw		return (cpp_demangle_read_nv_offset(ddata));
1479260684Skaiw	} else if (*ddata->cur == 'v') {
1480260684Skaiw		++ddata->cur;
1481260684Skaiw		return (cpp_demangle_read_v_offset(ddata));
1482260684Skaiw	}
1483260684Skaiw
1484260684Skaiw	return (0);
1485260684Skaiw}
1486260684Skaiw
1487260684Skaiwstatic int
1488260684Skaiwcpp_demangle_read_offset_number(struct cpp_demangle_data *ddata)
1489260684Skaiw{
1490260684Skaiw	bool negative;
1491260684Skaiw	const char *start;
1492260684Skaiw
1493260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1494260684Skaiw		return (0);
1495260684Skaiw
1496260684Skaiw	/* offset could be negative */
1497260684Skaiw	if (*ddata->cur == 'n') {
1498260684Skaiw		negative = true;
1499260684Skaiw		start = ddata->cur + 1;
1500260684Skaiw	} else {
1501260684Skaiw		negative = false;
1502260684Skaiw		start = ddata->cur;
1503260684Skaiw	}
1504260684Skaiw
1505260684Skaiw	while (*ddata->cur != '_')
1506260684Skaiw		++ddata->cur;
1507260684Skaiw
1508260684Skaiw	if (negative && !cpp_demangle_push_str(ddata, "-", 1))
1509260684Skaiw		return (0);
1510260684Skaiw
1511260684Skaiw	assert(start != NULL);
1512260684Skaiw
1513260684Skaiw	if (!cpp_demangle_push_str(ddata, start, ddata->cur - start))
1514260684Skaiw		return (0);
1515260684Skaiw	if (!cpp_demangle_push_str(ddata, " ", 1))
1516260684Skaiw		return (0);
1517260684Skaiw
1518260684Skaiw	++ddata->cur;
1519260684Skaiw
1520260684Skaiw	return (1);
1521260684Skaiw}
1522260684Skaiw
1523260684Skaiwstatic int
1524260684Skaiwcpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata)
1525260684Skaiw{
1526260684Skaiw	size_t class_type_len, i, idx, p_idx;
1527260684Skaiw	int p_func_type, rtn;
1528260684Skaiw	char *class_type;
1529260684Skaiw
1530260684Skaiw	if (ddata == NULL || *ddata->cur != 'M' || *(++ddata->cur) == '\0')
1531260684Skaiw		return (0);
1532260684Skaiw
1533260684Skaiw	p_idx = ddata->output.size;
1534260684Skaiw	if (!cpp_demangle_read_type(ddata, 0))
1535260684Skaiw		return (0);
1536260684Skaiw
1537260684Skaiw	if ((class_type = vector_str_substr(&ddata->output, p_idx,
1538260684Skaiw	    ddata->output.size - 1, &class_type_len)) == NULL)
1539260684Skaiw		return (0);
1540260684Skaiw
1541260684Skaiw	rtn = 0;
1542260684Skaiw	idx = ddata->output.size;
1543260684Skaiw	for (i = p_idx; i < idx; ++i)
1544260684Skaiw		if (!vector_str_pop(&ddata->output))
1545260684Skaiw			goto clean1;
1546260684Skaiw
1547260684Skaiw	if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM))
1548260684Skaiw		goto clean1;
1549260684Skaiw
1550260684Skaiw	if (!vector_str_push(&ddata->class_type, class_type, class_type_len))
1551260684Skaiw		goto clean2;
1552260684Skaiw
1553260684Skaiw	p_func_type = ddata->func_type;
1554260684Skaiw	if (!cpp_demangle_read_type(ddata, 0))
1555260684Skaiw		goto clean3;
1556260684Skaiw
1557260684Skaiw	if (p_func_type == ddata->func_type) {
1558260684Skaiw		if (!cpp_demangle_push_str(ddata, " ", 1))
1559260684Skaiw			goto clean3;
1560260684Skaiw		if (!cpp_demangle_push_str(ddata, class_type, class_type_len))
1561260684Skaiw			goto clean3;
1562260684Skaiw		if (!cpp_demangle_push_str(ddata, "::*", 3))
1563260684Skaiw			goto clean3;
1564260684Skaiw	}
1565260684Skaiw
1566260684Skaiw	rtn = 1;
1567260684Skaiwclean3:
1568260684Skaiw	if (!vector_str_pop(&ddata->class_type))
1569260684Skaiw		rtn = 0;
1570260684Skaiwclean2:
1571260684Skaiw	if (!vector_read_cmd_pop(&ddata->cmd))
1572260684Skaiw		rtn = 0;
1573260684Skaiwclean1:
1574260684Skaiw	free(class_type);
1575260684Skaiw
1576260684Skaiw	return (rtn);
1577260684Skaiw}
1578260684Skaiw
1579260684Skaiw/* read source-name, source-name is <len> <ID> */
1580260684Skaiwstatic int
1581260684Skaiwcpp_demangle_read_sname(struct cpp_demangle_data *ddata)
1582260684Skaiw{
1583260684Skaiw	long len;
1584260684Skaiw
1585260684Skaiw	if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
1586260684Skaiw	    len <= 0 || cpp_demangle_push_str(ddata, ddata->cur, len) == 0)
1587260684Skaiw		return (0);
1588260684Skaiw
1589260684Skaiw	assert(ddata->output.size > 0);
1590260684Skaiw	if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == 0)
1591260684Skaiw		ddata->last_sname =
1592260684Skaiw		    ddata->output.container[ddata->output.size - 1];
1593260684Skaiw
1594260684Skaiw	ddata->cur += len;
1595260684Skaiw
1596260684Skaiw	return (1);
1597260684Skaiw}
1598260684Skaiw
1599260684Skaiwstatic int
1600260684Skaiwcpp_demangle_read_subst(struct cpp_demangle_data *ddata)
1601260684Skaiw{
1602260684Skaiw	long nth;
1603260684Skaiw
1604260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1605260684Skaiw		return (0);
1606260684Skaiw
1607260684Skaiw	/* abbreviations of the form Sx */
1608260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
1609260684Skaiw	case SIMPLE_HASH('S', 'a'):
1610260684Skaiw		/* std::allocator */
1611260684Skaiw		if (cpp_demangle_push_str(ddata, "std::allocator", 14) == 0)
1612260684Skaiw			return (0);
1613260684Skaiw		ddata->cur += 2;
1614260684Skaiw		if (*ddata->cur == 'I')
1615260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1616260684Skaiw			    "std::allocator", 14));
1617260684Skaiw		return (1);
1618260684Skaiw
1619260684Skaiw	case SIMPLE_HASH('S', 'b'):
1620260684Skaiw		/* std::basic_string */
1621260684Skaiw		if (!cpp_demangle_push_str(ddata, "std::basic_string", 17))
1622260684Skaiw			return (0);
1623260684Skaiw		ddata->cur += 2;
1624260684Skaiw		if (*ddata->cur == 'I')
1625260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1626260684Skaiw			    "std::basic_string", 17));
1627260684Skaiw		return (1);
1628260684Skaiw
1629260684Skaiw	case SIMPLE_HASH('S', 'd'):
1630260684Skaiw		/* std::basic_iostream<char, std::char_traits<char> > */
1631260684Skaiw		if (!cpp_demangle_push_str(ddata, "std::iostream", 19))
1632260684Skaiw			return (0);
1633260684Skaiw		ddata->last_sname = "iostream";
1634260684Skaiw		ddata->cur += 2;
1635260684Skaiw		if (*ddata->cur == 'I')
1636260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1637260684Skaiw			    "std::iostream", 19));
1638260684Skaiw		return (1);
1639260684Skaiw
1640260684Skaiw	case SIMPLE_HASH('S', 'i'):
1641260684Skaiw		/* std::basic_istream<char, std::char_traits<char> > */
1642260684Skaiw		if (!cpp_demangle_push_str(ddata, "std::istream", 18))
1643260684Skaiw			return (0);
1644260684Skaiw		ddata->last_sname = "istream";
1645260684Skaiw		ddata->cur += 2;
1646260684Skaiw		if (*ddata->cur == 'I')
1647260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1648260684Skaiw			    "std::istream", 18));
1649260684Skaiw		return (1);
1650260684Skaiw
1651260684Skaiw	case SIMPLE_HASH('S', 'o'):
1652260684Skaiw		/* std::basic_ostream<char, std::char_traits<char> > */
1653260684Skaiw		if (!cpp_demangle_push_str(ddata, "std::ostream", 18))
1654260684Skaiw			return (0);
1655260684Skaiw		ddata->last_sname = "istream";
1656260684Skaiw		ddata->cur += 2;
1657260684Skaiw		if (*ddata->cur == 'I')
1658260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1659260684Skaiw			    "std::ostream", 18));
1660260684Skaiw		return (1);
1661260684Skaiw
1662260684Skaiw	case SIMPLE_HASH('S', 's'):
1663260684Skaiw		/*
1664260684Skaiw		 * std::basic_string<char, std::char_traits<char>,
1665260684Skaiw		 * std::allocator<char> >
1666260684Skaiw		 *
1667260684Skaiw		 * a.k.a std::string
1668260684Skaiw		 */
1669260684Skaiw		if (!cpp_demangle_push_str(ddata, "std::string", 11))
1670260684Skaiw			return (0);
1671260684Skaiw		ddata->last_sname = "string";
1672260684Skaiw		ddata->cur += 2;
1673260684Skaiw		if (*ddata->cur == 'I')
1674260684Skaiw			return (cpp_demangle_read_subst_stdtmpl(ddata,
1675260684Skaiw			    "std::string", 11));
1676260684Skaiw		return (1);
1677260684Skaiw
1678260684Skaiw	case SIMPLE_HASH('S', 't'):
1679260684Skaiw		/* std:: */
1680260684Skaiw		return (cpp_demangle_read_subst_std(ddata));
1681260684Skaiw	};
1682260684Skaiw
1683260684Skaiw	if (*(++ddata->cur) == '\0')
1684260684Skaiw		return (0);
1685260684Skaiw
1686260684Skaiw	/* substitution */
1687260684Skaiw	if (*ddata->cur == '_')
1688260684Skaiw		return (cpp_demangle_get_subst(ddata, 0));
1689260684Skaiw	else {
1690260684Skaiw		errno = 0;
1691260684Skaiw		/* substitution number is base 36 */
1692260684Skaiw		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
1693260684Skaiw		    errno != 0)
1694260684Skaiw			return (0);
1695260684Skaiw
1696260684Skaiw		/* first was '_', so increase one */
1697260684Skaiw		++nth;
1698260684Skaiw
1699260684Skaiw		while (*ddata->cur != '_')
1700260684Skaiw			++ddata->cur;
1701260684Skaiw
1702260684Skaiw		assert(nth > 0);
1703260684Skaiw
1704260684Skaiw		return (cpp_demangle_get_subst(ddata, nth));
1705260684Skaiw	}
1706260684Skaiw
1707260684Skaiw	/* NOTREACHED */
1708260684Skaiw	return (0);
1709260684Skaiw}
1710260684Skaiw
1711260684Skaiwstatic int
1712260684Skaiwcpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
1713260684Skaiw{
1714260684Skaiw	struct vector_str *output, v;
1715260684Skaiw	size_t p_idx, subst_str_len;
1716260684Skaiw	int rtn;
1717260684Skaiw	char *subst_str;
1718260684Skaiw
1719260684Skaiw	if (ddata == NULL)
1720260684Skaiw		return (0);
1721260684Skaiw
1722260684Skaiw	if (!vector_str_init(&v))
1723260684Skaiw		return (0);
1724260684Skaiw
1725260684Skaiw	subst_str = NULL;
1726260684Skaiw	rtn = 0;
1727260684Skaiw	if (!cpp_demangle_push_str(ddata, "std::", 5))
1728260684Skaiw		goto clean;
1729260684Skaiw
1730260684Skaiw	if (!vector_str_push(&v, "std::", 5))
1731260684Skaiw		goto clean;
1732260684Skaiw
1733260684Skaiw	ddata->cur += 2;
1734260684Skaiw
1735260684Skaiw	output = cpp_demangle_gnu3_push_head > 0 ?
1736260684Skaiw	    &ddata->output_tmp : &ddata->output;
1737260684Skaiw
1738260684Skaiw	p_idx = output->size;
1739260684Skaiw	if (!cpp_demangle_read_uqname(ddata))
1740260684Skaiw		goto clean;
1741260684Skaiw
1742260684Skaiw	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
1743260684Skaiw	    &subst_str_len)) == NULL)
1744260684Skaiw		goto clean;
1745260684Skaiw
1746260684Skaiw	if (!vector_str_push(&v, subst_str, subst_str_len))
1747260684Skaiw		goto clean;
1748260684Skaiw
1749260684Skaiw	if (!cpp_demangle_push_subst_v(ddata, &v))
1750260684Skaiw		goto clean;
1751260684Skaiw
1752260684Skaiw	if (*ddata->cur == 'I') {
1753260684Skaiw		p_idx = output->size;
1754260684Skaiw		if (!cpp_demangle_read_tmpl_args(ddata))
1755260684Skaiw			goto clean;
1756260684Skaiw		free(subst_str);
1757260684Skaiw		if ((subst_str = vector_str_substr(output, p_idx,
1758260684Skaiw		    output->size - 1, &subst_str_len)) == NULL)
1759260684Skaiw			goto clean;
1760260684Skaiw		if (!vector_str_push(&v, subst_str, subst_str_len))
1761260684Skaiw			goto clean;
1762260684Skaiw		if (!cpp_demangle_push_subst_v(ddata, &v))
1763260684Skaiw			goto clean;
1764260684Skaiw	}
1765260684Skaiw
1766260684Skaiw	rtn = 1;
1767260684Skaiwclean:
1768260684Skaiw	free(subst_str);
1769260684Skaiw	vector_str_dest(&v);
1770260684Skaiw
1771260684Skaiw	return (rtn);
1772260684Skaiw}
1773260684Skaiw
1774260684Skaiwstatic int
1775260684Skaiwcpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
1776260684Skaiw    const char *str, size_t len)
1777260684Skaiw{
1778260684Skaiw	struct vector_str *output;
1779260684Skaiw	size_t p_idx, substr_len;
1780260684Skaiw	int rtn;
1781260684Skaiw	char *subst_str, *substr;
1782260684Skaiw
1783260684Skaiw	if (ddata == NULL || str == NULL || len == 0)
1784260684Skaiw		return (0);
1785260684Skaiw
1786260684Skaiw	output = cpp_demangle_gnu3_push_head > 0 ? &ddata->output_tmp :
1787260684Skaiw	    &ddata->output;
1788260684Skaiw
1789260684Skaiw	p_idx = output->size;
1790260684Skaiw	substr = NULL;
1791260684Skaiw	subst_str = NULL;
1792260684Skaiw
1793260684Skaiw	if (!cpp_demangle_read_tmpl_args(ddata))
1794260684Skaiw		return (0);
1795260684Skaiw	if ((substr = vector_str_substr(output, p_idx, output->size - 1,
1796260684Skaiw	    &substr_len)) == NULL)
1797260684Skaiw		return (0);
1798260684Skaiw
1799260684Skaiw	rtn = 0;
1800260684Skaiw	if ((subst_str = malloc(sizeof(char) * (substr_len + len + 1))) ==
1801260684Skaiw	    NULL)
1802260684Skaiw		goto clean;
1803260684Skaiw
1804260684Skaiw	memcpy(subst_str, str, len);
1805260684Skaiw	memcpy(subst_str + len, substr, substr_len);
1806260684Skaiw	subst_str[substr_len + len] = '\0';
1807260684Skaiw
1808260684Skaiw	if (!cpp_demangle_push_subst(ddata, subst_str, substr_len + len))
1809260684Skaiw		goto clean;
1810260684Skaiw
1811260684Skaiw	rtn = 1;
1812260684Skaiwclean:
1813260684Skaiw	free(subst_str);
1814260684Skaiw	free(substr);
1815260684Skaiw
1816260684Skaiw	return (rtn);
1817260684Skaiw}
1818260684Skaiw
1819260684Skaiwstatic int
1820260684Skaiwcpp_demangle_read_tmpl_arg(struct cpp_demangle_data *ddata)
1821260684Skaiw{
1822260684Skaiw
1823260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1824260684Skaiw		return (0);
1825260684Skaiw
1826260684Skaiw	switch (*ddata->cur) {
1827260684Skaiw	case 'L':
1828260684Skaiw		return (cpp_demangle_read_expr_primary(ddata));
1829260684Skaiw	case 'X':
1830260684Skaiw		return (cpp_demangle_read_expression(ddata));
1831260684Skaiw	};
1832260684Skaiw
1833260684Skaiw	return (cpp_demangle_read_type(ddata, 0));
1834260684Skaiw}
1835260684Skaiw
1836260684Skaiwstatic int
1837260684Skaiwcpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
1838260684Skaiw{
1839260684Skaiw	struct vector_str *v;
1840260684Skaiw	size_t arg_len, idx, limit, size;
1841260684Skaiw	char *arg;
1842260684Skaiw
1843260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
1844260684Skaiw		return (0);
1845260684Skaiw
1846260684Skaiw	++ddata->cur;
1847260684Skaiw
1848260684Skaiw	if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL))
1849260684Skaiw		return (0);
1850260684Skaiw
1851260684Skaiw	if (!cpp_demangle_push_str(ddata, "<", 1))
1852260684Skaiw		return (0);
1853260684Skaiw
1854260684Skaiw	limit = 0;
1855260684Skaiw	v = cpp_demangle_gnu3_push_head > 0 ?
1856260684Skaiw	    &ddata->output_tmp : &ddata->output;
1857260684Skaiw	for (;;) {
1858260684Skaiw		idx = v->size;
1859260684Skaiw		if (!cpp_demangle_read_tmpl_arg(ddata))
1860260684Skaiw			return (0);
1861260684Skaiw		if ((arg = vector_str_substr(v, idx, v->size - 1, &arg_len)) ==
1862260684Skaiw		    NULL)
1863260684Skaiw			return (0);
1864260684Skaiw		if (!vector_str_find(&ddata->tmpl, arg, arg_len) &&
1865260684Skaiw		    !vector_str_push(&ddata->tmpl, arg, arg_len)) {
1866260684Skaiw			free(arg);
1867260684Skaiw			return (0);
1868260684Skaiw		}
1869260684Skaiw
1870260684Skaiw		free(arg);
1871260684Skaiw
1872260684Skaiw		if (*ddata->cur == 'E') {
1873260684Skaiw			++ddata->cur;
1874260684Skaiw			size = v->size;
1875260684Skaiw			assert(size > 0);
1876260684Skaiw			if (!strncmp(v->container[size - 1], ">", 1)) {
1877260684Skaiw				if (!cpp_demangle_push_str(ddata, " >", 2))
1878260684Skaiw					return (0);
1879260684Skaiw			} else if (!cpp_demangle_push_str(ddata, ">", 1))
1880260684Skaiw				return (0);
1881260684Skaiw			break;
1882260684Skaiw		} else if (*ddata->cur != 'I' &&
1883260684Skaiw		    !cpp_demangle_push_str(ddata, ", ", 2))
1884260684Skaiw			return (0);
1885260684Skaiw
1886260684Skaiw		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1887260684Skaiw			return (0);
1888260684Skaiw	}
1889260684Skaiw
1890260684Skaiw	return (vector_read_cmd_pop(&ddata->cmd));
1891260684Skaiw}
1892260684Skaiw
1893260684Skaiw/*
1894260684Skaiw * Read template parameter that forms in 'T[number]_'.
1895260684Skaiw * This function much like to read_subst but only for types.
1896260684Skaiw */
1897260684Skaiwstatic int
1898260684Skaiwcpp_demangle_read_tmpl_param(struct cpp_demangle_data *ddata)
1899260684Skaiw{
1900260684Skaiw	long nth;
1901260684Skaiw
1902260684Skaiw	if (ddata == NULL || *ddata->cur != 'T')
1903260684Skaiw		return (0);
1904260684Skaiw
1905260684Skaiw	++ddata->cur;
1906260684Skaiw
1907260684Skaiw	if (*ddata->cur == '_')
1908260684Skaiw		return (cpp_demangle_get_tmpl_param(ddata, 0));
1909260684Skaiw	else {
1910260684Skaiw
1911260684Skaiw		errno = 0;
1912260684Skaiw		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
1913260684Skaiw		    errno != 0)
1914260684Skaiw			return (0);
1915260684Skaiw
1916260684Skaiw		/* T_ is first */
1917260684Skaiw		++nth;
1918260684Skaiw
1919260684Skaiw		while (*ddata->cur != '_')
1920260684Skaiw			++ddata->cur;
1921260684Skaiw
1922260684Skaiw		assert(nth > 0);
1923260684Skaiw
1924260684Skaiw		return (cpp_demangle_get_tmpl_param(ddata, nth));
1925260684Skaiw	}
1926260684Skaiw
1927260684Skaiw	/* NOTREACHED */
1928260684Skaiw	return (0);
1929260684Skaiw}
1930260684Skaiw
1931260684Skaiwstatic int
1932260684Skaiwcpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
1933260684Skaiw{
1934260684Skaiw	struct vector_type_qualifier v;
1935260684Skaiw	struct vector_str *output;
1936260684Skaiw	size_t p_idx, type_str_len;
1937260684Skaiw	int extern_c, is_builtin;
1938260684Skaiw	long len;
1939260684Skaiw	char *type_str;
1940260684Skaiw
1941260684Skaiw	if (ddata == NULL)
1942260684Skaiw		return (0);
1943260684Skaiw
1944260684Skaiw	output = &ddata->output;
1945260684Skaiw	if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) {
1946260684Skaiw		cpp_demangle_gnu3_push_head++;
1947260684Skaiw		output = &ddata->output_tmp;
1948260684Skaiw	} else if (delimit == 1) {
1949260684Skaiw		if (ddata->paren == false) {
1950260684Skaiw			if (!cpp_demangle_push_str(ddata, "(", 1))
1951260684Skaiw				return (0);
1952260684Skaiw			if (ddata->output.size < 2)
1953260684Skaiw				return (0);
1954260684Skaiw			ddata->paren = true;
1955260684Skaiw			ddata->pfirst = true;
1956260684Skaiw			/* Need pop function name */
1957260684Skaiw			if (ddata->subst.size == 1 &&
1958260684Skaiw			    !vector_str_pop(&ddata->subst))
1959260684Skaiw				return (0);
1960260684Skaiw		}
1961260684Skaiw
1962260684Skaiw		if (ddata->pfirst)
1963260684Skaiw			ddata->pfirst = false;
1964260684Skaiw		else if (*ddata->cur != 'I' &&
1965260684Skaiw		    !cpp_demangle_push_str(ddata, ", ", 2))
1966260684Skaiw			return (0);
1967260684Skaiw	}
1968260684Skaiw
1969260684Skaiw	assert(output != NULL);
1970260684Skaiw	/*
1971260684Skaiw	 * [r, V, K] [P, R, C, G, U] builtin, function, class-enum, array
1972260684Skaiw	 * pointer-to-member, template-param, template-template-param, subst
1973260684Skaiw	 */
1974260684Skaiw
1975260684Skaiw	if (!vector_type_qualifier_init(&v))
1976260684Skaiw		return (0);
1977260684Skaiw
1978260684Skaiw	extern_c = 0;
1979260684Skaiw	is_builtin = 1;
1980260684Skaiw	p_idx = output->size;
1981260684Skaiw	type_str = NULL;
1982260684Skaiwagain:
1983260684Skaiw	/* builtin type */
1984260684Skaiw	switch (*ddata->cur) {
1985260684Skaiw	case 'a':
1986260684Skaiw		/* signed char */
1987260684Skaiw		if (!cpp_demangle_push_str(ddata, "signed char", 11))
1988260684Skaiw			goto clean;
1989260684Skaiw		++ddata->cur;
1990260684Skaiw		goto rtn;
1991260684Skaiw
1992260684Skaiw	case 'A':
1993260684Skaiw		/* array type */
1994260684Skaiw		if (!cpp_demangle_read_array(ddata))
1995260684Skaiw			goto clean;
1996260684Skaiw		is_builtin = 0;
1997260684Skaiw		goto rtn;
1998260684Skaiw
1999260684Skaiw	case 'b':
2000260684Skaiw		/* bool */
2001260684Skaiw		if (!cpp_demangle_push_str(ddata, "bool", 4))
2002260684Skaiw			goto clean;
2003260684Skaiw		++ddata->cur;
2004260684Skaiw		goto rtn;
2005260684Skaiw
2006260684Skaiw	case 'C':
2007260684Skaiw		/* complex pair */
2008260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_CMX))
2009260684Skaiw			goto clean;
2010260684Skaiw		++ddata->cur;
2011260684Skaiw		goto again;
2012260684Skaiw
2013260684Skaiw	case 'c':
2014260684Skaiw		/* char */
2015260684Skaiw		if (!cpp_demangle_push_str(ddata, "char", 4))
2016260684Skaiw			goto clean;
2017260684Skaiw		++ddata->cur;
2018260684Skaiw		goto rtn;
2019260684Skaiw
2020260684Skaiw	case 'd':
2021260684Skaiw		/* double */
2022260684Skaiw		if (!cpp_demangle_push_str(ddata, "double", 6))
2023260684Skaiw			goto clean;
2024260684Skaiw		++ddata->cur;
2025260684Skaiw		goto rtn;
2026260684Skaiw
2027260684Skaiw	case 'e':
2028260684Skaiw		/* long double */
2029260684Skaiw		if (!cpp_demangle_push_str(ddata, "long double", 11))
2030260684Skaiw			goto clean;
2031260684Skaiw		++ddata->cur;
2032260684Skaiw		goto rtn;
2033260684Skaiw
2034260684Skaiw	case 'f':
2035260684Skaiw		/* float */
2036260684Skaiw		if (!cpp_demangle_push_str(ddata, "float", 5))
2037260684Skaiw			goto clean;
2038260684Skaiw		++ddata->cur;
2039260684Skaiw		goto rtn;
2040260684Skaiw
2041260684Skaiw	case 'F':
2042260684Skaiw		/* function */
2043260684Skaiw		if (!cpp_demangle_read_function(ddata, &extern_c, &v))
2044260684Skaiw			goto clean;
2045260684Skaiw		is_builtin = 0;
2046260684Skaiw		goto rtn;
2047260684Skaiw
2048260684Skaiw	case 'g':
2049260684Skaiw		/* __float128 */
2050260684Skaiw		if (!cpp_demangle_push_str(ddata, "__float128", 10))
2051260684Skaiw			goto clean;
2052260684Skaiw		++ddata->cur;
2053260684Skaiw		goto rtn;
2054260684Skaiw
2055260684Skaiw	case 'G':
2056260684Skaiw		/* imaginary */
2057260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_IMG))
2058260684Skaiw			goto clean;
2059260684Skaiw		++ddata->cur;
2060260684Skaiw		goto again;
2061260684Skaiw
2062260684Skaiw	case 'h':
2063260684Skaiw		/* unsigned char */
2064260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned char", 13))
2065260684Skaiw			goto clean;
2066260684Skaiw		++ddata->cur;
2067260684Skaiw		goto rtn;
2068260684Skaiw
2069260684Skaiw	case 'i':
2070260684Skaiw		/* int */
2071260684Skaiw		if (!cpp_demangle_push_str(ddata, "int", 3))
2072260684Skaiw			goto clean;
2073260684Skaiw		++ddata->cur;
2074260684Skaiw		goto rtn;
2075260684Skaiw
2076260684Skaiw	case 'j':
2077260684Skaiw		/* unsigned int */
2078260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned int", 12))
2079260684Skaiw			goto clean;
2080260684Skaiw		++ddata->cur;
2081260684Skaiw		goto rtn;
2082260684Skaiw
2083260684Skaiw	case 'K':
2084260684Skaiw		/* const */
2085260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_CST))
2086260684Skaiw			goto clean;
2087260684Skaiw		++ddata->cur;
2088260684Skaiw		goto again;
2089260684Skaiw
2090260684Skaiw	case 'l':
2091260684Skaiw		/* long */
2092260684Skaiw		if (!cpp_demangle_push_str(ddata, "long", 4))
2093260684Skaiw			goto clean;
2094260684Skaiw		++ddata->cur;
2095260684Skaiw		goto rtn;
2096260684Skaiw
2097260684Skaiw	case 'm':
2098260684Skaiw		/* unsigned long */
2099260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned long", 13))
2100260684Skaiw			goto clean;
2101260684Skaiw
2102260684Skaiw		++ddata->cur;
2103260684Skaiw
2104260684Skaiw		goto rtn;
2105260684Skaiw	case 'M':
2106260684Skaiw		/* pointer to member */
2107260684Skaiw		if (!cpp_demangle_read_pointer_to_member(ddata))
2108260684Skaiw			goto clean;
2109260684Skaiw		is_builtin = 0;
2110260684Skaiw		goto rtn;
2111260684Skaiw
2112260684Skaiw	case 'n':
2113260684Skaiw		/* __int128 */
2114260684Skaiw		if (!cpp_demangle_push_str(ddata, "__int128", 8))
2115260684Skaiw			goto clean;
2116260684Skaiw		++ddata->cur;
2117260684Skaiw		goto rtn;
2118260684Skaiw
2119260684Skaiw	case 'o':
2120260684Skaiw		/* unsigned __int128 */
2121260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned _;int128", 17))
2122260684Skaiw			goto clean;
2123260684Skaiw		++ddata->cur;
2124260684Skaiw		goto rtn;
2125260684Skaiw
2126260684Skaiw	case 'P':
2127260684Skaiw		/* pointer */
2128260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_PTR))
2129260684Skaiw			goto clean;
2130260684Skaiw		++ddata->cur;
2131260684Skaiw		goto again;
2132260684Skaiw
2133260684Skaiw	case 'r':
2134260684Skaiw		/* restrict */
2135260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_RST))
2136260684Skaiw			goto clean;
2137260684Skaiw		++ddata->cur;
2138260684Skaiw		goto again;
2139260684Skaiw
2140260684Skaiw	case 'R':
2141260684Skaiw		/* reference */
2142260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_REF))
2143260684Skaiw			goto clean;
2144260684Skaiw		++ddata->cur;
2145260684Skaiw		goto again;
2146260684Skaiw
2147260684Skaiw	case 's':
2148260684Skaiw		/* short, local string */
2149260684Skaiw		if (!cpp_demangle_push_str(ddata, "short", 5))
2150260684Skaiw			goto clean;
2151260684Skaiw		++ddata->cur;
2152260684Skaiw		goto rtn;
2153260684Skaiw
2154260684Skaiw	case 'S':
2155260684Skaiw		/* substitution */
2156260684Skaiw		if (!cpp_demangle_read_subst(ddata))
2157260684Skaiw			goto clean;
2158260684Skaiw		is_builtin = 0;
2159260684Skaiw		goto rtn;
2160260684Skaiw
2161260684Skaiw	case 't':
2162260684Skaiw		/* unsigned short */
2163260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned short", 14))
2164260684Skaiw			goto clean;
2165260684Skaiw		++ddata->cur;
2166260684Skaiw		goto rtn;
2167260684Skaiw
2168260684Skaiw	case 'T':
2169260684Skaiw		/* template parameter */
2170260684Skaiw		if (!cpp_demangle_read_tmpl_param(ddata))
2171260684Skaiw			goto clean;
2172260684Skaiw		is_builtin = 0;
2173260684Skaiw		goto rtn;
2174260684Skaiw
2175260684Skaiw	case 'u':
2176260684Skaiw		/* vendor extended builtin */
2177260684Skaiw		++ddata->cur;
2178260684Skaiw		if (!cpp_demangle_read_sname(ddata))
2179260684Skaiw			goto clean;
2180260684Skaiw		is_builtin = 0;
2181260684Skaiw		goto rtn;
2182260684Skaiw
2183260684Skaiw	case 'U':
2184260684Skaiw		/* vendor extended type qualifier */
2185260684Skaiw		if (!cpp_demangle_read_number(ddata, &len))
2186260684Skaiw			goto clean;
2187260684Skaiw		if (len <= 0)
2188260684Skaiw			goto clean;
2189260684Skaiw		if (!vector_str_push(&v.ext_name, ddata->cur, len))
2190260684Skaiw			return (0);
2191260684Skaiw		ddata->cur += len;
2192260684Skaiw		goto again;
2193260684Skaiw
2194260684Skaiw	case 'v':
2195260684Skaiw		/* void */
2196260684Skaiw		if (!cpp_demangle_push_str(ddata, "void", 4))
2197260684Skaiw			goto clean;
2198260684Skaiw		++ddata->cur;
2199260684Skaiw		goto rtn;
2200260684Skaiw
2201260684Skaiw	case 'V':
2202260684Skaiw		/* volatile */
2203260684Skaiw		if (!vector_type_qualifier_push(&v, TYPE_VAT))
2204260684Skaiw			goto clean;
2205260684Skaiw		++ddata->cur;
2206260684Skaiw		goto again;
2207260684Skaiw
2208260684Skaiw	case 'w':
2209260684Skaiw		/* wchar_t */
2210260684Skaiw		if (!cpp_demangle_push_str(ddata, "wchar_t", 6))
2211260684Skaiw			goto clean;
2212260684Skaiw		++ddata->cur;
2213260684Skaiw		goto rtn;
2214260684Skaiw
2215260684Skaiw	case 'x':
2216260684Skaiw		/* long long */
2217260684Skaiw		if (!cpp_demangle_push_str(ddata, "long long", 9))
2218260684Skaiw			goto clean;
2219260684Skaiw		++ddata->cur;
2220260684Skaiw		goto rtn;
2221260684Skaiw
2222260684Skaiw	case 'y':
2223260684Skaiw		/* unsigned long long */
2224260684Skaiw		if (!cpp_demangle_push_str(ddata, "unsigned long long", 18))
2225260684Skaiw			goto clean;
2226260684Skaiw		++ddata->cur;
2227260684Skaiw		goto rtn;
2228260684Skaiw
2229260684Skaiw	case 'z':
2230260684Skaiw		/* ellipsis */
2231260684Skaiw		if (!cpp_demangle_push_str(ddata, "ellipsis", 8))
2232260684Skaiw			goto clean;
2233260684Skaiw		++ddata->cur;
2234260684Skaiw		goto rtn;
2235260684Skaiw	};
2236260684Skaiw
2237260684Skaiw	if (!cpp_demangle_read_name(ddata))
2238260684Skaiw		goto clean;
2239260684Skaiw
2240260684Skaiw	is_builtin = 0;
2241260684Skaiwrtn:
2242260684Skaiw	if ((type_str = vector_str_substr(output, p_idx, output->size - 1,
2243260684Skaiw	    &type_str_len)) == NULL)
2244260684Skaiw		goto clean;
2245260684Skaiw
2246260684Skaiw	if (is_builtin == 0) {
2247260684Skaiw		if (!vector_str_find(&ddata->subst, type_str, type_str_len) &&
2248260684Skaiw		    !vector_str_push(&ddata->subst, type_str, type_str_len))
2249260684Skaiw			goto clean;
2250260684Skaiw	}
2251260684Skaiw
2252260684Skaiw	if (!cpp_demangle_push_type_qualifier(ddata, &v, type_str))
2253260684Skaiw		goto clean;
2254260684Skaiw
2255260684Skaiw	free(type_str);
2256260684Skaiw	vector_type_qualifier_dest(&v);
2257260684Skaiw
2258260684Skaiw	if (cpp_demangle_gnu3_push_head > 0) {
2259260684Skaiw		if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata)
2260260684Skaiw		    == 0)
2261260684Skaiw			return (0);
2262260684Skaiw
2263260684Skaiw		if (--cpp_demangle_gnu3_push_head > 0)
2264260684Skaiw			return (1);
2265260684Skaiw
2266260684Skaiw		if (!vector_str_push(&ddata->output_tmp, " ", 1))
2267260684Skaiw			return (0);
2268260684Skaiw
2269260684Skaiw		if (!vector_str_push_vector_head(&ddata->output,
2270260684Skaiw		    &ddata->output_tmp))
2271260684Skaiw			return (0);
2272260684Skaiw
2273260684Skaiw		vector_str_dest(&ddata->output_tmp);
2274260684Skaiw		if (!vector_str_init(&ddata->output_tmp))
2275260684Skaiw			return (0);
2276260684Skaiw
2277260684Skaiw		if (!cpp_demangle_push_str(ddata, "(", 1))
2278260684Skaiw			return (0);
2279260684Skaiw
2280260684Skaiw		ddata->paren = true;
2281260684Skaiw		ddata->pfirst = true;
2282260684Skaiw	}
2283260684Skaiw
2284260684Skaiw	return (1);
2285260684Skaiwclean:
2286260684Skaiw	free(type_str);
2287260684Skaiw	vector_type_qualifier_dest(&v);
2288260684Skaiw
2289260684Skaiw	return (0);
2290260684Skaiw}
2291260684Skaiw
2292260684Skaiw/*
2293260684Skaiw * read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
2294260684Skaiw * source-name
2295260684Skaiw */
2296260684Skaiwstatic int
2297260684Skaiwcpp_demangle_read_uqname(struct cpp_demangle_data *ddata)
2298260684Skaiw{
2299260684Skaiw	size_t len;
2300260684Skaiw
2301260684Skaiw	if (ddata == NULL || *ddata->cur == '\0')
2302260684Skaiw		return (0);
2303260684Skaiw
2304260684Skaiw	/* operator name */
2305260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
2306260684Skaiw	case SIMPLE_HASH('a', 'a'):
2307260684Skaiw		/* operator && */
2308260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator&&", 10))
2309260684Skaiw			return (0);
2310260684Skaiw		ddata->cur += 2;
2311260684Skaiw		return (1);
2312260684Skaiw
2313260684Skaiw	case SIMPLE_HASH('a', 'd'):
2314260684Skaiw		/* operator & (unary) */
2315260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator&", 9))
2316260684Skaiw			return (0);
2317260684Skaiw		ddata->cur += 2;
2318260684Skaiw		return (1);
2319260684Skaiw
2320260684Skaiw	case SIMPLE_HASH('a', 'n'):
2321260684Skaiw		/* operator & */
2322260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator&", 9))
2323260684Skaiw			return (0);
2324260684Skaiw		ddata->cur += 2;
2325260684Skaiw		return (1);
2326260684Skaiw
2327260684Skaiw	case SIMPLE_HASH('a', 'N'):
2328260684Skaiw		/* operator &= */
2329260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator&=", 10))
2330260684Skaiw			return (0);
2331260684Skaiw		ddata->cur += 2;
2332260684Skaiw		return (1);
2333260684Skaiw
2334260684Skaiw	case SIMPLE_HASH('a', 'S'):
2335260684Skaiw		/* operator = */
2336260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator=", 9))
2337260684Skaiw			return (0);
2338260684Skaiw		ddata->cur += 2;
2339260684Skaiw		return (1);
2340260684Skaiw
2341260684Skaiw	case SIMPLE_HASH('c', 'l'):
2342260684Skaiw		/* operator () */
2343260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator()", 10))
2344260684Skaiw			return (0);
2345260684Skaiw		ddata->cur += 2;
2346260684Skaiw		return (1);
2347260684Skaiw
2348260684Skaiw	case SIMPLE_HASH('c', 'm'):
2349260684Skaiw		/* operator , */
2350260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator,", 9))
2351260684Skaiw			return (0);
2352260684Skaiw		ddata->cur += 2;
2353260684Skaiw		return (1);
2354260684Skaiw
2355260684Skaiw	case SIMPLE_HASH('c', 'o'):
2356260684Skaiw		/* operator ~ */
2357260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator~", 9))
2358260684Skaiw			return (0);
2359260684Skaiw		ddata->cur += 2;
2360260684Skaiw		return (1);
2361260684Skaiw
2362260684Skaiw	case SIMPLE_HASH('c', 'v'):
2363260684Skaiw		/* operator (cast) */
2364260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator(cast)", 14))
2365260684Skaiw			return (0);
2366260684Skaiw		ddata->cur += 2;
2367260684Skaiw		return (cpp_demangle_read_type(ddata, 1));
2368260684Skaiw
2369260684Skaiw	case SIMPLE_HASH('d', 'a'):
2370260684Skaiw		/* operator delete [] */
2371260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator delete []", 18))
2372260684Skaiw			return (0);
2373260684Skaiw		ddata->cur += 2;
2374260684Skaiw		return (1);
2375260684Skaiw
2376260684Skaiw	case SIMPLE_HASH('d', 'e'):
2377260684Skaiw		/* operator * (unary) */
2378260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator*", 9))
2379260684Skaiw			return (0);
2380260684Skaiw		ddata->cur += 2;
2381260684Skaiw		return (1);
2382260684Skaiw
2383260684Skaiw	case SIMPLE_HASH('d', 'l'):
2384260684Skaiw		/* operator delete */
2385260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator delete", 15))
2386260684Skaiw			return (0);
2387260684Skaiw		ddata->cur += 2;
2388260684Skaiw		return (1);
2389260684Skaiw
2390260684Skaiw	case SIMPLE_HASH('d', 'v'):
2391260684Skaiw		/* operator / */
2392260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator/", 9))
2393260684Skaiw			return (0);
2394260684Skaiw		ddata->cur += 2;
2395260684Skaiw		return (1);
2396260684Skaiw
2397260684Skaiw	case SIMPLE_HASH('d', 'V'):
2398260684Skaiw		/* operator /= */
2399260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator/=", 10))
2400260684Skaiw			return (0);
2401260684Skaiw		ddata->cur += 2;
2402260684Skaiw		return (1);
2403260684Skaiw
2404260684Skaiw	case SIMPLE_HASH('e', 'o'):
2405260684Skaiw		/* operator ^ */
2406260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator^", 9))
2407260684Skaiw			return (0);
2408260684Skaiw		ddata->cur += 2;
2409260684Skaiw		return (1);
2410260684Skaiw
2411260684Skaiw	case SIMPLE_HASH('e', 'O'):
2412260684Skaiw		/* operator ^= */
2413260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator^=", 10))
2414260684Skaiw			return (0);
2415260684Skaiw		ddata->cur += 2;
2416260684Skaiw		return (1);
2417260684Skaiw
2418260684Skaiw	case SIMPLE_HASH('e', 'q'):
2419260684Skaiw		/* operator == */
2420260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator==", 10))
2421260684Skaiw			return (0);
2422260684Skaiw		ddata->cur += 2;
2423260684Skaiw		return (1);
2424260684Skaiw
2425260684Skaiw	case SIMPLE_HASH('g', 'e'):
2426260684Skaiw		/* operator >= */
2427260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator>=", 10))
2428260684Skaiw			return (0);
2429260684Skaiw		ddata->cur += 2;
2430260684Skaiw		return (1);
2431260684Skaiw
2432260684Skaiw	case SIMPLE_HASH('g', 't'):
2433260684Skaiw		/* operator > */
2434260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator>", 9))
2435260684Skaiw			return (0);
2436260684Skaiw		ddata->cur += 2;
2437260684Skaiw		return (1);
2438260684Skaiw
2439260684Skaiw	case SIMPLE_HASH('i', 'x'):
2440260684Skaiw		/* operator [] */
2441260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator[]", 10))
2442260684Skaiw			return (0);
2443260684Skaiw		ddata->cur += 2;
2444260684Skaiw		return (1);
2445260684Skaiw
2446260684Skaiw	case SIMPLE_HASH('l', 'e'):
2447260684Skaiw		/* operator <= */
2448260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator<=", 10))
2449260684Skaiw			return (0);
2450260684Skaiw		ddata->cur += 2;
2451260684Skaiw		return (1);
2452260684Skaiw
2453260684Skaiw	case SIMPLE_HASH('l', 's'):
2454260684Skaiw		/* operator << */
2455260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator<<", 10))
2456260684Skaiw			return (0);
2457260684Skaiw		ddata->cur += 2;
2458260684Skaiw		return (1);
2459260684Skaiw
2460260684Skaiw	case SIMPLE_HASH('l', 'S'):
2461260684Skaiw		/* operator <<= */
2462260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator<<=", 11))
2463260684Skaiw			return (0);
2464260684Skaiw		ddata->cur += 2;
2465260684Skaiw		return (1);
2466260684Skaiw
2467260684Skaiw	case SIMPLE_HASH('l', 't'):
2468260684Skaiw		/* operator < */
2469260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator<", 9))
2470260684Skaiw			return (0);
2471260684Skaiw		ddata->cur += 2;
2472260684Skaiw		return (1);
2473260684Skaiw
2474260684Skaiw	case SIMPLE_HASH('m', 'i'):
2475260684Skaiw		/* operator - */
2476260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator-", 9))
2477260684Skaiw			return (0);
2478260684Skaiw		ddata->cur += 2;
2479260684Skaiw		return (1);
2480260684Skaiw
2481260684Skaiw	case SIMPLE_HASH('m', 'I'):
2482260684Skaiw		/* operator -= */
2483260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator-=", 10))
2484260684Skaiw			return (0);
2485260684Skaiw		ddata->cur += 2;
2486260684Skaiw		return (1);
2487260684Skaiw
2488260684Skaiw	case SIMPLE_HASH('m', 'l'):
2489260684Skaiw		/* operator * */
2490260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator*", 9))
2491260684Skaiw			return (0);
2492260684Skaiw		ddata->cur += 2;
2493260684Skaiw		return (1);
2494260684Skaiw
2495260684Skaiw	case SIMPLE_HASH('m', 'L'):
2496260684Skaiw		/* operator *= */
2497260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator*=", 10))
2498260684Skaiw			return (0);
2499260684Skaiw		ddata->cur += 2;
2500260684Skaiw		return (1);
2501260684Skaiw
2502260684Skaiw	case SIMPLE_HASH('m', 'm'):
2503260684Skaiw		/* operator -- */
2504260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator--", 10))
2505260684Skaiw			return (0);
2506260684Skaiw		ddata->cur += 2;
2507260684Skaiw		return (1);
2508260684Skaiw
2509260684Skaiw	case SIMPLE_HASH('n', 'a'):
2510260684Skaiw		/* operator new[] */
2511260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator new []", 15))
2512260684Skaiw			return (0);
2513260684Skaiw		ddata->cur += 2;
2514260684Skaiw		return (1);
2515260684Skaiw
2516260684Skaiw	case SIMPLE_HASH('n', 'e'):
2517260684Skaiw		/* operator != */
2518260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator!=", 10))
2519260684Skaiw			return (0);
2520260684Skaiw		ddata->cur += 2;
2521260684Skaiw		return (1);
2522260684Skaiw
2523260684Skaiw	case SIMPLE_HASH('n', 'g'):
2524260684Skaiw		/* operator - (unary) */
2525260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator-", 9))
2526260684Skaiw			return (0);
2527260684Skaiw		ddata->cur += 2;
2528260684Skaiw		return (1);
2529260684Skaiw
2530260684Skaiw	case SIMPLE_HASH('n', 't'):
2531260684Skaiw		/* operator ! */
2532260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator!", 9))
2533260684Skaiw			return (0);
2534260684Skaiw		ddata->cur += 2;
2535260684Skaiw		return (1);
2536260684Skaiw
2537260684Skaiw	case SIMPLE_HASH('n', 'w'):
2538260684Skaiw		/* operator new */
2539260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator new", 12))
2540260684Skaiw			return (0);
2541260684Skaiw		ddata->cur += 2;
2542260684Skaiw		return (1);
2543260684Skaiw
2544260684Skaiw	case SIMPLE_HASH('o', 'o'):
2545260684Skaiw		/* operator || */
2546260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator||", 10))
2547260684Skaiw			return (0);
2548260684Skaiw		ddata->cur += 2;
2549260684Skaiw		return (1);
2550260684Skaiw
2551260684Skaiw	case SIMPLE_HASH('o', 'r'):
2552260684Skaiw		/* operator | */
2553260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator|", 9))
2554260684Skaiw			return (0);
2555260684Skaiw		ddata->cur += 2;
2556260684Skaiw		return (1);
2557260684Skaiw
2558260684Skaiw	case SIMPLE_HASH('o', 'R'):
2559260684Skaiw		/* operator |= */
2560260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator|=", 10))
2561260684Skaiw			return (0);
2562260684Skaiw		ddata->cur += 2;
2563260684Skaiw		return (1);
2564260684Skaiw
2565260684Skaiw	case SIMPLE_HASH('p', 'l'):
2566260684Skaiw		/* operator + */
2567260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator+", 9))
2568260684Skaiw			return (0);
2569260684Skaiw		ddata->cur += 2;
2570260684Skaiw		return (1);
2571260684Skaiw
2572260684Skaiw	case SIMPLE_HASH('p', 'L'):
2573260684Skaiw		/* operator += */
2574260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator+=", 10))
2575260684Skaiw			return (0);
2576260684Skaiw		ddata->cur += 2;
2577260684Skaiw		return (1);
2578260684Skaiw
2579260684Skaiw	case SIMPLE_HASH('p', 'm'):
2580260684Skaiw		/* operator ->* */
2581260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator->*", 11))
2582260684Skaiw			return (0);
2583260684Skaiw		ddata->cur += 2;
2584260684Skaiw		return (1);
2585260684Skaiw
2586260684Skaiw	case SIMPLE_HASH('p', 'p'):
2587260684Skaiw		/* operator ++ */
2588260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator++", 10))
2589260684Skaiw			return (0);
2590260684Skaiw		ddata->cur += 2;
2591260684Skaiw		return (1);
2592260684Skaiw
2593260684Skaiw	case SIMPLE_HASH('p', 's'):
2594260684Skaiw		/* operator + (unary) */
2595260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator+", 9))
2596260684Skaiw			return (0);
2597260684Skaiw		ddata->cur += 2;
2598260684Skaiw		return (1);
2599260684Skaiw
2600260684Skaiw	case SIMPLE_HASH('p', 't'):
2601260684Skaiw		/* operator -> */
2602260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator->", 10))
2603260684Skaiw			return (0);
2604260684Skaiw		ddata->cur += 2;
2605260684Skaiw		return (1);
2606260684Skaiw
2607260684Skaiw	case SIMPLE_HASH('q', 'u'):
2608260684Skaiw		/* operator ? */
2609260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator?", 9))
2610260684Skaiw			return (0);
2611260684Skaiw		ddata->cur += 2;
2612260684Skaiw		return (1);
2613260684Skaiw
2614260684Skaiw	case SIMPLE_HASH('r', 'm'):
2615260684Skaiw		/* operator % */
2616260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator%", 9))
2617260684Skaiw			return (0);
2618260684Skaiw		ddata->cur += 2;
2619260684Skaiw		return (1);
2620260684Skaiw
2621260684Skaiw	case SIMPLE_HASH('r', 'M'):
2622260684Skaiw		/* operator %= */
2623260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator%=", 10))
2624260684Skaiw			return (0);
2625260684Skaiw		ddata->cur += 2;
2626260684Skaiw		return (1);
2627260684Skaiw
2628260684Skaiw	case SIMPLE_HASH('r', 's'):
2629260684Skaiw		/* operator >> */
2630260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator>>", 10))
2631260684Skaiw			return (0);
2632260684Skaiw		ddata->cur += 2;
2633260684Skaiw		return (1);
2634260684Skaiw
2635260684Skaiw	case SIMPLE_HASH('r', 'S'):
2636260684Skaiw		/* operator >>= */
2637260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator>>=", 11))
2638260684Skaiw			return (0);
2639260684Skaiw		ddata->cur += 2;
2640260684Skaiw		return (1);
2641260684Skaiw
2642260684Skaiw	case SIMPLE_HASH('r', 'z'):
2643260684Skaiw		/* operator sizeof */
2644260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16))
2645260684Skaiw			return (0);
2646260684Skaiw		ddata->cur += 2;
2647260684Skaiw		return (1);
2648260684Skaiw
2649260684Skaiw	case SIMPLE_HASH('s', 'r'):
2650260684Skaiw		/* scope resolution operator */
2651260684Skaiw		if (!cpp_demangle_push_str(ddata, "scope resolution operator ",
2652260684Skaiw		    26))
2653260684Skaiw			return (0);
2654260684Skaiw		ddata->cur += 2;
2655260684Skaiw		return (1);
2656260684Skaiw
2657260684Skaiw	case SIMPLE_HASH('s', 'v'):
2658260684Skaiw		/* operator sizeof */
2659260684Skaiw		if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16))
2660260684Skaiw			return (0);
2661260684Skaiw		ddata->cur += 2;
2662260684Skaiw		return (1);
2663260684Skaiw	};
2664260684Skaiw
2665260684Skaiw	/* vendor extened operator */
2666260684Skaiw	if (*ddata->cur == 'v' && ELFTC_ISDIGIT(*(ddata->cur + 1))) {
2667260684Skaiw		if (!cpp_demangle_push_str(ddata, "vendor extened operator ",
2668260684Skaiw		    24))
2669260684Skaiw			return (0);
2670260684Skaiw		if (!cpp_demangle_push_str(ddata, ddata->cur + 1, 1))
2671260684Skaiw			return (0);
2672260684Skaiw		ddata->cur += 2;
2673260684Skaiw		return (cpp_demangle_read_sname(ddata));
2674260684Skaiw	}
2675260684Skaiw
2676260684Skaiw	/* ctor-dtor-name */
2677260684Skaiw	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
2678260684Skaiw	case SIMPLE_HASH('C', '1'):
2679260684Skaiw		/* FALLTHROUGH */
2680260684Skaiw	case SIMPLE_HASH('C', '2'):
2681260684Skaiw		/* FALLTHROUGH */
2682260684Skaiw	case SIMPLE_HASH('C', '3'):
2683260684Skaiw		if (ddata->last_sname == NULL)
2684260684Skaiw			return (0);
2685260684Skaiw		if ((len = strlen(ddata->last_sname)) == 0)
2686260684Skaiw			return (0);
2687260684Skaiw		if (!cpp_demangle_push_str(ddata, "::", 2))
2688260684Skaiw			return (0);
2689260684Skaiw		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
2690260684Skaiw			return (0);
2691260684Skaiw		ddata->cur +=2;
2692260684Skaiw		return (1);
2693260684Skaiw
2694260684Skaiw	case SIMPLE_HASH('D', '0'):
2695260684Skaiw		/* FALLTHROUGH */
2696260684Skaiw	case SIMPLE_HASH('D', '1'):
2697260684Skaiw		/* FALLTHROUGH */
2698260684Skaiw	case SIMPLE_HASH('D', '2'):
2699260684Skaiw		if (ddata->last_sname == NULL)
2700260684Skaiw			return (0);
2701260684Skaiw		if ((len = strlen(ddata->last_sname)) == 0)
2702260684Skaiw			return (0);
2703260684Skaiw		if (!cpp_demangle_push_str(ddata, "::~", 3))
2704260684Skaiw			return (0);
2705260684Skaiw		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
2706260684Skaiw			return (0);
2707260684Skaiw		ddata->cur +=2;
2708260684Skaiw		return (1);
2709260684Skaiw	};
2710260684Skaiw
2711260684Skaiw	/* source name */
2712260684Skaiw	if (ELFTC_ISDIGIT(*ddata->cur) != 0)
2713260684Skaiw		return (cpp_demangle_read_sname(ddata));
2714260684Skaiw
2715260684Skaiw	/* local source name */
2716260684Skaiw	if (*ddata->cur == 'L')
2717260684Skaiw		return (cpp_demangle_local_source_name(ddata));
2718260684Skaiw
2719260684Skaiw	return (1);
2720260684Skaiw}
2721260684Skaiw
2722260684Skaiw/*
2723260684Skaiw * Read local source name.
2724260684Skaiw *
2725260684Skaiw * References:
2726260684Skaiw *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
2727260684Skaiw *   http://gcc.gnu.org/viewcvs?view=rev&revision=124467
2728260684Skaiw */
2729260684Skaiwstatic int
2730260684Skaiwcpp_demangle_local_source_name(struct cpp_demangle_data *ddata)
2731260684Skaiw{
2732260684Skaiw	/* L */
2733260684Skaiw	if (ddata == NULL || *ddata->cur != 'L')
2734260684Skaiw		return (0);
2735260684Skaiw	++ddata->cur;
2736260684Skaiw
2737260684Skaiw	/* source name */
2738260684Skaiw	if (!cpp_demangle_read_sname(ddata))
2739260684Skaiw		return (0);
2740260684Skaiw
2741260684Skaiw	/* discriminator */
2742260684Skaiw	if (*ddata->cur == '_') {
2743260684Skaiw		++ddata->cur;
2744260684Skaiw		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
2745260684Skaiw			++ddata->cur;
2746260684Skaiw	}
2747260684Skaiw
2748260684Skaiw	return (1);
2749260684Skaiw}
2750260684Skaiw
2751260684Skaiwstatic int
2752260684Skaiwcpp_demangle_read_v_offset(struct cpp_demangle_data *ddata)
2753260684Skaiw{
2754260684Skaiw
2755260684Skaiw	if (ddata == NULL)
2756260684Skaiw		return (0);
2757260684Skaiw
2758260684Skaiw	if (!cpp_demangle_push_str(ddata, "offset : ", 9))
2759260684Skaiw		return (0);
2760260684Skaiw
2761260684Skaiw	if (!cpp_demangle_read_offset_number(ddata))
2762260684Skaiw		return (0);
2763260684Skaiw
2764260684Skaiw	if (!cpp_demangle_push_str(ddata, "virtual offset : ", 17))
2765260684Skaiw		return (0);
2766260684Skaiw
2767260684Skaiw	return (!cpp_demangle_read_offset_number(ddata));
2768260684Skaiw}
2769260684Skaiw
2770260684Skaiw/*
2771260684Skaiw * Decode floating point representation to string
2772260684Skaiw * Return new allocated string or NULL
2773260684Skaiw *
2774260684Skaiw * Todo
2775260684Skaiw * Replace these functions to macro.
2776260684Skaiw */
2777260684Skaiwstatic char *
2778260684Skaiwdecode_fp_to_double(const char *p, size_t len)
2779260684Skaiw{
2780260684Skaiw	double f;
2781260684Skaiw	size_t rtn_len, limit, i;
2782260684Skaiw	int byte;
2783260684Skaiw	char *rtn;
2784260684Skaiw
2785260684Skaiw	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(double))
2786260684Skaiw		return (NULL);
2787260684Skaiw
2788260684Skaiw	memset(&f, 0, sizeof(double));
2789260684Skaiw
2790260684Skaiw	for (i = 0; i < len / 2; ++i) {
2791260684Skaiw		byte = hex_to_dec(p[len - i * 2 - 1]) +
2792260684Skaiw		    hex_to_dec(p[len - i * 2 - 2]) * 16;
2793260684Skaiw
2794260684Skaiw		if (byte < 0 || byte > 255)
2795260684Skaiw			return (NULL);
2796260684Skaiw
2797260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
2798260684Skaiw		((unsigned char *)&f)[i] = (unsigned char)(byte);
2799260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2800260684Skaiw		((unsigned char *)&f)[sizeof(double) - i - 1] =
2801260684Skaiw		    (unsigned char)(byte);
2802260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2803260684Skaiw	}
2804260684Skaiw
2805260684Skaiw	rtn_len = 64;
2806260684Skaiw	limit = 0;
2807260684Skaiwagain:
2808260684Skaiw	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
2809260684Skaiw		return (NULL);
2810260684Skaiw
2811260684Skaiw	if (snprintf(rtn, rtn_len, "%fld", f) >= (int)rtn_len) {
2812260684Skaiw		free(rtn);
2813260684Skaiw		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
2814260684Skaiw			return (NULL);
2815260684Skaiw		rtn_len *= BUFFER_GROWFACTOR;
2816260684Skaiw		goto again;
2817260684Skaiw	}
2818260684Skaiw
2819260684Skaiw	return rtn;
2820260684Skaiw}
2821260684Skaiw
2822260684Skaiwstatic char *
2823260684Skaiwdecode_fp_to_float(const char *p, size_t len)
2824260684Skaiw{
2825260684Skaiw	size_t i, rtn_len, limit;
2826260684Skaiw	float f;
2827260684Skaiw	int byte;
2828260684Skaiw	char *rtn;
2829260684Skaiw
2830260684Skaiw	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(float))
2831260684Skaiw		return (NULL);
2832260684Skaiw
2833260684Skaiw	memset(&f, 0, sizeof(float));
2834260684Skaiw
2835260684Skaiw	for (i = 0; i < len / 2; ++i) {
2836260684Skaiw		byte = hex_to_dec(p[len - i * 2 - 1]) +
2837260684Skaiw		    hex_to_dec(p[len - i * 2 - 2]) * 16;
2838260684Skaiw		if (byte < 0 || byte > 255)
2839260684Skaiw			return (NULL);
2840260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
2841260684Skaiw		((unsigned char *)&f)[i] = (unsigned char)(byte);
2842260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2843260684Skaiw		((unsigned char *)&f)[sizeof(float) - i - 1] =
2844260684Skaiw		    (unsigned char)(byte);
2845260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2846260684Skaiw	}
2847260684Skaiw
2848260684Skaiw	rtn_len = 64;
2849260684Skaiw	limit = 0;
2850260684Skaiwagain:
2851260684Skaiw	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
2852260684Skaiw		return (NULL);
2853260684Skaiw
2854260684Skaiw	if (snprintf(rtn, rtn_len, "%ff", f) >= (int)rtn_len) {
2855260684Skaiw		free(rtn);
2856260684Skaiw		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
2857260684Skaiw			return (NULL);
2858260684Skaiw		rtn_len *= BUFFER_GROWFACTOR;
2859260684Skaiw		goto again;
2860260684Skaiw	}
2861260684Skaiw
2862260684Skaiw	return rtn;
2863260684Skaiw}
2864260684Skaiw
2865260684Skaiwstatic char *
2866260684Skaiwdecode_fp_to_float128(const char *p, size_t len)
2867260684Skaiw{
2868260684Skaiw	long double f;
2869260684Skaiw	size_t rtn_len, limit, i;
2870260684Skaiw	int byte;
2871260684Skaiw	unsigned char buf[FLOAT_QUADRUPLE_BYTES];
2872260684Skaiw	char *rtn;
2873260684Skaiw
2874260684Skaiw	switch(sizeof(long double)) {
2875260684Skaiw	case FLOAT_QUADRUPLE_BYTES:
2876260684Skaiw		return (decode_fp_to_long_double(p, len));
2877260684Skaiw	case FLOAT_EXTENED_BYTES:
2878260684Skaiw		if (p == NULL || len == 0 || len % 2 != 0 ||
2879260684Skaiw		    len / 2 > FLOAT_QUADRUPLE_BYTES)
2880260684Skaiw			return (NULL);
2881260684Skaiw
2882260684Skaiw		memset(buf, 0, FLOAT_QUADRUPLE_BYTES);
2883260684Skaiw
2884260684Skaiw		for (i = 0; i < len / 2; ++i) {
2885260684Skaiw			byte = hex_to_dec(p[len - i * 2 - 1]) +
2886260684Skaiw			    hex_to_dec(p[len - i * 2 - 2]) * 16;
2887260684Skaiw			if (byte < 0 || byte > 255)
2888260684Skaiw				return (NULL);
2889260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
2890260684Skaiw			buf[i] = (unsigned char)(byte);
2891260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2892260684Skaiw			buf[FLOAT_QUADRUPLE_BYTES - i -1] =
2893260684Skaiw			    (unsigned char)(byte);
2894260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2895260684Skaiw		}
2896260684Skaiw		memset(&f, 0, FLOAT_EXTENED_BYTES);
2897260684Skaiw
2898260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
2899260684Skaiw		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
2900260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2901260684Skaiw		memcpy(&f, buf + 6, FLOAT_EXTENED_BYTES);
2902260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2903260684Skaiw
2904260684Skaiw		rtn_len = 256;
2905260684Skaiw		limit = 0;
2906260684Skaiwagain:
2907260684Skaiw		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
2908260684Skaiw			return (NULL);
2909260684Skaiw
2910260684Skaiw		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
2911260684Skaiw			free(rtn);
2912260684Skaiw			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
2913260684Skaiw				return (NULL);
2914260684Skaiw			rtn_len *= BUFFER_GROWFACTOR;
2915260684Skaiw			goto again;
2916260684Skaiw		}
2917260684Skaiw
2918260684Skaiw		return (rtn);
2919260684Skaiw	default:
2920260684Skaiw		return (NULL);
2921260684Skaiw	}
2922260684Skaiw}
2923260684Skaiw
2924260684Skaiwstatic char *
2925260684Skaiwdecode_fp_to_float80(const char *p, size_t len)
2926260684Skaiw{
2927260684Skaiw	long double f;
2928260684Skaiw	size_t rtn_len, limit, i;
2929260684Skaiw	int byte;
2930260684Skaiw	unsigned char buf[FLOAT_EXTENED_BYTES];
2931260684Skaiw	char *rtn;
2932260684Skaiw
2933260684Skaiw	switch(sizeof(long double)) {
2934260684Skaiw	case FLOAT_QUADRUPLE_BYTES:
2935260684Skaiw		if (p == NULL || len == 0 || len % 2 != 0 ||
2936260684Skaiw		    len / 2 > FLOAT_EXTENED_BYTES)
2937260684Skaiw			return (NULL);
2938260684Skaiw
2939260684Skaiw		memset(buf, 0, FLOAT_EXTENED_BYTES);
2940260684Skaiw
2941260684Skaiw		for (i = 0; i < len / 2; ++i) {
2942260684Skaiw			byte = hex_to_dec(p[len - i * 2 - 1]) +
2943260684Skaiw			    hex_to_dec(p[len - i * 2 - 2]) * 16;
2944260684Skaiw
2945260684Skaiw			if (byte < 0 || byte > 255)
2946260684Skaiw				return (NULL);
2947260684Skaiw
2948260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
2949260684Skaiw			buf[i] = (unsigned char)(byte);
2950260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2951260684Skaiw			buf[FLOAT_EXTENED_BYTES - i -1] =
2952260684Skaiw			    (unsigned char)(byte);
2953260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2954260684Skaiw		}
2955260684Skaiw
2956260684Skaiw		memset(&f, 0, FLOAT_QUADRUPLE_BYTES);
2957260684Skaiw
2958260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
2959260684Skaiw		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
2960260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2961260684Skaiw		memcpy((unsigned char *)(&f) + 6, buf, FLOAT_EXTENED_BYTES);
2962260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
2963260684Skaiw
2964260684Skaiw		rtn_len = 256;
2965260684Skaiw		limit = 0;
2966260684Skaiwagain:
2967260684Skaiw		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
2968260684Skaiw			return (NULL);
2969260684Skaiw
2970260684Skaiw		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
2971260684Skaiw			free(rtn);
2972260684Skaiw			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
2973260684Skaiw				return (NULL);
2974260684Skaiw			rtn_len *= BUFFER_GROWFACTOR;
2975260684Skaiw			goto again;
2976260684Skaiw		}
2977260684Skaiw
2978260684Skaiw		return (rtn);
2979260684Skaiw	case FLOAT_EXTENED_BYTES:
2980260684Skaiw		return (decode_fp_to_long_double(p, len));
2981260684Skaiw	default:
2982260684Skaiw		return (NULL);
2983260684Skaiw	}
2984260684Skaiw}
2985260684Skaiw
2986260684Skaiwstatic char *
2987260684Skaiwdecode_fp_to_long_double(const char *p, size_t len)
2988260684Skaiw{
2989260684Skaiw	long double f;
2990260684Skaiw	size_t rtn_len, limit, i;
2991260684Skaiw	int byte;
2992260684Skaiw	char *rtn;
2993260684Skaiw
2994260684Skaiw	if (p == NULL || len == 0 || len % 2 != 0 ||
2995260684Skaiw	    len / 2 > sizeof(long double))
2996260684Skaiw		return (NULL);
2997260684Skaiw
2998260684Skaiw	memset(&f, 0, sizeof(long double));
2999260684Skaiw
3000260684Skaiw	for (i = 0; i < len / 2; ++i) {
3001260684Skaiw		byte = hex_to_dec(p[len - i * 2 - 1]) +
3002260684Skaiw		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3003260684Skaiw
3004260684Skaiw		if (byte < 0 || byte > 255)
3005260684Skaiw			return (NULL);
3006260684Skaiw
3007260684Skaiw#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3008260684Skaiw		((unsigned char *)&f)[i] = (unsigned char)(byte);
3009260684Skaiw#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3010260684Skaiw		((unsigned char *)&f)[sizeof(long double) - i - 1] =
3011260684Skaiw		    (unsigned char)(byte);
3012260684Skaiw#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3013260684Skaiw	}
3014260684Skaiw
3015260684Skaiw	rtn_len = 256;
3016260684Skaiw	limit = 0;
3017260684Skaiwagain:
3018260684Skaiw	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3019260684Skaiw		return (NULL);
3020260684Skaiw
3021260684Skaiw	if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3022260684Skaiw		free(rtn);
3023260684Skaiw		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3024260684Skaiw			return (NULL);
3025260684Skaiw		rtn_len *= BUFFER_GROWFACTOR;
3026260684Skaiw		goto again;
3027260684Skaiw	}
3028260684Skaiw
3029260684Skaiw	return (rtn);
3030260684Skaiw}
3031260684Skaiw
3032260684Skaiw/* Simple hex to integer function used by decode_to_* function. */
3033260684Skaiwstatic int
3034260684Skaiwhex_to_dec(char c)
3035260684Skaiw{
3036260684Skaiw
3037260684Skaiw	switch (c) {
3038260684Skaiw	case '0':
3039260684Skaiw		return (0);
3040260684Skaiw	case '1':
3041260684Skaiw		return (1);
3042260684Skaiw	case '2':
3043260684Skaiw		return (2);
3044260684Skaiw	case '3':
3045260684Skaiw		return (3);
3046260684Skaiw	case '4':
3047260684Skaiw		return (4);
3048260684Skaiw	case '5':
3049260684Skaiw		return (5);
3050260684Skaiw	case '6':
3051260684Skaiw		return (6);
3052260684Skaiw	case '7':
3053260684Skaiw		return (7);
3054260684Skaiw	case '8':
3055260684Skaiw		return (8);
3056260684Skaiw	case '9':
3057260684Skaiw		return (9);
3058260684Skaiw	case 'a':
3059260684Skaiw		return (10);
3060260684Skaiw	case 'b':
3061260684Skaiw		return (11);
3062260684Skaiw	case 'c':
3063260684Skaiw		return (12);
3064260684Skaiw	case 'd':
3065260684Skaiw		return (13);
3066260684Skaiw	case 'e':
3067260684Skaiw		return (14);
3068260684Skaiw	case 'f':
3069260684Skaiw		return (15);
3070260684Skaiw	default:
3071260684Skaiw		return (-1);
3072260684Skaiw	};
3073260684Skaiw}
3074260684Skaiw
3075260684Skaiw/**
3076260684Skaiw * @brief Test input string is mangled by IA-64 C++ ABI style.
3077260684Skaiw *
3078260684Skaiw * Test string heads with "_Z" or "_GLOBAL__I_".
3079260684Skaiw * @return Return 0 at false.
3080260684Skaiw */
3081260684Skaiwbool
3082260684Skaiwis_cpp_mangled_gnu3(const char *org)
3083260684Skaiw{
3084260684Skaiw	size_t len;
3085260684Skaiw
3086260684Skaiw	len = strlen(org);
3087260684Skaiw	return ((len > 2 && *org == '_' && *(org + 1) == 'Z') ||
3088260684Skaiw	    (len > 11 && !strncmp(org, "_GLOBAL__I_", 11)));
3089260684Skaiw}
3090260684Skaiw
3091260684Skaiwstatic void
3092260684Skaiwvector_read_cmd_dest(struct vector_read_cmd *v)
3093260684Skaiw{
3094260684Skaiw
3095260684Skaiw	if (v == NULL)
3096260684Skaiw		return;
3097260684Skaiw
3098260684Skaiw	free(v->r_container);
3099260684Skaiw}
3100260684Skaiw
3101260684Skaiw/* return -1 at failed, 0 at not found, 1 at found. */
3102260684Skaiwstatic int
3103260684Skaiwvector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst)
3104260684Skaiw{
3105260684Skaiw	size_t i;
3106260684Skaiw
3107260684Skaiw	if (v == NULL || dst == READ_FAIL)
3108260684Skaiw		return (-1);
3109260684Skaiw
3110260684Skaiw	for (i = 0; i < v->size; ++i)
3111260684Skaiw		if (v->r_container[i] == dst)
3112260684Skaiw			return (1);
3113260684Skaiw
3114260684Skaiw	return (0);
3115260684Skaiw}
3116260684Skaiw
3117260684Skaiwstatic int
3118260684Skaiwvector_read_cmd_init(struct vector_read_cmd *v)
3119260684Skaiw{
3120260684Skaiw
3121260684Skaiw	if (v == NULL)
3122260684Skaiw		return (0);
3123260684Skaiw
3124260684Skaiw	v->size = 0;
3125260684Skaiw	v->capacity = VECTOR_DEF_CAPACITY;
3126260684Skaiw
3127260684Skaiw	if ((v->r_container = malloc(sizeof(enum read_cmd) * v->capacity))
3128260684Skaiw	    == NULL)
3129260684Skaiw		return (0);
3130260684Skaiw
3131260684Skaiw	return (1);
3132260684Skaiw}
3133260684Skaiw
3134260684Skaiwstatic int
3135260684Skaiwvector_read_cmd_pop(struct vector_read_cmd *v)
3136260684Skaiw{
3137260684Skaiw
3138260684Skaiw	if (v == NULL || v->size == 0)
3139260684Skaiw		return (0);
3140260684Skaiw
3141260684Skaiw	--v->size;
3142260684Skaiw	v->r_container[v->size] = READ_FAIL;
3143260684Skaiw
3144260684Skaiw	return (1);
3145260684Skaiw}
3146260684Skaiw
3147260684Skaiwstatic int
3148260684Skaiwvector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd)
3149260684Skaiw{
3150260684Skaiw	enum read_cmd *tmp_r_ctn;
3151260684Skaiw	size_t tmp_cap;
3152260684Skaiw	size_t i;
3153260684Skaiw
3154260684Skaiw	if (v == NULL)
3155260684Skaiw		return (0);
3156260684Skaiw
3157260684Skaiw	if (v->size == v->capacity) {
3158260684Skaiw		tmp_cap = v->capacity * BUFFER_GROWFACTOR;
3159260684Skaiw		if ((tmp_r_ctn = malloc(sizeof(enum read_cmd) * tmp_cap))
3160260684Skaiw		    == NULL)
3161260684Skaiw			return (0);
3162260684Skaiw		for (i = 0; i < v->size; ++i)
3163260684Skaiw			tmp_r_ctn[i] = v->r_container[i];
3164260684Skaiw		free(v->r_container);
3165260684Skaiw		v->r_container = tmp_r_ctn;
3166260684Skaiw		v->capacity = tmp_cap;
3167260684Skaiw	}
3168260684Skaiw
3169260684Skaiw	v->r_container[v->size] = cmd;
3170260684Skaiw	++v->size;
3171260684Skaiw
3172260684Skaiw	return (1);
3173260684Skaiw}
3174260684Skaiw
3175260684Skaiwstatic void
3176260684Skaiwvector_type_qualifier_dest(struct vector_type_qualifier *v)
3177260684Skaiw{
3178260684Skaiw
3179260684Skaiw	if (v == NULL)
3180260684Skaiw		return;
3181260684Skaiw
3182260684Skaiw	free(v->q_container);
3183260684Skaiw	vector_str_dest(&v->ext_name);
3184260684Skaiw}
3185260684Skaiw
3186260684Skaiw/* size, capacity, ext_name */
3187260684Skaiwstatic int
3188260684Skaiwvector_type_qualifier_init(struct vector_type_qualifier *v)
3189260684Skaiw{
3190260684Skaiw
3191260684Skaiw	if (v == NULL)
3192260684Skaiw		return (0);
3193260684Skaiw
3194260684Skaiw	v->size = 0;
3195260684Skaiw	v->capacity = VECTOR_DEF_CAPACITY;
3196260684Skaiw
3197260684Skaiw	if ((v->q_container = malloc(sizeof(enum type_qualifier) * v->capacity))
3198260684Skaiw	    == NULL)
3199260684Skaiw		return (0);
3200260684Skaiw
3201260684Skaiw	assert(v->q_container != NULL);
3202260684Skaiw
3203260684Skaiw	if (vector_str_init(&v->ext_name) == false) {
3204260684Skaiw		free(v->q_container);
3205260684Skaiw		return (0);
3206260684Skaiw	}
3207260684Skaiw
3208260684Skaiw	return (1);
3209260684Skaiw}
3210260684Skaiw
3211260684Skaiwstatic int
3212260684Skaiwvector_type_qualifier_push(struct vector_type_qualifier *v,
3213260684Skaiw    enum type_qualifier t)
3214260684Skaiw{
3215260684Skaiw	enum type_qualifier *tmp_ctn;
3216260684Skaiw	size_t tmp_cap;
3217260684Skaiw	size_t i;
3218260684Skaiw
3219260684Skaiw	if (v == NULL)
3220260684Skaiw		return (0);
3221260684Skaiw
3222260684Skaiw	if (v->size == v->capacity) {
3223260684Skaiw		tmp_cap = v->capacity * BUFFER_GROWFACTOR;
3224260684Skaiw		if ((tmp_ctn = malloc(sizeof(enum type_qualifier) * tmp_cap))
3225260684Skaiw		    == NULL)
3226260684Skaiw			return (0);
3227260684Skaiw		for (i = 0; i < v->size; ++i)
3228260684Skaiw			tmp_ctn[i] = v->q_container[i];
3229260684Skaiw		free(v->q_container);
3230260684Skaiw		v->q_container = tmp_ctn;
3231260684Skaiw		v->capacity = tmp_cap;
3232260684Skaiw	}
3233260684Skaiw
3234260684Skaiw	v->q_container[v->size] = t;
3235260684Skaiw	++v->size;
3236260684Skaiw
3237260684Skaiw	return (1);
3238260684Skaiw}
3239