1 /*
2  * Ported from LLVM's libcxxabi trunk/src/cxa_demangle.cpp
3  * LICENSE.TXT contents is available as ../THIRDPARTYLICENSE
4  *
5  *                     The LLVM Compiler Infrastructure
6  *
7  * This file is dual licensed under the MIT and the University of Illinois Open
8  * Source Licenses. See LICENSE.TXT for details.
9  *
10  */
11 
12 /*
13  * Copyright 2021 Jason King.
14  */
15 #include <errno.h>
16 #include <note.h>
17 #include <string.h>
18 #include <setjmp.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include "demangle-sys.h"
22 #include "demangle_int.h"
23 #include "cxx.h"
24 
25 #define	CPP_QUAL_CONST		(1U)
26 #define	CPP_QUAL_VOLATILE	(2U)
27 #define	CPP_QUAL_RESTRICT	(4U)
28 
29 typedef struct cpp_db_s {
30 	sysdem_ops_t	*cpp_ops;
31 	jmp_buf		cpp_jmp;
32 	name_t		cpp_name;
33 	sub_t		cpp_subs;
34 	templ_t		cpp_templ;
35 	unsigned	cpp_cv;
36 	unsigned	cpp_ref;
37 	unsigned	cpp_depth;
38 	boolean_t	cpp_parsed_ctor_dtor_cv;
39 	boolean_t	cpp_tag_templates;
40 	boolean_t	cpp_fix_forward_references;
41 	boolean_t	cpp_try_to_parse_template_args;
42 } cpp_db_t;
43 
44 #define	CK(x)						\
45 	do {						\
46 		if (!(x)) {				\
47 			longjmp(db->cpp_jmp, 1);	\
48 		}					\
49 	NOTE(CONSTCOND)					\
50 	} while (0)
51 
52 #define	TOP_L(db) (&(name_top(&(db)->cpp_name)->strp_l))
53 #define	RLEN(f, l) ((size_t)((l) - (f)))
54 #define	NAMT(db, n) (nlen(db) - n)
55 
56 static inline boolean_t is_xdigit(int);
57 
58 static boolean_t nempty(cpp_db_t *);
59 static size_t nlen(cpp_db_t *);
60 static void nadd_l(cpp_db_t *, const char *, size_t);
61 static void njoin(cpp_db_t *, size_t, const char *);
62 static void nfmt(cpp_db_t *, const char *, const char *);
63 
64 static void save_top(cpp_db_t *, size_t);
65 static void sub(cpp_db_t *, size_t);
66 
67 static boolean_t tempty(const cpp_db_t *);
68 static size_t ttlen(const cpp_db_t *);
69 
70 static void tsub(cpp_db_t *, size_t);
71 static void tpush(cpp_db_t *);
72 static void tpop(cpp_db_t *);
73 static void tsave(cpp_db_t *, size_t);
74 
75 static void db_init(cpp_db_t *, sysdem_ops_t *);
76 static void db_fini(cpp_db_t *);
77 static void dump(cpp_db_t *, FILE *);
78 
79 static void demangle(const char *, const char *, cpp_db_t *);
80 
81 static const char *parse_type(const char *, const char *, cpp_db_t *);
82 static const char *parse_builtin_type(const char *, const char *, cpp_db_t *);
83 static const char *parse_qual_type(const char *, const char *, cpp_db_t *);
84 static const char *parse_encoding(const char *, const char *, cpp_db_t *);
85 static const char *parse_dot_suffix(const char *, const char *, cpp_db_t *);
86 static const char *parse_block_invoke(const char *, const char *, cpp_db_t *);
87 static const char *parse_special_name(const char *, const char *, cpp_db_t *);
88 static const char *parse_name(const char *, const char *, boolean_t *,
89     cpp_db_t *);
90 static const char *parse_call_offset(const char *, const char *);
91 static const char *parse_number(const char *, const char *);
92 static const char *parse_nested_name(const char *, const char *, boolean_t *,
93     cpp_db_t *);
94 static const char *parse_local_name(const char *, const char *, boolean_t *,
95     cpp_db_t *);
96 static const char *parse_unscoped_name(const char *, const char *, cpp_db_t *);
97 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
98 static const char *parse_substitution(const char *, const char *, cpp_db_t *);
99 static const char *parse_discriminator(const char *, const char *);
100 static const char *parse_cv_qualifiers(const char *, const char *, unsigned *);
101 static const char *parse_template_param(const char *, const char *, cpp_db_t *);
102 static const char *parse_decltype(const char *, const char *, cpp_db_t *);
103 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
104 static const char *parse_unqualified_name(const char *, const char *,
105     cpp_db_t *);
106 static const char *parse_template_arg(const char *, const char *, cpp_db_t *);
107 static const char *parse_expression(const char *, const char *, cpp_db_t *);
108 static const char *parse_expr_primary(const char *, const char *, cpp_db_t *);
109 static const char *parse_binary_expr(const char *, const char *,
110     const char *, cpp_db_t *);
111 static const char *parse_prefix_expr(const char *, const char *,
112     const char *, cpp_db_t *);
113 static const char *parse_gs(const char *, const char *, cpp_db_t *);
114 static const char *parse_idx_expr(const char *, const char *, cpp_db_t *);
115 static const char *parse_mm_expr(const char *, const char *, cpp_db_t *);
116 static const char *parse_pp_expr(const char *, const char *, cpp_db_t *);
117 static const char *parse_trinary_expr(const char *, const char *, cpp_db_t *);
118 static const char *parse_new_expr(const char *, const char *, cpp_db_t *);
119 static const char *parse_del_expr(const char *, const char *, cpp_db_t *);
120 static const char *parse_cast_expr(const char *, const char *, cpp_db_t *);
121 static const char *parse_sizeof_param_pack_expr(const char *, const char *,
122     cpp_db_t *);
123 static const char *parse_typeid_expr(const char *, const char *, cpp_db_t *);
124 static const char *parse_throw_expr(const char *, const char *, cpp_db_t *);
125 static const char *parse_dot_star_expr(const char *, const char *, cpp_db_t *);
126 static const char *parse_dot_expr(const char *, const char *, cpp_db_t *);
127 static const char *parse_call_expr(const char *, const char *, cpp_db_t *);
128 static const char *parse_arrow_expr(const char *, const char *, cpp_db_t *);
129 static const char *parse_conv_expr(const char *, const char *, cpp_db_t *);
130 static const char *parse_function_param(const char *, const char *, cpp_db_t *);
131 static const char *parse_base_unresolved_name(const char *, const char *,
132     cpp_db_t *);
133 static const char *parse_unresolved_name(const char *, const char *,
134     cpp_db_t *);
135 static const char *parse_noexcept_expr(const char *, const char *, cpp_db_t *);
136 static const char *parse_alignof(const char *, const char *, cpp_db_t *);
137 static const char *parse_sizeof(const char *, const char *, cpp_db_t *);
138 static const char *parse_unnamed_type_name(const char *, const char *,
139     cpp_db_t *);
140 static const char *parse_ctor_dtor_name(const char *, const char *, cpp_db_t *);
141 static const char *parse_source_name(const char *, const char *, cpp_db_t *);
142 static const char *parse_operator_name(const char *, const char *, cpp_db_t *);
143 static const char *parse_pack_expansion(const char *, const char *, cpp_db_t *);
144 static const char *parse_unresolved_type(const char *, const char *,
145     cpp_db_t *);
146 static const char *parse_unresolved_qualifier_level(const char *, const char *,
147     cpp_db_t *);
148 static const char *parse_destructor_name(const char *, const char *,
149     cpp_db_t *);
150 static const char *parse_function_type(const char *, const char *, cpp_db_t *);
151 static const char *parse_array_type(const char *, const char *, cpp_db_t *);
152 static const char *parse_pointer_to_member_type(const char *, const char *,
153     cpp_db_t *);
154 static const char *parse_vector_type(const char *, const char *, cpp_db_t *);
155 
156 size_t cpp_name_max_depth = 1024;	/* max depth of name stack */
157 
158 char *
cpp_demangle(const char * src,size_t srclen,sysdem_ops_t * ops)159 cpp_demangle(const char *src, size_t srclen, sysdem_ops_t *ops)
160 {
161 	char *volatile result = NULL;
162 	cpp_db_t db;
163 
164 	db_init(&db, ops);
165 
166 	if (setjmp(db.cpp_jmp) != 0)
167 		goto done;
168 
169 	errno = 0;
170 	demangle(src, src + srclen, &db);
171 
172 	if (errno == 0 && db.cpp_fix_forward_references &&
173 	    !templ_empty(&db.cpp_templ) &&
174 	    !sub_empty(&db.cpp_templ.tpl_items[0])) {
175 		db.cpp_fix_forward_references = B_FALSE;
176 		db.cpp_tag_templates = B_FALSE;
177 		name_clear(&db.cpp_name);
178 		sub_clear(&db.cpp_subs);
179 
180 		if (setjmp(db.cpp_jmp) != 0)
181 			goto done;
182 
183 		demangle(src, src + srclen, &db);
184 
185 		if (db.cpp_fix_forward_references) {
186 			errno = EINVAL;
187 			goto done;
188 		}
189 	}
190 
191 	if (errno != 0)
192 		goto done;
193 
194 	if (nempty(&db)) {
195 		errno = EINVAL;
196 		goto done;
197 	}
198 
199 	njoin(&db, 1, "");
200 
201 	if (nlen(&db) > 0) {
202 		str_t *s = TOP_L(&db);
203 		char *res = zalloc(ops, s->str_len + 1);
204 		if (res == NULL)
205 			goto done;
206 
207 		(void) memcpy(res, s->str_s, s->str_len);
208 		result = res;
209 	}
210 
211 done:
212 	if (demangle_debug)
213 		dump(&db, stdout);
214 
215 	db_fini(&db);
216 	return (result);
217 }
218 
219 static void
demangle(const char * first,const char * last,cpp_db_t * db)220 demangle(const char *first, const char *last, cpp_db_t *db)
221 {
222 	const char *t = NULL;
223 
224 	if (first >= last) {
225 		errno = EINVAL;
226 		return;
227 	}
228 
229 	if (first[0] != '_') {
230 		t = parse_type(first, last, db);
231 		if (t == first) {
232 			errno = EINVAL;
233 			return;
234 		}
235 		goto done;
236 	}
237 
238 	if (last - first < 4) {
239 		errno = EINVAL;
240 		return;
241 	}
242 
243 	if (first[1] == 'Z') {
244 		t = parse_encoding(first + 2, last, db);
245 
246 		if (t != first + 2 && t != last && t[0] == '.') {
247 			t = parse_dot_suffix(t, last, db);
248 			if (nlen(db) > 1)
249 				njoin(db, 2, "");
250 		}
251 
252 		goto done;
253 	}
254 
255 	if (first[1] != '_' || first[2] != '_' || first[3] != 'Z')
256 		goto done;
257 
258 	t = parse_encoding(first + 4, last, db);
259 	if (t != first + 4 && t != last)
260 		t = parse_block_invoke(t, last, db);
261 
262 done:
263 	if (t != last)
264 		errno = EINVAL;
265 }
266 
267 static const char *
parse_dot_suffix(const char * first,const char * last,cpp_db_t * db)268 parse_dot_suffix(const char *first, const char *last, cpp_db_t *db)
269 {
270 	VERIFY3P(first, <=, last);
271 
272 	if (first == last || first[0] != '.')
273 		return (first);
274 
275 	if (nempty(db))
276 		return (first);
277 
278 	nadd_l(db, first, RLEN(first, last));
279 	nfmt(db, " ({0})", NULL);
280 
281 	return (last);
282 }
283 
284 /*
285  * _block_invoke
286  * _block_invoke<digit>*
287  * _block_invoke_<digit>+
288  */
289 static const char *
parse_block_invoke(const char * first,const char * last,cpp_db_t * db)290 parse_block_invoke(const char *first, const char *last, cpp_db_t *db)
291 {
292 	VERIFY3P(first, <=, last);
293 
294 	if (last - first < 13)
295 		return (first);
296 
297 	const char test[] = "_block_invoke";
298 	const char *t = first;
299 
300 	if (strncmp(first, test, sizeof (test) - 1) != 0)
301 		return (first);
302 
303 	t += sizeof (test);
304 	if (t == last)
305 		goto done;
306 
307 	if (t[0] == '_') {
308 		/* need at least one digit */
309 		if (t + 1 == last || ISDIGIT(t[1]))
310 			return (first);
311 		t += 2;
312 	}
313 
314 	while (t < last && ISDIGIT(t[0]))
315 		t++;
316 
317 done:
318 	if (nempty(db))
319 		return (first);
320 
321 	nfmt(db, "invocation function for block in {0}", NULL);
322 	return (t);
323 }
324 
325 /*
326  * <encoding> ::= <function name><bare-function-type>
327  *            ::= <data name>
328  *            ::= <special name>
329  */
330 static const char *
parse_encoding(const char * first,const char * last,cpp_db_t * db)331 parse_encoding(const char *first, const char *last, cpp_db_t *db)
332 {
333 	VERIFY3P(first, <=, last);
334 
335 	if (first == last)
336 		return (first);
337 
338 	const char *t = NULL;
339 	const char *t2 = NULL;
340 	unsigned cv = 0;
341 	unsigned ref = 0;
342 	boolean_t tag_templ_save = db->cpp_tag_templates;
343 
344 	if (++db->cpp_depth > 1)
345 		db->cpp_tag_templates = B_TRUE;
346 
347 	if (first[0] == 'G' || first[0] == 'T') {
348 		t = parse_special_name(first, last, db);
349 		goto done;
350 	}
351 
352 	boolean_t ends_with_template_args = B_FALSE;
353 	t = parse_name(first, last, &ends_with_template_args, db);
354 	if (t == first)
355 		goto fail;
356 
357 	cv = db->cpp_cv;
358 	ref = db->cpp_ref;
359 
360 	if (t == last || t[0] == 'E' || t[0] == '.')
361 		goto done;
362 
363 	db->cpp_tag_templates = B_FALSE;
364 	if (nempty(db) || str_length(TOP_L(db)) == 0)
365 		goto fail;
366 
367 	if (!db->cpp_parsed_ctor_dtor_cv && ends_with_template_args) {
368 		t2 = parse_type(t, last, db);
369 		if (t2 == t || nlen(db) < 2)
370 			goto fail;
371 
372 		str_pair_t *sp = name_top(&db->cpp_name);
373 
374 		if (str_length(&sp->strp_r) == 0)
375 			(void) str_append(&sp->strp_l, " ", 1);
376 
377 		nfmt(db, "{0:L}{1:L}", "{1:R}{0:R}");
378 		t = t2;
379 	}
380 
381 	if (t == last || nempty(db))
382 		goto fail;
383 
384 	size_t n = nlen(db);
385 
386 	if (t[0] == 'v') {
387 		t++;
388 	} else {
389 		for (;;) {
390 			t2 = parse_type(t, last, db);
391 			if (t2 == t || t == last)
392 				break;
393 
394 			t = t2;
395 		}
396 	}
397 
398 	/*
399 	 * a bit of a hack, but a template substitution can apparently be
400 	 * an empty string at the end of an argument list, so avoid
401 	 * <...., >
402 	 */
403 	if (NAMT(db, n) > 1 && str_pair_len(name_top(&db->cpp_name)) == 0)
404 		name_pop(&db->cpp_name, NULL);
405 
406 	njoin(db, NAMT(db, n), ", ");
407 	nfmt(db, "({0})", NULL);
408 
409 	str_t *s = TOP_L(db);
410 
411 	if (cv & CPP_QUAL_CONST) {
412 		CK(str_append(s, " const", 0));
413 	}
414 	if (cv & CPP_QUAL_VOLATILE) {
415 		CK(str_append(s, " volatile", 0));
416 	}
417 	if (cv & CPP_QUAL_RESTRICT) {
418 		CK(str_append(s, " restrict", 0));
419 	}
420 	if (ref == 1) {
421 		CK(str_append(s, " &", 0));
422 	}
423 	if (ref == 2) {
424 		CK(str_append(s, " &&", 0));
425 	}
426 
427 	nfmt(db, "{1:L}{0}{1:R}", NULL);
428 
429 done:
430 	db->cpp_tag_templates = tag_templ_save;
431 	db->cpp_depth--;
432 	return (t);
433 
434 fail:
435 	db->cpp_tag_templates = tag_templ_save;
436 	db->cpp_depth--;
437 	return (first);
438 }
439 
440 /*
441  * <special-name> ::= TV <type>    # virtual table
442  *                ::= TT <type>    # VTT structure (construction vtable index)
443  *                ::= TI <type>    # typeinfo structure
444  *                ::= TS <type>    # typeinfo name (null-terminated byte string)
445  *                ::= Tc <call-offset> <call-offset> <base encoding>
446  *                    # base is the nominal target function of thunk
447  *                    # first call-offset is 'this' adjustment
448  *                    # second call-offset is result adjustment
449  *                ::= T <call-offset> <base encoding>
450  *                    # base is the nominal target function of thunk
451  *                ::= GV <object name> # Guard variable for one-time init
452  *                                     # No <type>
453  *                ::= TW <object name> # Thread-local wrapper
454  *                ::= TH <object name> # Thread-local initialization
455  *      extension ::= TC <first type> <number> _ <second type>
456  *                                     # construction vtable for second-in-first
457  *      extension ::= GR <object name> # reference temporary for object
458  */
459 static const char *
parse_special_name(const char * first,const char * last,cpp_db_t * db)460 parse_special_name(const char *first, const char *last, cpp_db_t *db)
461 {
462 	VERIFY3P(first, <=, last);
463 
464 	const char *t = first;
465 	const char *t1 = NULL;
466 	size_t n = nlen(db);
467 
468 	if (last - first < 2)
469 		return (first);
470 
471 	switch (t[0]) {
472 	case 'T':
473 		switch (t[1]) {
474 		case 'V':
475 			nadd_l(db, "vtable for", 0);
476 			t = parse_type(first + 2, last, db);
477 			break;
478 		case 'T':
479 			nadd_l(db, "VTT for", 0);
480 			t = parse_type(first + 2, last, db);
481 			break;
482 		case 'I':
483 			nadd_l(db, "typeinfo for", 0);
484 			t = parse_type(first + 2, last, db);
485 			break;
486 		case 'S':
487 			nadd_l(db, "typeinfo name for", 0);
488 			t = parse_type(first + 2, last, db);
489 			break;
490 		case 'c':
491 			nadd_l(db, "covariant return thunk to", 0);
492 			t1 = parse_call_offset(first + 2, last);
493 			if (t1 == t)
494 				return (first);
495 			t = parse_call_offset(t1, last);
496 			if (t == t1)
497 				return (first);
498 			t1 = parse_encoding(t, last, db);
499 			if (t1 == t)
500 				return (first);
501 			break;
502 		case 'C':
503 			t = parse_type(first + 2, last, db);
504 			if (t == first + 2)
505 				return (first);
506 			t1 = parse_number(t, last);
507 			if (*t1 != '_')
508 				return (first);
509 			t = parse_type(t1 + 1, last, db);
510 			if (t == t1 + 1 || nlen(db) < 2)
511 				return (first);
512 			nfmt(db, "construction vtable for {0}-in-{1}", NULL);
513 			return (t);
514 		case 'W':
515 			nadd_l(db, "thread-local wrapper routine for", 0);
516 			t = parse_name(first + 2, last, NULL, db);
517 			break;
518 		case 'H':
519 			nadd_l(db, "thread-local initialization routine for",
520 			    0);
521 			t = parse_name(first + 2, last, NULL, db);
522 			break;
523 		default:
524 			if (first[1] == 'v') {
525 				nadd_l(db, "virtual thunk to", 0);
526 			} else {
527 				nadd_l(db, "non-virtual thunk to", 0);
528 			}
529 
530 			t = parse_call_offset(first + 1, last);
531 			if (t == first + 1)
532 				return (first);
533 			t1 = parse_encoding(t, last, db);
534 			if (t == t1)
535 				return (first);
536 			t = t1;
537 			break;
538 		}
539 		break;
540 	case 'G':
541 		switch (first[1]) {
542 		case 'V':
543 			nadd_l(db, "guard variable for", 0);
544 			t = parse_name(first + 2, last, NULL, db);
545 			break;
546 		case 'R':
547 			nadd_l(db, "reference temporary for", 0);
548 			t = parse_name(first + 2, last, NULL, db);
549 			break;
550 		default:
551 			return (first);
552 		}
553 		break;
554 	default:
555 		return (first);
556 	}
557 
558 	size_t amt = NAMT(db, n);
559 	if (t == first + 2 || amt < 2)
560 		return (first);
561 
562 	njoin(db, amt, " ");
563 	return (t);
564 }
565 
566 /*
567  * <call-offset> ::= h <nv-offset> _
568  *               ::= v <v-offset> _
569  *
570  * <nv-offset> ::= <offset number>
571  *               # non-virtual base override
572  *
573  * <v-offset>  ::= <offset number> _ <virtual offset number>
574  *               # virtual base override, with vcall offset
575  */
576 static const char *
parse_call_offset(const char * first,const char * last)577 parse_call_offset(const char *first, const char *last)
578 {
579 	VERIFY3P(first, <=, last);
580 
581 	const char *t = NULL;
582 	const char *t1 = NULL;
583 
584 	if (first == last)
585 		return (first);
586 
587 	if (first[0] != 'h' && first[0] != 'v')
588 		return (first);
589 
590 	t = parse_number(first + 1, last);
591 	if (t == first + 1 || t == last || t[0] != '_')
592 		return (first);
593 
594 	/* skip _ */
595 	t++;
596 
597 	if (first[0] == 'h')
598 		return (t);
599 
600 	t1 = parse_number(t, last);
601 	if (t == t1 || t1 == last || t1[0] != '_')
602 		return (first);
603 
604 	/* skip _ */
605 	t1++;
606 
607 	return (t1);
608 }
609 
610 /*
611  * <name> ::= <nested-name> // N
612  *        ::= <local-name> # See Scope Encoding below  // Z
613  *        ::= <unscoped-template-name> <template-args>
614  *        ::= <unscoped-name>
615  *
616  * <unscoped-template-name> ::= <unscoped-name>
617  *                          ::= <substitution>
618  */
619 static const char *
parse_name(const char * first,const char * last,boolean_t * ends_with_template_args,cpp_db_t * db)620 parse_name(const char *first, const char *last,
621     boolean_t *ends_with_template_args, cpp_db_t *db)
622 {
623 	VERIFY3P(first, <=, last);
624 
625 	const char *t = first;
626 	const char *t1 = NULL;
627 
628 	if (last - first < 2)
629 		return (first);
630 
631 	/* extension: ignore L here */
632 	if (t[0] == 'L')
633 		t++;
634 
635 	switch (t[0]) {
636 	case 'N':
637 		t1 = parse_nested_name(t, last, ends_with_template_args, db);
638 		return ((t == t1) ? first : t1);
639 	case 'Z':
640 		t1 = parse_local_name(t, last, ends_with_template_args, db);
641 		return ((t == t1) ? first : t1);
642 	}
643 
644 	/*
645 	 * <unscoped-name>
646 	 * <unscoped-name> <template-args>
647 	 * <substitution> <template-args>
648 	 */
649 	t1 = parse_unscoped_name(t, last, db);
650 
651 	/* <unscoped-name> */
652 	if (t != t1 && t1[0] != 'I')
653 		return (t1);
654 
655 	if (t == t1) {
656 		t1 = parse_substitution(t, last, db);
657 		if (t == t1 || t1 == last || t1[0] != 'I')
658 			return (first);
659 	} else {
660 		save_top(db, 1);
661 	}
662 
663 	t = parse_template_args(t1, last, db);
664 	if (t1 == t || nlen(db) < 2)
665 		return (first);
666 
667 	nfmt(db, "{1:L}{0}", "{1:R}");
668 
669 	if (ends_with_template_args != NULL)
670 		*ends_with_template_args = B_TRUE;
671 
672 	return (t);
673 }
674 
675 /* BEGIN CSTYLED */
676 /*
677  * <local-name> := Z <function encoding> E <entity name> [<discriminator>]
678  *              := Z <function encoding> E s [<discriminator>]
679  *              := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
680  */
681 /* END CSTYLED */
682 const char *
parse_local_name(const char * first,const char * last,boolean_t * ends_with_template_args,cpp_db_t * db)683 parse_local_name(const char *first, const char *last,
684     boolean_t *ends_with_template_args, cpp_db_t *db)
685 {
686 	VERIFY3P(first, <=, last);
687 
688 	const char *t = NULL;
689 	const char *t1 = NULL;
690 	const char *t2 = NULL;
691 
692 	if (first == last || first[0] != 'Z')
693 		return (first);
694 
695 	t = parse_encoding(first + 1, last, db);
696 	if (t == first + 1 || t == last || t[0] != 'E')
697 		return (first);
698 
699 	VERIFY(!nempty(db));
700 
701 	/* skip E */
702 	t++;
703 
704 	if (t[0] == 's') {
705 		nfmt(db, "{0:L}::string literal", "{0:R}");
706 		return (parse_discriminator(t, last));
707 	}
708 
709 	if (t[0] == 'd') {
710 		t1 = parse_number(t + 1, last);
711 		if (t1[0] != '_')
712 			return (first);
713 		t1++;
714 	} else {
715 		t1 = t;
716 	}
717 
718 	t2 = parse_name(t1, last, ends_with_template_args, db);
719 	if (t2 == t1)
720 		return (first);
721 
722 	nfmt(db, "{1:L}::{0}", "{1:R}");
723 
724 	/* parsed, but ignored */
725 	if (t[0] != 'd')
726 		t2 = parse_discriminator(t2, last);
727 
728 	return (t2);
729 }
730 
731 /* BEGIN CSTYLED */
732 /*
733  * <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
734  *               ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
735  *
736  * <prefix> ::= <prefix> <unqualified-name>
737  *          ::= <template-prefix> <template-args>
738  *          ::= <template-param>
739  *          ::= <decltype>
740  *          ::= # empty
741  *          ::= <substitution>
742  *          ::= <prefix> <data-member-prefix>
743  *  extension ::= L
744  *
745  * <template-prefix> ::= <prefix> <template unqualified-name>
746  *                   ::= <template-param>
747  *                   ::= <substitution>
748  */
749 /* END CSTYLED */
750 static const char *
parse_nested_name(const char * first,const char * last,boolean_t * ends_with_template_args,cpp_db_t * db)751 parse_nested_name(const char *first, const char *last,
752     boolean_t *ends_with_template_args, cpp_db_t *db)
753 {
754 	VERIFY3P(first, <=, last);
755 
756 	if (first == last || first[0] != 'N')
757 		return (first);
758 
759 	unsigned cv = 0;
760 	const char *t = parse_cv_qualifiers(first + 1, last, &cv);
761 
762 	if (t == last)
763 		return (first);
764 
765 	boolean_t more = B_FALSE;
766 
767 	switch (t[0]) {
768 	case 'R':
769 		db->cpp_ref = 1;
770 		t++;
771 		break;
772 	case 'O':
773 		db->cpp_ref = 2;
774 		t++;
775 		break;
776 	case 'S':
777 		if (last - first < 2 || t[1] != 't')
778 			break;
779 		if (last - first == 2)
780 			return (first);
781 		nadd_l(db, "std", 3);
782 		more = B_TRUE;
783 		t += 2;
784 		break;
785 	}
786 
787 	boolean_t pop_subs = B_FALSE;
788 	boolean_t component_ends_with_template_args = B_FALSE;
789 
790 	while (t[0] != 'E' && t != last) {
791 		const char *t1 = NULL;
792 		size_t n = nlen(db);
793 		component_ends_with_template_args = B_FALSE;
794 
795 		switch (t[0]) {
796 		case 'S':
797 			if (t + 1 != last && t[1] == 't')
798 				break;
799 
800 			t1 = parse_substitution(t, last, db);
801 			if (t1 == t || t1 == last || NAMT(db, n) != 1)
802 				return (first);
803 
804 			if (!more) {
805 				nfmt(db, "{0}", NULL);
806 			} else {
807 				VERIFY3U(nlen(db), >, 1);
808 				nfmt(db, "{1:L}::{0}", "{1:R}");
809 				save_top(db, 1);
810 			}
811 
812 			more = B_TRUE;
813 			pop_subs = B_TRUE;
814 			t = t1;
815 			continue;
816 
817 		case 'T':
818 			t1 = parse_template_param(t, last, db);
819 			if (t1 == t || t1 == last || NAMT(db, n) != 1)
820 				return (first);
821 
822 			if (!more) {
823 				nfmt(db, "{0}", NULL);
824 			} else {
825 				VERIFY3U(nlen(db), >, 1);
826 				nfmt(db, "{1:L}::{0}", "{1:R}");
827 			}
828 
829 			save_top(db, 1);
830 			more = B_TRUE;
831 			pop_subs = B_TRUE;
832 			t = t1;
833 			continue;
834 
835 		case 'D':
836 			if (t + 1 != last && t[1] != 't' && t[1] != 'T')
837 				break;
838 			t1 = parse_decltype(t, last, db);
839 			if (t1 == t || t1 == last || NAMT(db, n) != 1)
840 				return (first);
841 
842 			if (!more) {
843 				nfmt(db, "{0}", NULL);
844 			} else {
845 				VERIFY3U(nlen(db), >, 1);
846 				nfmt(db, "{1:L}::{0}", "{1:R}");
847 			}
848 
849 			save_top(db, 1);
850 			more = B_TRUE;
851 			pop_subs = B_TRUE;
852 			t = t1;
853 			continue;
854 
855 		case 'I':
856 			/*
857 			 * Must have at least one component before
858 			 * <template-args>
859 			 */
860 			if (!more)
861 				return (first);
862 
863 			t1 = parse_template_args(t, last, db);
864 			if (t1 == t || t1 == last)
865 				return (first);
866 
867 			VERIFY3U(nlen(db), >, 1);
868 			nfmt(db, "{1:L}{0}", "{1:R}");
869 			save_top(db, 1);
870 			t = t1;
871 			component_ends_with_template_args = B_TRUE;
872 			continue;
873 
874 		case 'L':
875 			if (t + 1 == last)
876 				return (first);
877 			t++;
878 			continue;
879 
880 		default:
881 			break;
882 		}
883 
884 		t1 = parse_unqualified_name(t, last, db);
885 		if (t1 == t || t1 == last || NAMT(db, n) != 1)
886 			return (first);
887 
888 		if (!more) {
889 			nfmt(db, "{0}", NULL);
890 		} else {
891 			VERIFY3U(nlen(db), >, 1);
892 			nfmt(db, "{1:L}::{0}", "{1:R}");
893 		}
894 
895 		save_top(db, 1);
896 		more = B_TRUE;
897 		pop_subs = B_TRUE;
898 		t = t1;
899 	}
900 
901 	/* need to parse at least one thing */
902 	if (!more)
903 		return (first);
904 
905 	db->cpp_cv = cv;
906 	if (pop_subs && !sub_empty(&db->cpp_subs))
907 		sub_pop(&db->cpp_subs);
908 
909 	if (ends_with_template_args != NULL)
910 		*ends_with_template_args = component_ends_with_template_args;
911 
912 	if (t[0] != 'E')
913 		return (first);
914 
915 	return (t + 1);
916 }
917 
918 /*
919  * <template-arg> ::= <type>                   # type or template
920  *                ::= X <expression> E         # expression
921  *                ::= <expr-primary>           # simple expressions
922  *                ::= J <template-arg>* E      # argument pack
923  *                ::= LZ <encoding> E          # extension
924  */
925 static const char *
parse_template_arg(const char * first,const char * last,cpp_db_t * db)926 parse_template_arg(const char *first, const char *last, cpp_db_t *db)
927 {
928 	VERIFY3P(first, <=, last);
929 
930 	const char *t = NULL;
931 	const char *t1 = NULL;
932 
933 	if (first == last)
934 		return (first);
935 
936 	switch (first[0]) {
937 	case 'X':
938 		t = parse_expression(first + 1, last, db);
939 		if (t == first + 1 || t[0] != 'E')
940 			return (first);
941 
942 		/* E */
943 		t++;
944 		break;
945 
946 	case 'J':
947 		t = first + 1;
948 		if (t == last)
949 			return (first);
950 
951 		while (t[0] != 'E') {
952 			t1 = parse_template_arg(t, last, db);
953 			if (t == t1)
954 				return (first);
955 			t = t1;
956 		}
957 
958 		/* E */
959 		t++;
960 		break;
961 
962 	case 'L':
963 		if (first + 1 == last || first[1] != 'Z') {
964 			t = parse_expr_primary(first, last, db);
965 		} else {
966 			t = parse_encoding(first + 2, last, db);
967 			if (t == first + 2 || t == last || t[0] != 'E')
968 				return (first);
969 
970 			/* E */
971 			t++;
972 		}
973 		break;
974 
975 	default:
976 		t = parse_type(first, last, db);
977 	}
978 
979 	return (t);
980 }
981 
982 /* BEGIN CSTYLED */
983 /*
984  * <expression> ::= <unary operator-name> <expression>
985  *              ::= <binary operator-name> <expression> <expression>
986  *              ::= <ternary operator-name> <expression> <expression> <expression>
987  *              ::= cl <expression>+ E                                   # call
988  *              ::= cv <type> <expression>                               # conversion with one argument
989  *              ::= cv <type> _ <expression>* E                          # conversion with a different number of arguments
990  *              ::= [gs] nw <expression>* _ <type> E                     # new (expr-list) type
991  *              ::= [gs] nw <expression>* _ <type> <initializer>         # new (expr-list) type (init)
992  *              ::= [gs] na <expression>* _ <type> E                     # new[] (expr-list) type
993  *              ::= [gs] na <expression>* _ <type> <initializer>         # new[] (expr-list) type (init)
994  *              ::= [gs] dl <expression>                                 # delete expression
995  *              ::= [gs] da <expression>                                 # delete[] expression
996  *              ::= pp_ <expression>                                     # prefix ++
997  *              ::= mm_ <expression>                                     # prefix --
998  *              ::= ti <type>                                            # typeid (type)
999  *              ::= te <expression>                                      # typeid (expression)
1000  *              ::= dc <type> <expression>                               # dynamic_cast<type> (expression)
1001  *              ::= sc <type> <expression>                               # static_cast<type> (expression)
1002  *              ::= cc <type> <expression>                               # const_cast<type> (expression)
1003  *              ::= rc <type> <expression>                               # reinterpret_cast<type> (expression)
1004  *              ::= st <type>                                            # sizeof (a type)
1005  *              ::= sz <expression>                                      # sizeof (an expression)
1006  *              ::= at <type>                                            # alignof (a type)
1007  *              ::= az <expression>                                      # alignof (an expression)
1008  *              ::= nx <expression>                                      # noexcept (expression)
1009  *              ::= <template-param>
1010  *              ::= <function-param>
1011  *              ::= dt <expression> <unresolved-name>                    # expr.name
1012  *              ::= pt <expression> <unresolved-name>                    # expr->name
1013  *              ::= ds <expression> <expression>                         # expr.*expr
1014  *              ::= sZ <template-param>                                  # size of a parameter pack
1015  *              ::= sZ <function-param>                                  # size of a function parameter pack
1016  *              ::= sp <expression>                                      # pack expansion
1017  *              ::= tw <expression>                                      # throw expression
1018  *              ::= tr                                                   # throw with no operand (rethrow)
1019  *              ::= <unresolved-name>                                    # f(p), N::f(p), ::f(p),
1020  *                                                                       # freestanding dependent name (e.g., T::x),
1021  *                                                                       # objectless nonstatic member reference
1022  *              ::= <expr-primary>
1023  */
1024 /* END CSTYLED */
1025 
1026 #define	PA(cd, arg, fn) {	\
1027 	.code = cd,		\
1028 	.p.parse_expr_arg = fn,	\
1029 	.fntype = EXPR_ARG,	\
1030 	.val = arg		\
1031 }
1032 
1033 #define	PN(cd, fn) {			\
1034 	.code = cd,			\
1035 	.p.parse_expr_noarg = fn,	\
1036 	.fntype = EXPR_NOARG		\
1037 }
1038 
1039 static struct {
1040 	const char code[3];
1041 	union {
1042 		const char *(*parse_expr_arg)(const char *, const char *,
1043 		    const char *, cpp_db_t *);
1044 		const char *(*parse_expr_noarg)(const char *, const char *,
1045 		    cpp_db_t *);
1046 	} p;
1047 	enum {
1048 		EXPR_ARG,
1049 		EXPR_NOARG
1050 	} fntype;
1051 	const char val[4];
1052 } expr_tbl[] = {
1053 	PA("aN", "&=", parse_binary_expr),
1054 	PA("aS", "=", parse_binary_expr),
1055 	PA("aa", "&&", parse_binary_expr),
1056 	PA("ad", "&", parse_prefix_expr),
1057 	PA("an", "&", parse_binary_expr),
1058 	PN("at", parse_alignof),
1059 	PN("az", parse_alignof),
1060 	PN("cc", parse_cast_expr),
1061 	PN("cl", parse_call_expr),
1062 	PA("cm", ",", parse_binary_expr),
1063 	PA("co", "~", parse_prefix_expr),
1064 	PN("cv", parse_conv_expr),
1065 	PN("da", parse_del_expr),
1066 	PA("dV", "/=", parse_binary_expr),
1067 	PN("dc", parse_cast_expr),
1068 	PA("de", "*", parse_prefix_expr),
1069 	PN("dl", parse_del_expr),
1070 	PN("dn", parse_unresolved_name),
1071 	PN("ds", parse_dot_star_expr),
1072 	PN("dt", parse_dot_expr),
1073 	PA("dv", "/", parse_binary_expr),
1074 	PA("eO", "^=", parse_binary_expr),
1075 	PA("eo", "^", parse_binary_expr),
1076 	PA("eq", "==", parse_binary_expr),
1077 	PA("ge", ">=", parse_binary_expr),
1078 	PN("gs", parse_gs),
1079 	PA("gt", ">", parse_binary_expr),
1080 	PN("ix", parse_idx_expr),
1081 	PA("lS", "<<=", parse_binary_expr),
1082 	PA("le", "<=", parse_binary_expr),
1083 	PA("ls", "<<", parse_binary_expr),
1084 	PA("lt", "<", parse_binary_expr),
1085 	PA("mI", "-=", parse_binary_expr),
1086 	PA("mL", "*=", parse_binary_expr),
1087 	PN("mm", parse_mm_expr),
1088 	PA("mi", "-", parse_binary_expr),
1089 	PA("ml", "*", parse_binary_expr),
1090 	PN("na", parse_new_expr),
1091 	PA("ne", "!=", parse_binary_expr),
1092 	PA("ng", "-", parse_prefix_expr),
1093 	PA("nt", "!", parse_prefix_expr),
1094 	PN("nw", parse_new_expr),
1095 	PN("nx", parse_noexcept_expr),
1096 	PA("oR", "|=", parse_binary_expr),
1097 	PN("on", parse_unresolved_name),
1098 	PA("oo", "||", parse_binary_expr),
1099 	PA("or", "|", parse_binary_expr),
1100 	PA("pL", "+=", parse_binary_expr),
1101 	PA("pl", "+", parse_binary_expr),
1102 	PA("pm", "->*", parse_binary_expr),
1103 	PN("pp", parse_pp_expr),
1104 	PA("ps", "+", parse_prefix_expr),
1105 	PN("pt", parse_arrow_expr),
1106 	PN("qu", parse_trinary_expr),
1107 	PA("rM", "%=", parse_binary_expr),
1108 	PA("rS", ">>=", parse_binary_expr),
1109 	PN("rc", parse_cast_expr),
1110 	PA("rm", "%", parse_binary_expr),
1111 	PA("rs", ">>", parse_binary_expr),
1112 	PN("sc", parse_cast_expr),
1113 	PN("sp", parse_pack_expansion),
1114 	PN("sr", parse_unresolved_name),
1115 	PN("st", parse_sizeof),
1116 	PN("sz", parse_sizeof),
1117 	PN("sZ", parse_sizeof_param_pack_expr),
1118 	PN("te", parse_typeid_expr),
1119 	PN("tr", parse_throw_expr),
1120 	PN("tw", parse_throw_expr)
1121 };
1122 #undef PA
1123 #undef PN
1124 
1125 static const char *
parse_expression(const char * first,const char * last,cpp_db_t * db)1126 parse_expression(const char *first, const char *last, cpp_db_t *db)
1127 {
1128 	VERIFY3P(first, <=, last);
1129 
1130 	if (last - first < 2)
1131 		return (first);
1132 
1133 	for (size_t i = 0; i < ARRAY_SIZE(expr_tbl); i++) {
1134 		if (strncmp(expr_tbl[i].code, first, 2) != 0)
1135 			continue;
1136 		switch (expr_tbl[i].fntype) {
1137 		case EXPR_ARG:
1138 			return (expr_tbl[i].p.parse_expr_arg(first, last,
1139 			    expr_tbl[i].val, db));
1140 		case EXPR_NOARG:
1141 			return (expr_tbl[i].p.parse_expr_noarg(first, last,
1142 			    db));
1143 		}
1144 	}
1145 
1146 	switch (first[0]) {
1147 	case 'L':
1148 		return (parse_expr_primary(first, last, db));
1149 	case 'T':
1150 		return (parse_template_param(first, last, db));
1151 	case 'f':
1152 		return (parse_function_param(first, last, db));
1153 	case '1':
1154 	case '2':
1155 	case '3':
1156 	case '4':
1157 	case '5':
1158 	case '6':
1159 	case '7':
1160 	case '8':
1161 	case '9':
1162 		return (parse_unresolved_name(first, last, db));
1163 	}
1164 
1165 	return (first);
1166 }
1167 
1168 static const char *
parse_binary_expr(const char * first,const char * last,const char * op,cpp_db_t * db)1169 parse_binary_expr(const char *first, const char *last, const char *op,
1170     cpp_db_t *db)
1171 {
1172 	VERIFY3P(first, <=, last);
1173 
1174 	if (last - first < 2)
1175 		return (first);
1176 
1177 	size_t n = nlen(db);
1178 
1179 	const char *t1 = parse_expression(first + 2, last, db);
1180 	if (t1 == first + 2)
1181 		return (first);
1182 
1183 	nadd_l(db, op, 0);
1184 
1185 	const char *t2 = parse_expression(t1, last, db);
1186 	if (t2 == t1)
1187 		return (first);
1188 
1189 	if (NAMT(db, n) != 3)
1190 		return (first);
1191 
1192 	VERIFY3U(nlen(db), >, 2);
1193 
1194 	nfmt(db, "({2}) {1} ({0})", NULL);
1195 	if (strcmp(op, ">") == 0)
1196 		nfmt(db, "({0})", NULL);
1197 
1198 	return (t2);
1199 }
1200 
1201 static const char *
parse_prefix_expr(const char * first,const char * last,const char * op,cpp_db_t * db)1202 parse_prefix_expr(const char *first, const char *last, const char *op,
1203     cpp_db_t *db)
1204 {
1205 	VERIFY3P(first, <=, last);
1206 
1207 	if (last - first < 2)
1208 		return (first);
1209 
1210 	nadd_l(db, op, 0);
1211 
1212 	const char *t = parse_expression(first + 2, last, db);
1213 	if (t == first + 2) {
1214 		return (first);
1215 	}
1216 
1217 	VERIFY3U(nlen(db), >, 1);
1218 
1219 	nfmt(db, "{1}({0})", NULL);
1220 	return (t);
1221 }
1222 
1223 static const char *
parse_gs(const char * first,const char * last,cpp_db_t * db)1224 parse_gs(const char *first, const char *last, cpp_db_t *db)
1225 {
1226 	VERIFY3P(first, <=, last);
1227 
1228 	const char *t = NULL;
1229 
1230 	if (last - first < 4)
1231 		return (first);
1232 
1233 	if (first[2] == 'n' && (first[3] == 'a' || first[3] == 'w'))
1234 		t = parse_new_expr(first + 2, last, db);
1235 	else if (first[2] == 'd' && (first[3] == 'l' || first[3] == 'a'))
1236 		t = parse_del_expr(first + 2, last, db);
1237 	else
1238 		return (first);
1239 
1240 	if (t == first + 2)
1241 		return (first);
1242 
1243 	VERIFY3U(nlen(db), >, 0);
1244 
1245 	nfmt(db, "::{0}", NULL);
1246 	return (t);
1247 }
1248 
1249 /*
1250  * [gs] nw <expression>* _ <type> E		# new (expr-list) type
1251  * [gs] nw <expression>* _ <type> <initializer>	# new (expr-list) type (init)
1252  * [gs] na <expression>* _ <type> E		# new[] (expr-list) type
1253  * [gs] na <expression>* _ <type> <initializer>	# new[] (expr-list) type (init)
1254  * <initializer> ::= pi <expression>* E		# parenthesized initialization
1255  */
1256 static const char *
parse_new_expr(const char * first,const char * last,cpp_db_t * db)1257 parse_new_expr(const char *first, const char *last, cpp_db_t *db)
1258 {
1259 	VERIFY3P(first, <=, last);
1260 
1261 	/* note [gs] is already handled by parse_gs() */
1262 	if (last - first < 3)
1263 		return (first);
1264 
1265 	VERIFY3U(first[0], ==, 'n');
1266 	VERIFY(first[1] == 'a' || first[1] == 'w');
1267 
1268 	const char *t1 = first + 2;
1269 	const char *t2 = NULL;
1270 	size_t n = nlen(db);
1271 
1272 	nadd_l(db, (first[1] == 'w') ? "new" : "new[]", 0);
1273 
1274 	while (t1 != last && t1[0] != '_') {
1275 		t2 = parse_expression(t1, last, db);
1276 		VERIFY3P(t2, !=, NULL);
1277 		if (t2 == t1)
1278 			return (first);
1279 		t1 = t2;
1280 	}
1281 	if (t1 == last)
1282 		return (first);
1283 
1284 	if (NAMT(db, n) > 1) {
1285 		njoin(db, NAMT(db, n) - 1, ", ");
1286 		nfmt(db, "({0})", NULL);
1287 	}
1288 
1289 	t2 = parse_type(t1 + 1, last, db);
1290 	if (t1 + 1 == t2)
1291 		return (first);
1292 
1293 	if (t2[0] != 'E') {
1294 		if (last - t2 < 3)
1295 			return (first);
1296 		if (t2[0] != 'p' && t2[1] != 'i')
1297 			return (first);
1298 
1299 		t2 += 2;
1300 		const char *t3 = t2;
1301 		size_t n1 = nlen(db);
1302 
1303 		while (t2[0] != 'E' && t2 != last) {
1304 			t3 = parse_expression(t2, last, db);
1305 
1306 			if (t2 == t3)
1307 				return (first);
1308 			t2 = t3;
1309 		}
1310 		if (t3 == last || t3[0] != 'E')
1311 			return (first);
1312 
1313 		if (NAMT(db, n1) > 0) {
1314 			njoin(db, NAMT(db, n1), ", ");
1315 			nfmt(db, "({0})", NULL);
1316 		}
1317 	}
1318 
1319 	njoin(db, NAMT(db, n), " ");
1320 	return (t2 + 1);
1321 }
1322 
1323 static const char *
parse_del_expr(const char * first,const char * last,cpp_db_t * db)1324 parse_del_expr(const char *first, const char *last, cpp_db_t *db)
1325 {
1326 	VERIFY3P(first, <=, last);
1327 
1328 	if (last - first < 3)
1329 		return (first);
1330 
1331 	VERIFY3U(first[0], ==, 'd');
1332 	VERIFY(first[1] == 'l' || first[1] == 'a');
1333 
1334 	size_t n = nlen(db);
1335 	const char *t = parse_expression(first + 2, last, db);
1336 	if (t == first + 2 || NAMT(db, n) != 1)
1337 		return (first);
1338 
1339 	nfmt(db, (first[1] == 'a') ? "delete[] {0}" : "delete {0}", NULL);
1340 	return (t);
1341 }
1342 
1343 static const char *
parse_idx_expr(const char * first,const char * last,cpp_db_t * db)1344 parse_idx_expr(const char *first, const char *last, cpp_db_t *db)
1345 {
1346 	VERIFY3P(first, <=, last);
1347 	VERIFY3U(first[0], ==, 'i');
1348 	VERIFY3U(first[1], ==, 'x');
1349 
1350 	size_t n = nlen(db);
1351 	const char *t1 = parse_expression(first + 2, last, db);
1352 	if (t1 == first + 2)
1353 		return (first);
1354 
1355 	const char *t2 = parse_expression(t1, last, db);
1356 	if (t2 == t1 || NAMT(db, n) != 2)
1357 		return (first);
1358 
1359 	nfmt(db, "({0})[{1}]", NULL);
1360 	return (t2);
1361 }
1362 
1363 static const char *
parse_ppmm_expr(const char * first,const char * last,const char * fmt,cpp_db_t * db)1364 parse_ppmm_expr(const char *first, const char *last, const char *fmt,
1365     cpp_db_t *db)
1366 {
1367 	VERIFY3P(first, <=, last);
1368 
1369 	if (last - first < 3)
1370 		return (first);
1371 
1372 	const char *t = NULL;
1373 	size_t n = nlen(db);
1374 
1375 	if (first[2] == '_') {
1376 		t = parse_binary_expr(first + 3, last, "--", db);
1377 		if (t == first + 3)
1378 			return (first);
1379 		return (t);
1380 	}
1381 
1382 	t = parse_expression(first + 2, last, db);
1383 	if (t == first + 2 || NAMT(db, n) < 1)
1384 		return (first);
1385 
1386 	nfmt(db, fmt, NULL);
1387 	return (t);
1388 }
1389 
1390 static const char *
parse_mm_expr(const char * first,const char * last,cpp_db_t * db)1391 parse_mm_expr(const char *first, const char *last, cpp_db_t *db)
1392 {
1393 	VERIFY3P(first, <=, last);
1394 	VERIFY3U(first[0], ==, 'm');
1395 	VERIFY3U(first[1], ==, 'm');
1396 
1397 	return (parse_ppmm_expr(first, last, "({0})--", db));
1398 }
1399 
1400 static const char *
parse_pp_expr(const char * first,const char * last,cpp_db_t * db)1401 parse_pp_expr(const char *first, const char *last, cpp_db_t *db)
1402 {
1403 	VERIFY3P(first, <=, last);
1404 
1405 	VERIFY3U(first[0], ==, 'p');
1406 	VERIFY3U(first[0], ==, 'p');
1407 
1408 	return (parse_ppmm_expr(first, last, "({0})++", db));
1409 }
1410 
1411 static const char *
parse_trinary_expr(const char * first,const char * last,cpp_db_t * db)1412 parse_trinary_expr(const char *first, const char *last, cpp_db_t *db)
1413 {
1414 	VERIFY3P(first, <=, last);
1415 
1416 	const char *t1, *t2, *t3;
1417 	size_t n = nlen(db);
1418 
1419 	if (last - first < 2)
1420 		return (first);
1421 
1422 	t1 = parse_expression(first + 2, last, db);
1423 	if (t1 == first + 2)
1424 		return (first);
1425 	t2 = parse_expression(t1, last, db);
1426 	if (t1 == t2)
1427 		return (first);
1428 	t3 = parse_expression(t2, last, db);
1429 	if (t3 == t2)
1430 		return (first);
1431 
1432 	if (NAMT(db, n) != 3)
1433 		return (first);
1434 
1435 	nfmt(db, "({2}) ? ({1}) : ({0})", NULL);
1436 	return (t3);
1437 }
1438 
1439 static const char *
parse_noexcept_expr(const char * first,const char * last,cpp_db_t * db)1440 parse_noexcept_expr(const char *first, const char *last, cpp_db_t *db)
1441 {
1442 	VERIFY3P(first, <=, last);
1443 
1444 	if (last - first < 2)
1445 		return (first);
1446 
1447 	size_t n = nlen(db);
1448 	const char *t = parse_expression(first + 2, last, db);
1449 	if (t == first + 2 || NAMT(db, n) != 1)
1450 		return (first);
1451 
1452 	nfmt(db, "noexcept ({0})", NULL);
1453 	return (t);
1454 }
1455 
1456 /*
1457  * cc <type> <expression>	# const_cast<type> (expression)
1458  * dc <type> <expression>	# dynamic_cast<type> (expression)
1459  * rc <type> <expression>	# reinterpret_cast<type> (expression)
1460  * sc <type> <expression>	# static_cast<type> (expression)
1461  */
1462 static const char *
parse_cast_expr(const char * first,const char * last,cpp_db_t * db)1463 parse_cast_expr(const char *first, const char *last, cpp_db_t *db)
1464 {
1465 	VERIFY3P(first, <=, last);
1466 
1467 	if (last - first < 2)
1468 		return (first);
1469 
1470 	const char *fmt = NULL;
1471 	switch (first[0]) {
1472 	case 'c':
1473 		fmt = "const_cast<{1}> ({0})";
1474 		break;
1475 	case 'd':
1476 		fmt = "dynamic_cast<{1}> ({0})";
1477 		break;
1478 	case 'r':
1479 		fmt = "reinterpret_cast<{1}> ({0})";
1480 		break;
1481 	case 's':
1482 		fmt = "static_cast<{1}> ({0})";
1483 		break;
1484 	default:
1485 		return (first);
1486 	}
1487 
1488 	VERIFY3U(first[1], ==, 'c');
1489 
1490 	const char *t1 = parse_type(first + 2, last, db);
1491 	if (t1 == first + 2)
1492 		return (first);
1493 
1494 	const char *t2 = parse_expression(t1, last, db);
1495 	if (t2 == t1)
1496 		return (first);
1497 
1498 	VERIFY3U(nlen(db), >, 1);
1499 
1500 	nfmt(db, fmt, NULL);
1501 	return (t2);
1502 }
1503 
1504 /* pt <expression> <expression>		# expr->name */
1505 static const char *
parse_arrow_expr(const char * first,const char * last,cpp_db_t * db)1506 parse_arrow_expr(const char *first, const char *last, cpp_db_t *db)
1507 {
1508 	VERIFY3P(first, <=, last);
1509 
1510 	if (last - first < 4)
1511 		return (first);
1512 
1513 	size_t n = nlen(db);
1514 
1515 	const char *t1 = parse_expression(first + 2, last, db);
1516 	if (t1 == first + 2)
1517 		return (first);
1518 
1519 	const char *t2 = parse_expression(t1, last, db);
1520 	if (t2 == t1 || NAMT(db, n) != 2)
1521 		return (first);
1522 
1523 	nfmt(db, "{1}->{0}", NULL);
1524 	return (t2);
1525 }
1526 
1527 /* wrap value in () when necessary */
1528 static void
paren(str_pair_t * sp)1529 paren(str_pair_t *sp)
1530 {
1531 	str_t *l = &sp->strp_l;
1532 	str_t *r = &sp->strp_r;
1533 
1534 	if (str_length(r) > 1 &&
1535 	    r->str_s[0] == ' ' && r->str_s[1] == '[') {
1536 		(void) str_append(l, " (", 2);
1537 		(void) str_insert(r, 0, ")", 1);
1538 	} else if (str_length(r) > 0 && r->str_s[0] == '(') {
1539 		(void) str_append(l, "(", 1);
1540 		(void) str_insert(r, 0, ")", 1);
1541 	}
1542 }
1543 
1544 /* BEGIN CSTYLED */
1545 /*
1546  * <type> ::= <builtin-type>
1547  *        ::= <function-type>
1548  *        ::= <class-enum-type>
1549  *        ::= <array-type>
1550  *        ::= <pointer-to-member-type>
1551  *        ::= <template-param>
1552  *        ::= <template-template-param> <template-args>
1553  *        ::= <decltype>
1554  *        ::= <substitution>
1555  *        ::= <CV-qualifiers> <type>
1556  *        ::= P <type>        # pointer-to
1557  *        ::= R <type>        # reference-to
1558  *        ::= O <type>        # rvalue reference-to (C++0x)
1559  *        ::= C <type>        # complex pair (C 2000)
1560  *        ::= G <type>        # imaginary (C 2000)
1561  *        ::= Dp <type>       # pack expansion (C++0x)
1562  *        ::= U <source-name> <type>  # vendor extended type qualifier
1563  * extension := U <objc-name> <objc-type>  # objc-type<identifier>
1564  * extension := <vector-type> # <vector-type> starts with Dv
1565  *
1566  * <objc-name> ::= <k0 number> objcproto <k1 number> <identifier>  # k0 = 9 + <number of digits in k1> + k1
1567  * <objc-type> := <source-name>  # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1568  */
1569 /* END CSTYLED */
1570 static const char *
parse_type(const char * first,const char * last,cpp_db_t * db)1571 parse_type(const char *first, const char *last, cpp_db_t *db)
1572 {
1573 	VERIFY3P(first, <=, last);
1574 
1575 	if (first == last)
1576 		return (first);
1577 
1578 	switch (first[0]) {
1579 	case 'r':
1580 	case 'V':
1581 	case 'K':
1582 		return (parse_qual_type(first, last, db));
1583 	}
1584 
1585 	const char *t = first;
1586 	const char *t1 = NULL;
1587 	str_pair_t *sp = NULL;
1588 	size_t n = nlen(db);
1589 	size_t amt = 0;
1590 
1591 	t = parse_builtin_type(first, last, db);
1592 	if (t != first)
1593 		return (t);
1594 
1595 	switch (first[0]) {
1596 	case 'A':
1597 		t = parse_array_type(first, last, db);
1598 		if (t == first || NAMT(db, n) == 0)
1599 			return (first);
1600 		save_top(db, 1);
1601 		return (t);
1602 
1603 	case 'C':
1604 		t = parse_type(first + 1, last, db);
1605 		if (t == first + 1 || NAMT(db, n) == 0)
1606 			return (first);
1607 
1608 		(void) str_append(TOP_L(db), " complex", 8);
1609 		save_top(db, 1);
1610 		return (t);
1611 
1612 	case 'F':
1613 		t = parse_function_type(first, last, db);
1614 		if (t == first || NAMT(db, n) == 0)
1615 			return (first);
1616 		save_top(db, 1);
1617 		return (t);
1618 
1619 	case 'G':
1620 		t = parse_type(first + 1, last, db);
1621 		if (t == first + 1 || NAMT(db, n) == 0)
1622 			return (first);
1623 
1624 		(void) str_append(TOP_L(db), " imaginary", 10);
1625 		save_top(db, 1);
1626 		return (t);
1627 
1628 	case 'M':
1629 		t = parse_pointer_to_member_type(first, last, db);
1630 		if (t == first || NAMT(db, n) == 0)
1631 			return (first);
1632 		save_top(db, 1);
1633 		return (t);
1634 
1635 	case 'O':
1636 		t = parse_type(first + 1, last, db);
1637 		amt = NAMT(db, n);
1638 		if (t == first + 1 || amt == 0)
1639 			return (first);
1640 
1641 		sp = name_at(&db->cpp_name, amt - 1);
1642 		for (size_t i = 0; i < amt; i++, sp++) {
1643 			paren(sp);
1644 			if (str_pair_len(sp) > 0)
1645 				(void) str_append(&sp->strp_l, "&&", 2);
1646 		}
1647 
1648 		save_top(db, amt);
1649 		return (t);
1650 
1651 	case 'P':
1652 		t = parse_type(first + 1, last, db);
1653 		amt = NAMT(db, n);
1654 		if (t == first + 1 || amt == 0)
1655 			return (first);
1656 
1657 		sp = name_at(&db->cpp_name, amt - 1);
1658 		for (size_t i = 0; i < amt; i++, sp++) {
1659 			str_t *l = &sp->strp_l;
1660 
1661 			if (str_pair_len(sp) == 0)
1662 				continue;
1663 
1664 			paren(sp);
1665 			if (first[1] != 'U' ||
1666 			    strncmp(l->str_s, "objc_object<", 12) != 0) {
1667 				(void) str_append(l, "*", 1);
1668 			} else {
1669 				(void) str_erase(l, 0, 11);
1670 				(void) str_insert(l, 0, "id", 2);
1671 			}
1672 		}
1673 		save_top(db, amt);
1674 		return (t);
1675 
1676 	case 'R':
1677 		t = parse_type(first + 1, last, db);
1678 		amt = NAMT(db, n);
1679 		if (t == first + 1 || amt == 0)
1680 			return (first);
1681 
1682 		sp = name_at(&db->cpp_name, amt - 1);
1683 		for (size_t i = 0; i < amt; i++, sp++) {
1684 			if (str_length(&sp->strp_l) == 0 &&
1685 			    str_length(&sp->strp_r) == 0)
1686 				continue;
1687 
1688 			paren(sp);
1689 			(void) str_append(&sp->strp_l, "&", 1);
1690 		}
1691 
1692 		save_top(db, amt);
1693 		return (t);
1694 
1695 	case 'T':
1696 		t = parse_template_param(first, last, db);
1697 		if (t == first)
1698 			return (first);
1699 
1700 		amt = NAMT(db, n);
1701 		save_top(db, amt);
1702 		if (!db->cpp_try_to_parse_template_args || amt != 1)
1703 			return (t);
1704 
1705 		t1 = parse_template_args(t, last, db);
1706 		if (t1 == t)
1707 			return (t);
1708 
1709 		nfmt(db, "{1:L}{0}", "{1:R}");
1710 		save_top(db, 1);
1711 		return (t1);
1712 
1713 	case 'U':
1714 		if (first + 1 == last)
1715 			return (first);
1716 
1717 		t = parse_source_name(first + 1, last, db);
1718 		if (t == first + 1)
1719 			return (first);
1720 
1721 		nfmt(db, "{0}", NULL);
1722 
1723 		t1 = parse_type(t, last, db);
1724 		if (t1 == t || NAMT(db, n) < 2)
1725 			return (first);
1726 
1727 		const str_t *name = &name_at(&db->cpp_name, 1)->strp_l;
1728 
1729 		if (str_length(name) > 0 &&
1730 		    strncmp(name->str_s, "objcproto", 9) != 0) {
1731 			nfmt(db, "{0} {1}", NULL);
1732 		} else {
1733 			t = parse_source_name(name->str_s + 9,
1734 			    name->str_s + name->str_len, db);
1735 			if (t != name->str_s + 9) {
1736 				nfmt(db, "{1}<{0}>", NULL);
1737 
1738 				str_pair_t save = {0};
1739 
1740 				name_pop(&db->cpp_name, &save);
1741 
1742 				/* get rid of 'objcproto' */
1743 				name_pop(&db->cpp_name, NULL);
1744 				CK(name_add_str(&db->cpp_name, &save.strp_l,
1745 				    &save.strp_r));
1746 			} else {
1747 				nfmt(db, "{1} {0}", NULL);
1748 			}
1749 		}
1750 
1751 		save_top(db, 1);
1752 		return (t1);
1753 
1754 	case 'S':
1755 		if (first + 1 != last && first[1] == 't') {
1756 			t = parse_name(first, last, NULL, db);
1757 			if (t == first || NAMT(db, n) == 0)
1758 				return (first);
1759 
1760 			save_top(db, 1);
1761 			return (t);
1762 		}
1763 
1764 		t = parse_substitution(first, last, db);
1765 		if (t == first)
1766 			return (first);
1767 
1768 		/*
1769 		 * If the substitution is a <template-param>, it might
1770 		 * be followed by <template-args>
1771 		 */
1772 		t1 = parse_template_args(t, last, db);
1773 		if (t1 == t)
1774 			return (t);
1775 
1776 		if (NAMT(db, n) < 2)
1777 			return (t);
1778 
1779 		nfmt(db, "{1:L}{0}", "{1:R}");
1780 		save_top(db, 1);
1781 		return (t1);
1782 
1783 	case 'D':
1784 		if (first + 1 == last)
1785 			return (first);
1786 
1787 		switch (first[1]) {
1788 		case 'p':
1789 			t = parse_type(first + 2, last, db);
1790 			if (t == first + 2)
1791 				break;
1792 
1793 			save_top(db, NAMT(db, n));
1794 			return (t);
1795 
1796 		case 't':
1797 		case 'T':
1798 			t = parse_decltype(first, last, db);
1799 			if (first == t)
1800 				break;
1801 
1802 			save_top(db, 1);
1803 			return (t);
1804 
1805 		case 'v':
1806 			t = parse_vector_type(first, last, db);
1807 			if (first == t)
1808 				break;
1809 
1810 			if (NAMT(db, n) == 0)
1811 				return (first);
1812 
1813 			save_top(db, 1);
1814 			return (t);
1815 		}
1816 		break;
1817 	}
1818 
1819 	/*
1820 	 * must check for builtin-types before class-enum-types to avoid
1821 	 * ambiguities with operator-names
1822 	 */
1823 	t = parse_builtin_type(first, last, db);
1824 	if (t != first)
1825 		return (t);
1826 
1827 	t = parse_name(first, last, NULL, db);
1828 	if (t == first || NAMT(db, n) == 0)
1829 		return (first);
1830 
1831 	save_top(db, 1);
1832 	return (t);
1833 }
1834 
1835 static const char *
parse_qual_type(const char * first,const char * last,cpp_db_t * db)1836 parse_qual_type(const char *first, const char *last, cpp_db_t *db)
1837 {
1838 	VERIFY3P(first, <=, last);
1839 
1840 	const char *t = NULL;
1841 	const char *t1 = NULL;
1842 	unsigned cv = 0;
1843 
1844 	t = parse_cv_qualifiers(first, last, &cv);
1845 	if (t == first)
1846 		return (first);
1847 
1848 	size_t n = nlen(db);
1849 	boolean_t is_func = !!(t[0] == 'F');
1850 
1851 	t1 = parse_type(t, last, db);
1852 	size_t amt = NAMT(db, n);
1853 	if (t == t1 || amt == 0)
1854 		return (first);
1855 
1856 	if (is_func)
1857 		sub_pop(&db->cpp_subs);
1858 
1859 	str_pair_t *sp = name_at(&db->cpp_name, amt - 1);
1860 
1861 	for (size_t i = 0; i < amt; i++, sp++) {
1862 		str_t *s = NULL;
1863 
1864 		if (!is_func) {
1865 			s = &sp->strp_l;
1866 
1867 			if (str_length(s) == 0)
1868 				continue;
1869 
1870 			if (cv & 1)
1871 				(void) str_append(s, " const", 6);
1872 			if (cv & 2)
1873 				(void) str_append(s, " volatile", 9);
1874 			if (cv & 4)
1875 				(void) str_append(s, " restrict", 9);
1876 
1877 			continue;
1878 		}
1879 
1880 		s = &sp->strp_r;
1881 		size_t pos = str_length(s);
1882 
1883 		if (pos > 0 && s->str_s[pos - 1] == '&') {
1884 			pos--;
1885 			if (s->str_s[pos - 1] == '&')
1886 				pos--;
1887 		}
1888 
1889 		if (cv & 1) {
1890 			(void) str_insert(s, pos, " const", 6);
1891 			pos += 6;
1892 		}
1893 		if (cv & 2) {
1894 			(void) str_insert(s, pos, " volatile", 9);
1895 			pos += 9;
1896 		}
1897 		if (cv & 4) {
1898 			(void) str_insert(s, pos, " restrict", 9);
1899 		}
1900 	}
1901 
1902 	save_top(db, amt);
1903 	return (t1);
1904 }
1905 
1906 /*
1907  * at <type>		# alignof (a type)
1908  * az <expression>	# alignof (a expression)
1909  */
1910 static const char *
parse_alignof(const char * first,const char * last,cpp_db_t * db)1911 parse_alignof(const char *first, const char *last, cpp_db_t *db)
1912 {
1913 	VERIFY3P(first, <=, last);
1914 
1915 	if (last - first < 2)
1916 		return (first);
1917 
1918 	const char *(*fn)(const char *, const char *, cpp_db_t *);
1919 
1920 	fn = (first[1] == 't') ? parse_type : parse_expression;
1921 
1922 	size_t n = nlen(db);
1923 	const char *t = fn(first + 2, last, db);
1924 	if (t == first + 2 || NAMT(db, n) != 1)
1925 		return (first);
1926 
1927 	nfmt(db, "alignof ({0})", NULL);
1928 	return (t);
1929 }
1930 
1931 /*
1932  * st <type>	# sizeof (a type)
1933  * sz <expr>	# sizeof (a expression)
1934  */
1935 static const char *
parse_sizeof(const char * first,const char * last,cpp_db_t * db)1936 parse_sizeof(const char *first, const char *last, cpp_db_t *db)
1937 {
1938 	VERIFY3P(first, <=, last);
1939 
1940 	if (last - first < 2)
1941 		return (first);
1942 
1943 	VERIFY3U(first[0], ==, 's');
1944 
1945 	const char *t = NULL;
1946 	size_t n = nlen(db);
1947 
1948 	switch (first[1]) {
1949 	case 't':
1950 		t = parse_type(first + 2, last, db);
1951 		break;
1952 	case 'z':
1953 		t = parse_expression(first + 2, last, db);
1954 		break;
1955 	default:
1956 		return (first);
1957 	}
1958 	if (t == first + 2 || NAMT(db, n) != 1)
1959 		return (first);
1960 
1961 	nfmt(db, "sizeof ({0})", NULL);
1962 	return (t);
1963 }
1964 
1965 /* BEGIN CSTYLED */
1966 /*
1967  * <function-param> ::= fp <top-level CV-qualifiers> _                                     # L == 0, first parameter
1968  *                  ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _   # L == 0, second and later parameters
1969  *                  ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _         # L > 0, first parameter
1970  *                  ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _   # L > 0, second and later parameters
1971  */
1972 /* END CSTYLED */
1973 static const char *
parse_function_param(const char * first,const char * last,cpp_db_t * db)1974 parse_function_param(const char *first, const char *last, cpp_db_t *db)
1975 {
1976 	VERIFY3P(first, <=, last);
1977 
1978 	if (last - first < 3 || first[0] != 'f')
1979 		return (first);
1980 
1981 	const char *t1 = first + 2;
1982 	const char *t2 = NULL;
1983 	unsigned cv = 0;
1984 
1985 	if (first[1] == 'L') {
1986 		t2 = parse_number(t1, last);
1987 		if (t2 == last || t2[0] != 'p')
1988 			return (first);
1989 		t1 = t2;
1990 	}
1991 
1992 	if (first[1] != 'p')
1993 		return (first);
1994 
1995 	t1 = parse_cv_qualifiers(t1, last, &cv);
1996 	t2 = parse_number(t1, last);
1997 	if (t2 == last || t2[0] != '_')
1998 		return (first);
1999 
2000 	if (t2 - t1 > 0)
2001 		nadd_l(db, t1, (size_t)(t2 - t1));
2002 	else
2003 		nadd_l(db, "", 0);
2004 
2005 	nfmt(db, "fp{0}", NULL);
2006 	return (t2 + 1);
2007 }
2008 
2009 /*
2010  * sZ <template-param>		# size of a parameter pack
2011  * sZ <function-param>		# size of a function parameter pack
2012  */
2013 static const char *
parse_sizeof_param_pack_expr(const char * first,const char * last,cpp_db_t * db)2014 parse_sizeof_param_pack_expr(const char *first, const char *last, cpp_db_t *db)
2015 {
2016 	VERIFY3P(first, <=, last);
2017 
2018 	if (last - first < 3)
2019 		return (first);
2020 
2021 	VERIFY3U(first[0], ==, 's');
2022 	VERIFY3U(first[1], ==, 'Z');
2023 
2024 	if (first[2] != 'T' && first[2] != 'f')
2025 		return (first);
2026 
2027 	const char *t = NULL;
2028 	size_t n = nlen(db);
2029 
2030 	if (first[2] == 'T')
2031 		t = parse_template_param(first + 2, last, db);
2032 	else
2033 		t = parse_function_param(first + 2, last, db);
2034 
2035 	if (t == first + 2)
2036 		return (first);
2037 
2038 	njoin(db, NAMT(db, n), ", ");
2039 	nfmt(db, "sizeof...({0})", NULL);
2040 	return (t);
2041 }
2042 
2043 /*
2044  * te <expression>                                      # typeid (expression)
2045  * ti <type>                                            # typeid (type)
2046  */
2047 static const char *
parse_typeid_expr(const char * first,const char * last,cpp_db_t * db)2048 parse_typeid_expr(const char *first, const char *last, cpp_db_t *db)
2049 {
2050 	VERIFY3P(first, <=, last);
2051 
2052 	if (last - first < 3)
2053 		return (first);
2054 
2055 	VERIFY3U(first[0], ==, 't');
2056 	VERIFY(first[1] == 'e' || first[1] == 'i');
2057 
2058 	const char *t = NULL;
2059 	size_t n = nlen(db);
2060 
2061 	if (first[1] == 'e')
2062 		t = parse_expression(first + 2, last, db);
2063 	else
2064 		t = parse_type(first + 2, last, db);
2065 
2066 	if (t == first + 2 || NAMT(db, n) != 1)
2067 		return (first);
2068 
2069 	nfmt(db, "typeid ({0})", NULL);
2070 	return (t);
2071 }
2072 
2073 /*
2074  * tr							# throw
2075  * tw <expression>					# throw expression
2076  */
2077 static const char *
parse_throw_expr(const char * first,const char * last,cpp_db_t * db)2078 parse_throw_expr(const char *first, const char *last, cpp_db_t *db)
2079 {
2080 	VERIFY3P(first, <=, last);
2081 
2082 	if (last - first < 3)
2083 		return (first);
2084 
2085 	VERIFY3U(first[0], ==, 't');
2086 	VERIFY(first[1] == 'w' || first[1] == 'r');
2087 
2088 	if (first[1] == 'r') {
2089 		nadd_l(db, "throw", 0);
2090 		return (first + 2);
2091 	}
2092 
2093 	size_t n = nlen(db);
2094 	const char *t = parse_expression(first + 2, last, db);
2095 	if (t == first + 2 || NAMT(db, n) != 1)
2096 		return (first);
2097 
2098 	nfmt(db, "throw {0}", NULL);
2099 	return (t);
2100 }
2101 
2102 /* ds <expression> <expression>		# expr.*expr */
2103 static const char *
parse_dot_star_expr(const char * first,const char * last,cpp_db_t * db)2104 parse_dot_star_expr(const char *first, const char *last, cpp_db_t *db)
2105 {
2106 	VERIFY3P(first, <=, last);
2107 
2108 	if (last - first < 3)
2109 		return (first);
2110 
2111 	VERIFY3U(first[0], ==, 'd');
2112 	VERIFY3U(first[1], ==, 's');
2113 
2114 	size_t n = nlen(db);
2115 	const char *t = parse_expression(first + 2, last, db);
2116 	if (t == first + 2)
2117 		return (first);
2118 
2119 	const char *t2 = parse_expression(t, last, db);
2120 	if (t == t2 || NAMT(db, n) != 2)
2121 		return (first);
2122 
2123 	nfmt(db, "{1}.*{0}", NULL);
2124 	return (t2);
2125 }
2126 
2127 /* dt <expression> <unresolved-name>		# expr.name */
2128 static const char *
parse_dot_expr(const char * first,const char * last,cpp_db_t * db)2129 parse_dot_expr(const char *first, const char *last, cpp_db_t *db)
2130 {
2131 	VERIFY3P(first, <=, last);
2132 
2133 	if (last - first < 3)
2134 		return (first);
2135 
2136 	VERIFY3U(first[0], ==, 'd');
2137 	VERIFY3U(first[1], ==, 't');
2138 
2139 	const char *t = parse_expression(first + 2, last, db);
2140 	if (t == first + 2)
2141 		return (first);
2142 
2143 	const char *t1 = parse_unresolved_name(t, last, db);
2144 	if (t1 == t)
2145 		return (first);
2146 
2147 	nfmt(db, "{1}.{0}", NULL);
2148 	return (t1);
2149 }
2150 
2151 /* cl <expression>+ E		# call */
2152 static const char *
parse_call_expr(const char * first,const char * last,cpp_db_t * db)2153 parse_call_expr(const char *first, const char *last, cpp_db_t *db)
2154 {
2155 	VERIFY3P(first, <=, last);
2156 
2157 	if (last - first < 4)
2158 		return (first);
2159 
2160 	VERIFY3U(first[0], ==, 'c');
2161 	VERIFY3U(first[1], ==, 'l');
2162 
2163 	const char *t = first + 2;
2164 	const char *t1 = NULL;
2165 	size_t n = nlen(db);
2166 
2167 	for (t = first + 2; t != last && t[0] != 'E'; t = t1) {
2168 		t1 = parse_expression(t, last, db);
2169 		if (t1 == t)
2170 			return (first);
2171 	}
2172 
2173 	size_t amt = NAMT(db, n);
2174 
2175 	if (t == last || amt == 0)
2176 		return (first);
2177 
2178 	njoin(db, amt - 1, ", ");
2179 	nfmt(db, "{1}({0})", NULL);
2180 
2181 	VERIFY3U(t[0], ==, 'E');
2182 	return (t + 1);
2183 }
2184 
2185 /* BEGIN CSTYLED */
2186 /*
2187  * cv <type> <expression>	# conversion with one argument
2188  * cv <type> _ <expression>* E	# conversion with a different number of arguments
2189  */
2190 /* END CSTYLED */
2191 static const char *
parse_conv_expr(const char * first,const char * last,cpp_db_t * db)2192 parse_conv_expr(const char *first, const char *last, cpp_db_t *db)
2193 {
2194 	VERIFY3P(first, <=, last);
2195 
2196 	if (last - first < 3)
2197 		return (first);
2198 
2199 	VERIFY3U(first[0], ==, 'c');
2200 	VERIFY3U(first[1], ==, 'v');
2201 
2202 	const char *t = NULL;
2203 	const char *t1 = NULL;
2204 	size_t n = nlen(db);
2205 
2206 	boolean_t try_to_parse_template_args =
2207 	    db->cpp_try_to_parse_template_args;
2208 
2209 	db->cpp_try_to_parse_template_args = B_FALSE;
2210 	t = parse_type(first + 2, last, db);
2211 	db->cpp_try_to_parse_template_args = try_to_parse_template_args;
2212 
2213 	if (t == first + 2)
2214 		return (first);
2215 
2216 	if (t[0] != '_') {
2217 		t1 = parse_expression(t, last, db);
2218 		if (t1 == t)
2219 			return (first);
2220 
2221 		t = t1;
2222 	} else {
2223 		size_t n1 = nlen(db);
2224 
2225 		/* skip _ */
2226 		t++;
2227 		while (t[0] != 'E' && t != last) {
2228 			t1 = parse_expression(t, last, db);
2229 			if (t1 == t)
2230 				return (first);
2231 			t1 = t;
2232 		}
2233 
2234 		/* E */
2235 		t++;
2236 
2237 		njoin(db, NAMT(db, n1), ", ");
2238 	}
2239 
2240 	if (NAMT(db, n) < 2)
2241 		return (first);
2242 
2243 	nfmt(db, "({1})({0})", NULL);
2244 	return (t);
2245 }
2246 
2247 /* <simple-id> ::= <source-name> [ <template-args> ] */
2248 static const char *
parse_simple_id(const char * first,const char * last,cpp_db_t * db)2249 parse_simple_id(const char *first, const char *last, cpp_db_t *db)
2250 {
2251 	VERIFY3P(first, <=, last);
2252 
2253 	const char *t = parse_source_name(first, last, db);
2254 	if (t == first)
2255 		return (t);
2256 
2257 	const char *t1 = parse_template_args(t, last, db);
2258 	if (t == t1)
2259 		return (t);
2260 
2261 	nfmt(db, "{1}{0}", NULL);
2262 	return (t1);
2263 }
2264 
2265 /*
2266  * <unresolved-type> ::= <template-param>
2267  *                   ::= <decltype>
2268  *                   ::= <substitution>
2269  */
2270 static const char *
parse_unresolved_type(const char * first,const char * last,cpp_db_t * db)2271 parse_unresolved_type(const char *first, const char *last, cpp_db_t *db)
2272 {
2273 	VERIFY3P(first, <=, last);
2274 
2275 	if (first == last)
2276 		return (first);
2277 
2278 	const char *t = first;
2279 	size_t n = nlen(db);
2280 
2281 	switch (first[0]) {
2282 	case 'T':
2283 		t = parse_template_param(first, last, db);
2284 		if (t == first || NAMT(db, n) != 1) {
2285 			for (size_t i = 0; i < NAMT(db, n); i++)
2286 				name_pop(&db->cpp_name, NULL);
2287 			return (first);
2288 		}
2289 		save_top(db, 1);
2290 		return (t);
2291 
2292 	case 'D':
2293 		t = parse_decltype(first, last, db);
2294 		if (t == first || NAMT(db, n) == 0)
2295 			return (first);
2296 		save_top(db, 1);
2297 		return (t);
2298 
2299 	case 'S':
2300 		t = parse_substitution(first, last, db);
2301 		if (t != first)
2302 			return (t);
2303 
2304 		if (last - first < 2 || first[1] != 't')
2305 			return (first);
2306 
2307 		t = parse_unqualified_name(first + 2, last, db);
2308 		if (t == first + 2 || NAMT(db, n) == 0)
2309 			return (first);
2310 
2311 		nfmt(db, "std::{0:L}", "{0:R}");
2312 		save_top(db, 1);
2313 		return (t);
2314 	}
2315 
2316 	return (first);
2317 }
2318 
2319 /* sp <expression>		# pack expansion */
2320 static const char *
parse_pack_expansion(const char * first,const char * last,cpp_db_t * db)2321 parse_pack_expansion(const char *first, const char *last, cpp_db_t *db)
2322 {
2323 	VERIFY3P(first, <=, last);
2324 
2325 	if (last - first < 3)
2326 		return (first);
2327 
2328 	VERIFY3U(first[0], ==, 's');
2329 	VERIFY3U(first[1], ==, 'p');
2330 
2331 	const char *t = parse_expression(first + 2, last, db);
2332 	if (t == first +2)
2333 		return (first);
2334 
2335 	return (t);
2336 }
2337 
2338 /*
2339  * <unscoped-name> ::= <unqualified-name>
2340  *                 ::= St <unqualified-name>   # ::std::
2341  * extension       ::= StL<unqualified-name>
2342  */
2343 static const char *
parse_unscoped_name(const char * first,const char * last,cpp_db_t * db)2344 parse_unscoped_name(const char *first, const char *last, cpp_db_t *db)
2345 {
2346 	VERIFY3P(first, <=, last);
2347 
2348 	if (last - first < 2)
2349 		return (first);
2350 
2351 	const char *t = first;
2352 	const char *t1 = NULL;
2353 	boolean_t st = B_FALSE;
2354 
2355 	if (first[0] == 'S' && first[1] == 't') {
2356 		st = B_TRUE;
2357 		t = first + 2;
2358 
2359 		if (first + 3 != last && first[2] == 'L')
2360 			t++;
2361 	}
2362 
2363 	t1 = parse_unqualified_name(t, last, db);
2364 	if (t == t1)
2365 		return (first);
2366 
2367 	if (st)
2368 		nfmt(db, "std::{0}", NULL);
2369 
2370 	return (t1);
2371 }
2372 
2373 /*
2374  * <unqualified-name> ::= <operator-name>
2375  *                    ::= <ctor-dtor-name>
2376  *                    ::= <source-name>
2377  *                    ::= <unnamed-type-name>
2378  */
2379 const char *
parse_unqualified_name(const char * first,const char * last,cpp_db_t * db)2380 parse_unqualified_name(const char *first, const char *last, cpp_db_t *db)
2381 {
2382 	VERIFY3P(first, <=, last);
2383 
2384 	if (first == last)
2385 		return (first);
2386 
2387 	switch (*first) {
2388 	case 'C':
2389 	case 'D':
2390 		return (parse_ctor_dtor_name(first, last, db));
2391 	case 'U':
2392 		return (parse_unnamed_type_name(first, last, db));
2393 
2394 	case '1':
2395 	case '2':
2396 	case '3':
2397 	case '4':
2398 	case '5':
2399 	case '6':
2400 	case '7':
2401 	case '8':
2402 	case '9':
2403 		return (parse_source_name(first, last, db));
2404 	default:
2405 		return (parse_operator_name(first, last, db));
2406 	}
2407 }
2408 
2409 /*
2410  * <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
2411  *                     ::= <closure-type-name>
2412  *
2413  * <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2414  *
2415  * <lambda-sig> ::= <parameter type>+
2416  *			# Parameter types or "v" if the lambda has no parameters
2417  */
2418 static const char *
parse_unnamed_type_name(const char * first,const char * last,cpp_db_t * db)2419 parse_unnamed_type_name(const char *first, const char *last, cpp_db_t *db)
2420 {
2421 	VERIFY3P(first, <=, last);
2422 
2423 	if (last - first < 2 || first[0] != 'U')
2424 		return (first);
2425 
2426 	if (first[1] != 't' && first[1] != 'l')
2427 		return (first);
2428 
2429 	const char *t1 = first + 2;
2430 	const char *t2 = NULL;
2431 
2432 	if (first[1] == 't') {
2433 		while (t1 != last && t1[0] != '_' && ISDIGIT(t1[0]))
2434 			t1++;
2435 
2436 		if (t1[0] != '_')
2437 			return (first);
2438 
2439 		if (t1 == first + 2)
2440 			nadd_l(db, "", 0);
2441 		else
2442 			nadd_l(db, first + 2, (size_t)(t1 - first - 2));
2443 
2444 		nfmt(db, "'unnamed{0}'", NULL);
2445 		return (t1 + 1);
2446 	}
2447 
2448 	size_t n = nlen(db);
2449 
2450 	if (first[2] != 'v') {
2451 		do {
2452 			t2 = parse_type(t1, last, db);
2453 			if (t1 == t2)
2454 				return (first);
2455 			t1 = t2;
2456 		} while (t1 != last && t1[0] != 'E');
2457 
2458 		if (t1 == last || NAMT(db, n) < 1)
2459 			return (first);
2460 
2461 		if (NAMT(db, n) < 1)
2462 			return (first);
2463 	} else {
2464 		t1++;
2465 		if (t1[0] != 'E')
2466 			return (first);
2467 	}
2468 
2469 	njoin(db, NAMT(db, n), ", ");
2470 
2471 	/* E */
2472 	t1++;
2473 
2474 	t2 = t1;
2475 	while (t2 != last && t2[0] != '_') {
2476 		char c = *t2++;
2477 		if (!ISDIGIT(c))
2478 			return (first);
2479 	}
2480 
2481 	if (t2[0] != '_')
2482 		return (first);
2483 
2484 	if (t2 - t1 > 0)
2485 		nadd_l(db, t1, (size_t)(t2 - t1));
2486 	else
2487 		nadd_l(db, "", 0);
2488 
2489 	nfmt(db, "'lambda{0}'({1})", NULL);
2490 
2491 	/* _ */
2492 	return (t2 + 1);
2493 }
2494 
2495 static struct {
2496 	const char *alias;
2497 	const char *fullname;
2498 	const char *basename;
2499 } aliases[] = {
2500 	{
2501 		"std::string",
2502 		"std::basic_string<char, std::char_traits<char>, "
2503 		    "std::allocator<char> >",
2504 		"basic_string"
2505 	},
2506 	{
2507 		"std::istream",
2508 		"std::basic_istream<char, std::char_traits<char> >",
2509 		"basic_istream"
2510 	},
2511 	{
2512 		"std::ostream",
2513 		"std::basic_ostream<char, std::char_traits<char> >",
2514 		"basic_ostream"
2515 	},
2516 	{
2517 		"std::iostream",
2518 		"std::basic_iostream<char, std::char_traits<char> >",
2519 		"basic_iostream"
2520 	}
2521 };
2522 
2523 static void
basename(cpp_db_t * db)2524 basename(cpp_db_t *db)
2525 {
2526 	str_t *s = TOP_L(db);
2527 
2528 	for (size_t i = 0; i < ARRAY_SIZE(aliases); i++) {
2529 		if (str_length(s) != strlen(aliases[i].alias))
2530 			continue;
2531 		if (strncmp(aliases[i].alias, s->str_s, str_length(s)) != 0)
2532 			continue;
2533 
2534 		/* swap out alias for full name */
2535 		sysdem_ops_t *ops = s->str_ops;
2536 		str_fini(s);
2537 		str_init(s, ops);
2538 		str_set(s, aliases[i].fullname, 0);
2539 
2540 		nadd_l(db, aliases[i].basename, 0);
2541 		return;
2542 	}
2543 
2544 	const char *start = s->str_s;
2545 	const char *end = s->str_s + s->str_len;
2546 
2547 	/*
2548 	 * if name ends with a template i.e. <.....> back up to start
2549 	 * of outermost template
2550 	 */
2551 	unsigned c = 0;
2552 
2553 	if (end[-1] == '>') {
2554 		for (; end > start; end--) {
2555 			switch (end[-1]) {
2556 			case '<':
2557 				if (--c == 0) {
2558 					end--;
2559 					goto out;
2560 				}
2561 				break;
2562 			case '>':
2563 				c++;
2564 				break;
2565 			}
2566 		}
2567 	}
2568 
2569 out:
2570 	VERIFY3P(end, >=, start);
2571 
2572 	if (end - start < 2) {
2573 		nadd_l(db, "", 0);
2574 		return;
2575 	}
2576 
2577 	for (start = end - 1; start > s->str_s; start--) {
2578 		if (start[0] == ':') {
2579 			start++;
2580 			break;
2581 		}
2582 	}
2583 
2584 	VERIFY3P(end, >=, start);
2585 
2586 	nadd_l(db, start, (size_t)(end - start));
2587 }
2588 
2589 /*
2590  * <ctor-dtor-name> ::= C1    # complete object constructor
2591  *                  ::= C2    # base object constructor
2592  *                  ::= C3    # complete object allocating constructor
2593  *   extension      ::= C5    # ?
2594  *                  ::= D0    # deleting destructor
2595  *                  ::= D1    # complete object destructor
2596  *                  ::= D2    # base object destructor
2597  *   extension      ::= D5    # ?
2598  */
2599 static const char *
parse_ctor_dtor_name(const char * first,const char * last,cpp_db_t * db)2600 parse_ctor_dtor_name(const char *first, const char *last, cpp_db_t *db)
2601 {
2602 	VERIFY3P(first, <=, last);
2603 
2604 	if (last - first < 2 || nempty(db) || str_length(TOP_L(db)) == 0)
2605 		return (first);
2606 
2607 	switch (first[0]) {
2608 	case 'C':
2609 		switch (first[1]) {
2610 		case '1':
2611 		case '2':
2612 		case '3':
2613 		case '5':
2614 			basename(db);
2615 			break;
2616 		default:
2617 			return (first);
2618 		}
2619 		break;
2620 	case 'D':
2621 		switch (first[1]) {
2622 		case '0':
2623 		case '1':
2624 		case '2':
2625 		case '5':
2626 			basename(db);
2627 			(void) str_insert(TOP_L(db), 0, "~", 1);
2628 			break;
2629 		default:
2630 			return (first);
2631 		}
2632 		break;
2633 	default:
2634 		return (first);
2635 	}
2636 
2637 	db->cpp_parsed_ctor_dtor_cv = B_TRUE;
2638 	return (first + 2);
2639 }
2640 
2641 static const char *
parse_integer_literal(const char * first,const char * last,const char * fmt,cpp_db_t * db)2642 parse_integer_literal(const char *first, const char *last, const char *fmt,
2643     cpp_db_t *db)
2644 {
2645 	VERIFY3P(first, <=, last);
2646 
2647 	const char *t = parse_number(first, last);
2648 	const char *start = first;
2649 
2650 	if (t == first || t == last || t[0] != 'E')
2651 		return (first);
2652 
2653 	if (first[0] == 'n')
2654 		start++;
2655 
2656 	nadd_l(db, start, (size_t)(t - start));
2657 	if (start != first)
2658 		nfmt(db, "-{0}", NULL);
2659 
2660 	nfmt(db, fmt, NULL);
2661 	return (t + 1);
2662 }
2663 
2664 static struct float_data_s {
2665 	const char *spec;
2666 	size_t mangled_size;
2667 	size_t max_demangled_size;
2668 	char type;
2669 } float_info[] = {
2670 	{ "%af", 8, 24, 'f' },		/* float */
2671 	{ "%a", 16, 32, 'd' },		/* double */
2672 	{ "%LaL", 20, 40, 'e' }		/* long double */
2673 };
2674 
2675 static const char *
parse_floating_literal(const char * first,const char * last,cpp_db_t * db)2676 parse_floating_literal(const char *first, const char *last, cpp_db_t *db)
2677 {
2678 	VERIFY3P(first, <=, last);
2679 	VERIFY(first[0] == 'f' || first[0] == 'd' || first[0] == 'e');
2680 
2681 	const struct float_data_s *fd = NULL;
2682 
2683 	for (size_t i = 0; i < ARRAY_SIZE(float_info); i++) {
2684 		if (float_info[i].type != first[0])
2685 			continue;
2686 
2687 		fd = &float_info[i];
2688 		break;
2689 	}
2690 
2691 	if (fd == NULL || (size_t)(last - first) < fd->mangled_size)
2692 		return (first);
2693 
2694 	union {
2695 		union {
2696 			float v;
2697 			char buf[sizeof (float)];
2698 		} f;
2699 		union {
2700 			double v;
2701 			char buf[sizeof (double)];
2702 		} d;
2703 		union {
2704 			long double v;
2705 			char buf[sizeof (long double)];
2706 		} ld;
2707 	} conv;
2708 
2709 	const char *t = NULL;
2710 	char *e = NULL;
2711 
2712 	switch (first[0]) {
2713 	case 'f':
2714 		e = conv.f.buf;
2715 		break;
2716 	case 'd':
2717 		e = conv.d.buf;
2718 		break;
2719 	case 'e':
2720 		e = conv.ld.buf;
2721 		break;
2722 	}
2723 	last = first + fd->mangled_size + 1;
2724 
2725 #if defined(_BIG_ENDIAN)
2726 	for (t = first + 1; t != last; t++, e++) {
2727 		if (!is_xdigit(t[0]))
2728 			return (first);
2729 
2730 		unsigned d1 = ISDIGIT(t[0]) ?  t[0] - '0' : t[0] - 'a' + 10;
2731 		t++;
2732 		unsigned d0 = ISDIGIT(t[0]) ?  t[0] - '0' : t[0] - 'a' + 10;
2733 
2734 		*e = (d1 << 4) + d0;
2735 	}
2736 #elif defined(_LITTLE_ENDIAN)
2737 	for (t = last - 1; t > first; t--, e++) {
2738 		if (!is_xdigit(t[0]))
2739 			return (first);
2740 
2741 		unsigned d0 = ISDIGIT(t[0]) ?  t[0] - '0' : t[0] - 'a' + 10;
2742 		t--;
2743 		unsigned d1 = ISDIGIT(t[0]) ?  t[0] - '0' : t[0] - 'a' + 10;
2744 
2745 		*e = (d1 << 4) + d0;
2746 	}
2747 	t = last;
2748 #else
2749 #error One of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined
2750 #endif
2751 
2752 	if (t[0] != 'E')
2753 		return (first);
2754 
2755 	str_t num = { 0 };
2756 	str_init(&num, db->cpp_ops);
2757 
2758 	num.str_size = fd->max_demangled_size + 1;
2759 	num.str_s = zalloc(db->cpp_ops, num.str_size);
2760 	CK(num.str_s != NULL);
2761 
2762 	int n = 0;
2763 
2764 	switch (first[0]) {
2765 	case 'f':
2766 		n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2767 		    conv.f.v);
2768 		break;
2769 	case 'd':
2770 		n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2771 		    conv.d.v);
2772 		break;
2773 	case 'e':
2774 		n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2775 		    conv.ld.v);
2776 	}
2777 
2778 	if (n >= fd->max_demangled_size || n <= 0) {
2779 		str_fini(&num);
2780 		return (first);
2781 	}
2782 
2783 	num.str_len = n;
2784 	(void) name_add_str(&db->cpp_name, &num, NULL);
2785 
2786 	return (t + 1);
2787 }
2788 
2789 /*
2790  * <expr-primary> ::= L <type> <value number> E	# integer literal
2791  *                ::= L <type> <value float> E	# floating literal
2792  *                ::= L <string type> E		# string literal
2793  *                ::= L <nullptr type> E	# nullptr literal (i.e., "LDnE")
2794  *
2795  *                ::= L <type> <real-part float> _ <imag-part float> E
2796  *						# complex floating point
2797  *						# literal (C 2000)
2798  *
2799  *                ::= L <mangled-name> E	# external name
2800  */
2801 static struct {
2802 	int		c;
2803 	const char	*fmt;
2804 } int_lits[] = {
2805 	{ 'a', "(signed char){0}" },
2806 	{ 'c', "(char){0}" },
2807 	{ 'h', "(unsigned char){0}" },
2808 	{ 'i', "{0}" },
2809 	{ 'j', "{0}u" },
2810 	{ 'l', "{0}l" },
2811 	{ 'm', "{0}ul" },
2812 	{ 'n', "(__int128){0}" },
2813 	{ 'o', "(unsigned __int128){0}" },
2814 	{ 's', "(short){0}" },
2815 	{ 't', "(unsigned short){0}" },
2816 	{ 'w', "(wchar_t){0}" },
2817 	{ 'x', "{0}ll" },
2818 	{ 'y', "{0}ull" }
2819 };
2820 
2821 static const char *
parse_expr_primary(const char * first,const char * last,cpp_db_t * db)2822 parse_expr_primary(const char *first, const char *last, cpp_db_t *db)
2823 {
2824 	VERIFY3P(first, <=, last);
2825 
2826 	if (last - first < 4 || first[0] != 'L')
2827 		return (first);
2828 
2829 	const char *t = NULL;
2830 
2831 	for (size_t i = 0; i < ARRAY_SIZE(int_lits); i++) {
2832 		if (first[1] == int_lits[i].c) {
2833 			t = parse_integer_literal(first + 2, last,
2834 			    int_lits[i].fmt, db);
2835 			return ((t == first + 2) ? first : t);
2836 		}
2837 	}
2838 
2839 	switch (first[1]) {
2840 	case 'b':
2841 		if (first[3] != 'E')
2842 			return (first);
2843 
2844 		switch (first[2]) {
2845 		case '0':
2846 			nadd_l(db, "false", 5);
2847 			break;
2848 		case '1':
2849 			nadd_l(db, "true", 4);
2850 			break;
2851 		default:
2852 			return (first);
2853 		}
2854 		return (first + 4);
2855 	case 'd':	/* double */
2856 	case 'e':	/* long double */
2857 	case 'f':	/* float */
2858 		t = parse_floating_literal(first + 1, last, db);
2859 		return ((t == first + 1) ? first : t);
2860 	case 'T':
2861 /* BEGIN CSTYLED */
2862 		/*
2863 		 * Invalid mangled name per
2864 		 *   http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
2865 		 *
2866 		 */
2867 /* END CSTYLED */
2868 		return (first);
2869 	case '_':
2870 		if (first[2] != 'Z')
2871 			return (first);
2872 
2873 		t = parse_encoding(first + 3, last, db);
2874 		if (t == first + 3 || t == last || t[0] != 'E')
2875 			return (first);
2876 
2877 		/* skip E */
2878 		return (t + 1);
2879 	default:
2880 		t = parse_type(first + 1, last, db);
2881 		if (t == first + 1 || t == last)
2882 			return (first);
2883 
2884 		if (t[0] == 'E')
2885 			return (t + 1);
2886 
2887 		const char *n;
2888 		for (n = t; n != last && ISDIGIT(n[0]); n++)
2889 			;
2890 		if (n == last || nempty(db) || n[0] != 'E')
2891 			return (first);
2892 		if (n == t)
2893 			return (t);
2894 
2895 		nadd_l(db, t, (size_t)(n - t));
2896 		nfmt(db, "({1}){0}", NULL);
2897 
2898 		return (n + 1);
2899 	}
2900 }
2901 
2902 /*
2903  *   <operator-name>
2904  *                   ::= aa    # &&
2905  *                   ::= ad    # & (unary)
2906  *                   ::= an    # &
2907  *                   ::= aN    # &=
2908  *                   ::= aS    # =
2909  *                   ::= cl    # ()
2910  *                   ::= cm    # ,
2911  *                   ::= co    # ~
2912  *                   ::= cv <type>    # (cast)
2913  *                   ::= da    # delete[]
2914  *                   ::= de    # * (unary)
2915  *                   ::= dl    # delete
2916  *                   ::= dv    # /
2917  *                   ::= dV    # /=
2918  *                   ::= eo    # ^
2919  *                   ::= eO    # ^=
2920  *                   ::= eq    # ==
2921  *                   ::= ge    # >=
2922  *                   ::= gt    # >
2923  *                   ::= ix    # []
2924  *                   ::= le    # <=
2925  *                   ::= li <source-name>	# operator ""
2926  *                   ::= ls    # <<
2927  *                   ::= lS    # <<=
2928  *                   ::= lt    # <
2929  *                   ::= mi    # -
2930  *                   ::= mI    # -=
2931  *                   ::= ml    # *
2932  *                   ::= mL    # *=
2933  *                   ::= mm    # -- (postfix in <expression> context)
2934  *                   ::= na    # new[]
2935  *                   ::= ne    # !=
2936  *                   ::= ng    # - (unary)
2937  *                   ::= nt    # !
2938  *                   ::= nw    # new
2939  *                   ::= oo    # ||
2940  *                   ::= or    # |
2941  *                   ::= oR    # |=
2942  *                   ::= pm    # ->*
2943  *                   ::= pl    # +
2944  *                   ::= pL    # +=
2945  *                   ::= pp    # ++ (postfix in <expression> context)
2946  *                   ::= ps    # + (unary)
2947  *                   ::= pt    # ->
2948  *                   ::= qu    # ?
2949  *                   ::= rm    # %
2950  *                   ::= rM    # %=
2951  *                   ::= rs    # >>
2952  *                   ::= rS    # >>=
2953  *                   ::= v <digit> <source-name> # vendor extended operator
2954  */
2955 static struct {
2956 	const char code[3];
2957 	const char *op;
2958 } op_tbl[] = {
2959 	{ "aa", "operator&&" },
2960 	{ "ad", "operator&" },
2961 	{ "an", "operator&" },
2962 	{ "aN", "operator&=" },
2963 	{ "aS", "operator=" },
2964 	{ "cl", "operator()" },
2965 	{ "cm", "operator," },
2966 	{ "co", "operator~" },
2967 	{ "da", "operator delete[]" },
2968 	{ "de", "operator*" },
2969 	{ "dl", "operator delete" },
2970 	{ "dv", "operator/" },
2971 	{ "dV", "operator/=" },
2972 	{ "eo", "operator^" },
2973 	{ "eO", "operator^=" },
2974 	{ "eq", "operator==" },
2975 	{ "ge", "operator>=" },
2976 	{ "gt", "operator>" },
2977 	{ "ix", "operator[]" },
2978 	{ "le", "operator<=" },
2979 	{ "ls", "operator<<" },
2980 	{ "lS", "operator<<=" },
2981 	{ "lt", "operator<" },
2982 	{ "mi", "operator-" },
2983 	{ "mI", "operator-=" },
2984 	{ "ml", "operator*" },
2985 	{ "mL", "operator*=" },
2986 	{ "mm", "operator--" },
2987 	{ "na", "operator new[]" },
2988 	{ "ne", "operator!=" },
2989 	{ "ng", "operator-" },
2990 	{ "nt", "operator!" },
2991 	{ "nw", "operator new" },
2992 	{ "oo", "operator||" },
2993 	{ "or", "operator|" },
2994 	{ "oR", "operator|=" },
2995 	{ "pm", "operator->*" },
2996 	{ "pl", "operator+" },
2997 	{ "pL", "operator+=" },
2998 	{ "pp", "operator++" },
2999 	{ "ps", "operator+" },
3000 	{ "pt", "operator->" },
3001 	{ "qu", "operator?" },
3002 	{ "rm", "operator%" },
3003 	{ "rM", "operator%=" },
3004 	{ "rs", "operator>>" },
3005 	{ "rS", "operator>>=" }
3006 };
3007 
3008 static const char *
parse_operator_name(const char * first,const char * last,cpp_db_t * db)3009 parse_operator_name(const char *first, const char *last, cpp_db_t *db)
3010 {
3011 	VERIFY3P(first, <=, last);
3012 
3013 	if (last - first < 2)
3014 		return (first);
3015 
3016 	for (size_t i = 0; i < ARRAY_SIZE(op_tbl); i++) {
3017 		if (strncmp(first, op_tbl[i].code, 2) != 0)
3018 			continue;
3019 
3020 		nadd_l(db, op_tbl[i].op, 0);
3021 		return (first + 2);
3022 	}
3023 
3024 	const char *t = NULL;
3025 
3026 	if (first[0] == 'l' && first[1] == 'i') {
3027 		t = parse_source_name(first + 2, last, db);
3028 		if (t == first + 2 || nempty(db))
3029 			return (first);
3030 
3031 		nfmt(db, "operator\"\" {0}", NULL);
3032 		return (t);
3033 	}
3034 
3035 	if (first[0] == 'v') {
3036 		if (!ISDIGIT(first[1]))
3037 			return (first);
3038 
3039 		t = parse_source_name(first + 2, last, db);
3040 		if (t == first + 2)
3041 			return (first);
3042 
3043 		nfmt(db, "operator {0}", NULL);
3044 		return (t);
3045 	}
3046 
3047 	if (first[0] != 'c' && first[1] != 'v')
3048 		return (first);
3049 
3050 	boolean_t try_to_parse_template_args =
3051 	    db->cpp_try_to_parse_template_args;
3052 
3053 	db->cpp_try_to_parse_template_args = B_FALSE;
3054 	t = parse_type(first + 2, last, db);
3055 	db->cpp_try_to_parse_template_args = try_to_parse_template_args;
3056 
3057 	if (t == first + 2 || nempty(db))
3058 		return (first);
3059 
3060 	nfmt(db, "operator {0}", NULL);
3061 	db->cpp_parsed_ctor_dtor_cv = B_TRUE;
3062 	return (t);
3063 }
3064 
3065 struct type_tbl_s {
3066 	int code;
3067 	const char *name;
3068 };
3069 
3070 static struct type_tbl_s type_tbl1[] = {
3071 	{ 'a', "signed char" },
3072 	{ 'b', "bool" },
3073 	{ 'c', "char" },
3074 	{ 'd', "double" },
3075 	{ 'e', "long double" },
3076 	{ 'f', "float" },
3077 	{ 'g', "__float128" },
3078 	{ 'h', "unsigned char" },
3079 	{ 'i', "int" },
3080 	{ 'j', "unsigned int" },
3081 	{ 'l', "long" },
3082 	{ 'm', "unsigned long" },
3083 	{ 'n', "__int128" },
3084 	{ 'o', "unsigned __int128" },
3085 	{ 's', "short" },
3086 	{ 't', "unsigned short" },
3087 	{ 'v', "void" },
3088 	{ 'w', "wchar_t" },
3089 	{ 'x', "long long" },
3090 	{ 'y', "unsigned long long" },
3091 	{ 'z', "..." }
3092 };
3093 
3094 static struct type_tbl_s type_tbl2[] = {
3095 	{ 'a', "auto" },
3096 	{ 'c', "decltype(auto)" },
3097 	{ 'd', "decimal64" },
3098 	{ 'e', "decimal128" },
3099 	{ 'f', "decimal32" },
3100 	{ 'h', "decimal16" },
3101 	{ 'i', "char32_t" },
3102 	{ 'n', "std::nullptr_t" },
3103 	{ 's', "char16_t" }
3104 };
3105 
3106 static const char *
parse_builtin_type(const char * first,const char * last,cpp_db_t * db)3107 parse_builtin_type(const char *first, const char *last, cpp_db_t *db)
3108 {
3109 	VERIFY3P(first, <=, last);
3110 
3111 	if (first == last)
3112 		return (first);
3113 
3114 	size_t i;
3115 
3116 	for (i = 0; i < ARRAY_SIZE(type_tbl1); i++) {
3117 		if (first[0] == type_tbl1[i].code) {
3118 			nadd_l(db, type_tbl1[i].name, 0);
3119 			return (first + 1);
3120 		}
3121 	}
3122 
3123 	if (first[0] == 'D') {
3124 		if (first + 1 == last)
3125 			return (first);
3126 		for (i = 0; i < ARRAY_SIZE(type_tbl2); i++) {
3127 			if (first[1] == type_tbl2[i].code) {
3128 				nadd_l(db, type_tbl2[i].name, 0);
3129 				return (first + 2);
3130 			}
3131 		}
3132 	}
3133 
3134 	if (first[0] == 'u') {
3135 		const char *t = parse_source_name(first + 1, last, db);
3136 		if (t == first + 1)
3137 			return (first);
3138 		return (t);
3139 	}
3140 
3141 	return (first);
3142 }
3143 
3144 static const char *
parse_base36(const char * first,const char * last,size_t * val)3145 parse_base36(const char *first, const char *last, size_t *val)
3146 {
3147 	VERIFY3P(first, <=, last);
3148 
3149 	const char *t;
3150 
3151 	for (t = first, *val = 0; t != last; t++) {
3152 		if (!ISDIGIT(t[0]) && !ISUPPER(t[0]))
3153 			return (t);
3154 
3155 		*val *= 36;
3156 
3157 		if (ISDIGIT(t[0]))
3158 			*val += t[0] - '0';
3159 		else
3160 			*val += t[0] - 'A' + 10;
3161 	}
3162 	return (t);
3163 }
3164 
3165 static struct type_tbl_s sub_tbl[] = {
3166 	{ 'a', "std::allocator" },
3167 	{ 'b', "std::basic_string" },
3168 	{ 's', "std::string" },
3169 	{ 'i', "std::istream" },
3170 	{ 'o', "std::ostream" },
3171 	{ 'd', "std::iostream" }
3172 };
3173 
3174 static const char *
parse_substitution(const char * first,const char * last,cpp_db_t * db)3175 parse_substitution(const char *first, const char *last, cpp_db_t *db)
3176 {
3177 	VERIFY3P(first, <=, last);
3178 
3179 	if (first == last || last - first < 2)
3180 		return (first);
3181 
3182 	if (first[0] != 'S')
3183 		return (first);
3184 
3185 	for (size_t i = 0; i < ARRAY_SIZE(sub_tbl); i++) {
3186 		if (first[1] == sub_tbl[i].code) {
3187 			nadd_l(db, sub_tbl[i].name, 0);
3188 			return (first + 2);
3189 		}
3190 	}
3191 
3192 	const char *t = first + 1;
3193 	size_t n = 0;
3194 
3195 	if (t[0] != '_') {
3196 		t = parse_base36(first + 1, last, &n);
3197 		if (t == first + 1 || t[0] != '_')
3198 			return (first);
3199 
3200 		/*
3201 		 * S_ == substitution 0,
3202 		 * S0_ == substituion 1,
3203 		 * ...
3204 		 */
3205 		n++;
3206 	}
3207 
3208 	if (n >= sub_len(&db->cpp_subs))
3209 		return (first);
3210 
3211 	sub(db, n);
3212 
3213 	/* skip _ */
3214 	VERIFY3U(t[0], ==, '_');
3215 
3216 	return (t + 1);
3217 }
3218 
3219 static const char *
parse_source_name(const char * first,const char * last,cpp_db_t * db)3220 parse_source_name(const char *first, const char *last, cpp_db_t *db)
3221 {
3222 	VERIFY3P(first, <=, last);
3223 
3224 	if (first == last)
3225 		return (first);
3226 
3227 	const char *t = NULL;
3228 	size_t n = 0;
3229 
3230 	for (t = first; t != last && ISDIGIT(t[0]); t++) {
3231 		/* make sure we don't overflow */
3232 		size_t nn = n * 10;
3233 		if (nn < n)
3234 			return (first);
3235 
3236 		nn += t[0] - '0';
3237 		if (nn < n)
3238 			return (first);
3239 
3240 		n = nn;
3241 	}
3242 
3243 	if (n == 0 || t == last || t + n > last ||
3244 	    (uintptr_t)t + n < (uintptr_t)t)
3245 		return (first);
3246 
3247 	if (strncmp(t, "_GLOBAL__N", 10) == 0)
3248 		nadd_l(db, "(anonymous namespace)", 0);
3249 	else
3250 		nadd_l(db, t, n);
3251 
3252 	return (t + n);
3253 }
3254 
3255 /*
3256  * extension:
3257  * <vector-type>           ::= Dv <positive dimension number> _
3258  *                                    <extended element type>
3259  *                         ::= Dv [<dimension expression>] _ <element type>
3260  * <extended element type> ::= <element type>
3261  *                         ::= p # AltiVec vector pixel
3262  */
3263 static const char *
parse_vector_type(const char * first,const char * last,cpp_db_t * db)3264 parse_vector_type(const char *first, const char *last, cpp_db_t *db)
3265 {
3266 	VERIFY3P(first, <=, last);
3267 
3268 	if (last - first < 3)
3269 		return (first);
3270 
3271 	VERIFY3U(first[0], ==, 'D');
3272 	VERIFY3U(first[1], ==, 'v');
3273 
3274 	const char *t = first + 2;
3275 	const char *t1 = NULL;
3276 
3277 	if (ISDIGIT(first[2]) && first[2] != '0') {
3278 		t1 = parse_number(t, last);
3279 		if (t1 == last || t1 + 1 == last || t1[0] != '_')
3280 			return (first);
3281 
3282 		nadd_l(db, t, (size_t)(t1 - t));
3283 
3284 		/* skip _ */
3285 		t = t1 + 1;
3286 
3287 		if (t[0] != 'p') {
3288 			t1 = parse_type(t, last, db);
3289 			if (t1 == t)
3290 				return (first);
3291 
3292 			nfmt(db, "{0} vector[{1}]", NULL);
3293 			return (t1);
3294 		}
3295 		nfmt(db, "{0} pixel vector[{1}]", NULL);
3296 		return (t1);
3297 	}
3298 
3299 	if (first[2] != '_') {
3300 		t1 = parse_expression(first + 2, last, db);
3301 		if (first == last || t1 == first + 2 || t1[0] != '_')
3302 			return (first);
3303 
3304 		/* skip _ */
3305 		t = t1 + 1;
3306 	} else {
3307 		nadd_l(db, "", 0);
3308 	}
3309 
3310 	t1 = parse_type(t, last, db);
3311 	if (t == t1)
3312 		return (first);
3313 
3314 	nfmt(db, "{1:L} vector[{0}]", "{1:R}");
3315 	return (t1);
3316 }
3317 
3318 /* BEGIN CSTYLED */
3319 /*
3320  * <decltype>  ::= Dt <expression> E  # decltype of an id-expression or class member access (C++0x)
3321  *             ::= DT <expression> E  # decltype of an expression (C++0x)
3322  */
3323 /* END CSTYLED */
3324 static const char *
parse_decltype(const char * first,const char * last,cpp_db_t * db)3325 parse_decltype(const char *first, const char *last, cpp_db_t *db)
3326 {
3327 	VERIFY3P(first, <=, last);
3328 
3329 	if (last - first < 4)
3330 		return (first);
3331 
3332 	VERIFY3U(first[0], ==, 'D');
3333 
3334 	if (first[1] != 't' && first[1] != 'T')
3335 		return (first);
3336 
3337 	size_t n = nlen(db);
3338 	const char *t = parse_expression(first + 2, last, db);
3339 	if (NAMT(db, n) != 1 || t == first + 2 || t == last || t[0] != 'E')
3340 		return (first);
3341 
3342 	nfmt(db, "decltype({0})", NULL);
3343 
3344 	/* skip E */
3345 	return (t + 1);
3346 }
3347 
3348 /*
3349  * <array-type> ::= A <positive dimension number> _ <element type>
3350  *              ::= A [<dimension expression>] _ <element type>
3351  */
3352 static const char *
parse_array_type(const char * first,const char * last,cpp_db_t * db)3353 parse_array_type(const char *first, const char *last, cpp_db_t *db)
3354 {
3355 	VERIFY3P(first, <=, last);
3356 	VERIFY3U(first[0], ==, 'A');
3357 
3358 	if (last - first < 3)
3359 		return (first);
3360 
3361 	const char *t = first + 1;
3362 	const char *t1 = NULL;
3363 	size_t n = nlen(db);
3364 
3365 	if (t[0] != '_') {
3366 		if (ISDIGIT(t[0]) && t[0] != '0') {
3367 			t1 = parse_number(t, last);
3368 			if (t1 == last)
3369 				return (first);
3370 
3371 			nadd_l(db, t, (size_t)(t1 - t));
3372 		} else {
3373 			t1 = parse_expression(t, last, db);
3374 			if (t1 == last || t == t1)
3375 				return (first);
3376 		}
3377 
3378 		if (t1[0] != '_')
3379 			return (first);
3380 
3381 		t = t1;
3382 	} else {
3383 		nadd_l(db, "", 0);
3384 	}
3385 
3386 	VERIFY3U(t[0], ==, '_');
3387 
3388 	t1 = parse_type(t + 1, last, db);
3389 	if (t1 == t + 1 || NAMT(db, n) != 2)
3390 		return (first);
3391 
3392 	/*
3393 	 * if we have  " [xxx]" already, want new result to be
3394 	 * " [yyy][xxx]"
3395 	 */
3396 	str_t *r = &name_top(&db->cpp_name)->strp_r;
3397 	if (r->str_len > 1 && r->str_s[0] == ' ' && r->str_s[1] == '[')
3398 		(void) str_erase(r, 0, 1);
3399 
3400 	nfmt(db, "{0:L}", " [{1}]{0:R}");
3401 	return (t1);
3402 }
3403 
3404 /* <pointer-to-member-type> ::= M <class type> <member type> */
3405 static const char *
parse_pointer_to_member_type(const char * first,const char * last,cpp_db_t * db)3406 parse_pointer_to_member_type(const char *first, const char *last, cpp_db_t *db)
3407 {
3408 	VERIFY3P(first, <=, last);
3409 
3410 	if (last - first < 3)
3411 		return (first);
3412 
3413 	VERIFY3U(first[0], ==, 'M');
3414 
3415 	const char *t1 = first + 1;
3416 	const char *t2 = NULL;
3417 	size_t n = nlen(db);
3418 
3419 	t2 = parse_type(t1, last, db);
3420 	if (t1 == t2)
3421 		return (first);
3422 
3423 	t1 = t2;
3424 	t2 = parse_type(t1, last, db);
3425 	if (t1 == t2)
3426 		return (first);
3427 
3428 	if (NAMT(db, n) != 2)
3429 		return (first);
3430 
3431 	str_pair_t *func = name_top(&db->cpp_name);
3432 
3433 	if (str_length(&func->strp_r) > 0 && func->strp_r.str_s[0] == '(')
3434 		nfmt(db, "{0:L}({1}::*", "){0:R}");
3435 	else
3436 		nfmt(db, "{0:L} {1}::*", "{0:R}");
3437 
3438 	return (t2);
3439 }
3440 
3441 /* BEGIN CSTYLED */
3442 /*
3443  * <unresolved-name>
3444  *  extension        ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3445  *                   ::= [gs] <base-unresolved-name>                     # x or (with "gs") ::x
3446  *                   ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3447  *                                                                       # A::x, N::y, A<T>::z; "gs" means leading "::"
3448  *                   ::= sr <unresolved-type> <base-unresolved-name>     # T::x / decltype(p)::x
3449  *  extension        ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3450  *                                                                       # T::N::x /decltype(p)::N::x
3451  *  (ignored)        ::= srN <unresolved-type>  <unresolved-qualifier-level>+ E <base-unresolved-name>
3452  */
3453 /* END CSTYLED */
3454 static const char *
parse_unresolved_name(const char * first,const char * last,cpp_db_t * db)3455 parse_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3456 {
3457 	VERIFY3P(first, <=, last);
3458 
3459 	if (last - first < 2)
3460 		return (first);
3461 
3462 	const char *t = first;
3463 	const char *t2 = NULL;
3464 	boolean_t global = B_FALSE;
3465 	size_t n;
3466 
3467 	if (t[0] == 'g' && t[1] == 's') {
3468 		global = B_TRUE;
3469 		t += 2;
3470 	}
3471 	if (t == last)
3472 		return (first);
3473 
3474 	t2 = parse_base_unresolved_name(t, last, db);
3475 	if (t != t2) {
3476 		if (global) {
3477 			if (nempty(db))
3478 				return (first);
3479 
3480 			(void) str_insert(TOP_L(db), 0, "::", 2);
3481 		}
3482 		return (t2);
3483 	}
3484 
3485 	if (t[0] != 's' || t[1] != 'r' || last - t < 2)
3486 		return (first);
3487 
3488 	n = nlen(db);
3489 	if (t[2] == 'N') {
3490 		t += 3;
3491 		t2 = parse_unresolved_type(t, last, db);
3492 		if (t2 == t || t2 == last)
3493 			return (first);
3494 		t = t2;
3495 
3496 		t2 = parse_template_args(t, last, db);
3497 		if (t2 != t) {
3498 			if (NAMT(db, n) < 2 || t2 == last)
3499 				return (first);
3500 
3501 			nfmt(db, "{1:L}{0}", "{1:R}");
3502 			t = t2;
3503 		}
3504 
3505 		VERIFY3U(NAMT(db, n), ==, 1);
3506 
3507 		while (t[0] != 'E') {
3508 			size_t nn = nlen(db);
3509 			t2 = parse_unresolved_qualifier_level(t, last, db);
3510 			if (t == t2 || t == last || NAMT(db, nn) != 1)
3511 				return (first);
3512 
3513 			t = t2;
3514 		}
3515 
3516 		/* skip E */
3517 		t++;
3518 
3519 		t2 = parse_base_unresolved_name(t, last, db);
3520 		if (t == t2 || NAMT(db, n) < 2)
3521 			return (first);
3522 
3523 		njoin(db, NAMT(db, n), "::");
3524 		return (t2);
3525 	}
3526 
3527 	t += 2;
3528 
3529 	t2 = parse_unresolved_type(t, last, db);
3530 	if (t != t2) {
3531 		t = t2;
3532 		t2 = parse_template_args(t, last, db);
3533 		if (t2 != t)
3534 			nfmt(db, "{1:L}{0}", "{1:R}");
3535 		t = t2;
3536 
3537 		t2 = parse_base_unresolved_name(t, last, db);
3538 		if (t == t2 || nlen(db) < 2)
3539 			return (first);
3540 
3541 		nfmt(db, "{1:L}::{0}", "{1:R}");
3542 		return (t2);
3543 	}
3544 
3545 	t2 = parse_unresolved_qualifier_level(t, last, db);
3546 	if (t2 == t || t2 == last)
3547 		return (first);
3548 
3549 	t = t2;
3550 	if (global && nlen(db) > 0)
3551 		nfmt(db, "::{0:L}", "{0:R}");
3552 
3553 	while (t[0] != 'E') {
3554 		t2 = parse_unresolved_qualifier_level(t, last, db);
3555 		if (t == t2 || t == last || nlen(db) < 2)
3556 			return (first);
3557 
3558 		t = t2;
3559 	}
3560 
3561 	/* skip E */
3562 	t++;
3563 
3564 	t2 = parse_base_unresolved_name(t, last, db);
3565 	if (t == t2 || nlen(db) < 2)
3566 		return (first);
3567 
3568 	njoin(db, NAMT(db, n), "::");
3569 	return (t2);
3570 }
3571 
3572 /* <unresolved-qualifier-level> ::= <simple-id> */
3573 static const char *
parse_unresolved_qualifier_level(const char * first,const char * last,cpp_db_t * db)3574 parse_unresolved_qualifier_level(const char *first, const char *last,
3575     cpp_db_t *db)
3576 {
3577 	VERIFY3P(first, <=, last);
3578 	return (parse_simple_id(first, last, db));
3579 }
3580 
3581 /* BEGIN CSTYLED */
3582 /*
3583  * <base-unresolved-name> ::= <simple-id>                                # unresolved name
3584  *          extension     ::= <operator-name>                            # unresolved operator-function-id
3585  *          extension     ::= <operator-name> <template-args>            # unresolved operator template-id
3586  *                        ::= on <operator-name>                         # unresolved operator-function-id
3587  *                        ::= on <operator-name> <template-args>         # unresolved operator template-id
3588  *                        ::= dn <destructor-name>                       # destructor or pseudo-destructor;
3589  *                                                                       # e.g. ~X or ~X<N-1>
3590  */
3591 /* END CSTYLED */
3592 static const char *
parse_base_unresolved_name(const char * first,const char * last,cpp_db_t * db)3593 parse_base_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3594 {
3595 	VERIFY3P(first, <=, last);
3596 
3597 	if (last - first < 2)
3598 		return (first);
3599 
3600 	const char *t = NULL;
3601 	const char *t1 = NULL;
3602 
3603 	if ((first[0] != 'o' && first[0] != 'd') || first[1] != 'n') {
3604 		t = parse_simple_id(first, last, db);
3605 		if (t != first)
3606 			return (t);
3607 
3608 		t = parse_operator_name(first, last, db);
3609 		if (t == first)
3610 			return (first);
3611 
3612 		t1 = parse_template_args(t, last, db);
3613 		if (t1 != t) {
3614 			if (nlen(db) < 2)
3615 				return (first);
3616 			nfmt(db, "{1:L}{0}", "{1:R}");
3617 		}
3618 
3619 		return (t1);
3620 	}
3621 
3622 	if (first[0] == 'd') {
3623 		t = parse_destructor_name(first + 2, last, db);
3624 		return ((t != first + 2) ? t : first);
3625 	}
3626 
3627 	t = parse_operator_name(first + 2, last, db);
3628 	if (t == first + 2)
3629 		return (first);
3630 
3631 	t1 = parse_template_args(t, last, db);
3632 	if (t1 != t)
3633 		nfmt(db, "{1:L}{0}", "{1:R}");
3634 	return (t1);
3635 }
3636 
3637 /*
3638  * <destructor-name> ::= <unresolved-type>	# e.g., ~T or ~decltype(f())
3639  *                   ::= <simple-id>		# e.g., ~A<2*N>
3640  */
3641 static const char *
parse_destructor_name(const char * first,const char * last,cpp_db_t * db)3642 parse_destructor_name(const char *first, const char *last, cpp_db_t *db)
3643 {
3644 	VERIFY3P(first, <=, last);
3645 
3646 	if (first == last)
3647 		return (first);
3648 
3649 	const char *t = parse_unresolved_type(first, last, db);
3650 
3651 	if (t == first)
3652 		t = parse_simple_id(first, last, db);
3653 
3654 	if (t == first)
3655 		return (first);
3656 
3657 	nfmt(db, "~{0:L}", "{0:R}");
3658 	return (t);
3659 }
3660 
3661 /*
3662  *  <ref-qualifier> ::= R                   # & ref-qualifier
3663  *  <ref-qualifier> ::= O                   # && ref-qualifier
3664  *
3665  * <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
3666  */
3667 static const char *
parse_function_type(const char * first,const char * last,cpp_db_t * db)3668 parse_function_type(const char *first, const char *last, cpp_db_t *db)
3669 {
3670 	VERIFY3P(first, <=, last);
3671 
3672 	if (last - first < 2)
3673 		return (first);
3674 
3675 	VERIFY3U(first[0], ==, 'F');
3676 
3677 	const char *t = first + 1;
3678 
3679 	/* extern "C" */
3680 	if (t[0] == 'Y')
3681 		t++;
3682 
3683 	const char *t1 = parse_type(t, last, db);
3684 	if (t1 == t)
3685 		return (first);
3686 
3687 	size_t n = nlen(db);
3688 	int ref_qual = 0;
3689 
3690 	t = t1;
3691 
3692 	while (t != last && t[0] != 'E') {
3693 		if (t[0] == 'v') {
3694 			t++;
3695 			continue;
3696 		}
3697 
3698 		if (t[0] == 'R' && t + 1 != last && t[1] == 'E') {
3699 			ref_qual = 1;
3700 			t++;
3701 			continue;
3702 		}
3703 
3704 		if (t[0] == 'O' && t + 1 != last && t[1] == 'E') {
3705 			ref_qual = 2;
3706 			t++;
3707 			continue;
3708 		}
3709 
3710 
3711 		t1 = parse_type(t, last, db);
3712 		if (t1 == t || t == last)
3713 			return (first);
3714 
3715 		t = t1;
3716 	}
3717 
3718 	if (t == last)
3719 		return (first);
3720 
3721 	njoin(db, NAMT(db, n), ", ");
3722 	nfmt(db, "({0})", NULL);
3723 
3724 	switch (ref_qual) {
3725 	case 1:
3726 		nfmt(db, "{0} &", NULL);
3727 		break;
3728 	case 2:
3729 		nfmt(db, "{0} &&", NULL);
3730 		break;
3731 	}
3732 
3733 	nfmt(db, "{1:L} ", "{0}{1:R}");
3734 
3735 	/* skip E */
3736 	return (t + 1);
3737 }
3738 
3739 /*
3740  * <template-param> ::= T_    # first template parameter
3741  *                  ::= T <parameter-2 non-negative number> _
3742  */
3743 static const char *
parse_template_param(const char * first,const char * last,cpp_db_t * db)3744 parse_template_param(const char *first, const char *last, cpp_db_t *db)
3745 {
3746 	VERIFY3P(first, <=, last);
3747 
3748 	if (last - first < 2 || first[0] != 'T')
3749 		return (first);
3750 
3751 	const char *t = first + 1;
3752 	size_t idx = 0;
3753 
3754 	while (t != last && t[0] != '_') {
3755 		if (!ISDIGIT(t[0]))
3756 			return (first);
3757 
3758 		idx *= 10;
3759 		idx += t[0] - '0';
3760 		t++;
3761 	}
3762 
3763 	if (t == last)
3764 		return (first);
3765 
3766 	VERIFY3U(t[0], ==, '_');
3767 
3768 	/*
3769 	 * T_ -> idx 0
3770 	 * T0 -> idx 1
3771 	 * T1 -> idx 2
3772 	 * ...
3773 	 */
3774 	if (first[1] != '_')
3775 		idx++;
3776 
3777 	/* skip _ */
3778 	t++;
3779 
3780 	if (tempty(db))
3781 		return (first);
3782 
3783 	if (idx >= ttlen(db)) {
3784 		nadd_l(db, first, (size_t)(t - first));
3785 		db->cpp_fix_forward_references = B_TRUE;
3786 		return (t);
3787 	}
3788 
3789 	tsub(db, idx);
3790 	return (t);
3791 }
3792 
3793 /*
3794  * <template-args> ::= I <template-arg>* E
3795  *     extension, the abi says <template-arg>+
3796  */
3797 static const char *
parse_template_args(const char * first,const char * last,cpp_db_t * db)3798 parse_template_args(const char *first, const char *last, cpp_db_t *db)
3799 {
3800 	VERIFY3P(first, <=, last);
3801 
3802 	if (last - first < 2 || first[0] != 'I')
3803 		return (first);
3804 
3805 	if (db->cpp_tag_templates)
3806 		sub_clear(templ_top(&db->cpp_templ));
3807 
3808 	const char *t = first + 1;
3809 	size_t n = nlen(db);
3810 
3811 	while (t[0] != 'E') {
3812 		if (db->cpp_tag_templates)
3813 			tpush(db);
3814 
3815 		size_t n1 = nlen(db);
3816 		const char *t1 = parse_template_arg(t, last, db);
3817 
3818 		if (db->cpp_tag_templates)
3819 			tpop(db);
3820 
3821 		if (t1 == t || t == last)
3822 			return (first);
3823 
3824 		if (db->cpp_tag_templates)
3825 			tsave(db, NAMT(db, n1));
3826 
3827 		t = t1;
3828 	}
3829 
3830 	/*
3831 	 * ugly, but if the last thing pushed was an empty string,
3832 	 * get rid of it so we dont get "<..., >"
3833 	 */
3834 	if (NAMT(db, n) > 1 &&
3835 	    str_pair_len(name_top(&db->cpp_name)) == 0)
3836 		name_pop(&db->cpp_name, NULL);
3837 
3838 	njoin(db, NAMT(db, n), ", ");
3839 
3840 	VERIFY3U(nlen(db), >, 0);
3841 
3842 	/* make sure we don't bitshift ourselves into oblivion */
3843 	str_t *top = TOP_L(db);
3844 	if (str_length(top) > 0 &&
3845 	    top->str_s[top->str_len - 1] == '>')
3846 		nfmt(db, "<{0} >", NULL);
3847 	else
3848 		nfmt(db, "<{0}>", NULL);
3849 
3850 	/* skip E */
3851 	return (t + 1);
3852 }
3853 
3854 /*
3855  * <discriminator> := _ <non-negative number>      # when number < 10
3856  *                 := __ <non-negative number> _   # when number >= 10
3857  *  extension      := decimal-digit+               # at the end of string
3858  */
3859 static const char *
parse_discriminator(const char * first,const char * last)3860 parse_discriminator(const char *first, const char *last)
3861 {
3862 	VERIFY3P(first, <=, last);
3863 
3864 	const char *t = NULL;
3865 
3866 	if (first == last)
3867 		return (first);
3868 
3869 	if (ISDIGIT(first[0])) {
3870 		for (t = first; t != last && ISDIGIT(t[0]); t++)
3871 			;
3872 
3873 		/* not at the end of the string */
3874 		if (t != last)
3875 			return (first);
3876 
3877 		return (t);
3878 	} else if (first[0] != '_' || first + 1 == last) {
3879 		return (first);
3880 	}
3881 
3882 	t = first + 1;
3883 	if (ISDIGIT(t[0]))
3884 		return (t + 1);
3885 
3886 	if (t[0] != '_' || t + 1 == last)
3887 		return (first);
3888 
3889 	for (t++; t != last && ISDIGIT(t[0]); t++)
3890 		;
3891 	if (t == last || t[0] != '_')
3892 		return (first);
3893 
3894 	return (t);
3895 }
3896 
3897 /* <CV-qualifiers> ::= [r] [V] [K] */
3898 const char *
parse_cv_qualifiers(const char * first,const char * last,unsigned * cv)3899 parse_cv_qualifiers(const char *first, const char *last, unsigned *cv)
3900 {
3901 	VERIFY3P(first, <=, last);
3902 
3903 	if (first == last)
3904 		return (first);
3905 
3906 	*cv = 0;
3907 	if (first[0] == 'r') {
3908 		*cv |= CPP_QUAL_RESTRICT;
3909 		first++;
3910 	}
3911 	if (first != last && first[0] == 'V') {
3912 		*cv |= CPP_QUAL_VOLATILE;
3913 		first++;
3914 	}
3915 	if (first != last && first[0] == 'K') {
3916 		*cv |= CPP_QUAL_CONST;
3917 		first++;
3918 	}
3919 
3920 	return (first);
3921 }
3922 
3923 /*
3924  * <number> ::= [n] <non-negative decimal integer>
3925  */
3926 static const char *
parse_number(const char * first,const char * last)3927 parse_number(const char *first, const char *last)
3928 {
3929 	VERIFY3P(first, <=, last);
3930 
3931 	const char *t = first;
3932 
3933 	if (first == last || (first[0] != 'n' && !ISDIGIT(first[0])))
3934 		return (first);
3935 
3936 	if (t[0] == 'n')
3937 		t++;
3938 
3939 	if (t[0] == '0')
3940 		return (t + 1);
3941 
3942 	while (ISDIGIT(t[0]))
3943 		t++;
3944 
3945 	return (t);
3946 }
3947 
3948 /*
3949  * Like isxdigit(3C), except we can only accept lower case letters as
3950  * that's only what is allowed when [de]mangling floating point constants into
3951  * their hex representation.
3952  */
3953 static inline boolean_t
is_xdigit(int c)3954 is_xdigit(int c)
3955 {
3956 	if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
3957 		return (B_TRUE);
3958 	return (B_FALSE);
3959 }
3960 
3961 static boolean_t
nempty(cpp_db_t * db)3962 nempty(cpp_db_t *db)
3963 {
3964 	return (name_empty(&db->cpp_name));
3965 }
3966 
3967 static size_t
nlen(cpp_db_t * db)3968 nlen(cpp_db_t *db)
3969 {
3970 	return (name_len(&db->cpp_name));
3971 }
3972 
3973 static void
nadd_l(cpp_db_t * db,const char * s,size_t len)3974 nadd_l(cpp_db_t *db, const char *s, size_t len)
3975 {
3976 	CK(name_add(&db->cpp_name, s, len, NULL, 0));
3977 }
3978 
3979 static void
njoin(cpp_db_t * db,size_t amt,const char * sep)3980 njoin(cpp_db_t *db, size_t amt, const char *sep)
3981 {
3982 	name_t *nm = &db->cpp_name;
3983 
3984 	CK(name_join(nm, amt, sep));
3985 }
3986 
3987 static void
nfmt(cpp_db_t * db,const char * fmt_l,const char * fmt_r)3988 nfmt(cpp_db_t *db, const char *fmt_l, const char *fmt_r)
3989 {
3990 	CK(name_fmt(&db->cpp_name, fmt_l, fmt_r));
3991 }
3992 
3993 static void
save_top(cpp_db_t * db,size_t amt)3994 save_top(cpp_db_t *db, size_t amt)
3995 {
3996 	CK(sub_save(&db->cpp_subs, &db->cpp_name, amt));
3997 }
3998 
3999 static void
sub(cpp_db_t * db,size_t n)4000 sub(cpp_db_t *db, size_t n)
4001 {
4002 	CK(sub_substitute(&db->cpp_subs, n, &db->cpp_name));
4003 }
4004 
4005 static boolean_t
tempty(const cpp_db_t * db)4006 tempty(const cpp_db_t *db)
4007 {
4008 	return (templ_empty(&db->cpp_templ) ? B_TRUE : B_FALSE);
4009 }
4010 
4011 static size_t
ttlen(const cpp_db_t * db)4012 ttlen(const cpp_db_t *db)
4013 {
4014 	return (templ_top_len(&db->cpp_templ));
4015 }
4016 
4017 static void
tsub(cpp_db_t * db,size_t n)4018 tsub(cpp_db_t *db, size_t n)
4019 {
4020 	CK(templ_sub(&db->cpp_templ, n, &db->cpp_name));
4021 }
4022 
4023 static void
tpush(cpp_db_t * db)4024 tpush(cpp_db_t *db)
4025 {
4026 	CK(templ_push(&db->cpp_templ));
4027 }
4028 
4029 static void
tpop(cpp_db_t * db)4030 tpop(cpp_db_t *db)
4031 {
4032 	templ_pop(&db->cpp_templ);
4033 }
4034 
4035 static void
tsave(cpp_db_t * db,size_t amt)4036 tsave(cpp_db_t *db, size_t amt)
4037 {
4038 	CK(templ_save(&db->cpp_name, amt, &db->cpp_templ));
4039 }
4040 
4041 static void
db_init(cpp_db_t * db,sysdem_ops_t * ops)4042 db_init(cpp_db_t *db, sysdem_ops_t *ops)
4043 {
4044 	(void) memset(db, 0, sizeof (*db));
4045 	db->cpp_ops = ops;
4046 	name_init(&db->cpp_name, ops);
4047 	sub_init(&db->cpp_subs, ops);
4048 	templ_init(&db->cpp_templ, ops);
4049 	db->cpp_tag_templates = B_TRUE;
4050 	db->cpp_try_to_parse_template_args = B_TRUE;
4051 	tpush(db);
4052 }
4053 
4054 static void
db_fini(cpp_db_t * db)4055 db_fini(cpp_db_t *db)
4056 {
4057 	name_fini(&db->cpp_name);
4058 	sub_fini(&db->cpp_subs);
4059 	templ_fini(&db->cpp_templ);
4060 	(void) memset(db, 0, sizeof (*db));
4061 }
4062 
4063 static void
print_sp(const str_pair_t * sp,FILE * out)4064 print_sp(const str_pair_t *sp, FILE *out)
4065 {
4066 	(void) fprintf(out, "{%.*s#%.*s}",
4067 	    (int)sp->strp_l.str_len, sp->strp_l.str_s,
4068 	    (int)sp->strp_r.str_len, sp->strp_r.str_s);
4069 }
4070 
4071 static void
print_name(const name_t * n,FILE * out)4072 print_name(const name_t *n, FILE *out)
4073 {
4074 	const str_pair_t *sp;
4075 	size_t i;
4076 
4077 	(void) fprintf(out, "Name:\n");
4078 
4079 	if (name_len(n) == 0)
4080 		return;
4081 
4082 	sp = name_top((name_t *)n);
4083 
4084 	for (i = 0; i < n->nm_len; i++, sp--) {
4085 		(void) fprintf(out, "  [%02zu] ", i);
4086 		print_sp(sp, out);
4087 		(void) fputc('\n', out);
4088 	}
4089 
4090 	(void) fputc('\n', out);
4091 }
4092 
4093 /* Print a base-36 number (for substitutions) */
4094 static char *
base36(char * buf,size_t val)4095 base36(char *buf, size_t val)
4096 {
4097 	char tmp[16] = { 0 };
4098 	char *p = tmp;
4099 
4100 	if (val == 0) {
4101 		buf[0] = '0';
4102 		buf[1] = '\0';
4103 		return (buf);
4104 	}
4105 
4106 	while (val > 0) {
4107 		size_t r = val % 36;
4108 
4109 		if (r < 10)
4110 			*p++ = r + '0';
4111 		else
4112 			*p++ = r - 10 + 'A';
4113 
4114 		val /= 36;
4115 	}
4116 
4117 	char *q = buf;
4118 	while (--p >= tmp)
4119 		*q++ = *p;
4120 
4121 	return (buf);
4122 }
4123 
4124 static void
print_sub(const sub_t * sub,FILE * out)4125 print_sub(const sub_t *sub, FILE *out)
4126 {
4127 	const name_t *n = sub->sub_items;
4128 
4129 	(void) fprintf(out, "Substitutions:\n");
4130 
4131 	if (sub->sub_len == 0)
4132 		return;
4133 
4134 	for (size_t i = 0; i < sub->sub_len; i++, n++) {
4135 		(void) printf("  ");
4136 		if (i == 0) {
4137 			(void) fprintf(out, "%-4s", "S_");
4138 		} else {
4139 			char buf[16] = { 0 };
4140 			char buf2[16] = { 0 };
4141 
4142 			(void) snprintf(buf, sizeof (buf), "S%s_",
4143 			    base36(buf2, i));
4144 			(void) fprintf(out, "%-4s", buf);
4145 		}
4146 		(void) fprintf(out, " = ");
4147 
4148 		(void) fputc('{', out);
4149 		for (size_t j = 0; j < n->nm_len; j++) {
4150 			if (j > 0)
4151 				(void) fputc(' ', out);
4152 			print_sp(&n->nm_items[j], out);
4153 		}
4154 		(void) fputc('}', out);
4155 
4156 		(void) fputc('\n', out);
4157 	}
4158 	(void) fputc('\n', out);
4159 }
4160 
4161 static void
print_templ(const templ_t * tpl,FILE * out)4162 print_templ(const templ_t *tpl, FILE *out)
4163 {
4164 
4165 	(void) fprintf(out, "Template\n");
4166 
4167 	const sub_t *s = templ_top((templ_t *)tpl);
4168 
4169 	for (size_t i = 0; i < s->sub_len; i++) {
4170 		char buf[16] = { 0 };
4171 
4172 		if (i == 0)
4173 			(void) snprintf(buf, sizeof (buf), "%s", "T_");
4174 		else
4175 			(void) snprintf(buf, sizeof (buf), "T%zu_", i - 1);
4176 
4177 		(void) fprintf(out, "  %-4s = ", buf);
4178 
4179 		(void) fputc('{', out);
4180 
4181 		const name_t *n = &s->sub_items[i];
4182 		for (size_t j = 0; j < n->nm_len; j++) {
4183 			const str_pair_t *sp = &n->nm_items[j];
4184 
4185 			if (j > 0)
4186 				(void) fputc(' ', out);
4187 
4188 			(void) fprintf(out, "{%.*s#%.*s}",
4189 			    (int)sp->strp_l.str_len, sp->strp_l.str_s,
4190 			    (int)sp->strp_r.str_len, sp->strp_r.str_s);
4191 		}
4192 		(void) fprintf(out, "}\n");
4193 	}
4194 	(void) fprintf(out, "\n");
4195 }
4196 
4197 static void
dump(cpp_db_t * db,FILE * out)4198 dump(cpp_db_t *db, FILE *out)
4199 {
4200 	print_name(&db->cpp_name, out);
4201 	print_sub(&db->cpp_subs, out);
4202 	print_templ(&db->cpp_templ, out);
4203 }
4204