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