Merge commit 'cc543d0f9e35a75cc302a4cb152756d233299564'
[unleashed.git] / lib / libdemangle-sys / cxx.c
blobe3b4c06a8a24c39260604145970d6c30ce102f0d
1 /*
2 * Ported from LLVM's libcxxabi trunk/src/cxa_demangle.cpp
3 * LICENSE.TXT contents is available as ../THIRDPARTYLICENSE
5 * The LLVM Compiler Infrastructure
7 * This file is dual licensed under the MIT and the University of Illinois Open
8 * Source Licenses. See LICENSE.TXT for details.
13 * Copyright 2018 Jason King.
15 #include <ctype.h>
16 #include <errno.h>
17 #include <locale.h>
18 #include <note.h>
19 #include <string.h>
20 #include <setjmp.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/isa_defs.h>
24 #include <sys/debug.h>
25 #include "demangle-sys.h"
26 #include "demangle_int.h"
27 #include "cxx.h"
29 #ifndef ARRAY_SIZE
30 #define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
31 #endif
33 #define CPP_QUAL_CONST (1U)
34 #define CPP_QUAL_VOLATILE (2U)
35 #define CPP_QUAL_RESTRICT (4U)
37 typedef struct cpp_db_s {
38 sysdem_ops_t *cpp_ops;
39 jmp_buf cpp_jmp;
40 name_t cpp_name;
41 sub_t cpp_subs;
42 templ_t cpp_templ;
43 unsigned cpp_cv;
44 unsigned cpp_ref;
45 unsigned cpp_depth;
46 boolean_t cpp_parsed_ctor_dtor_cv;
47 boolean_t cpp_tag_templates;
48 boolean_t cpp_fix_forward_references;
49 boolean_t cpp_try_to_parse_template_args;
50 locale_t cpp_loc;
51 } cpp_db_t;
53 #define CK(x) \
54 do { \
55 if (!(x)) { \
56 longjmp(db->cpp_jmp, 1); \
57 } \
58 NOTE(CONSTCOND) \
59 } while (0)
61 #define TOP_L(db) (&(name_top(&(db)->cpp_name)->strp_l))
62 #define RLEN(f, l) ((size_t)((l) - (f)))
63 #define NAMT(db, n) (nlen(db) - n)
65 static inline boolean_t is_xdigit(int);
67 static boolean_t nempty(cpp_db_t *);
68 static size_t nlen(cpp_db_t *);
69 static void nadd_l(cpp_db_t *, const char *, size_t);
70 static void njoin(cpp_db_t *, size_t, const char *);
71 static void nfmt(cpp_db_t *, const char *, const char *);
73 static void save_top(cpp_db_t *, size_t);
74 static void sub(cpp_db_t *, size_t);
76 static boolean_t tempty(const cpp_db_t *);
77 static size_t ttlen(const cpp_db_t *);
79 static void tsub(cpp_db_t *, size_t);
80 static void tpush(cpp_db_t *);
81 static void tpop(cpp_db_t *);
82 static void tsave(cpp_db_t *, size_t);
84 static boolean_t db_init(cpp_db_t *, sysdem_ops_t *);
85 static void db_fini(cpp_db_t *);
86 static void dump(cpp_db_t *, FILE *);
88 static void demangle(const char *, const char *, cpp_db_t *);
90 static const char *parse_type(const char *, const char *, cpp_db_t *);
91 static const char *parse_builtin_type(const char *, const char *, cpp_db_t *);
92 static const char *parse_qual_type(const char *, const char *, cpp_db_t *);
93 static const char *parse_encoding(const char *, const char *, cpp_db_t *);
94 static const char *parse_dot_suffix(const char *, const char *, cpp_db_t *);
95 static const char *parse_block_invoke(const char *, const char *, cpp_db_t *);
96 static const char *parse_special_name(const char *, const char *, cpp_db_t *);
97 static const char *parse_name(const char *, const char *, boolean_t *,
98 cpp_db_t *);
99 static const char *parse_call_offset(const char *, const char *, locale_t);
100 static const char *parse_number(const char *, const char *, locale_t);
101 static const char *parse_nested_name(const char *, const char *, boolean_t *,
102 cpp_db_t *);
103 static const char *parse_local_name(const char *, const char *, boolean_t *,
104 cpp_db_t *);
105 static const char *parse_unscoped_name(const char *, const char *, cpp_db_t *);
106 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
107 static const char *parse_substitution(const char *, const char *, cpp_db_t *);
108 static const char *parse_discriminator(const char *, const char *, locale_t);
109 static const char *parse_cv_qualifiers(const char *, const char *, unsigned *);
110 static const char *parse_template_param(const char *, const char *, cpp_db_t *);
111 static const char *parse_decltype(const char *, const char *, cpp_db_t *);
112 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
113 static const char *parse_unqualified_name(const char *, const char *,
114 cpp_db_t *);
115 static const char *parse_template_arg(const char *, const char *, cpp_db_t *);
116 static const char *parse_expression(const char *, const char *, cpp_db_t *);
117 static const char *parse_expr_primary(const char *, const char *, cpp_db_t *);
118 static const char *parse_binary_expr(const char *, const char *,
119 const char *, cpp_db_t *);
120 static const char *parse_prefix_expr(const char *, const char *,
121 const char *, cpp_db_t *);
122 static const char *parse_gs(const char *, const char *, cpp_db_t *);
123 static const char *parse_idx_expr(const char *, const char *, cpp_db_t *);
124 static const char *parse_mm_expr(const char *, const char *, cpp_db_t *);
125 static const char *parse_pp_expr(const char *, const char *, cpp_db_t *);
126 static const char *parse_trinary_expr(const char *, const char *, cpp_db_t *);
127 static const char *parse_new_expr(const char *, const char *, cpp_db_t *);
128 static const char *parse_del_expr(const char *, const char *, cpp_db_t *);
129 static const char *parse_cast_expr(const char *, const char *, cpp_db_t *);
130 static const char *parse_sizeof_param_pack_expr(const char *, const char *,
131 cpp_db_t *);
132 static const char *parse_typeid_expr(const char *, const char *, cpp_db_t *);
133 static const char *parse_throw_expr(const char *, const char *, cpp_db_t *);
134 static const char *parse_dot_star_expr(const char *, const char *, cpp_db_t *);
135 static const char *parse_dot_expr(const char *, const char *, cpp_db_t *);
136 static const char *parse_call_expr(const char *, const char *, cpp_db_t *);
137 static const char *parse_arrow_expr(const char *, const char *, cpp_db_t *);
138 static const char *parse_conv_expr(const char *, const char *, cpp_db_t *);
139 static const char *parse_function_param(const char *, const char *, cpp_db_t *);
140 static const char *parse_base_unresolved_name(const char *, const char *,
141 cpp_db_t *);
142 static const char *parse_unresolved_name(const char *, const char *,
143 cpp_db_t *);
144 static const char *parse_noexcept_expr(const char *, const char *, cpp_db_t *);
145 static const char *parse_alignof(const char *, const char *, cpp_db_t *);
146 static const char *parse_sizeof(const char *, const char *, cpp_db_t *);
147 static const char *parse_unnamed_type_name(const char *, const char *,
148 cpp_db_t *);
149 static const char *parse_ctor_dtor_name(const char *, const char *, cpp_db_t *);
150 static const char *parse_source_name(const char *, const char *, cpp_db_t *);
151 static const char *parse_operator_name(const char *, const char *, cpp_db_t *);
152 static const char *parse_pack_expansion(const char *, const char *, cpp_db_t *);
153 static const char *parse_unresolved_type(const char *, const char *,
154 cpp_db_t *);
155 static const char *parse_unresolved_qualifier_level(const char *, const char *,
156 cpp_db_t *);
157 static const char *parse_destructor_name(const char *, const char *,
158 cpp_db_t *);
159 static const char *parse_function_type(const char *, const char *, cpp_db_t *);
160 static const char *parse_array_type(const char *, const char *, cpp_db_t *);
161 static const char *parse_pointer_to_member_type(const char *, const char *,
162 cpp_db_t *);
163 static const char *parse_vector_type(const char *, const char *, cpp_db_t *);
165 size_t cpp_name_max_depth = 1024; /* max depth of name stack */
167 char *
168 cpp_demangle(const char *src, sysdem_ops_t *ops)
170 char *result = NULL;
171 cpp_db_t db;
172 size_t srclen = strlen(src);
174 if (!db_init(&db, ops))
175 goto done;
176 if (setjmp(db.cpp_jmp) != 0)
177 goto done;
179 errno = 0;
180 demangle(src, src + srclen, &db);
182 if (errno == 0 && db.cpp_fix_forward_references &&
183 !templ_empty(&db.cpp_templ) &&
184 !sub_empty(&db.cpp_templ.tpl_items[0])) {
185 db.cpp_fix_forward_references = B_FALSE;
186 db.cpp_tag_templates = B_FALSE;
187 name_clear(&db.cpp_name);
188 sub_clear(&db.cpp_subs);
190 if (setjmp(db.cpp_jmp) != 0)
191 goto done;
193 demangle(src, src + srclen, &db);
195 if (db.cpp_fix_forward_references) {
196 errno = EINVAL;
197 goto done;
201 if (errno != 0)
202 goto done;
204 if (nempty(&db)) {
205 errno = EINVAL;
206 goto done;
209 njoin(&db, 1, "");
211 if (nlen(&db) > 0) {
212 str_t *s = TOP_L(&db);
213 char *res = zalloc(ops, s->str_len + 1);
214 if (res == NULL)
215 goto done;
217 (void) memcpy(res, s->str_s, s->str_len);
218 result = res;
221 done:
222 if (demangle_debug)
223 dump(&db, stdout);
225 db_fini(&db);
226 return (result);
229 static void
230 demangle(const char *first, const char *last, cpp_db_t *db)
232 const char *t = NULL;
234 if (first >= last) {
235 errno = EINVAL;
236 return;
239 if (first[0] != '_') {
240 t = parse_type(first, last, db);
241 if (t == first) {
242 errno = EINVAL;
243 return;
245 goto done;
248 if (last - first < 4) {
249 errno = EINVAL;
250 return;
253 if (first[1] == 'Z') {
254 t = parse_encoding(first + 2, last, db);
256 if (t != first + 2 && t != last && t[0] == '.') {
257 t = parse_dot_suffix(t, last, db);
258 if (nlen(db) > 1)
259 njoin(db, 2, "");
262 goto done;
265 if (first[1] != '_' || first[2] != '_' || first[3] != 'Z')
266 goto done;
268 t = parse_encoding(first + 4, last, db);
269 if (t != first + 4 && t != last)
270 t = parse_block_invoke(t, last, db);
272 done:
273 if (t != last)
274 errno = EINVAL;
277 static const char *
278 parse_dot_suffix(const char *first, const char *last, cpp_db_t *db)
280 VERIFY3P(first, <=, last);
282 if (first == last || first[0] != '.')
283 return (first);
285 if (nempty(db))
286 return (first);
288 nadd_l(db, first, RLEN(first, last));
289 nfmt(db, " ({0})", NULL);
291 return (last);
295 * _block_invoke
296 * _block_invoke<digit>*
297 * _block_invoke_<digit>+
299 static const char *
300 parse_block_invoke(const char *first, const char *last, cpp_db_t *db)
302 VERIFY3P(first, <=, last);
304 if (last - first < 13)
305 return (first);
307 const char test[] = "_block_invoke";
308 const char *t = first;
310 if (strncmp(first, test, sizeof (test) - 1) != 0)
311 return (first);
313 t += sizeof (test);
314 if (t == last)
315 goto done;
317 if (t[0] == '_') {
318 /* need at least one digit */
319 if (t + 1 == last || !isdigit_l(t[1], db->cpp_loc))
320 return (first);
321 t += 2;
324 while (t < last && isdigit_l(t[0], db->cpp_loc))
325 t++;
327 done:
328 if (nempty(db))
329 return (first);
331 nfmt(db, "invocation function for block in {0}", NULL);
332 return (t);
336 * <encoding> ::= <function name><bare-function-type>
337 * ::= <data name>
338 * ::= <special name>
340 static const char *
341 parse_encoding(const char *first, const char *last, cpp_db_t *db)
343 VERIFY3P(first, <=, last);
345 if (first == last)
346 return (first);
348 const char *t = NULL;
349 const char *t2 = NULL;
350 unsigned cv = 0;
351 unsigned ref = 0;
352 boolean_t tag_templ_save = db->cpp_tag_templates;
354 if (++db->cpp_depth > 1)
355 db->cpp_tag_templates = B_TRUE;
357 if (first[0] == 'G' || first[0] == 'T') {
358 t = parse_special_name(first, last, db);
359 goto done;
362 boolean_t ends_with_template_args = B_FALSE;
363 t = parse_name(first, last, &ends_with_template_args, db);
364 if (t == first)
365 goto fail;
367 cv = db->cpp_cv;
368 ref = db->cpp_ref;
370 if (t == last || t[0] == 'E' || t[0] == '.')
371 goto done;
373 db->cpp_tag_templates = B_FALSE;
374 if (nempty(db) || str_length(TOP_L(db)) == 0)
375 goto fail;
377 if (!db->cpp_parsed_ctor_dtor_cv && ends_with_template_args) {
378 t2 = parse_type(t, last, db);
379 if (t2 == t || nlen(db) < 2)
380 goto fail;
382 str_pair_t *sp = name_top(&db->cpp_name);
384 if (str_length(&sp->strp_r) == 0)
385 (void) str_append(&sp->strp_l, " ", 1);
387 nfmt(db, "{0:L}{1:L}", "{1:R}{0:R}");
388 t = t2;
391 if (t == last || nempty(db))
392 goto fail;
394 size_t n = nlen(db);
396 if (t[0] == 'v') {
397 t++;
398 } else {
399 for (;;) {
400 t2 = parse_type(t, last, db);
401 if (t2 == t || t == last)
402 break;
404 t = t2;
409 * a bit of a hack, but a template substitution can apparently be
410 * an empty string at the end of an argument list, so avoid
411 * <...., >
413 if (NAMT(db, n) > 1 && str_pair_len(name_top(&db->cpp_name)) == 0)
414 name_pop(&db->cpp_name, NULL);
416 njoin(db, NAMT(db, n), ", ");
417 nfmt(db, "({0})", NULL);
419 str_t *s = TOP_L(db);
421 if (cv & CPP_QUAL_CONST) {
422 CK(str_append(s, " const", 0));
424 if (cv & CPP_QUAL_VOLATILE) {
425 CK(str_append(s, " volatile", 0));
427 if (cv & CPP_QUAL_RESTRICT) {
428 CK(str_append(s, " restrict", 0));
430 if (ref == 1) {
431 CK(str_append(s, " &", 0));
433 if (ref == 2) {
434 CK(str_append(s, " &&", 0));
437 nfmt(db, "{1:L}{0}{1:R}", NULL);
439 done:
440 db->cpp_tag_templates = tag_templ_save;
441 db->cpp_depth--;
442 return (t);
444 fail:
445 db->cpp_tag_templates = tag_templ_save;
446 db->cpp_depth--;
447 return (first);
451 * <special-name> ::= TV <type> # virtual table
452 * ::= TT <type> # VTT structure (construction vtable index)
453 * ::= TI <type> # typeinfo structure
454 * ::= TS <type> # typeinfo name (null-terminated byte string)
455 * ::= Tc <call-offset> <call-offset> <base encoding>
456 * # base is the nominal target function of thunk
457 * # first call-offset is 'this' adjustment
458 * # second call-offset is result adjustment
459 * ::= T <call-offset> <base encoding>
460 * # base is the nominal target function of thunk
461 * ::= GV <object name> # Guard variable for one-time init
462 * # No <type>
463 * ::= TW <object name> # Thread-local wrapper
464 * ::= TH <object name> # Thread-local initialization
465 * extension ::= TC <first type> <number> _ <second type>
466 * # construction vtable for second-in-first
467 * extension ::= GR <object name> # reference temporary for object
469 static const char *
470 parse_special_name(const char *first, const char *last, cpp_db_t *db)
472 VERIFY3P(first, <=, last);
474 const char *t = first;
475 const char *t1 = NULL;
476 size_t n = nlen(db);
478 if (last - first < 2)
479 return (first);
481 switch (t[0]) {
482 case 'T':
483 switch (t[1]) {
484 case 'V':
485 nadd_l(db, "vtable for", 0);
486 t = parse_type(first + 2, last, db);
487 break;
488 case 'T':
489 nadd_l(db, "VTT for", 0);
490 t = parse_type(first + 2, last, db);
491 break;
492 case 'I':
493 nadd_l(db, "typeinfo for", 0);
494 t = parse_type(first + 2, last, db);
495 break;
496 case 'S':
497 nadd_l(db, "typeinfo name for", 0);
498 t = parse_type(first + 2, last, db);
499 break;
500 case 'c':
501 nadd_l(db, "covariant return thunk to", 0);
502 t1 = parse_call_offset(first + 2, last, db->cpp_loc);
503 if (t1 == t)
504 return (first);
505 t = parse_call_offset(t1, last, db->cpp_loc);
506 if (t == t1)
507 return (first);
508 t1 = parse_encoding(t, last, db);
509 if (t1 == t)
510 return (first);
511 break;
512 case 'C':
513 t = parse_type(first + 2, last, db);
514 if (t == first + 2)
515 return (first);
516 t1 = parse_number(t, last, db->cpp_loc);
517 if (*t1 != '_')
518 return (first);
519 t = parse_type(t1 + 1, last, db);
520 if (t == t1 + 1 || nlen(db) < 2)
521 return (first);
522 nfmt(db, "construction vtable for {0}-in-{1}", NULL);
523 return (t);
524 case 'W':
525 nadd_l(db, "thread-local wrapper routine for", 0);
526 t = parse_name(first + 2, last, NULL, db);
527 break;
528 case 'H':
529 nadd_l(db, "thread-local initialization routine for",
531 t = parse_name(first + 2, last, NULL, db);
532 break;
533 default:
534 if (first[1] == 'v') {
535 nadd_l(db, "virtual thunk to", 0);
536 } else {
537 nadd_l(db, "non-virtual thunk to", 0);
540 t = parse_call_offset(first + 1, last, db->cpp_loc);
541 if (t == first + 1)
542 return (first);
543 t1 = parse_encoding(t, last, db);
544 if (t == t1)
545 return (first);
546 t = t1;
547 break;
549 break;
550 case 'G':
551 switch (first[1]) {
552 case 'V':
553 nadd_l(db, "guard variable for", 0);
554 t = parse_name(first + 2, last, NULL, db);
555 break;
556 case 'R':
557 nadd_l(db, "reference temporary for", 0);
558 t = parse_name(first + 2, last, NULL, db);
559 break;
560 default:
561 return (first);
563 break;
564 default:
565 return (first);
568 size_t amt = NAMT(db, n);
569 if (t == first + 2 || amt < 2)
570 return (first);
572 njoin(db, amt, " ");
573 return (t);
577 * <call-offset> ::= h <nv-offset> _
578 * ::= v <v-offset> _
580 * <nv-offset> ::= <offset number>
581 * # non-virtual base override
583 * <v-offset> ::= <offset number> _ <virtual offset number>
584 * # virtual base override, with vcall offset
586 static const char *
587 parse_call_offset(const char *first, const char *last, locale_t loc)
589 VERIFY3P(first, <=, last);
591 const char *t = NULL;
592 const char *t1 = NULL;
594 if (first == last)
595 return (first);
597 if (first[0] != 'h' && first[0] != 'v')
598 return (first);
600 t = parse_number(first + 1, last, loc);
601 if (t == first + 1 || t == last || t[0] != '_')
602 return (first);
604 /* skip _ */
605 t++;
607 if (first[0] == 'h')
608 return (t);
610 t1 = parse_number(t, last, loc);
611 if (t == t1 || t1 == last || t1[0] != '_')
612 return (first);
614 /* skip _ */
615 t1++;
617 return (t1);
621 * <name> ::= <nested-name> // N
622 * ::= <local-name> # See Scope Encoding below // Z
623 * ::= <unscoped-template-name> <template-args>
624 * ::= <unscoped-name>
626 * <unscoped-template-name> ::= <unscoped-name>
627 * ::= <substitution>
629 static const char *
630 parse_name(const char *first, const char *last,
631 boolean_t *ends_with_template_args, cpp_db_t *db)
633 VERIFY3P(first, <=, last);
635 const char *t = first;
636 const char *t1 = NULL;
638 if (last - first < 2)
639 return (first);
641 /* extension: ignore L here */
642 if (t[0] == 'L')
643 t++;
645 switch (t[0]) {
646 case 'N':
647 t1 = parse_nested_name(t, last, ends_with_template_args, db);
648 return ((t == t1) ? first : t1);
649 case 'Z':
650 t1 = parse_local_name(t, last, ends_with_template_args, db);
651 return ((t == t1) ? first : t1);
655 * <unscoped-name>
656 * <unscoped-name> <template-args>
657 * <substitution> <template-args>
659 t1 = parse_unscoped_name(t, last, db);
661 /* <unscoped-name> */
662 if (t != t1 && t1[0] != 'I')
663 return (t1);
665 if (t == t1) {
666 t1 = parse_substitution(t, last, db);
667 if (t == t1 || t1 == last || t1[0] != 'I')
668 return (first);
669 } else {
670 save_top(db, 1);
673 t = parse_template_args(t1, last, db);
674 if (t1 == t || nlen(db) < 2)
675 return (first);
677 nfmt(db, "{1:L}{0}", "{1:R}");
679 if (ends_with_template_args != NULL)
680 *ends_with_template_args = B_TRUE;
682 return (t);
685 /* BEGIN CSTYLED */
687 * <local-name> := Z <function encoding> E <entity name> [<discriminator>]
688 * := Z <function encoding> E s [<discriminator>]
689 * := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
691 /* END CSTYLED */
692 const char *
693 parse_local_name(const char *first, const char *last,
694 boolean_t *ends_with_template_args, cpp_db_t *db)
696 VERIFY3P(first, <=, last);
698 const char *t = NULL;
699 const char *t1 = NULL;
700 const char *t2 = NULL;
702 if (first == last || first[0] != 'Z')
703 return (first);
705 t = parse_encoding(first + 1, last, db);
706 if (t == first + 1 || t == last || t[0] != 'E')
707 return (first);
709 VERIFY(!nempty(db));
711 /* skip E */
712 t++;
714 if (t[0] == 's') {
715 nfmt(db, "{0:L}::string literal", "{0:R}");
716 return (parse_discriminator(t, last, db->cpp_loc));
719 if (t[0] == 'd') {
720 t1 = parse_number(t + 1, last, db->cpp_loc);
721 if (t1[0] != '_')
722 return (first);
723 t1++;
724 } else {
725 t1 = t;
728 t2 = parse_name(t1, last, ends_with_template_args, db);
729 if (t2 == t1)
730 return (first);
732 nfmt(db, "{1:L}::{0}", "{1:R}");
734 /* parsed, but ignored */
735 if (t[0] != 'd')
736 t2 = parse_discriminator(t2, last, db->cpp_loc);
738 return (t2);
741 /* BEGIN CSTYLED */
743 * <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
744 * ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
746 * <prefix> ::= <prefix> <unqualified-name>
747 * ::= <template-prefix> <template-args>
748 * ::= <template-param>
749 * ::= <decltype>
750 * ::= # empty
751 * ::= <substitution>
752 * ::= <prefix> <data-member-prefix>
753 * extension ::= L
755 * <template-prefix> ::= <prefix> <template unqualified-name>
756 * ::= <template-param>
757 * ::= <substitution>
759 /* END CSTYLED */
760 static const char *
761 parse_nested_name(const char *first, const char *last,
762 boolean_t *ends_with_template_args, cpp_db_t *db)
764 VERIFY3P(first, <=, last);
766 if (first == last || first[0] != 'N')
767 return (first);
769 unsigned cv = 0;
770 const char *t = parse_cv_qualifiers(first + 1, last, &cv);
772 if (t == last)
773 return (first);
775 boolean_t more = B_FALSE;
777 switch (t[0]) {
778 case 'R':
779 db->cpp_ref = 1;
780 t++;
781 break;
782 case 'O':
783 db->cpp_ref = 2;
784 t++;
785 break;
786 case 'S':
787 if (last - first < 2 || t[1] != 't')
788 break;
789 if (last - first == 2)
790 return (first);
791 nadd_l(db, "std", 3);
792 more = B_TRUE;
793 t += 2;
794 break;
797 boolean_t pop_subs = B_FALSE;
798 boolean_t component_ends_with_template_args = B_FALSE;
800 while (t[0] != 'E' && t != last) {
801 const char *t1 = NULL;
802 size_t n = nlen(db);
803 component_ends_with_template_args = B_FALSE;
805 switch (t[0]) {
806 case 'S':
807 if (t + 1 != last && t[1] == 't')
808 break;
810 t1 = parse_substitution(t, last, db);
811 if (t1 == t || t1 == last || NAMT(db, n) != 1)
812 return (first);
814 if (!more) {
815 nfmt(db, "{0}", NULL);
816 } else {
817 VERIFY3U(nlen(db), >, 1);
818 nfmt(db, "{1:L}::{0}", "{1:R}");
819 save_top(db, 1);
822 more = B_TRUE;
823 pop_subs = B_TRUE;
824 t = t1;
825 continue;
827 case 'T':
828 t1 = parse_template_param(t, last, db);
829 if (t1 == t || t1 == last || NAMT(db, n) != 1)
830 return (first);
832 if (!more) {
833 nfmt(db, "{0}", NULL);
834 } else {
835 VERIFY3U(nlen(db), >, 1);
836 nfmt(db, "{1:L}::{0}", "{1:R}");
839 save_top(db, 1);
840 more = B_TRUE;
841 pop_subs = B_TRUE;
842 t = t1;
843 continue;
845 case 'D':
846 if (t + 1 != last && t[1] != 't' && t[1] != 'T')
847 break;
848 t1 = parse_decltype(t, last, db);
849 if (t1 == t || t1 == last || NAMT(db, n) != 1)
850 return (first);
852 if (!more) {
853 nfmt(db, "{0}", NULL);
854 } else {
855 VERIFY3U(nlen(db), >, 1);
856 nfmt(db, "{1:L}::{0}", "{1:R}");
859 save_top(db, 1);
860 more = B_TRUE;
861 pop_subs = B_TRUE;
862 t = t1;
863 continue;
865 case 'I':
867 * Must have at least one component before
868 * <template-args>
870 if (!more)
871 return (first);
873 t1 = parse_template_args(t, last, db);
874 if (t1 == t || t1 == last)
875 return (first);
877 VERIFY3U(nlen(db), >, 1);
878 nfmt(db, "{1:L}{0}", "{1:R}");
879 save_top(db, 1);
880 t = t1;
881 component_ends_with_template_args = B_TRUE;
882 continue;
884 case 'L':
885 if (t + 1 == last)
886 return (first);
887 t++;
888 continue;
890 default:
891 break;
894 t1 = parse_unqualified_name(t, last, db);
895 if (t1 == t || t1 == last || NAMT(db, n) != 1)
896 return (first);
898 if (!more) {
899 nfmt(db, "{0}", NULL);
900 } else {
901 VERIFY3U(nlen(db), >, 1);
902 nfmt(db, "{1:L}::{0}", "{1:R}");
905 save_top(db, 1);
906 more = B_TRUE;
907 pop_subs = B_TRUE;
908 t = t1;
911 /* need to parse at least one thing */
912 if (!more)
913 return (first);
915 db->cpp_cv = cv;
916 if (pop_subs && !sub_empty(&db->cpp_subs))
917 sub_pop(&db->cpp_subs);
919 if (ends_with_template_args != NULL)
920 *ends_with_template_args = component_ends_with_template_args;
922 if (t[0] != 'E')
923 return (first);
925 return (t + 1);
929 * <template-arg> ::= <type> # type or template
930 * ::= X <expression> E # expression
931 * ::= <expr-primary> # simple expressions
932 * ::= J <template-arg>* E # argument pack
933 * ::= LZ <encoding> E # extension
935 static const char *
936 parse_template_arg(const char *first, const char *last, cpp_db_t *db)
938 VERIFY3P(first, <=, last);
940 const char *t = NULL;
941 const char *t1 = NULL;
943 if (first == last)
944 return (first);
946 switch (first[0]) {
947 case 'X':
948 t = parse_expression(first + 1, last, db);
949 if (t == first + 1 || t[0] != 'E')
950 return (first);
952 /* E */
953 t++;
954 break;
956 case 'J':
957 t = first + 1;
958 if (t == last)
959 return (first);
961 while (t[0] != 'E') {
962 t1 = parse_template_arg(t, last, db);
963 if (t == t1)
964 return (first);
965 t = t1;
968 /* E */
969 t++;
970 break;
972 case 'L':
973 if (first + 1 == last || first[1] != 'Z') {
974 t = parse_expr_primary(first, last, db);
975 } else {
976 t = parse_encoding(first + 2, last, db);
977 if (t == first + 2 || t == last || t[0] != 'E')
978 return (first);
980 /* E */
981 t++;
983 break;
985 default:
986 t = parse_type(first, last, db);
989 return (t);
992 /* BEGIN CSTYLED */
994 * <expression> ::= <unary operator-name> <expression>
995 * ::= <binary operator-name> <expression> <expression>
996 * ::= <ternary operator-name> <expression> <expression> <expression>
997 * ::= cl <expression>+ E # call
998 * ::= cv <type> <expression> # conversion with one argument
999 * ::= cv <type> _ <expression>* E # conversion with a different number of arguments
1000 * ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
1001 * ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1002 * ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
1003 * ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1004 * ::= [gs] dl <expression> # delete expression
1005 * ::= [gs] da <expression> # delete[] expression
1006 * ::= pp_ <expression> # prefix ++
1007 * ::= mm_ <expression> # prefix --
1008 * ::= ti <type> # typeid (type)
1009 * ::= te <expression> # typeid (expression)
1010 * ::= dc <type> <expression> # dynamic_cast<type> (expression)
1011 * ::= sc <type> <expression> # static_cast<type> (expression)
1012 * ::= cc <type> <expression> # const_cast<type> (expression)
1013 * ::= rc <type> <expression> # reinterpret_cast<type> (expression)
1014 * ::= st <type> # sizeof (a type)
1015 * ::= sz <expression> # sizeof (an expression)
1016 * ::= at <type> # alignof (a type)
1017 * ::= az <expression> # alignof (an expression)
1018 * ::= nx <expression> # noexcept (expression)
1019 * ::= <template-param>
1020 * ::= <function-param>
1021 * ::= dt <expression> <unresolved-name> # expr.name
1022 * ::= pt <expression> <unresolved-name> # expr->name
1023 * ::= ds <expression> <expression> # expr.*expr
1024 * ::= sZ <template-param> # size of a parameter pack
1025 * ::= sZ <function-param> # size of a function parameter pack
1026 * ::= sp <expression> # pack expansion
1027 * ::= tw <expression> # throw expression
1028 * ::= tr # throw with no operand (rethrow)
1029 * ::= <unresolved-name> # f(p), N::f(p), ::f(p),
1030 * # freestanding dependent name (e.g., T::x),
1031 * # objectless nonstatic member reference
1032 * ::= <expr-primary>
1034 /* END CSTYLED */
1036 #define PA(cd, arg, fn) { \
1037 .code = cd, \
1038 .p.parse_expr_arg = fn, \
1039 .fntype = EXPR_ARG, \
1040 .val = arg \
1043 #define PN(cd, fn) { \
1044 .code = cd, \
1045 .p.parse_expr_noarg = fn, \
1046 .fntype = EXPR_NOARG \
1049 static struct {
1050 const char code[3];
1051 union {
1052 const char *(*parse_expr_arg)(const char *, const char *,
1053 const char *, cpp_db_t *);
1054 const char *(*parse_expr_noarg)(const char *, const char *,
1055 cpp_db_t *);
1056 } p;
1057 enum {
1058 EXPR_ARG,
1059 EXPR_NOARG
1060 } fntype;
1061 const char val[4];
1062 } expr_tbl[] = {
1063 PA("aN", "&=", parse_binary_expr),
1064 PA("aS", "=", parse_binary_expr),
1065 PA("aa", "&&", parse_binary_expr),
1066 PA("ad", "&", parse_prefix_expr),
1067 PA("an", "&", parse_binary_expr),
1068 PN("at", parse_alignof),
1069 PN("az", parse_alignof),
1070 PN("cc", parse_cast_expr),
1071 PN("cl", parse_call_expr),
1072 PA("cm", ",", parse_binary_expr),
1073 PA("co", "~", parse_prefix_expr),
1074 PN("cv", parse_conv_expr),
1075 PN("da", parse_del_expr),
1076 PA("dV", "/=", parse_binary_expr),
1077 PN("dc", parse_cast_expr),
1078 PA("de", "*", parse_prefix_expr),
1079 PN("dl", parse_del_expr),
1080 PN("dn", parse_unresolved_name),
1081 PN("ds", parse_dot_star_expr),
1082 PN("dt", parse_dot_expr),
1083 PA("dv", "/", parse_binary_expr),
1084 PA("eO", "^=", parse_binary_expr),
1085 PA("eo", "^", parse_binary_expr),
1086 PA("eq", "==", parse_binary_expr),
1087 PA("ge", ">=", parse_binary_expr),
1088 PN("gs", parse_gs),
1089 PA("gt", ">", parse_binary_expr),
1090 PN("ix", parse_idx_expr),
1091 PA("lS", "<<=", parse_binary_expr),
1092 PA("le", "<=", parse_binary_expr),
1093 PA("ls", "<<", parse_binary_expr),
1094 PA("lt", "<", parse_binary_expr),
1095 PA("mI", "-=", parse_binary_expr),
1096 PA("mL", "*=", parse_binary_expr),
1097 PN("mm", parse_mm_expr),
1098 PA("mi", "-", parse_binary_expr),
1099 PA("ml", "*", parse_binary_expr),
1100 PN("na", parse_new_expr),
1101 PA("ne", "!=", parse_binary_expr),
1102 PA("ng", "-", parse_prefix_expr),
1103 PA("nt", "!", parse_prefix_expr),
1104 PN("nw", parse_new_expr),
1105 PN("nx", parse_noexcept_expr),
1106 PA("oR", "|=", parse_binary_expr),
1107 PN("on", parse_unresolved_name),
1108 PA("oo", "||", parse_binary_expr),
1109 PA("or", "|", parse_binary_expr),
1110 PA("pL", "+=", parse_binary_expr),
1111 PA("pl", "+", parse_binary_expr),
1112 PA("pm", "->*", parse_binary_expr),
1113 PN("pp", parse_pp_expr),
1114 PA("ps", "+", parse_prefix_expr),
1115 PN("pt", parse_arrow_expr),
1116 PN("qu", parse_trinary_expr),
1117 PA("rM", "%=", parse_binary_expr),
1118 PA("rS", ">>=", parse_binary_expr),
1119 PN("rc", parse_cast_expr),
1120 PA("rm", "%", parse_binary_expr),
1121 PA("rs", ">>", parse_binary_expr),
1122 PN("sc", parse_cast_expr),
1123 PN("sp", parse_pack_expansion),
1124 PN("sr", parse_unresolved_name),
1125 PN("st", parse_sizeof),
1126 PN("sz", parse_sizeof),
1127 PN("sZ", parse_sizeof_param_pack_expr),
1128 PN("te", parse_typeid_expr),
1129 PN("tr", parse_throw_expr),
1130 PN("tw", parse_throw_expr)
1132 #undef PA
1133 #undef PN
1135 static const char *
1136 parse_expression(const char *first, const char *last, cpp_db_t *db)
1138 VERIFY3P(first, <=, last);
1140 if (last - first < 2)
1141 return (first);
1143 for (size_t i = 0; i < ARRAY_SIZE(expr_tbl); i++) {
1144 if (strncmp(expr_tbl[i].code, first, 2) != 0)
1145 continue;
1146 switch (expr_tbl[i].fntype) {
1147 case EXPR_ARG:
1148 return (expr_tbl[i].p.parse_expr_arg(first, last,
1149 expr_tbl[i].val, db));
1150 case EXPR_NOARG:
1151 return (expr_tbl[i].p.parse_expr_noarg(first, last,
1152 db));
1156 switch (first[0]) {
1157 case 'L':
1158 return (parse_expr_primary(first, last, db));
1159 case 'T':
1160 return (parse_template_param(first, last, db));
1161 case 'f':
1162 return (parse_function_param(first, last, db));
1163 case '1':
1164 case '2':
1165 case '3':
1166 case '4':
1167 case '5':
1168 case '6':
1169 case '7':
1170 case '8':
1171 case '9':
1172 return (parse_unresolved_name(first, last, db));
1175 return (first);
1178 static const char *
1179 parse_binary_expr(const char *first, const char *last, const char *op,
1180 cpp_db_t *db)
1182 VERIFY3P(first, <=, last);
1184 if (last - first < 2)
1185 return (first);
1187 size_t n = nlen(db);
1189 const char *t1 = parse_expression(first + 2, last, db);
1190 if (t1 == first + 2)
1191 return (first);
1193 nadd_l(db, op, 0);
1195 const char *t2 = parse_expression(t1, last, db);
1196 if (t2 == t1)
1197 return (first);
1199 if (NAMT(db, n) != 3)
1200 return (first);
1202 VERIFY3U(nlen(db), >, 2);
1204 nfmt(db, "({2}) {1} ({0})", NULL);
1205 if (strcmp(op, ">") == 0)
1206 nfmt(db, "({0})", NULL);
1208 return (t2);
1211 static const char *
1212 parse_prefix_expr(const char *first, const char *last, const char *op,
1213 cpp_db_t *db)
1215 VERIFY3P(first, <=, last);
1217 if (last - first < 2)
1218 return (first);
1220 nadd_l(db, op, 0);
1222 const char *t = parse_expression(first + 2, last, db);
1223 if (t == first + 2) {
1224 return (first);
1227 VERIFY3U(nlen(db), >, 1);
1229 nfmt(db, "{1}({0})", NULL);
1230 return (t);
1233 static const char *
1234 parse_gs(const char *first, const char *last, cpp_db_t *db)
1236 VERIFY3P(first, <=, last);
1238 const char *t = NULL;
1240 if (last - first < 4)
1241 return (first);
1243 if (first[2] == 'n' && (first[3] == 'a' || first[3] == 'w'))
1244 t = parse_new_expr(first + 2, last, db);
1245 else if (first[2] == 'd' && (first[3] == 'l' || first[3] == 'a'))
1246 t = parse_del_expr(first + 2, last, db);
1247 else
1248 return (first);
1250 if (t == first + 2)
1251 return (first);
1253 VERIFY3U(nlen(db), >, 0);
1255 nfmt(db, "::{0}", NULL);
1256 return (t);
1260 * [gs] nw <expression>* _ <type> E # new (expr-list) type
1261 * [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1262 * [gs] na <expression>* _ <type> E # new[] (expr-list) type
1263 * [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1264 * <initializer> ::= pi <expression>* E # parenthesized initialization
1266 static const char *
1267 parse_new_expr(const char *first, const char *last, cpp_db_t *db)
1269 VERIFY3P(first, <=, last);
1271 /* note [gs] is already handled by parse_gs() */
1272 if (last - first < 3)
1273 return (first);
1275 VERIFY3U(first[0], ==, 'n');
1276 VERIFY(first[1] == 'a' || first[1] == 'w');
1278 const char *t1 = first + 2;
1279 const char *t2 = NULL;
1280 size_t n = nlen(db);
1282 nadd_l(db, (first[1] == 'w') ? "new" : "new[]", 0);
1284 while (t1 != last && t1[0] != '_') {
1285 t2 = parse_expression(t1, last, db);
1286 VERIFY3P(t2, !=, NULL);
1287 if (t2 == t1)
1288 return (first);
1289 t1 = t2;
1291 if (t1 == last)
1292 return (first);
1294 if (NAMT(db, n) > 1) {
1295 njoin(db, NAMT(db, n) - 1, ", ");
1296 nfmt(db, "({0})", NULL);
1299 t2 = parse_type(t1 + 1, last, db);
1300 if (t1 + 1 == t2)
1301 return (first);
1303 if (t2[0] != 'E') {
1304 if (last - t2 < 3)
1305 return (first);
1306 if (t2[0] != 'p' && t2[1] != 'i')
1307 return (first);
1309 t2 += 2;
1310 const char *t3 = t2;
1311 size_t n1 = nlen(db);
1313 while (t2[0] != 'E' && t2 != last) {
1314 t3 = parse_expression(t2, last, db);
1316 if (t2 == t3)
1317 return (first);
1318 t2 = t3;
1320 if (t3 == last || t3[0] != 'E')
1321 return (first);
1323 if (NAMT(db, n1) > 0) {
1324 njoin(db, NAMT(db, n1), ", ");
1325 nfmt(db, "({0})", NULL);
1329 njoin(db, NAMT(db, n), " ");
1330 return (t2 + 1);
1333 static const char *
1334 parse_del_expr(const char *first, const char *last, cpp_db_t *db)
1336 VERIFY3P(first, <=, last);
1338 if (last - first < 3)
1339 return (first);
1341 VERIFY3U(first[0], ==, 'd');
1342 VERIFY(first[1] == 'l' || first[1] == 'a');
1344 size_t n = nlen(db);
1345 const char *t = parse_expression(first + 2, last, db);
1346 if (t == first + 2 || NAMT(db, n) != 1)
1347 return (first);
1349 nfmt(db, (first[1] == 'a') ? "delete[] {0}" : "delete {0}", NULL);
1350 return (t);
1353 static const char *
1354 parse_idx_expr(const char *first, const char *last, cpp_db_t *db)
1356 VERIFY3P(first, <=, last);
1357 VERIFY3U(first[0], ==, 'i');
1358 VERIFY3U(first[1], ==, 'x');
1360 size_t n = nlen(db);
1361 const char *t1 = parse_expression(first + 2, last, db);
1362 if (t1 == first + 2)
1363 return (first);
1365 const char *t2 = parse_expression(t1, last, db);
1366 if (t2 == t1 || NAMT(db, n) != 2)
1367 return (first);
1369 nfmt(db, "({0})[{1}]", NULL);
1370 return (t2);
1373 static const char *
1374 parse_ppmm_expr(const char *first, const char *last, const char *fmt,
1375 cpp_db_t *db)
1377 VERIFY3P(first, <=, last);
1379 if (last - first < 3)
1380 return (first);
1382 const char *t = NULL;
1383 size_t n = nlen(db);
1385 if (first[2] == '_') {
1386 t = parse_binary_expr(first + 3, last, "--", db);
1387 if (t == first + 3)
1388 return (first);
1389 return (t);
1392 t = parse_expression(first + 2, last, db);
1393 if (t == first + 2 || NAMT(db, n) < 1)
1394 return (first);
1396 nfmt(db, fmt, NULL);
1397 return (t);
1400 static const char *
1401 parse_mm_expr(const char *first, const char *last, cpp_db_t *db)
1403 VERIFY3P(first, <=, last);
1404 VERIFY3U(first[0], ==, 'm');
1405 VERIFY3U(first[1], ==, 'm');
1407 return (parse_ppmm_expr(first, last, "({0})--", db));
1410 static const char *
1411 parse_pp_expr(const char *first, const char *last, cpp_db_t *db)
1413 VERIFY3P(first, <=, last);
1415 VERIFY3U(first[0], ==, 'p');
1416 VERIFY3U(first[0], ==, 'p');
1418 return (parse_ppmm_expr(first, last, "({0})++", db));
1421 static const char *
1422 parse_trinary_expr(const char *first, const char *last, cpp_db_t *db)
1424 VERIFY3P(first, <=, last);
1426 const char *t1, *t2, *t3;
1427 size_t n = nlen(db);
1429 if (last - first < 2)
1430 return (first);
1432 t1 = parse_expression(first + 2, last, db);
1433 if (t1 == first + 2)
1434 return (first);
1435 t2 = parse_expression(t1, last, db);
1436 if (t1 == t2)
1437 return (first);
1438 t3 = parse_expression(t2, last, db);
1439 if (t3 == t2)
1440 return (first);
1442 if (NAMT(db, n) != 3)
1443 return (first);
1445 nfmt(db, "({2}) ? ({1}) : ({0})", NULL);
1446 return (t3);
1449 static const char *
1450 parse_noexcept_expr(const char *first, const char *last, cpp_db_t *db)
1452 VERIFY3P(first, <=, last);
1454 if (last - first < 2)
1455 return (first);
1457 size_t n = nlen(db);
1458 const char *t = parse_expression(first + 2, last, db);
1459 if (t == first + 2 || NAMT(db, n) != 1)
1460 return (first);
1462 nfmt(db, "noexcept ({0})", NULL);
1463 return (t);
1467 * cc <type> <expression> # const_cast<type> (expression)
1468 * dc <type> <expression> # dynamic_cast<type> (expression)
1469 * rc <type> <expression> # reinterpret_cast<type> (expression)
1470 * sc <type> <expression> # static_cast<type> (expression)
1472 static const char *
1473 parse_cast_expr(const char *first, const char *last, cpp_db_t *db)
1475 VERIFY3P(first, <=, last);
1477 if (last - first < 2)
1478 return (first);
1480 const char *fmt = NULL;
1481 switch (first[0]) {
1482 case 'c':
1483 fmt = "const_cast<{1}> ({0})";
1484 break;
1485 case 'd':
1486 fmt = "dynamic_cast<{1}> ({0})";
1487 break;
1488 case 'r':
1489 fmt = "reinterpret_cast<{1}> ({0})";
1490 break;
1491 case 's':
1492 fmt = "static_cast<{1}> ({0})";
1493 break;
1494 default:
1495 return (first);
1498 VERIFY3U(first[1], ==, 'c');
1500 const char *t1 = parse_type(first + 2, last, db);
1501 if (t1 == first + 2)
1502 return (first);
1504 const char *t2 = parse_expression(t1, last, db);
1505 if (t2 == t1)
1506 return (first);
1508 VERIFY3U(nlen(db), >, 1);
1510 nfmt(db, fmt, NULL);
1511 return (t2);
1514 /* pt <expression> <expression> # expr->name */
1515 static const char *
1516 parse_arrow_expr(const char *first, const char *last, cpp_db_t *db)
1518 VERIFY3P(first, <=, last);
1520 if (last - first < 4)
1521 return (first);
1523 size_t n = nlen(db);
1525 const char *t1 = parse_expression(first + 2, last, db);
1526 if (t1 == first + 2)
1527 return (first);
1529 const char *t2 = parse_expression(t1, last, db);
1530 if (t2 == t1 || NAMT(db, n) != 2)
1531 return (first);
1533 nfmt(db, "{1}->{0}", NULL);
1534 return (t2);
1537 /* wrap value in () when necessary */
1538 static void
1539 paren(str_pair_t *sp)
1541 str_t *l = &sp->strp_l;
1542 str_t *r = &sp->strp_r;
1544 if (str_length(r) > 1 &&
1545 r->str_s[0] == ' ' && r->str_s[1] == '[') {
1546 (void) str_append(l, " (", 2);
1547 (void) str_insert(r, 0, ")", 1);
1548 } else if (str_length(r) > 0 && r->str_s[0] == '(') {
1549 (void) str_append(l, "(", 1);
1550 (void) str_insert(r, 0, ")", 1);
1554 /* BEGIN CSTYLED */
1556 * <type> ::= <builtin-type>
1557 * ::= <function-type>
1558 * ::= <class-enum-type>
1559 * ::= <array-type>
1560 * ::= <pointer-to-member-type>
1561 * ::= <template-param>
1562 * ::= <template-template-param> <template-args>
1563 * ::= <decltype>
1564 * ::= <substitution>
1565 * ::= <CV-qualifiers> <type>
1566 * ::= P <type> # pointer-to
1567 * ::= R <type> # reference-to
1568 * ::= O <type> # rvalue reference-to (C++0x)
1569 * ::= C <type> # complex pair (C 2000)
1570 * ::= G <type> # imaginary (C 2000)
1571 * ::= Dp <type> # pack expansion (C++0x)
1572 * ::= U <source-name> <type> # vendor extended type qualifier
1573 * extension := U <objc-name> <objc-type> # objc-type<identifier>
1574 * extension := <vector-type> # <vector-type> starts with Dv
1576 * <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1577 * <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1579 /* END CSTYLED */
1580 static const char *
1581 parse_type(const char *first, const char *last, cpp_db_t *db)
1583 VERIFY3P(first, <=, last);
1585 if (first == last)
1586 return (first);
1588 switch (first[0]) {
1589 case 'r':
1590 case 'V':
1591 case 'K':
1592 return (parse_qual_type(first, last, db));
1595 const char *t = first;
1596 const char *t1 = NULL;
1597 str_pair_t *sp = NULL;
1598 size_t n = nlen(db);
1599 size_t amt = 0;
1601 t = parse_builtin_type(first, last, db);
1602 if (t != first)
1603 return (t);
1605 switch (first[0]) {
1606 case 'A':
1607 t = parse_array_type(first, last, db);
1608 if (t == first || NAMT(db, n) == 0)
1609 return (first);
1610 save_top(db, 1);
1611 return (t);
1613 case 'C':
1614 t = parse_type(first + 1, last, db);
1615 if (t == first + 1 || NAMT(db, n) == 0)
1616 return (first);
1618 (void) str_append(TOP_L(db), " complex", 8);
1619 save_top(db, 1);
1620 return (t);
1622 case 'F':
1623 t = parse_function_type(first, last, db);
1624 if (t == first || NAMT(db, n) == 0)
1625 return (first);
1626 save_top(db, 1);
1627 return (t);
1629 case 'G':
1630 t = parse_type(first + 1, last, db);
1631 if (t == first + 1 || NAMT(db, n) == 0)
1632 return (first);
1634 (void) str_append(TOP_L(db), " imaginary", 10);
1635 save_top(db, 1);
1636 return (t);
1638 case 'M':
1639 t = parse_pointer_to_member_type(first, last, db);
1640 if (t == first || NAMT(db, n) == 0)
1641 return (first);
1642 save_top(db, 1);
1643 return (t);
1645 case 'O':
1646 t = parse_type(first + 1, last, db);
1647 amt = NAMT(db, n);
1648 if (t == first + 1 || amt == 0)
1649 return (first);
1651 sp = name_at(&db->cpp_name, amt - 1);
1652 for (size_t i = 0; i < amt; i++, sp++) {
1653 paren(sp);
1654 if (str_pair_len(sp) > 0)
1655 (void) str_append(&sp->strp_l, "&&", 2);
1658 save_top(db, amt);
1659 return (t);
1661 case 'P':
1662 t = parse_type(first + 1, last, db);
1663 amt = NAMT(db, n);
1664 if (t == first + 1 || amt == 0)
1665 return (first);
1667 sp = name_at(&db->cpp_name, amt - 1);
1668 for (size_t i = 0; i < amt; i++, sp++) {
1669 str_t *l = &sp->strp_l;
1671 if (str_pair_len(sp) == 0)
1672 continue;
1674 paren(sp);
1675 if (first[1] != 'U' ||
1676 strncmp(l->str_s, "objc_object<", 12) != 0) {
1677 (void) str_append(l, "*", 1);
1678 } else {
1679 (void) str_erase(l, 0, 11);
1680 (void) str_insert(l, 0, "id", 2);
1683 save_top(db, amt);
1684 return (t);
1686 case 'R':
1687 t = parse_type(first + 1, last, db);
1688 amt = NAMT(db, n);
1689 if (t == first + 1 || amt == 0)
1690 return (first);
1692 sp = name_at(&db->cpp_name, amt - 1);
1693 for (size_t i = 0; i < amt; i++, sp++) {
1694 if (str_length(&sp->strp_l) == 0 &&
1695 str_length(&sp->strp_r) == 0)
1696 continue;
1698 paren(sp);
1699 (void) str_append(&sp->strp_l, "&", 1);
1702 save_top(db, amt);
1703 return (t);
1705 case 'T':
1706 t = parse_template_param(first, last, db);
1707 if (t == first)
1708 return (first);
1710 amt = NAMT(db, n);
1711 save_top(db, amt);
1712 if (!db->cpp_try_to_parse_template_args || amt != 1)
1713 return (t);
1715 t1 = parse_template_args(t, last, db);
1716 if (t1 == t)
1717 return (t);
1719 nfmt(db, "{1:L}{0}", "{1:R}");
1720 save_top(db, 1);
1721 return (t1);
1723 case 'U':
1724 if (first + 1 == last)
1725 return (first);
1727 t = parse_source_name(first + 1, last, db);
1728 if (t == first + 1)
1729 return (first);
1731 nfmt(db, "{0}", NULL);
1733 t1 = parse_type(t, last, db);
1734 if (t1 == t || NAMT(db, n) < 2)
1735 return (first);
1737 const str_t *name = &name_at(&db->cpp_name, 1)->strp_l;
1739 if (str_length(name) > 0 &&
1740 strncmp(name->str_s, "objcproto", 9) != 0) {
1741 nfmt(db, "{0} {1}", NULL);
1742 } else {
1743 t = parse_source_name(name->str_s + 9,
1744 name->str_s + name->str_len, db);
1745 if (t != name->str_s + 9) {
1746 nfmt(db, "{1}<{0}>", NULL);
1748 str_pair_t save = {0};
1750 name_pop(&db->cpp_name, &save);
1752 /* get rid of 'objcproto' */
1753 name_pop(&db->cpp_name, NULL);
1754 CK(name_add_str(&db->cpp_name, &save.strp_l,
1755 &save.strp_r));
1756 } else {
1757 nfmt(db, "{1} {0}", NULL);
1761 save_top(db, 1);
1762 return (t1);
1764 case 'S':
1765 if (first + 1 != last && first[1] == 't') {
1766 t = parse_name(first, last, NULL, db);
1767 if (t == first || NAMT(db, n) == 0)
1768 return (first);
1770 save_top(db, 1);
1771 return (t);
1774 t = parse_substitution(first, last, db);
1775 if (t == first)
1776 return (first);
1779 * If the substitution is a <template-param>, it might
1780 * be followed by <template-args>
1782 t1 = parse_template_args(t, last, db);
1783 if (t1 == t)
1784 return (t);
1786 if (NAMT(db, n) < 2)
1787 return (t);
1789 nfmt(db, "{1:L}{0}", "{1:R}");
1790 save_top(db, 1);
1791 return (t1);
1793 case 'D':
1794 if (first + 1 == last)
1795 return (first);
1797 switch (first[1]) {
1798 case 'p':
1799 t = parse_type(first + 2, last, db);
1800 if (t == first + 2)
1801 break;
1803 save_top(db, NAMT(db, n));
1804 return (t);
1806 case 't':
1807 case 'T':
1808 t = parse_decltype(first, last, db);
1809 if (first == t)
1810 break;
1812 save_top(db, 1);
1813 return (t);
1815 case 'v':
1816 t = parse_vector_type(first, last, db);
1817 if (first == t)
1818 break;
1820 if (NAMT(db, n) == 0)
1821 return (first);
1823 save_top(db, 1);
1824 return (t);
1826 break;
1830 * must check for builtin-types before class-enum-types to avoid
1831 * ambiguities with operator-names
1833 t = parse_builtin_type(first, last, db);
1834 if (t != first)
1835 return (t);
1837 t = parse_name(first, last, NULL, db);
1838 if (t == first || NAMT(db, n) == 0)
1839 return (first);
1841 save_top(db, 1);
1842 return (t);
1845 static const char *
1846 parse_qual_type(const char *first, const char *last, cpp_db_t *db)
1848 VERIFY3P(first, <=, last);
1850 const char *t = NULL;
1851 const char *t1 = NULL;
1852 unsigned cv = 0;
1854 t = parse_cv_qualifiers(first, last, &cv);
1855 if (t == first)
1856 return (first);
1858 size_t n = nlen(db);
1859 boolean_t is_func = !!(t[0] == 'F');
1861 t1 = parse_type(t, last, db);
1862 size_t amt = NAMT(db, n);
1863 if (t == t1 || amt == 0)
1864 return (first);
1866 if (is_func)
1867 sub_pop(&db->cpp_subs);
1869 str_pair_t *sp = name_at(&db->cpp_name, amt - 1);
1871 for (size_t i = 0; i < amt; i++, sp++) {
1872 str_t *s = NULL;
1874 if (!is_func) {
1875 s = &sp->strp_l;
1877 if (str_length(s) == 0)
1878 continue;
1880 if (cv & 1)
1881 (void) str_append(s, " const", 6);
1882 if (cv & 2)
1883 (void) str_append(s, " volatile", 9);
1884 if (cv & 4)
1885 (void) str_append(s, " restrict", 9);
1887 continue;
1890 s = &sp->strp_r;
1891 size_t pos = str_length(s);
1893 if (pos > 0 && s->str_s[pos - 1] == '&') {
1894 pos--;
1895 if (s->str_s[pos - 1] == '&')
1896 pos--;
1899 if (cv & 1) {
1900 (void) str_insert(s, pos, " const", 6);
1901 pos += 6;
1903 if (cv & 2) {
1904 (void) str_insert(s, pos, " volatile", 9);
1905 pos += 9;
1907 if (cv & 4) {
1908 (void) str_insert(s, pos, " restrict", 9);
1912 save_top(db, amt);
1913 return (t1);
1917 * at <type> # alignof (a type)
1918 * az <expression> # alignof (a expression)
1920 static const char *
1921 parse_alignof(const char *first, const char *last, cpp_db_t *db)
1923 VERIFY3P(first, <=, last);
1925 if (last - first < 2)
1926 return (first);
1928 const char *(*fn)(const char *, const char *, cpp_db_t *);
1930 fn = (first[1] == 't') ? parse_type : parse_expression;
1932 size_t n = nlen(db);
1933 const char *t = fn(first + 2, last, db);
1934 if (t == first + 2 || NAMT(db, n) != 1)
1935 return (first);
1937 nfmt(db, "alignof ({0})", NULL);
1938 return (t);
1942 * st <type> # sizeof (a type)
1943 * sz <expr> # sizeof (a expression)
1945 static const char *
1946 parse_sizeof(const char *first, const char *last, cpp_db_t *db)
1948 VERIFY3P(first, <=, last);
1950 if (last - first < 2)
1951 return (first);
1953 VERIFY3U(first[0], ==, 's');
1955 const char *t = NULL;
1956 size_t n = nlen(db);
1958 switch (first[1]) {
1959 case 't':
1960 t = parse_type(first + 2, last, db);
1961 break;
1962 case 'z':
1963 t = parse_expression(first + 2, last, db);
1964 break;
1965 default:
1966 return (first);
1968 if (t == first + 2 || NAMT(db, n) != 1)
1969 return (first);
1971 nfmt(db, "sizeof ({0})", NULL);
1972 return (t);
1975 /* BEGIN CSTYLED */
1977 * <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
1978 * ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
1979 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter
1980 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
1982 /* END CSTYLED */
1983 static const char *
1984 parse_function_param(const char *first, const char *last, cpp_db_t *db)
1986 VERIFY3P(first, <=, last);
1988 if (last - first < 3 || first[0] != 'f')
1989 return (first);
1991 const char *t1 = first + 2;
1992 const char *t2 = NULL;
1993 unsigned cv = 0;
1995 if (first[1] == 'L') {
1996 t2 = parse_number(t1, last, db->cpp_loc);
1997 if (t2 == last || t2[0] != 'p')
1998 return (first);
1999 t1 = t2;
2002 if (first[1] != 'p')
2003 return (first);
2005 t1 = parse_cv_qualifiers(t1, last, &cv);
2006 t2 = parse_number(t1, last, db->cpp_loc);
2007 if (t2 == last || t2[0] != '_')
2008 return (first);
2010 if (t2 - t1 > 0)
2011 nadd_l(db, t1, (size_t)(t2 - t1));
2012 else
2013 nadd_l(db, "", 0);
2015 nfmt(db, "fp{0}", NULL);
2016 return (t2 + 1);
2020 * sZ <template-param> # size of a parameter pack
2021 * sZ <function-param> # size of a function parameter pack
2023 static const char *
2024 parse_sizeof_param_pack_expr(const char *first, const char *last, cpp_db_t *db)
2026 VERIFY3P(first, <=, last);
2028 if (last - first < 3)
2029 return (first);
2031 VERIFY3U(first[0], ==, 's');
2032 VERIFY3U(first[1], ==, 'Z');
2034 if (first[2] != 'T' && first[2] != 'f')
2035 return (first);
2037 const char *t = NULL;
2038 size_t n = nlen(db);
2040 if (first[2] == 'T')
2041 t = parse_template_param(first + 2, last, db);
2042 else
2043 t = parse_function_param(first + 2, last, db);
2045 if (t == first + 2)
2046 return (first);
2048 njoin(db, NAMT(db, n), ", ");
2049 nfmt(db, "sizeof...({0})", NULL);
2050 return (t);
2054 * te <expression> # typeid (expression)
2055 * ti <type> # typeid (type)
2057 static const char *
2058 parse_typeid_expr(const char *first, const char *last, cpp_db_t *db)
2060 VERIFY3P(first, <=, last);
2062 if (last - first < 3)
2063 return (first);
2065 VERIFY3U(first[0], ==, 't');
2066 VERIFY(first[1] == 'e' || first[1] == 'i');
2068 const char *t = NULL;
2069 size_t n = nlen(db);
2071 if (first[1] == 'e')
2072 t = parse_expression(first + 2, last, db);
2073 else
2074 t = parse_type(first + 2, last, db);
2076 if (t == first + 2 || NAMT(db, n) != 1)
2077 return (first);
2079 nfmt(db, "typeid ({0})", NULL);
2080 return (t);
2084 * tr # throw
2085 * tw <expression> # throw expression
2087 static const char *
2088 parse_throw_expr(const char *first, const char *last, cpp_db_t *db)
2090 VERIFY3P(first, <=, last);
2092 if (last - first < 3)
2093 return (first);
2095 VERIFY3U(first[0], ==, 't');
2096 VERIFY(first[1] == 'w' || first[1] == 'r');
2098 if (first[1] == 'r') {
2099 nadd_l(db, "throw", 0);
2100 return (first + 2);
2103 size_t n = nlen(db);
2104 const char *t = parse_expression(first + 2, last, db);
2105 if (t == first + 2 || NAMT(db, n) != 1)
2106 return (first);
2108 nfmt(db, "throw {0}", NULL);
2109 return (t);
2112 /* ds <expression> <expression> # expr.*expr */
2113 static const char *
2114 parse_dot_star_expr(const char *first, const char *last, cpp_db_t *db)
2116 VERIFY3P(first, <=, last);
2118 if (last - first < 3)
2119 return (first);
2121 VERIFY3U(first[0], ==, 'd');
2122 VERIFY3U(first[1], ==, 's');
2124 size_t n = nlen(db);
2125 const char *t = parse_expression(first + 2, last, db);
2126 if (t == first + 2)
2127 return (first);
2129 const char *t2 = parse_expression(t, last, db);
2130 if (t == t2 || NAMT(db, n) != 2)
2131 return (first);
2133 nfmt(db, "{1}.*{0}", NULL);
2134 return (t2);
2137 /* dt <expression> <unresolved-name> # expr.name */
2138 static const char *
2139 parse_dot_expr(const char *first, const char *last, cpp_db_t *db)
2141 VERIFY3P(first, <=, last);
2143 if (last - first < 3)
2144 return (first);
2146 VERIFY3U(first[0], ==, 'd');
2147 VERIFY3U(first[1], ==, 't');
2149 const char *t = parse_expression(first + 2, last, db);
2150 if (t == first + 2)
2151 return (first);
2153 const char *t1 = parse_unresolved_name(t, last, db);
2154 if (t1 == t)
2155 return (first);
2157 nfmt(db, "{1}.{0}", NULL);
2158 return (t1);
2161 /* cl <expression>+ E # call */
2162 static const char *
2163 parse_call_expr(const char *first, const char *last, cpp_db_t *db)
2165 VERIFY3P(first, <=, last);
2167 if (last - first < 4)
2168 return (first);
2170 VERIFY3U(first[0], ==, 'c');
2171 VERIFY3U(first[1], ==, 'l');
2173 const char *t = first + 2;
2174 const char *t1 = NULL;
2175 size_t n = nlen(db);
2177 for (t = first + 2; t != last && t[0] != 'E'; t = t1) {
2178 t1 = parse_expression(t, last, db);
2179 if (t1 == t)
2180 return (first);
2183 size_t amt = NAMT(db, n);
2185 if (t == last || amt == 0)
2186 return (first);
2188 njoin(db, amt - 1, ", ");
2189 nfmt(db, "{1}({0})", NULL);
2191 VERIFY3U(t[0], ==, 'E');
2192 return (t + 1);
2195 /* BEGIN CSTYLED */
2197 * cv <type> <expression> # conversion with one argument
2198 * cv <type> _ <expression>* E # conversion with a different number of arguments
2200 /* END CSTYLED */
2201 static const char *
2202 parse_conv_expr(const char *first, const char *last, cpp_db_t *db)
2204 VERIFY3P(first, <=, last);
2206 if (last - first < 3)
2207 return (first);
2209 VERIFY3U(first[0], ==, 'c');
2210 VERIFY3U(first[1], ==, 'v');
2212 const char *t = NULL;
2213 const char *t1 = NULL;
2214 size_t n = nlen(db);
2216 boolean_t try_to_parse_template_args =
2217 db->cpp_try_to_parse_template_args;
2219 db->cpp_try_to_parse_template_args = B_FALSE;
2220 t = parse_type(first + 2, last, db);
2221 db->cpp_try_to_parse_template_args = try_to_parse_template_args;
2223 if (t == first + 2)
2224 return (first);
2226 if (t[0] != '_') {
2227 t1 = parse_expression(t, last, db);
2228 if (t1 == t)
2229 return (first);
2231 t = t1;
2232 } else {
2233 size_t n1 = nlen(db);
2235 /* skip _ */
2236 t++;
2237 while (t[0] != 'E' && t != last) {
2238 t1 = parse_expression(t, last, db);
2239 if (t1 == t)
2240 return (first);
2241 t1 = t;
2244 /* E */
2245 t++;
2247 njoin(db, NAMT(db, n1), ", ");
2250 if (NAMT(db, n) < 2)
2251 return (first);
2253 nfmt(db, "({1})({0})", NULL);
2254 return (t);
2257 /* <simple-id> ::= <source-name> [ <template-args> ] */
2258 static const char *
2259 parse_simple_id(const char *first, const char *last, cpp_db_t *db)
2261 VERIFY3P(first, <=, last);
2263 const char *t = parse_source_name(first, last, db);
2264 if (t == first)
2265 return (t);
2267 const char *t1 = parse_template_args(t, last, db);
2268 if (t == t1)
2269 return (t);
2271 nfmt(db, "{1}{0}", NULL);
2272 return (t1);
2276 * <unresolved-type> ::= <template-param>
2277 * ::= <decltype>
2278 * ::= <substitution>
2280 static const char *
2281 parse_unresolved_type(const char *first, const char *last, cpp_db_t *db)
2283 VERIFY3P(first, <=, last);
2285 if (first == last)
2286 return (first);
2288 const char *t = first;
2289 size_t n = nlen(db);
2291 switch (first[0]) {
2292 case 'T':
2293 t = parse_template_param(first, last, db);
2294 if (t == first || NAMT(db, n) != 1) {
2295 for (size_t i = 0; i < NAMT(db, n); i++)
2296 name_pop(&db->cpp_name, NULL);
2297 return (first);
2299 save_top(db, 1);
2300 return (t);
2302 case 'D':
2303 t = parse_decltype(first, last, db);
2304 if (t == first || NAMT(db, n) == 0)
2305 return (first);
2306 save_top(db, 1);
2307 return (t);
2309 case 'S':
2310 t = parse_substitution(first, last, db);
2311 if (t != first)
2312 return (t);
2314 if (last - first < 2 || first[1] != 't')
2315 return (first);
2317 t = parse_unqualified_name(first + 2, last, db);
2318 if (t == first + 2 || NAMT(db, n) == 0)
2319 return (first);
2321 nfmt(db, "std::{0:L}", "{0:R}");
2322 save_top(db, 1);
2323 return (t);
2326 return (first);
2329 /* sp <expression> # pack expansion */
2330 static const char *
2331 parse_pack_expansion(const char *first, const char *last, cpp_db_t *db)
2333 VERIFY3P(first, <=, last);
2335 if (last - first < 3)
2336 return (first);
2338 VERIFY3U(first[0], ==, 's');
2339 VERIFY3U(first[1], ==, 'p');
2341 const char *t = parse_expression(first + 2, last, db);
2342 if (t == first +2)
2343 return (first);
2345 return (t);
2349 * <unscoped-name> ::= <unqualified-name>
2350 * ::= St <unqualified-name> # ::std::
2351 * extension ::= StL<unqualified-name>
2353 static const char *
2354 parse_unscoped_name(const char *first, const char *last, cpp_db_t *db)
2356 VERIFY3P(first, <=, last);
2358 if (last - first < 2)
2359 return (first);
2361 const char *t = first;
2362 const char *t1 = NULL;
2363 boolean_t st = B_FALSE;
2365 if (first[0] == 'S' && first[1] == 't') {
2366 st = B_TRUE;
2367 t = first + 2;
2369 if (first + 3 != last && first[2] == 'L')
2370 t++;
2373 t1 = parse_unqualified_name(t, last, db);
2374 if (t == t1)
2375 return (first);
2377 if (st)
2378 nfmt(db, "std::{0}", NULL);
2380 return (t1);
2384 * <unqualified-name> ::= <operator-name>
2385 * ::= <ctor-dtor-name>
2386 * ::= <source-name>
2387 * ::= <unnamed-type-name>
2389 const char *
2390 parse_unqualified_name(const char *first, const char *last, cpp_db_t *db)
2392 VERIFY3P(first, <=, last);
2394 if (first == last)
2395 return (first);
2397 switch (*first) {
2398 case 'C':
2399 case 'D':
2400 return (parse_ctor_dtor_name(first, last, db));
2401 case 'U':
2402 return (parse_unnamed_type_name(first, last, db));
2404 case '1':
2405 case '2':
2406 case '3':
2407 case '4':
2408 case '5':
2409 case '6':
2410 case '7':
2411 case '8':
2412 case '9':
2413 return (parse_source_name(first, last, db));
2414 default:
2415 return (parse_operator_name(first, last, db));
2420 * <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
2421 * ::= <closure-type-name>
2423 * <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2425 * <lambda-sig> ::= <parameter type>+
2426 * # Parameter types or "v" if the lambda has no parameters
2428 static const char *
2429 parse_unnamed_type_name(const char *first, const char *last, cpp_db_t *db)
2431 VERIFY3P(first, <=, last);
2433 if (last - first < 2 || first[0] != 'U')
2434 return (first);
2436 if (first[1] != 't' && first[1] != 'l')
2437 return (first);
2439 const char *t1 = first + 2;
2440 const char *t2 = NULL;
2442 if (first[1] == 't') {
2443 while (t1 != last && t1[0] != '_' &&
2444 isdigit_l(t1[0], db->cpp_loc))
2445 t1++;
2447 if (t1[0] != '_')
2448 return (first);
2450 if (t1 == first + 2)
2451 nadd_l(db, "", 0);
2452 else
2453 nadd_l(db, first + 2, (size_t)(t1 - first - 2));
2455 nfmt(db, "'unnamed{0}'", NULL);
2456 return (t1 + 1);
2459 size_t n = nlen(db);
2461 if (first[2] != 'v') {
2462 do {
2463 t2 = parse_type(t1, last, db);
2464 if (t1 == t2)
2465 return (first);
2466 t1 = t2;
2467 } while (t1 != last && t1[0] != 'E');
2469 if (t1 == last || NAMT(db, n) < 1)
2470 return (first);
2472 if (NAMT(db, n) < 1)
2473 return (first);
2474 } else {
2475 t1++;
2476 if (t1[0] != 'E')
2477 return (first);
2480 njoin(db, NAMT(db, n), ", ");
2482 /* E */
2483 t1++;
2485 t2 = t1;
2486 while (t2 != last && t2[0] != '_') {
2487 if (!isdigit_l(*t2++, db->cpp_loc))
2488 return (first);
2491 if (t2[0] != '_')
2492 return (first);
2494 if (t2 - t1 > 0)
2495 nadd_l(db, t1, (size_t)(t2 - t1));
2496 else
2497 nadd_l(db, "", 0);
2499 nfmt(db, "'lambda{0}'({1})", NULL);
2501 /* _ */
2502 return (t2 + 1);
2505 static struct {
2506 const char *alias;
2507 const char *fullname;
2508 const char *basename;
2509 } aliases[] = {
2511 "std::string",
2512 "std::basic_string<char, std::char_traits<char>, "
2513 "std::allocator<char> >",
2514 "basic_string"
2517 "std::istream",
2518 "std::basic_istream<char, std::char_traits<char> >",
2519 "basic_istream"
2522 "std::ostream",
2523 "std::basic_ostream<char, std::char_traits<char> >",
2524 "basic_ostream"
2527 "std::iostream",
2528 "std::basic_iostream<char, std::char_traits<char> >",
2529 "basic_iostream"
2533 static void
2534 basename(cpp_db_t *db)
2536 str_t *s = TOP_L(db);
2538 for (size_t i = 0; i < ARRAY_SIZE(aliases); i++) {
2539 if (str_length(s) != strlen(aliases[i].alias))
2540 continue;
2541 if (strncmp(aliases[i].alias, s->str_s, str_length(s)) != 0)
2542 continue;
2544 /* swap out alias for full name */
2545 sysdem_ops_t *ops = s->str_ops;
2546 str_fini(s);
2547 str_init(s, ops);
2548 str_set(s, aliases[i].fullname, 0);
2550 nadd_l(db, aliases[i].basename, 0);
2551 return;
2554 const char *start = s->str_s;
2555 const char *end = s->str_s + s->str_len;
2558 * if name ends with a template i.e. <.....> back up to start
2559 * of outermost template
2561 unsigned c = 0;
2563 if (end[-1] == '>') {
2564 for (; end > start; end--) {
2565 switch (end[-1]) {
2566 case '<':
2567 if (--c == 0) {
2568 end--;
2569 goto out;
2571 break;
2572 case '>':
2573 c++;
2574 break;
2579 out:
2580 VERIFY3P(end, >=, start);
2582 if (end - start < 2) {
2583 nadd_l(db, "", 0);
2584 return;
2587 for (start = end - 1; start > s->str_s; start--) {
2588 if (start[0] == ':') {
2589 start++;
2590 break;
2594 VERIFY3P(end, >=, start);
2596 nadd_l(db, start, (size_t)(end - start));
2600 * <ctor-dtor-name> ::= C1 # complete object constructor
2601 * ::= C2 # base object constructor
2602 * ::= C3 # complete object allocating constructor
2603 * extension ::= C5 # ?
2604 * ::= D0 # deleting destructor
2605 * ::= D1 # complete object destructor
2606 * ::= D2 # base object destructor
2607 * extension ::= D5 # ?
2609 static const char *
2610 parse_ctor_dtor_name(const char *first, const char *last, cpp_db_t *db)
2612 VERIFY3P(first, <=, last);
2614 if (last - first < 2 || nempty(db) || str_length(TOP_L(db)) == 0)
2615 return (first);
2617 switch (first[0]) {
2618 case 'C':
2619 switch (first[1]) {
2620 case '1':
2621 case '2':
2622 case '3':
2623 case '5':
2624 basename(db);
2625 break;
2626 default:
2627 return (first);
2629 break;
2630 case 'D':
2631 switch (first[1]) {
2632 case '0':
2633 case '1':
2634 case '2':
2635 case '5':
2636 basename(db);
2637 (void) str_insert(TOP_L(db), 0, "~", 1);
2638 break;
2639 default:
2640 return (first);
2642 break;
2643 default:
2644 return (first);
2647 db->cpp_parsed_ctor_dtor_cv = B_TRUE;
2648 return (first + 2);
2651 static const char *
2652 parse_integer_literal(const char *first, const char *last, const char *fmt,
2653 cpp_db_t *db)
2655 VERIFY3P(first, <=, last);
2657 const char *t = parse_number(first, last, db->cpp_loc);
2658 const char *start = first;
2660 if (t == first || t == last || t[0] != 'E')
2661 return (first);
2663 if (first[0] == 'n')
2664 start++;
2666 nadd_l(db, start, (size_t)(t - start));
2667 if (start != first)
2668 nfmt(db, "-{0}", NULL);
2670 nfmt(db, fmt, NULL);
2671 return (t + 1);
2674 static struct float_data_s {
2675 const char *spec;
2676 size_t mangled_size;
2677 size_t max_demangled_size;
2678 char type;
2679 } float_info[] = {
2680 { "%af", 8, 24, 'f' }, /* float */
2681 { "%a", 16, 32, 'd' }, /* double */
2682 { "%LaL", 20, 40, 'e' } /* long double */
2685 static const char *
2686 parse_floating_literal(const char *first, const char *last, cpp_db_t *db)
2688 VERIFY3P(first, <=, last);
2689 VERIFY(first[0] == 'f' || first[0] == 'd' || first[0] == 'e');
2691 const struct float_data_s *fd = NULL;
2693 for (size_t i = 0; i < ARRAY_SIZE(float_info); i++) {
2694 if (float_info[i].type != first[0])
2695 continue;
2697 fd = &float_info[i];
2698 break;
2701 if (fd == NULL || (size_t)(last - first) < fd->mangled_size)
2702 return (first);
2704 union {
2705 union {
2706 float v;
2707 char buf[sizeof (float)];
2708 } f;
2709 union {
2710 double v;
2711 char buf[sizeof (double)];
2712 } d;
2713 union {
2714 long double v;
2715 char buf[sizeof (long double)];
2716 } ld;
2717 } conv;
2719 const char *t = NULL;
2720 char *e = NULL;
2722 switch (first[0]) {
2723 case 'f':
2724 e = conv.f.buf;
2725 break;
2726 case 'd':
2727 e = conv.d.buf;
2728 break;
2729 case 'e':
2730 e = conv.ld.buf;
2731 break;
2733 last = first + fd->mangled_size + 1;
2735 #if defined(_BIG_ENDIAN)
2736 for (t = first + 1; t != last; t++, e++) {
2737 if (!is_xdigit(t[0]))
2738 return (first);
2740 unsigned d1 = isdigit_l(t[0], db->cpp_loc) ?
2741 t[0] - '0' : t[0] - 'a' + 10;
2742 t++;
2743 unsigned d0 = isdigit_l(t[0], db->cpp_loc) ?
2744 t[0] - '0' : t[0] - 'a' + 10;
2746 *e = (d1 << 4) + d0;
2748 #elif defined(_LITTLE_ENDIAN)
2749 for (t = last - 1; t > first; t--, e++) {
2750 if (!is_xdigit(t[0]))
2751 return (first);
2753 unsigned d0 = isdigit_l(t[0], db->cpp_loc) ?
2754 t[0] - '0' : t[0] - 'a' + 10;
2755 t--;
2756 unsigned d1 = isdigit_l(t[0], db->cpp_loc) ?
2757 t[0] - '0' : t[0] - 'a' + 10;
2759 *e = (d1 << 4) + d0;
2761 t = last;
2762 #else
2763 #error One of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined
2764 #endif
2766 if (t[0] != 'E')
2767 return (first);
2769 str_t num = { 0 };
2770 str_init(&num, db->cpp_ops);
2772 num.str_size = fd->max_demangled_size + 1;
2773 num.str_s = zalloc(db->cpp_ops, num.str_size);
2774 CK(num.str_s != NULL);
2776 int n = 0;
2778 switch (first[0]) {
2779 case 'f':
2780 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2781 conv.f.v);
2782 break;
2783 case 'd':
2784 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2785 conv.d.v);
2786 break;
2787 case 'e':
2788 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2789 conv.ld.v);
2792 if (n >= fd->max_demangled_size || n <= 0) {
2793 str_fini(&num);
2794 return (first);
2797 num.str_len = n;
2798 (void) name_add_str(&db->cpp_name, &num, NULL);
2800 return (t + 1);
2804 * <expr-primary> ::= L <type> <value number> E # integer literal
2805 * ::= L <type> <value float> E # floating literal
2806 * ::= L <string type> E # string literal
2807 * ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
2809 * ::= L <type> <real-part float> _ <imag-part float> E
2810 * # complex floating point
2811 * # literal (C 2000)
2813 * ::= L <mangled-name> E # external name
2815 static struct {
2816 int c;
2817 const char *fmt;
2818 } int_lits[] = {
2819 { 'a', "(signed char){0}" },
2820 { 'c', "(char){0}" },
2821 { 'h', "(unsigned char){0}" },
2822 { 'i', "{0}" },
2823 { 'j', "{0}u" },
2824 { 'l', "{0}l" },
2825 { 'm', "{0}ul" },
2826 { 'n', "(__int128){0}" },
2827 { 'o', "(unsigned __int128){0}" },
2828 { 's', "(short){0}" },
2829 { 't', "(unsigned short){0}" },
2830 { 'w', "(wchar_t){0}" },
2831 { 'x', "{0}ll" },
2832 { 'y', "{0}ull" }
2835 static const char *
2836 parse_expr_primary(const char *first, const char *last, cpp_db_t *db)
2838 VERIFY3P(first, <=, last);
2840 if (last - first < 4 || first[0] != 'L')
2841 return (first);
2843 const char *t = NULL;
2845 for (size_t i = 0; i < ARRAY_SIZE(int_lits); i++) {
2846 if (first[1] == int_lits[i].c) {
2847 t = parse_integer_literal(first + 2, last,
2848 int_lits[i].fmt, db);
2849 return ((t == first + 2) ? first : t);
2853 switch (first[1]) {
2854 case 'b':
2855 if (first[3] != 'E')
2856 return (first);
2858 switch (first[2]) {
2859 case '0':
2860 nadd_l(db, "false", 5);
2861 break;
2862 case '1':
2863 nadd_l(db, "true", 4);
2864 break;
2865 default:
2866 return (first);
2868 return (first + 4);
2869 case 'd': /* double */
2870 case 'e': /* long double */
2871 case 'f': /* float */
2872 t = parse_floating_literal(first + 1, last, db);
2873 return ((t == first + 1) ? first : t);
2874 case 'T':
2875 /* BEGIN CSTYLED */
2877 * Invalid mangled name per
2878 * http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
2881 /* END CSTYLED */
2882 return (first);
2883 case '_':
2884 if (first[2] != 'Z')
2885 return (first);
2887 t = parse_encoding(first + 3, last, db);
2888 if (t == first + 3 || t == last || t[0] != 'E')
2889 return (first);
2891 /* skip E */
2892 return (t + 1);
2893 default:
2894 t = parse_type(first + 1, last, db);
2895 if (t == first + 1 || t == last)
2896 return (first);
2898 if (t[0] == 'E')
2899 return (t + 1);
2901 const char *n;
2902 for (n = t; n != last && isdigit_l(n[0], db->cpp_loc); n++)
2904 if (n == last || nempty(db) || n[0] != 'E')
2905 return (first);
2906 if (n == t)
2907 return (t);
2909 nadd_l(db, t, (size_t)(n - t));
2910 nfmt(db, "({1}){0}", NULL);
2912 return (n + 1);
2917 * <operator-name>
2918 * ::= aa # &&
2919 * ::= ad # & (unary)
2920 * ::= an # &
2921 * ::= aN # &=
2922 * ::= aS # =
2923 * ::= cl # ()
2924 * ::= cm # ,
2925 * ::= co # ~
2926 * ::= cv <type> # (cast)
2927 * ::= da # delete[]
2928 * ::= de # * (unary)
2929 * ::= dl # delete
2930 * ::= dv # /
2931 * ::= dV # /=
2932 * ::= eo # ^
2933 * ::= eO # ^=
2934 * ::= eq # ==
2935 * ::= ge # >=
2936 * ::= gt # >
2937 * ::= ix # []
2938 * ::= le # <=
2939 * ::= li <source-name> # operator ""
2940 * ::= ls # <<
2941 * ::= lS # <<=
2942 * ::= lt # <
2943 * ::= mi # -
2944 * ::= mI # -=
2945 * ::= ml # *
2946 * ::= mL # *=
2947 * ::= mm # -- (postfix in <expression> context)
2948 * ::= na # new[]
2949 * ::= ne # !=
2950 * ::= ng # - (unary)
2951 * ::= nt # !
2952 * ::= nw # new
2953 * ::= oo # ||
2954 * ::= or # |
2955 * ::= oR # |=
2956 * ::= pm # ->*
2957 * ::= pl # +
2958 * ::= pL # +=
2959 * ::= pp # ++ (postfix in <expression> context)
2960 * ::= ps # + (unary)
2961 * ::= pt # ->
2962 * ::= qu # ?
2963 * ::= rm # %
2964 * ::= rM # %=
2965 * ::= rs # >>
2966 * ::= rS # >>=
2967 * ::= v <digit> <source-name> # vendor extended operator
2969 static struct {
2970 const char code[3];
2971 const char *op;
2972 } op_tbl[] = {
2973 { "aa", "operator&&" },
2974 { "ad", "operator&" },
2975 { "an", "operator&" },
2976 { "aN", "operator&=" },
2977 { "aS", "operator=" },
2978 { "cl", "operator()" },
2979 { "cm", "operator," },
2980 { "co", "operator~" },
2981 { "da", "operator delete[]" },
2982 { "de", "operator*" },
2983 { "dl", "operator delete" },
2984 { "dv", "operator/" },
2985 { "dV", "operator/=" },
2986 { "eo", "operator^" },
2987 { "eO", "operator^=" },
2988 { "eq", "operator==" },
2989 { "ge", "operator>=" },
2990 { "gt", "operator>" },
2991 { "ix", "operator[]" },
2992 { "le", "operator<=" },
2993 { "ls", "operator<<" },
2994 { "lS", "operator<<=" },
2995 { "lt", "operator<" },
2996 { "mi", "operator-" },
2997 { "mI", "operator-=" },
2998 { "ml", "operator*" },
2999 { "mL", "operator*=" },
3000 { "mm", "operator--" },
3001 { "na", "operator new[]" },
3002 { "ne", "operator!=" },
3003 { "ng", "operator-" },
3004 { "nt", "operator!" },
3005 { "nw", "operator new" },
3006 { "oo", "operator||" },
3007 { "or", "operator|" },
3008 { "oR", "operator|=" },
3009 { "pm", "operator->*" },
3010 { "pl", "operator+" },
3011 { "pL", "operator+=" },
3012 { "pp", "operator++" },
3013 { "ps", "operator+" },
3014 { "pt", "operator->" },
3015 { "qu", "operator?" },
3016 { "rm", "operator%" },
3017 { "rM", "operator%=" },
3018 { "rs", "operator>>" },
3019 { "rS", "operator>>=" }
3022 static const char *
3023 parse_operator_name(const char *first, const char *last, cpp_db_t *db)
3025 VERIFY3P(first, <=, last);
3027 if (last - first < 2)
3028 return (first);
3030 for (size_t i = 0; i < ARRAY_SIZE(op_tbl); i++) {
3031 if (strncmp(first, op_tbl[i].code, 2) != 0)
3032 continue;
3034 nadd_l(db, op_tbl[i].op, 0);
3035 return (first + 2);
3038 const char *t = NULL;
3040 if (first[0] == 'l' && first[1] == 'i') {
3041 t = parse_source_name(first + 2, last, db);
3042 if (t == first + 2 || nempty(db))
3043 return (first);
3045 nfmt(db, "operator\"\" {0}", NULL);
3046 return (t);
3049 if (first[0] == 'v') {
3050 if (!isdigit_l(first[1], db->cpp_loc))
3051 return (first);
3053 t = parse_source_name(first + 2, last, db);
3054 if (t == first + 2)
3055 return (first);
3057 nfmt(db, "operator {0}", NULL);
3058 return (t);
3061 if (first[0] != 'c' && first[1] != 'v')
3062 return (first);
3064 boolean_t try_to_parse_template_args =
3065 db->cpp_try_to_parse_template_args;
3067 db->cpp_try_to_parse_template_args = B_FALSE;
3068 t = parse_type(first + 2, last, db);
3069 db->cpp_try_to_parse_template_args = try_to_parse_template_args;
3071 if (t == first + 2 || nempty(db))
3072 return (first);
3074 nfmt(db, "operator {0}", NULL);
3075 db->cpp_parsed_ctor_dtor_cv = B_TRUE;
3076 return (t);
3079 struct type_tbl_s {
3080 int code;
3081 const char *name;
3084 static struct type_tbl_s type_tbl1[] = {
3085 { 'a', "signed char" },
3086 { 'b', "bool" },
3087 { 'c', "char" },
3088 { 'd', "double" },
3089 { 'e', "long double" },
3090 { 'f', "float" },
3091 { 'g', "__float128" },
3092 { 'h', "unsigned char" },
3093 { 'i', "int" },
3094 { 'j', "unsigned int" },
3095 { 'l', "long" },
3096 { 'm', "unsigned long" },
3097 { 'n', "__int128" },
3098 { 'o', "unsigned __int128" },
3099 { 's', "short" },
3100 { 't', "unsigned short" },
3101 { 'v', "void" },
3102 { 'w', "wchar_t" },
3103 { 'x', "long long" },
3104 { 'y', "unsigned long long" },
3105 { 'z', "..." }
3108 static struct type_tbl_s type_tbl2[] = {
3109 { 'a', "auto" },
3110 { 'c', "decltype(auto)" },
3111 { 'd', "decimal64" },
3112 { 'e', "decimal128" },
3113 { 'f', "decimal32" },
3114 { 'h', "decimal16" },
3115 { 'i', "char32_t" },
3116 { 'n', "std::nullptr_t" },
3117 { 's', "char16_t" }
3120 static const char *
3121 parse_builtin_type(const char *first, const char *last, cpp_db_t *db)
3123 VERIFY3P(first, <=, last);
3125 if (first == last)
3126 return (first);
3128 size_t i;
3130 for (i = 0; i < ARRAY_SIZE(type_tbl1); i++) {
3131 if (first[0] == type_tbl1[i].code) {
3132 nadd_l(db, type_tbl1[i].name, 0);
3133 return (first + 1);
3137 if (first[0] == 'D') {
3138 if (first + 1 == last)
3139 return (first);
3140 for (i = 0; i < ARRAY_SIZE(type_tbl2); i++) {
3141 if (first[1] == type_tbl2[i].code) {
3142 nadd_l(db, type_tbl2[i].name, 0);
3143 return (first + 2);
3148 if (first[0] == 'u') {
3149 const char *t = parse_source_name(first + 1, last, db);
3150 if (t == first + 1)
3151 return (first);
3152 return (t);
3155 return (first);
3158 static const char *
3159 parse_base36(const char *first, const char *last, size_t *val, locale_t loc)
3161 VERIFY3P(first, <=, last);
3163 const char *t;
3165 for (t = first, *val = 0; t != last; t++) {
3166 if (!isdigit_l(t[0], loc) && !isupper_l(t[0], loc))
3167 return (t);
3169 *val *= 36;
3171 if (isdigit_l(t[0], loc))
3172 *val += t[0] - '0';
3173 else
3174 *val += t[0] - 'A' + 10;
3176 return (t);
3179 static struct type_tbl_s sub_tbl[] = {
3180 { 'a', "std::allocator" },
3181 { 'b', "std::basic_string" },
3182 { 's', "std::string" },
3183 { 'i', "std::istream" },
3184 { 'o', "std::ostream" },
3185 { 'd', "std::iostream" }
3188 static const char *
3189 parse_substitution(const char *first, const char *last, cpp_db_t *db)
3191 VERIFY3P(first, <=, last);
3193 if (first == last || last - first < 2)
3194 return (first);
3196 if (first[0] != 'S')
3197 return (first);
3199 for (size_t i = 0; i < ARRAY_SIZE(sub_tbl); i++) {
3200 if (first[1] == sub_tbl[i].code) {
3201 nadd_l(db, sub_tbl[i].name, 0);
3202 return (first + 2);
3206 const char *t = first + 1;
3207 size_t n = 0;
3209 if (t[0] != '_') {
3210 t = parse_base36(first + 1, last, &n, db->cpp_loc);
3211 if (t == first + 1 || t[0] != '_')
3212 return (first);
3215 * S_ == substitution 0,
3216 * S0_ == substituion 1,
3217 * ...
3219 n++;
3222 if (n >= sub_len(&db->cpp_subs))
3223 return (first);
3225 sub(db, n);
3227 /* skip _ */
3228 VERIFY3U(t[0], ==, '_');
3230 return (t + 1);
3233 static const char *
3234 parse_source_name(const char *first, const char *last, cpp_db_t *db)
3236 VERIFY3P(first, <=, last);
3238 if (first == last)
3239 return (first);
3241 const char *t = NULL;
3242 size_t n = 0;
3244 for (t = first; t != last && isdigit_l(t[0], db->cpp_loc); t++) {
3245 /* make sure we don't overflow */
3246 size_t nn = n * 10;
3247 if (nn < n)
3248 return (first);
3250 nn += t[0] - '0';
3251 if (nn < n)
3252 return (first);
3254 n = nn;
3257 if (n == 0 || t == last || t + n > last ||
3258 (uintptr_t)t + n < (uintptr_t)t)
3259 return (first);
3261 if (strncmp(t, "_GLOBAL__N", 10) == 0)
3262 nadd_l(db, "(anonymous namespace)", 0);
3263 else
3264 nadd_l(db, t, n);
3266 return (t + n);
3270 * extension:
3271 * <vector-type> ::= Dv <positive dimension number> _
3272 * <extended element type>
3273 * ::= Dv [<dimension expression>] _ <element type>
3274 * <extended element type> ::= <element type>
3275 * ::= p # AltiVec vector pixel
3277 static const char *
3278 parse_vector_type(const char *first, const char *last, cpp_db_t *db)
3280 VERIFY3P(first, <=, last);
3282 if (last - first < 3)
3283 return (first);
3285 VERIFY3U(first[0], ==, 'D');
3286 VERIFY3U(first[1], ==, 'v');
3288 const char *t = first + 2;
3289 const char *t1 = NULL;
3291 if (isdigit_l(first[2], db->cpp_loc) && first[2] != '0') {
3292 t1 = parse_number(t, last, db->cpp_loc);
3293 if (t1 == last || t1 + 1 == last || t1[0] != '_')
3294 return (first);
3296 nadd_l(db, t, (size_t)(t1 - t));
3298 /* skip _ */
3299 t = t1 + 1;
3301 if (t[0] != 'p') {
3302 t1 = parse_type(t, last, db);
3303 if (t1 == t)
3304 return (first);
3306 nfmt(db, "{0} vector[{1}]", NULL);
3307 return (t1);
3309 nfmt(db, "{0} pixel vector[{1}]", NULL);
3310 return (t1);
3313 if (first[2] != '_') {
3314 t1 = parse_expression(first + 2, last, db);
3315 if (first == last || t1 == first + 2 || t1[0] != '_')
3316 return (first);
3318 /* skip _ */
3319 t = t1 + 1;
3320 } else {
3321 nadd_l(db, "", 0);
3324 t1 = parse_type(t, last, db);
3325 if (t == t1)
3326 return (first);
3328 nfmt(db, "{1:L} vector[{0}]", "{1:R}");
3329 return (t1);
3332 /* BEGIN CSTYLED */
3334 * <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3335 * ::= DT <expression> E # decltype of an expression (C++0x)
3337 /* END CSTYLED */
3338 static const char *
3339 parse_decltype(const char *first, const char *last, cpp_db_t *db)
3341 VERIFY3P(first, <=, last);
3343 if (last - first < 4)
3344 return (first);
3346 VERIFY3U(first[0], ==, 'D');
3348 if (first[1] != 't' && first[1] != 'T')
3349 return (first);
3351 size_t n = nlen(db);
3352 const char *t = parse_expression(first + 2, last, db);
3353 if (NAMT(db, n) != 1 || t == first + 2 || t == last || t[0] != 'E')
3354 return (first);
3356 nfmt(db, "decltype({0})", NULL);
3358 /* skip E */
3359 return (t + 1);
3363 * <array-type> ::= A <positive dimension number> _ <element type>
3364 * ::= A [<dimension expression>] _ <element type>
3366 static const char *
3367 parse_array_type(const char *first, const char *last, cpp_db_t *db)
3369 VERIFY3P(first, <=, last);
3370 VERIFY3U(first[0], ==, 'A');
3372 if (last - first < 3)
3373 return (first);
3375 const char *t = first + 1;
3376 const char *t1 = NULL;
3377 size_t n = nlen(db);
3379 if (t[0] != '_') {
3380 if (isdigit_l(t[0], db->cpp_loc) && t[0] != '0') {
3381 t1 = parse_number(t, last, db->cpp_loc);
3382 if (t1 == last)
3383 return (first);
3385 nadd_l(db, t, (size_t)(t1 - t));
3386 } else {
3387 t1 = parse_expression(t, last, db);
3388 if (t1 == last || t == t1)
3389 return (first);
3392 if (t1[0] != '_')
3393 return (first);
3395 t = t1;
3396 } else {
3397 nadd_l(db, "", 0);
3400 VERIFY3U(t[0], ==, '_');
3402 t1 = parse_type(t + 1, last, db);
3403 if (t1 == t + 1 || NAMT(db, n) != 2)
3404 return (first);
3407 * if we have " [xxx]" already, want new result to be
3408 * " [yyy][xxx]"
3410 str_t *r = &name_top(&db->cpp_name)->strp_r;
3411 if (r->str_len > 1 && r->str_s[0] == ' ' && r->str_s[1] == '[')
3412 (void) str_erase(r, 0, 1);
3414 nfmt(db, "{0:L}", " [{1}]{0:R}");
3415 return (t1);
3418 /* <pointer-to-member-type> ::= M <class type> <member type> */
3419 static const char *
3420 parse_pointer_to_member_type(const char *first, const char *last, cpp_db_t *db)
3422 VERIFY3P(first, <=, last);
3424 if (last - first < 3)
3425 return (first);
3427 VERIFY3U(first[0], ==, 'M');
3429 const char *t1 = first + 1;
3430 const char *t2 = NULL;
3431 size_t n = nlen(db);
3433 t2 = parse_type(t1, last, db);
3434 if (t1 == t2)
3435 return (first);
3437 t1 = t2;
3438 t2 = parse_type(t1, last, db);
3439 if (t1 == t2)
3440 return (first);
3442 if (NAMT(db, n) != 2)
3443 return (first);
3445 str_pair_t *func = name_top(&db->cpp_name);
3447 if (str_length(&func->strp_r) > 0 && func->strp_r.str_s[0] == '(')
3448 nfmt(db, "{0:L}({1}::*", "){0:R}");
3449 else
3450 nfmt(db, "{0:L} {1}::*", "{0:R}");
3452 return (t2);
3455 /* BEGIN CSTYLED */
3457 * <unresolved-name>
3458 * extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3459 * ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3460 * ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3461 * # A::x, N::y, A<T>::z; "gs" means leading "::"
3462 * ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3463 * extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3464 * # T::N::x /decltype(p)::N::x
3465 * (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3467 /* END CSTYLED */
3468 static const char *
3469 parse_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3471 VERIFY3P(first, <=, last);
3473 if (last - first < 2)
3474 return (first);
3476 const char *t = first;
3477 const char *t2 = NULL;
3478 boolean_t global = B_FALSE;
3479 size_t n;
3481 if (t[0] == 'g' && t[1] == 's') {
3482 global = B_TRUE;
3483 t += 2;
3485 if (t == last)
3486 return (first);
3488 t2 = parse_base_unresolved_name(t, last, db);
3489 if (t != t2) {
3490 if (global) {
3491 if (nempty(db))
3492 return (first);
3494 (void) str_insert(TOP_L(db), 0, "::", 2);
3496 return (t2);
3499 if (t[0] != 's' || t[1] != 'r' || last - t < 2)
3500 return (first);
3502 n = nlen(db);
3503 if (t[2] == 'N') {
3504 t += 3;
3505 t2 = parse_unresolved_type(t, last, db);
3506 if (t2 == t || t2 == last)
3507 return (first);
3508 t = t2;
3510 t2 = parse_template_args(t, last, db);
3511 if (t2 != t) {
3512 if (NAMT(db, n) < 2 || t2 == last)
3513 return (first);
3515 nfmt(db, "{1:L}{0}", "{1:R}");
3516 t = t2;
3519 VERIFY3U(NAMT(db, n), ==, 1);
3521 while (t[0] != 'E') {
3522 size_t nn = nlen(db);
3523 t2 = parse_unresolved_qualifier_level(t, last, db);
3524 if (t == t2 || t == last || NAMT(db, nn) != 1)
3525 return (first);
3527 t = t2;
3530 /* skip E */
3531 t++;
3533 t2 = parse_base_unresolved_name(t, last, db);
3534 if (t == t2 || NAMT(db, n) < 2)
3535 return (first);
3537 njoin(db, NAMT(db, n), "::");
3538 return (t2);
3541 t += 2;
3543 t2 = parse_unresolved_type(t, last, db);
3544 if (t != t2) {
3545 t = t2;
3546 t2 = parse_template_args(t, last, db);
3547 if (t2 != t)
3548 nfmt(db, "{1:L}{0}", "{1:R}");
3549 t = t2;
3551 t2 = parse_base_unresolved_name(t, last, db);
3552 if (t == t2 || nlen(db) < 2)
3553 return (first);
3555 nfmt(db, "{1:L}::{0}", "{1:R}");
3556 return (t2);
3559 t2 = parse_unresolved_qualifier_level(t, last, db);
3560 if (t2 == t || t2 == last)
3561 return (first);
3563 t = t2;
3564 if (global && nlen(db) > 0)
3565 nfmt(db, "::{0:L}", "{0:R}");
3567 while (t[0] != 'E') {
3568 t2 = parse_unresolved_qualifier_level(t, last, db);
3569 if (t == t2 || t == last || nlen(db) < 2)
3570 return (first);
3572 t = t2;
3575 /* skip E */
3576 t++;
3578 t2 = parse_base_unresolved_name(t, last, db);
3579 if (t == t2 || nlen(db) < 2)
3580 return (first);
3582 njoin(db, NAMT(db, n), "::");
3583 return (t2);
3586 /* <unresolved-qualifier-level> ::= <simple-id> */
3587 static const char *
3588 parse_unresolved_qualifier_level(const char *first, const char *last,
3589 cpp_db_t *db)
3591 VERIFY3P(first, <=, last);
3592 return (parse_simple_id(first, last, db));
3595 /* BEGIN CSTYLED */
3597 * <base-unresolved-name> ::= <simple-id> # unresolved name
3598 * extension ::= <operator-name> # unresolved operator-function-id
3599 * extension ::= <operator-name> <template-args> # unresolved operator template-id
3600 * ::= on <operator-name> # unresolved operator-function-id
3601 * ::= on <operator-name> <template-args> # unresolved operator template-id
3602 * ::= dn <destructor-name> # destructor or pseudo-destructor;
3603 * # e.g. ~X or ~X<N-1>
3605 /* END CSTYLED */
3606 static const char *
3607 parse_base_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3609 VERIFY3P(first, <=, last);
3611 if (last - first < 2)
3612 return (first);
3614 const char *t = NULL;
3615 const char *t1 = NULL;
3617 if ((first[0] != 'o' && first[0] != 'd') || first[1] != 'n') {
3618 t = parse_simple_id(first, last, db);
3619 if (t != first)
3620 return (t);
3622 t = parse_operator_name(first, last, db);
3623 if (t == first)
3624 return (first);
3626 t1 = parse_template_args(t, last, db);
3627 if (t1 != t) {
3628 if (nlen(db) < 2)
3629 return (first);
3630 nfmt(db, "{1:L}{0}", "{1:R}");
3633 return (t1);
3636 if (first[0] == 'd') {
3637 t = parse_destructor_name(first + 2, last, db);
3638 return ((t != first + 2) ? t : first);
3641 t = parse_operator_name(first + 2, last, db);
3642 if (t == first + 2)
3643 return (first);
3645 t1 = parse_template_args(t, last, db);
3646 if (t1 != t)
3647 nfmt(db, "{1:L}{0}", "{1:R}");
3648 return (t1);
3652 * <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3653 * ::= <simple-id> # e.g., ~A<2*N>
3655 static const char *
3656 parse_destructor_name(const char *first, const char *last, cpp_db_t *db)
3658 VERIFY3P(first, <=, last);
3660 if (first == last)
3661 return (first);
3663 const char *t = parse_unresolved_type(first, last, db);
3665 if (t == first)
3666 t = parse_simple_id(first, last, db);
3668 if (t == first)
3669 return (first);
3671 nfmt(db, "~{0:L}", "{0:R}");
3672 return (t);
3676 * <ref-qualifier> ::= R # & ref-qualifier
3677 * <ref-qualifier> ::= O # && ref-qualifier
3679 * <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
3681 static const char *
3682 parse_function_type(const char *first, const char *last, cpp_db_t *db)
3684 VERIFY3P(first, <=, last);
3686 if (last - first < 2)
3687 return (first);
3689 VERIFY3U(first[0], ==, 'F');
3691 const char *t = first + 1;
3693 /* extern "C" */
3694 if (t[0] == 'Y')
3695 t++;
3697 const char *t1 = parse_type(t, last, db);
3698 if (t1 == t)
3699 return (first);
3701 size_t n = nlen(db);
3702 int ref_qual = 0;
3704 t = t1;
3706 while (t != last && t[0] != 'E') {
3707 if (t[0] == 'v') {
3708 t++;
3709 continue;
3712 if (t[0] == 'R' && t + 1 != last && t[1] == 'E') {
3713 ref_qual = 1;
3714 t++;
3715 continue;
3718 if (t[0] == 'O' && t + 1 != last && t[1] == 'E') {
3719 ref_qual = 2;
3720 t++;
3721 continue;
3725 t1 = parse_type(t, last, db);
3726 if (t1 == t || t == last)
3727 return (first);
3729 t = t1;
3732 if (t == last)
3733 return (first);
3735 njoin(db, NAMT(db, n), ", ");
3736 nfmt(db, "({0})", NULL);
3738 switch (ref_qual) {
3739 case 1:
3740 nfmt(db, "{0} &", NULL);
3741 break;
3742 case 2:
3743 nfmt(db, "{0} &&", NULL);
3744 break;
3747 nfmt(db, "{1:L} ", "{0}{1:R}");
3749 /* skip E */
3750 return (t + 1);
3754 * <template-param> ::= T_ # first template parameter
3755 * ::= T <parameter-2 non-negative number> _
3757 static const char *
3758 parse_template_param(const char *first, const char *last, cpp_db_t *db)
3760 VERIFY3P(first, <=, last);
3762 if (last - first < 2 || first[0] != 'T')
3763 return (first);
3765 const char *t = first + 1;
3766 size_t idx = 0;
3768 while (t != last && t[0] != '_') {
3769 if (!isdigit_l(t[0], db->cpp_loc))
3770 return (first);
3772 idx *= 10;
3773 idx += t[0] - '0';
3774 t++;
3777 if (t == last)
3778 return (first);
3780 VERIFY3U(t[0], ==, '_');
3783 * T_ -> idx 0
3784 * T0 -> idx 1
3785 * T1 -> idx 2
3786 * ...
3788 if (first[1] != '_')
3789 idx++;
3791 /* skip _ */
3792 t++;
3794 if (tempty(db))
3795 return (first);
3797 if (idx >= ttlen(db)) {
3798 nadd_l(db, first, (size_t)(t - first));
3799 db->cpp_fix_forward_references = B_TRUE;
3800 return (t);
3803 tsub(db, idx);
3804 return (t);
3808 * <template-args> ::= I <template-arg>* E
3809 * extension, the abi says <template-arg>+
3811 static const char *
3812 parse_template_args(const char *first, const char *last, cpp_db_t *db)
3814 VERIFY3P(first, <=, last);
3816 if (last - first < 2 || first[0] != 'I')
3817 return (first);
3819 if (db->cpp_tag_templates)
3820 sub_clear(templ_top(&db->cpp_templ));
3822 const char *t = first + 1;
3823 size_t n = nlen(db);
3825 while (t[0] != 'E') {
3826 if (db->cpp_tag_templates)
3827 tpush(db);
3829 size_t n1 = nlen(db);
3830 const char *t1 = parse_template_arg(t, last, db);
3832 if (db->cpp_tag_templates)
3833 tpop(db);
3835 if (t1 == t || t == last)
3836 return (first);
3838 if (db->cpp_tag_templates)
3839 tsave(db, NAMT(db, n1));
3841 t = t1;
3845 * ugly, but if the last thing pushed was an empty string,
3846 * get rid of it so we dont get "<..., >"
3848 if (NAMT(db, n) > 1 &&
3849 str_pair_len(name_top(&db->cpp_name)) == 0)
3850 name_pop(&db->cpp_name, NULL);
3852 njoin(db, NAMT(db, n), ", ");
3854 VERIFY3U(nlen(db), >, 0);
3856 /* make sure we don't bitshift ourselves into oblivion */
3857 str_t *top = TOP_L(db);
3858 if (str_length(top) > 0 &&
3859 top->str_s[top->str_len - 1] == '>')
3860 nfmt(db, "<{0} >", NULL);
3861 else
3862 nfmt(db, "<{0}>", NULL);
3864 /* skip E */
3865 return (t + 1);
3869 * <discriminator> := _ <non-negative number> # when number < 10
3870 * := __ <non-negative number> _ # when number >= 10
3871 * extension := decimal-digit+ # at the end of string
3873 static const char *
3874 parse_discriminator(const char *first, const char *last, locale_t loc)
3876 VERIFY3P(first, <=, last);
3878 const char *t = NULL;
3880 if (first == last)
3881 return (first);
3883 if (isdigit_l(first[0], loc)) {
3884 for (t = first; t != last && isdigit_l(t[0], loc); t++)
3887 /* not at the end of the string */
3888 if (t != last)
3889 return (first);
3891 return (t);
3892 } else if (first[0] != '_' || first + 1 == last) {
3893 return (first);
3896 t = first + 1;
3897 if (isdigit_l(t[0], loc))
3898 return (t + 1);
3900 if (t[0] != '_' || t + 1 == last)
3901 return (first);
3903 for (t++; t != last && isdigit_l(t[0], loc); t++)
3905 if (t == last || t[0] != '_')
3906 return (first);
3908 return (t);
3911 /* <CV-qualifiers> ::= [r] [V] [K] */
3912 const char *
3913 parse_cv_qualifiers(const char *first, const char *last, unsigned *cv)
3915 VERIFY3P(first, <=, last);
3917 if (first == last)
3918 return (first);
3920 *cv = 0;
3921 if (first[0] == 'r') {
3922 *cv |= CPP_QUAL_RESTRICT;
3923 first++;
3925 if (first != last && first[0] == 'V') {
3926 *cv |= CPP_QUAL_VOLATILE;
3927 first++;
3929 if (first != last && first[0] == 'K') {
3930 *cv |= CPP_QUAL_CONST;
3931 first++;
3934 return (first);
3938 * <number> ::= [n] <non-negative decimal integer>
3940 static const char *
3941 parse_number(const char *first, const char *last, locale_t loc)
3943 VERIFY3P(first, <=, last);
3945 const char *t = first;
3947 if (first == last || (first[0] != 'n' && !isdigit_l(first[0], loc)))
3948 return (first);
3950 if (t[0] == 'n')
3951 t++;
3953 if (t[0] == '0')
3954 return (t + 1);
3956 while (isdigit_l(t[0], loc))
3957 t++;
3959 return (t);
3963 * Like isxdigit(3C), except we can only accept lower case letters as
3964 * that's only what is allowed when [de]mangling floating point constants into
3965 * their hex representation.
3967 static inline boolean_t
3968 is_xdigit(int c)
3970 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
3971 return (B_TRUE);
3972 return (B_FALSE);
3975 static boolean_t
3976 nempty(cpp_db_t *db)
3978 return (name_empty(&db->cpp_name));
3981 static size_t
3982 nlen(cpp_db_t *db)
3984 return (name_len(&db->cpp_name));
3987 static void
3988 nadd_l(cpp_db_t *db, const char *s, size_t len)
3990 CK(name_add(&db->cpp_name, s, len, NULL, 0));
3993 static void
3994 njoin(cpp_db_t *db, size_t amt, const char *sep)
3996 name_t *nm = &db->cpp_name;
3998 CK(name_join(nm, amt, sep));
4001 static void
4002 nfmt(cpp_db_t *db, const char *fmt_l, const char *fmt_r)
4004 CK(name_fmt(&db->cpp_name, fmt_l, fmt_r));
4007 static void
4008 save_top(cpp_db_t *db, size_t amt)
4010 CK(sub_save(&db->cpp_subs, &db->cpp_name, amt));
4013 static void
4014 sub(cpp_db_t *db, size_t n)
4016 CK(sub_substitute(&db->cpp_subs, n, &db->cpp_name));
4019 static boolean_t
4020 tempty(const cpp_db_t *db)
4022 return (templ_empty(&db->cpp_templ) ? B_TRUE : B_FALSE);
4025 static size_t
4026 ttlen(const cpp_db_t *db)
4028 return (templ_top_len(&db->cpp_templ));
4031 static void
4032 tsub(cpp_db_t *db, size_t n)
4034 CK(templ_sub(&db->cpp_templ, n, &db->cpp_name));
4037 static void
4038 tpush(cpp_db_t *db)
4040 CK(templ_push(&db->cpp_templ));
4043 static void
4044 tpop(cpp_db_t *db)
4046 templ_pop(&db->cpp_templ);
4049 static void
4050 tsave(cpp_db_t *db, size_t amt)
4052 CK(templ_save(&db->cpp_name, amt, &db->cpp_templ));
4055 static boolean_t
4056 db_init(cpp_db_t *db, sysdem_ops_t *ops)
4058 (void) memset(db, 0, sizeof (*db));
4059 db->cpp_ops = ops;
4060 name_init(&db->cpp_name, ops);
4061 sub_init(&db->cpp_subs, ops);
4062 templ_init(&db->cpp_templ, ops);
4063 db->cpp_tag_templates = B_TRUE;
4064 db->cpp_try_to_parse_template_args = B_TRUE;
4065 tpush(db);
4066 db->cpp_loc = newlocale(LC_CTYPE_MASK, "C", 0);
4067 return ((db->cpp_loc != NULL) ? B_TRUE : B_FALSE);
4070 static void
4071 db_fini(cpp_db_t *db)
4073 name_fini(&db->cpp_name);
4074 sub_fini(&db->cpp_subs);
4075 templ_fini(&db->cpp_templ);
4076 freelocale(db->cpp_loc);
4077 (void) memset(db, 0, sizeof (*db));
4080 static void
4081 print_sp(const str_pair_t *sp, FILE *out)
4083 (void) fprintf(out, "{%.*s#%.*s}",
4084 (int)sp->strp_l.str_len, sp->strp_l.str_s,
4085 (int)sp->strp_r.str_len, sp->strp_r.str_s);
4088 static void
4089 print_name(const name_t *n, FILE *out)
4091 const str_pair_t *sp = name_top((name_t *)n);
4092 size_t i;
4094 (void) fprintf(out, "Name:\n");
4096 if (name_len(n) == 0)
4097 return;
4099 for (i = 0; i < n->nm_len; i++, sp--) {
4100 (void) fprintf(out, " [%02zu] ", i);
4101 print_sp(sp, out);
4102 (void) fputc('\n', out);
4105 (void) fputc('\n', out);
4108 /* Print a base-36 number (for substitutions) */
4109 static char *
4110 base36(char *buf, size_t val)
4112 char tmp[16] = { 0 };
4113 char *p = tmp;
4115 if (val == 0) {
4116 buf[0] = '0';
4117 buf[1] = '\0';
4118 return (buf);
4121 while (val > 0) {
4122 size_t r = val % 36;
4124 if (r < 10)
4125 *p++ = r + '0';
4126 else
4127 *p++ = r - 10 + 'A';
4129 val /= 36;
4132 char *q = buf;
4133 while (--p >= tmp)
4134 *q++ = *p;
4136 return (buf);
4139 static void
4140 print_sub(const sub_t *sub, FILE *out)
4142 const name_t *n = sub->sub_items;
4144 (void) fprintf(out, "Substitutions:\n");
4146 if (sub->sub_len == 0)
4147 return;
4149 for (size_t i = 0; i < sub->sub_len; i++, n++) {
4150 (void) printf(" ");
4151 if (i == 0) {
4152 (void) fprintf(out, "%-4s", "S_");
4153 } else {
4154 char buf[16] = { 0 };
4155 char buf2[16] = { 0 };
4157 (void) snprintf(buf, sizeof (buf), "S%s_",
4158 base36(buf2, i));
4159 (void) fprintf(out, "%-4s", buf);
4161 (void) fprintf(out, " = ");
4163 (void) fputc('{', out);
4164 for (size_t j = 0; j < n->nm_len; j++) {
4165 if (j > 0)
4166 (void) fputc(' ', out);
4167 print_sp(&n->nm_items[j], out);
4169 (void) fputc('}', out);
4171 (void) fputc('\n', out);
4173 (void) fputc('\n', out);
4176 static void
4177 print_templ(const templ_t *tpl, FILE *out)
4180 (void) fprintf(out, "Template\n");
4182 const sub_t *s = templ_top((templ_t *)tpl);
4184 for (size_t i = 0; i < s->sub_len; i++) {
4185 char buf[16] = { 0 };
4187 if (i == 0)
4188 (void) snprintf(buf, sizeof (buf), "%s", "T_");
4189 else
4190 (void) snprintf(buf, sizeof (buf), "T%zu_", i - 1);
4192 (void) fprintf(out, " %-4s = ", buf);
4194 (void) fputc('{', out);
4196 const name_t *n = &s->sub_items[i];
4197 for (size_t j = 0; j < n->nm_len; j++) {
4198 const str_pair_t *sp = &n->nm_items[j];
4200 if (j > 0)
4201 (void) fputc(' ', out);
4203 (void) fprintf(out, "{%.*s#%.*s}",
4204 (int)sp->strp_l.str_len, sp->strp_l.str_s,
4205 (int)sp->strp_r.str_len, sp->strp_r.str_s);
4207 (void) fprintf(out, "}\n");
4209 (void) fprintf(out, "\n");
4212 static void
4213 dump(cpp_db_t *db, FILE *out)
4215 print_name(&db->cpp_name, out);
4216 print_sub(&db->cpp_subs, out);
4217 print_templ(&db->cpp_templ, out);