1 /*
2 * Ported from LLVM's libcxxabi trunk/src/cxa_demangle.cpp
3 * LICENSE.TXT contents is available as ../THIRDPARTYLICENSE
4 *
5 * The LLVM Compiler Infrastructure
6 *
7 * This file is dual licensed under the MIT and the University of Illinois Open
8 * Source Licenses. See LICENSE.TXT for details.
9 *
10 */
11
12 /*
13 * Copyright 2017 Jason King.
14 */
15
16 #include <errno.h>
17 #include <string.h>
18 #include <setjmp.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <sys/isa_defs.h>
22 #include <sys/debug.h>
23 #include "sysdemangle.h"
24 #include "sysdemangle_int.h"
25 #include "cpp.h"
26
27 #define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
28
29 #define CPP_QUAL_CONST (1U)
30 #define CPP_QUAL_VOLATILE (2U)
31 #define CPP_QUAL_RESTRICT (4U)
32
33 typedef struct cpp_db_s {
34 sysdem_ops_t *cpp_ops;
35 jmp_buf cpp_jmp;
36 name_t cpp_name;
37 sub_t cpp_subs;
38 templ_t cpp_templ;
39 unsigned cpp_cv;
40 unsigned cpp_ref;
41 unsigned cpp_depth;
42 boolean_t cpp_parsed_ctor_dtor_cv;
43 boolean_t cpp_tag_templates;
44 boolean_t cpp_fix_forward_references;
45 boolean_t cpp_try_to_parse_template_args;
46 } cpp_db_t;
47
48 #define CK(x) \
49 do { \
50 if (!(x)) \
51 longjmp(db->cpp_jmp, 1); \
52 } while (0)
53
54 #define TOP_L(db) (&(name_top(&(db)->cpp_name)->strp_l))
55 #define RLEN(f, l) ((size_t)((l) - (f)))
56 #define NAMT(db, n) (nlen(db) - n)
57
58 static inline boolean_t is_digit(int);
59 static inline boolean_t is_upper(int);
60 static inline boolean_t is_xdigit(int);
61
62 static boolean_t nempty(cpp_db_t *);
63 static size_t nlen(cpp_db_t *);
64 static void nadd_l(cpp_db_t *, const char *, size_t);
65 static void njoin(cpp_db_t *, size_t, const char *);
66 static void nfmt(cpp_db_t *, const char *, const char *);
67
68 static void save_top(cpp_db_t *, size_t);
69 static void sub(cpp_db_t *, size_t);
70
71 static boolean_t tempty(const cpp_db_t *);
72 static size_t ttlen(const cpp_db_t *);
73
74 static void tsub(cpp_db_t *, size_t);
75 static void tpush(cpp_db_t *);
76 static void tpop(cpp_db_t *);
77 static void tsave(cpp_db_t *, size_t);
78
79 static void db_init(cpp_db_t *, sysdem_ops_t *);
80 static void db_fini(cpp_db_t *);
81 static void dump(cpp_db_t *, FILE *);
82
83 static void demangle(const char *, const char *, cpp_db_t *);
84
85 static const char *parse_type(const char *, const char *, cpp_db_t *);
86 static const char *parse_builtin_type(const char *, const char *, cpp_db_t *);
87 static const char *parse_qual_type(const char *, const char *, cpp_db_t *);
88 static const char *parse_encoding(const char *, const char *, cpp_db_t *);
89 static const char *parse_dot_suffix(const char *, const char *, cpp_db_t *);
90 static const char *parse_block_invoke(const char *, const char *, cpp_db_t *);
91 static const char *parse_special_name(const char *, const char *, cpp_db_t *);
92 static const char *parse_name(const char *, const char *, boolean_t *,
93 cpp_db_t *);
94 static const char *parse_call_offset(const char *, const char *);
95 static const char *parse_number(const char *, const char *);
96 static const char *parse_nested_name(const char *, const char *, boolean_t *,
97 cpp_db_t *);
98 static const char *parse_local_name(const char *, const char *, boolean_t *,
99 cpp_db_t *);
100 static const char *parse_unscoped_name(const char *, const char *, cpp_db_t *);
101 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
102 static const char *parse_substitution(const char *, const char *, cpp_db_t *);
103 static const char *parse_discriminator(const char *, const char *);
104 static const char *parse_cv_qualifiers(const char *, const char *, unsigned *);
105 static const char *parse_template_param(const char *, const char *, cpp_db_t *);
106 static const char *parse_decltype(const char *, const char *, cpp_db_t *);
107 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
108 static const char *parse_unqualified_name(const char *, const char *,
109 cpp_db_t *);
110 static const char *parse_template_arg(const char *, const char *, cpp_db_t *);
111 static const char *parse_expression(const char *, const char *, cpp_db_t *);
112 static const char *parse_expr_primary(const char *, const char *, cpp_db_t *);
113 static const char *parse_binary_expr(const char *, const char *,
114 const char *, cpp_db_t *);
115 static const char *parse_prefix_expr(const char *, const char *,
116 const char *, cpp_db_t *);
117 static const char *parse_gs(const char *, const char *, cpp_db_t *);
118 static const char *parse_idx_expr(const char *, const char *, cpp_db_t *);
119 static const char *parse_mm_expr(const char *, const char *, cpp_db_t *);
120 static const char *parse_pp_expr(const char *, const char *, cpp_db_t *);
121 static const char *parse_trinary_expr(const char *, const char *, cpp_db_t *);
122 static const char *parse_new_expr(const char *, const char *, cpp_db_t *);
123 static const char *parse_del_expr(const char *, const char *, cpp_db_t *);
149 cpp_db_t *);
150 static const char *parse_unresolved_qualifier_level(const char *, const char *,
151 cpp_db_t *);
152 static const char *parse_destructor_name(const char *, const char *,
153 cpp_db_t *);
154 static const char *parse_function_type(const char *, const char *, cpp_db_t *);
155 static const char *parse_array_type(const char *, const char *, cpp_db_t *);
156 static const char *parse_pointer_to_member_type(const char *, const char *,
157 cpp_db_t *);
158 static const char *parse_vector_type(const char *, const char *, cpp_db_t *);
159
160 size_t cpp_name_max_depth = 1024; /* max depth of name stack */
161
162 char *
163 cpp_demangle(const char *src, sysdem_ops_t *ops)
164 {
165 char *result = NULL;
166 cpp_db_t db;
167 size_t srclen = strlen(src);
168
169 db_init(&db, ops);
170
171 if (setjmp(db.cpp_jmp) != 0)
172 goto done;
173
174 errno = 0;
175 demangle(src, src + srclen, &db);
176
177 if (errno == 0 && db.cpp_fix_forward_references &&
178 !templ_empty(&db.cpp_templ) &&
179 !sub_empty(&db.cpp_templ.tpl_items[0])) {
180 db.cpp_fix_forward_references = B_FALSE;
181 db.cpp_tag_templates = B_FALSE;
182 name_clear(&db.cpp_name);
183 sub_clear(&db.cpp_subs);
184
185 if (setjmp(db.cpp_jmp) != 0)
186 goto done;
187
188 demangle(src, src + srclen, &db);
189
190 if (db.cpp_fix_forward_references) {
254 }
255
256 goto done;
257 }
258
259 if (first[1] != '_' || first[2] != '_' || first[3] != 'Z')
260 goto done;
261
262 t = parse_encoding(first + 4, last, db);
263 if (t != first + 4 && t != last)
264 t = parse_block_invoke(t, last, db);
265
266 done:
267 if (t != last)
268 errno = EINVAL;
269 }
270
271 static const char *
272 parse_dot_suffix(const char *first, const char *last, cpp_db_t *db)
273 {
274 ASSERT3P(first, <=, last);
275
276 if (first == last || first[0] != '.')
277 return (first);
278
279 if (nempty(db))
280 return (first);
281
282 nadd_l(db, first, RLEN(first, last));
283 nfmt(db, " ({0})", NULL);
284
285 return (last);
286 }
287
288 /*
289 * _block_invoke
290 * _block_invoke<digit>+ XXX: should it be <digit>* ?
291 * _block_invoke_<digit>+
292 */
293 static const char *
294 parse_block_invoke(const char *first, const char *last, cpp_db_t *db)
295 {
296 ASSERT3P(first, <=, last);
297
298 if (last - first < 13)
299 return (first);
300
301 const char test[] = "_block_invoke";
302 const char *t = first;
303
304 if (strncmp(first, test, sizeof (test) - 1) != 0)
305 return (first);
306
307 t += sizeof (test);
308 if (t == last)
309 goto done;
310
311 if (t[0] == '_') {
312 /* need at least one digit */
313 if (t + 1 == last || !is_digit(t[1]))
314 return (first);
315 t += 2;
316 }
317
318 while (t < last && is_digit(t[0]))
319 t++;
320
321 done:
322 if (nempty(db))
323 return (first);
324
325 nfmt(db, "invocation function for block in {0}", NULL);
326 return (t);
327 }
328
329 /*
330 * <encoding> ::= <function name><bare-function-type>
331 * ::= <data name>
332 * ::= <special name>
333 */
334 static const char *
335 parse_encoding(const char *first, const char *last, cpp_db_t *db)
336 {
337 ASSERT3P(first, <=, last);
338
339 if (first == last)
340 return (first);
341
342 const char *t = NULL;
343 const char *t2 = NULL;
344 unsigned cv = 0;
345 unsigned ref = 0;
346 boolean_t tag_templ_save = db->cpp_tag_templates;
347
348 if (++db->cpp_depth > 1)
349 db->cpp_tag_templates = B_TRUE;
350
351 if (first[0] == 'G' || first[0] == 'T') {
352 t = parse_special_name(first, last, db);
353 goto done;
354 }
355
356 boolean_t ends_with_template_args = B_FALSE;
357 t = parse_name(first, last, &ends_with_template_args, db);
390 if (t[0] == 'v') {
391 t++;
392 } else {
393
394 /*CONSTCOND*/
395 while (1) {
396 t2 = parse_type(t, last, db);
397 if (t2 == t || t == last)
398 break;
399
400 t = t2;
401 }
402 }
403
404 /*
405 * a bit of a hack, but a template substitution can apparently be
406 * an empty string at the end of an argument list, so avoid
407 * <...., >
408 */
409 if (NAMT(db, n) > 1 && str_pair_len(name_top(&db->cpp_name)) == 0)
410 (void) name_pop(&db->cpp_name, NULL);
411
412 njoin(db, NAMT(db, n), ", ");
413 nfmt(db, "({0})", NULL);
414
415 str_t *s = TOP_L(db);
416
417 if (cv & CPP_QUAL_CONST) {
418 CK(str_append(s, " const", 0));
419 }
420 if (cv & CPP_QUAL_VOLATILE) {
421 CK(str_append(s, " volatile", 0));
422 }
423 if (cv & CPP_QUAL_RESTRICT) {
424 CK(str_append(s, " restrict", 0));
425 }
426 if (ref == 1) {
427 CK(str_append(s, " &", 0));
428 }
429 if (ref == 2) {
430 CK(str_append(s, " &&", 0));
448 * ::= TT <type> # VTT structure (construction vtable index)
449 * ::= TI <type> # typeinfo structure
450 * ::= TS <type> # typeinfo name (null-terminated byte string)
451 * ::= Tc <call-offset> <call-offset> <base encoding>
452 * # base is the nominal target function of thunk
453 * # first call-offset is 'this' adjustment
454 * # second call-offset is result adjustment
455 * ::= T <call-offset> <base encoding>
456 * # base is the nominal target function of thunk
457 * ::= GV <object name> # Guard variable for one-time init
458 * # No <type>
459 * ::= TW <object name> # Thread-local wrapper
460 * ::= TH <object name> # Thread-local initialization
461 * extension ::= TC <first type> <number> _ <second type>
462 * # construction vtable for second-in-first
463 * extension ::= GR <object name> # reference temporary for object
464 */
465 static const char *
466 parse_special_name(const char *first, const char *last, cpp_db_t *db)
467 {
468 ASSERT3P(first, <=, last);
469
470 const char *t = first;
471 const char *t1 = NULL;
472 size_t n = nlen(db);
473
474 if (last - first < 2)
475 return (first);
476
477 switch (t[0]) {
478 case 'T':
479 switch (t[1]) {
480 case 'V':
481 nadd_l(db, "vtable for", 0);
482 t = parse_type(first + 2, last, db);
483 break;
484 case 'T':
485 nadd_l(db, "VTT for", 0);
486 t = parse_type(first + 2, last, db);
487 break;
488 case 'I':
489 nadd_l(db, "typeinfo for", 0);
490 t = parse_type(first + 2, last, db);
491 break;
492 case 'S':
493 nadd_l(db, "typeinfo name for", 0);
494 t = parse_type(first + 2, last, db);
495 break;
496 case 'c':
497 nadd_l(db, "covariant return thunk to", 0);
498 t1 = parse_call_offset(first + 2, last);
499 if (t1 == t)
500 return (first);
501 t = parse_call_offset(t1, last);
502 if (t == t1)
503 return (first);
504 t1 = parse_encoding(t, last, db);
505 if (t1 == t)
506 return (first);
507 break;
508 case 'C':
509 t = parse_type(first + 2, last, db);
510 if (t == first + 2)
511 return (first);
512 t1 = parse_number(t, last);
513 if (*t1 != '_')
514 return (first);
515 t = parse_type(t1 + 1, last, db);
516 if (t == t1 + 1 || nlen(db) < 2)
517 return (first);
518 nfmt(db, "construction vtable for {0}-in-{1}", NULL);
519 return (t);
520 case 'W':
521 nadd_l(db, "thread-local wrapper routine for", 0);
522 t = parse_name(first + 2, last, NULL, db);
523 break;
524 case 'H':
525 nadd_l(db, "thread-local initialization routine for",
526 0);
527 t = parse_name(first + 2, last, NULL, db);
528 break;
529 default:
530 if (first[1] == 'v') {
531 nadd_l(db, "virtual thunk to", 0);
532 } else {
533 nadd_l(db, "non-virtual thunk to", 0);
534 }
535
536 t = parse_call_offset(first + 1, last);
537 if (t == first + 1)
538 return (first);
539 t1 = parse_encoding(t, last, db);
540 if (t == t1)
541 return (first);
542 t = t1;
543 break;
544 }
545 break;
546 case 'G':
547 switch (first[1]) {
548 case 'V':
549 nadd_l(db, "guard variable for", 0);
550 t = parse_name(first + 2, last, NULL, db);
551 break;
552 case 'R':
553 nadd_l(db, "reference temporary for", 0);
554 t = parse_name(first + 2, last, NULL, db);
555 break;
556 default:
563
564 size_t amt = NAMT(db, n);
565 if (t == first + 2 || amt < 2)
566 return (first);
567
568 njoin(db, amt, " ");
569 return (t);
570 }
571
572 /*
573 * <call-offset> ::= h <nv-offset> _
574 * ::= v <v-offset> _
575 *
576 * <nv-offset> ::= <offset number>
577 * # non-virtual base override
578 *
579 * <v-offset> ::= <offset number> _ <virtual offset number>
580 * # virtual base override, with vcall offset
581 */
582 static const char *
583 parse_call_offset(const char *first, const char *last)
584 {
585 ASSERT3P(first, <=, last);
586
587 const char *t = NULL;
588 const char *t1 = NULL;
589
590 if (first == last)
591 return (first);
592
593 if (first[0] != 'h' && first[0] != 'v')
594 return (first);
595
596 t = parse_number(first + 1, last);
597 if (t == first + 1 || t == last || t[0] != '_')
598 return (first);
599
600 /* skip _ */
601 t++;
602
603 if (first[0] == 'h')
604 return (t);
605
606 t1 = parse_number(t, last);
607 if (t == t1 || t1 == last || t1[0] != '_')
608 return (first);
609
610 /* skip _ */
611 t1++;
612
613 return (t1);
614 }
615
616 /*
617 * <name> ::= <nested-name> // N
618 * ::= <local-name> # See Scope Encoding below // Z
619 * ::= <unscoped-template-name> <template-args>
620 * ::= <unscoped-name>
621 *
622 * <unscoped-template-name> ::= <unscoped-name>
623 * ::= <substitution>
624 */
625 static const char *
626 parse_name(const char *first, const char *last,
627 boolean_t *ends_with_template_args, cpp_db_t *db)
628 {
629 ASSERT3P(first, <=, last);
630
631 const char *t = first;
632 const char *t1 = NULL;
633
634 if (last - first < 2)
635 return (first);
636
637 /* extension: ignore L here */
638 if (t[0] == 'L')
639 t++;
640
641 switch (t[0]) {
642 case 'N':
643 t1 = parse_nested_name(t, last, ends_with_template_args, db);
644 return ((t == t1) ? first : t1);
645 case 'Z':
646 t1 = parse_local_name(t, last, ends_with_template_args, db);
647 return ((t == t1) ? first : t1);
648 }
649
672
673 nfmt(db, "{1:L}{0}", "{1:R}");
674
675 if (ends_with_template_args != NULL)
676 *ends_with_template_args = B_TRUE;
677
678 return (t);
679 }
680
681 /* BEGIN CSTYLED */
682 /*
683 * <local-name> := Z <function encoding> E <entity name> [<discriminator>]
684 * := Z <function encoding> E s [<discriminator>]
685 * := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
686 */
687 /* END CSTYLED */
688 const char *
689 parse_local_name(const char *first, const char *last,
690 boolean_t *ends_with_template_args, cpp_db_t *db)
691 {
692 ASSERT3P(first, <=, last);
693
694 const char *t = NULL;
695 const char *t1 = NULL;
696 const char *t2 = NULL;
697
698 if (first == last || first[0] != 'Z')
699 return (first);
700
701 t = parse_encoding(first + 1, last, db);
702 if (t == first + 1 || t == last || t[0] != 'E')
703 return (first);
704
705 ASSERT(!nempty(db));
706
707 /* skip E */
708 t++;
709
710 if (t[0] == 's') {
711 nfmt(db, "{0:L}::string literal", "{0:R}");
712 return (parse_discriminator(t, last));
713 }
714
715 if (t[0] == 'd') {
716 t1 = parse_number(t + 1, last);
717 if (t1[0] != '_')
718 return (first);
719 t1++;
720 } else {
721 t1 = t;
722 }
723
724 t2 = parse_name(t1, last, ends_with_template_args, db);
725 if (t2 == t1)
726 return (first);
727
728 nfmt(db, "{1:L}::{0}", "{1:R}");
729
730 /* parsed, but ignored */
731 if (t[0] != 'd')
732 t2 = parse_discriminator(t2, last);
733
734 return (t2);
735 }
736
737 /* BEGIN CSTYLED */
738 /*
739 * <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
740 * ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
741 *
742 * <prefix> ::= <prefix> <unqualified-name>
743 * ::= <template-prefix> <template-args>
744 * ::= <template-param>
745 * ::= <decltype>
746 * ::= # empty
747 * ::= <substitution>
748 * ::= <prefix> <data-member-prefix>
749 * extension ::= L
750 *
751 * <template-prefix> ::= <prefix> <template unqualified-name>
752 * ::= <template-param>
753 * ::= <substitution>
754 */
755 /* END CSTYLED */
756 static const char *
757 parse_nested_name(const char *first, const char *last,
758 boolean_t *ends_with_template_args, cpp_db_t *db)
759 {
760 ASSERT3P(first, <=, last);
761
762 if (first == last || first[0] != 'N')
763 return (first);
764
765 unsigned cv = 0;
766 const char *t = parse_cv_qualifiers(first + 1, last, &cv);
767
768 if (t == last)
769 return (first);
770
771 boolean_t more = B_FALSE;
772
773 switch (t[0]) {
774 case 'R':
775 db->cpp_ref = 1;
776 t++;
777 break;
778 case 'O':
779 db->cpp_ref = 2;
780 t++;
793 boolean_t pop_subs = B_FALSE;
794 boolean_t component_ends_with_template_args = B_FALSE;
795
796 while (t[0] != 'E' && t != last) {
797 const char *t1 = NULL;
798 size_t n = nlen(db);
799 component_ends_with_template_args = B_FALSE;
800
801 switch (t[0]) {
802 case 'S':
803 if (t + 1 != last && t[1] == 't')
804 break;
805
806 t1 = parse_substitution(t, last, db);
807 if (t1 == t || t1 == last || NAMT(db, n) != 1)
808 return (first);
809
810 if (!more) {
811 nfmt(db, "{0}", NULL);
812 } else {
813 ASSERT3U(nlen(db), >, 1);
814 nfmt(db, "{1:L}::{0}", "{1:R}");
815 save_top(db, 1);
816 }
817
818 more = B_TRUE;
819 pop_subs = B_TRUE;
820 t = t1;
821 continue;
822
823 case 'T':
824 t1 = parse_template_param(t, last, db);
825 if (t1 == t || t1 == last || NAMT(db, n) != 1)
826 return (first);
827
828 if (!more) {
829 nfmt(db, "{0}", NULL);
830 } else {
831 ASSERT3U(nlen(db), >, 1);
832 nfmt(db, "{1:L}::{0}", "{1:R}");
833 }
834
835 save_top(db, 1);
836 more = B_TRUE;
837 pop_subs = B_TRUE;
838 t = t1;
839 continue;
840
841 case 'D':
842 if (t + 1 != last && t[1] != 't' && t[1] != 'T')
843 break;
844 t1 = parse_decltype(t, last, db);
845 if (t1 == t || t1 == last || NAMT(db, n) != 1)
846 return (first);
847
848 if (!more) {
849 nfmt(db, "{0}", NULL);
850 } else {
851 ASSERT3U(nlen(db), >, 1);
852 nfmt(db, "{1:L}::{0}", "{1:R}");
853 }
854
855 save_top(db, 1);
856 more = B_TRUE;
857 pop_subs = B_TRUE;
858 t = t1;
859 continue;
860
861 case 'I':
862 /*
863 * Must have at least one component before
864 * <template-args>
865 */
866 if (!more)
867 return (first);
868
869 t1 = parse_template_args(t, last, db);
870 if (t1 == t || t1 == last)
871 return (first);
872
873 ASSERT3U(nlen(db), >, 1);
874 nfmt(db, "{1:L}{0}", "{1:R}");
875 save_top(db, 1);
876 t = t1;
877 component_ends_with_template_args = B_TRUE;
878 continue;
879
880 case 'L':
881 if (t + 1 == last)
882 return (first);
883 t++;
884 continue;
885
886 default:
887 break;
888 }
889
890 t1 = parse_unqualified_name(t, last, db);
891 if (t1 == t || t1 == last || NAMT(db, n) != 1)
892 return (first);
893
894 if (!more) {
895 nfmt(db, "{0}", NULL);
896 } else {
897 ASSERT3U(nlen(db), >, 1);
898 nfmt(db, "{1:L}::{0}", "{1:R}");
899 }
900
901 save_top(db, 1);
902 more = B_TRUE;
903 pop_subs = B_TRUE;
904 t = t1;
905 }
906
907 /* need to parse at least one thing */
908 if (!more)
909 return (first);
910
911 db->cpp_cv = cv;
912 if (pop_subs && !sub_empty(&db->cpp_subs))
913 sub_pop(&db->cpp_subs);
914
915 if (ends_with_template_args != NULL)
916 *ends_with_template_args = component_ends_with_template_args;
917
918 if (t[0] != 'E')
919 return (first);
920
921 return (t + 1);
922 }
923
924 /*
925 * <template-arg> ::= <type> # type or template
926 * ::= X <expression> E # expression
927 * ::= <expr-primary> # simple expressions
928 * ::= J <template-arg>* E # argument pack
929 * ::= LZ <encoding> E # extension
930 */
931 static const char *
932 parse_template_arg(const char *first, const char *last, cpp_db_t *db)
933 {
934 ASSERT3P(first, <=, last);
935
936 const char *t = NULL;
937 const char *t1 = NULL;
938
939 if (first == last)
940 return (first);
941
942 switch (first[0]) {
943 case 'X':
944 t = parse_expression(first + 1, last, db);
945 if (t == first + 1 || t[0] != 'E')
946 return (first);
947
948 /* E */
949 t++;
950 break;
951
952 case 'J':
953 t = first + 1;
954 if (t == last)
1114 PA("rS", ">>=", parse_binary_expr),
1115 PN("rc", parse_cast_expr),
1116 PA("rm", "%", parse_binary_expr),
1117 PA("rs", ">>", parse_binary_expr),
1118 PN("sc", parse_cast_expr),
1119 PN("sp", parse_pack_expansion),
1120 PN("sr", parse_unresolved_name),
1121 PN("st", parse_sizeof),
1122 PN("sz", parse_sizeof),
1123 PN("sZ", parse_sizeof_param_pack_expr),
1124 PN("te", parse_typeid_expr),
1125 PN("tr", parse_throw_expr),
1126 PN("tw", parse_throw_expr)
1127 };
1128 #undef PA
1129 #undef PN
1130
1131 static const char *
1132 parse_expression(const char *first, const char *last, cpp_db_t *db)
1133 {
1134 ASSERT3P(first, <=, last);
1135
1136 if (last - first < 2)
1137 return (first);
1138
1139 for (size_t i = 0; i < ARRAY_SIZE(expr_tbl); i++) {
1140 if (strncmp(expr_tbl[i].code, first, 2) != 0)
1141 continue;
1142 switch (expr_tbl[i].fntype) {
1143 case EXPR_ARG:
1144 return (expr_tbl[i].p.parse_expr_arg(first, last,
1145 expr_tbl[i].val, db));
1146 case EXPR_NOARG:
1147 return (expr_tbl[i].p.parse_expr_noarg(first, last,
1148 db));
1149 }
1150 }
1151
1152 switch (first[0]) {
1153 case 'L':
1154 return (parse_expr_primary(first, last, db));
1158 return (parse_function_param(first, last, db));
1159 case '1':
1160 case '2':
1161 case '3':
1162 case '4':
1163 case '5':
1164 case '6':
1165 case '7':
1166 case '8':
1167 case '9':
1168 return (parse_unresolved_name(first, last, db));
1169 }
1170
1171 return (first);
1172 }
1173
1174 static const char *
1175 parse_binary_expr(const char *first, const char *last, const char *op,
1176 cpp_db_t *db)
1177 {
1178 ASSERT3P(first, <=, last);
1179
1180 if (last - first < 2)
1181 return (first);
1182
1183 size_t n = nlen(db);
1184
1185 const char *t1 = parse_expression(first + 2, last, db);
1186 if (t1 == first + 2)
1187 return (first);
1188
1189 nadd_l(db, op, 0);
1190
1191 const char *t2 = parse_expression(t1, last, db);
1192 if (t2 == t1)
1193 return (first);
1194
1195 if (NAMT(db, n) != 3)
1196 return (first);
1197
1198 ASSERT3U(nlen(db), >, 2);
1199
1200 nfmt(db, "({2}) {1} ({0})", NULL);
1201 if (strcmp(op, ">") == 0)
1202 nfmt(db, "({0})", NULL);
1203
1204 return (t2);
1205 }
1206
1207 static const char *
1208 parse_prefix_expr(const char *first, const char *last, const char *op,
1209 cpp_db_t *db)
1210 {
1211 ASSERT3P(first, <=, last);
1212
1213 if (last - first < 2)
1214 return (first);
1215
1216 nadd_l(db, op, 0);
1217
1218 const char *t = parse_expression(first + 2, last, db);
1219 if (t == first + 2) {
1220 return (first);
1221 }
1222
1223 ASSERT3U(nlen(db), >, 1);
1224
1225 nfmt(db, "{1}({0})", NULL);
1226 return (t);
1227 }
1228
1229 static const char *
1230 parse_gs(const char *first, const char *last, cpp_db_t *db)
1231 {
1232 ASSERT3P(first, <=, last);
1233
1234 const char *t = NULL;
1235
1236 if (last - first < 4)
1237 return (first);
1238
1239 if (first[2] == 'n' && (first[3] == 'a' || first[3] == 'w'))
1240 t = parse_new_expr(first + 2, last, db);
1241 else if (first[2] == 'd' && (first[3] == 'l' || first[3] == 'a'))
1242 t = parse_del_expr(first + 2, last, db);
1243 else
1244 return (first);
1245
1246 if (t == first + 2)
1247 return (first);
1248
1249 ASSERT3U(nlen(db), >, 0);
1250
1251 nfmt(db, "::{0}", NULL);
1252 return (t);
1253 }
1254
1255 /*
1256 * [gs] nw <expression>* _ <type> E # new (expr-list) type
1257 * [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1258 * [gs] na <expression>* _ <type> E # new[] (expr-list) type
1259 * [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1260 * <initializer> ::= pi <expression>* E # parenthesized initialization
1261 */
1262 static const char *
1263 parse_new_expr(const char *first, const char *last, cpp_db_t *db)
1264 {
1265 ASSERT3P(first, <=, last);
1266
1267 /* note [gs] is already handled by parse_gs() */
1268 if (last - first < 3)
1269 return (first);
1270
1271 ASSERT3U(first[0], ==, 'n');
1272 ASSERT(first[1] == 'a' || first[1] == 'w');
1273
1274 const char *t1 = first + 2;
1275 const char *t2 = NULL;
1276 size_t n = nlen(db);
1277
1278 nadd_l(db, (first[1] == 'w') ? "new" : "new[]", 0);
1279
1280 while (t1 != last && t1[0] != '_') {
1281 t2 = parse_expression(t1, last, db);
1282 ASSERT3P(t2, !=, NULL);
1283 if (t2 == t1)
1284 return (first);
1285 t1 = t2;
1286 }
1287 if (t1 == last)
1288 return (first);
1289
1290 if (NAMT(db, n) > 1) {
1291 njoin(db, NAMT(db, n) - 1, ", ");
1292 nfmt(db, "({0})", NULL);
1293 }
1294
1295 t2 = parse_type(t1 + 1, last, db);
1296 if (t1 + 1 == t2)
1297 return (first);
1298
1299 if (t2[0] != 'E') {
1300 if (last - t2 < 3)
1301 return (first);
1302 if (t2[0] != 'p' && t2[1] != 'i')
1312 if (t2 == t3)
1313 return (first);
1314 t2 = t3;
1315 }
1316 if (t3 == last || t3[0] != 'E')
1317 return (first);
1318
1319 if (NAMT(db, n1) > 0) {
1320 njoin(db, NAMT(db, n1), ", ");
1321 nfmt(db, "({0})", NULL);
1322 }
1323 }
1324
1325 njoin(db, NAMT(db, n), " ");
1326 return (t2 + 1);
1327 }
1328
1329 static const char *
1330 parse_del_expr(const char *first, const char *last, cpp_db_t *db)
1331 {
1332 ASSERT3P(first, <=, last);
1333
1334 if (last - first < 3)
1335 return (first);
1336
1337 ASSERT3U(first[0], ==, 'd');
1338 ASSERT(first[1] == 'l' || first[1] == 'a');
1339
1340 size_t n = nlen(db);
1341 const char *t = parse_expression(first + 2, last, db);
1342 if (t == first + 2 || NAMT(db, n) != 1)
1343 return (first);
1344
1345 nfmt(db, (first[1] == 'a') ? "delete[] {0}" : "delete {0}", NULL);
1346 return (t);
1347 }
1348
1349 static const char *
1350 parse_idx_expr(const char *first, const char *last, cpp_db_t *db)
1351 {
1352 ASSERT3P(first, <=, last);
1353 ASSERT3U(first[0], ==, 'i');
1354 ASSERT3U(first[1], ==, 'x');
1355
1356 size_t n = nlen(db);
1357 const char *t1 = parse_expression(first + 2, last, db);
1358 if (t1 == first + 2)
1359 return (first);
1360
1361 const char *t2 = parse_expression(t1, last, db);
1362 if (t2 == t1 || NAMT(db, n) != 2)
1363 return (first);
1364
1365 nfmt(db, "({0})[{1}]", NULL);
1366 return (t2);
1367 }
1368
1369 static const char *
1370 parse_ppmm_expr(const char *first, const char *last, const char *fmt,
1371 cpp_db_t *db)
1372 {
1373 ASSERT3P(first, <=, last);
1374
1375 if (last - first < 3)
1376 return (first);
1377
1378 const char *t = NULL;
1379 size_t n = nlen(db);
1380
1381 if (first[2] == '_') {
1382 t = parse_binary_expr(first + 3, last, "--", db);
1383 if (t == first + 3)
1384 return (first);
1385 return (t);
1386 }
1387
1388 t = parse_expression(first + 2, last, db);
1389 if (t == first + 2 || NAMT(db, n) < 1)
1390 return (first);
1391
1392 nfmt(db, fmt, NULL);
1393 return (t);
1394 }
1395
1396 static const char *
1397 parse_mm_expr(const char *first, const char *last, cpp_db_t *db)
1398 {
1399 ASSERT3P(first, <=, last);
1400 ASSERT3U(first[0], ==, 'm');
1401 ASSERT3U(first[1], ==, 'm');
1402
1403 return (parse_ppmm_expr(first, last, "({0})--", db));
1404 }
1405
1406 static const char *
1407 parse_pp_expr(const char *first, const char *last, cpp_db_t *db)
1408 {
1409 ASSERT3P(first, <=, last);
1410
1411 ASSERT3U(first[0], ==, 'p');
1412 ASSERT3U(first[0], ==, 'p');
1413
1414 return (parse_ppmm_expr(first, last, "({0})++", db));
1415 }
1416
1417 static const char *
1418 parse_trinary_expr(const char *first, const char *last, cpp_db_t *db)
1419 {
1420 ASSERT3P(first, <=, last);
1421
1422 const char *t1, *t2, *t3;
1423 size_t n = nlen(db);
1424
1425 if (last - first < 2)
1426 return (first);
1427
1428 t1 = parse_expression(first + 2, last, db);
1429 if (t1 == first + 2)
1430 return (first);
1431 t2 = parse_expression(t1, last, db);
1432 if (t1 == t2)
1433 return (first);
1434 t3 = parse_expression(t2, last, db);
1435 if (t3 == t2)
1436 return (first);
1437
1438 if (NAMT(db, n) != 3)
1439 return (first);
1440
1441 nfmt(db, "({2}) ? ({1}) : ({0})", NULL);
1442 return (t3);
1443 }
1444
1445 static const char *
1446 parse_noexcept_expr(const char *first, const char *last, cpp_db_t *db)
1447 {
1448 ASSERT3P(first, <=, last);
1449
1450 if (last - first < 2)
1451 return (first);
1452
1453 size_t n = nlen(db);
1454 const char *t = parse_expression(first + 2, last, db);
1455 if (t == first + 2 || NAMT(db, n) != 1)
1456 return (first);
1457
1458 nfmt(db, "noexcept ({0})", NULL);
1459 return (t);
1460 }
1461
1462 /*
1463 * cc <type> <expression> # const_cast<type> (expression)
1464 * dc <type> <expression> # dynamic_cast<type> (expression)
1465 * rc <type> <expression> # reinterpret_cast<type> (expression)
1466 * sc <type> <expression> # static_cast<type> (expression)
1467 */
1468 static const char *
1469 parse_cast_expr(const char *first, const char *last, cpp_db_t *db)
1470 {
1471 ASSERT3P(first, <=, last);
1472
1473 if (last - first < 2)
1474 return (first);
1475
1476 const char *fmt = NULL;
1477 switch (first[0]) {
1478 case 'c':
1479 fmt = "const_cast<{1}> ({0})";
1480 break;
1481 case 'd':
1482 fmt = "dynamic_cast<{1}> ({0})";
1483 break;
1484 case 'r':
1485 fmt = "reinterpret_cast<{1}> ({0})";
1486 break;
1487 case 's':
1488 fmt = "static_cast<{1}> ({0})";
1489 break;
1490 default:
1491 return (first);
1492 }
1493
1494 ASSERT3U(first[1], ==, 'c');
1495
1496 const char *t1 = parse_type(first + 2, last, db);
1497 if (t1 == first + 2)
1498 return (first);
1499
1500 const char *t2 = parse_expression(t1, last, db);
1501 if (t2 == t1)
1502 return (first);
1503
1504 ASSERT3U(nlen(db), >, 1);
1505
1506 nfmt(db, fmt, NULL);
1507 return (t2);
1508 }
1509
1510 /* pt <expression> <expression> # expr->name */
1511 static const char *
1512 parse_arrow_expr(const char *first, const char *last, cpp_db_t *db)
1513 {
1514 ASSERT3P(first, <=, last);
1515
1516 if (last - first < 4)
1517 return (first);
1518
1519 size_t n = nlen(db);
1520
1521 const char *t1 = parse_expression(first + 2, last, db);
1522 if (t1 == first + 2)
1523 return (first);
1524
1525 const char *t2 = parse_expression(t1, last, db);
1526 if (t2 == t1 || NAMT(db, n) != 2)
1527 return (first);
1528
1529 nfmt(db, "{1}->{0}", NULL);
1530 return (t2);
1531 }
1532
1533 /* wrap value in () when necessary */
1534 static void
1559 * ::= <decltype>
1560 * ::= <substitution>
1561 * ::= <CV-qualifiers> <type>
1562 * ::= P <type> # pointer-to
1563 * ::= R <type> # reference-to
1564 * ::= O <type> # rvalue reference-to (C++0x)
1565 * ::= C <type> # complex pair (C 2000)
1566 * ::= G <type> # imaginary (C 2000)
1567 * ::= Dp <type> # pack expansion (C++0x)
1568 * ::= U <source-name> <type> # vendor extended type qualifier
1569 * extension := U <objc-name> <objc-type> # objc-type<identifier>
1570 * extension := <vector-type> # <vector-type> starts with Dv
1571 *
1572 * <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1573 * <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1574 */
1575 /* END CSTYLED */
1576 static const char *
1577 parse_type(const char *first, const char *last, cpp_db_t *db)
1578 {
1579 ASSERT3P(first, <=, last);
1580
1581 if (first == last)
1582 return (first);
1583
1584 switch (first[0]) {
1585 case 'r':
1586 case 'V':
1587 case 'K':
1588 return (parse_qual_type(first, last, db));
1589 }
1590
1591 const char *t = first;
1592 const char *t1 = NULL;
1593 str_pair_t *sp = NULL;
1594 size_t n = nlen(db);
1595 size_t amt = 0;
1596
1597 t = parse_builtin_type(first, last, db);
1598 if (t != first)
1599 return (t);
1726
1727 nfmt(db, "{0}", NULL);
1728
1729 t1 = parse_type(t, last, db);
1730 if (t1 == t || NAMT(db, n) < 2)
1731 return (first);
1732
1733 const str_t *name = &name_at(&db->cpp_name, 1)->strp_l;
1734
1735 if (str_length(name) > 0 &&
1736 strncmp(name->str_s, "objcproto", 9) != 0) {
1737 nfmt(db, "{0} {1}", NULL);
1738 } else {
1739 t = parse_source_name(name->str_s + 9,
1740 name->str_s + name->str_len, db);
1741 if (t != name->str_s + 9) {
1742 nfmt(db, "{1}<{0}>", NULL);
1743
1744 str_pair_t save = {0};
1745
1746 (void) name_pop(&db->cpp_name, &save);
1747
1748 /* get rid of 'objcproto' */
1749 (void) name_pop(&db->cpp_name, NULL);
1750 CK(name_add_str(&db->cpp_name, &save.strp_l,
1751 &save.strp_r));
1752 } else {
1753 nfmt(db, "{1} {0}", NULL);
1754 }
1755 }
1756
1757 save_top(db, 1);
1758 return (t1);
1759
1760 case 'S':
1761 if (first + 1 != last && first[1] == 't') {
1762 t = parse_name(first, last, NULL, db);
1763 if (t == first || NAMT(db, n) == 0)
1764 return (first);
1765
1766 save_top(db, 1);
1767 return (t);
1768 }
1769
1824
1825 /*
1826 * must check for builtin-types before class-enum-types to avoid
1827 * ambiguities with operator-names
1828 */
1829 t = parse_builtin_type(first, last, db);
1830 if (t != first)
1831 return (t);
1832
1833 t = parse_name(first, last, NULL, db);
1834 if (t == first || NAMT(db, n) == 0)
1835 return (first);
1836
1837 save_top(db, 1);
1838 return (t);
1839 }
1840
1841 static const char *
1842 parse_qual_type(const char *first, const char *last, cpp_db_t *db)
1843 {
1844 ASSERT3P(first, <=, last);
1845
1846 const char *t = NULL;
1847 const char *t1 = NULL;
1848 unsigned cv = 0;
1849
1850 t = parse_cv_qualifiers(first, last, &cv);
1851 if (t == first)
1852 return (first);
1853
1854 size_t n = nlen(db);
1855 boolean_t is_func = !!(t[0] == 'F');
1856
1857 t1 = parse_type(t, last, db);
1858 size_t amt = NAMT(db, n);
1859 if (t == t1 || amt == 0)
1860 return (first);
1861
1862 if (is_func)
1863 sub_pop(&db->cpp_subs);
1864
1899 if (cv & 2) {
1900 str_insert(s, pos, " volatile", 9);
1901 pos += 9;
1902 }
1903 if (cv & 4) {
1904 str_insert(s, pos, " restrict", 9);
1905 }
1906 }
1907
1908 save_top(db, amt);
1909 return (t1);
1910 }
1911
1912 /*
1913 * at <type> # alignof (a type)
1914 * az <expression> # alignof (a expression)
1915 */
1916 static const char *
1917 parse_alignof(const char *first, const char *last, cpp_db_t *db)
1918 {
1919 ASSERT3P(first, <=, last);
1920
1921 if (last - first < 2)
1922 return (first);
1923
1924 const char *(*fn)(const char *, const char *, cpp_db_t *);
1925
1926 fn = (first[1] == 't') ? parse_type : parse_expression;
1927
1928 size_t n = nlen(db);
1929 const char *t = fn(first + 2, last, db);
1930 if (t == first + 2 || NAMT(db, n) != 1)
1931 return (first);
1932
1933 nfmt(db, "alignof ({0})", NULL);
1934 return (t);
1935 }
1936
1937 /*
1938 * st <type> # sizeof (a type)
1939 * sz <expr> # sizeof (a expression)
1940 */
1941 static const char *
1942 parse_sizeof(const char *first, const char *last, cpp_db_t *db)
1943 {
1944 ASSERT3P(first, <=, last);
1945
1946 if (last - first < 2)
1947 return (first);
1948
1949 ASSERT3U(first[0], ==, 's');
1950
1951 const char *t = NULL;
1952 size_t n = nlen(db);
1953
1954 switch (first[1]) {
1955 case 't':
1956 t = parse_type(first + 2, last, db);
1957 break;
1958 case 'z':
1959 t = parse_expression(first + 2, last, db);
1960 break;
1961 default:
1962 return (first);
1963 }
1964 if (t == first + 2 || NAMT(db, n) != 1)
1965 return (first);
1966
1967 nfmt(db, "sizeof ({0})", NULL);
1968 return (t);
1969 }
1970
1971 /* BEGIN CSTYLED */
1972 /*
1973 * <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
1974 * ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
1975 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter
1976 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
1977 */
1978 /* END CSTYLED */
1979 static const char *
1980 parse_function_param(const char *first, const char *last, cpp_db_t *db)
1981 {
1982 ASSERT3P(first, <=, last);
1983
1984 if (last - first < 3 || first[0] != 'f')
1985 return (first);
1986
1987 const char *t1 = first + 2;
1988 const char *t2 = NULL;
1989 unsigned cv = 0;
1990
1991 if (first[1] == 'L') {
1992 t2 = parse_number(t1, last);
1993 if (t2 == last || t2[0] != 'p')
1994 return (first);
1995 t1 = t2;
1996 }
1997
1998 if (first[1] != 'p')
1999 return (first);
2000
2001 t1 = parse_cv_qualifiers(t1, last, &cv);
2002 t2 = parse_number(t1, last);
2003 if (t2 == last || t2[0] != '_')
2004 return (first);
2005
2006 if (t2 - t1 > 0)
2007 nadd_l(db, t1, (size_t)(t2 - t1));
2008 else
2009 nadd_l(db, "", 0);
2010
2011 nfmt(db, "fp{0}", NULL);
2012 return (t2 + 1);
2013 }
2014
2015 /*
2016 * sZ <template-param> # size of a parameter pack
2017 * sZ <function-param> # size of a function parameter pack
2018 */
2019 static const char *
2020 parse_sizeof_param_pack_expr(const char *first, const char *last, cpp_db_t *db)
2021 {
2022 ASSERT3P(first, <=, last);
2023
2024 if (last - first < 3)
2025 return (first);
2026
2027 ASSERT3U(first[0], ==, 's');
2028 ASSERT3U(first[1], ==, 'Z');
2029
2030 if (first[2] != 'T' && first[2] != 'f')
2031 return (first);
2032
2033 const char *t = NULL;
2034 size_t n = nlen(db);
2035
2036 if (first[2] == 'T')
2037 t = parse_template_param(first + 2, last, db);
2038 else
2039 t = parse_function_param(first + 2, last, db);
2040
2041 if (t == first + 2)
2042 return (first);
2043
2044 njoin(db, NAMT(db, n), ", ");
2045 nfmt(db, "sizeof...({0})", NULL);
2046 return (t);
2047 }
2048
2049 /*
2050 * te <expression> # typeid (expression)
2051 * ti <type> # typeid (type)
2052 */
2053 static const char *
2054 parse_typeid_expr(const char *first, const char *last, cpp_db_t *db)
2055 {
2056 ASSERT3P(first, <=, last);
2057
2058 if (last - first < 3)
2059 return (first);
2060
2061 ASSERT3U(first[0], ==, 't');
2062 ASSERT(first[1] == 'e' || first[1] == 'i');
2063
2064 const char *t = NULL;
2065 size_t n = nlen(db);
2066
2067 if (first[1] == 'e')
2068 t = parse_expression(first + 2, last, db);
2069 else
2070 t = parse_type(first + 2, last, db);
2071
2072 if (t == first + 2 || NAMT(db, n) != 1)
2073 return (first);
2074
2075 nfmt(db, "typeid ({0})", NULL);
2076 return (t);
2077 }
2078
2079 /*
2080 * tr # throw
2081 * tw <expression> # throw expression
2082 */
2083 static const char *
2084 parse_throw_expr(const char *first, const char *last, cpp_db_t *db)
2085 {
2086 ASSERT3P(first, <=, last);
2087
2088 if (last - first < 3)
2089 return (first);
2090
2091 ASSERT3U(first[0], ==, 't');
2092 ASSERT(first[1] == 'w' || first[1] == 'r');
2093
2094 if (first[1] == 'r') {
2095 nadd_l(db, "throw", 0);
2096 return (first + 2);
2097 }
2098
2099 size_t n = nlen(db);
2100 const char *t = parse_expression(first + 2, last, db);
2101 if (t == first + 2 || NAMT(db, n) != 1)
2102 return (first);
2103
2104 nfmt(db, "throw {0}", NULL);
2105 return (t);
2106 }
2107
2108 /* ds <expression> <expression> # expr.*expr */
2109 static const char *
2110 parse_dot_star_expr(const char *first, const char *last, cpp_db_t *db)
2111 {
2112 ASSERT3P(first, <=, last);
2113
2114 if (last - first < 3)
2115 return (first);
2116
2117 ASSERT3U(first[0], ==, 'd');
2118 ASSERT3U(first[1], ==, 's');
2119
2120 size_t n = nlen(db);
2121 const char *t = parse_expression(first + 2, last, db);
2122 if (t == first + 2)
2123 return (first);
2124
2125 const char *t2 = parse_expression(t, last, db);
2126 if (t == t2 || NAMT(db, n) != 2)
2127 return (first);
2128
2129 nfmt(db, "{1}.*{0}", NULL);
2130 return (t2);
2131 }
2132
2133 /* dt <expression> <unresolved-name> # expr.name */
2134 static const char *
2135 parse_dot_expr(const char *first, const char *last, cpp_db_t *db)
2136 {
2137 ASSERT3P(first, <=, last);
2138
2139 if (last - first < 3)
2140 return (first);
2141
2142 ASSERT3U(first[0], ==, 'd');
2143 ASSERT3U(first[1], ==, 't');
2144
2145 const char *t = parse_expression(first + 2, last, db);
2146 if (t == first + 2)
2147 return (first);
2148
2149 const char *t1 = parse_unresolved_name(t, last, db);
2150 if (t1 == t)
2151 return (first);
2152
2153 nfmt(db, "{1}.{0}", NULL);
2154 return (t1);
2155 }
2156
2157 /* cl <expression>+ E # call */
2158 static const char *
2159 parse_call_expr(const char *first, const char *last, cpp_db_t *db)
2160 {
2161 ASSERT3P(first, <=, last);
2162
2163 if (last - first < 4)
2164 return (first);
2165
2166 ASSERT3U(first[0], ==, 'c');
2167 ASSERT3U(first[1], ==, 'l');
2168
2169 const char *t = first + 2;
2170 const char *t1 = NULL;
2171 size_t n = nlen(db);
2172
2173 for (t = first + 2; t != last && t[0] != 'E'; t = t1) {
2174 t1 = parse_expression(t, last, db);
2175 if (t1 == t)
2176 return (first);
2177 }
2178
2179 size_t amt = NAMT(db, n);
2180
2181 if (t == last || amt == 0)
2182 return (first);
2183
2184 njoin(db, amt - 1, ", ");
2185 nfmt(db, "{1}({0})", NULL);
2186
2187 ASSERT3U(t[0], ==, 'E');
2188 return (t + 1);
2189 }
2190
2191 /* BEGIN CSTYLED */
2192 /*
2193 * cv <type> <expression> # conversion with one argument
2194 * cv <type> _ <expression>* E # conversion with a different number of arguments
2195 */
2196 /* END CSTYLED */
2197 static const char *
2198 parse_conv_expr(const char *first, const char *last, cpp_db_t *db)
2199 {
2200 ASSERT3P(first, <=, last);
2201
2202 if (last - first < 3)
2203 return (first);
2204
2205 ASSERT3U(first[0], ==, 'c');
2206 ASSERT3U(first[1], ==, 'v');
2207
2208 const char *t = NULL;
2209 const char *t1 = NULL;
2210 size_t n = nlen(db);
2211
2212 boolean_t try_to_parse_template_args =
2213 db->cpp_try_to_parse_template_args;
2214
2215 db->cpp_try_to_parse_template_args = B_FALSE;
2216 t = parse_type(first + 2, last, db);
2217 db->cpp_try_to_parse_template_args = try_to_parse_template_args;
2218
2219 if (t == first + 2)
2220 return (first);
2221
2222 if (t[0] != '_') {
2223 t1 = parse_expression(t, last, db);
2224 if (t1 == t)
2225 return (first);
2226
2237 t1 = t;
2238 }
2239
2240 /* E */
2241 t++;
2242
2243 njoin(db, NAMT(db, n1), ", ");
2244 }
2245
2246 if (NAMT(db, n) < 2)
2247 return (first);
2248
2249 nfmt(db, "({1})({0})", NULL);
2250 return (t);
2251 }
2252
2253 /* <simple-id> ::= <source-name> [ <template-args> ] */
2254 static const char *
2255 parse_simple_id(const char *first, const char *last, cpp_db_t *db)
2256 {
2257 ASSERT3P(first, <=, last);
2258
2259 const char *t = parse_source_name(first, last, db);
2260 if (t == first)
2261 return (t);
2262
2263 const char *t1 = parse_template_args(t, last, db);
2264 if (t == t1)
2265 return (t);
2266
2267 nfmt(db, "{1}{0}", NULL);
2268 return (t1);
2269 }
2270
2271 /*
2272 * <unresolved-type> ::= <template-param>
2273 * ::= <decltype>
2274 * ::= <substitution>
2275 */
2276 static const char *
2277 parse_unresolved_type(const char *first, const char *last, cpp_db_t *db)
2278 {
2279 ASSERT3P(first, <=, last);
2280
2281 if (first == last)
2282 return (first);
2283
2284 const char *t = first;
2285 size_t n = nlen(db);
2286
2287 switch (first[0]) {
2288 case 'T':
2289 t = parse_template_param(first, last, db);
2290 if (t == first || NAMT(db, n) != 1) {
2291 for (size_t i = 0; i < NAMT(db, n); i++)
2292 (void) name_pop(&db->cpp_name, NULL);
2293 return (first);
2294 }
2295 save_top(db, 1);
2296 return (t);
2297
2298 case 'D':
2299 t = parse_decltype(first, last, db);
2300 if (t == first || NAMT(db, n) == 0)
2301 return (first);
2302 save_top(db, 1);
2303 return (t);
2304
2305 case 'S':
2306 t = parse_substitution(first, last, db);
2307 if (t != first)
2308 return (t);
2309
2310 if (last - first < 2 || first[1] != 't')
2311 return (first);
2312
2313 t = parse_unqualified_name(first + 2, last, db);
2314 if (t == first + 2 || NAMT(db, n) == 0)
2315 return (first);
2316
2317 nfmt(db, "std::{0:L}", "{0:R}");
2318 save_top(db, 1);
2319 return (t);
2320 }
2321
2322 return (first);
2323 }
2324
2325 /* sp <expression> # pack expansion */
2326 static const char *
2327 parse_pack_expansion(const char *first, const char *last, cpp_db_t *db)
2328 {
2329 ASSERT3P(first, <=, last);
2330
2331 if (last - first < 3)
2332 return (first);
2333
2334 ASSERT3U(first[0], ==, 's');
2335 ASSERT3U(first[1], ==, 'p');
2336
2337 const char *t = parse_expression(first + 2, last, db);
2338 if (t == first +2)
2339 return (first);
2340
2341 return (t);
2342 }
2343
2344 /*
2345 * <unscoped-name> ::= <unqualified-name>
2346 * ::= St <unqualified-name> # ::std::
2347 * extension ::= StL<unqualified-name>
2348 */
2349 static const char *
2350 parse_unscoped_name(const char *first, const char *last, cpp_db_t *db)
2351 {
2352 ASSERT3P(first, <=, last);
2353
2354 if (last - first < 2)
2355 return (first);
2356
2357 const char *t = first;
2358 const char *t1 = NULL;
2359 boolean_t st = B_FALSE;
2360
2361 if (first[0] == 'S' && first[1] == 't') {
2362 st = B_TRUE;
2363 t = first + 2;
2364
2365 if (first + 3 != last && first[2] == 'L')
2366 t++;
2367 }
2368
2369 t1 = parse_unqualified_name(t, last, db);
2370 if (t == t1)
2371 return (first);
2372
2373 if (st)
2374 nfmt(db, "std::{0}", NULL);
2375
2376 return (t1);
2377 }
2378
2379 /*
2380 * <unqualified-name> ::= <operator-name>
2381 * ::= <ctor-dtor-name>
2382 * ::= <source-name>
2383 * ::= <unnamed-type-name>
2384 */
2385 const char *
2386 parse_unqualified_name(const char *first, const char *last, cpp_db_t *db)
2387 {
2388 ASSERT3P(first, <=, last);
2389
2390 if (first == last)
2391 return (first);
2392
2393 switch (*first) {
2394 case 'C':
2395 case 'D':
2396 return (parse_ctor_dtor_name(first, last, db));
2397 case 'U':
2398 return (parse_unnamed_type_name(first, last, db));
2399
2400 case '1':
2401 case '2':
2402 case '3':
2403 case '4':
2404 case '5':
2405 case '6':
2406 case '7':
2407 case '8':
2408 case '9':
2409 return (parse_source_name(first, last, db));
2410 default:
2411 return (parse_operator_name(first, last, db));
2412 }
2413 }
2414
2415 /*
2416 * <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
2417 * ::= <closure-type-name>
2418 *
2419 * <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2420 *
2421 * <lambda-sig> ::= <parameter type>+
2422 * # Parameter types or "v" if the lambda has no parameters
2423 */
2424 static const char *
2425 parse_unnamed_type_name(const char *first, const char *last, cpp_db_t *db)
2426 {
2427 ASSERT3P(first, <=, last);
2428
2429 if (last - first < 2 || first[0] != 'U')
2430 return (first);
2431
2432 if (first[1] != 't' && first[1] != 'l')
2433 return (first);
2434
2435 const char *t1 = first + 2;
2436 const char *t2 = NULL;
2437
2438 if (first[1] == 't') {
2439 while (t1 != last && t1[0] != '_' && is_digit(t1[0]))
2440 t1++;
2441
2442 if (t1[0] != '_')
2443 return (first);
2444
2445 if (t1 == first + 2)
2446 nadd_l(db, "", 0);
2447 else
2448 nadd_l(db, first + 2, (size_t)(t1 - first - 2));
2449
2450 nfmt(db, "'unnamed{0}'", NULL);
2451 return (t1 + 1);
2452 }
2453
2454 size_t n = nlen(db);
2455
2456 if (first[2] != 'v') {
2457 do {
2458 t2 = parse_type(t1, last, db);
2459 if (t1 == t2)
2462 } while (t1 != last && t1[0] != 'E');
2463
2464 if (t1 == last || NAMT(db, n) < 1)
2465 return (first);
2466
2467 if (NAMT(db, n) < 1)
2468 return (first);
2469 } else {
2470 t1++;
2471 if (t1[0] != 'E')
2472 return (first);
2473 }
2474
2475 njoin(db, NAMT(db, n), ", ");
2476
2477 /* E */
2478 t1++;
2479
2480 t2 = t1;
2481 while (t2 != last && t2[0] != '_') {
2482 if (!is_digit(*t2++))
2483 return (first);
2484 }
2485
2486 if (t2[0] != '_')
2487 return (first);
2488
2489 if (t2 - t1 > 0)
2490 nadd_l(db, t1, (size_t)(t2 - t1));
2491 else
2492 nadd_l(db, "", 0);
2493
2494 nfmt(db, "'lambda{0}'({1})", NULL);
2495
2496 /* _ */
2497 return (t2 + 1);
2498 }
2499
2500 static struct {
2501 const char *alias;
2502 const char *fullname;
2555 */
2556 unsigned c = 0;
2557
2558 if (end[-1] == '>') {
2559 for (; end > start; end--) {
2560 switch (end[-1]) {
2561 case '<':
2562 if (--c == 0) {
2563 end--;
2564 goto out;
2565 }
2566 break;
2567 case '>':
2568 c++;
2569 break;
2570 }
2571 }
2572 }
2573
2574 out:
2575 ASSERT3P(end, >=, start);
2576
2577 if (end - start < 2) {
2578 nadd_l(db, "", 0);
2579 return;
2580 }
2581
2582 for (start = end - 1; start > s->str_s; start--) {
2583 if (start[0] == ':') {
2584 start++;
2585 break;
2586 }
2587 }
2588
2589 ASSERT3P(end, >=, start);
2590
2591 nadd_l(db, start, (size_t)(end - start));
2592 }
2593
2594 /*
2595 * <ctor-dtor-name> ::= C1 # complete object constructor
2596 * ::= C2 # base object constructor
2597 * ::= C3 # complete object allocating constructor
2598 * extension ::= C5 # ?
2599 * ::= D0 # deleting destructor
2600 * ::= D1 # complete object destructor
2601 * ::= D2 # base object destructor
2602 * extension ::= D5 # ?
2603 */
2604 static const char *
2605 parse_ctor_dtor_name(const char *first, const char *last, cpp_db_t *db)
2606 {
2607 ASSERT3P(first, <=, last);
2608
2609 if (last - first < 2 || nempty(db) || str_length(TOP_L(db)) == 0)
2610 return (first);
2611
2612 switch (first[0]) {
2613 case 'C':
2614 switch (first[1]) {
2615 case '1':
2616 case '2':
2617 case '3':
2618 case '5':
2619 basename(db);
2620 break;
2621 default:
2622 return (first);
2623 }
2624 break;
2625 case 'D':
2626 switch (first[1]) {
2627 case '0':
2630 case '5':
2631 basename(db);
2632 str_insert(TOP_L(db), 0, "~", 1);
2633 break;
2634 default:
2635 return (first);
2636 }
2637 break;
2638 default:
2639 return (first);
2640 }
2641
2642 db->cpp_parsed_ctor_dtor_cv = B_TRUE;
2643 return (first + 2);
2644 }
2645
2646 static const char *
2647 parse_integer_literal(const char *first, const char *last, const char *fmt,
2648 cpp_db_t *db)
2649 {
2650 ASSERT3P(first, <=, last);
2651
2652 const char *t = parse_number(first, last);
2653 const char *start = first;
2654
2655 if (t == first || t == last || t[0] != 'E')
2656 return (first);
2657
2658 if (first[0] == 'n')
2659 start++;
2660
2661 nadd_l(db, start, (size_t)(t - start));
2662 if (start != first)
2663 nfmt(db, "-{0}", NULL);
2664
2665 nfmt(db, fmt, NULL);
2666 return (t + 1);
2667 }
2668
2669 static struct float_data_s {
2670 const char *spec;
2671 size_t mangled_size;
2672 size_t max_demangled_size;
2673 char type;
2674 } float_info[] = {
2675 { "%af", 8, 24, 'f' }, /* float */
2676 { "%a", 16, 32, 'd' }, /* double */
2677 { "%LaL", 20, 40, 'e' } /* long double */
2678 };
2679
2680 static const char *
2681 parse_floating_literal(const char *first, const char *last, cpp_db_t *db)
2682 {
2683 ASSERT3P(first, <=, last);
2684 ASSERT(first[0] == 'f' || first[0] == 'd' || first[0] == 'e');
2685
2686 const struct float_data_s *fd = NULL;
2687
2688 for (size_t i = 0; i < ARRAY_SIZE(float_info); i++) {
2689 if (float_info[i].type != first[0])
2690 continue;
2691
2692 fd = &float_info[i];
2693 break;
2694 }
2695
2696 if (fd == NULL || (size_t)(last - first) < fd->mangled_size)
2697 return (first);
2698
2699 union {
2700 union {
2701 float v;
2702 char buf[sizeof (float)];
2703 } f;
2704 union {
2715 char *e = NULL;
2716
2717 switch (first[0]) {
2718 case 'f':
2719 e = conv.f.buf;
2720 break;
2721 case 'd':
2722 e = conv.d.buf;
2723 break;
2724 case 'e':
2725 e = conv.ld.buf;
2726 break;
2727 }
2728 last = first + fd->mangled_size + 1;
2729
2730 #if defined(_BIG_ENDIAN)
2731 for (t = first + 1; t != last; t++, e++) {
2732 if (!is_xdigit(t[0]))
2733 return (first);
2734
2735 unsigned d1 = is_digit(t[0]) ? t[0] - '0' : t[0] - 'a' + 10;
2736 t++;
2737 unsigned d0 = is_digit(t[0]) ? t[0] - '0' : t[0] - 'a' + 10;
2738
2739 *e = (d1 << 4) + d0;
2740 }
2741 #elif defined(_LITTLE_ENDIAN)
2742 for (t = last - 1; t > first; t--, e++) {
2743 if (!is_xdigit(t[0]))
2744 return (first);
2745
2746 unsigned d0 = is_digit(t[0]) ? t[0] - '0' : t[0] - 'a' + 10;
2747 t--;
2748 unsigned d1 = is_digit(t[0]) ? t[0] - '0' : t[0] - 'a' + 10;
2749
2750 *e = (d1 << 4) + d0;
2751 }
2752 t = last;
2753 #else
2754 #error One of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined
2755 #endif
2756
2757 if (t[0] != 'E')
2758 return (first);
2759
2760 str_t num = { 0 };
2761 str_init(&num, db->cpp_ops);
2762
2763 num.str_size = fd->max_demangled_size + 1;
2764 num.str_s = zalloc(db->cpp_ops, num.str_size);
2765 CK(num.str_s != NULL);
2766
2767 int n = 0;
2768
2809 } int_lits[] = {
2810 { 'a', "(signed char){0}" },
2811 { 'c', "(char){0}" },
2812 { 'h', "(unsigned char){0}" },
2813 { 'i', "{0}" },
2814 { 'j', "{0}u" },
2815 { 'l', "{0}l" },
2816 { 'm', "{0}ul" },
2817 { 'n', "(__int128){0}" },
2818 { 'o', "(unsigned __int128){0}" },
2819 { 's', "(short){0}" },
2820 { 't', "(unsigned short){0}" },
2821 { 'w', "(wchar_t){0}" },
2822 { 'x', "{0}ll" },
2823 { 'y', "{0}ull" }
2824 };
2825
2826 static const char *
2827 parse_expr_primary(const char *first, const char *last, cpp_db_t *db)
2828 {
2829 ASSERT3P(first, <=, last);
2830
2831 if (last - first < 4 || first[0] != 'L')
2832 return (first);
2833
2834 const char *t = NULL;
2835
2836 for (size_t i = 0; i < ARRAY_SIZE(int_lits); i++) {
2837 if (first[1] == int_lits[i].c) {
2838 t = parse_integer_literal(first + 2, last,
2839 int_lits[i].fmt, db);
2840 return ((t == first + 2) ? first : t);
2841 }
2842 }
2843
2844 switch (first[1]) {
2845 case 'b':
2846 if (first[3] != 'E')
2847 return (first);
2848
2849 switch (first[2]) {
2873 return (first);
2874 case '_':
2875 if (first[2] != 'Z')
2876 return (first);
2877
2878 t = parse_encoding(first + 3, last, db);
2879 if (t == first + 3 || t == last || t[0] != 'E')
2880 return (first);
2881
2882 /* skip E */
2883 return (t + 1);
2884 default:
2885 t = parse_type(first + 1, last, db);
2886 if (t == first + 1 || t == last)
2887 return (first);
2888
2889 if (t[0] == 'E')
2890 return (t + 1);
2891
2892 const char *n;
2893 for (n = t; n != last && is_digit(n[0]); n++)
2894 ;
2895 if (n == last || nempty(db) || n[0] != 'E')
2896 return (first);
2897 if (n == t)
2898 return (t);
2899
2900 nadd_l(db, t, (size_t)(n - t));
2901 nfmt(db, "({1}){0}", NULL);
2902
2903 return (n + 1);
2904 }
2905 }
2906
2907 /*
2908 * <operator-name>
2909 * ::= aa # &&
2910 * ::= ad # & (unary)
2911 * ::= an # &
2912 * ::= aN # &=
2913 * ::= aS # =
2996 { "nw", "operator new" },
2997 { "oo", "operator||" },
2998 { "or", "operator|" },
2999 { "oR", "operator|=" },
3000 { "pm", "operator->*" },
3001 { "pl", "operator+" },
3002 { "pL", "operator+=" },
3003 { "pp", "operator++" },
3004 { "ps", "operator+" },
3005 { "pt", "operator->" },
3006 { "qu", "operator?" },
3007 { "rm", "operator%" },
3008 { "rM", "operator%=" },
3009 { "rs", "operator>>" },
3010 { "rS", "operator>>=" }
3011 };
3012
3013 static const char *
3014 parse_operator_name(const char *first, const char *last, cpp_db_t *db)
3015 {
3016 ASSERT3P(first, <=, last);
3017
3018 if (last - first < 2)
3019 return (first);
3020
3021 for (size_t i = 0; i < ARRAY_SIZE(op_tbl); i++) {
3022 if (strncmp(first, op_tbl[i].code, 2) != 0)
3023 continue;
3024
3025 nadd_l(db, op_tbl[i].op, 0);
3026 return (first + 2);
3027 }
3028
3029 const char *t = NULL;
3030
3031 if (first[0] == 'l' && first[1] == 'i') {
3032 t = parse_source_name(first + 2, last, db);
3033 if (t == first + 2 || nempty(db))
3034 return (first);
3035
3036 nfmt(db, "operator\"\" {0}", NULL);
3037 return (t);
3038 }
3039
3040 if (first[0] == 'v') {
3041 if (!is_digit(first[1]))
3042 return (first);
3043
3044 t = parse_source_name(first + 2, last, db);
3045 if (t == first + 2)
3046 return (first);
3047
3048 nfmt(db, "operator {0}", NULL);
3049 return (t);
3050 }
3051
3052 if (first[0] != 'c' && first[1] != 'v')
3053 return (first);
3054
3055 boolean_t try_to_parse_template_args =
3056 db->cpp_try_to_parse_template_args;
3057
3058 db->cpp_try_to_parse_template_args = B_FALSE;
3059 t = parse_type(first + 2, last, db);
3060 db->cpp_try_to_parse_template_args = try_to_parse_template_args;
3061
3094 { 'x', "long long" },
3095 { 'y', "unsigned long long" },
3096 { 'z', "..." }
3097 };
3098
3099 static struct type_tbl_s type_tbl2[] = {
3100 { 'a', "auto" },
3101 { 'c', "decltype(auto)" },
3102 { 'd', "decimal64" },
3103 { 'e', "decimal128" },
3104 { 'f', "decimal32" },
3105 { 'h', "decimal16" },
3106 { 'i', "char32_t" },
3107 { 'n', "std::nullptr_t" },
3108 { 's', "char16_t" }
3109 };
3110
3111 static const char *
3112 parse_builtin_type(const char *first, const char *last, cpp_db_t *db)
3113 {
3114 ASSERT3P(first, <=, last);
3115
3116 if (first == last)
3117 return (first);
3118
3119 size_t i;
3120
3121 for (i = 0; i < ARRAY_SIZE(type_tbl1); i++) {
3122 if (first[0] == type_tbl1[i].code) {
3123 nadd_l(db, type_tbl1[i].name, 0);
3124 return (first + 1);
3125 }
3126 }
3127
3128 if (first[0] == 'D') {
3129 if (first + 1 == last)
3130 return (first);
3131 for (i = 0; i < ARRAY_SIZE(type_tbl2); i++) {
3132 if (first[1] == type_tbl2[i].code) {
3133 nadd_l(db, type_tbl2[i].name, 0);
3134 return (first + 2);
3135 }
3136 }
3137 }
3138
3139 if (first[0] == 'u') {
3140 const char *t = parse_source_name(first + 1, last, db);
3141 if (t == first + 1)
3142 return (first);
3143 return (t);
3144 }
3145
3146 return (first);
3147 }
3148
3149 static const char *
3150 parse_base36(const char *first, const char *last, size_t *val)
3151 {
3152 ASSERT3P(first, <=, last);
3153
3154 const char *t;
3155
3156 for (t = first, *val = 0; t != last; t++) {
3157 if (!is_digit(t[0]) && !is_upper(t[0]))
3158 return (t);
3159
3160 *val *= 36;
3161
3162 if (is_digit(t[0]))
3163 *val += t[0] - '0';
3164 else
3165 *val += t[0] - 'A' + 10;
3166 }
3167 return (t);
3168 }
3169
3170 static struct type_tbl_s sub_tbl[] = {
3171 { 'a', "std::allocator" },
3172 { 'b', "std::basic_string" },
3173 { 's', "std::string" },
3174 { 'i', "std::istream" },
3175 { 'o', "std::ostream" },
3176 { 'd', "std::iostream" }
3177 };
3178
3179 static const char *
3180 parse_substitution(const char *first, const char *last, cpp_db_t *db)
3181 {
3182 ASSERT3P(first, <=, last);
3183
3184 if (first == last || last - first < 2)
3185 return (first);
3186
3187 if (first[0] != 'S')
3188 return (first);
3189
3190 for (size_t i = 0; i < ARRAY_SIZE(sub_tbl); i++) {
3191 if (first[1] == sub_tbl[i].code) {
3192 nadd_l(db, sub_tbl[i].name, 0);
3193 return (first + 2);
3194 }
3195 }
3196
3197 const char *t = first + 1;
3198 size_t n = 0;
3199
3200 if (t[0] != '_') {
3201 t = parse_base36(first + 1, last, &n);
3202 if (t == first + 1 || t[0] != '_')
3203 return (first);
3204
3205 /*
3206 * S_ == substitution 0,
3207 * S0_ == substituion 1,
3208 * ...
3209 */
3210 n++;
3211 }
3212
3213 if (n >= sub_len(&db->cpp_subs))
3214 return (first);
3215
3216 sub(db, n);
3217
3218 /* skip _ */
3219 ASSERT3U(t[0], ==, '_');
3220
3221 return (t + 1);
3222 }
3223
3224 static const char *
3225 parse_source_name(const char *first, const char *last, cpp_db_t *db)
3226 {
3227 ASSERT3P(first, <=, last);
3228
3229 if (first == last)
3230 return (first);
3231
3232 const char *t = NULL;
3233 size_t n = 0;
3234
3235 for (t = first; t != last && is_digit(t[0]); t++) {
3236 /* make sure we don't overflow */
3237 size_t nn = n * 10;
3238 if (nn < n)
3239 return (first);
3240
3241 nn += t[0] - '0';
3242 if (nn < n)
3243 return (first);
3244
3245 n = nn;
3246 }
3247
3248 if (n == 0 || t == last || t + n > last ||
3249 (uintptr_t)t + n < (uintptr_t)t)
3250 return (first);
3251
3252 if (strncmp(t, "_GLOBAL__N", 10) == 0)
3253 nadd_l(db, "(anonymous namespace)", 0);
3254 else
3255 nadd_l(db, t, n);
3256
3257 return (t + n);
3258 }
3259
3260 /*
3261 * extension:
3262 * <vector-type> ::= Dv <positive dimension number> _
3263 * <extended element type>
3264 * ::= Dv [<dimension expression>] _ <element type>
3265 * <extended element type> ::= <element type>
3266 * ::= p # AltiVec vector pixel
3267 */
3268 static const char *
3269 parse_vector_type(const char *first, const char *last, cpp_db_t *db)
3270 {
3271 ASSERT3P(first, <=, last);
3272
3273 if (last - first < 3)
3274 return (first);
3275
3276 ASSERT3U(first[0], ==, 'D');
3277 ASSERT3U(first[1], ==, 'v');
3278
3279 const char *t = first + 2;
3280 const char *t1 = NULL;
3281
3282 if (is_digit(first[2]) && first[2] != '0') {
3283 t1 = parse_number(t, last);
3284 if (t1 == last || t1 + 1 == last || t1[0] != '_')
3285 return (first);
3286
3287 nadd_l(db, t, (size_t)(t1 - t));
3288
3289 /* skip _ */
3290 t = t1 + 1;
3291
3292 if (t[0] != 'p') {
3293 t1 = parse_type(t, last, db);
3294 if (t1 == t)
3295 return (first);
3296
3297 nfmt(db, "{0} vector[{1}]", NULL);
3298 return (t1);
3299 }
3300 nfmt(db, "{0} pixel vector[{1}]", NULL);
3301 return (t1);
3302 }
3303
3312 nadd_l(db, "", 0);
3313 }
3314
3315 t1 = parse_type(t, last, db);
3316 if (t == t1)
3317 return (first);
3318
3319 nfmt(db, "{1:L} vector[{0}]", "{1:R}");
3320 return (t1);
3321 }
3322
3323 /* BEGIN CSTYLED */
3324 /*
3325 * <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3326 * ::= DT <expression> E # decltype of an expression (C++0x)
3327 */
3328 /* END CSTYLED */
3329 static const char *
3330 parse_decltype(const char *first, const char *last, cpp_db_t *db)
3331 {
3332 ASSERT3P(first, <=, last);
3333
3334 if (last - first < 4)
3335 return (first);
3336
3337 ASSERT3U(first[0], ==, 'D');
3338
3339 if (first[1] != 't' && first[1] != 'T')
3340 return (first);
3341
3342 size_t n = nlen(db);
3343 const char *t = parse_expression(first + 2, last, db);
3344 if (NAMT(db, n) != 1 || t == first + 2 || t == last || t[0] != 'E')
3345 return (first);
3346
3347 nfmt(db, "decltype({0})", NULL);
3348
3349 /* skip E */
3350 return (t + 1);
3351 }
3352
3353 /*
3354 * <array-type> ::= A <positive dimension number> _ <element type>
3355 * ::= A [<dimension expression>] _ <element type>
3356 */
3357 static const char *
3358 parse_array_type(const char *first, const char *last, cpp_db_t *db)
3359 {
3360 ASSERT3P(first, <=, last);
3361 ASSERT3U(first[0], ==, 'A');
3362
3363 if (last - first < 3)
3364 return (first);
3365
3366 const char *t = first + 1;
3367 const char *t1 = NULL;
3368 size_t n = nlen(db);
3369
3370 if (t[0] != '_') {
3371 if (is_digit(t[0]) && t[0] != '0') {
3372 t1 = parse_number(t, last);
3373 if (t1 == last)
3374 return (first);
3375
3376 nadd_l(db, t, (size_t)(t1 - t));
3377 } else {
3378 t1 = parse_expression(t, last, db);
3379 if (t1 == last || t == t1)
3380 return (first);
3381 }
3382
3383 if (t1[0] != '_')
3384 return (first);
3385
3386 t = t1;
3387 } else {
3388 nadd_l(db, "", 0);
3389 }
3390
3391 ASSERT3U(t[0], ==, '_');
3392
3393 t1 = parse_type(t + 1, last, db);
3394 if (t1 == t + 1 || NAMT(db, n) != 2)
3395 return (first);
3396
3397 /*
3398 * if we have " [xxx]" already, want new result to be
3399 * " [yyy][xxx]"
3400 */
3401 str_t *r = &name_top(&db->cpp_name)->strp_r;
3402 if (r->str_len > 1 && r->str_s[0] == ' ' && r->str_s[1] == '[')
3403 str_erase(r, 0, 1);
3404
3405 nfmt(db, "{0:L}", " [{1}]{0:R}");
3406 return (t1);
3407 }
3408
3409 /* <pointer-to-member-type> ::= M <class type> <member type> */
3410 static const char *
3411 parse_pointer_to_member_type(const char *first, const char *last, cpp_db_t *db)
3412 {
3413 ASSERT3P(first, <=, last);
3414
3415 if (last - first < 3)
3416 return (first);
3417
3418 ASSERT3U(first[0], ==, 'M');
3419
3420 const char *t1 = first + 1;
3421 const char *t2 = NULL;
3422 size_t n = nlen(db);
3423
3424 t2 = parse_type(t1, last, db);
3425 if (t1 == t2)
3426 return (first);
3427
3428 t1 = t2;
3429 t2 = parse_type(t1, last, db);
3430 if (t1 == t2)
3431 return (first);
3432
3433 if (NAMT(db, n) != 2)
3434 return (first);
3435
3436 str_pair_t *func = name_top(&db->cpp_name);
3437
3438 if (str_length(&func->strp_r) > 0 && func->strp_r.str_s[0] == '(')
3442
3443 return (t2);
3444 }
3445
3446 /* BEGIN CSTYLED */
3447 /*
3448 * <unresolved-name>
3449 * extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3450 * ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3451 * ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3452 * # A::x, N::y, A<T>::z; "gs" means leading "::"
3453 * ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3454 * extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3455 * # T::N::x /decltype(p)::N::x
3456 * (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3457 */
3458 /* END CSTYLED */
3459 static const char *
3460 parse_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3461 {
3462 ASSERT3P(first, <=, last);
3463
3464 if (last - first < 2)
3465 return (first);
3466
3467 const char *t = first;
3468 const char *t2 = NULL;
3469 boolean_t global = B_FALSE;
3470 size_t n;
3471
3472 if (t[0] == 'g' && t[1] == 's') {
3473 global = B_TRUE;
3474 t += 2;
3475 }
3476 if (t == last)
3477 return (first);
3478
3479 t2 = parse_base_unresolved_name(t, last, db);
3480 if (t != t2) {
3481 if (global) {
3482 if (nempty(db))
3490 if (t[0] != 's' || t[1] != 'r' || last - t < 2)
3491 return (first);
3492
3493 n = nlen(db);
3494 if (t[2] == 'N') {
3495 t += 3;
3496 t2 = parse_unresolved_type(t, last, db);
3497 if (t2 == t || t2 == last)
3498 return (first);
3499 t = t2;
3500
3501 t2 = parse_template_args(t, last, db);
3502 if (t2 != t) {
3503 if (NAMT(db, n) < 2 || t2 == last)
3504 return (first);
3505
3506 nfmt(db, "{1:L}{0}", "{1:R}");
3507 t = t2;
3508 }
3509
3510 ASSERT3U(NAMT(db, n), ==, 1);
3511
3512 while (t[0] != 'E') {
3513 size_t nn = nlen(db);
3514 t2 = parse_unresolved_qualifier_level(t, last, db);
3515 if (t == t2 || t == last || NAMT(db, nn) != 1)
3516 return (first);
3517
3518 t = t2;
3519 }
3520
3521 /* skip E */
3522 t++;
3523
3524 t2 = parse_base_unresolved_name(t, last, db);
3525 if (t == t2 || NAMT(db, n) < 2)
3526 return (first);
3527
3528 njoin(db, NAMT(db, n), "::");
3529 return (t2);
3530 }
3562
3563 t = t2;
3564 }
3565
3566 /* skip E */
3567 t++;
3568
3569 t2 = parse_base_unresolved_name(t, last, db);
3570 if (t == t2 || nlen(db) < 2)
3571 return (first);
3572
3573 njoin(db, NAMT(db, n), "::");
3574 return (t2);
3575 }
3576
3577 /* <unresolved-qualifier-level> ::= <simple-id> */
3578 static const char *
3579 parse_unresolved_qualifier_level(const char *first, const char *last,
3580 cpp_db_t *db)
3581 {
3582 ASSERT3P(first, <=, last);
3583 return (parse_simple_id(first, last, db));
3584 }
3585
3586 /* BEGIN CSTYLED */
3587 /*
3588 * <base-unresolved-name> ::= <simple-id> # unresolved name
3589 * extension ::= <operator-name> # unresolved operator-function-id
3590 * extension ::= <operator-name> <template-args> # unresolved operator template-id
3591 * ::= on <operator-name> # unresolved operator-function-id
3592 * ::= on <operator-name> <template-args> # unresolved operator template-id
3593 * ::= dn <destructor-name> # destructor or pseudo-destructor;
3594 * # e.g. ~X or ~X<N-1>
3595 */
3596 /* END CSTYLED */
3597 static const char *
3598 parse_base_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3599 {
3600 ASSERT3P(first, <=, last);
3601
3602 if (last - first < 2)
3603 return (first);
3604
3605 const char *t = NULL;
3606 const char *t1 = NULL;
3607
3608 if ((first[0] != 'o' && first[0] != 'd') || first[1] != 'n') {
3609 t = parse_simple_id(first, last, db);
3610 if (t != first)
3611 return (t);
3612
3613 t = parse_operator_name(first, last, db);
3614 if (t == first)
3615 return (first);
3616
3617 t1 = parse_template_args(t, last, db);
3618 if (t1 != t) {
3619 if (nlen(db) < 2)
3620 return (first);
3629 return ((t != first + 2) ? t : first);
3630 }
3631
3632 t = parse_operator_name(first + 2, last, db);
3633 if (t == first + 2)
3634 return (first);
3635
3636 t1 = parse_template_args(t, last, db);
3637 if (t1 != t)
3638 nfmt(db, "{1:L}{0}", "{1:R}");
3639 return (t1);
3640 }
3641
3642 /*
3643 * <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3644 * ::= <simple-id> # e.g., ~A<2*N>
3645 */
3646 static const char *
3647 parse_destructor_name(const char *first, const char *last, cpp_db_t *db)
3648 {
3649 ASSERT3P(first, <=, last);
3650
3651 if (first == last)
3652 return (first);
3653
3654 const char *t = parse_unresolved_type(first, last, db);
3655
3656 if (t == first)
3657 t = parse_simple_id(first, last, db);
3658
3659 if (t == first)
3660 return (first);
3661
3662 nfmt(db, "~{0:L}", "{0:R}");
3663 return (t);
3664 }
3665
3666 /*
3667 * <ref-qualifier> ::= R # & ref-qualifier
3668 * <ref-qualifier> ::= O # && ref-qualifier
3669 *
3670 * <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
3671 */
3672 static const char *
3673 parse_function_type(const char *first, const char *last, cpp_db_t *db)
3674 {
3675 ASSERT3P(first, <=, last);
3676
3677 if (last - first < 2)
3678 return (first);
3679
3680 ASSERT3U(first[0], ==, 'F');
3681
3682 const char *t = first + 1;
3683
3684 /* extern "C" */
3685 if (t[0] == 'Y')
3686 t++;
3687
3688 const char *t1 = parse_type(t, last, db);
3689 if (t1 == t)
3690 return (first);
3691
3692 size_t n = nlen(db);
3693 int ref_qual = 0;
3694
3695 t = t1;
3696
3697 while (t != last && t[0] != 'E') {
3698 if (t[0] == 'v') {
3699 t++;
3700 continue;
3731 nfmt(db, "{0} &", NULL);
3732 break;
3733 case 2:
3734 nfmt(db, "{0} &&", NULL);
3735 break;
3736 }
3737
3738 nfmt(db, "{1:L} ", "{0}{1:R}");
3739
3740 /* skip E */
3741 return (t + 1);
3742 }
3743
3744 /*
3745 * <template-param> ::= T_ # first template parameter
3746 * ::= T <parameter-2 non-negative number> _
3747 */
3748 static const char *
3749 parse_template_param(const char *first, const char *last, cpp_db_t *db)
3750 {
3751 ASSERT3P(first, <=, last);
3752
3753 if (last - first < 2 || first[0] != 'T')
3754 return (first);
3755
3756 const char *t = first + 1;
3757 size_t idx = 0;
3758
3759 while (t != last && t[0] != '_') {
3760 if (!is_digit(t[0]))
3761 return (first);
3762
3763 idx *= 10;
3764 idx += t[0] - '0';
3765 t++;
3766 }
3767
3768 if (t == last)
3769 return (first);
3770
3771 ASSERT3U(t[0], ==, '_');
3772
3773 /*
3774 * T_ -> idx 0
3775 * T0 -> idx 1
3776 * T1 -> idx 2
3777 * ...
3778 */
3779 if (first[1] != '_')
3780 idx++;
3781
3782 /* skip _ */
3783 t++;
3784
3785 if (tempty(db))
3786 return (first);
3787
3788 if (idx >= ttlen(db)) {
3789 nadd_l(db, first, (size_t)(t - first));
3790 db->cpp_fix_forward_references = B_TRUE;
3791 return (t);
3792 }
3793
3794 tsub(db, idx);
3795 return (t);
3796 }
3797
3798 /*
3799 * <template-args> ::= I <template-arg>* E
3800 * extension, the abi says <template-arg>+
3801 */
3802 static const char *
3803 parse_template_args(const char *first, const char *last, cpp_db_t *db)
3804 {
3805 ASSERT3P(first, <=, last);
3806
3807 if (last - first < 2 || first[0] != 'I')
3808 return (first);
3809
3810 if (db->cpp_tag_templates)
3811 sub_clear(templ_top(&db->cpp_templ));
3812
3813 const char *t = first + 1;
3814 size_t n = nlen(db);
3815
3816 while (t[0] != 'E') {
3817 if (db->cpp_tag_templates)
3818 tpush(db);
3819
3820 size_t n1 = nlen(db);
3821 const char *t1 = parse_template_arg(t, last, db);
3822
3823 if (db->cpp_tag_templates)
3824 tpop(db);
3825
3826 if (t1 == t || t == last)
3827 return (first);
3828
3829 if (db->cpp_tag_templates)
3830 tsave(db, NAMT(db, n1));
3831
3832 t = t1;
3833 }
3834
3835 /*
3836 * ugly, but if the last thing pushed was an empty string,
3837 * get rid of it so we dont get "<..., >"
3838 */
3839 if (NAMT(db, n) > 1 &&
3840 str_pair_len(name_top(&db->cpp_name)) == 0)
3841 (void) name_pop(&db->cpp_name, NULL);
3842
3843 njoin(db, NAMT(db, n), ", ");
3844
3845 ASSERT3U(nlen(db), >, 0);
3846
3847 /* make sure we don't bitshift ourselves into oblivion */
3848 str_t *top = TOP_L(db);
3849 if (str_length(top) > 0 &&
3850 top->str_s[top->str_len - 1] == '>')
3851 nfmt(db, "<{0} >", NULL);
3852 else
3853 nfmt(db, "<{0}>", NULL);
3854
3855 /* skip E */
3856 return (t + 1);
3857 }
3858
3859 /*
3860 * <discriminator> := _ <non-negative number> # when number < 10
3861 * := __ <non-negative number> _ # when number >= 10
3862 * extension := decimal-digit+ # at the end of string
3863 */
3864 static const char *
3865 parse_discriminator(const char *first, const char *last)
3866 {
3867 ASSERT3P(first, <=, last);
3868
3869 const char *t = NULL;
3870
3871 if (first == last)
3872 return (first);
3873
3874 if (is_digit(first[0])) {
3875 for (t = first; t != last && is_digit(t[0]); t++)
3876 ;
3877
3878 /* not at the end of the string */
3879 if (t != last)
3880 return (first);
3881
3882 return (t);
3883 } else if (first[0] != '_' || first + 1 == last) {
3884 return (first);
3885 }
3886
3887 t = first + 1;
3888 if (is_digit(t[0]))
3889 return (t + 1);
3890
3891 if (t[0] != '_' || t + 1 == last)
3892 return (first);
3893
3894 for (t++; t != last && is_digit(t[0]); t++)
3895 ;
3896 if (t == last || t[0] != '_')
3897 return (first);
3898
3899 return (t);
3900 }
3901
3902 /* <CV-qualifiers> ::= [r] [V] [K] */
3903 const char *
3904 parse_cv_qualifiers(const char *first, const char *last, unsigned *cv)
3905 {
3906 ASSERT3P(first, <=, last);
3907
3908 if (first == last)
3909 return (first);
3910
3911 *cv = 0;
3912 if (first[0] == 'r') {
3913 *cv |= CPP_QUAL_RESTRICT;
3914 first++;
3915 }
3916 if (first != last && first[0] == 'V') {
3917 *cv |= CPP_QUAL_VOLATILE;
3918 first++;
3919 }
3920 if (first != last && first[0] == 'K') {
3921 *cv |= CPP_QUAL_CONST;
3922 first++;
3923 }
3924
3925 return (first);
3926 }
3927
3928 /*
3929 * <number> ::= [n] <non-negative decimal integer>
3930 */
3931 static const char *
3932 parse_number(const char *first, const char *last)
3933 {
3934 ASSERT3P(first, <=, last);
3935
3936 const char *t = first;
3937
3938 if (first == last || (first[0] != 'n' && !is_digit(first[0])))
3939 return (first);
3940
3941 if (t[0] == 'n')
3942 t++;
3943
3944 if (t[0] == '0')
3945 return (t + 1);
3946
3947 while (is_digit(t[0]))
3948 t++;
3949
3950 return (t);
3951 }
3952
3953 /*
3954 * we only ever use ASCII versions of these
3955 */
3956 static inline boolean_t
3957 is_digit(int c)
3958 {
3959 if (c < '0' || c > '9')
3960 return (B_FALSE);
3961 return (B_TRUE);
3962 }
3963
3964 static inline boolean_t
3965 is_upper(int c)
3966 {
3967 if (c < 'A' || c > 'Z')
3968 return (B_FALSE);
3969 return (B_TRUE);
3970 }
3971
3972 static inline boolean_t
3973 is_xdigit(int c)
3974 {
3975 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
3976 return (B_TRUE);
3977 return (B_FALSE);
3978 }
3979
3980 static boolean_t
3981 nempty(cpp_db_t *db)
3982 {
3983 return (name_empty(&db->cpp_name));
3984 }
3985
3986 static size_t
3987 nlen(cpp_db_t *db)
3988 {
3989 return (name_len(&db->cpp_name));
3990 }
3991
3992 static void
4040 }
4041
4042 static void
4043 tpush(cpp_db_t *db)
4044 {
4045 CK(templ_push(&db->cpp_templ));
4046 }
4047
4048 static void
4049 tpop(cpp_db_t *db)
4050 {
4051 templ_pop(&db->cpp_templ);
4052 }
4053
4054 static void
4055 tsave(cpp_db_t *db, size_t amt)
4056 {
4057 CK(templ_save(&db->cpp_name, amt, &db->cpp_templ));
4058 }
4059
4060 static void
4061 db_init(cpp_db_t *db, sysdem_ops_t *ops)
4062 {
4063 (void) memset(db, 0, sizeof (*db));
4064 db->cpp_ops = ops;
4065 name_init(&db->cpp_name, ops);
4066 sub_init(&db->cpp_subs, ops);
4067 templ_init(&db->cpp_templ, ops);
4068 db->cpp_tag_templates = B_TRUE;
4069 db->cpp_try_to_parse_template_args = B_TRUE;
4070 tpush(db);
4071 }
4072
4073 static void
4074 db_fini(cpp_db_t *db)
4075 {
4076 name_fini(&db->cpp_name);
4077 sub_fini(&db->cpp_subs);
4078 templ_fini(&db->cpp_templ);
4079 (void) memset(db, 0, sizeof (*db));
4080 }
4081
4082 static void
4083 print_sp(const str_pair_t *sp, FILE *out)
4084 {
4085 (void) fprintf(out, "{%.*s#%.*s}",
4086 (int)sp->strp_l.str_len, sp->strp_l.str_s,
4087 (int)sp->strp_r.str_len, sp->strp_r.str_s);
4088 }
4089
4090 static void
4091 print_name(const name_t *n, FILE *out)
4092 {
4093 const str_pair_t *sp = name_top((name_t *)n);
4094 size_t i;
4095
4096 (void) fprintf(out, "Name:\n");
4097
4098 if (name_len(n) == 0)
4099 return;
4100
4101 for (i = 0; i < n->nm_len; i++, sp--) {
4102 (void) fprintf(out, " [%02zu] ", i);
4103 print_sp(sp, out);
4104 (void) fputc('\n', out);
4105 }
4106
4107 (void) fputc('\n', out);
4108 }
4109
4110
4111 static char *
4112 base36(char *buf, size_t val)
4113 {
4114 char tmp[16] = { 0 };
4115 char *p = tmp;
4116
4117 if (val == 0) {
4118 buf[0] = '0';
4119 buf[1] = '\0';
4120 return (buf);
4121 }
4122
4123 while (val > 0) {
4124 size_t r = val % 36;
4125
4126 if (r < 10)
4127 *p++ = r + '0';
4128 else
4129 *p++ = r - 10 + 'A';
4130
|
1 /*
2 * Ported from LLVM's libcxxabi trunk/src/cxa_demangle.cpp
3 * LICENSE.TXT contents is available as ../THIRDPARTYLICENSE
4 *
5 * The LLVM Compiler Infrastructure
6 *
7 * This file is dual licensed under the MIT and the University of Illinois Open
8 * Source Licenses. See LICENSE.TXT for details.
9 *
10 */
11
12 /*
13 * Copyright 2017 Jason King.
14 */
15 #include <ctype.h>
16 #include <errno.h>
17 #include <locale.h>
18 #include <string.h>
19 #include <setjmp.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/isa_defs.h>
23 #include <sys/debug.h>
24 #include "sysdemangle.h"
25 #include "sysdemangle_int.h"
26 #include "cxx.h"
27
28 #ifndef ARRAY_SIZE
29 #define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
30 #endif
31
32 #define CPP_QUAL_CONST (1U)
33 #define CPP_QUAL_VOLATILE (2U)
34 #define CPP_QUAL_RESTRICT (4U)
35
36 typedef struct cpp_db_s {
37 sysdem_ops_t *cpp_ops;
38 jmp_buf cpp_jmp;
39 name_t cpp_name;
40 sub_t cpp_subs;
41 templ_t cpp_templ;
42 unsigned cpp_cv;
43 unsigned cpp_ref;
44 unsigned cpp_depth;
45 boolean_t cpp_parsed_ctor_dtor_cv;
46 boolean_t cpp_tag_templates;
47 boolean_t cpp_fix_forward_references;
48 boolean_t cpp_try_to_parse_template_args;
49 locale_t cpp_loc;
50 } cpp_db_t;
51
52 #define CK(x) \
53 do { \
54 if (!(x)) \
55 longjmp(db->cpp_jmp, 1); \
56 } while (0)
57
58 #define TOP_L(db) (&(name_top(&(db)->cpp_name)->strp_l))
59 #define RLEN(f, l) ((size_t)((l) - (f)))
60 #define NAMT(db, n) (nlen(db) - n)
61
62 static inline boolean_t is_xdigit(int);
63
64 static boolean_t nempty(cpp_db_t *);
65 static size_t nlen(cpp_db_t *);
66 static void nadd_l(cpp_db_t *, const char *, size_t);
67 static void njoin(cpp_db_t *, size_t, const char *);
68 static void nfmt(cpp_db_t *, const char *, const char *);
69
70 static void save_top(cpp_db_t *, size_t);
71 static void sub(cpp_db_t *, size_t);
72
73 static boolean_t tempty(const cpp_db_t *);
74 static size_t ttlen(const cpp_db_t *);
75
76 static void tsub(cpp_db_t *, size_t);
77 static void tpush(cpp_db_t *);
78 static void tpop(cpp_db_t *);
79 static void tsave(cpp_db_t *, size_t);
80
81 static boolean_t db_init(cpp_db_t *, sysdem_ops_t *);
82 static void db_fini(cpp_db_t *);
83 static void dump(cpp_db_t *, FILE *);
84
85 static void demangle(const char *, const char *, cpp_db_t *);
86
87 static const char *parse_type(const char *, const char *, cpp_db_t *);
88 static const char *parse_builtin_type(const char *, const char *, cpp_db_t *);
89 static const char *parse_qual_type(const char *, const char *, cpp_db_t *);
90 static const char *parse_encoding(const char *, const char *, cpp_db_t *);
91 static const char *parse_dot_suffix(const char *, const char *, cpp_db_t *);
92 static const char *parse_block_invoke(const char *, const char *, cpp_db_t *);
93 static const char *parse_special_name(const char *, const char *, cpp_db_t *);
94 static const char *parse_name(const char *, const char *, boolean_t *,
95 cpp_db_t *);
96 static const char *parse_call_offset(const char *, const char *, locale_t);
97 static const char *parse_number(const char *, const char *, locale_t);
98 static const char *parse_nested_name(const char *, const char *, boolean_t *,
99 cpp_db_t *);
100 static const char *parse_local_name(const char *, const char *, boolean_t *,
101 cpp_db_t *);
102 static const char *parse_unscoped_name(const char *, const char *, cpp_db_t *);
103 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
104 static const char *parse_substitution(const char *, const char *, cpp_db_t *);
105 static const char *parse_discriminator(const char *, const char *, locale_t);
106 static const char *parse_cv_qualifiers(const char *, const char *, unsigned *);
107 static const char *parse_template_param(const char *, const char *, cpp_db_t *);
108 static const char *parse_decltype(const char *, const char *, cpp_db_t *);
109 static const char *parse_template_args(const char *, const char *, cpp_db_t *);
110 static const char *parse_unqualified_name(const char *, const char *,
111 cpp_db_t *);
112 static const char *parse_template_arg(const char *, const char *, cpp_db_t *);
113 static const char *parse_expression(const char *, const char *, cpp_db_t *);
114 static const char *parse_expr_primary(const char *, const char *, cpp_db_t *);
115 static const char *parse_binary_expr(const char *, const char *,
116 const char *, cpp_db_t *);
117 static const char *parse_prefix_expr(const char *, const char *,
118 const char *, cpp_db_t *);
119 static const char *parse_gs(const char *, const char *, cpp_db_t *);
120 static const char *parse_idx_expr(const char *, const char *, cpp_db_t *);
121 static const char *parse_mm_expr(const char *, const char *, cpp_db_t *);
122 static const char *parse_pp_expr(const char *, const char *, cpp_db_t *);
123 static const char *parse_trinary_expr(const char *, const char *, cpp_db_t *);
124 static const char *parse_new_expr(const char *, const char *, cpp_db_t *);
125 static const char *parse_del_expr(const char *, const char *, cpp_db_t *);
151 cpp_db_t *);
152 static const char *parse_unresolved_qualifier_level(const char *, const char *,
153 cpp_db_t *);
154 static const char *parse_destructor_name(const char *, const char *,
155 cpp_db_t *);
156 static const char *parse_function_type(const char *, const char *, cpp_db_t *);
157 static const char *parse_array_type(const char *, const char *, cpp_db_t *);
158 static const char *parse_pointer_to_member_type(const char *, const char *,
159 cpp_db_t *);
160 static const char *parse_vector_type(const char *, const char *, cpp_db_t *);
161
162 size_t cpp_name_max_depth = 1024; /* max depth of name stack */
163
164 char *
165 cpp_demangle(const char *src, sysdem_ops_t *ops)
166 {
167 char *result = NULL;
168 cpp_db_t db;
169 size_t srclen = strlen(src);
170
171 if (!db_init(&db, ops))
172 goto done;
173 if (setjmp(db.cpp_jmp) != 0)
174 goto done;
175
176 errno = 0;
177 demangle(src, src + srclen, &db);
178
179 if (errno == 0 && db.cpp_fix_forward_references &&
180 !templ_empty(&db.cpp_templ) &&
181 !sub_empty(&db.cpp_templ.tpl_items[0])) {
182 db.cpp_fix_forward_references = B_FALSE;
183 db.cpp_tag_templates = B_FALSE;
184 name_clear(&db.cpp_name);
185 sub_clear(&db.cpp_subs);
186
187 if (setjmp(db.cpp_jmp) != 0)
188 goto done;
189
190 demangle(src, src + srclen, &db);
191
192 if (db.cpp_fix_forward_references) {
256 }
257
258 goto done;
259 }
260
261 if (first[1] != '_' || first[2] != '_' || first[3] != 'Z')
262 goto done;
263
264 t = parse_encoding(first + 4, last, db);
265 if (t != first + 4 && t != last)
266 t = parse_block_invoke(t, last, db);
267
268 done:
269 if (t != last)
270 errno = EINVAL;
271 }
272
273 static const char *
274 parse_dot_suffix(const char *first, const char *last, cpp_db_t *db)
275 {
276 VERIFY3P(first, <=, last);
277
278 if (first == last || first[0] != '.')
279 return (first);
280
281 if (nempty(db))
282 return (first);
283
284 nadd_l(db, first, RLEN(first, last));
285 nfmt(db, " ({0})", NULL);
286
287 return (last);
288 }
289
290 /*
291 * _block_invoke
292 * _block_invoke<digit>+ XXX: should it be <digit>* ?
293 * _block_invoke_<digit>+
294 */
295 static const char *
296 parse_block_invoke(const char *first, const char *last, cpp_db_t *db)
297 {
298 VERIFY3P(first, <=, last);
299
300 if (last - first < 13)
301 return (first);
302
303 const char test[] = "_block_invoke";
304 const char *t = first;
305
306 if (strncmp(first, test, sizeof (test) - 1) != 0)
307 return (first);
308
309 t += sizeof (test);
310 if (t == last)
311 goto done;
312
313 if (t[0] == '_') {
314 /* need at least one digit */
315 if (t + 1 == last || !isdigit_l(t[1], db->cpp_loc))
316 return (first);
317 t += 2;
318 }
319
320 while (t < last && isdigit_l(t[0], db->cpp_loc))
321 t++;
322
323 done:
324 if (nempty(db))
325 return (first);
326
327 nfmt(db, "invocation function for block in {0}", NULL);
328 return (t);
329 }
330
331 /*
332 * <encoding> ::= <function name><bare-function-type>
333 * ::= <data name>
334 * ::= <special name>
335 */
336 static const char *
337 parse_encoding(const char *first, const char *last, cpp_db_t *db)
338 {
339 VERIFY3P(first, <=, last);
340
341 if (first == last)
342 return (first);
343
344 const char *t = NULL;
345 const char *t2 = NULL;
346 unsigned cv = 0;
347 unsigned ref = 0;
348 boolean_t tag_templ_save = db->cpp_tag_templates;
349
350 if (++db->cpp_depth > 1)
351 db->cpp_tag_templates = B_TRUE;
352
353 if (first[0] == 'G' || first[0] == 'T') {
354 t = parse_special_name(first, last, db);
355 goto done;
356 }
357
358 boolean_t ends_with_template_args = B_FALSE;
359 t = parse_name(first, last, &ends_with_template_args, db);
392 if (t[0] == 'v') {
393 t++;
394 } else {
395
396 /*CONSTCOND*/
397 while (1) {
398 t2 = parse_type(t, last, db);
399 if (t2 == t || t == last)
400 break;
401
402 t = t2;
403 }
404 }
405
406 /*
407 * a bit of a hack, but a template substitution can apparently be
408 * an empty string at the end of an argument list, so avoid
409 * <...., >
410 */
411 if (NAMT(db, n) > 1 && str_pair_len(name_top(&db->cpp_name)) == 0)
412 name_pop(&db->cpp_name, NULL);
413
414 njoin(db, NAMT(db, n), ", ");
415 nfmt(db, "({0})", NULL);
416
417 str_t *s = TOP_L(db);
418
419 if (cv & CPP_QUAL_CONST) {
420 CK(str_append(s, " const", 0));
421 }
422 if (cv & CPP_QUAL_VOLATILE) {
423 CK(str_append(s, " volatile", 0));
424 }
425 if (cv & CPP_QUAL_RESTRICT) {
426 CK(str_append(s, " restrict", 0));
427 }
428 if (ref == 1) {
429 CK(str_append(s, " &", 0));
430 }
431 if (ref == 2) {
432 CK(str_append(s, " &&", 0));
450 * ::= TT <type> # VTT structure (construction vtable index)
451 * ::= TI <type> # typeinfo structure
452 * ::= TS <type> # typeinfo name (null-terminated byte string)
453 * ::= Tc <call-offset> <call-offset> <base encoding>
454 * # base is the nominal target function of thunk
455 * # first call-offset is 'this' adjustment
456 * # second call-offset is result adjustment
457 * ::= T <call-offset> <base encoding>
458 * # base is the nominal target function of thunk
459 * ::= GV <object name> # Guard variable for one-time init
460 * # No <type>
461 * ::= TW <object name> # Thread-local wrapper
462 * ::= TH <object name> # Thread-local initialization
463 * extension ::= TC <first type> <number> _ <second type>
464 * # construction vtable for second-in-first
465 * extension ::= GR <object name> # reference temporary for object
466 */
467 static const char *
468 parse_special_name(const char *first, const char *last, cpp_db_t *db)
469 {
470 VERIFY3P(first, <=, last);
471
472 const char *t = first;
473 const char *t1 = NULL;
474 size_t n = nlen(db);
475
476 if (last - first < 2)
477 return (first);
478
479 switch (t[0]) {
480 case 'T':
481 switch (t[1]) {
482 case 'V':
483 nadd_l(db, "vtable for", 0);
484 t = parse_type(first + 2, last, db);
485 break;
486 case 'T':
487 nadd_l(db, "VTT for", 0);
488 t = parse_type(first + 2, last, db);
489 break;
490 case 'I':
491 nadd_l(db, "typeinfo for", 0);
492 t = parse_type(first + 2, last, db);
493 break;
494 case 'S':
495 nadd_l(db, "typeinfo name for", 0);
496 t = parse_type(first + 2, last, db);
497 break;
498 case 'c':
499 nadd_l(db, "covariant return thunk to", 0);
500 t1 = parse_call_offset(first + 2, last, db->cpp_loc);
501 if (t1 == t)
502 return (first);
503 t = parse_call_offset(t1, last, db->cpp_loc);
504 if (t == t1)
505 return (first);
506 t1 = parse_encoding(t, last, db);
507 if (t1 == t)
508 return (first);
509 break;
510 case 'C':
511 t = parse_type(first + 2, last, db);
512 if (t == first + 2)
513 return (first);
514 t1 = parse_number(t, last, db->cpp_loc);
515 if (*t1 != '_')
516 return (first);
517 t = parse_type(t1 + 1, last, db);
518 if (t == t1 + 1 || nlen(db) < 2)
519 return (first);
520 nfmt(db, "construction vtable for {0}-in-{1}", NULL);
521 return (t);
522 case 'W':
523 nadd_l(db, "thread-local wrapper routine for", 0);
524 t = parse_name(first + 2, last, NULL, db);
525 break;
526 case 'H':
527 nadd_l(db, "thread-local initialization routine for",
528 0);
529 t = parse_name(first + 2, last, NULL, db);
530 break;
531 default:
532 if (first[1] == 'v') {
533 nadd_l(db, "virtual thunk to", 0);
534 } else {
535 nadd_l(db, "non-virtual thunk to", 0);
536 }
537
538 t = parse_call_offset(first + 1, last, db->cpp_loc);
539 if (t == first + 1)
540 return (first);
541 t1 = parse_encoding(t, last, db);
542 if (t == t1)
543 return (first);
544 t = t1;
545 break;
546 }
547 break;
548 case 'G':
549 switch (first[1]) {
550 case 'V':
551 nadd_l(db, "guard variable for", 0);
552 t = parse_name(first + 2, last, NULL, db);
553 break;
554 case 'R':
555 nadd_l(db, "reference temporary for", 0);
556 t = parse_name(first + 2, last, NULL, db);
557 break;
558 default:
565
566 size_t amt = NAMT(db, n);
567 if (t == first + 2 || amt < 2)
568 return (first);
569
570 njoin(db, amt, " ");
571 return (t);
572 }
573
574 /*
575 * <call-offset> ::= h <nv-offset> _
576 * ::= v <v-offset> _
577 *
578 * <nv-offset> ::= <offset number>
579 * # non-virtual base override
580 *
581 * <v-offset> ::= <offset number> _ <virtual offset number>
582 * # virtual base override, with vcall offset
583 */
584 static const char *
585 parse_call_offset(const char *first, const char *last, locale_t loc)
586 {
587 VERIFY3P(first, <=, last);
588
589 const char *t = NULL;
590 const char *t1 = NULL;
591
592 if (first == last)
593 return (first);
594
595 if (first[0] != 'h' && first[0] != 'v')
596 return (first);
597
598 t = parse_number(first + 1, last, loc);
599 if (t == first + 1 || t == last || t[0] != '_')
600 return (first);
601
602 /* skip _ */
603 t++;
604
605 if (first[0] == 'h')
606 return (t);
607
608 t1 = parse_number(t, last, loc);
609 if (t == t1 || t1 == last || t1[0] != '_')
610 return (first);
611
612 /* skip _ */
613 t1++;
614
615 return (t1);
616 }
617
618 /*
619 * <name> ::= <nested-name> // N
620 * ::= <local-name> # See Scope Encoding below // Z
621 * ::= <unscoped-template-name> <template-args>
622 * ::= <unscoped-name>
623 *
624 * <unscoped-template-name> ::= <unscoped-name>
625 * ::= <substitution>
626 */
627 static const char *
628 parse_name(const char *first, const char *last,
629 boolean_t *ends_with_template_args, cpp_db_t *db)
630 {
631 VERIFY3P(first, <=, last);
632
633 const char *t = first;
634 const char *t1 = NULL;
635
636 if (last - first < 2)
637 return (first);
638
639 /* extension: ignore L here */
640 if (t[0] == 'L')
641 t++;
642
643 switch (t[0]) {
644 case 'N':
645 t1 = parse_nested_name(t, last, ends_with_template_args, db);
646 return ((t == t1) ? first : t1);
647 case 'Z':
648 t1 = parse_local_name(t, last, ends_with_template_args, db);
649 return ((t == t1) ? first : t1);
650 }
651
674
675 nfmt(db, "{1:L}{0}", "{1:R}");
676
677 if (ends_with_template_args != NULL)
678 *ends_with_template_args = B_TRUE;
679
680 return (t);
681 }
682
683 /* BEGIN CSTYLED */
684 /*
685 * <local-name> := Z <function encoding> E <entity name> [<discriminator>]
686 * := Z <function encoding> E s [<discriminator>]
687 * := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
688 */
689 /* END CSTYLED */
690 const char *
691 parse_local_name(const char *first, const char *last,
692 boolean_t *ends_with_template_args, cpp_db_t *db)
693 {
694 VERIFY3P(first, <=, last);
695
696 const char *t = NULL;
697 const char *t1 = NULL;
698 const char *t2 = NULL;
699
700 if (first == last || first[0] != 'Z')
701 return (first);
702
703 t = parse_encoding(first + 1, last, db);
704 if (t == first + 1 || t == last || t[0] != 'E')
705 return (first);
706
707 VERIFY(!nempty(db));
708
709 /* skip E */
710 t++;
711
712 if (t[0] == 's') {
713 nfmt(db, "{0:L}::string literal", "{0:R}");
714 return (parse_discriminator(t, last, db->cpp_loc));
715 }
716
717 if (t[0] == 'd') {
718 t1 = parse_number(t + 1, last, db->cpp_loc);
719 if (t1[0] != '_')
720 return (first);
721 t1++;
722 } else {
723 t1 = t;
724 }
725
726 t2 = parse_name(t1, last, ends_with_template_args, db);
727 if (t2 == t1)
728 return (first);
729
730 nfmt(db, "{1:L}::{0}", "{1:R}");
731
732 /* parsed, but ignored */
733 if (t[0] != 'd')
734 t2 = parse_discriminator(t2, last, db->cpp_loc);
735
736 return (t2);
737 }
738
739 /* BEGIN CSTYLED */
740 /*
741 * <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
742 * ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
743 *
744 * <prefix> ::= <prefix> <unqualified-name>
745 * ::= <template-prefix> <template-args>
746 * ::= <template-param>
747 * ::= <decltype>
748 * ::= # empty
749 * ::= <substitution>
750 * ::= <prefix> <data-member-prefix>
751 * extension ::= L
752 *
753 * <template-prefix> ::= <prefix> <template unqualified-name>
754 * ::= <template-param>
755 * ::= <substitution>
756 */
757 /* END CSTYLED */
758 static const char *
759 parse_nested_name(const char *first, const char *last,
760 boolean_t *ends_with_template_args, cpp_db_t *db)
761 {
762 VERIFY3P(first, <=, last);
763
764 if (first == last || first[0] != 'N')
765 return (first);
766
767 unsigned cv = 0;
768 const char *t = parse_cv_qualifiers(first + 1, last, &cv);
769
770 if (t == last)
771 return (first);
772
773 boolean_t more = B_FALSE;
774
775 switch (t[0]) {
776 case 'R':
777 db->cpp_ref = 1;
778 t++;
779 break;
780 case 'O':
781 db->cpp_ref = 2;
782 t++;
795 boolean_t pop_subs = B_FALSE;
796 boolean_t component_ends_with_template_args = B_FALSE;
797
798 while (t[0] != 'E' && t != last) {
799 const char *t1 = NULL;
800 size_t n = nlen(db);
801 component_ends_with_template_args = B_FALSE;
802
803 switch (t[0]) {
804 case 'S':
805 if (t + 1 != last && t[1] == 't')
806 break;
807
808 t1 = parse_substitution(t, last, db);
809 if (t1 == t || t1 == last || NAMT(db, n) != 1)
810 return (first);
811
812 if (!more) {
813 nfmt(db, "{0}", NULL);
814 } else {
815 VERIFY3U(nlen(db), >, 1);
816 nfmt(db, "{1:L}::{0}", "{1:R}");
817 save_top(db, 1);
818 }
819
820 more = B_TRUE;
821 pop_subs = B_TRUE;
822 t = t1;
823 continue;
824
825 case 'T':
826 t1 = parse_template_param(t, last, db);
827 if (t1 == t || t1 == last || NAMT(db, n) != 1)
828 return (first);
829
830 if (!more) {
831 nfmt(db, "{0}", NULL);
832 } else {
833 VERIFY3U(nlen(db), >, 1);
834 nfmt(db, "{1:L}::{0}", "{1:R}");
835 }
836
837 save_top(db, 1);
838 more = B_TRUE;
839 pop_subs = B_TRUE;
840 t = t1;
841 continue;
842
843 case 'D':
844 if (t + 1 != last && t[1] != 't' && t[1] != 'T')
845 break;
846 t1 = parse_decltype(t, last, db);
847 if (t1 == t || t1 == last || NAMT(db, n) != 1)
848 return (first);
849
850 if (!more) {
851 nfmt(db, "{0}", NULL);
852 } else {
853 VERIFY3U(nlen(db), >, 1);
854 nfmt(db, "{1:L}::{0}", "{1:R}");
855 }
856
857 save_top(db, 1);
858 more = B_TRUE;
859 pop_subs = B_TRUE;
860 t = t1;
861 continue;
862
863 case 'I':
864 /*
865 * Must have at least one component before
866 * <template-args>
867 */
868 if (!more)
869 return (first);
870
871 t1 = parse_template_args(t, last, db);
872 if (t1 == t || t1 == last)
873 return (first);
874
875 VERIFY3U(nlen(db), >, 1);
876 nfmt(db, "{1:L}{0}", "{1:R}");
877 save_top(db, 1);
878 t = t1;
879 component_ends_with_template_args = B_TRUE;
880 continue;
881
882 case 'L':
883 if (t + 1 == last)
884 return (first);
885 t++;
886 continue;
887
888 default:
889 break;
890 }
891
892 t1 = parse_unqualified_name(t, last, db);
893 if (t1 == t || t1 == last || NAMT(db, n) != 1)
894 return (first);
895
896 if (!more) {
897 nfmt(db, "{0}", NULL);
898 } else {
899 VERIFY3U(nlen(db), >, 1);
900 nfmt(db, "{1:L}::{0}", "{1:R}");
901 }
902
903 save_top(db, 1);
904 more = B_TRUE;
905 pop_subs = B_TRUE;
906 t = t1;
907 }
908
909 /* need to parse at least one thing */
910 if (!more)
911 return (first);
912
913 db->cpp_cv = cv;
914 if (pop_subs && !sub_empty(&db->cpp_subs))
915 sub_pop(&db->cpp_subs);
916
917 if (ends_with_template_args != NULL)
918 *ends_with_template_args = component_ends_with_template_args;
919
920 if (t[0] != 'E')
921 return (first);
922
923 return (t + 1);
924 }
925
926 /*
927 * <template-arg> ::= <type> # type or template
928 * ::= X <expression> E # expression
929 * ::= <expr-primary> # simple expressions
930 * ::= J <template-arg>* E # argument pack
931 * ::= LZ <encoding> E # extension
932 */
933 static const char *
934 parse_template_arg(const char *first, const char *last, cpp_db_t *db)
935 {
936 VERIFY3P(first, <=, last);
937
938 const char *t = NULL;
939 const char *t1 = NULL;
940
941 if (first == last)
942 return (first);
943
944 switch (first[0]) {
945 case 'X':
946 t = parse_expression(first + 1, last, db);
947 if (t == first + 1 || t[0] != 'E')
948 return (first);
949
950 /* E */
951 t++;
952 break;
953
954 case 'J':
955 t = first + 1;
956 if (t == last)
1116 PA("rS", ">>=", parse_binary_expr),
1117 PN("rc", parse_cast_expr),
1118 PA("rm", "%", parse_binary_expr),
1119 PA("rs", ">>", parse_binary_expr),
1120 PN("sc", parse_cast_expr),
1121 PN("sp", parse_pack_expansion),
1122 PN("sr", parse_unresolved_name),
1123 PN("st", parse_sizeof),
1124 PN("sz", parse_sizeof),
1125 PN("sZ", parse_sizeof_param_pack_expr),
1126 PN("te", parse_typeid_expr),
1127 PN("tr", parse_throw_expr),
1128 PN("tw", parse_throw_expr)
1129 };
1130 #undef PA
1131 #undef PN
1132
1133 static const char *
1134 parse_expression(const char *first, const char *last, cpp_db_t *db)
1135 {
1136 VERIFY3P(first, <=, last);
1137
1138 if (last - first < 2)
1139 return (first);
1140
1141 for (size_t i = 0; i < ARRAY_SIZE(expr_tbl); i++) {
1142 if (strncmp(expr_tbl[i].code, first, 2) != 0)
1143 continue;
1144 switch (expr_tbl[i].fntype) {
1145 case EXPR_ARG:
1146 return (expr_tbl[i].p.parse_expr_arg(first, last,
1147 expr_tbl[i].val, db));
1148 case EXPR_NOARG:
1149 return (expr_tbl[i].p.parse_expr_noarg(first, last,
1150 db));
1151 }
1152 }
1153
1154 switch (first[0]) {
1155 case 'L':
1156 return (parse_expr_primary(first, last, db));
1160 return (parse_function_param(first, last, db));
1161 case '1':
1162 case '2':
1163 case '3':
1164 case '4':
1165 case '5':
1166 case '6':
1167 case '7':
1168 case '8':
1169 case '9':
1170 return (parse_unresolved_name(first, last, db));
1171 }
1172
1173 return (first);
1174 }
1175
1176 static const char *
1177 parse_binary_expr(const char *first, const char *last, const char *op,
1178 cpp_db_t *db)
1179 {
1180 VERIFY3P(first, <=, last);
1181
1182 if (last - first < 2)
1183 return (first);
1184
1185 size_t n = nlen(db);
1186
1187 const char *t1 = parse_expression(first + 2, last, db);
1188 if (t1 == first + 2)
1189 return (first);
1190
1191 nadd_l(db, op, 0);
1192
1193 const char *t2 = parse_expression(t1, last, db);
1194 if (t2 == t1)
1195 return (first);
1196
1197 if (NAMT(db, n) != 3)
1198 return (first);
1199
1200 VERIFY3U(nlen(db), >, 2);
1201
1202 nfmt(db, "({2}) {1} ({0})", NULL);
1203 if (strcmp(op, ">") == 0)
1204 nfmt(db, "({0})", NULL);
1205
1206 return (t2);
1207 }
1208
1209 static const char *
1210 parse_prefix_expr(const char *first, const char *last, const char *op,
1211 cpp_db_t *db)
1212 {
1213 VERIFY3P(first, <=, last);
1214
1215 if (last - first < 2)
1216 return (first);
1217
1218 nadd_l(db, op, 0);
1219
1220 const char *t = parse_expression(first + 2, last, db);
1221 if (t == first + 2) {
1222 return (first);
1223 }
1224
1225 VERIFY3U(nlen(db), >, 1);
1226
1227 nfmt(db, "{1}({0})", NULL);
1228 return (t);
1229 }
1230
1231 static const char *
1232 parse_gs(const char *first, const char *last, cpp_db_t *db)
1233 {
1234 VERIFY3P(first, <=, last);
1235
1236 const char *t = NULL;
1237
1238 if (last - first < 4)
1239 return (first);
1240
1241 if (first[2] == 'n' && (first[3] == 'a' || first[3] == 'w'))
1242 t = parse_new_expr(first + 2, last, db);
1243 else if (first[2] == 'd' && (first[3] == 'l' || first[3] == 'a'))
1244 t = parse_del_expr(first + 2, last, db);
1245 else
1246 return (first);
1247
1248 if (t == first + 2)
1249 return (first);
1250
1251 VERIFY3U(nlen(db), >, 0);
1252
1253 nfmt(db, "::{0}", NULL);
1254 return (t);
1255 }
1256
1257 /*
1258 * [gs] nw <expression>* _ <type> E # new (expr-list) type
1259 * [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
1260 * [gs] na <expression>* _ <type> E # new[] (expr-list) type
1261 * [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1262 * <initializer> ::= pi <expression>* E # parenthesized initialization
1263 */
1264 static const char *
1265 parse_new_expr(const char *first, const char *last, cpp_db_t *db)
1266 {
1267 VERIFY3P(first, <=, last);
1268
1269 /* note [gs] is already handled by parse_gs() */
1270 if (last - first < 3)
1271 return (first);
1272
1273 VERIFY3U(first[0], ==, 'n');
1274 VERIFY(first[1] == 'a' || first[1] == 'w');
1275
1276 const char *t1 = first + 2;
1277 const char *t2 = NULL;
1278 size_t n = nlen(db);
1279
1280 nadd_l(db, (first[1] == 'w') ? "new" : "new[]", 0);
1281
1282 while (t1 != last && t1[0] != '_') {
1283 t2 = parse_expression(t1, last, db);
1284 VERIFY3P(t2, !=, NULL);
1285 if (t2 == t1)
1286 return (first);
1287 t1 = t2;
1288 }
1289 if (t1 == last)
1290 return (first);
1291
1292 if (NAMT(db, n) > 1) {
1293 njoin(db, NAMT(db, n) - 1, ", ");
1294 nfmt(db, "({0})", NULL);
1295 }
1296
1297 t2 = parse_type(t1 + 1, last, db);
1298 if (t1 + 1 == t2)
1299 return (first);
1300
1301 if (t2[0] != 'E') {
1302 if (last - t2 < 3)
1303 return (first);
1304 if (t2[0] != 'p' && t2[1] != 'i')
1314 if (t2 == t3)
1315 return (first);
1316 t2 = t3;
1317 }
1318 if (t3 == last || t3[0] != 'E')
1319 return (first);
1320
1321 if (NAMT(db, n1) > 0) {
1322 njoin(db, NAMT(db, n1), ", ");
1323 nfmt(db, "({0})", NULL);
1324 }
1325 }
1326
1327 njoin(db, NAMT(db, n), " ");
1328 return (t2 + 1);
1329 }
1330
1331 static const char *
1332 parse_del_expr(const char *first, const char *last, cpp_db_t *db)
1333 {
1334 VERIFY3P(first, <=, last);
1335
1336 if (last - first < 3)
1337 return (first);
1338
1339 VERIFY3U(first[0], ==, 'd');
1340 VERIFY(first[1] == 'l' || first[1] == 'a');
1341
1342 size_t n = nlen(db);
1343 const char *t = parse_expression(first + 2, last, db);
1344 if (t == first + 2 || NAMT(db, n) != 1)
1345 return (first);
1346
1347 nfmt(db, (first[1] == 'a') ? "delete[] {0}" : "delete {0}", NULL);
1348 return (t);
1349 }
1350
1351 static const char *
1352 parse_idx_expr(const char *first, const char *last, cpp_db_t *db)
1353 {
1354 VERIFY3P(first, <=, last);
1355 VERIFY3U(first[0], ==, 'i');
1356 VERIFY3U(first[1], ==, 'x');
1357
1358 size_t n = nlen(db);
1359 const char *t1 = parse_expression(first + 2, last, db);
1360 if (t1 == first + 2)
1361 return (first);
1362
1363 const char *t2 = parse_expression(t1, last, db);
1364 if (t2 == t1 || NAMT(db, n) != 2)
1365 return (first);
1366
1367 nfmt(db, "({0})[{1}]", NULL);
1368 return (t2);
1369 }
1370
1371 static const char *
1372 parse_ppmm_expr(const char *first, const char *last, const char *fmt,
1373 cpp_db_t *db)
1374 {
1375 VERIFY3P(first, <=, last);
1376
1377 if (last - first < 3)
1378 return (first);
1379
1380 const char *t = NULL;
1381 size_t n = nlen(db);
1382
1383 if (first[2] == '_') {
1384 t = parse_binary_expr(first + 3, last, "--", db);
1385 if (t == first + 3)
1386 return (first);
1387 return (t);
1388 }
1389
1390 t = parse_expression(first + 2, last, db);
1391 if (t == first + 2 || NAMT(db, n) < 1)
1392 return (first);
1393
1394 nfmt(db, fmt, NULL);
1395 return (t);
1396 }
1397
1398 static const char *
1399 parse_mm_expr(const char *first, const char *last, cpp_db_t *db)
1400 {
1401 VERIFY3P(first, <=, last);
1402 VERIFY3U(first[0], ==, 'm');
1403 VERIFY3U(first[1], ==, 'm');
1404
1405 return (parse_ppmm_expr(first, last, "({0})--", db));
1406 }
1407
1408 static const char *
1409 parse_pp_expr(const char *first, const char *last, cpp_db_t *db)
1410 {
1411 VERIFY3P(first, <=, last);
1412
1413 VERIFY3U(first[0], ==, 'p');
1414 VERIFY3U(first[0], ==, 'p');
1415
1416 return (parse_ppmm_expr(first, last, "({0})++", db));
1417 }
1418
1419 static const char *
1420 parse_trinary_expr(const char *first, const char *last, cpp_db_t *db)
1421 {
1422 VERIFY3P(first, <=, last);
1423
1424 const char *t1, *t2, *t3;
1425 size_t n = nlen(db);
1426
1427 if (last - first < 2)
1428 return (first);
1429
1430 t1 = parse_expression(first + 2, last, db);
1431 if (t1 == first + 2)
1432 return (first);
1433 t2 = parse_expression(t1, last, db);
1434 if (t1 == t2)
1435 return (first);
1436 t3 = parse_expression(t2, last, db);
1437 if (t3 == t2)
1438 return (first);
1439
1440 if (NAMT(db, n) != 3)
1441 return (first);
1442
1443 nfmt(db, "({2}) ? ({1}) : ({0})", NULL);
1444 return (t3);
1445 }
1446
1447 static const char *
1448 parse_noexcept_expr(const char *first, const char *last, cpp_db_t *db)
1449 {
1450 VERIFY3P(first, <=, last);
1451
1452 if (last - first < 2)
1453 return (first);
1454
1455 size_t n = nlen(db);
1456 const char *t = parse_expression(first + 2, last, db);
1457 if (t == first + 2 || NAMT(db, n) != 1)
1458 return (first);
1459
1460 nfmt(db, "noexcept ({0})", NULL);
1461 return (t);
1462 }
1463
1464 /*
1465 * cc <type> <expression> # const_cast<type> (expression)
1466 * dc <type> <expression> # dynamic_cast<type> (expression)
1467 * rc <type> <expression> # reinterpret_cast<type> (expression)
1468 * sc <type> <expression> # static_cast<type> (expression)
1469 */
1470 static const char *
1471 parse_cast_expr(const char *first, const char *last, cpp_db_t *db)
1472 {
1473 VERIFY3P(first, <=, last);
1474
1475 if (last - first < 2)
1476 return (first);
1477
1478 const char *fmt = NULL;
1479 switch (first[0]) {
1480 case 'c':
1481 fmt = "const_cast<{1}> ({0})";
1482 break;
1483 case 'd':
1484 fmt = "dynamic_cast<{1}> ({0})";
1485 break;
1486 case 'r':
1487 fmt = "reinterpret_cast<{1}> ({0})";
1488 break;
1489 case 's':
1490 fmt = "static_cast<{1}> ({0})";
1491 break;
1492 default:
1493 return (first);
1494 }
1495
1496 VERIFY3U(first[1], ==, 'c');
1497
1498 const char *t1 = parse_type(first + 2, last, db);
1499 if (t1 == first + 2)
1500 return (first);
1501
1502 const char *t2 = parse_expression(t1, last, db);
1503 if (t2 == t1)
1504 return (first);
1505
1506 VERIFY3U(nlen(db), >, 1);
1507
1508 nfmt(db, fmt, NULL);
1509 return (t2);
1510 }
1511
1512 /* pt <expression> <expression> # expr->name */
1513 static const char *
1514 parse_arrow_expr(const char *first, const char *last, cpp_db_t *db)
1515 {
1516 VERIFY3P(first, <=, last);
1517
1518 if (last - first < 4)
1519 return (first);
1520
1521 size_t n = nlen(db);
1522
1523 const char *t1 = parse_expression(first + 2, last, db);
1524 if (t1 == first + 2)
1525 return (first);
1526
1527 const char *t2 = parse_expression(t1, last, db);
1528 if (t2 == t1 || NAMT(db, n) != 2)
1529 return (first);
1530
1531 nfmt(db, "{1}->{0}", NULL);
1532 return (t2);
1533 }
1534
1535 /* wrap value in () when necessary */
1536 static void
1561 * ::= <decltype>
1562 * ::= <substitution>
1563 * ::= <CV-qualifiers> <type>
1564 * ::= P <type> # pointer-to
1565 * ::= R <type> # reference-to
1566 * ::= O <type> # rvalue reference-to (C++0x)
1567 * ::= C <type> # complex pair (C 2000)
1568 * ::= G <type> # imaginary (C 2000)
1569 * ::= Dp <type> # pack expansion (C++0x)
1570 * ::= U <source-name> <type> # vendor extended type qualifier
1571 * extension := U <objc-name> <objc-type> # objc-type<identifier>
1572 * extension := <vector-type> # <vector-type> starts with Dv
1573 *
1574 * <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
1575 * <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
1576 */
1577 /* END CSTYLED */
1578 static const char *
1579 parse_type(const char *first, const char *last, cpp_db_t *db)
1580 {
1581 VERIFY3P(first, <=, last);
1582
1583 if (first == last)
1584 return (first);
1585
1586 switch (first[0]) {
1587 case 'r':
1588 case 'V':
1589 case 'K':
1590 return (parse_qual_type(first, last, db));
1591 }
1592
1593 const char *t = first;
1594 const char *t1 = NULL;
1595 str_pair_t *sp = NULL;
1596 size_t n = nlen(db);
1597 size_t amt = 0;
1598
1599 t = parse_builtin_type(first, last, db);
1600 if (t != first)
1601 return (t);
1728
1729 nfmt(db, "{0}", NULL);
1730
1731 t1 = parse_type(t, last, db);
1732 if (t1 == t || NAMT(db, n) < 2)
1733 return (first);
1734
1735 const str_t *name = &name_at(&db->cpp_name, 1)->strp_l;
1736
1737 if (str_length(name) > 0 &&
1738 strncmp(name->str_s, "objcproto", 9) != 0) {
1739 nfmt(db, "{0} {1}", NULL);
1740 } else {
1741 t = parse_source_name(name->str_s + 9,
1742 name->str_s + name->str_len, db);
1743 if (t != name->str_s + 9) {
1744 nfmt(db, "{1}<{0}>", NULL);
1745
1746 str_pair_t save = {0};
1747
1748 name_pop(&db->cpp_name, &save);
1749
1750 /* get rid of 'objcproto' */
1751 name_pop(&db->cpp_name, NULL);
1752 CK(name_add_str(&db->cpp_name, &save.strp_l,
1753 &save.strp_r));
1754 } else {
1755 nfmt(db, "{1} {0}", NULL);
1756 }
1757 }
1758
1759 save_top(db, 1);
1760 return (t1);
1761
1762 case 'S':
1763 if (first + 1 != last && first[1] == 't') {
1764 t = parse_name(first, last, NULL, db);
1765 if (t == first || NAMT(db, n) == 0)
1766 return (first);
1767
1768 save_top(db, 1);
1769 return (t);
1770 }
1771
1826
1827 /*
1828 * must check for builtin-types before class-enum-types to avoid
1829 * ambiguities with operator-names
1830 */
1831 t = parse_builtin_type(first, last, db);
1832 if (t != first)
1833 return (t);
1834
1835 t = parse_name(first, last, NULL, db);
1836 if (t == first || NAMT(db, n) == 0)
1837 return (first);
1838
1839 save_top(db, 1);
1840 return (t);
1841 }
1842
1843 static const char *
1844 parse_qual_type(const char *first, const char *last, cpp_db_t *db)
1845 {
1846 VERIFY3P(first, <=, last);
1847
1848 const char *t = NULL;
1849 const char *t1 = NULL;
1850 unsigned cv = 0;
1851
1852 t = parse_cv_qualifiers(first, last, &cv);
1853 if (t == first)
1854 return (first);
1855
1856 size_t n = nlen(db);
1857 boolean_t is_func = !!(t[0] == 'F');
1858
1859 t1 = parse_type(t, last, db);
1860 size_t amt = NAMT(db, n);
1861 if (t == t1 || amt == 0)
1862 return (first);
1863
1864 if (is_func)
1865 sub_pop(&db->cpp_subs);
1866
1901 if (cv & 2) {
1902 str_insert(s, pos, " volatile", 9);
1903 pos += 9;
1904 }
1905 if (cv & 4) {
1906 str_insert(s, pos, " restrict", 9);
1907 }
1908 }
1909
1910 save_top(db, amt);
1911 return (t1);
1912 }
1913
1914 /*
1915 * at <type> # alignof (a type)
1916 * az <expression> # alignof (a expression)
1917 */
1918 static const char *
1919 parse_alignof(const char *first, const char *last, cpp_db_t *db)
1920 {
1921 VERIFY3P(first, <=, last);
1922
1923 if (last - first < 2)
1924 return (first);
1925
1926 const char *(*fn)(const char *, const char *, cpp_db_t *);
1927
1928 fn = (first[1] == 't') ? parse_type : parse_expression;
1929
1930 size_t n = nlen(db);
1931 const char *t = fn(first + 2, last, db);
1932 if (t == first + 2 || NAMT(db, n) != 1)
1933 return (first);
1934
1935 nfmt(db, "alignof ({0})", NULL);
1936 return (t);
1937 }
1938
1939 /*
1940 * st <type> # sizeof (a type)
1941 * sz <expr> # sizeof (a expression)
1942 */
1943 static const char *
1944 parse_sizeof(const char *first, const char *last, cpp_db_t *db)
1945 {
1946 VERIFY3P(first, <=, last);
1947
1948 if (last - first < 2)
1949 return (first);
1950
1951 VERIFY3U(first[0], ==, 's');
1952
1953 const char *t = NULL;
1954 size_t n = nlen(db);
1955
1956 switch (first[1]) {
1957 case 't':
1958 t = parse_type(first + 2, last, db);
1959 break;
1960 case 'z':
1961 t = parse_expression(first + 2, last, db);
1962 break;
1963 default:
1964 return (first);
1965 }
1966 if (t == first + 2 || NAMT(db, n) != 1)
1967 return (first);
1968
1969 nfmt(db, "sizeof ({0})", NULL);
1970 return (t);
1971 }
1972
1973 /* BEGIN CSTYLED */
1974 /*
1975 * <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter
1976 * ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
1977 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter
1978 * ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
1979 */
1980 /* END CSTYLED */
1981 static const char *
1982 parse_function_param(const char *first, const char *last, cpp_db_t *db)
1983 {
1984 VERIFY3P(first, <=, last);
1985
1986 if (last - first < 3 || first[0] != 'f')
1987 return (first);
1988
1989 const char *t1 = first + 2;
1990 const char *t2 = NULL;
1991 unsigned cv = 0;
1992
1993 if (first[1] == 'L') {
1994 t2 = parse_number(t1, last, db->cpp_loc);
1995 if (t2 == last || t2[0] != 'p')
1996 return (first);
1997 t1 = t2;
1998 }
1999
2000 if (first[1] != 'p')
2001 return (first);
2002
2003 t1 = parse_cv_qualifiers(t1, last, &cv);
2004 t2 = parse_number(t1, last, db->cpp_loc);
2005 if (t2 == last || t2[0] != '_')
2006 return (first);
2007
2008 if (t2 - t1 > 0)
2009 nadd_l(db, t1, (size_t)(t2 - t1));
2010 else
2011 nadd_l(db, "", 0);
2012
2013 nfmt(db, "fp{0}", NULL);
2014 return (t2 + 1);
2015 }
2016
2017 /*
2018 * sZ <template-param> # size of a parameter pack
2019 * sZ <function-param> # size of a function parameter pack
2020 */
2021 static const char *
2022 parse_sizeof_param_pack_expr(const char *first, const char *last, cpp_db_t *db)
2023 {
2024 VERIFY3P(first, <=, last);
2025
2026 if (last - first < 3)
2027 return (first);
2028
2029 VERIFY3U(first[0], ==, 's');
2030 VERIFY3U(first[1], ==, 'Z');
2031
2032 if (first[2] != 'T' && first[2] != 'f')
2033 return (first);
2034
2035 const char *t = NULL;
2036 size_t n = nlen(db);
2037
2038 if (first[2] == 'T')
2039 t = parse_template_param(first + 2, last, db);
2040 else
2041 t = parse_function_param(first + 2, last, db);
2042
2043 if (t == first + 2)
2044 return (first);
2045
2046 njoin(db, NAMT(db, n), ", ");
2047 nfmt(db, "sizeof...({0})", NULL);
2048 return (t);
2049 }
2050
2051 /*
2052 * te <expression> # typeid (expression)
2053 * ti <type> # typeid (type)
2054 */
2055 static const char *
2056 parse_typeid_expr(const char *first, const char *last, cpp_db_t *db)
2057 {
2058 VERIFY3P(first, <=, last);
2059
2060 if (last - first < 3)
2061 return (first);
2062
2063 VERIFY3U(first[0], ==, 't');
2064 VERIFY(first[1] == 'e' || first[1] == 'i');
2065
2066 const char *t = NULL;
2067 size_t n = nlen(db);
2068
2069 if (first[1] == 'e')
2070 t = parse_expression(first + 2, last, db);
2071 else
2072 t = parse_type(first + 2, last, db);
2073
2074 if (t == first + 2 || NAMT(db, n) != 1)
2075 return (first);
2076
2077 nfmt(db, "typeid ({0})", NULL);
2078 return (t);
2079 }
2080
2081 /*
2082 * tr # throw
2083 * tw <expression> # throw expression
2084 */
2085 static const char *
2086 parse_throw_expr(const char *first, const char *last, cpp_db_t *db)
2087 {
2088 VERIFY3P(first, <=, last);
2089
2090 if (last - first < 3)
2091 return (first);
2092
2093 VERIFY3U(first[0], ==, 't');
2094 VERIFY(first[1] == 'w' || first[1] == 'r');
2095
2096 if (first[1] == 'r') {
2097 nadd_l(db, "throw", 0);
2098 return (first + 2);
2099 }
2100
2101 size_t n = nlen(db);
2102 const char *t = parse_expression(first + 2, last, db);
2103 if (t == first + 2 || NAMT(db, n) != 1)
2104 return (first);
2105
2106 nfmt(db, "throw {0}", NULL);
2107 return (t);
2108 }
2109
2110 /* ds <expression> <expression> # expr.*expr */
2111 static const char *
2112 parse_dot_star_expr(const char *first, const char *last, cpp_db_t *db)
2113 {
2114 VERIFY3P(first, <=, last);
2115
2116 if (last - first < 3)
2117 return (first);
2118
2119 VERIFY3U(first[0], ==, 'd');
2120 VERIFY3U(first[1], ==, 's');
2121
2122 size_t n = nlen(db);
2123 const char *t = parse_expression(first + 2, last, db);
2124 if (t == first + 2)
2125 return (first);
2126
2127 const char *t2 = parse_expression(t, last, db);
2128 if (t == t2 || NAMT(db, n) != 2)
2129 return (first);
2130
2131 nfmt(db, "{1}.*{0}", NULL);
2132 return (t2);
2133 }
2134
2135 /* dt <expression> <unresolved-name> # expr.name */
2136 static const char *
2137 parse_dot_expr(const char *first, const char *last, cpp_db_t *db)
2138 {
2139 VERIFY3P(first, <=, last);
2140
2141 if (last - first < 3)
2142 return (first);
2143
2144 VERIFY3U(first[0], ==, 'd');
2145 VERIFY3U(first[1], ==, 't');
2146
2147 const char *t = parse_expression(first + 2, last, db);
2148 if (t == first + 2)
2149 return (first);
2150
2151 const char *t1 = parse_unresolved_name(t, last, db);
2152 if (t1 == t)
2153 return (first);
2154
2155 nfmt(db, "{1}.{0}", NULL);
2156 return (t1);
2157 }
2158
2159 /* cl <expression>+ E # call */
2160 static const char *
2161 parse_call_expr(const char *first, const char *last, cpp_db_t *db)
2162 {
2163 VERIFY3P(first, <=, last);
2164
2165 if (last - first < 4)
2166 return (first);
2167
2168 VERIFY3U(first[0], ==, 'c');
2169 VERIFY3U(first[1], ==, 'l');
2170
2171 const char *t = first + 2;
2172 const char *t1 = NULL;
2173 size_t n = nlen(db);
2174
2175 for (t = first + 2; t != last && t[0] != 'E'; t = t1) {
2176 t1 = parse_expression(t, last, db);
2177 if (t1 == t)
2178 return (first);
2179 }
2180
2181 size_t amt = NAMT(db, n);
2182
2183 if (t == last || amt == 0)
2184 return (first);
2185
2186 njoin(db, amt - 1, ", ");
2187 nfmt(db, "{1}({0})", NULL);
2188
2189 VERIFY3U(t[0], ==, 'E');
2190 return (t + 1);
2191 }
2192
2193 /* BEGIN CSTYLED */
2194 /*
2195 * cv <type> <expression> # conversion with one argument
2196 * cv <type> _ <expression>* E # conversion with a different number of arguments
2197 */
2198 /* END CSTYLED */
2199 static const char *
2200 parse_conv_expr(const char *first, const char *last, cpp_db_t *db)
2201 {
2202 VERIFY3P(first, <=, last);
2203
2204 if (last - first < 3)
2205 return (first);
2206
2207 VERIFY3U(first[0], ==, 'c');
2208 VERIFY3U(first[1], ==, 'v');
2209
2210 const char *t = NULL;
2211 const char *t1 = NULL;
2212 size_t n = nlen(db);
2213
2214 boolean_t try_to_parse_template_args =
2215 db->cpp_try_to_parse_template_args;
2216
2217 db->cpp_try_to_parse_template_args = B_FALSE;
2218 t = parse_type(first + 2, last, db);
2219 db->cpp_try_to_parse_template_args = try_to_parse_template_args;
2220
2221 if (t == first + 2)
2222 return (first);
2223
2224 if (t[0] != '_') {
2225 t1 = parse_expression(t, last, db);
2226 if (t1 == t)
2227 return (first);
2228
2239 t1 = t;
2240 }
2241
2242 /* E */
2243 t++;
2244
2245 njoin(db, NAMT(db, n1), ", ");
2246 }
2247
2248 if (NAMT(db, n) < 2)
2249 return (first);
2250
2251 nfmt(db, "({1})({0})", NULL);
2252 return (t);
2253 }
2254
2255 /* <simple-id> ::= <source-name> [ <template-args> ] */
2256 static const char *
2257 parse_simple_id(const char *first, const char *last, cpp_db_t *db)
2258 {
2259 VERIFY3P(first, <=, last);
2260
2261 const char *t = parse_source_name(first, last, db);
2262 if (t == first)
2263 return (t);
2264
2265 const char *t1 = parse_template_args(t, last, db);
2266 if (t == t1)
2267 return (t);
2268
2269 nfmt(db, "{1}{0}", NULL);
2270 return (t1);
2271 }
2272
2273 /*
2274 * <unresolved-type> ::= <template-param>
2275 * ::= <decltype>
2276 * ::= <substitution>
2277 */
2278 static const char *
2279 parse_unresolved_type(const char *first, const char *last, cpp_db_t *db)
2280 {
2281 VERIFY3P(first, <=, last);
2282
2283 if (first == last)
2284 return (first);
2285
2286 const char *t = first;
2287 size_t n = nlen(db);
2288
2289 switch (first[0]) {
2290 case 'T':
2291 t = parse_template_param(first, last, db);
2292 if (t == first || NAMT(db, n) != 1) {
2293 for (size_t i = 0; i < NAMT(db, n); i++)
2294 name_pop(&db->cpp_name, NULL);
2295 return (first);
2296 }
2297 save_top(db, 1);
2298 return (t);
2299
2300 case 'D':
2301 t = parse_decltype(first, last, db);
2302 if (t == first || NAMT(db, n) == 0)
2303 return (first);
2304 save_top(db, 1);
2305 return (t);
2306
2307 case 'S':
2308 t = parse_substitution(first, last, db);
2309 if (t != first)
2310 return (t);
2311
2312 if (last - first < 2 || first[1] != 't')
2313 return (first);
2314
2315 t = parse_unqualified_name(first + 2, last, db);
2316 if (t == first + 2 || NAMT(db, n) == 0)
2317 return (first);
2318
2319 nfmt(db, "std::{0:L}", "{0:R}");
2320 save_top(db, 1);
2321 return (t);
2322 }
2323
2324 return (first);
2325 }
2326
2327 /* sp <expression> # pack expansion */
2328 static const char *
2329 parse_pack_expansion(const char *first, const char *last, cpp_db_t *db)
2330 {
2331 VERIFY3P(first, <=, last);
2332
2333 if (last - first < 3)
2334 return (first);
2335
2336 VERIFY3U(first[0], ==, 's');
2337 VERIFY3U(first[1], ==, 'p');
2338
2339 const char *t = parse_expression(first + 2, last, db);
2340 if (t == first +2)
2341 return (first);
2342
2343 return (t);
2344 }
2345
2346 /*
2347 * <unscoped-name> ::= <unqualified-name>
2348 * ::= St <unqualified-name> # ::std::
2349 * extension ::= StL<unqualified-name>
2350 */
2351 static const char *
2352 parse_unscoped_name(const char *first, const char *last, cpp_db_t *db)
2353 {
2354 VERIFY3P(first, <=, last);
2355
2356 if (last - first < 2)
2357 return (first);
2358
2359 const char *t = first;
2360 const char *t1 = NULL;
2361 boolean_t st = B_FALSE;
2362
2363 if (first[0] == 'S' && first[1] == 't') {
2364 st = B_TRUE;
2365 t = first + 2;
2366
2367 if (first + 3 != last && first[2] == 'L')
2368 t++;
2369 }
2370
2371 t1 = parse_unqualified_name(t, last, db);
2372 if (t == t1)
2373 return (first);
2374
2375 if (st)
2376 nfmt(db, "std::{0}", NULL);
2377
2378 return (t1);
2379 }
2380
2381 /*
2382 * <unqualified-name> ::= <operator-name>
2383 * ::= <ctor-dtor-name>
2384 * ::= <source-name>
2385 * ::= <unnamed-type-name>
2386 */
2387 const char *
2388 parse_unqualified_name(const char *first, const char *last, cpp_db_t *db)
2389 {
2390 VERIFY3P(first, <=, last);
2391
2392 if (first == last)
2393 return (first);
2394
2395 switch (*first) {
2396 case 'C':
2397 case 'D':
2398 return (parse_ctor_dtor_name(first, last, db));
2399 case 'U':
2400 return (parse_unnamed_type_name(first, last, db));
2401
2402 case '1':
2403 case '2':
2404 case '3':
2405 case '4':
2406 case '5':
2407 case '6':
2408 case '7':
2409 case '8':
2410 case '9':
2411 return (parse_source_name(first, last, db));
2412 default:
2413 return (parse_operator_name(first, last, db));
2414 }
2415 }
2416
2417 /*
2418 * <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
2419 * ::= <closure-type-name>
2420 *
2421 * <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2422 *
2423 * <lambda-sig> ::= <parameter type>+
2424 * # Parameter types or "v" if the lambda has no parameters
2425 */
2426 static const char *
2427 parse_unnamed_type_name(const char *first, const char *last, cpp_db_t *db)
2428 {
2429 VERIFY3P(first, <=, last);
2430
2431 if (last - first < 2 || first[0] != 'U')
2432 return (first);
2433
2434 if (first[1] != 't' && first[1] != 'l')
2435 return (first);
2436
2437 const char *t1 = first + 2;
2438 const char *t2 = NULL;
2439
2440 if (first[1] == 't') {
2441 while (t1 != last && t1[0] != '_' &&
2442 isdigit_l(t1[0], db->cpp_loc))
2443 t1++;
2444
2445 if (t1[0] != '_')
2446 return (first);
2447
2448 if (t1 == first + 2)
2449 nadd_l(db, "", 0);
2450 else
2451 nadd_l(db, first + 2, (size_t)(t1 - first - 2));
2452
2453 nfmt(db, "'unnamed{0}'", NULL);
2454 return (t1 + 1);
2455 }
2456
2457 size_t n = nlen(db);
2458
2459 if (first[2] != 'v') {
2460 do {
2461 t2 = parse_type(t1, last, db);
2462 if (t1 == t2)
2465 } while (t1 != last && t1[0] != 'E');
2466
2467 if (t1 == last || NAMT(db, n) < 1)
2468 return (first);
2469
2470 if (NAMT(db, n) < 1)
2471 return (first);
2472 } else {
2473 t1++;
2474 if (t1[0] != 'E')
2475 return (first);
2476 }
2477
2478 njoin(db, NAMT(db, n), ", ");
2479
2480 /* E */
2481 t1++;
2482
2483 t2 = t1;
2484 while (t2 != last && t2[0] != '_') {
2485 if (!isdigit_l(*t2++, db->cpp_loc))
2486 return (first);
2487 }
2488
2489 if (t2[0] != '_')
2490 return (first);
2491
2492 if (t2 - t1 > 0)
2493 nadd_l(db, t1, (size_t)(t2 - t1));
2494 else
2495 nadd_l(db, "", 0);
2496
2497 nfmt(db, "'lambda{0}'({1})", NULL);
2498
2499 /* _ */
2500 return (t2 + 1);
2501 }
2502
2503 static struct {
2504 const char *alias;
2505 const char *fullname;
2558 */
2559 unsigned c = 0;
2560
2561 if (end[-1] == '>') {
2562 for (; end > start; end--) {
2563 switch (end[-1]) {
2564 case '<':
2565 if (--c == 0) {
2566 end--;
2567 goto out;
2568 }
2569 break;
2570 case '>':
2571 c++;
2572 break;
2573 }
2574 }
2575 }
2576
2577 out:
2578 VERIFY3P(end, >=, start);
2579
2580 if (end - start < 2) {
2581 nadd_l(db, "", 0);
2582 return;
2583 }
2584
2585 for (start = end - 1; start > s->str_s; start--) {
2586 if (start[0] == ':') {
2587 start++;
2588 break;
2589 }
2590 }
2591
2592 VERIFY3P(end, >=, start);
2593
2594 nadd_l(db, start, (size_t)(end - start));
2595 }
2596
2597 /*
2598 * <ctor-dtor-name> ::= C1 # complete object constructor
2599 * ::= C2 # base object constructor
2600 * ::= C3 # complete object allocating constructor
2601 * extension ::= C5 # ?
2602 * ::= D0 # deleting destructor
2603 * ::= D1 # complete object destructor
2604 * ::= D2 # base object destructor
2605 * extension ::= D5 # ?
2606 */
2607 static const char *
2608 parse_ctor_dtor_name(const char *first, const char *last, cpp_db_t *db)
2609 {
2610 VERIFY3P(first, <=, last);
2611
2612 if (last - first < 2 || nempty(db) || str_length(TOP_L(db)) == 0)
2613 return (first);
2614
2615 switch (first[0]) {
2616 case 'C':
2617 switch (first[1]) {
2618 case '1':
2619 case '2':
2620 case '3':
2621 case '5':
2622 basename(db);
2623 break;
2624 default:
2625 return (first);
2626 }
2627 break;
2628 case 'D':
2629 switch (first[1]) {
2630 case '0':
2633 case '5':
2634 basename(db);
2635 str_insert(TOP_L(db), 0, "~", 1);
2636 break;
2637 default:
2638 return (first);
2639 }
2640 break;
2641 default:
2642 return (first);
2643 }
2644
2645 db->cpp_parsed_ctor_dtor_cv = B_TRUE;
2646 return (first + 2);
2647 }
2648
2649 static const char *
2650 parse_integer_literal(const char *first, const char *last, const char *fmt,
2651 cpp_db_t *db)
2652 {
2653 VERIFY3P(first, <=, last);
2654
2655 const char *t = parse_number(first, last, db->cpp_loc);
2656 const char *start = first;
2657
2658 if (t == first || t == last || t[0] != 'E')
2659 return (first);
2660
2661 if (first[0] == 'n')
2662 start++;
2663
2664 nadd_l(db, start, (size_t)(t - start));
2665 if (start != first)
2666 nfmt(db, "-{0}", NULL);
2667
2668 nfmt(db, fmt, NULL);
2669 return (t + 1);
2670 }
2671
2672 static struct float_data_s {
2673 const char *spec;
2674 size_t mangled_size;
2675 size_t max_demangled_size;
2676 char type;
2677 } float_info[] = {
2678 { "%af", 8, 24, 'f' }, /* float */
2679 { "%a", 16, 32, 'd' }, /* double */
2680 { "%LaL", 20, 40, 'e' } /* long double */
2681 };
2682
2683 static const char *
2684 parse_floating_literal(const char *first, const char *last, cpp_db_t *db)
2685 {
2686 VERIFY3P(first, <=, last);
2687 VERIFY(first[0] == 'f' || first[0] == 'd' || first[0] == 'e');
2688
2689 const struct float_data_s *fd = NULL;
2690
2691 for (size_t i = 0; i < ARRAY_SIZE(float_info); i++) {
2692 if (float_info[i].type != first[0])
2693 continue;
2694
2695 fd = &float_info[i];
2696 break;
2697 }
2698
2699 if (fd == NULL || (size_t)(last - first) < fd->mangled_size)
2700 return (first);
2701
2702 union {
2703 union {
2704 float v;
2705 char buf[sizeof (float)];
2706 } f;
2707 union {
2718 char *e = NULL;
2719
2720 switch (first[0]) {
2721 case 'f':
2722 e = conv.f.buf;
2723 break;
2724 case 'd':
2725 e = conv.d.buf;
2726 break;
2727 case 'e':
2728 e = conv.ld.buf;
2729 break;
2730 }
2731 last = first + fd->mangled_size + 1;
2732
2733 #if defined(_BIG_ENDIAN)
2734 for (t = first + 1; t != last; t++, e++) {
2735 if (!is_xdigit(t[0]))
2736 return (first);
2737
2738 unsigned d1 = isdigit_l(t[0], db->cpp_loc) ? t[0] - '0' : t[0] - 'a' + 10;
2739 t++;
2740 unsigned d0 = isdigit_l(t[0], db->cpp_loc) ? t[0] - '0' : t[0] - 'a' + 10;
2741
2742 *e = (d1 << 4) + d0;
2743 }
2744 #elif defined(_LITTLE_ENDIAN)
2745 for (t = last - 1; t > first; t--, e++) {
2746 if (!is_xdigit(t[0]))
2747 return (first);
2748
2749 unsigned d0 = isdigit_l(t[0], db->cpp_loc) ? t[0] - '0' : t[0] - 'a' + 10;
2750 t--;
2751 unsigned d1 = isdigit_l(t[0], db->cpp_loc) ? t[0] - '0' : t[0] - 'a' + 10;
2752
2753 *e = (d1 << 4) + d0;
2754 }
2755 t = last;
2756 #else
2757 #error One of _BIG_ENDIAN or _LITTLE_ENDIAN must be defined
2758 #endif
2759
2760 if (t[0] != 'E')
2761 return (first);
2762
2763 str_t num = { 0 };
2764 str_init(&num, db->cpp_ops);
2765
2766 num.str_size = fd->max_demangled_size + 1;
2767 num.str_s = zalloc(db->cpp_ops, num.str_size);
2768 CK(num.str_s != NULL);
2769
2770 int n = 0;
2771
2812 } int_lits[] = {
2813 { 'a', "(signed char){0}" },
2814 { 'c', "(char){0}" },
2815 { 'h', "(unsigned char){0}" },
2816 { 'i', "{0}" },
2817 { 'j', "{0}u" },
2818 { 'l', "{0}l" },
2819 { 'm', "{0}ul" },
2820 { 'n', "(__int128){0}" },
2821 { 'o', "(unsigned __int128){0}" },
2822 { 's', "(short){0}" },
2823 { 't', "(unsigned short){0}" },
2824 { 'w', "(wchar_t){0}" },
2825 { 'x', "{0}ll" },
2826 { 'y', "{0}ull" }
2827 };
2828
2829 static const char *
2830 parse_expr_primary(const char *first, const char *last, cpp_db_t *db)
2831 {
2832 VERIFY3P(first, <=, last);
2833
2834 if (last - first < 4 || first[0] != 'L')
2835 return (first);
2836
2837 const char *t = NULL;
2838
2839 for (size_t i = 0; i < ARRAY_SIZE(int_lits); i++) {
2840 if (first[1] == int_lits[i].c) {
2841 t = parse_integer_literal(first + 2, last,
2842 int_lits[i].fmt, db);
2843 return ((t == first + 2) ? first : t);
2844 }
2845 }
2846
2847 switch (first[1]) {
2848 case 'b':
2849 if (first[3] != 'E')
2850 return (first);
2851
2852 switch (first[2]) {
2876 return (first);
2877 case '_':
2878 if (first[2] != 'Z')
2879 return (first);
2880
2881 t = parse_encoding(first + 3, last, db);
2882 if (t == first + 3 || t == last || t[0] != 'E')
2883 return (first);
2884
2885 /* skip E */
2886 return (t + 1);
2887 default:
2888 t = parse_type(first + 1, last, db);
2889 if (t == first + 1 || t == last)
2890 return (first);
2891
2892 if (t[0] == 'E')
2893 return (t + 1);
2894
2895 const char *n;
2896 for (n = t; n != last && isdigit_l(n[0], db->cpp_loc); n++)
2897 ;
2898 if (n == last || nempty(db) || n[0] != 'E')
2899 return (first);
2900 if (n == t)
2901 return (t);
2902
2903 nadd_l(db, t, (size_t)(n - t));
2904 nfmt(db, "({1}){0}", NULL);
2905
2906 return (n + 1);
2907 }
2908 }
2909
2910 /*
2911 * <operator-name>
2912 * ::= aa # &&
2913 * ::= ad # & (unary)
2914 * ::= an # &
2915 * ::= aN # &=
2916 * ::= aS # =
2999 { "nw", "operator new" },
3000 { "oo", "operator||" },
3001 { "or", "operator|" },
3002 { "oR", "operator|=" },
3003 { "pm", "operator->*" },
3004 { "pl", "operator+" },
3005 { "pL", "operator+=" },
3006 { "pp", "operator++" },
3007 { "ps", "operator+" },
3008 { "pt", "operator->" },
3009 { "qu", "operator?" },
3010 { "rm", "operator%" },
3011 { "rM", "operator%=" },
3012 { "rs", "operator>>" },
3013 { "rS", "operator>>=" }
3014 };
3015
3016 static const char *
3017 parse_operator_name(const char *first, const char *last, cpp_db_t *db)
3018 {
3019 VERIFY3P(first, <=, last);
3020
3021 if (last - first < 2)
3022 return (first);
3023
3024 for (size_t i = 0; i < ARRAY_SIZE(op_tbl); i++) {
3025 if (strncmp(first, op_tbl[i].code, 2) != 0)
3026 continue;
3027
3028 nadd_l(db, op_tbl[i].op, 0);
3029 return (first + 2);
3030 }
3031
3032 const char *t = NULL;
3033
3034 if (first[0] == 'l' && first[1] == 'i') {
3035 t = parse_source_name(first + 2, last, db);
3036 if (t == first + 2 || nempty(db))
3037 return (first);
3038
3039 nfmt(db, "operator\"\" {0}", NULL);
3040 return (t);
3041 }
3042
3043 if (first[0] == 'v') {
3044 if (!isdigit_l(first[1], db->cpp_loc))
3045 return (first);
3046
3047 t = parse_source_name(first + 2, last, db);
3048 if (t == first + 2)
3049 return (first);
3050
3051 nfmt(db, "operator {0}", NULL);
3052 return (t);
3053 }
3054
3055 if (first[0] != 'c' && first[1] != 'v')
3056 return (first);
3057
3058 boolean_t try_to_parse_template_args =
3059 db->cpp_try_to_parse_template_args;
3060
3061 db->cpp_try_to_parse_template_args = B_FALSE;
3062 t = parse_type(first + 2, last, db);
3063 db->cpp_try_to_parse_template_args = try_to_parse_template_args;
3064
3097 { 'x', "long long" },
3098 { 'y', "unsigned long long" },
3099 { 'z', "..." }
3100 };
3101
3102 static struct type_tbl_s type_tbl2[] = {
3103 { 'a', "auto" },
3104 { 'c', "decltype(auto)" },
3105 { 'd', "decimal64" },
3106 { 'e', "decimal128" },
3107 { 'f', "decimal32" },
3108 { 'h', "decimal16" },
3109 { 'i', "char32_t" },
3110 { 'n', "std::nullptr_t" },
3111 { 's', "char16_t" }
3112 };
3113
3114 static const char *
3115 parse_builtin_type(const char *first, const char *last, cpp_db_t *db)
3116 {
3117 VERIFY3P(first, <=, last);
3118
3119 if (first == last)
3120 return (first);
3121
3122 size_t i;
3123
3124 for (i = 0; i < ARRAY_SIZE(type_tbl1); i++) {
3125 if (first[0] == type_tbl1[i].code) {
3126 nadd_l(db, type_tbl1[i].name, 0);
3127 return (first + 1);
3128 }
3129 }
3130
3131 if (first[0] == 'D') {
3132 if (first + 1 == last)
3133 return (first);
3134 for (i = 0; i < ARRAY_SIZE(type_tbl2); i++) {
3135 if (first[1] == type_tbl2[i].code) {
3136 nadd_l(db, type_tbl2[i].name, 0);
3137 return (first + 2);
3138 }
3139 }
3140 }
3141
3142 if (first[0] == 'u') {
3143 const char *t = parse_source_name(first + 1, last, db);
3144 if (t == first + 1)
3145 return (first);
3146 return (t);
3147 }
3148
3149 return (first);
3150 }
3151
3152 static const char *
3153 parse_base36(const char *first, const char *last, size_t *val, locale_t loc)
3154 {
3155 VERIFY3P(first, <=, last);
3156
3157 const char *t;
3158
3159 for (t = first, *val = 0; t != last; t++) {
3160 if (!isdigit_l(t[0], loc) && !isupper_l(t[0], loc))
3161 return (t);
3162
3163 *val *= 36;
3164
3165 if (isdigit_l(t[0], loc))
3166 *val += t[0] - '0';
3167 else
3168 *val += t[0] - 'A' + 10;
3169 }
3170 return (t);
3171 }
3172
3173 static struct type_tbl_s sub_tbl[] = {
3174 { 'a', "std::allocator" },
3175 { 'b', "std::basic_string" },
3176 { 's', "std::string" },
3177 { 'i', "std::istream" },
3178 { 'o', "std::ostream" },
3179 { 'd', "std::iostream" }
3180 };
3181
3182 static const char *
3183 parse_substitution(const char *first, const char *last, cpp_db_t *db)
3184 {
3185 VERIFY3P(first, <=, last);
3186
3187 if (first == last || last - first < 2)
3188 return (first);
3189
3190 if (first[0] != 'S')
3191 return (first);
3192
3193 for (size_t i = 0; i < ARRAY_SIZE(sub_tbl); i++) {
3194 if (first[1] == sub_tbl[i].code) {
3195 nadd_l(db, sub_tbl[i].name, 0);
3196 return (first + 2);
3197 }
3198 }
3199
3200 const char *t = first + 1;
3201 size_t n = 0;
3202
3203 if (t[0] != '_') {
3204 t = parse_base36(first + 1, last, &n, db->cpp_loc);
3205 if (t == first + 1 || t[0] != '_')
3206 return (first);
3207
3208 /*
3209 * S_ == substitution 0,
3210 * S0_ == substituion 1,
3211 * ...
3212 */
3213 n++;
3214 }
3215
3216 if (n >= sub_len(&db->cpp_subs))
3217 return (first);
3218
3219 sub(db, n);
3220
3221 /* skip _ */
3222 VERIFY3U(t[0], ==, '_');
3223
3224 return (t + 1);
3225 }
3226
3227 static const char *
3228 parse_source_name(const char *first, const char *last, cpp_db_t *db)
3229 {
3230 VERIFY3P(first, <=, last);
3231
3232 if (first == last)
3233 return (first);
3234
3235 const char *t = NULL;
3236 size_t n = 0;
3237
3238 for (t = first; t != last && isdigit_l(t[0], db->cpp_loc); t++) {
3239 /* make sure we don't overflow */
3240 size_t nn = n * 10;
3241 if (nn < n)
3242 return (first);
3243
3244 nn += t[0] - '0';
3245 if (nn < n)
3246 return (first);
3247
3248 n = nn;
3249 }
3250
3251 if (n == 0 || t == last || t + n > last ||
3252 (uintptr_t)t + n < (uintptr_t)t)
3253 return (first);
3254
3255 if (strncmp(t, "_GLOBAL__N", 10) == 0)
3256 nadd_l(db, "(anonymous namespace)", 0);
3257 else
3258 nadd_l(db, t, n);
3259
3260 return (t + n);
3261 }
3262
3263 /*
3264 * extension:
3265 * <vector-type> ::= Dv <positive dimension number> _
3266 * <extended element type>
3267 * ::= Dv [<dimension expression>] _ <element type>
3268 * <extended element type> ::= <element type>
3269 * ::= p # AltiVec vector pixel
3270 */
3271 static const char *
3272 parse_vector_type(const char *first, const char *last, cpp_db_t *db)
3273 {
3274 VERIFY3P(first, <=, last);
3275
3276 if (last - first < 3)
3277 return (first);
3278
3279 VERIFY3U(first[0], ==, 'D');
3280 VERIFY3U(first[1], ==, 'v');
3281
3282 const char *t = first + 2;
3283 const char *t1 = NULL;
3284
3285 if (isdigit_l(first[2], db->cpp_loc) && first[2] != '0') {
3286 t1 = parse_number(t, last, db->cpp_loc);
3287 if (t1 == last || t1 + 1 == last || t1[0] != '_')
3288 return (first);
3289
3290 nadd_l(db, t, (size_t)(t1 - t));
3291
3292 /* skip _ */
3293 t = t1 + 1;
3294
3295 if (t[0] != 'p') {
3296 t1 = parse_type(t, last, db);
3297 if (t1 == t)
3298 return (first);
3299
3300 nfmt(db, "{0} vector[{1}]", NULL);
3301 return (t1);
3302 }
3303 nfmt(db, "{0} pixel vector[{1}]", NULL);
3304 return (t1);
3305 }
3306
3315 nadd_l(db, "", 0);
3316 }
3317
3318 t1 = parse_type(t, last, db);
3319 if (t == t1)
3320 return (first);
3321
3322 nfmt(db, "{1:L} vector[{0}]", "{1:R}");
3323 return (t1);
3324 }
3325
3326 /* BEGIN CSTYLED */
3327 /*
3328 * <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3329 * ::= DT <expression> E # decltype of an expression (C++0x)
3330 */
3331 /* END CSTYLED */
3332 static const char *
3333 parse_decltype(const char *first, const char *last, cpp_db_t *db)
3334 {
3335 VERIFY3P(first, <=, last);
3336
3337 if (last - first < 4)
3338 return (first);
3339
3340 VERIFY3U(first[0], ==, 'D');
3341
3342 if (first[1] != 't' && first[1] != 'T')
3343 return (first);
3344
3345 size_t n = nlen(db);
3346 const char *t = parse_expression(first + 2, last, db);
3347 if (NAMT(db, n) != 1 || t == first + 2 || t == last || t[0] != 'E')
3348 return (first);
3349
3350 nfmt(db, "decltype({0})", NULL);
3351
3352 /* skip E */
3353 return (t + 1);
3354 }
3355
3356 /*
3357 * <array-type> ::= A <positive dimension number> _ <element type>
3358 * ::= A [<dimension expression>] _ <element type>
3359 */
3360 static const char *
3361 parse_array_type(const char *first, const char *last, cpp_db_t *db)
3362 {
3363 VERIFY3P(first, <=, last);
3364 VERIFY3U(first[0], ==, 'A');
3365
3366 if (last - first < 3)
3367 return (first);
3368
3369 const char *t = first + 1;
3370 const char *t1 = NULL;
3371 size_t n = nlen(db);
3372
3373 if (t[0] != '_') {
3374 if (isdigit_l(t[0], db->cpp_loc) && t[0] != '0') {
3375 t1 = parse_number(t, last, db->cpp_loc);
3376 if (t1 == last)
3377 return (first);
3378
3379 nadd_l(db, t, (size_t)(t1 - t));
3380 } else {
3381 t1 = parse_expression(t, last, db);
3382 if (t1 == last || t == t1)
3383 return (first);
3384 }
3385
3386 if (t1[0] != '_')
3387 return (first);
3388
3389 t = t1;
3390 } else {
3391 nadd_l(db, "", 0);
3392 }
3393
3394 VERIFY3U(t[0], ==, '_');
3395
3396 t1 = parse_type(t + 1, last, db);
3397 if (t1 == t + 1 || NAMT(db, n) != 2)
3398 return (first);
3399
3400 /*
3401 * if we have " [xxx]" already, want new result to be
3402 * " [yyy][xxx]"
3403 */
3404 str_t *r = &name_top(&db->cpp_name)->strp_r;
3405 if (r->str_len > 1 && r->str_s[0] == ' ' && r->str_s[1] == '[')
3406 str_erase(r, 0, 1);
3407
3408 nfmt(db, "{0:L}", " [{1}]{0:R}");
3409 return (t1);
3410 }
3411
3412 /* <pointer-to-member-type> ::= M <class type> <member type> */
3413 static const char *
3414 parse_pointer_to_member_type(const char *first, const char *last, cpp_db_t *db)
3415 {
3416 VERIFY3P(first, <=, last);
3417
3418 if (last - first < 3)
3419 return (first);
3420
3421 VERIFY3U(first[0], ==, 'M');
3422
3423 const char *t1 = first + 1;
3424 const char *t2 = NULL;
3425 size_t n = nlen(db);
3426
3427 t2 = parse_type(t1, last, db);
3428 if (t1 == t2)
3429 return (first);
3430
3431 t1 = t2;
3432 t2 = parse_type(t1, last, db);
3433 if (t1 == t2)
3434 return (first);
3435
3436 if (NAMT(db, n) != 2)
3437 return (first);
3438
3439 str_pair_t *func = name_top(&db->cpp_name);
3440
3441 if (str_length(&func->strp_r) > 0 && func->strp_r.str_s[0] == '(')
3445
3446 return (t2);
3447 }
3448
3449 /* BEGIN CSTYLED */
3450 /*
3451 * <unresolved-name>
3452 * extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3453 * ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3454 * ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3455 * # A::x, N::y, A<T>::z; "gs" means leading "::"
3456 * ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3457 * extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3458 * # T::N::x /decltype(p)::N::x
3459 * (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3460 */
3461 /* END CSTYLED */
3462 static const char *
3463 parse_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3464 {
3465 VERIFY3P(first, <=, last);
3466
3467 if (last - first < 2)
3468 return (first);
3469
3470 const char *t = first;
3471 const char *t2 = NULL;
3472 boolean_t global = B_FALSE;
3473 size_t n;
3474
3475 if (t[0] == 'g' && t[1] == 's') {
3476 global = B_TRUE;
3477 t += 2;
3478 }
3479 if (t == last)
3480 return (first);
3481
3482 t2 = parse_base_unresolved_name(t, last, db);
3483 if (t != t2) {
3484 if (global) {
3485 if (nempty(db))
3493 if (t[0] != 's' || t[1] != 'r' || last - t < 2)
3494 return (first);
3495
3496 n = nlen(db);
3497 if (t[2] == 'N') {
3498 t += 3;
3499 t2 = parse_unresolved_type(t, last, db);
3500 if (t2 == t || t2 == last)
3501 return (first);
3502 t = t2;
3503
3504 t2 = parse_template_args(t, last, db);
3505 if (t2 != t) {
3506 if (NAMT(db, n) < 2 || t2 == last)
3507 return (first);
3508
3509 nfmt(db, "{1:L}{0}", "{1:R}");
3510 t = t2;
3511 }
3512
3513 VERIFY3U(NAMT(db, n), ==, 1);
3514
3515 while (t[0] != 'E') {
3516 size_t nn = nlen(db);
3517 t2 = parse_unresolved_qualifier_level(t, last, db);
3518 if (t == t2 || t == last || NAMT(db, nn) != 1)
3519 return (first);
3520
3521 t = t2;
3522 }
3523
3524 /* skip E */
3525 t++;
3526
3527 t2 = parse_base_unresolved_name(t, last, db);
3528 if (t == t2 || NAMT(db, n) < 2)
3529 return (first);
3530
3531 njoin(db, NAMT(db, n), "::");
3532 return (t2);
3533 }
3565
3566 t = t2;
3567 }
3568
3569 /* skip E */
3570 t++;
3571
3572 t2 = parse_base_unresolved_name(t, last, db);
3573 if (t == t2 || nlen(db) < 2)
3574 return (first);
3575
3576 njoin(db, NAMT(db, n), "::");
3577 return (t2);
3578 }
3579
3580 /* <unresolved-qualifier-level> ::= <simple-id> */
3581 static const char *
3582 parse_unresolved_qualifier_level(const char *first, const char *last,
3583 cpp_db_t *db)
3584 {
3585 VERIFY3P(first, <=, last);
3586 return (parse_simple_id(first, last, db));
3587 }
3588
3589 /* BEGIN CSTYLED */
3590 /*
3591 * <base-unresolved-name> ::= <simple-id> # unresolved name
3592 * extension ::= <operator-name> # unresolved operator-function-id
3593 * extension ::= <operator-name> <template-args> # unresolved operator template-id
3594 * ::= on <operator-name> # unresolved operator-function-id
3595 * ::= on <operator-name> <template-args> # unresolved operator template-id
3596 * ::= dn <destructor-name> # destructor or pseudo-destructor;
3597 * # e.g. ~X or ~X<N-1>
3598 */
3599 /* END CSTYLED */
3600 static const char *
3601 parse_base_unresolved_name(const char *first, const char *last, cpp_db_t *db)
3602 {
3603 VERIFY3P(first, <=, last);
3604
3605 if (last - first < 2)
3606 return (first);
3607
3608 const char *t = NULL;
3609 const char *t1 = NULL;
3610
3611 if ((first[0] != 'o' && first[0] != 'd') || first[1] != 'n') {
3612 t = parse_simple_id(first, last, db);
3613 if (t != first)
3614 return (t);
3615
3616 t = parse_operator_name(first, last, db);
3617 if (t == first)
3618 return (first);
3619
3620 t1 = parse_template_args(t, last, db);
3621 if (t1 != t) {
3622 if (nlen(db) < 2)
3623 return (first);
3632 return ((t != first + 2) ? t : first);
3633 }
3634
3635 t = parse_operator_name(first + 2, last, db);
3636 if (t == first + 2)
3637 return (first);
3638
3639 t1 = parse_template_args(t, last, db);
3640 if (t1 != t)
3641 nfmt(db, "{1:L}{0}", "{1:R}");
3642 return (t1);
3643 }
3644
3645 /*
3646 * <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3647 * ::= <simple-id> # e.g., ~A<2*N>
3648 */
3649 static const char *
3650 parse_destructor_name(const char *first, const char *last, cpp_db_t *db)
3651 {
3652 VERIFY3P(first, <=, last);
3653
3654 if (first == last)
3655 return (first);
3656
3657 const char *t = parse_unresolved_type(first, last, db);
3658
3659 if (t == first)
3660 t = parse_simple_id(first, last, db);
3661
3662 if (t == first)
3663 return (first);
3664
3665 nfmt(db, "~{0:L}", "{0:R}");
3666 return (t);
3667 }
3668
3669 /*
3670 * <ref-qualifier> ::= R # & ref-qualifier
3671 * <ref-qualifier> ::= O # && ref-qualifier
3672 *
3673 * <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
3674 */
3675 static const char *
3676 parse_function_type(const char *first, const char *last, cpp_db_t *db)
3677 {
3678 VERIFY3P(first, <=, last);
3679
3680 if (last - first < 2)
3681 return (first);
3682
3683 VERIFY3U(first[0], ==, 'F');
3684
3685 const char *t = first + 1;
3686
3687 /* extern "C" */
3688 if (t[0] == 'Y')
3689 t++;
3690
3691 const char *t1 = parse_type(t, last, db);
3692 if (t1 == t)
3693 return (first);
3694
3695 size_t n = nlen(db);
3696 int ref_qual = 0;
3697
3698 t = t1;
3699
3700 while (t != last && t[0] != 'E') {
3701 if (t[0] == 'v') {
3702 t++;
3703 continue;
3734 nfmt(db, "{0} &", NULL);
3735 break;
3736 case 2:
3737 nfmt(db, "{0} &&", NULL);
3738 break;
3739 }
3740
3741 nfmt(db, "{1:L} ", "{0}{1:R}");
3742
3743 /* skip E */
3744 return (t + 1);
3745 }
3746
3747 /*
3748 * <template-param> ::= T_ # first template parameter
3749 * ::= T <parameter-2 non-negative number> _
3750 */
3751 static const char *
3752 parse_template_param(const char *first, const char *last, cpp_db_t *db)
3753 {
3754 VERIFY3P(first, <=, last);
3755
3756 if (last - first < 2 || first[0] != 'T')
3757 return (first);
3758
3759 const char *t = first + 1;
3760 size_t idx = 0;
3761
3762 while (t != last && t[0] != '_') {
3763 if (!isdigit_l(t[0], db->cpp_loc))
3764 return (first);
3765
3766 idx *= 10;
3767 idx += t[0] - '0';
3768 t++;
3769 }
3770
3771 if (t == last)
3772 return (first);
3773
3774 VERIFY3U(t[0], ==, '_');
3775
3776 /*
3777 * T_ -> idx 0
3778 * T0 -> idx 1
3779 * T1 -> idx 2
3780 * ...
3781 */
3782 if (first[1] != '_')
3783 idx++;
3784
3785 /* skip _ */
3786 t++;
3787
3788 if (tempty(db))
3789 return (first);
3790
3791 if (idx >= ttlen(db)) {
3792 nadd_l(db, first, (size_t)(t - first));
3793 db->cpp_fix_forward_references = B_TRUE;
3794 return (t);
3795 }
3796
3797 tsub(db, idx);
3798 return (t);
3799 }
3800
3801 /*
3802 * <template-args> ::= I <template-arg>* E
3803 * extension, the abi says <template-arg>+
3804 */
3805 static const char *
3806 parse_template_args(const char *first, const char *last, cpp_db_t *db)
3807 {
3808 VERIFY3P(first, <=, last);
3809
3810 if (last - first < 2 || first[0] != 'I')
3811 return (first);
3812
3813 if (db->cpp_tag_templates)
3814 sub_clear(templ_top(&db->cpp_templ));
3815
3816 const char *t = first + 1;
3817 size_t n = nlen(db);
3818
3819 while (t[0] != 'E') {
3820 if (db->cpp_tag_templates)
3821 tpush(db);
3822
3823 size_t n1 = nlen(db);
3824 const char *t1 = parse_template_arg(t, last, db);
3825
3826 if (db->cpp_tag_templates)
3827 tpop(db);
3828
3829 if (t1 == t || t == last)
3830 return (first);
3831
3832 if (db->cpp_tag_templates)
3833 tsave(db, NAMT(db, n1));
3834
3835 t = t1;
3836 }
3837
3838 /*
3839 * ugly, but if the last thing pushed was an empty string,
3840 * get rid of it so we dont get "<..., >"
3841 */
3842 if (NAMT(db, n) > 1 &&
3843 str_pair_len(name_top(&db->cpp_name)) == 0)
3844 name_pop(&db->cpp_name, NULL);
3845
3846 njoin(db, NAMT(db, n), ", ");
3847
3848 VERIFY3U(nlen(db), >, 0);
3849
3850 /* make sure we don't bitshift ourselves into oblivion */
3851 str_t *top = TOP_L(db);
3852 if (str_length(top) > 0 &&
3853 top->str_s[top->str_len - 1] == '>')
3854 nfmt(db, "<{0} >", NULL);
3855 else
3856 nfmt(db, "<{0}>", NULL);
3857
3858 /* skip E */
3859 return (t + 1);
3860 }
3861
3862 /*
3863 * <discriminator> := _ <non-negative number> # when number < 10
3864 * := __ <non-negative number> _ # when number >= 10
3865 * extension := decimal-digit+ # at the end of string
3866 */
3867 static const char *
3868 parse_discriminator(const char *first, const char *last, locale_t loc)
3869 {
3870 VERIFY3P(first, <=, last);
3871
3872 const char *t = NULL;
3873
3874 if (first == last)
3875 return (first);
3876
3877 if (isdigit_l(first[0], loc)) {
3878 for (t = first; t != last && isdigit_l(t[0], loc); t++)
3879 ;
3880
3881 /* not at the end of the string */
3882 if (t != last)
3883 return (first);
3884
3885 return (t);
3886 } else if (first[0] != '_' || first + 1 == last) {
3887 return (first);
3888 }
3889
3890 t = first + 1;
3891 if (isdigit_l(t[0], loc))
3892 return (t + 1);
3893
3894 if (t[0] != '_' || t + 1 == last)
3895 return (first);
3896
3897 for (t++; t != last && isdigit_l(t[0], loc); t++)
3898 ;
3899 if (t == last || t[0] != '_')
3900 return (first);
3901
3902 return (t);
3903 }
3904
3905 /* <CV-qualifiers> ::= [r] [V] [K] */
3906 const char *
3907 parse_cv_qualifiers(const char *first, const char *last, unsigned *cv)
3908 {
3909 VERIFY3P(first, <=, last);
3910
3911 if (first == last)
3912 return (first);
3913
3914 *cv = 0;
3915 if (first[0] == 'r') {
3916 *cv |= CPP_QUAL_RESTRICT;
3917 first++;
3918 }
3919 if (first != last && first[0] == 'V') {
3920 *cv |= CPP_QUAL_VOLATILE;
3921 first++;
3922 }
3923 if (first != last && first[0] == 'K') {
3924 *cv |= CPP_QUAL_CONST;
3925 first++;
3926 }
3927
3928 return (first);
3929 }
3930
3931 /*
3932 * <number> ::= [n] <non-negative decimal integer>
3933 */
3934 static const char *
3935 parse_number(const char *first, const char *last, locale_t loc)
3936 {
3937 VERIFY3P(first, <=, last);
3938
3939 const char *t = first;
3940
3941 if (first == last || (first[0] != 'n' && !isdigit_l(first[0], loc)))
3942 return (first);
3943
3944 if (t[0] == 'n')
3945 t++;
3946
3947 if (t[0] == '0')
3948 return (t + 1);
3949
3950 while (isdigit_l(t[0], loc))
3951 t++;
3952
3953 return (t);
3954 }
3955
3956 /*
3957 * Like isxdigit(3C), except we can only accept lower case letters as
3958 * that's only what is allowed when [de]mangling floating point constants into
3959 * their hex representation.
3960 */
3961 static inline boolean_t
3962 is_xdigit(int c)
3963 {
3964 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'))
3965 return (B_TRUE);
3966 return (B_FALSE);
3967 }
3968
3969 static boolean_t
3970 nempty(cpp_db_t *db)
3971 {
3972 return (name_empty(&db->cpp_name));
3973 }
3974
3975 static size_t
3976 nlen(cpp_db_t *db)
3977 {
3978 return (name_len(&db->cpp_name));
3979 }
3980
3981 static void
4029 }
4030
4031 static void
4032 tpush(cpp_db_t *db)
4033 {
4034 CK(templ_push(&db->cpp_templ));
4035 }
4036
4037 static void
4038 tpop(cpp_db_t *db)
4039 {
4040 templ_pop(&db->cpp_templ);
4041 }
4042
4043 static void
4044 tsave(cpp_db_t *db, size_t amt)
4045 {
4046 CK(templ_save(&db->cpp_name, amt, &db->cpp_templ));
4047 }
4048
4049 static boolean_t
4050 db_init(cpp_db_t *db, sysdem_ops_t *ops)
4051 {
4052 (void) memset(db, 0, sizeof (*db));
4053 db->cpp_ops = ops;
4054 name_init(&db->cpp_name, ops);
4055 sub_init(&db->cpp_subs, ops);
4056 templ_init(&db->cpp_templ, ops);
4057 db->cpp_tag_templates = B_TRUE;
4058 db->cpp_try_to_parse_template_args = B_TRUE;
4059 tpush(db);
4060 db->cpp_loc = newlocale(LC_CTYPE_MASK, "C", 0);
4061 return ((db->cpp_loc != NULL) ? B_TRUE : B_FALSE);
4062 }
4063
4064 static void
4065 db_fini(cpp_db_t *db)
4066 {
4067 name_fini(&db->cpp_name);
4068 sub_fini(&db->cpp_subs);
4069 templ_fini(&db->cpp_templ);
4070 freelocale(db->cpp_loc);
4071 (void) memset(db, 0, sizeof (*db));
4072 }
4073
4074 static void
4075 print_sp(const str_pair_t *sp, FILE *out)
4076 {
4077 (void) fprintf(out, "{%.*s#%.*s}",
4078 (int)sp->strp_l.str_len, sp->strp_l.str_s,
4079 (int)sp->strp_r.str_len, sp->strp_r.str_s);
4080 }
4081
4082 static void
4083 print_name(const name_t *n, FILE *out)
4084 {
4085 const str_pair_t *sp = name_top((name_t *)n);
4086 size_t i;
4087
4088 (void) fprintf(out, "Name:\n");
4089
4090 if (name_len(n) == 0)
4091 return;
4092
4093 for (i = 0; i < n->nm_len; i++, sp--) {
4094 (void) fprintf(out, " [%02zu] ", i);
4095 print_sp(sp, out);
4096 (void) fputc('\n', out);
4097 }
4098
4099 (void) fputc('\n', out);
4100 }
4101
4102 /* Print a base-36 number (for substitutions) */
4103 static char *
4104 base36(char *buf, size_t val)
4105 {
4106 char tmp[16] = { 0 };
4107 char *p = tmp;
4108
4109 if (val == 0) {
4110 buf[0] = '0';
4111 buf[1] = '\0';
4112 return (buf);
4113 }
4114
4115 while (val > 0) {
4116 size_t r = val % 36;
4117
4118 if (r < 10)
4119 *p++ = r + '0';
4120 else
4121 *p++ = r - 10 + 'A';
4122
|