1227825Stheraven/*-
2227825Stheraven * Copyright (c) 2007, 2008 Hyogeol Lee <hyogeollee@gmail.com>
3227825Stheraven * All rights reserved.
4227825Stheraven *
5227825Stheraven * Redistribution and use in source and binary forms, with or without
6227825Stheraven * modification, are permitted provided that the following conditions
7227825Stheraven * are met:
8227825Stheraven * 1. Redistributions of source code must retain the above copyright
9227825Stheraven *    notice, this list of conditions and the following disclaimer
10227825Stheraven *    in this position and unchanged.
11227825Stheraven * 2. Redistributions in binary form must reproduce the above copyright
12227825Stheraven *    notice, this list of conditions and the following disclaimer in the
13227825Stheraven *    documentation and/or other materials provided with the distribution.
14227825Stheraven *
15227825Stheraven * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16227825Stheraven * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17227825Stheraven * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18227825Stheraven * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19227825Stheraven * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20227825Stheraven * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21227825Stheraven * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22227825Stheraven * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23227825Stheraven * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24227825Stheraven * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25227825Stheraven */
26227825Stheraven#include <sys/types.h>
27227825Stheraven#include <assert.h>
28227825Stheraven#include <ctype.h>
29227825Stheraven#include <errno.h>
30227825Stheraven#include <limits.h>
31227825Stheraven#include <stdbool.h>
32227825Stheraven#include <stdio.h>
33227825Stheraven#include <stdlib.h>
34227825Stheraven#include <string.h>
35227825Stheraven
36227825Stheraven/**
37227825Stheraven * @file cpp_demangle.c
38227825Stheraven * @brief Decode IA-64 C++ ABI style implementation.
39227825Stheraven *
40227825Stheraven * IA-64 standard ABI(Itanium C++ ABI) references.
41227825Stheraven *
42227825Stheraven * http://www.codesourcery.com/cxx-abi/abi.html#mangling \n
43227825Stheraven * http://www.codesourcery.com/cxx-abi/abi-mangling.html
44227825Stheraven */
45227825Stheraven
46227825Stheraven/** @brief Dynamic vector data for string. */
47227825Stheravenstruct vector_str {
48227825Stheraven	/** Current size */
49227825Stheraven	size_t		size;
50227825Stheraven	/** Total capacity */
51227825Stheraven	size_t		capacity;
52227825Stheraven	/** String array */
53227825Stheraven	char		**container;
54227825Stheraven};
55227825Stheraven
56227825Stheraven#define BUFFER_GROWFACTOR	1.618
57227825Stheraven#define VECTOR_DEF_CAPACITY	8
58227825Stheraven#define	ELFTC_ISDIGIT(C) 	(isdigit((C) & 0xFF))
59227825Stheraven
60227825Stheravenenum type_qualifier {
61227825Stheraven	TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
62227825Stheraven	TYPE_CST
63227825Stheraven};
64227825Stheraven
65227825Stheravenstruct vector_type_qualifier {
66227825Stheraven	size_t size, capacity;
67227825Stheraven	enum type_qualifier *q_container;
68227825Stheraven	struct vector_str ext_name;
69227825Stheraven};
70227825Stheraven
71227825Stheravenenum read_cmd {
72227825Stheraven	READ_FAIL, READ_NEST, READ_TMPL, READ_EXPR, READ_EXPL, READ_LOCAL,
73227825Stheraven	READ_TYPE, READ_FUNC, READ_PTRMEM
74227825Stheraven};
75227825Stheraven
76227825Stheravenstruct vector_read_cmd {
77227825Stheraven	size_t size, capacity;
78227825Stheraven	enum read_cmd *r_container;
79227825Stheraven};
80227825Stheraven
81227825Stheravenstruct cpp_demangle_data {
82227825Stheraven	struct vector_str	 output;	/* output string vector */
83227825Stheraven	struct vector_str	 output_tmp;
84227825Stheraven	struct vector_str	 subst;		/* substitution string vector */
85227825Stheraven	struct vector_str	 tmpl;
86227825Stheraven	struct vector_str	 class_type;
87227825Stheraven	struct vector_read_cmd	 cmd;
88227825Stheraven	bool			 paren;		/* parenthesis opened */
89227825Stheraven	bool			 pfirst;	/* first element of parameter */
90227825Stheraven	bool			 mem_rst;	/* restrict member function */
91227825Stheraven	bool			 mem_vat;	/* volatile member function */
92227825Stheraven	bool			 mem_cst;	/* const member function */
93227825Stheraven	int			 func_type;
94227825Stheraven	const char		*cur;		/* current mangled name ptr */
95227825Stheraven	const char		*last_sname;	/* last source name */
96227825Stheraven	int			 push_head;
97227825Stheraven};
98227825Stheraven
99227825Stheraven#define	CPP_DEMANGLE_TRY_LIMIT	128
100227825Stheraven#define	FLOAT_SPRINTF_TRY_LIMIT	5
101227825Stheraven#define	FLOAT_QUADRUPLE_BYTES	16
102227825Stheraven#define	FLOAT_EXTENED_BYTES	10
103227825Stheraven
104227825Stheraven#define SIMPLE_HASH(x,y)	(64 * x + y)
105227825Stheraven
106227825Stheravenstatic size_t	get_strlen_sum(const struct vector_str *v);
107227825Stheravenstatic bool	vector_str_grow(struct vector_str *v);
108227825Stheraven
109227825Stheravenstatic size_t
110227825Stheravenget_strlen_sum(const struct vector_str *v)
111227825Stheraven{
112227825Stheraven	size_t i, len = 0;
113227825Stheraven
114227825Stheraven	if (v == NULL)
115227825Stheraven		return (0);
116227825Stheraven
117227825Stheraven	assert(v->size > 0);
118227825Stheraven
119227825Stheraven	for (i = 0; i < v->size; ++i)
120227825Stheraven		len += strlen(v->container[i]);
121227825Stheraven
122227825Stheraven	return (len);
123227825Stheraven}
124227825Stheraven
125227825Stheraven/**
126227825Stheraven * @brief Deallocate resource in vector_str.
127227825Stheraven */
128227825Stheravenstatic void
129227825Stheravenvector_str_dest(struct vector_str *v)
130227825Stheraven{
131227825Stheraven	size_t i;
132227825Stheraven
133227825Stheraven	if (v == NULL)
134227825Stheraven		return;
135227825Stheraven
136227825Stheraven	for (i = 0; i < v->size; ++i)
137227825Stheraven		free(v->container[i]);
138227825Stheraven
139227825Stheraven	free(v->container);
140227825Stheraven}
141227825Stheraven
142227825Stheraven/**
143227825Stheraven * @brief Find string in vector_str.
144227825Stheraven * @param v Destination vector.
145227825Stheraven * @param o String to find.
146227825Stheraven * @param l Length of the string.
147227825Stheraven * @return -1 at failed, 0 at not found, 1 at found.
148227825Stheraven */
149227825Stheravenstatic int
150227825Stheravenvector_str_find(const struct vector_str *v, const char *o, size_t l)
151227825Stheraven{
152227825Stheraven	size_t i;
153227825Stheraven
154227825Stheraven	if (v == NULL || o == NULL)
155227825Stheraven		return (-1);
156227825Stheraven
157227825Stheraven	for (i = 0; i < v->size; ++i)
158227825Stheraven		if (strncmp(v->container[i], o, l) == 0)
159227825Stheraven			return (1);
160227825Stheraven
161227825Stheraven	return (0);
162227825Stheraven}
163227825Stheraven
164227825Stheraven/**
165227825Stheraven * @brief Get new allocated flat string from vector.
166227825Stheraven *
167227825Stheraven * If l is not NULL, return length of the string.
168227825Stheraven * @param v Destination vector.
169227825Stheraven * @param l Length of the string.
170227825Stheraven * @return NULL at failed or NUL terminated new allocated string.
171227825Stheraven */
172227825Stheravenstatic char *
173227825Stheravenvector_str_get_flat(const struct vector_str *v, size_t *l)
174227825Stheraven{
175227825Stheraven	ssize_t elem_pos, elem_size, rtn_size;
176227825Stheraven	size_t i;
177227825Stheraven	char *rtn;
178227825Stheraven
179227825Stheraven	if (v == NULL || v->size == 0)
180227825Stheraven		return (NULL);
181227825Stheraven
182227825Stheraven	if ((rtn_size = get_strlen_sum(v)) == 0)
183227825Stheraven		return (NULL);
184227825Stheraven
185227825Stheraven	if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL)
186227825Stheraven		return (NULL);
187227825Stheraven
188227825Stheraven	elem_pos = 0;
189227825Stheraven	for (i = 0; i < v->size; ++i) {
190227825Stheraven		elem_size = strlen(v->container[i]);
191227825Stheraven
192227825Stheraven		memcpy(rtn + elem_pos, v->container[i], elem_size);
193227825Stheraven
194227825Stheraven		elem_pos += elem_size;
195227825Stheraven	}
196227825Stheraven
197227825Stheraven	rtn[rtn_size] = '\0';
198227825Stheraven
199227825Stheraven	if (l != NULL)
200227825Stheraven		*l = rtn_size;
201227825Stheraven
202227825Stheraven	return (rtn);
203227825Stheraven}
204227825Stheraven
205227825Stheravenstatic bool
206227825Stheravenvector_str_grow(struct vector_str *v)
207227825Stheraven{
208227825Stheraven	size_t i, tmp_cap;
209227825Stheraven	char **tmp_ctn;
210227825Stheraven
211227825Stheraven	if (v == NULL)
212227825Stheraven		return (false);
213227825Stheraven
214227825Stheraven	assert(v->capacity > 0);
215227825Stheraven
216227825Stheraven	tmp_cap = v->capacity * BUFFER_GROWFACTOR;
217227825Stheraven
218227825Stheraven	assert(tmp_cap > v->capacity);
219227825Stheraven
220227825Stheraven	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
221227825Stheraven		return (false);
222227825Stheraven
223227825Stheraven	for (i = 0; i < v->size; ++i)
224227825Stheraven		tmp_ctn[i] = v->container[i];
225227825Stheraven
226227825Stheraven	free(v->container);
227227825Stheraven
228227825Stheraven	v->container = tmp_ctn;
229227825Stheraven	v->capacity = tmp_cap;
230227825Stheraven
231227825Stheraven	return (true);
232227825Stheraven}
233227825Stheraven
234227825Stheraven/**
235227825Stheraven * @brief Initialize vector_str.
236227825Stheraven * @return false at failed, true at success.
237227825Stheraven */
238227825Stheravenstatic bool
239227825Stheravenvector_str_init(struct vector_str *v)
240227825Stheraven{
241227825Stheraven
242227825Stheraven	if (v == NULL)
243227825Stheraven		return (false);
244227825Stheraven
245227825Stheraven	v->size = 0;
246227825Stheraven	v->capacity = VECTOR_DEF_CAPACITY;
247227825Stheraven
248227825Stheraven	assert(v->capacity > 0);
249227825Stheraven
250227825Stheraven	if ((v->container = malloc(sizeof(char *) * v->capacity)) == NULL)
251227825Stheraven		return (false);
252227825Stheraven
253227825Stheraven	assert(v->container != NULL);
254227825Stheraven
255227825Stheraven	return (true);
256227825Stheraven}
257227825Stheraven
258227825Stheraven/**
259227825Stheraven * @brief Remove last element in vector_str.
260227825Stheraven * @return false at failed, true at success.
261227825Stheraven */
262227825Stheravenstatic bool
263227825Stheravenvector_str_pop(struct vector_str *v)
264227825Stheraven{
265227825Stheraven
266227825Stheraven	if (v == NULL)
267227825Stheraven		return (false);
268227825Stheraven
269227825Stheraven	if (v->size == 0)
270227825Stheraven		return (true);
271227825Stheraven
272227825Stheraven	--v->size;
273227825Stheraven
274227825Stheraven	free(v->container[v->size]);
275227825Stheraven	v->container[v->size] = NULL;
276227825Stheraven
277227825Stheraven	return (true);
278227825Stheraven}
279227825Stheraven
280227825Stheraven/**
281227825Stheraven * @brief Push back string to vector.
282227825Stheraven * @return false at failed, true at success.
283227825Stheraven */
284227825Stheravenstatic bool
285227825Stheravenvector_str_push(struct vector_str *v, const char *str, size_t len)
286227825Stheraven{
287227825Stheraven
288227825Stheraven	if (v == NULL || str == NULL)
289227825Stheraven		return (false);
290227825Stheraven
291227825Stheraven	if (v->size == v->capacity && vector_str_grow(v) == false)
292227825Stheraven		return (false);
293227825Stheraven
294227825Stheraven	if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL)
295227825Stheraven		return (false);
296227825Stheraven
297227825Stheraven	snprintf(v->container[v->size], len + 1, "%s", str);
298227825Stheraven
299227825Stheraven	++v->size;
300227825Stheraven
301227825Stheraven	return (true);
302227825Stheraven}
303227825Stheraven
304227825Stheraven/**
305227825Stheraven * @brief Push front org vector to det vector.
306227825Stheraven * @return false at failed, true at success.
307227825Stheraven */
308227825Stheravenstatic bool
309227825Stheravenvector_str_push_vector_head(struct vector_str *dst, struct vector_str *org)
310227825Stheraven{
311227825Stheraven	size_t i, j, tmp_cap;
312227825Stheraven	char **tmp_ctn;
313227825Stheraven
314227825Stheraven	if (dst == NULL || org == NULL)
315227825Stheraven		return (false);
316227825Stheraven
317227825Stheraven	tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR;
318227825Stheraven
319227825Stheraven	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
320227825Stheraven		return (false);
321227825Stheraven
322227825Stheraven	for (i = 0; i < org->size; ++i)
323227825Stheraven		if ((tmp_ctn[i] = strdup(org->container[i])) == NULL) {
324227825Stheraven			for (j = 0; j < i; ++j)
325227825Stheraven				free(tmp_ctn[j]);
326227825Stheraven
327227825Stheraven			free(tmp_ctn);
328227825Stheraven
329227825Stheraven			return (false);
330227825Stheraven		}
331227825Stheraven
332227825Stheraven	for (i = 0; i < dst->size; ++i)
333227825Stheraven		tmp_ctn[i + org->size] = dst->container[i];
334227825Stheraven
335227825Stheraven	free(dst->container);
336227825Stheraven
337227825Stheraven	dst->container = tmp_ctn;
338227825Stheraven	dst->capacity = tmp_cap;
339227825Stheraven	dst->size += org->size;
340227825Stheraven
341227825Stheraven	return (true);
342227825Stheraven}
343227825Stheraven
344227825Stheraven/**
345227825Stheraven * @brief Get new allocated flat string from vector between begin and end.
346227825Stheraven *
347227825Stheraven * If r_len is not NULL, string length will be returned.
348227825Stheraven * @return NULL at failed or NUL terminated new allocated string.
349227825Stheraven */
350227825Stheravenstatic char *
351227825Stheravenvector_str_substr(const struct vector_str *v, size_t begin, size_t end,
352227825Stheraven    size_t *r_len)
353227825Stheraven{
354227825Stheraven	size_t cur, i, len;
355227825Stheraven	char *rtn;
356227825Stheraven
357227825Stheraven	if (v == NULL || begin > end)
358227825Stheraven		return (NULL);
359227825Stheraven
360227825Stheraven	len = 0;
361227825Stheraven	for (i = begin; i < end + 1; ++i)
362227825Stheraven		len += strlen(v->container[i]);
363227825Stheraven
364227825Stheraven	if ((rtn = malloc(sizeof(char) * (len + 1))) == NULL)
365227825Stheraven		return (NULL);
366227825Stheraven
367227825Stheraven	if (r_len != NULL)
368227825Stheraven		*r_len = len;
369227825Stheraven
370227825Stheraven	cur = 0;
371227825Stheraven	for (i = begin; i < end + 1; ++i) {
372227825Stheraven		len = strlen(v->container[i]);
373227825Stheraven		memcpy(rtn + cur, v->container[i], len);
374227825Stheraven		cur += len;
375227825Stheraven	}
376227825Stheraven	rtn[cur] = '\0';
377227825Stheraven
378227825Stheraven	return (rtn);
379227825Stheraven}
380227825Stheraven
381227825Stheravenstatic void	cpp_demangle_data_dest(struct cpp_demangle_data *);
382227825Stheravenstatic int	cpp_demangle_data_init(struct cpp_demangle_data *,
383227825Stheraven		    const char *);
384227825Stheravenstatic int	cpp_demangle_get_subst(struct cpp_demangle_data *, size_t);
385227825Stheravenstatic int	cpp_demangle_get_tmpl_param(struct cpp_demangle_data *, size_t);
386227825Stheravenstatic int	cpp_demangle_push_fp(struct cpp_demangle_data *,
387227825Stheraven		    char *(*)(const char *, size_t));
388227825Stheravenstatic int	cpp_demangle_push_str(struct cpp_demangle_data *, const char *,
389227825Stheraven		    size_t);
390227825Stheravenstatic int	cpp_demangle_push_subst(struct cpp_demangle_data *,
391227825Stheraven		    const char *, size_t);
392227825Stheravenstatic int	cpp_demangle_push_subst_v(struct cpp_demangle_data *,
393227825Stheraven		    struct vector_str *);
394227825Stheravenstatic int	cpp_demangle_push_type_qualifier(struct cpp_demangle_data *,
395227825Stheraven		    struct vector_type_qualifier *, const char *);
396227825Stheravenstatic int	cpp_demangle_read_array(struct cpp_demangle_data *);
397227825Stheravenstatic int	cpp_demangle_read_encoding(struct cpp_demangle_data *);
398227825Stheravenstatic int	cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
399227825Stheravenstatic int	cpp_demangle_read_expression(struct cpp_demangle_data *);
400227825Stheravenstatic int	cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
401227825Stheraven		    const char *, size_t);
402227825Stheravenstatic int	cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
403227825Stheraven		    const char *, size_t);
404227825Stheravenstatic int	cpp_demangle_read_expression_trinary(struct cpp_demangle_data *,
405227825Stheraven		    const char *, size_t, const char *, size_t);
406227825Stheravenstatic int	cpp_demangle_read_function(struct cpp_demangle_data *, int *,
407227825Stheraven		    struct vector_type_qualifier *);
408255815Stheravenstatic int	cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
409227825Stheravenstatic int	cpp_demangle_read_local_name(struct cpp_demangle_data *);
410227825Stheravenstatic int	cpp_demangle_read_name(struct cpp_demangle_data *);
411227825Stheravenstatic int	cpp_demangle_read_nested_name(struct cpp_demangle_data *);
412227825Stheravenstatic int	cpp_demangle_read_number(struct cpp_demangle_data *, long *);
413227825Stheravenstatic int	cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
414227825Stheravenstatic int	cpp_demangle_read_offset(struct cpp_demangle_data *);
415227825Stheravenstatic int	cpp_demangle_read_offset_number(struct cpp_demangle_data *);
416227825Stheravenstatic int	cpp_demangle_read_pointer_to_member(struct cpp_demangle_data *);
417227825Stheravenstatic int	cpp_demangle_read_sname(struct cpp_demangle_data *);
418227825Stheravenstatic int	cpp_demangle_read_subst(struct cpp_demangle_data *);
419227825Stheravenstatic int	cpp_demangle_read_subst_std(struct cpp_demangle_data *);
420227825Stheravenstatic int	cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *,
421227825Stheraven		    const char *, size_t);
422227825Stheravenstatic int	cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
423227825Stheravenstatic int	cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
424227825Stheravenstatic int	cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
425227825Stheravenstatic int	cpp_demangle_read_type(struct cpp_demangle_data *, int);
426227825Stheravenstatic int	cpp_demangle_read_uqname(struct cpp_demangle_data *);
427227825Stheravenstatic int	cpp_demangle_read_v_offset(struct cpp_demangle_data *);
428227825Stheravenstatic char	*decode_fp_to_double(const char *, size_t);
429227825Stheravenstatic char	*decode_fp_to_float(const char *, size_t);
430227825Stheravenstatic char	*decode_fp_to_float128(const char *, size_t);
431227825Stheravenstatic char	*decode_fp_to_float80(const char *, size_t);
432227825Stheravenstatic char	*decode_fp_to_long_double(const char *, size_t);
433227825Stheravenstatic int	hex_to_dec(char);
434227825Stheravenstatic void	vector_read_cmd_dest(struct vector_read_cmd *);
435227825Stheravenstatic int	vector_read_cmd_find(struct vector_read_cmd *, enum read_cmd);
436227825Stheravenstatic int	vector_read_cmd_init(struct vector_read_cmd *);
437227825Stheravenstatic int	vector_read_cmd_pop(struct vector_read_cmd *);
438227825Stheravenstatic int	vector_read_cmd_push(struct vector_read_cmd *, enum read_cmd);
439227825Stheravenstatic void	vector_type_qualifier_dest(struct vector_type_qualifier *);
440227825Stheravenstatic int	vector_type_qualifier_init(struct vector_type_qualifier *);
441227825Stheravenstatic int	vector_type_qualifier_push(struct vector_type_qualifier *,
442227825Stheraven		    enum type_qualifier);
443227825Stheraven
444227825Stheraven/**
445227825Stheraven * @brief Decode the input string by IA-64 C++ ABI style.
446227825Stheraven *
447227825Stheraven * GNU GCC v3 use IA-64 standard ABI.
448227825Stheraven * @return New allocated demangled string or NULL if failed.
449227825Stheraven * @todo 1. Testing and more test case. 2. Code cleaning.
450227825Stheraven */
451227825Stheravenchar *
452227825Stheraven__cxa_demangle_gnu3(const char *org)
453227825Stheraven{
454227825Stheraven	struct cpp_demangle_data ddata;
455227825Stheraven	ssize_t org_len;
456227825Stheraven	unsigned int limit;
457255815Stheraven	char *rtn = NULL;
458227825Stheraven
459227825Stheraven	if (org == NULL)
460227825Stheraven		return (NULL);
461227825Stheraven
462255815Stheraven	org_len = strlen(org);
463255815Stheraven	if (org_len > 11 && !strncmp(org, "_GLOBAL__I_", 11)) {
464255815Stheraven		if ((rtn = malloc(org_len + 19)) == NULL)
465255815Stheraven			return (NULL);
466255815Stheraven		snprintf(rtn, org_len + 19,
467255815Stheraven		    "global constructors keyed to %s", org + 11);
468255815Stheraven		return (rtn);
469255815Stheraven	}
470255815Stheraven
471227825Stheraven	// Try demangling as a type for short encodings
472255815Stheraven	if ((org_len < 2) || (org[0] != '_' || org[1] != 'Z' )) {
473227825Stheraven		if (!cpp_demangle_data_init(&ddata, org))
474227825Stheraven			return (NULL);
475227825Stheraven		if (!cpp_demangle_read_type(&ddata, 0))
476227825Stheraven			goto clean;
477227825Stheraven		rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
478227825Stheraven		goto clean;
479227825Stheraven	}
480227825Stheraven
481227825Stheraven
482227825Stheraven	if (!cpp_demangle_data_init(&ddata, org + 2))
483227825Stheraven		return (NULL);
484227825Stheraven
485227825Stheraven	rtn = NULL;
486227825Stheraven
487227825Stheraven	if (!cpp_demangle_read_encoding(&ddata))
488227825Stheraven		goto clean;
489227825Stheraven
490227825Stheraven	limit = 0;
491227825Stheraven	while (*ddata.cur != '\0') {
492227825Stheraven		/*
493227825Stheraven		 * Breaking at some gcc info at tail. e.g) @@GLIBCXX_3.4
494227825Stheraven		 */
495227825Stheraven		if (*ddata.cur == '@' && *(ddata.cur + 1) == '@')
496227825Stheraven			break;
497227825Stheraven		if (!cpp_demangle_read_type(&ddata, 1))
498227825Stheraven			goto clean;
499227825Stheraven		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
500227825Stheraven			goto clean;
501227825Stheraven	}
502227825Stheraven
503227825Stheraven	if (ddata.output.size == 0)
504227825Stheraven		goto clean;
505227825Stheraven	if (ddata.paren && !vector_str_push(&ddata.output, ")", 1))
506227825Stheraven		goto clean;
507227825Stheraven	if (ddata.mem_vat && !vector_str_push(&ddata.output, " volatile", 9))
508227825Stheraven		goto clean;
509227825Stheraven	if (ddata.mem_cst && !vector_str_push(&ddata.output, " const", 6))
510227825Stheraven		goto clean;
511227825Stheraven	if (ddata.mem_rst && !vector_str_push(&ddata.output, " restrict", 9))
512227825Stheraven		goto clean;
513227825Stheraven
514227825Stheraven	rtn = vector_str_get_flat(&ddata.output, (size_t *) NULL);
515227825Stheraven
516227825Stheravenclean:
517227825Stheraven	cpp_demangle_data_dest(&ddata);
518227825Stheraven
519227825Stheraven	return (rtn);
520227825Stheraven}
521227825Stheraven
522227825Stheravenstatic void
523227825Stheravencpp_demangle_data_dest(struct cpp_demangle_data *d)
524227825Stheraven{
525227825Stheraven
526227825Stheraven	if (d == NULL)
527227825Stheraven		return;
528227825Stheraven
529227825Stheraven	vector_read_cmd_dest(&d->cmd);
530227825Stheraven	vector_str_dest(&d->class_type);
531227825Stheraven	vector_str_dest(&d->tmpl);
532227825Stheraven	vector_str_dest(&d->subst);
533227825Stheraven	vector_str_dest(&d->output_tmp);
534227825Stheraven	vector_str_dest(&d->output);
535227825Stheraven}
536227825Stheraven
537227825Stheravenstatic int
538227825Stheravencpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
539227825Stheraven{
540227825Stheraven
541227825Stheraven	if (d == NULL || cur == NULL)
542227825Stheraven		return (0);
543227825Stheraven
544227825Stheraven	if (!vector_str_init(&d->output))
545227825Stheraven		return (0);
546227825Stheraven	if (!vector_str_init(&d->output_tmp))
547227825Stheraven		goto clean1;
548227825Stheraven	if (!vector_str_init(&d->subst))
549227825Stheraven		goto clean2;
550227825Stheraven	if (!vector_str_init(&d->tmpl))
551227825Stheraven		goto clean3;
552227825Stheraven	if (!vector_str_init(&d->class_type))
553227825Stheraven		goto clean4;
554227825Stheraven	if (!vector_read_cmd_init(&d->cmd))
555227825Stheraven		goto clean5;
556227825Stheraven
557227825Stheraven	assert(d->output.container != NULL);
558227825Stheraven	assert(d->output_tmp.container != NULL);
559227825Stheraven	assert(d->subst.container != NULL);
560227825Stheraven	assert(d->tmpl.container != NULL);
561227825Stheraven	assert(d->class_type.container != NULL);
562227825Stheraven
563227825Stheraven	d->paren = false;
564227825Stheraven	d->pfirst = false;
565227825Stheraven	d->mem_rst = false;
566227825Stheraven	d->mem_vat = false;
567227825Stheraven	d->mem_cst = false;
568227825Stheraven	d->func_type = 0;
569227825Stheraven	d->cur = cur;
570227825Stheraven	d->last_sname = NULL;
571227825Stheraven	d->push_head = 0;
572227825Stheraven
573227825Stheraven	return (1);
574227825Stheraven
575227825Stheravenclean5:
576227825Stheraven	vector_str_dest(&d->class_type);
577227825Stheravenclean4:
578227825Stheraven	vector_str_dest(&d->tmpl);
579227825Stheravenclean3:
580227825Stheraven	vector_str_dest(&d->subst);
581227825Stheravenclean2:
582227825Stheraven	vector_str_dest(&d->output_tmp);
583227825Stheravenclean1:
584227825Stheraven	vector_str_dest(&d->output);
585227825Stheraven
586227825Stheraven	return (0);
587227825Stheraven}
588227825Stheraven
589227825Stheravenstatic int
590227825Stheravencpp_demangle_push_fp(struct cpp_demangle_data *ddata,
591227825Stheraven    char *(*decoder)(const char *, size_t))
592227825Stheraven{
593227825Stheraven	size_t len;
594227825Stheraven	int rtn;
595227825Stheraven	const char *fp;
596227825Stheraven	char *f;
597227825Stheraven
598227825Stheraven	if (ddata == NULL || decoder == NULL)
599227825Stheraven		return (0);
600227825Stheraven
601227825Stheraven	fp = ddata->cur;
602227825Stheraven	while (*ddata->cur != 'E')
603227825Stheraven		++ddata->cur;
604227825Stheraven	++ddata->cur;
605227825Stheraven
606227825Stheraven	if ((f = decoder(fp, ddata->cur - fp)) == NULL)
607227825Stheraven		return (0);
608227825Stheraven
609227825Stheraven	rtn = 0;
610255815Stheraven	if ((len = strlen(f)) > 0)
611255815Stheraven		rtn = cpp_demangle_push_str(ddata, f, len);
612227825Stheraven
613227825Stheraven	free(f);
614227825Stheraven
615255815Stheraven	return (rtn);
616227825Stheraven}
617227825Stheraven
618227825Stheravenstatic int
619227825Stheravencpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
620227825Stheraven    size_t len)
621227825Stheraven{
622227825Stheraven
623227825Stheraven	if (ddata == NULL || str == NULL || len == 0)
624227825Stheraven		return (0);
625227825Stheraven
626227825Stheraven	if (ddata->push_head > 0)
627227825Stheraven		return (vector_str_push(&ddata->output_tmp, str, len));
628227825Stheraven
629227825Stheraven	return (vector_str_push(&ddata->output, str, len));
630227825Stheraven}
631227825Stheraven
632227825Stheravenstatic int
633227825Stheravencpp_demangle_push_subst(struct cpp_demangle_data *ddata, const char *str,
634227825Stheraven    size_t len)
635227825Stheraven{
636227825Stheraven
637227825Stheraven	if (ddata == NULL || str == NULL || len == 0)
638227825Stheraven		return (0);
639227825Stheraven
640227825Stheraven	if (!vector_str_find(&ddata->subst, str, len))
641227825Stheraven		return (vector_str_push(&ddata->subst, str, len));
642227825Stheraven
643227825Stheraven	return (1);
644227825Stheraven}
645227825Stheraven
646227825Stheravenstatic int
647227825Stheravencpp_demangle_push_subst_v(struct cpp_demangle_data *ddata, struct vector_str *v)
648227825Stheraven{
649227825Stheraven	size_t str_len;
650227825Stheraven	int rtn;
651227825Stheraven	char *str;
652227825Stheraven
653227825Stheraven	if (ddata == NULL || v == NULL)
654227825Stheraven		return (0);
655227825Stheraven
656227825Stheraven	if ((str = vector_str_get_flat(v, &str_len)) == NULL)
657227825Stheraven		return (0);
658227825Stheraven
659227825Stheraven	rtn = cpp_demangle_push_subst(ddata, str, str_len);
660255815Stheraven
661227825Stheraven	free(str);
662227825Stheraven
663227825Stheraven	return (rtn);
664227825Stheraven}
665227825Stheraven
666227825Stheravenstatic int
667227825Stheravencpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
668227825Stheraven    struct vector_type_qualifier *v, const char *type_str)
669227825Stheraven{
670227825Stheraven	struct vector_str subst_v;
671227825Stheraven	size_t idx, e_idx, e_len;
672227825Stheraven	int rtn;
673227825Stheraven	char *buf;
674227825Stheraven
675227825Stheraven	if (ddata == NULL || v == NULL)
676227825Stheraven		return (0);
677227825Stheraven
678227825Stheraven	if ((idx = v->size) == 0)
679227825Stheraven		return (1);
680227825Stheraven
681227825Stheraven	rtn = 0;
682227825Stheraven	if (type_str != NULL) {
683227825Stheraven		if (!vector_str_init(&subst_v))
684227825Stheraven			return (0);
685227825Stheraven		if (!vector_str_push(&subst_v, type_str, strlen(type_str)))
686227825Stheraven			goto clean;
687227825Stheraven	}
688227825Stheraven
689227825Stheraven	e_idx = 0;
690227825Stheraven	while (idx > 0) {
691227825Stheraven		switch (v->q_container[idx - 1]) {
692227825Stheraven		case TYPE_PTR:
693227825Stheraven			if (!cpp_demangle_push_str(ddata, "*", 1))
694227825Stheraven				goto clean;
695227825Stheraven			if (type_str != NULL) {
696227825Stheraven				if (!vector_str_push(&subst_v, "*", 1))
697227825Stheraven					goto clean;
698227825Stheraven				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
699227825Stheraven					goto clean;
700227825Stheraven			}
701227825Stheraven			break;
702227825Stheraven
703227825Stheraven		case TYPE_REF:
704227825Stheraven			if (!cpp_demangle_push_str(ddata, "&", 1))
705227825Stheraven				goto clean;
706227825Stheraven			if (type_str != NULL) {
707227825Stheraven				if (!vector_str_push(&subst_v, "&", 1))
708227825Stheraven					goto clean;
709227825Stheraven				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
710227825Stheraven					goto clean;
711227825Stheraven			}
712227825Stheraven			break;
713227825Stheraven
714227825Stheraven		case TYPE_CMX:
715227825Stheraven			if (!cpp_demangle_push_str(ddata, " complex", 8))
716227825Stheraven				goto clean;
717227825Stheraven			if (type_str != NULL) {
718227825Stheraven				if (!vector_str_push(&subst_v, " complex", 8))
719227825Stheraven					goto clean;
720227825Stheraven				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
721227825Stheraven					goto clean;
722227825Stheraven			}
723227825Stheraven			break;
724227825Stheraven
725227825Stheraven		case TYPE_IMG:
726227825Stheraven			if (!cpp_demangle_push_str(ddata, " imaginary", 10))
727227825Stheraven				goto clean;
728227825Stheraven			if (type_str != NULL) {
729227825Stheraven				if (!vector_str_push(&subst_v, " imaginary", 10))
730227825Stheraven					goto clean;
731227825Stheraven				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
732227825Stheraven					goto clean;
733227825Stheraven			}
734227825Stheraven			break;
735227825Stheraven
736227825Stheraven		case TYPE_EXT:
737227825Stheraven			if (e_idx > v->ext_name.size - 1)
738227825Stheraven				goto clean;
739227825Stheraven			if ((e_len = strlen(v->ext_name.container[e_idx])) == 0)
740227825Stheraven				goto clean;
741227825Stheraven			if ((buf = malloc(sizeof(char) * (e_len + 1))) == NULL)
742227825Stheraven				goto clean;
743227825Stheraven
744227825Stheraven			memcpy(buf, " ", 1);
745227825Stheraven			memcpy(buf + 1, v->ext_name.container[e_idx], e_len);
746227825Stheraven
747227825Stheraven			if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) {
748227825Stheraven				free(buf);
749227825Stheraven				goto clean;
750227825Stheraven			}
751227825Stheraven
752227825Stheraven			if (type_str != NULL) {
753227825Stheraven				if (!vector_str_push(&subst_v, buf,
754227825Stheraven				    e_len + 1)) {
755227825Stheraven					free(buf);
756227825Stheraven					goto clean;
757227825Stheraven				}
758227825Stheraven				if (!cpp_demangle_push_subst_v(ddata, &subst_v)) {
759227825Stheraven					free(buf);
760227825Stheraven					goto clean;
761227825Stheraven				}
762227825Stheraven			}
763227825Stheraven			free(buf);
764227825Stheraven			++e_idx;
765227825Stheraven			break;
766227825Stheraven
767227825Stheraven		case TYPE_RST:
768227825Stheraven			if (!cpp_demangle_push_str(ddata, " restrict", 9))
769227825Stheraven				goto clean;
770227825Stheraven			if (type_str != NULL) {
771227825Stheraven				if (!vector_str_push(&subst_v, " restrict", 9))
772227825Stheraven					goto clean;
773227825Stheraven				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
774227825Stheraven					goto clean;
775227825Stheraven			}
776227825Stheraven			break;
777227825Stheraven
778227825Stheraven		case TYPE_VAT:
779227825Stheraven			if (!cpp_demangle_push_str(ddata, " volatile", 9))
780227825Stheraven				goto clean;
781227825Stheraven			if (type_str != NULL) {
782227825Stheraven				if (!vector_str_push(&subst_v, " volatile", 9))
783227825Stheraven					goto clean;
784227825Stheraven				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
785227825Stheraven					goto clean;
786227825Stheraven			}
787227825Stheraven			break;
788227825Stheraven
789227825Stheraven		case TYPE_CST:
790227825Stheraven			if (!cpp_demangle_push_str(ddata, " const", 6))
791227825Stheraven				goto clean;
792227825Stheraven			if (type_str != NULL) {
793227825Stheraven				if (!vector_str_push(&subst_v, " const", 6))
794227825Stheraven					goto clean;
795227825Stheraven				if (!cpp_demangle_push_subst_v(ddata, &subst_v))
796227825Stheraven					goto clean;
797227825Stheraven			}
798227825Stheraven			break;
799227825Stheraven
800227825Stheraven		};
801227825Stheraven		--idx;
802227825Stheraven	}
803227825Stheraven
804227825Stheraven	rtn = 1;
805227825Stheravenclean:
806227825Stheraven	if (type_str != NULL)
807227825Stheraven		vector_str_dest(&subst_v);
808227825Stheraven
809227825Stheraven	return (rtn);
810227825Stheraven}
811227825Stheraven
812227825Stheravenstatic int
813227825Stheravencpp_demangle_get_subst(struct cpp_demangle_data *ddata, size_t idx)
814227825Stheraven{
815227825Stheraven	size_t len;
816227825Stheraven
817227825Stheraven	if (ddata == NULL || ddata->subst.size <= idx)
818227825Stheraven		return (0);
819227825Stheraven	if ((len = strlen(ddata->subst.container[idx])) == 0)
820227825Stheraven		return (0);
821227825Stheraven	if (!cpp_demangle_push_str(ddata, ddata->subst.container[idx], len))
822227825Stheraven		return (0);
823227825Stheraven
824227825Stheraven	/* skip '_' */
825227825Stheraven	++ddata->cur;
826227825Stheraven
827227825Stheraven	return (1);
828227825Stheraven}
829227825Stheraven
830227825Stheravenstatic int
831227825Stheravencpp_demangle_get_tmpl_param(struct cpp_demangle_data *ddata, size_t idx)
832227825Stheraven{
833227825Stheraven	size_t len;
834227825Stheraven
835227825Stheraven	if (ddata == NULL || ddata->tmpl.size <= idx)
836227825Stheraven		return (0);
837227825Stheraven	if ((len = strlen(ddata->tmpl.container[idx])) == 0)
838227825Stheraven		return (0);
839227825Stheraven	if (!cpp_demangle_push_str(ddata, ddata->tmpl.container[idx], len))
840227825Stheraven		return (0);
841227825Stheraven
842227825Stheraven	++ddata->cur;
843227825Stheraven
844227825Stheraven	return (1);
845227825Stheraven}
846227825Stheraven
847227825Stheravenstatic int
848227825Stheravencpp_demangle_read_array(struct cpp_demangle_data *ddata)
849227825Stheraven{
850227825Stheraven	size_t i, num_len, exp_len, p_idx, idx;
851227825Stheraven	const char *num;
852227825Stheraven	char *exp;
853227825Stheraven
854227825Stheraven	if (ddata == NULL || *(++ddata->cur) == '\0')
855227825Stheraven		return (0);
856227825Stheraven
857227825Stheraven	if (*ddata->cur == '_') {
858227825Stheraven		if (*(++ddata->cur) == '\0')
859227825Stheraven			return (0);
860227825Stheraven
861227825Stheraven		if (!cpp_demangle_read_type(ddata, 0))
862227825Stheraven			return (0);
863227825Stheraven
864227825Stheraven		if (!cpp_demangle_push_str(ddata, "[]", 2))
865227825Stheraven			return (0);
866227825Stheraven	} else {
867227825Stheraven		if (ELFTC_ISDIGIT(*ddata->cur) != 0) {
868227825Stheraven			num = ddata->cur;
869227825Stheraven			while (ELFTC_ISDIGIT(*ddata->cur) != 0)
870227825Stheraven				++ddata->cur;
871227825Stheraven			if (*ddata->cur != '_')
872227825Stheraven				return (0);
873227825Stheraven			num_len = ddata->cur - num;
874227825Stheraven			assert(num_len > 0);
875227825Stheraven			if (*(++ddata->cur) == '\0')
876227825Stheraven				return (0);
877227825Stheraven			if (!cpp_demangle_read_type(ddata, 0))
878227825Stheraven				return (0);
879227825Stheraven			if (!cpp_demangle_push_str(ddata, "[", 1))
880227825Stheraven				return (0);
881227825Stheraven			if (!cpp_demangle_push_str(ddata, num, num_len))
882227825Stheraven				return (0);
883227825Stheraven			if (!cpp_demangle_push_str(ddata, "]", 1))
884227825Stheraven				return (0);
885227825Stheraven		} else {
886227825Stheraven			p_idx = ddata->output.size;
887227825Stheraven			if (!cpp_demangle_read_expression(ddata))
888227825Stheraven				return (0);
889227825Stheraven			if ((exp = vector_str_substr(&ddata->output, p_idx,
890227825Stheraven				 ddata->output.size - 1, &exp_len)) == NULL)
891227825Stheraven				return (0);
892227825Stheraven			idx = ddata->output.size;
893227825Stheraven			for (i = p_idx; i < idx; ++i)
894227825Stheraven				if (!vector_str_pop(&ddata->output)) {
895227825Stheraven					free(exp);
896227825Stheraven					return (0);
897227825Stheraven				}
898227825Stheraven			if (*ddata->cur != '_') {
899227825Stheraven				free(exp);
900227825Stheraven				return (0);
901227825Stheraven			}
902227825Stheraven			++ddata->cur;
903227825Stheraven			if (*ddata->cur == '\0') {
904227825Stheraven				free(exp);
905227825Stheraven				return (0);
906227825Stheraven			}
907227825Stheraven			if (!cpp_demangle_read_type(ddata, 0)) {
908227825Stheraven				free(exp);
909227825Stheraven				return (0);
910227825Stheraven			}
911227825Stheraven			if (!cpp_demangle_push_str(ddata, "[", 1)) {
912227825Stheraven				free(exp);
913227825Stheraven				return (0);
914227825Stheraven			}
915227825Stheraven			if (!cpp_demangle_push_str(ddata, exp, exp_len)) {
916227825Stheraven				free(exp);
917227825Stheraven				return (0);
918227825Stheraven			}
919227825Stheraven			if (!cpp_demangle_push_str(ddata, "]", 1)) {
920227825Stheraven				free(exp);
921227825Stheraven				return (0);
922227825Stheraven			}
923227825Stheraven			free(exp);
924227825Stheraven		}
925227825Stheraven	}
926227825Stheraven
927227825Stheraven	return (1);
928227825Stheraven}
929227825Stheraven
930227825Stheravenstatic int
931227825Stheravencpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
932227825Stheraven{
933227825Stheraven	const char *num;
934227825Stheraven
935227825Stheraven	if (ddata == NULL || *(++ddata->cur) == '\0')
936227825Stheraven		return (0);
937227825Stheraven
938227825Stheraven	if (*ddata->cur == '_' && *(ddata->cur + 1) == 'Z') {
939227825Stheraven		ddata->cur += 2;
940227825Stheraven		if (*ddata->cur == '\0')
941227825Stheraven			return (0);
942227825Stheraven		if (!cpp_demangle_read_encoding(ddata))
943227825Stheraven			return (0);
944227825Stheraven		++ddata->cur;
945227825Stheraven		return (1);
946227825Stheraven	}
947227825Stheraven
948227825Stheraven	switch (*ddata->cur) {
949227825Stheraven	case 'b':
950227825Stheraven		switch (*(++ddata->cur)) {
951227825Stheraven		case '0':
952227825Stheraven			return (cpp_demangle_push_str(ddata, "false", 5));
953227825Stheraven		case '1':
954227825Stheraven			return (cpp_demangle_push_str(ddata, "true", 4));
955227825Stheraven		default:
956227825Stheraven			return (0);
957227825Stheraven		};
958227825Stheraven
959227825Stheraven	case 'd':
960227825Stheraven		++ddata->cur;
961227825Stheraven		return (cpp_demangle_push_fp(ddata, decode_fp_to_double));
962227825Stheraven
963227825Stheraven	case 'e':
964227825Stheraven		++ddata->cur;
965227825Stheraven		if (sizeof(long double) == 10)
966227825Stheraven			return (cpp_demangle_push_fp(ddata,
967227825Stheraven			    decode_fp_to_double));
968227825Stheraven		return (cpp_demangle_push_fp(ddata, decode_fp_to_float80));
969227825Stheraven
970227825Stheraven	case 'f':
971227825Stheraven		++ddata->cur;
972227825Stheraven		return (cpp_demangle_push_fp(ddata, decode_fp_to_float));
973227825Stheraven
974227825Stheraven	case 'g':
975227825Stheraven		++ddata->cur;
976227825Stheraven		if (sizeof(long double) == 16)
977227825Stheraven			return (cpp_demangle_push_fp(ddata,
978227825Stheraven			    decode_fp_to_double));
979227825Stheraven		return (cpp_demangle_push_fp(ddata, decode_fp_to_float128));
980227825Stheraven
981227825Stheraven	case 'i':
982227825Stheraven	case 'j':
983227825Stheraven	case 'l':
984227825Stheraven	case 'm':
985227825Stheraven	case 'n':
986227825Stheraven	case 's':
987227825Stheraven	case 't':
988227825Stheraven	case 'x':
989227825Stheraven	case 'y':
990227825Stheraven		if (*(++ddata->cur) == 'n') {
991227825Stheraven			if (!cpp_demangle_push_str(ddata, "-", 1))
992227825Stheraven				return (0);
993227825Stheraven			++ddata->cur;
994227825Stheraven		}
995227825Stheraven		num = ddata->cur;
996227825Stheraven		while (*ddata->cur != 'E') {
997227825Stheraven			if (!ELFTC_ISDIGIT(*ddata->cur))
998227825Stheraven				return (0);
999227825Stheraven			++ddata->cur;
1000227825Stheraven		}
1001227825Stheraven		++ddata->cur;
1002227825Stheraven		return (cpp_demangle_push_str(ddata, num, ddata->cur - num));
1003227825Stheraven
1004227825Stheraven	default:
1005227825Stheraven		return (0);
1006227825Stheraven	};
1007227825Stheraven}
1008227825Stheraven
1009227825Stheravenstatic int
1010227825Stheravencpp_demangle_read_expression(struct cpp_demangle_data *ddata)
1011227825Stheraven{
1012227825Stheraven
1013227825Stheraven	if (ddata == NULL || *ddata->cur == '\0')
1014227825Stheraven		return (0);
1015227825Stheraven
1016227825Stheraven	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
1017227825Stheraven	case SIMPLE_HASH('s', 't'):
1018227825Stheraven		ddata->cur += 2;
1019227825Stheraven		return (cpp_demangle_read_type(ddata, 0));
1020227825Stheraven
1021227825Stheraven	case SIMPLE_HASH('s', 'r'):
1022227825Stheraven		ddata->cur += 2;
1023227825Stheraven		if (!cpp_demangle_read_type(ddata, 0))
1024227825Stheraven			return (0);
1025227825Stheraven		if (!cpp_demangle_read_uqname(ddata))
1026227825Stheraven			return (0);
1027227825Stheraven		if (*ddata->cur == 'I')
1028227825Stheraven			return (cpp_demangle_read_tmpl_args(ddata));
1029227825Stheraven		return (1);
1030227825Stheraven
1031227825Stheraven	case SIMPLE_HASH('a', 'a'):
1032227825Stheraven		/* operator && */
1033227825Stheraven		ddata->cur += 2;
1034227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "&&", 2));
1035227825Stheraven
1036227825Stheraven	case SIMPLE_HASH('a', 'd'):
1037227825Stheraven		/* operator & (unary) */
1038227825Stheraven		ddata->cur += 2;
1039227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "&", 1));
1040227825Stheraven
1041227825Stheraven	case SIMPLE_HASH('a', 'n'):
1042227825Stheraven		/* operator & */
1043227825Stheraven		ddata->cur += 2;
1044227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "&", 1));
1045227825Stheraven
1046227825Stheraven	case SIMPLE_HASH('a', 'N'):
1047227825Stheraven		/* operator &= */
1048227825Stheraven		ddata->cur += 2;
1049227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "&=", 2));
1050227825Stheraven
1051227825Stheraven	case SIMPLE_HASH('a', 'S'):
1052227825Stheraven		/* operator = */
1053227825Stheraven		ddata->cur += 2;
1054227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "=", 1));
1055227825Stheraven
1056227825Stheraven	case SIMPLE_HASH('c', 'l'):
1057227825Stheraven		/* operator () */
1058227825Stheraven		ddata->cur += 2;
1059227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "()", 2));
1060227825Stheraven
1061227825Stheraven	case SIMPLE_HASH('c', 'm'):
1062227825Stheraven		/* operator , */
1063227825Stheraven		ddata->cur += 2;
1064227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, ",", 1));
1065227825Stheraven
1066227825Stheraven	case SIMPLE_HASH('c', 'o'):
1067227825Stheraven		/* operator ~ */
1068227825Stheraven		ddata->cur += 2;
1069227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "~", 1));
1070227825Stheraven
1071227825Stheraven	case SIMPLE_HASH('c', 'v'):
1072227825Stheraven		/* operator (cast) */
1073227825Stheraven		ddata->cur += 2;
1074227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "(cast)", 6));
1075227825Stheraven
1076227825Stheraven	case SIMPLE_HASH('d', 'a'):
1077227825Stheraven		/* operator delete [] */
1078227825Stheraven		ddata->cur += 2;
1079227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "delete []", 9));
1080227825Stheraven
1081227825Stheraven	case SIMPLE_HASH('d', 'e'):
1082227825Stheraven		/* operator * (unary) */
1083227825Stheraven		ddata->cur += 2;
1084227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "*", 1));
1085227825Stheraven
1086227825Stheraven	case SIMPLE_HASH('d', 'l'):
1087227825Stheraven		/* operator delete */
1088227825Stheraven		ddata->cur += 2;
1089227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "delete", 6));
1090227825Stheraven
1091227825Stheraven	case SIMPLE_HASH('d', 'v'):
1092227825Stheraven		/* operator / */
1093227825Stheraven		ddata->cur += 2;
1094227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "/", 1));
1095227825Stheraven
1096227825Stheraven	case SIMPLE_HASH('d', 'V'):
1097227825Stheraven		/* operator /= */
1098227825Stheraven		ddata->cur += 2;
1099227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "/=", 2));
1100227825Stheraven
1101227825Stheraven	case SIMPLE_HASH('e', 'o'):
1102227825Stheraven		/* operator ^ */
1103227825Stheraven		ddata->cur += 2;
1104227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "^", 1));
1105227825Stheraven
1106227825Stheraven	case SIMPLE_HASH('e', 'O'):
1107227825Stheraven		/* operator ^= */
1108227825Stheraven		ddata->cur += 2;
1109227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "^=", 2));
1110227825Stheraven
1111227825Stheraven	case SIMPLE_HASH('e', 'q'):
1112227825Stheraven		/* operator == */
1113227825Stheraven		ddata->cur += 2;
1114227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "==", 2));
1115227825Stheraven
1116227825Stheraven	case SIMPLE_HASH('g', 'e'):
1117227825Stheraven		/* operator >= */
1118227825Stheraven		ddata->cur += 2;
1119227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, ">=", 2));
1120227825Stheraven
1121227825Stheraven	case SIMPLE_HASH('g', 't'):
1122227825Stheraven		/* operator > */
1123227825Stheraven		ddata->cur += 2;
1124227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, ">", 1));
1125227825Stheraven
1126227825Stheraven	case SIMPLE_HASH('i', 'x'):
1127227825Stheraven		/* operator [] */
1128227825Stheraven		ddata->cur += 2;
1129227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "[]", 2));
1130227825Stheraven
1131227825Stheraven	case SIMPLE_HASH('l', 'e'):
1132227825Stheraven		/* operator <= */
1133227825Stheraven		ddata->cur += 2;
1134227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "<=", 2));
1135227825Stheraven
1136227825Stheraven	case SIMPLE_HASH('l', 's'):
1137227825Stheraven		/* operator << */
1138227825Stheraven		ddata->cur += 2;
1139227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "<<", 2));
1140227825Stheraven
1141227825Stheraven	case SIMPLE_HASH('l', 'S'):
1142227825Stheraven		/* operator <<= */
1143227825Stheraven		ddata->cur += 2;
1144227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "<<=", 3));
1145227825Stheraven
1146227825Stheraven	case SIMPLE_HASH('l', 't'):
1147227825Stheraven		/* operator < */
1148227825Stheraven		ddata->cur += 2;
1149227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "<", 1));
1150227825Stheraven
1151227825Stheraven	case SIMPLE_HASH('m', 'i'):
1152227825Stheraven		/* operator - */
1153227825Stheraven		ddata->cur += 2;
1154227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "-", 1));
1155227825Stheraven
1156227825Stheraven	case SIMPLE_HASH('m', 'I'):
1157227825Stheraven		/* operator -= */
1158227825Stheraven		ddata->cur += 2;
1159227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "-=", 2));
1160227825Stheraven
1161227825Stheraven	case SIMPLE_HASH('m', 'l'):
1162227825Stheraven		/* operator * */
1163227825Stheraven		ddata->cur += 2;
1164227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "*", 1));
1165227825Stheraven
1166227825Stheraven	case SIMPLE_HASH('m', 'L'):
1167227825Stheraven		/* operator *= */
1168227825Stheraven		ddata->cur += 2;
1169227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "*=", 2));
1170227825Stheraven
1171227825Stheraven	case SIMPLE_HASH('m', 'm'):
1172227825Stheraven		/* operator -- */
1173227825Stheraven		ddata->cur += 2;
1174227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "--", 2));
1175227825Stheraven
1176227825Stheraven	case SIMPLE_HASH('n', 'a'):
1177227825Stheraven		/* operator new[] */
1178227825Stheraven		ddata->cur += 2;
1179227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "new []", 6));
1180227825Stheraven
1181227825Stheraven	case SIMPLE_HASH('n', 'e'):
1182227825Stheraven		/* operator != */
1183227825Stheraven		ddata->cur += 2;
1184227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "!=", 2));
1185227825Stheraven
1186227825Stheraven	case SIMPLE_HASH('n', 'g'):
1187227825Stheraven		/* operator - (unary) */
1188227825Stheraven		ddata->cur += 2;
1189227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "-", 1));
1190227825Stheraven
1191227825Stheraven	case SIMPLE_HASH('n', 't'):
1192227825Stheraven		/* operator ! */
1193227825Stheraven		ddata->cur += 2;
1194227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "!", 1));
1195227825Stheraven
1196227825Stheraven	case SIMPLE_HASH('n', 'w'):
1197227825Stheraven		/* operator new */
1198227825Stheraven		ddata->cur += 2;
1199227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "new", 3));
1200227825Stheraven
1201227825Stheraven	case SIMPLE_HASH('o', 'o'):
1202227825Stheraven		/* operator || */
1203227825Stheraven		ddata->cur += 2;
1204227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "||", 2));
1205227825Stheraven
1206227825Stheraven	case SIMPLE_HASH('o', 'r'):
1207227825Stheraven		/* operator | */
1208227825Stheraven		ddata->cur += 2;
1209227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "|", 1));
1210227825Stheraven
1211227825Stheraven	case SIMPLE_HASH('o', 'R'):
1212227825Stheraven		/* operator |= */
1213227825Stheraven		ddata->cur += 2;
1214227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "|=", 2));
1215227825Stheraven
1216227825Stheraven	case SIMPLE_HASH('p', 'l'):
1217227825Stheraven		/* operator + */
1218227825Stheraven		ddata->cur += 2;
1219227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "+", 1));
1220227825Stheraven
1221227825Stheraven	case SIMPLE_HASH('p', 'L'):
1222227825Stheraven		/* operator += */
1223227825Stheraven		ddata->cur += 2;
1224227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "+=", 2));
1225227825Stheraven
1226227825Stheraven	case SIMPLE_HASH('p', 'm'):
1227227825Stheraven		/* operator ->* */
1228227825Stheraven		ddata->cur += 2;
1229227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "->*", 3));
1230227825Stheraven
1231227825Stheraven	case SIMPLE_HASH('p', 'p'):
1232227825Stheraven		/* operator ++ */
1233227825Stheraven		ddata->cur += 2;
1234227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "++", 2));
1235227825Stheraven
1236227825Stheraven	case SIMPLE_HASH('p', 's'):
1237227825Stheraven		/* operator + (unary) */
1238227825Stheraven		ddata->cur += 2;
1239227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "+", 1));
1240227825Stheraven
1241227825Stheraven	case SIMPLE_HASH('p', 't'):
1242227825Stheraven		/* operator -> */
1243227825Stheraven		ddata->cur += 2;
1244227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "->", 2));
1245227825Stheraven
1246227825Stheraven	case SIMPLE_HASH('q', 'u'):
1247227825Stheraven		/* operator ? */
1248227825Stheraven		ddata->cur += 2;
1249227825Stheraven		return (cpp_demangle_read_expression_trinary(ddata, "?", 1,
1250227825Stheraven		    ":", 1));
1251227825Stheraven
1252227825Stheraven	case SIMPLE_HASH('r', 'm'):
1253227825Stheraven		/* operator % */
1254227825Stheraven		ddata->cur += 2;
1255227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "%", 1));
1256227825Stheraven
1257227825Stheraven	case SIMPLE_HASH('r', 'M'):
1258227825Stheraven		/* operator %= */
1259227825Stheraven		ddata->cur += 2;
1260227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, "%=", 2));
1261227825Stheraven
1262227825Stheraven	case SIMPLE_HASH('r', 's'):
1263227825Stheraven		/* operator >> */
1264227825Stheraven		ddata->cur += 2;
1265227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, ">>", 2));
1266227825Stheraven
1267227825Stheraven	case SIMPLE_HASH('r', 'S'):
1268227825Stheraven		/* operator >>= */
1269227825Stheraven		ddata->cur += 2;
1270227825Stheraven		return (cpp_demangle_read_expression_binary(ddata, ">>=", 3));
1271227825Stheraven
1272227825Stheraven	case SIMPLE_HASH('r', 'z'):
1273227825Stheraven		/* operator sizeof */
1274227825Stheraven		ddata->cur += 2;
1275227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
1276227825Stheraven
1277227825Stheraven	case SIMPLE_HASH('s', 'v'):
1278227825Stheraven		/* operator sizeof */
1279227825Stheraven		ddata->cur += 2;
1280227825Stheraven		return (cpp_demangle_read_expression_unary(ddata, "sizeof", 6));
1281227825Stheraven	};
1282227825Stheraven
1283227825Stheraven	switch (*ddata->cur) {
1284227825Stheraven	case 'L':
1285227825Stheraven		return (cpp_demangle_read_expr_primary(ddata));
1286227825Stheraven	case 'T':
1287227825Stheraven		return (cpp_demangle_read_tmpl_param(ddata));
1288227825Stheraven	};
1289227825Stheraven
1290227825Stheraven	return (0);
1291227825Stheraven}
1292227825Stheraven
1293227825Stheravenstatic int
1294227825Stheravencpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
1295227825Stheraven    const char *name, size_t len)
1296227825Stheraven{
1297227825Stheraven
1298227825Stheraven	if (ddata == NULL || name == NULL || len == 0)
1299227825Stheraven		return (0);
1300227825Stheraven	if (!cpp_demangle_read_expression(ddata))
1301227825Stheraven		return (0);
1302227825Stheraven	if (!cpp_demangle_push_str(ddata, name, len))
1303227825Stheraven		return (0);
1304227825Stheraven
1305227825Stheraven	return (cpp_demangle_read_expression(ddata));
1306227825Stheraven}
1307227825Stheraven
1308227825Stheravenstatic int
1309227825Stheravencpp_demangle_read_expression_unary(struct cpp_demangle_data *ddata,
1310227825Stheraven    const char *name, size_t len)
1311227825Stheraven{
1312227825Stheraven
1313227825Stheraven	if (ddata == NULL || name == NULL || len == 0)
1314227825Stheraven		return (0);
1315227825Stheraven	if (!cpp_demangle_read_expression(ddata))
1316227825Stheraven		return (0);
1317227825Stheraven
1318227825Stheraven	return (cpp_demangle_push_str(ddata, name, len));
1319227825Stheraven}
1320227825Stheraven
1321227825Stheravenstatic int
1322227825Stheravencpp_demangle_read_expression_trinary(struct cpp_demangle_data *ddata,
1323227825Stheraven    const char *name1, size_t len1, const char *name2, size_t len2)
1324227825Stheraven{
1325227825Stheraven
1326227825Stheraven	if (ddata == NULL || name1 == NULL || len1 == 0 || name2 == NULL ||
1327227825Stheraven	    len2 == 0)
1328227825Stheraven		return (0);
1329227825Stheraven
1330227825Stheraven	if (!cpp_demangle_read_expression(ddata))
1331227825Stheraven		return (0);
1332227825Stheraven	if (!cpp_demangle_push_str(ddata, name1, len1))
1333227825Stheraven		return (0);
1334227825Stheraven	if (!cpp_demangle_read_expression(ddata))
1335227825Stheraven		return (0);
1336227825Stheraven	if (!cpp_demangle_push_str(ddata, name2, len2))
1337227825Stheraven		return (0);
1338227825Stheraven
1339227825Stheraven	return (cpp_demangle_read_expression(ddata));
1340227825Stheraven}
1341227825Stheraven
1342227825Stheravenstatic int
1343227825Stheravencpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
1344227825Stheraven    struct vector_type_qualifier *v)
1345227825Stheraven{
1346227825Stheraven	size_t class_type_size, class_type_len, limit;
1347227825Stheraven	const char *class_type;
1348227825Stheraven
1349227825Stheraven	if (ddata == NULL || *ddata->cur != 'F' || v == NULL)
1350227825Stheraven		return (0);
1351227825Stheraven
1352227825Stheraven	++ddata->cur;
1353227825Stheraven	if (*ddata->cur == 'Y') {
1354227825Stheraven		if (ext_c != NULL)
1355227825Stheraven			*ext_c = 1;
1356227825Stheraven		++ddata->cur;
1357227825Stheraven	}
1358227825Stheraven	if (!cpp_demangle_read_type(ddata, 0))
1359227825Stheraven		return (0);
1360227825Stheraven	if (*ddata->cur != 'E') {
1361227825Stheraven		if (!cpp_demangle_push_str(ddata, "(", 1))
1362227825Stheraven			return (0);
1363227825Stheraven		if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM)) {
1364227825Stheraven			if ((class_type_size = ddata->class_type.size) == 0)
1365227825Stheraven				return (0);
1366227825Stheraven			class_type =
1367227825Stheraven			    ddata->class_type.container[class_type_size - 1];
1368227825Stheraven			if (class_type == NULL)
1369227825Stheraven				return (0);
1370227825Stheraven			if ((class_type_len = strlen(class_type)) == 0)
1371227825Stheraven				return (0);
1372227825Stheraven			if (!cpp_demangle_push_str(ddata, class_type,
1373227825Stheraven			    class_type_len))
1374227825Stheraven				return (0);
1375227825Stheraven			if (!cpp_demangle_push_str(ddata, "::*", 3))
1376227825Stheraven				return (0);
1377227825Stheraven			++ddata->func_type;
1378227825Stheraven		} else {
1379227825Stheraven			if (!cpp_demangle_push_type_qualifier(ddata, v,
1380227825Stheraven			    (const char *) NULL))
1381227825Stheraven				return (0);
1382227825Stheraven			vector_type_qualifier_dest(v);
1383227825Stheraven			if (!vector_type_qualifier_init(v))
1384227825Stheraven				return (0);
1385227825Stheraven		}
1386227825Stheraven
1387227825Stheraven		if (!cpp_demangle_push_str(ddata, ")(", 2))
1388227825Stheraven			return (0);
1389227825Stheraven
1390227825Stheraven		limit = 0;
1391227825Stheraven		for (;;) {
1392227825Stheraven			if (!cpp_demangle_read_type(ddata, 0))
1393227825Stheraven				return (0);
1394227825Stheraven			if (*ddata->cur == 'E')
1395227825Stheraven				break;
1396227825Stheraven			if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1397227825Stheraven				return (0);
1398227825Stheraven		}
1399227825Stheraven
1400227825Stheraven		if (vector_read_cmd_find(&ddata->cmd, READ_PTRMEM) == 1) {
1401227825Stheraven			if (!cpp_demangle_push_type_qualifier(ddata, v,
1402227825Stheraven			    (const char *) NULL))
1403227825Stheraven				return (0);
1404227825Stheraven			vector_type_qualifier_dest(v);
1405227825Stheraven			if (!vector_type_qualifier_init(v))
1406227825Stheraven				return (0);
1407227825Stheraven		}
1408227825Stheraven
1409227825Stheraven		if (!cpp_demangle_push_str(ddata, ")", 1))
1410227825Stheraven			return (0);
1411227825Stheraven	}
1412227825Stheraven
1413227825Stheraven	++ddata->cur;
1414227825Stheraven
1415227825Stheraven	return (1);
1416227825Stheraven}
1417227825Stheraven
1418227825Stheraven/* read encoding, encoding are function name, data name, special-name */
1419227825Stheravenstatic int
1420227825Stheravencpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
1421227825Stheraven{
1422227825Stheraven
1423227825Stheraven	if (ddata == NULL || *ddata->cur == '\0')
1424227825Stheraven		return (0);
1425227825Stheraven
1426227825Stheraven	/* special name */
1427227825Stheraven	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
1428227825Stheraven	case SIMPLE_HASH('G', 'V'):
1429227825Stheraven		/* sentry object for 1 time init */
1430227825Stheraven		if (!cpp_demangle_push_str(ddata, "guard variable for ", 20))
1431227825Stheraven			return (0);
1432227825Stheraven		ddata->cur += 2;
1433227825Stheraven		break;
1434227825Stheraven
1435227825Stheraven	case SIMPLE_HASH('T', 'c'):
1436227825Stheraven		/* virtual function covariant override thunk */
1437227825Stheraven		if (!cpp_demangle_push_str(ddata,
1438227825Stheraven		    "virtual function covariant override ", 36))
1439227825Stheraven			return (0);
1440227825Stheraven		ddata->cur += 2;
1441227825Stheraven		if (*ddata->cur == '\0')
1442227825Stheraven			return (0);
1443227825Stheraven		if (!cpp_demangle_read_offset(ddata))
1444227825Stheraven			return (0);
1445227825Stheraven		if (!cpp_demangle_read_offset(ddata))
1446227825Stheraven			return (0);
1447227825Stheraven		return (cpp_demangle_read_encoding(ddata));
1448227825Stheraven
1449227825Stheraven	case SIMPLE_HASH('T', 'D'):
1450227825Stheraven		/* typeinfo common proxy */
1451227825Stheraven		break;
1452227825Stheraven
1453227825Stheraven	case SIMPLE_HASH('T', 'h'):
1454227825Stheraven		/* virtual function non-virtual override thunk */
1455227825Stheraven		if (cpp_demangle_push_str(ddata,
1456227825Stheraven		    "virtual function non-virtual override ", 38) == 0)
1457227825Stheraven			return (0);
1458227825Stheraven		ddata->cur += 2;
1459227825Stheraven		if (*ddata->cur == '\0')
1460227825Stheraven			return (0);
1461227825Stheraven		if (!cpp_demangle_read_nv_offset(ddata))
1462227825Stheraven			return (0);
1463227825Stheraven		return (cpp_demangle_read_encoding(ddata));
1464227825Stheraven
1465227825Stheraven	case SIMPLE_HASH('T', 'I'):
1466227825Stheraven		/* typeinfo structure */
1467227825Stheraven		/* FALLTHROUGH */
1468227825Stheraven	case SIMPLE_HASH('T', 'S'):
1469227825Stheraven		/* RTTI name (NTBS) */
1470227825Stheraven		if (!cpp_demangle_push_str(ddata, "typeinfo for ", 14))
1471227825Stheraven			return (0);
1472227825Stheraven		ddata->cur += 2;
1473227825Stheraven		if (*ddata->cur == '\0')
1474227825Stheraven			return (0);
1475227825Stheraven		return (cpp_demangle_read_type(ddata, 1));
1476227825Stheraven
1477227825Stheraven	case SIMPLE_HASH('T', 'T'):
1478227825Stheraven		/* VTT table */
1479227825Stheraven		if (!cpp_demangle_push_str(ddata, "VTT for ", 8))
1480227825Stheraven			return (0);
1481227825Stheraven		ddata->cur += 2;
1482227825Stheraven		return (cpp_demangle_read_type(ddata, 1));
1483227825Stheraven
1484227825Stheraven	case SIMPLE_HASH('T', 'v'):
1485227825Stheraven		/* virtual function virtual override thunk */
1486227825Stheraven		if (!cpp_demangle_push_str(ddata,
1487227825Stheraven		    "virtual function virtual override ", 34))
1488227825Stheraven			return (0);
1489227825Stheraven		ddata->cur += 2;
1490227825Stheraven		if (*ddata->cur == '\0')
1491227825Stheraven			return (0);
1492227825Stheraven		if (!cpp_demangle_read_v_offset(ddata))
1493227825Stheraven			return (0);
1494227825Stheraven		return (cpp_demangle_read_encoding(ddata));
1495227825Stheraven
1496227825Stheraven	case SIMPLE_HASH('T', 'V'):
1497227825Stheraven		/* virtual table */
1498227825Stheraven		if (!cpp_demangle_push_str(ddata, "vtable for ", 12))
1499227825Stheraven			return (0);
1500227825Stheraven		ddata->cur += 2;
1501227825Stheraven		if (*ddata->cur == '\0')
1502227825Stheraven			return (0);
1503227825Stheraven		return (cpp_demangle_read_type(ddata, 1));
1504227825Stheraven	};
1505227825Stheraven
1506227825Stheraven	return (cpp_demangle_read_name(ddata));
1507227825Stheraven}
1508227825Stheraven
1509227825Stheravenstatic int
1510227825Stheravencpp_demangle_read_local_name(struct cpp_demangle_data *ddata)
1511227825Stheraven{
1512227825Stheraven	size_t limit;
1513227825Stheraven
1514227825Stheraven	if (ddata == NULL)
1515227825Stheraven		return (0);
1516227825Stheraven	if (*(++ddata->cur) == '\0')
1517227825Stheraven		return (0);
1518227825Stheraven	if (!cpp_demangle_read_encoding(ddata))
1519227825Stheraven		return (0);
1520227825Stheraven
1521227825Stheraven	limit = 0;
1522227825Stheraven	for (;;) {
1523227825Stheraven		if (!cpp_demangle_read_type(ddata, 1))
1524227825Stheraven			return (0);
1525227825Stheraven		if (*ddata->cur == 'E')
1526227825Stheraven			break;
1527227825Stheraven		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1528227825Stheraven			return (0);
1529227825Stheraven	}
1530227825Stheraven	if (*(++ddata->cur) == '\0')
1531227825Stheraven		return (0);
1532227825Stheraven	if (ddata->paren == true) {
1533227825Stheraven		if (!cpp_demangle_push_str(ddata, ")", 1))
1534227825Stheraven			return (0);
1535227825Stheraven		ddata->paren = false;
1536227825Stheraven	}
1537227825Stheraven	if (*ddata->cur == 's')
1538227825Stheraven		++ddata->cur;
1539227825Stheraven	else {
1540227825Stheraven		if (!cpp_demangle_push_str(ddata, "::", 2))
1541227825Stheraven			return (0);
1542227825Stheraven		if (!cpp_demangle_read_name(ddata))
1543227825Stheraven			return (0);
1544227825Stheraven	}
1545227825Stheraven	if (*ddata->cur == '_') {
1546227825Stheraven		++ddata->cur;
1547227825Stheraven		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
1548227825Stheraven			++ddata->cur;
1549227825Stheraven	}
1550227825Stheraven
1551227825Stheraven	return (1);
1552227825Stheraven}
1553227825Stheraven
1554227825Stheravenstatic int
1555227825Stheravencpp_demangle_read_name(struct cpp_demangle_data *ddata)
1556227825Stheraven{
1557227825Stheraven	struct vector_str *output, v;
1558227825Stheraven	size_t p_idx, subst_str_len;
1559227825Stheraven	int rtn;
1560227825Stheraven	char *subst_str;
1561227825Stheraven
1562227825Stheraven	if (ddata == NULL || *ddata->cur == '\0')
1563227825Stheraven		return (0);
1564227825Stheraven
1565227825Stheraven	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
1566227825Stheraven
1567227825Stheraven	subst_str = NULL;
1568227825Stheraven
1569227825Stheraven	switch (*ddata->cur) {
1570227825Stheraven	case 'S':
1571227825Stheraven		return (cpp_demangle_read_subst(ddata));
1572227825Stheraven	case 'N':
1573227825Stheraven		return (cpp_demangle_read_nested_name(ddata));
1574227825Stheraven	case 'Z':
1575227825Stheraven		return (cpp_demangle_read_local_name(ddata));
1576227825Stheraven	};
1577227825Stheraven
1578227825Stheraven	if (!vector_str_init(&v))
1579227825Stheraven		return (0);
1580227825Stheraven
1581227825Stheraven	p_idx = output->size;
1582227825Stheraven	rtn = 0;
1583227825Stheraven	if (!cpp_demangle_read_uqname(ddata))
1584227825Stheraven		goto clean;
1585227825Stheraven	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
1586227825Stheraven	    &subst_str_len)) == NULL)
1587227825Stheraven		goto clean;
1588227825Stheraven	if (subst_str_len > 8 && strstr(subst_str, "operator") != NULL) {
1589227825Stheraven		rtn = 1;
1590227825Stheraven		goto clean;
1591227825Stheraven	}
1592227825Stheraven	if (!vector_str_push(&v, subst_str, subst_str_len))
1593227825Stheraven		goto clean;
1594227825Stheraven	if (!cpp_demangle_push_subst_v(ddata, &v))
1595227825Stheraven		goto clean;
1596227825Stheraven
1597227825Stheraven	if (*ddata->cur == 'I') {
1598227825Stheraven		p_idx = output->size;
1599227825Stheraven		if (!cpp_demangle_read_tmpl_args(ddata))
1600227825Stheraven			goto clean;
1601227825Stheraven		free(subst_str);
1602227825Stheraven		if ((subst_str = vector_str_substr(output, p_idx,
1603227825Stheraven		    output->size - 1, &subst_str_len)) == NULL)
1604227825Stheraven			goto clean;
1605227825Stheraven		if (!vector_str_push(&v, subst_str, subst_str_len))
1606227825Stheraven			goto clean;
1607227825Stheraven		if (!cpp_demangle_push_subst_v(ddata, &v))
1608227825Stheraven			goto clean;
1609227825Stheraven	}
1610227825Stheraven
1611227825Stheraven	rtn = 1;
1612227825Stheraven
1613227825Stheravenclean:
1614227825Stheraven	free(subst_str);
1615227825Stheraven	vector_str_dest(&v);
1616227825Stheraven
1617227825Stheraven	return (rtn);
1618227825Stheraven}
1619227825Stheraven
1620227825Stheravenstatic int
1621227825Stheravencpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
1622227825Stheraven{
1623227825Stheraven	struct vector_str *output, v;
1624227825Stheraven	size_t limit, p_idx, subst_str_len;
1625227825Stheraven	int rtn;
1626227825Stheraven	char *subst_str;
1627227825Stheraven
1628227825Stheraven	if (ddata == NULL || *ddata->cur != 'N')
1629227825Stheraven		return (0);
1630227825Stheraven	if (*(++ddata->cur) == '\0')
1631227825Stheraven		return (0);
1632227825Stheraven
1633227825Stheraven	while (*ddata->cur == 'r' || *ddata->cur == 'V' ||
1634227825Stheraven	    *ddata->cur == 'K') {
1635227825Stheraven		switch (*ddata->cur) {
1636227825Stheraven		case 'r':
1637227825Stheraven			ddata->mem_rst = true;
1638227825Stheraven			break;
1639227825Stheraven		case 'V':
1640227825Stheraven			ddata->mem_vat = true;
1641227825Stheraven			break;
1642227825Stheraven		case 'K':
1643227825Stheraven			ddata->mem_cst = true;
1644227825Stheraven			break;
1645227825Stheraven		};
1646227825Stheraven		++ddata->cur;
1647227825Stheraven	}
1648227825Stheraven
1649227825Stheraven	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
1650227825Stheraven	if (!vector_str_init(&v))
1651227825Stheraven		return (0);
1652227825Stheraven
1653227825Stheraven	rtn = 0;
1654227825Stheraven	limit = 0;
1655227825Stheraven	for (;;) {
1656227825Stheraven		p_idx = output->size;
1657227825Stheraven		switch (*ddata->cur) {
1658227825Stheraven		case 'I':
1659227825Stheraven			if (!cpp_demangle_read_tmpl_args(ddata))
1660227825Stheraven				goto clean;
1661227825Stheraven			break;
1662227825Stheraven		case 'S':
1663227825Stheraven			if (!cpp_demangle_read_subst(ddata))
1664227825Stheraven				goto clean;
1665227825Stheraven			break;
1666227825Stheraven		case 'T':
1667227825Stheraven			if (!cpp_demangle_read_tmpl_param(ddata))
1668227825Stheraven				goto clean;
1669227825Stheraven			break;
1670227825Stheraven		default:
1671227825Stheraven			if (!cpp_demangle_read_uqname(ddata))
1672227825Stheraven				goto clean;
1673227825Stheraven		};
1674227825Stheraven
1675227825Stheraven		if ((subst_str = vector_str_substr(output, p_idx,
1676227825Stheraven		    output->size - 1, &subst_str_len)) == NULL)
1677227825Stheraven			goto clean;
1678227825Stheraven		if (!vector_str_push(&v, subst_str, subst_str_len)) {
1679227825Stheraven			free(subst_str);
1680227825Stheraven			goto clean;
1681227825Stheraven		}
1682227825Stheraven		free(subst_str);
1683227825Stheraven
1684227825Stheraven		if (!cpp_demangle_push_subst_v(ddata, &v))
1685227825Stheraven			goto clean;
1686227825Stheraven		if (*ddata->cur == 'E')
1687227825Stheraven			break;
1688227825Stheraven		else if (*ddata->cur != 'I' &&
1689227825Stheraven		    *ddata->cur != 'C' && *ddata->cur != 'D') {
1690227825Stheraven			if (!cpp_demangle_push_str(ddata, "::", 2))
1691227825Stheraven				goto clean;
1692227825Stheraven			if (!vector_str_push(&v, "::", 2))
1693227825Stheraven				goto clean;
1694227825Stheraven		}
1695227825Stheraven		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
1696227825Stheraven			goto clean;
1697227825Stheraven	}
1698227825Stheraven
1699227825Stheraven	++ddata->cur;
1700227825Stheraven	rtn = 1;
1701227825Stheraven
1702227825Stheravenclean:
1703227825Stheraven	vector_str_dest(&v);
1704227825Stheraven
1705227825Stheraven	return (rtn);
1706227825Stheraven}
1707227825Stheraven
1708227825Stheraven/*
1709227825Stheraven * read number
1710227825Stheraven * number ::= [n] <decimal>
1711227825Stheraven */
1712227825Stheravenstatic int
1713227825Stheravencpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
1714227825Stheraven{
1715227825Stheraven	long len, negative_factor;
1716227825Stheraven
1717227825Stheraven	if (ddata == NULL || rtn == NULL)
1718227825Stheraven		return (0);
1719227825Stheraven
1720227825Stheraven	negative_factor = 1;
1721227825Stheraven	if (*ddata->cur == 'n') {
1722227825Stheraven		negative_factor = -1;
1723227825Stheraven
1724227825Stheraven		++ddata->cur;
1725227825Stheraven	}
1726227825Stheraven	if (ELFTC_ISDIGIT(*ddata->cur) == 0)
1727227825Stheraven		return (0);
1728227825Stheraven
1729227825Stheraven	errno = 0;
1730227825Stheraven	if ((len = strtol(ddata->cur, (char **) NULL, 10)) == 0 &&
1731227825Stheraven	    errno != 0)
1732227825Stheraven		return (0);
1733227825Stheraven
1734227825Stheraven	while (ELFTC_ISDIGIT(*ddata->cur) != 0)
1735227825Stheraven		++ddata->cur;
1736227825Stheraven
1737227825Stheraven	assert(len >= 0);
1738227825Stheraven	assert(negative_factor == 1 || negative_factor == -1);
1739227825Stheraven
1740227825Stheraven	*rtn = len * negative_factor;
1741227825Stheraven
1742227825Stheraven	return (1);
1743227825Stheraven}
1744227825Stheraven
1745227825Stheravenstatic int
1746227825Stheravencpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
1747227825Stheraven{
1748227825Stheraven
1749227825Stheraven	if (ddata == NULL)
1750227825Stheraven		return (0);
1751227825Stheraven
1752227825Stheraven	if (!cpp_demangle_push_str(ddata, "offset : ", 9))
1753227825Stheraven		return (0);
1754227825Stheraven
1755227825Stheraven	return (cpp_demangle_read_offset_number(ddata));
1756227825Stheraven}
1757227825Stheraven
1758227825Stheraven/* read offset, offset are nv-offset, v-offset */
1759227825Stheravenstatic int
1760227825Stheravencpp_demangle_read_offset(struct cpp_demangle_data *ddata)
1761227825Stheraven{
1762227825Stheraven
1763227825Stheraven	if (ddata == NULL)
1764227825Stheraven		return (0);
1765227825Stheraven
1766227825Stheraven	if (*ddata->cur == 'h') {
1767227825Stheraven		++ddata->cur;
1768227825Stheraven		return (cpp_demangle_read_nv_offset(ddata));
1769227825Stheraven	} else if (*ddata->cur == 'v') {
1770227825Stheraven		++ddata->cur;
1771227825Stheraven		return (cpp_demangle_read_v_offset(ddata));
1772227825Stheraven	}
1773227825Stheraven
1774227825Stheraven	return (0);
1775227825Stheraven}
1776227825Stheraven
1777227825Stheravenstatic int
1778227825Stheravencpp_demangle_read_offset_number(struct cpp_demangle_data *ddata)
1779227825Stheraven{
1780227825Stheraven	bool negative;
1781227825Stheraven	const char *start;
1782227825Stheraven
1783227825Stheraven	if (ddata == NULL || *ddata->cur == '\0')
1784227825Stheraven		return (0);
1785227825Stheraven
1786227825Stheraven	/* offset could be negative */
1787227825Stheraven	if (*ddata->cur == 'n') {
1788227825Stheraven		negative = true;
1789227825Stheraven		start = ddata->cur + 1;
1790227825Stheraven	} else {
1791227825Stheraven		negative = false;
1792227825Stheraven		start = ddata->cur;
1793227825Stheraven	}
1794227825Stheraven
1795227825Stheraven	while (*ddata->cur != '_')
1796227825Stheraven		++ddata->cur;
1797227825Stheraven
1798227825Stheraven	if (negative && !cpp_demangle_push_str(ddata, "-", 1))
1799227825Stheraven		return (0);
1800227825Stheraven
1801227825Stheraven	assert(start != NULL);
1802227825Stheraven
1803227825Stheraven	if (!cpp_demangle_push_str(ddata, start, ddata->cur - start))
1804227825Stheraven		return (0);
1805227825Stheraven	if (!cpp_demangle_push_str(ddata, " ", 1))
1806227825Stheraven		return (0);
1807227825Stheraven
1808227825Stheraven	++ddata->cur;
1809227825Stheraven
1810227825Stheraven	return (1);
1811227825Stheraven}
1812227825Stheraven
1813227825Stheravenstatic int
1814227825Stheravencpp_demangle_read_pointer_to_member(struct cpp_demangle_data *ddata)
1815227825Stheraven{
1816227825Stheraven	size_t class_type_len, i, idx, p_idx;
1817227825Stheraven	int p_func_type, rtn;
1818227825Stheraven	char *class_type;
1819227825Stheraven
1820227825Stheraven	if (ddata == NULL || *ddata->cur != 'M' || *(++ddata->cur) == '\0')
1821227825Stheraven		return (0);
1822227825Stheraven
1823227825Stheraven	p_idx = ddata->output.size;
1824227825Stheraven	if (!cpp_demangle_read_type(ddata, 0))
1825227825Stheraven		return (0);
1826227825Stheraven
1827227825Stheraven	if ((class_type = vector_str_substr(&ddata->output, p_idx,
1828227825Stheraven	    ddata->output.size - 1, &class_type_len)) == NULL)
1829227825Stheraven		return (0);
1830227825Stheraven
1831227825Stheraven	rtn = 0;
1832227825Stheraven	idx = ddata->output.size;
1833227825Stheraven	for (i = p_idx; i < idx; ++i)
1834227825Stheraven		if (!vector_str_pop(&ddata->output))
1835227825Stheraven			goto clean1;
1836227825Stheraven
1837227825Stheraven	if (!vector_read_cmd_push(&ddata->cmd, READ_PTRMEM))
1838227825Stheraven		goto clean1;
1839227825Stheraven
1840227825Stheraven	if (!vector_str_push(&ddata->class_type, class_type, class_type_len))
1841227825Stheraven		goto clean2;
1842227825Stheraven
1843227825Stheraven	p_func_type = ddata->func_type;
1844227825Stheraven	if (!cpp_demangle_read_type(ddata, 0))
1845227825Stheraven		goto clean3;
1846227825Stheraven
1847227825Stheraven	if (p_func_type == ddata->func_type) {
1848227825Stheraven		if (!cpp_demangle_push_str(ddata, " ", 1))
1849227825Stheraven			goto clean3;
1850227825Stheraven		if (!cpp_demangle_push_str(ddata, class_type, class_type_len))
1851227825Stheraven			goto clean3;
1852227825Stheraven		if (!cpp_demangle_push_str(ddata, "::*", 3))
1853227825Stheraven			goto clean3;
1854227825Stheraven	}
1855227825Stheraven
1856227825Stheraven	rtn = 1;
1857227825Stheravenclean3:
1858227825Stheraven	if (!vector_str_pop(&ddata->class_type))
1859227825Stheraven		rtn = 0;
1860227825Stheravenclean2:
1861227825Stheraven	if (!vector_read_cmd_pop(&ddata->cmd))
1862227825Stheraven		rtn = 0;
1863227825Stheravenclean1:
1864227825Stheraven	free(class_type);
1865227825Stheraven
1866227825Stheraven	return (rtn);
1867227825Stheraven}
1868227825Stheraven
1869227825Stheraven/* read source-name, source-name is <len> <ID> */
1870227825Stheravenstatic int
1871227825Stheravencpp_demangle_read_sname(struct cpp_demangle_data *ddata)
1872227825Stheraven{
1873227825Stheraven	long len;
1874255815Stheraven	int err;
1875227825Stheraven
1876227825Stheraven	if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
1877255815Stheraven	    len <= 0)
1878227825Stheraven		return (0);
1879227825Stheraven
1880255815Stheraven 	if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0))
1881255815Stheraven		err = cpp_demangle_push_str(ddata, "(anonymous namespace)", 21);
1882255815Stheraven	else
1883255815Stheraven		err = cpp_demangle_push_str(ddata, ddata->cur, len);
1884255815Stheraven
1885255815Stheraven	if (err == 0)
1886255815Stheraven		return (0);
1887255815Stheraven
1888227825Stheraven	assert(ddata->output.size > 0);
1889227825Stheraven	if (vector_read_cmd_find(&ddata->cmd, READ_TMPL) == 0)
1890227825Stheraven		ddata->last_sname =
1891227825Stheraven		    ddata->output.container[ddata->output.size - 1];
1892227825Stheraven
1893227825Stheraven	ddata->cur += len;
1894227825Stheraven
1895227825Stheraven	return (1);
1896227825Stheraven}
1897227825Stheraven
1898227825Stheravenstatic int
1899227825Stheravencpp_demangle_read_subst(struct cpp_demangle_data *ddata)
1900227825Stheraven{
1901227825Stheraven	long nth;
1902227825Stheraven
1903227825Stheraven	if (ddata == NULL || *ddata->cur == '\0')
1904227825Stheraven		return (0);
1905227825Stheraven
1906227825Stheraven	/* abbreviations of the form Sx */
1907227825Stheraven	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
1908227825Stheraven	case SIMPLE_HASH('S', 'a'):
1909227825Stheraven		/* std::allocator */
1910227825Stheraven		if (cpp_demangle_push_str(ddata, "std::allocator", 14) == 0)
1911227825Stheraven			return (0);
1912227825Stheraven		ddata->cur += 2;
1913227825Stheraven		if (*ddata->cur == 'I')
1914227825Stheraven			return (cpp_demangle_read_subst_stdtmpl(ddata,
1915227825Stheraven			    "std::allocator", 14));
1916227825Stheraven		return (1);
1917227825Stheraven
1918227825Stheraven	case SIMPLE_HASH('S', 'b'):
1919227825Stheraven		/* std::basic_string */
1920227825Stheraven		if (!cpp_demangle_push_str(ddata, "std::basic_string", 17))
1921227825Stheraven			return (0);
1922227825Stheraven		ddata->cur += 2;
1923227825Stheraven		if (*ddata->cur == 'I')
1924227825Stheraven			return (cpp_demangle_read_subst_stdtmpl(ddata,
1925227825Stheraven			    "std::basic_string", 17));
1926227825Stheraven		return (1);
1927227825Stheraven
1928227825Stheraven	case SIMPLE_HASH('S', 'd'):
1929227825Stheraven		/* std::basic_iostream<char, std::char_traits<char> > */
1930227825Stheraven		if (!cpp_demangle_push_str(ddata, "std::iostream", 19))
1931227825Stheraven			return (0);
1932227825Stheraven		ddata->last_sname = "iostream";
1933227825Stheraven		ddata->cur += 2;
1934227825Stheraven		if (*ddata->cur == 'I')
1935227825Stheraven			return (cpp_demangle_read_subst_stdtmpl(ddata,
1936227825Stheraven			    "std::iostream", 19));
1937227825Stheraven		return (1);
1938227825Stheraven
1939227825Stheraven	case SIMPLE_HASH('S', 'i'):
1940227825Stheraven		/* std::basic_istream<char, std::char_traits<char> > */
1941227825Stheraven		if (!cpp_demangle_push_str(ddata, "std::istream", 18))
1942227825Stheraven			return (0);
1943227825Stheraven		ddata->last_sname = "istream";
1944227825Stheraven		ddata->cur += 2;
1945227825Stheraven		if (*ddata->cur == 'I')
1946227825Stheraven			return (cpp_demangle_read_subst_stdtmpl(ddata,
1947227825Stheraven			    "std::istream", 18));
1948227825Stheraven		return (1);
1949227825Stheraven
1950227825Stheraven	case SIMPLE_HASH('S', 'o'):
1951227825Stheraven		/* std::basic_ostream<char, std::char_traits<char> > */
1952227825Stheraven		if (!cpp_demangle_push_str(ddata, "std::ostream", 18))
1953227825Stheraven			return (0);
1954227825Stheraven		ddata->last_sname = "istream";
1955227825Stheraven		ddata->cur += 2;
1956227825Stheraven		if (*ddata->cur == 'I')
1957227825Stheraven			return (cpp_demangle_read_subst_stdtmpl(ddata,
1958227825Stheraven			    "std::ostream", 18));
1959227825Stheraven		return (1);
1960227825Stheraven
1961227825Stheraven	case SIMPLE_HASH('S', 's'):
1962227825Stheraven		/*
1963227825Stheraven		 * std::basic_string<char, std::char_traits<char>,
1964227825Stheraven		 * std::allocator<char> >
1965227825Stheraven		 *
1966227825Stheraven		 * a.k.a std::string
1967227825Stheraven		 */
1968227825Stheraven		if (!cpp_demangle_push_str(ddata, "std::string", 11))
1969227825Stheraven			return (0);
1970227825Stheraven		ddata->last_sname = "string";
1971227825Stheraven		ddata->cur += 2;
1972227825Stheraven		if (*ddata->cur == 'I')
1973227825Stheraven			return (cpp_demangle_read_subst_stdtmpl(ddata,
1974227825Stheraven			    "std::string", 11));
1975227825Stheraven		return (1);
1976227825Stheraven
1977227825Stheraven	case SIMPLE_HASH('S', 't'):
1978227825Stheraven		/* std:: */
1979227825Stheraven		return (cpp_demangle_read_subst_std(ddata));
1980227825Stheraven	};
1981227825Stheraven
1982227825Stheraven	if (*(++ddata->cur) == '\0')
1983227825Stheraven		return (0);
1984227825Stheraven
1985227825Stheraven	/* substitution */
1986227825Stheraven	if (*ddata->cur == '_')
1987227825Stheraven		return (cpp_demangle_get_subst(ddata, 0));
1988227825Stheraven	else {
1989227825Stheraven		errno = 0;
1990227825Stheraven		/* substitution number is base 36 */
1991227825Stheraven		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
1992227825Stheraven		    errno != 0)
1993227825Stheraven			return (0);
1994227825Stheraven
1995227825Stheraven		/* first was '_', so increase one */
1996227825Stheraven		++nth;
1997227825Stheraven
1998227825Stheraven		while (*ddata->cur != '_')
1999227825Stheraven			++ddata->cur;
2000227825Stheraven
2001227825Stheraven		assert(nth > 0);
2002227825Stheraven
2003227825Stheraven		return (cpp_demangle_get_subst(ddata, nth));
2004227825Stheraven	}
2005227825Stheraven
2006227825Stheraven	/* NOTREACHED */
2007227825Stheraven	return (0);
2008227825Stheraven}
2009227825Stheraven
2010227825Stheravenstatic int
2011227825Stheravencpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
2012227825Stheraven{
2013227825Stheraven	struct vector_str *output, v;
2014227825Stheraven	size_t p_idx, subst_str_len;
2015227825Stheraven	int rtn;
2016227825Stheraven	char *subst_str;
2017227825Stheraven
2018227825Stheraven	if (ddata == NULL)
2019227825Stheraven		return (0);
2020227825Stheraven
2021227825Stheraven	if (!vector_str_init(&v))
2022227825Stheraven		return (0);
2023227825Stheraven
2024227825Stheraven	subst_str = NULL;
2025227825Stheraven	rtn = 0;
2026227825Stheraven	if (!cpp_demangle_push_str(ddata, "std::", 5))
2027227825Stheraven		goto clean;
2028227825Stheraven
2029227825Stheraven	if (!vector_str_push(&v, "std::", 5))
2030227825Stheraven		goto clean;
2031227825Stheraven
2032227825Stheraven	ddata->cur += 2;
2033227825Stheraven
2034227825Stheraven	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
2035227825Stheraven
2036227825Stheraven	p_idx = output->size;
2037227825Stheraven	if (!cpp_demangle_read_uqname(ddata))
2038227825Stheraven		goto clean;
2039227825Stheraven
2040227825Stheraven	if ((subst_str = vector_str_substr(output, p_idx, output->size - 1,
2041227825Stheraven	    &subst_str_len)) == NULL)
2042227825Stheraven		goto clean;
2043227825Stheraven
2044227825Stheraven	if (!vector_str_push(&v, subst_str, subst_str_len))
2045227825Stheraven		goto clean;
2046227825Stheraven
2047227825Stheraven	if (!cpp_demangle_push_subst_v(ddata, &v))
2048227825Stheraven		goto clean;
2049227825Stheraven
2050227825Stheraven	if (*ddata->cur == 'I') {
2051227825Stheraven		p_idx = output->size;
2052227825Stheraven		if (!cpp_demangle_read_tmpl_args(ddata))
2053227825Stheraven			goto clean;
2054227825Stheraven		free(subst_str);
2055227825Stheraven		if ((subst_str = vector_str_substr(output, p_idx,
2056227825Stheraven		    output->size - 1, &subst_str_len)) == NULL)
2057227825Stheraven			goto clean;
2058227825Stheraven		if (!vector_str_push(&v, subst_str, subst_str_len))
2059227825Stheraven			goto clean;
2060227825Stheraven		if (!cpp_demangle_push_subst_v(ddata, &v))
2061227825Stheraven			goto clean;
2062227825Stheraven	}
2063227825Stheraven
2064227825Stheraven	rtn = 1;
2065227825Stheravenclean:
2066227825Stheraven	free(subst_str);
2067227825Stheraven	vector_str_dest(&v);
2068227825Stheraven
2069255815Stheraven	return (rtn);
2070227825Stheraven}
2071227825Stheraven
2072227825Stheravenstatic int
2073227825Stheravencpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
2074227825Stheraven    const char *str, size_t len)
2075227825Stheraven{
2076227825Stheraven	struct vector_str *output;
2077227825Stheraven	size_t p_idx, substr_len;
2078227825Stheraven	int rtn;
2079227825Stheraven	char *subst_str, *substr;
2080227825Stheraven
2081227825Stheraven	if (ddata == NULL || str == NULL || len == 0)
2082227825Stheraven		return (0);
2083227825Stheraven
2084227825Stheraven	output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
2085227825Stheraven
2086227825Stheraven	p_idx = output->size;
2087227825Stheraven	substr = NULL;
2088227825Stheraven	subst_str = NULL;
2089227825Stheraven
2090227825Stheraven	if (!cpp_demangle_read_tmpl_args(ddata))
2091227825Stheraven		return (0);
2092227825Stheraven	if ((substr = vector_str_substr(output, p_idx, output->size - 1,
2093227825Stheraven	    &substr_len)) == NULL)
2094227825Stheraven		return (0);
2095227825Stheraven
2096227825Stheraven	rtn = 0;
2097227825Stheraven	if ((subst_str = malloc(sizeof(char) * (substr_len + len + 1))) ==
2098227825Stheraven	    NULL)
2099227825Stheraven		goto clean;
2100227825Stheraven
2101227825Stheraven	memcpy(subst_str, str, len);
2102227825Stheraven	memcpy(subst_str + len, substr, substr_len);
2103227825Stheraven	subst_str[substr_len + len] = '\0';
2104227825Stheraven
2105227825Stheraven	if (!cpp_demangle_push_subst(ddata, subst_str, substr_len + len))
2106227825Stheraven		goto clean;
2107227825Stheraven
2108227825Stheraven	rtn = 1;
2109227825Stheravenclean:
2110227825Stheraven	free(subst_str);
2111227825Stheraven	free(substr);
2112227825Stheraven
2113227825Stheraven	return (rtn);
2114227825Stheraven}
2115227825Stheraven
2116227825Stheravenstatic int
2117227825Stheravencpp_demangle_read_tmpl_arg(struct cpp_demangle_data *ddata)
2118227825Stheraven{
2119227825Stheraven
2120227825Stheraven	if (ddata == NULL || *ddata->cur == '\0')
2121227825Stheraven		return (0);
2122227825Stheraven
2123227825Stheraven	switch (*ddata->cur) {
2124227825Stheraven	case 'L':
2125227825Stheraven		return (cpp_demangle_read_expr_primary(ddata));
2126227825Stheraven	case 'X':
2127227825Stheraven		return (cpp_demangle_read_expression(ddata));
2128227825Stheraven	};
2129227825Stheraven
2130227825Stheraven	return (cpp_demangle_read_type(ddata, 0));
2131227825Stheraven}
2132227825Stheraven
2133227825Stheravenstatic int
2134227825Stheravencpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
2135227825Stheraven{
2136227825Stheraven	struct vector_str *v;
2137227825Stheraven	size_t arg_len, idx, limit, size;
2138227825Stheraven	char *arg;
2139227825Stheraven
2140227825Stheraven	if (ddata == NULL || *ddata->cur == '\0')
2141227825Stheraven		return (0);
2142227825Stheraven
2143227825Stheraven	++ddata->cur;
2144227825Stheraven
2145227825Stheraven	if (!vector_read_cmd_push(&ddata->cmd, READ_TMPL))
2146227825Stheraven		return (0);
2147227825Stheraven
2148227825Stheraven	if (!cpp_demangle_push_str(ddata, "<", 1))
2149227825Stheraven		return (0);
2150227825Stheraven
2151227825Stheraven	limit = 0;
2152227825Stheraven	v = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
2153227825Stheraven	for (;;) {
2154227825Stheraven		idx = v->size;
2155227825Stheraven		if (!cpp_demangle_read_tmpl_arg(ddata))
2156227825Stheraven			return (0);
2157227825Stheraven		if ((arg = vector_str_substr(v, idx, v->size - 1, &arg_len)) ==
2158227825Stheraven		    NULL)
2159227825Stheraven			return (0);
2160227825Stheraven		if (!vector_str_find(&ddata->tmpl, arg, arg_len) &&
2161227825Stheraven		    !vector_str_push(&ddata->tmpl, arg, arg_len)) {
2162227825Stheraven			free(arg);
2163227825Stheraven			return (0);
2164227825Stheraven		}
2165227825Stheraven
2166227825Stheraven		free(arg);
2167227825Stheraven
2168227825Stheraven		if (*ddata->cur == 'E') {
2169227825Stheraven			++ddata->cur;
2170227825Stheraven			size = v->size;
2171227825Stheraven			assert(size > 0);
2172227825Stheraven			if (!strncmp(v->container[size - 1], ">", 1)) {
2173227825Stheraven				if (!cpp_demangle_push_str(ddata, " >", 2))
2174227825Stheraven					return (0);
2175227825Stheraven			} else if (!cpp_demangle_push_str(ddata, ">", 1))
2176227825Stheraven				return (0);
2177227825Stheraven			break;
2178227825Stheraven		} else if (*ddata->cur != 'I' &&
2179227825Stheraven		    !cpp_demangle_push_str(ddata, ", ", 2))
2180227825Stheraven			return (0);
2181227825Stheraven
2182227825Stheraven		if (limit++ > CPP_DEMANGLE_TRY_LIMIT)
2183227825Stheraven			return (0);
2184227825Stheraven	}
2185227825Stheraven
2186227825Stheraven	return (vector_read_cmd_pop(&ddata->cmd));
2187227825Stheraven}
2188227825Stheraven
2189227825Stheraven/*
2190227825Stheraven * Read template parameter that forms in 'T[number]_'.
2191227825Stheraven * This function much like to read_subst but only for types.
2192227825Stheraven */
2193227825Stheravenstatic int
2194227825Stheravencpp_demangle_read_tmpl_param(struct cpp_demangle_data *ddata)
2195227825Stheraven{
2196227825Stheraven	long nth;
2197227825Stheraven
2198227825Stheraven	if (ddata == NULL || *ddata->cur != 'T')
2199227825Stheraven		return (0);
2200227825Stheraven
2201227825Stheraven	++ddata->cur;
2202227825Stheraven
2203227825Stheraven	if (*ddata->cur == '_')
2204227825Stheraven		return (cpp_demangle_get_tmpl_param(ddata, 0));
2205227825Stheraven	else {
2206227825Stheraven
2207227825Stheraven		errno = 0;
2208227825Stheraven		if ((nth = strtol(ddata->cur, (char **) NULL, 36)) == 0 &&
2209227825Stheraven		    errno != 0)
2210227825Stheraven			return (0);
2211227825Stheraven
2212227825Stheraven		/* T_ is first */
2213227825Stheraven		++nth;
2214227825Stheraven
2215227825Stheraven		while (*ddata->cur != '_')
2216227825Stheraven			++ddata->cur;
2217227825Stheraven
2218227825Stheraven		assert(nth > 0);
2219227825Stheraven
2220227825Stheraven		return (cpp_demangle_get_tmpl_param(ddata, nth));
2221227825Stheraven	}
2222227825Stheraven
2223227825Stheraven	/* NOTREACHED */
2224227825Stheraven	return (0);
2225227825Stheraven}
2226227825Stheraven
2227227825Stheravenstatic int
2228227825Stheravencpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
2229227825Stheraven{
2230227825Stheraven	struct vector_type_qualifier v;
2231227825Stheraven	struct vector_str *output;
2232227825Stheraven	size_t p_idx, type_str_len;
2233227825Stheraven	int extern_c, is_builtin;
2234227825Stheraven	long len;
2235227825Stheraven	char *type_str;
2236227825Stheraven
2237227825Stheraven	if (ddata == NULL)
2238227825Stheraven		return (0);
2239227825Stheraven
2240227825Stheraven	output = &ddata->output;
2241227825Stheraven	if (ddata->output.size > 0 && !strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) {
2242227825Stheraven		ddata->push_head++;
2243227825Stheraven		output = &ddata->output_tmp;
2244227825Stheraven	} else if (delimit == 1) {
2245227825Stheraven		if (ddata->paren == false) {
2246227825Stheraven			if (!cpp_demangle_push_str(ddata, "(", 1))
2247227825Stheraven				return (0);
2248227825Stheraven			if (ddata->output.size < 2)
2249227825Stheraven				return (0);
2250227825Stheraven			ddata->paren = true;
2251227825Stheraven			ddata->pfirst = true;
2252227825Stheraven			/* Need pop function name */
2253227825Stheraven			if (ddata->subst.size == 1 &&
2254227825Stheraven			    !vector_str_pop(&ddata->subst))
2255227825Stheraven				return (0);
2256227825Stheraven		}
2257227825Stheraven
2258227825Stheraven		if (ddata->pfirst)
2259227825Stheraven			ddata->pfirst = false;
2260227825Stheraven		else if (*ddata->cur != 'I' &&
2261227825Stheraven		    !cpp_demangle_push_str(ddata, ", ", 2))
2262227825Stheraven			return (0);
2263227825Stheraven	}
2264227825Stheraven
2265227825Stheraven	assert(output != NULL);
2266227825Stheraven	/*
2267227825Stheraven	 * [r, V, K] [P, R, C, G, U] builtin, function, class-enum, array
2268227825Stheraven	 * pointer-to-member, template-param, template-template-param, subst
2269227825Stheraven	 */
2270227825Stheraven
2271227825Stheraven	if (!vector_type_qualifier_init(&v))
2272227825Stheraven		return (0);
2273227825Stheraven
2274227825Stheraven	extern_c = 0;
2275227825Stheraven	is_builtin = 1;
2276227825Stheraven	p_idx = output->size;
2277227825Stheraven	type_str = NULL;
2278227825Stheravenagain:
2279227825Stheraven	/* builtin type */
2280227825Stheraven	switch (*ddata->cur) {
2281227825Stheraven	case 'a':
2282227825Stheraven		/* signed char */
2283227825Stheraven		if (!cpp_demangle_push_str(ddata, "signed char", 11))
2284227825Stheraven			goto clean;
2285227825Stheraven		++ddata->cur;
2286227825Stheraven		goto rtn;
2287227825Stheraven
2288227825Stheraven	case 'A':
2289227825Stheraven		/* array type */
2290227825Stheraven		if (!cpp_demangle_read_array(ddata))
2291227825Stheraven			goto clean;
2292227825Stheraven		is_builtin = 0;
2293227825Stheraven		goto rtn;
2294227825Stheraven
2295227825Stheraven	case 'b':
2296227825Stheraven		/* bool */
2297227825Stheraven		if (!cpp_demangle_push_str(ddata, "bool", 4))
2298227825Stheraven			goto clean;
2299227825Stheraven		++ddata->cur;
2300227825Stheraven		goto rtn;
2301227825Stheraven
2302227825Stheraven	case 'C':
2303227825Stheraven		/* complex pair */
2304227825Stheraven		if (!vector_type_qualifier_push(&v, TYPE_CMX))
2305227825Stheraven			goto clean;
2306227825Stheraven		++ddata->cur;
2307227825Stheraven		goto again;
2308227825Stheraven
2309227825Stheraven	case 'c':
2310227825Stheraven		/* char */
2311227825Stheraven		if (!cpp_demangle_push_str(ddata, "char", 4))
2312227825Stheraven			goto clean;
2313227825Stheraven		++ddata->cur;
2314227825Stheraven		goto rtn;
2315227825Stheraven
2316227825Stheraven	case 'd':
2317227825Stheraven		/* double */
2318227825Stheraven		if (!cpp_demangle_push_str(ddata, "double", 6))
2319227825Stheraven			goto clean;
2320227825Stheraven		++ddata->cur;
2321227825Stheraven		goto rtn;
2322227825Stheraven
2323227825Stheraven	case 'e':
2324227825Stheraven		/* long double */
2325227825Stheraven		if (!cpp_demangle_push_str(ddata, "long double", 11))
2326227825Stheraven			goto clean;
2327227825Stheraven		++ddata->cur;
2328227825Stheraven		goto rtn;
2329227825Stheraven
2330227825Stheraven	case 'f':
2331227825Stheraven		/* float */
2332227825Stheraven		if (!cpp_demangle_push_str(ddata, "float", 5))
2333227825Stheraven			goto clean;
2334227825Stheraven		++ddata->cur;
2335227825Stheraven		goto rtn;
2336227825Stheraven
2337227825Stheraven	case 'F':
2338227825Stheraven		/* function */
2339227825Stheraven		if (!cpp_demangle_read_function(ddata, &extern_c, &v))
2340227825Stheraven			goto clean;
2341227825Stheraven		is_builtin = 0;
2342227825Stheraven		goto rtn;
2343227825Stheraven
2344227825Stheraven	case 'g':
2345227825Stheraven		/* __float128 */
2346227825Stheraven		if (!cpp_demangle_push_str(ddata, "__float128", 10))
2347227825Stheraven			goto clean;
2348227825Stheraven		++ddata->cur;
2349227825Stheraven		goto rtn;
2350227825Stheraven
2351227825Stheraven	case 'G':
2352227825Stheraven		/* imaginary */
2353227825Stheraven		if (!vector_type_qualifier_push(&v, TYPE_IMG))
2354227825Stheraven			goto clean;
2355227825Stheraven		++ddata->cur;
2356227825Stheraven		goto again;
2357227825Stheraven
2358227825Stheraven	case 'h':
2359227825Stheraven		/* unsigned char */
2360227825Stheraven		if (!cpp_demangle_push_str(ddata, "unsigned char", 13))
2361227825Stheraven			goto clean;
2362227825Stheraven		++ddata->cur;
2363227825Stheraven		goto rtn;
2364227825Stheraven
2365227825Stheraven	case 'i':
2366227825Stheraven		/* int */
2367227825Stheraven		if (!cpp_demangle_push_str(ddata, "int", 3))
2368227825Stheraven			goto clean;
2369227825Stheraven		++ddata->cur;
2370227825Stheraven		goto rtn;
2371227825Stheraven
2372227825Stheraven	case 'j':
2373227825Stheraven		/* unsigned int */
2374227825Stheraven		if (!cpp_demangle_push_str(ddata, "unsigned int", 12))
2375227825Stheraven			goto clean;
2376227825Stheraven		++ddata->cur;
2377227825Stheraven		goto rtn;
2378227825Stheraven
2379227825Stheraven	case 'K':
2380227825Stheraven		/* const */
2381227825Stheraven		if (!vector_type_qualifier_push(&v, TYPE_CST))
2382227825Stheraven			goto clean;
2383227825Stheraven		++ddata->cur;
2384227825Stheraven		goto again;
2385227825Stheraven
2386227825Stheraven	case 'l':
2387227825Stheraven		/* long */
2388227825Stheraven		if (!cpp_demangle_push_str(ddata, "long", 4))
2389227825Stheraven			goto clean;
2390227825Stheraven		++ddata->cur;
2391227825Stheraven		goto rtn;
2392227825Stheraven
2393227825Stheraven	case 'm':
2394227825Stheraven		/* unsigned long */
2395227825Stheraven		if (!cpp_demangle_push_str(ddata, "unsigned long", 13))
2396227825Stheraven			goto clean;
2397227825Stheraven
2398227825Stheraven		++ddata->cur;
2399227825Stheraven
2400227825Stheraven		goto rtn;
2401227825Stheraven	case 'M':
2402227825Stheraven		/* pointer to member */
2403227825Stheraven		if (!cpp_demangle_read_pointer_to_member(ddata))
2404227825Stheraven			goto clean;
2405227825Stheraven		is_builtin = 0;
2406227825Stheraven		goto rtn;
2407227825Stheraven
2408227825Stheraven	case 'n':
2409227825Stheraven		/* __int128 */
2410227825Stheraven		if (!cpp_demangle_push_str(ddata, "__int128", 8))
2411227825Stheraven			goto clean;
2412227825Stheraven		++ddata->cur;
2413227825Stheraven		goto rtn;
2414227825Stheraven
2415227825Stheraven	case 'o':
2416227825Stheraven		/* unsigned __int128 */
2417227825Stheraven		if (!cpp_demangle_push_str(ddata, "unsigned _;int128", 17))
2418227825Stheraven			goto clean;
2419227825Stheraven		++ddata->cur;
2420227825Stheraven		goto rtn;
2421227825Stheraven
2422227825Stheraven	case 'P':
2423227825Stheraven		/* pointer */
2424227825Stheraven		if (!vector_type_qualifier_push(&v, TYPE_PTR))
2425227825Stheraven			goto clean;
2426227825Stheraven		++ddata->cur;
2427227825Stheraven		goto again;
2428227825Stheraven
2429227825Stheraven	case 'r':
2430227825Stheraven		/* restrict */
2431227825Stheraven		if (!vector_type_qualifier_push(&v, TYPE_RST))
2432227825Stheraven			goto clean;
2433227825Stheraven		++ddata->cur;
2434227825Stheraven		goto again;
2435227825Stheraven
2436227825Stheraven	case 'R':
2437227825Stheraven		/* reference */
2438227825Stheraven		if (!vector_type_qualifier_push(&v, TYPE_REF))
2439227825Stheraven			goto clean;
2440227825Stheraven		++ddata->cur;
2441227825Stheraven		goto again;
2442227825Stheraven
2443227825Stheraven	case 's':
2444227825Stheraven		/* short, local string */
2445227825Stheraven		if (!cpp_demangle_push_str(ddata, "short", 5))
2446227825Stheraven			goto clean;
2447227825Stheraven		++ddata->cur;
2448227825Stheraven		goto rtn;
2449227825Stheraven
2450227825Stheraven	case 'S':
2451227825Stheraven		/* substitution */
2452227825Stheraven		if (!cpp_demangle_read_subst(ddata))
2453227825Stheraven			goto clean;
2454227825Stheraven		is_builtin = 0;
2455227825Stheraven		goto rtn;
2456227825Stheraven
2457227825Stheraven	case 't':
2458227825Stheraven		/* unsigned short */
2459227825Stheraven		if (!cpp_demangle_push_str(ddata, "unsigned short", 14))
2460227825Stheraven			goto clean;
2461227825Stheraven		++ddata->cur;
2462227825Stheraven		goto rtn;
2463227825Stheraven
2464227825Stheraven	case 'T':
2465227825Stheraven		/* template parameter */
2466227825Stheraven		if (!cpp_demangle_read_tmpl_param(ddata))
2467227825Stheraven			goto clean;
2468227825Stheraven		is_builtin = 0;
2469227825Stheraven		goto rtn;
2470227825Stheraven
2471227825Stheraven	case 'u':
2472227825Stheraven		/* vendor extended builtin */
2473227825Stheraven		++ddata->cur;
2474227825Stheraven		if (!cpp_demangle_read_sname(ddata))
2475227825Stheraven			goto clean;
2476227825Stheraven		is_builtin = 0;
2477227825Stheraven		goto rtn;
2478227825Stheraven
2479227825Stheraven	case 'U':
2480227825Stheraven		/* vendor extended type qualifier */
2481227825Stheraven		if (!cpp_demangle_read_number(ddata, &len))
2482227825Stheraven			goto clean;
2483227825Stheraven		if (len <= 0)
2484227825Stheraven			goto clean;
2485227825Stheraven		if (!vector_str_push(&v.ext_name, ddata->cur, len))
2486227825Stheraven			return (0);
2487227825Stheraven		ddata->cur += len;
2488227825Stheraven		goto again;
2489227825Stheraven
2490227825Stheraven	case 'v':
2491227825Stheraven		/* void */
2492227825Stheraven		if (!cpp_demangle_push_str(ddata, "void", 4))
2493227825Stheraven			goto clean;
2494227825Stheraven		++ddata->cur;
2495227825Stheraven		goto rtn;
2496227825Stheraven
2497227825Stheraven	case 'V':
2498227825Stheraven		/* volatile */
2499227825Stheraven		if (!vector_type_qualifier_push(&v, TYPE_VAT))
2500227825Stheraven			goto clean;
2501227825Stheraven		++ddata->cur;
2502227825Stheraven		goto again;
2503227825Stheraven
2504227825Stheraven	case 'w':
2505227825Stheraven		/* wchar_t */
2506227825Stheraven		if (!cpp_demangle_push_str(ddata, "wchar_t", 6))
2507227825Stheraven			goto clean;
2508227825Stheraven		++ddata->cur;
2509227825Stheraven		goto rtn;
2510227825Stheraven
2511227825Stheraven	case 'x':
2512227825Stheraven		/* long long */
2513227825Stheraven		if (!cpp_demangle_push_str(ddata, "long long", 9))
2514227825Stheraven			goto clean;
2515227825Stheraven		++ddata->cur;
2516227825Stheraven		goto rtn;
2517227825Stheraven
2518227825Stheraven	case 'y':
2519227825Stheraven		/* unsigned long long */
2520227825Stheraven		if (!cpp_demangle_push_str(ddata, "unsigned long long", 18))
2521227825Stheraven			goto clean;
2522227825Stheraven		++ddata->cur;
2523227825Stheraven		goto rtn;
2524227825Stheraven
2525227825Stheraven	case 'z':
2526227825Stheraven		/* ellipsis */
2527227825Stheraven		if (!cpp_demangle_push_str(ddata, "ellipsis", 8))
2528227825Stheraven			goto clean;
2529227825Stheraven		++ddata->cur;
2530227825Stheraven		goto rtn;
2531227825Stheraven	};
2532227825Stheraven
2533227825Stheraven	if (!cpp_demangle_read_name(ddata))
2534227825Stheraven		goto clean;
2535227825Stheraven
2536227825Stheraven	is_builtin = 0;
2537227825Stheravenrtn:
2538227825Stheraven	if ((type_str = vector_str_substr(output, p_idx, output->size - 1,
2539227825Stheraven	    &type_str_len)) == NULL)
2540227825Stheraven		goto clean;
2541227825Stheraven
2542227825Stheraven	if (is_builtin == 0) {
2543227825Stheraven		if (!vector_str_find(&ddata->subst, type_str, type_str_len) &&
2544227825Stheraven		    !vector_str_push(&ddata->subst, type_str, type_str_len))
2545227825Stheraven			goto clean;
2546227825Stheraven	}
2547227825Stheraven
2548227825Stheraven	if (!cpp_demangle_push_type_qualifier(ddata, &v, type_str))
2549227825Stheraven		goto clean;
2550227825Stheraven
2551227825Stheraven	free(type_str);
2552227825Stheraven	vector_type_qualifier_dest(&v);
2553227825Stheraven
2554227825Stheraven	if (ddata->push_head > 0) {
2555227825Stheraven		if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata)
2556227825Stheraven		    == 0)
2557227825Stheraven			return (0);
2558227825Stheraven
2559227825Stheraven		if (--ddata->push_head > 0)
2560227825Stheraven			return (1);
2561227825Stheraven
2562227825Stheraven		if (!vector_str_push(&ddata->output_tmp, " ", 1))
2563227825Stheraven			return (0);
2564227825Stheraven
2565227825Stheraven		if (!vector_str_push_vector_head(&ddata->output,
2566227825Stheraven		    &ddata->output_tmp))
2567227825Stheraven			return (0);
2568227825Stheraven
2569227825Stheraven		vector_str_dest(&ddata->output_tmp);
2570227825Stheraven		if (!vector_str_init(&ddata->output_tmp))
2571227825Stheraven			return (0);
2572227825Stheraven
2573227825Stheraven		if (!cpp_demangle_push_str(ddata, "(", 1))
2574227825Stheraven			return (0);
2575227825Stheraven
2576227825Stheraven		ddata->paren = true;
2577227825Stheraven		ddata->pfirst = true;
2578227825Stheraven	}
2579227825Stheraven
2580227825Stheraven	return (1);
2581227825Stheravenclean:
2582227825Stheraven	free(type_str);
2583227825Stheraven	vector_type_qualifier_dest(&v);
2584227825Stheraven
2585227825Stheraven	return (0);
2586227825Stheraven}
2587227825Stheraven
2588227825Stheraven/*
2589227825Stheraven * read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
2590227825Stheraven * source-name
2591227825Stheraven */
2592227825Stheravenstatic int
2593227825Stheravencpp_demangle_read_uqname(struct cpp_demangle_data *ddata)
2594227825Stheraven{
2595227825Stheraven	size_t len;
2596227825Stheraven
2597227825Stheraven	if (ddata == NULL || *ddata->cur == '\0')
2598227825Stheraven		return (0);
2599227825Stheraven
2600227825Stheraven	/* operator name */
2601227825Stheraven	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
2602227825Stheraven	case SIMPLE_HASH('a', 'a'):
2603227825Stheraven		/* operator && */
2604227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator&&", 10))
2605227825Stheraven			return (0);
2606227825Stheraven		ddata->cur += 2;
2607227825Stheraven		return (1);
2608227825Stheraven
2609227825Stheraven	case SIMPLE_HASH('a', 'd'):
2610227825Stheraven		/* operator & (unary) */
2611227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator&", 9))
2612227825Stheraven			return (0);
2613227825Stheraven		ddata->cur += 2;
2614227825Stheraven		return (1);
2615227825Stheraven
2616227825Stheraven	case SIMPLE_HASH('a', 'n'):
2617227825Stheraven		/* operator & */
2618227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator&", 9))
2619227825Stheraven			return (0);
2620227825Stheraven		ddata->cur += 2;
2621227825Stheraven		return (1);
2622227825Stheraven
2623227825Stheraven	case SIMPLE_HASH('a', 'N'):
2624227825Stheraven		/* operator &= */
2625227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator&=", 10))
2626227825Stheraven			return (0);
2627227825Stheraven		ddata->cur += 2;
2628227825Stheraven		return (1);
2629227825Stheraven
2630227825Stheraven	case SIMPLE_HASH('a', 'S'):
2631227825Stheraven		/* operator = */
2632227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator=", 9))
2633227825Stheraven			return (0);
2634227825Stheraven		ddata->cur += 2;
2635227825Stheraven		return (1);
2636227825Stheraven
2637227825Stheraven	case SIMPLE_HASH('c', 'l'):
2638227825Stheraven		/* operator () */
2639227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator()", 10))
2640227825Stheraven			return (0);
2641227825Stheraven		ddata->cur += 2;
2642227825Stheraven		return (1);
2643227825Stheraven
2644227825Stheraven	case SIMPLE_HASH('c', 'm'):
2645227825Stheraven		/* operator , */
2646227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator,", 9))
2647227825Stheraven			return (0);
2648227825Stheraven		ddata->cur += 2;
2649227825Stheraven		return (1);
2650227825Stheraven
2651227825Stheraven	case SIMPLE_HASH('c', 'o'):
2652227825Stheraven		/* operator ~ */
2653227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator~", 9))
2654227825Stheraven			return (0);
2655227825Stheraven		ddata->cur += 2;
2656227825Stheraven		return (1);
2657227825Stheraven
2658227825Stheraven	case SIMPLE_HASH('c', 'v'):
2659227825Stheraven		/* operator (cast) */
2660227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator(cast)", 14))
2661227825Stheraven			return (0);
2662227825Stheraven		ddata->cur += 2;
2663227825Stheraven		return (cpp_demangle_read_type(ddata, 1));
2664227825Stheraven
2665227825Stheraven	case SIMPLE_HASH('d', 'a'):
2666227825Stheraven		/* operator delete [] */
2667227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator delete []", 18))
2668227825Stheraven			return (0);
2669227825Stheraven		ddata->cur += 2;
2670227825Stheraven		return (1);
2671227825Stheraven
2672227825Stheraven	case SIMPLE_HASH('d', 'e'):
2673227825Stheraven		/* operator * (unary) */
2674227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator*", 9))
2675227825Stheraven			return (0);
2676227825Stheraven		ddata->cur += 2;
2677227825Stheraven		return (1);
2678227825Stheraven
2679227825Stheraven	case SIMPLE_HASH('d', 'l'):
2680227825Stheraven		/* operator delete */
2681227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator delete", 15))
2682227825Stheraven			return (0);
2683227825Stheraven		ddata->cur += 2;
2684227825Stheraven		return (1);
2685227825Stheraven
2686227825Stheraven	case SIMPLE_HASH('d', 'v'):
2687227825Stheraven		/* operator / */
2688227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator/", 9))
2689227825Stheraven			return (0);
2690227825Stheraven		ddata->cur += 2;
2691227825Stheraven		return (1);
2692227825Stheraven
2693227825Stheraven	case SIMPLE_HASH('d', 'V'):
2694227825Stheraven		/* operator /= */
2695227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator/=", 10))
2696227825Stheraven			return (0);
2697227825Stheraven		ddata->cur += 2;
2698227825Stheraven		return (1);
2699227825Stheraven
2700227825Stheraven	case SIMPLE_HASH('e', 'o'):
2701227825Stheraven		/* operator ^ */
2702227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator^", 9))
2703227825Stheraven			return (0);
2704227825Stheraven		ddata->cur += 2;
2705227825Stheraven		return (1);
2706227825Stheraven
2707227825Stheraven	case SIMPLE_HASH('e', 'O'):
2708227825Stheraven		/* operator ^= */
2709227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator^=", 10))
2710227825Stheraven			return (0);
2711227825Stheraven		ddata->cur += 2;
2712227825Stheraven		return (1);
2713227825Stheraven
2714227825Stheraven	case SIMPLE_HASH('e', 'q'):
2715227825Stheraven		/* operator == */
2716227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator==", 10))
2717227825Stheraven			return (0);
2718227825Stheraven		ddata->cur += 2;
2719227825Stheraven		return (1);
2720227825Stheraven
2721227825Stheraven	case SIMPLE_HASH('g', 'e'):
2722227825Stheraven		/* operator >= */
2723227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator>=", 10))
2724227825Stheraven			return (0);
2725227825Stheraven		ddata->cur += 2;
2726227825Stheraven		return (1);
2727227825Stheraven
2728227825Stheraven	case SIMPLE_HASH('g', 't'):
2729227825Stheraven		/* operator > */
2730227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator>", 9))
2731227825Stheraven			return (0);
2732227825Stheraven		ddata->cur += 2;
2733227825Stheraven		return (1);
2734227825Stheraven
2735227825Stheraven	case SIMPLE_HASH('i', 'x'):
2736227825Stheraven		/* operator [] */
2737227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator[]", 10))
2738227825Stheraven			return (0);
2739227825Stheraven		ddata->cur += 2;
2740227825Stheraven		return (1);
2741227825Stheraven
2742227825Stheraven	case SIMPLE_HASH('l', 'e'):
2743227825Stheraven		/* operator <= */
2744227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator<=", 10))
2745227825Stheraven			return (0);
2746227825Stheraven		ddata->cur += 2;
2747227825Stheraven		return (1);
2748227825Stheraven
2749227825Stheraven	case SIMPLE_HASH('l', 's'):
2750227825Stheraven		/* operator << */
2751227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator<<", 10))
2752227825Stheraven			return (0);
2753227825Stheraven		ddata->cur += 2;
2754227825Stheraven		return (1);
2755227825Stheraven
2756227825Stheraven	case SIMPLE_HASH('l', 'S'):
2757227825Stheraven		/* operator <<= */
2758227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator<<=", 11))
2759227825Stheraven			return (0);
2760227825Stheraven		ddata->cur += 2;
2761227825Stheraven		return (1);
2762227825Stheraven
2763227825Stheraven	case SIMPLE_HASH('l', 't'):
2764227825Stheraven		/* operator < */
2765227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator<", 9))
2766227825Stheraven			return (0);
2767227825Stheraven		ddata->cur += 2;
2768227825Stheraven		return (1);
2769227825Stheraven
2770227825Stheraven	case SIMPLE_HASH('m', 'i'):
2771227825Stheraven		/* operator - */
2772227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator-", 9))
2773227825Stheraven			return (0);
2774227825Stheraven		ddata->cur += 2;
2775227825Stheraven		return (1);
2776227825Stheraven
2777227825Stheraven	case SIMPLE_HASH('m', 'I'):
2778227825Stheraven		/* operator -= */
2779227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator-=", 10))
2780227825Stheraven			return (0);
2781227825Stheraven		ddata->cur += 2;
2782227825Stheraven		return (1);
2783227825Stheraven
2784227825Stheraven	case SIMPLE_HASH('m', 'l'):
2785227825Stheraven		/* operator * */
2786227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator*", 9))
2787227825Stheraven			return (0);
2788227825Stheraven		ddata->cur += 2;
2789227825Stheraven		return (1);
2790227825Stheraven
2791227825Stheraven	case SIMPLE_HASH('m', 'L'):
2792227825Stheraven		/* operator *= */
2793227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator*=", 10))
2794227825Stheraven			return (0);
2795227825Stheraven		ddata->cur += 2;
2796227825Stheraven		return (1);
2797227825Stheraven
2798227825Stheraven	case SIMPLE_HASH('m', 'm'):
2799227825Stheraven		/* operator -- */
2800227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator--", 10))
2801227825Stheraven			return (0);
2802227825Stheraven		ddata->cur += 2;
2803227825Stheraven		return (1);
2804227825Stheraven
2805227825Stheraven	case SIMPLE_HASH('n', 'a'):
2806227825Stheraven		/* operator new[] */
2807227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator new []", 15))
2808227825Stheraven			return (0);
2809227825Stheraven		ddata->cur += 2;
2810227825Stheraven		return (1);
2811227825Stheraven
2812227825Stheraven	case SIMPLE_HASH('n', 'e'):
2813227825Stheraven		/* operator != */
2814227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator!=", 10))
2815227825Stheraven			return (0);
2816227825Stheraven		ddata->cur += 2;
2817227825Stheraven		return (1);
2818227825Stheraven
2819227825Stheraven	case SIMPLE_HASH('n', 'g'):
2820227825Stheraven		/* operator - (unary) */
2821227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator-", 9))
2822227825Stheraven			return (0);
2823227825Stheraven		ddata->cur += 2;
2824227825Stheraven		return (1);
2825227825Stheraven
2826227825Stheraven	case SIMPLE_HASH('n', 't'):
2827227825Stheraven		/* operator ! */
2828227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator!", 9))
2829227825Stheraven			return (0);
2830227825Stheraven		ddata->cur += 2;
2831227825Stheraven		return (1);
2832227825Stheraven
2833227825Stheraven	case SIMPLE_HASH('n', 'w'):
2834227825Stheraven		/* operator new */
2835227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator new", 12))
2836227825Stheraven			return (0);
2837227825Stheraven		ddata->cur += 2;
2838227825Stheraven		return (1);
2839227825Stheraven
2840227825Stheraven	case SIMPLE_HASH('o', 'o'):
2841227825Stheraven		/* operator || */
2842227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator||", 10))
2843227825Stheraven			return (0);
2844227825Stheraven		ddata->cur += 2;
2845227825Stheraven		return (1);
2846227825Stheraven
2847227825Stheraven	case SIMPLE_HASH('o', 'r'):
2848227825Stheraven		/* operator | */
2849227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator|", 9))
2850227825Stheraven			return (0);
2851227825Stheraven		ddata->cur += 2;
2852227825Stheraven		return (1);
2853227825Stheraven
2854227825Stheraven	case SIMPLE_HASH('o', 'R'):
2855227825Stheraven		/* operator |= */
2856227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator|=", 10))
2857227825Stheraven			return (0);
2858227825Stheraven		ddata->cur += 2;
2859227825Stheraven		return (1);
2860227825Stheraven
2861227825Stheraven	case SIMPLE_HASH('p', 'l'):
2862227825Stheraven		/* operator + */
2863227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator+", 9))
2864227825Stheraven			return (0);
2865227825Stheraven		ddata->cur += 2;
2866227825Stheraven		return (1);
2867227825Stheraven
2868227825Stheraven	case SIMPLE_HASH('p', 'L'):
2869227825Stheraven		/* operator += */
2870227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator+=", 10))
2871227825Stheraven			return (0);
2872227825Stheraven		ddata->cur += 2;
2873227825Stheraven		return (1);
2874227825Stheraven
2875227825Stheraven	case SIMPLE_HASH('p', 'm'):
2876227825Stheraven		/* operator ->* */
2877227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator->*", 11))
2878227825Stheraven			return (0);
2879227825Stheraven		ddata->cur += 2;
2880227825Stheraven		return (1);
2881227825Stheraven
2882227825Stheraven	case SIMPLE_HASH('p', 'p'):
2883227825Stheraven		/* operator ++ */
2884227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator++", 10))
2885227825Stheraven			return (0);
2886227825Stheraven		ddata->cur += 2;
2887227825Stheraven		return (1);
2888227825Stheraven
2889227825Stheraven	case SIMPLE_HASH('p', 's'):
2890227825Stheraven		/* operator + (unary) */
2891227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator+", 9))
2892227825Stheraven			return (0);
2893227825Stheraven		ddata->cur += 2;
2894227825Stheraven		return (1);
2895227825Stheraven
2896227825Stheraven	case SIMPLE_HASH('p', 't'):
2897227825Stheraven		/* operator -> */
2898227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator->", 10))
2899227825Stheraven			return (0);
2900227825Stheraven		ddata->cur += 2;
2901227825Stheraven		return (1);
2902227825Stheraven
2903227825Stheraven	case SIMPLE_HASH('q', 'u'):
2904227825Stheraven		/* operator ? */
2905227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator?", 9))
2906227825Stheraven			return (0);
2907227825Stheraven		ddata->cur += 2;
2908227825Stheraven		return (1);
2909227825Stheraven
2910227825Stheraven	case SIMPLE_HASH('r', 'm'):
2911227825Stheraven		/* operator % */
2912227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator%", 9))
2913227825Stheraven			return (0);
2914227825Stheraven		ddata->cur += 2;
2915227825Stheraven		return (1);
2916227825Stheraven
2917227825Stheraven	case SIMPLE_HASH('r', 'M'):
2918227825Stheraven		/* operator %= */
2919227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator%=", 10))
2920227825Stheraven			return (0);
2921227825Stheraven		ddata->cur += 2;
2922227825Stheraven		return (1);
2923227825Stheraven
2924227825Stheraven	case SIMPLE_HASH('r', 's'):
2925227825Stheraven		/* operator >> */
2926227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator>>", 10))
2927227825Stheraven			return (0);
2928227825Stheraven		ddata->cur += 2;
2929227825Stheraven		return (1);
2930227825Stheraven
2931227825Stheraven	case SIMPLE_HASH('r', 'S'):
2932227825Stheraven		/* operator >>= */
2933227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator>>=", 11))
2934227825Stheraven			return (0);
2935227825Stheraven		ddata->cur += 2;
2936227825Stheraven		return (1);
2937227825Stheraven
2938227825Stheraven	case SIMPLE_HASH('r', 'z'):
2939227825Stheraven		/* operator sizeof */
2940227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16))
2941227825Stheraven			return (0);
2942227825Stheraven		ddata->cur += 2;
2943227825Stheraven		return (1);
2944227825Stheraven
2945227825Stheraven	case SIMPLE_HASH('s', 'r'):
2946227825Stheraven		/* scope resolution operator */
2947227825Stheraven		if (!cpp_demangle_push_str(ddata, "scope resolution operator ",
2948227825Stheraven		    26))
2949227825Stheraven			return (0);
2950227825Stheraven		ddata->cur += 2;
2951227825Stheraven		return (1);
2952227825Stheraven
2953227825Stheraven	case SIMPLE_HASH('s', 'v'):
2954227825Stheraven		/* operator sizeof */
2955227825Stheraven		if (!cpp_demangle_push_str(ddata, "operator sizeof ", 16))
2956227825Stheraven			return (0);
2957227825Stheraven		ddata->cur += 2;
2958227825Stheraven		return (1);
2959227825Stheraven	};
2960227825Stheraven
2961227825Stheraven	/* vendor extened operator */
2962227825Stheraven	if (*ddata->cur == 'v' && ELFTC_ISDIGIT(*(ddata->cur + 1))) {
2963227825Stheraven		if (!cpp_demangle_push_str(ddata, "vendor extened operator ",
2964227825Stheraven		    24))
2965227825Stheraven			return (0);
2966227825Stheraven		if (!cpp_demangle_push_str(ddata, ddata->cur + 1, 1))
2967227825Stheraven			return (0);
2968227825Stheraven		ddata->cur += 2;
2969227825Stheraven		return (cpp_demangle_read_sname(ddata));
2970227825Stheraven	}
2971227825Stheraven
2972227825Stheraven	/* ctor-dtor-name */
2973227825Stheraven	switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
2974227825Stheraven	case SIMPLE_HASH('C', '1'):
2975227825Stheraven		/* FALLTHROUGH */
2976227825Stheraven	case SIMPLE_HASH('C', '2'):
2977227825Stheraven		/* FALLTHROUGH */
2978227825Stheraven	case SIMPLE_HASH('C', '3'):
2979227825Stheraven		if (ddata->last_sname == NULL)
2980227825Stheraven			return (0);
2981227825Stheraven		if ((len = strlen(ddata->last_sname)) == 0)
2982227825Stheraven			return (0);
2983227825Stheraven		if (!cpp_demangle_push_str(ddata, "::", 2))
2984227825Stheraven			return (0);
2985227825Stheraven		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
2986227825Stheraven			return (0);
2987227825Stheraven		ddata->cur +=2;
2988227825Stheraven		return (1);
2989227825Stheraven
2990227825Stheraven	case SIMPLE_HASH('D', '0'):
2991227825Stheraven		/* FALLTHROUGH */
2992227825Stheraven	case SIMPLE_HASH('D', '1'):
2993227825Stheraven		/* FALLTHROUGH */
2994227825Stheraven	case SIMPLE_HASH('D', '2'):
2995227825Stheraven		if (ddata->last_sname == NULL)
2996227825Stheraven			return (0);
2997227825Stheraven		if ((len = strlen(ddata->last_sname)) == 0)
2998227825Stheraven			return (0);
2999227825Stheraven		if (!cpp_demangle_push_str(ddata, "::~", 3))
3000227825Stheraven			return (0);
3001227825Stheraven		if (!cpp_demangle_push_str(ddata, ddata->last_sname, len))
3002227825Stheraven			return (0);
3003227825Stheraven		ddata->cur +=2;
3004227825Stheraven		return (1);
3005227825Stheraven	};
3006227825Stheraven
3007227825Stheraven	/* source name */
3008227825Stheraven	if (ELFTC_ISDIGIT(*ddata->cur) != 0)
3009227825Stheraven		return (cpp_demangle_read_sname(ddata));
3010227825Stheraven
3011255815Stheraven
3012255815Stheraven	/* local source name */
3013255815Stheraven	if (*ddata->cur == 'L')
3014255815Stheraven		return (cpp_demangle_local_source_name(ddata));
3015255815Stheraven
3016255815Stheraven	return (1);
3017255815Stheraven}
3018255815Stheraven
3019255815Stheraven/*
3020255815Stheraven * Read local source name.
3021255815Stheraven *
3022255815Stheraven * References:
3023255815Stheraven *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
3024255815Stheraven *   http://gcc.gnu.org/viewcvs?view=rev&revision=124467
3025255815Stheraven */
3026255815Stheravenstatic int
3027255815Stheravencpp_demangle_local_source_name(struct cpp_demangle_data *ddata)
3028255815Stheraven{
3029255815Stheraven	/* L */
3030255815Stheraven	if (ddata == NULL || *ddata->cur != 'L')
3031255815Stheraven		return (0);
3032255815Stheraven	++ddata->cur;
3033255815Stheraven
3034255815Stheraven	/* source name */
3035255815Stheraven	if (!cpp_demangle_read_sname(ddata))
3036255815Stheraven		return (0);
3037255815Stheraven
3038255815Stheraven	/* discriminator */
3039255815Stheraven	if (*ddata->cur == '_') {
3040255815Stheraven		++ddata->cur;
3041255815Stheraven		while (ELFTC_ISDIGIT(*ddata->cur) != 0)
3042255815Stheraven			++ddata->cur;
3043255815Stheraven	}
3044255815Stheraven
3045227825Stheraven	return (1);
3046227825Stheraven}
3047227825Stheraven
3048227825Stheravenstatic int
3049227825Stheravencpp_demangle_read_v_offset(struct cpp_demangle_data *ddata)
3050227825Stheraven{
3051227825Stheraven
3052227825Stheraven	if (ddata == NULL)
3053227825Stheraven		return (0);
3054227825Stheraven
3055227825Stheraven	if (!cpp_demangle_push_str(ddata, "offset : ", 9))
3056227825Stheraven		return (0);
3057227825Stheraven
3058227825Stheraven	if (!cpp_demangle_read_offset_number(ddata))
3059227825Stheraven		return (0);
3060227825Stheraven
3061227825Stheraven	if (!cpp_demangle_push_str(ddata, "virtual offset : ", 17))
3062227825Stheraven		return (0);
3063227825Stheraven
3064227825Stheraven	return (!cpp_demangle_read_offset_number(ddata));
3065227825Stheraven}
3066227825Stheraven
3067227825Stheraven/*
3068227825Stheraven * Decode floating point representation to string
3069227825Stheraven * Return new allocated string or NULL
3070227825Stheraven *
3071227825Stheraven * Todo
3072227825Stheraven * Replace these functions to macro.
3073227825Stheraven */
3074227825Stheravenstatic char *
3075227825Stheravendecode_fp_to_double(const char *p, size_t len)
3076227825Stheraven{
3077227825Stheraven	double f;
3078227825Stheraven	size_t rtn_len, limit, i;
3079227825Stheraven	int byte;
3080227825Stheraven	char *rtn;
3081227825Stheraven
3082227825Stheraven	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(double))
3083227825Stheraven		return (NULL);
3084227825Stheraven
3085227825Stheraven	memset(&f, 0, sizeof(double));
3086227825Stheraven
3087227825Stheraven	for (i = 0; i < len / 2; ++i) {
3088227825Stheraven		byte = hex_to_dec(p[len - i * 2 - 1]) +
3089227825Stheraven		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3090227825Stheraven
3091227825Stheraven		if (byte < 0 || byte > 255)
3092227825Stheraven			return (NULL);
3093227825Stheraven
3094227825Stheraven#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3095227825Stheraven		((unsigned char *)&f)[i] = (unsigned char)(byte);
3096227825Stheraven#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3097227825Stheraven		((unsigned char *)&f)[sizeof(double) - i - 1] =
3098227825Stheraven		    (unsigned char)(byte);
3099227825Stheraven#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3100227825Stheraven	}
3101227825Stheraven
3102227825Stheraven	rtn_len = 64;
3103227825Stheraven	limit = 0;
3104227825Stheravenagain:
3105227825Stheraven	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3106227825Stheraven		return (NULL);
3107227825Stheraven
3108227825Stheraven	if (snprintf(rtn, rtn_len, "%fld", f) >= (int)rtn_len) {
3109227825Stheraven		free(rtn);
3110227825Stheraven		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3111227825Stheraven			return (NULL);
3112227825Stheraven		rtn_len *= BUFFER_GROWFACTOR;
3113227825Stheraven		goto again;
3114227825Stheraven	}
3115227825Stheraven
3116227825Stheraven	return rtn;
3117227825Stheraven}
3118227825Stheraven
3119227825Stheravenstatic char *
3120227825Stheravendecode_fp_to_float(const char *p, size_t len)
3121227825Stheraven{
3122227825Stheraven	size_t i, rtn_len, limit;
3123227825Stheraven	float f;
3124227825Stheraven	int byte;
3125227825Stheraven	char *rtn;
3126227825Stheraven
3127227825Stheraven	if (p == NULL || len == 0 || len % 2 != 0 || len / 2 > sizeof(float))
3128227825Stheraven		return (NULL);
3129227825Stheraven
3130227825Stheraven	memset(&f, 0, sizeof(float));
3131227825Stheraven
3132227825Stheraven	for (i = 0; i < len / 2; ++i) {
3133227825Stheraven		byte = hex_to_dec(p[len - i * 2 - 1]) +
3134227825Stheraven		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3135227825Stheraven		if (byte < 0 || byte > 255)
3136227825Stheraven			return (NULL);
3137227825Stheraven#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3138227825Stheraven		((unsigned char *)&f)[i] = (unsigned char)(byte);
3139227825Stheraven#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3140227825Stheraven		((unsigned char *)&f)[sizeof(float) - i - 1] =
3141227825Stheraven		    (unsigned char)(byte);
3142227825Stheraven#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3143227825Stheraven	}
3144227825Stheraven
3145227825Stheraven	rtn_len = 64;
3146227825Stheraven	limit = 0;
3147227825Stheravenagain:
3148227825Stheraven	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3149227825Stheraven		return (NULL);
3150227825Stheraven
3151227825Stheraven	if (snprintf(rtn, rtn_len, "%ff", f) >= (int)rtn_len) {
3152227825Stheraven		free(rtn);
3153227825Stheraven		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3154227825Stheraven			return (NULL);
3155227825Stheraven		rtn_len *= BUFFER_GROWFACTOR;
3156227825Stheraven		goto again;
3157227825Stheraven	}
3158227825Stheraven
3159227825Stheraven	return rtn;
3160227825Stheraven}
3161227825Stheraven
3162227825Stheravenstatic char *
3163227825Stheravendecode_fp_to_float128(const char *p, size_t len)
3164227825Stheraven{
3165227825Stheraven	long double f;
3166227825Stheraven	size_t rtn_len, limit, i;
3167227825Stheraven	int byte;
3168227825Stheraven	unsigned char buf[FLOAT_QUADRUPLE_BYTES];
3169227825Stheraven	char *rtn;
3170227825Stheraven
3171227825Stheraven	switch(sizeof(long double)) {
3172227825Stheraven	case FLOAT_QUADRUPLE_BYTES:
3173227825Stheraven		return (decode_fp_to_long_double(p, len));
3174227825Stheraven	case FLOAT_EXTENED_BYTES:
3175227825Stheraven		if (p == NULL || len == 0 || len % 2 != 0 ||
3176227825Stheraven		    len / 2 > FLOAT_QUADRUPLE_BYTES)
3177227825Stheraven			return (NULL);
3178227825Stheraven
3179227825Stheraven		memset(buf, 0, FLOAT_QUADRUPLE_BYTES);
3180227825Stheraven
3181227825Stheraven		for (i = 0; i < len / 2; ++i) {
3182227825Stheraven			byte = hex_to_dec(p[len - i * 2 - 1]) +
3183227825Stheraven			    hex_to_dec(p[len - i * 2 - 2]) * 16;
3184227825Stheraven			if (byte < 0 || byte > 255)
3185227825Stheraven				return (NULL);
3186227825Stheraven#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3187227825Stheraven			buf[i] = (unsigned char)(byte);
3188227825Stheraven#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3189227825Stheraven			buf[FLOAT_QUADRUPLE_BYTES - i -1] =
3190227825Stheraven			    (unsigned char)(byte);
3191227825Stheraven#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3192227825Stheraven		}
3193227825Stheraven		memset(&f, 0, FLOAT_EXTENED_BYTES);
3194227825Stheraven
3195227825Stheraven#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3196227825Stheraven		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
3197227825Stheraven#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3198227825Stheraven		memcpy(&f, buf + 6, FLOAT_EXTENED_BYTES);
3199227825Stheraven#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3200227825Stheraven
3201227825Stheraven		rtn_len = 256;
3202227825Stheraven		limit = 0;
3203227825Stheravenagain:
3204227825Stheraven		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3205227825Stheraven			return (NULL);
3206227825Stheraven
3207227825Stheraven		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3208227825Stheraven			free(rtn);
3209227825Stheraven			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3210227825Stheraven				return (NULL);
3211227825Stheraven			rtn_len *= BUFFER_GROWFACTOR;
3212227825Stheraven			goto again;
3213227825Stheraven		}
3214227825Stheraven
3215227825Stheraven		return (rtn);
3216227825Stheraven	default:
3217227825Stheraven		return (NULL);
3218227825Stheraven	}
3219227825Stheraven}
3220227825Stheraven
3221227825Stheravenstatic char *
3222227825Stheravendecode_fp_to_float80(const char *p, size_t len)
3223227825Stheraven{
3224227825Stheraven	long double f;
3225227825Stheraven	size_t rtn_len, limit, i;
3226227825Stheraven	int byte;
3227227825Stheraven	unsigned char buf[FLOAT_EXTENED_BYTES];
3228227825Stheraven	char *rtn;
3229227825Stheraven
3230227825Stheraven	switch(sizeof(long double)) {
3231227825Stheraven	case FLOAT_QUADRUPLE_BYTES:
3232227825Stheraven		if (p == NULL || len == 0 || len % 2 != 0 ||
3233227825Stheraven		    len / 2 > FLOAT_EXTENED_BYTES)
3234227825Stheraven			return (NULL);
3235227825Stheraven
3236227825Stheraven		memset(buf, 0, FLOAT_EXTENED_BYTES);
3237227825Stheraven
3238227825Stheraven		for (i = 0; i < len / 2; ++i) {
3239227825Stheraven			byte = hex_to_dec(p[len - i * 2 - 1]) +
3240227825Stheraven			    hex_to_dec(p[len - i * 2 - 2]) * 16;
3241227825Stheraven
3242227825Stheraven			if (byte < 0 || byte > 255)
3243227825Stheraven				return (NULL);
3244227825Stheraven
3245227825Stheraven#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3246227825Stheraven			buf[i] = (unsigned char)(byte);
3247227825Stheraven#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3248227825Stheraven			buf[FLOAT_EXTENED_BYTES - i -1] =
3249227825Stheraven			    (unsigned char)(byte);
3250227825Stheraven#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3251227825Stheraven		}
3252227825Stheraven
3253227825Stheraven		memset(&f, 0, FLOAT_QUADRUPLE_BYTES);
3254227825Stheraven
3255227825Stheraven#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3256227825Stheraven		memcpy(&f, buf, FLOAT_EXTENED_BYTES);
3257227825Stheraven#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3258227825Stheraven		memcpy((unsigned char *)(&f) + 6, buf, FLOAT_EXTENED_BYTES);
3259227825Stheraven#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3260227825Stheraven
3261227825Stheraven		rtn_len = 256;
3262227825Stheraven		limit = 0;
3263227825Stheravenagain:
3264227825Stheraven		if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3265227825Stheraven			return (NULL);
3266227825Stheraven
3267227825Stheraven		if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3268227825Stheraven			free(rtn);
3269227825Stheraven			if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3270227825Stheraven				return (NULL);
3271227825Stheraven			rtn_len *= BUFFER_GROWFACTOR;
3272227825Stheraven			goto again;
3273227825Stheraven		}
3274227825Stheraven
3275227825Stheraven		return (rtn);
3276227825Stheraven	case FLOAT_EXTENED_BYTES:
3277227825Stheraven		return (decode_fp_to_long_double(p, len));
3278227825Stheraven	default:
3279227825Stheraven		return (NULL);
3280227825Stheraven	}
3281227825Stheraven}
3282227825Stheraven
3283227825Stheravenstatic char *
3284227825Stheravendecode_fp_to_long_double(const char *p, size_t len)
3285227825Stheraven{
3286227825Stheraven	long double f;
3287227825Stheraven	size_t rtn_len, limit, i;
3288227825Stheraven	int byte;
3289227825Stheraven	char *rtn;
3290227825Stheraven
3291227825Stheraven	if (p == NULL || len == 0 || len % 2 != 0 ||
3292227825Stheraven	    len / 2 > sizeof(long double))
3293227825Stheraven		return (NULL);
3294227825Stheraven
3295227825Stheraven	memset(&f, 0, sizeof(long double));
3296227825Stheraven
3297227825Stheraven	for (i = 0; i < len / 2; ++i) {
3298227825Stheraven		byte = hex_to_dec(p[len - i * 2 - 1]) +
3299227825Stheraven		    hex_to_dec(p[len - i * 2 - 2]) * 16;
3300227825Stheraven
3301227825Stheraven		if (byte < 0 || byte > 255)
3302227825Stheraven			return (NULL);
3303227825Stheraven
3304227825Stheraven#if ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN
3305227825Stheraven		((unsigned char *)&f)[i] = (unsigned char)(byte);
3306227825Stheraven#else /* ELFTC_BYTE_ORDER != ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3307227825Stheraven		((unsigned char *)&f)[sizeof(long double) - i - 1] =
3308227825Stheraven		    (unsigned char)(byte);
3309227825Stheraven#endif /* ELFTC_BYTE_ORDER == ELFTC_BYTE_ORDER_LITTLE_ENDIAN */
3310227825Stheraven	}
3311227825Stheraven
3312227825Stheraven	rtn_len = 256;
3313227825Stheraven	limit = 0;
3314227825Stheravenagain:
3315227825Stheraven	if ((rtn = malloc(sizeof(char) * rtn_len)) == NULL)
3316227825Stheraven		return (NULL);
3317227825Stheraven
3318227825Stheraven	if (snprintf(rtn, rtn_len, "%Lfd", f) >= (int)rtn_len) {
3319227825Stheraven		free(rtn);
3320227825Stheraven		if (limit++ > FLOAT_SPRINTF_TRY_LIMIT)
3321227825Stheraven			return (NULL);
3322227825Stheraven		rtn_len *= BUFFER_GROWFACTOR;
3323227825Stheraven		goto again;
3324227825Stheraven	}
3325227825Stheraven
3326227825Stheraven	return (rtn);
3327227825Stheraven}
3328227825Stheraven
3329227825Stheraven/* Simple hex to integer function used by decode_to_* function. */
3330227825Stheravenstatic int
3331227825Stheravenhex_to_dec(char c)
3332227825Stheraven{
3333227825Stheraven
3334227825Stheraven	switch (c) {
3335227825Stheraven	case '0':
3336227825Stheraven		return (0);
3337227825Stheraven	case '1':
3338227825Stheraven		return (1);
3339227825Stheraven	case '2':
3340227825Stheraven		return (2);
3341227825Stheraven	case '3':
3342227825Stheraven		return (3);
3343227825Stheraven	case '4':
3344227825Stheraven		return (4);
3345227825Stheraven	case '5':
3346227825Stheraven		return (5);
3347227825Stheraven	case '6':
3348227825Stheraven		return (6);
3349227825Stheraven	case '7':
3350227825Stheraven		return (7);
3351227825Stheraven	case '8':
3352227825Stheraven		return (8);
3353227825Stheraven	case '9':
3354227825Stheraven		return (9);
3355227825Stheraven	case 'a':
3356227825Stheraven		return (10);
3357227825Stheraven	case 'b':
3358227825Stheraven		return (11);
3359227825Stheraven	case 'c':
3360227825Stheraven		return (12);
3361227825Stheraven	case 'd':
3362227825Stheraven		return (13);
3363227825Stheraven	case 'e':
3364227825Stheraven		return (14);
3365227825Stheraven	case 'f':
3366227825Stheraven		return (15);
3367227825Stheraven	default:
3368227825Stheraven		return (-1);
3369227825Stheraven	};
3370227825Stheraven}
3371227825Stheraven
3372227825Stheravenstatic void
3373227825Stheravenvector_read_cmd_dest(struct vector_read_cmd *v)
3374227825Stheraven{
3375227825Stheraven
3376227825Stheraven	if (v == NULL)
3377227825Stheraven		return;
3378227825Stheraven
3379227825Stheraven	free(v->r_container);
3380227825Stheraven}
3381227825Stheraven
3382227825Stheraven/* return -1 at failed, 0 at not found, 1 at found. */
3383227825Stheravenstatic int
3384227825Stheravenvector_read_cmd_find(struct vector_read_cmd *v, enum read_cmd dst)
3385227825Stheraven{
3386227825Stheraven	size_t i;
3387227825Stheraven
3388227825Stheraven	if (v == NULL || dst == READ_FAIL)
3389227825Stheraven		return (-1);
3390227825Stheraven
3391227825Stheraven	for (i = 0; i < v->size; ++i)
3392227825Stheraven		if (v->r_container[i] == dst)
3393227825Stheraven			return (1);
3394227825Stheraven
3395227825Stheraven	return (0);
3396227825Stheraven}
3397227825Stheraven
3398227825Stheravenstatic int
3399227825Stheravenvector_read_cmd_init(struct vector_read_cmd *v)
3400227825Stheraven{
3401227825Stheraven
3402227825Stheraven	if (v == NULL)
3403227825Stheraven		return (0);
3404227825Stheraven
3405227825Stheraven	v->size = 0;
3406227825Stheraven	v->capacity = VECTOR_DEF_CAPACITY;
3407227825Stheraven
3408227825Stheraven	if ((v->r_container = malloc(sizeof(enum read_cmd) * v->capacity))
3409227825Stheraven	    == NULL)
3410227825Stheraven		return (0);
3411227825Stheraven
3412227825Stheraven	return (1);
3413227825Stheraven}
3414227825Stheraven
3415227825Stheravenstatic int
3416227825Stheravenvector_read_cmd_pop(struct vector_read_cmd *v)
3417227825Stheraven{
3418227825Stheraven
3419227825Stheraven	if (v == NULL || v->size == 0)
3420227825Stheraven		return (0);
3421227825Stheraven
3422227825Stheraven	--v->size;
3423227825Stheraven	v->r_container[v->size] = READ_FAIL;
3424227825Stheraven
3425227825Stheraven	return (1);
3426227825Stheraven}
3427227825Stheraven
3428227825Stheravenstatic int
3429227825Stheravenvector_read_cmd_push(struct vector_read_cmd *v, enum read_cmd cmd)
3430227825Stheraven{
3431227825Stheraven	enum read_cmd *tmp_r_ctn;
3432227825Stheraven	size_t tmp_cap;
3433227825Stheraven	size_t i;
3434227825Stheraven
3435227825Stheraven	if (v == NULL)
3436227825Stheraven		return (0);
3437227825Stheraven
3438227825Stheraven	if (v->size == v->capacity) {
3439227825Stheraven		tmp_cap = v->capacity * BUFFER_GROWFACTOR;
3440227825Stheraven		if ((tmp_r_ctn = malloc(sizeof(enum read_cmd) * tmp_cap))
3441227825Stheraven		    == NULL)
3442227825Stheraven			return (0);
3443227825Stheraven		for (i = 0; i < v->size; ++i)
3444227825Stheraven			tmp_r_ctn[i] = v->r_container[i];
3445227825Stheraven		free(v->r_container);
3446227825Stheraven		v->r_container = tmp_r_ctn;
3447227825Stheraven		v->capacity = tmp_cap;
3448227825Stheraven	}
3449227825Stheraven
3450227825Stheraven	v->r_container[v->size] = cmd;
3451227825Stheraven	++v->size;
3452227825Stheraven
3453227825Stheraven	return (1);
3454227825Stheraven}
3455227825Stheraven
3456227825Stheravenstatic void
3457227825Stheravenvector_type_qualifier_dest(struct vector_type_qualifier *v)
3458227825Stheraven{
3459227825Stheraven
3460227825Stheraven	if (v == NULL)
3461227825Stheraven		return;
3462227825Stheraven
3463227825Stheraven	free(v->q_container);
3464227825Stheraven	vector_str_dest(&v->ext_name);
3465227825Stheraven}
3466227825Stheraven
3467227825Stheraven/* size, capacity, ext_name */
3468227825Stheravenstatic int
3469227825Stheravenvector_type_qualifier_init(struct vector_type_qualifier *v)
3470227825Stheraven{
3471227825Stheraven
3472227825Stheraven	if (v == NULL)
3473227825Stheraven		return (0);
3474227825Stheraven
3475227825Stheraven	v->size = 0;
3476227825Stheraven	v->capacity = VECTOR_DEF_CAPACITY;
3477227825Stheraven
3478227825Stheraven	if ((v->q_container = malloc(sizeof(enum type_qualifier) * v->capacity))
3479227825Stheraven	    == NULL)
3480227825Stheraven		return (0);
3481227825Stheraven
3482227825Stheraven	assert(v->q_container != NULL);
3483227825Stheraven
3484227825Stheraven	if (vector_str_init(&v->ext_name) == false) {
3485227825Stheraven		free(v->q_container);
3486227825Stheraven		return (0);
3487227825Stheraven	}
3488227825Stheraven
3489227825Stheraven	return (1);
3490227825Stheraven}
3491227825Stheraven
3492227825Stheravenstatic int
3493227825Stheravenvector_type_qualifier_push(struct vector_type_qualifier *v,
3494227825Stheraven    enum type_qualifier t)
3495227825Stheraven{
3496227825Stheraven	enum type_qualifier *tmp_ctn;
3497227825Stheraven	size_t tmp_cap;
3498227825Stheraven	size_t i;
3499227825Stheraven
3500227825Stheraven	if (v == NULL)
3501227825Stheraven		return (0);
3502227825Stheraven
3503227825Stheraven	if (v->size == v->capacity) {
3504227825Stheraven		tmp_cap = v->capacity * BUFFER_GROWFACTOR;
3505227825Stheraven		if ((tmp_ctn = malloc(sizeof(enum type_qualifier) * tmp_cap))
3506227825Stheraven		    == NULL)
3507227825Stheraven			return (0);
3508227825Stheraven		for (i = 0; i < v->size; ++i)
3509227825Stheraven			tmp_ctn[i] = v->q_container[i];
3510227825Stheraven		free(v->q_container);
3511227825Stheraven		v->q_container = tmp_ctn;
3512227825Stheraven		v->capacity = tmp_cap;
3513227825Stheraven	}
3514227825Stheraven
3515227825Stheraven	v->q_container[v->size] = t;
3516227825Stheraven	++v->size;
3517227825Stheraven
3518227825Stheraven	return (1);
3519227825Stheraven}
3520