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 *);
124 static const char *parse_cast_expr(const char *, const char *, cpp_db_t *);
125 static const char *parse_sizeof_param_pack_expr(const char *, const char *,
126 cpp_db_t *);
127 static const char *parse_typeid_expr(const char *, const char *, cpp_db_t *);
128 static const char *parse_throw_expr(const char *, const char *, cpp_db_t *);
129 static const char *parse_dot_star_expr(const char *, const char *, cpp_db_t *);
130 static const char *parse_dot_expr(const char *, const char *, cpp_db_t *);
131 static const char *parse_call_expr(const char *, const char *, cpp_db_t *);
132 static const char *parse_arrow_expr(const char *, const char *, cpp_db_t *);
133 static const char *parse_conv_expr(const char *, const char *, cpp_db_t *);
134 static const char *parse_function_param(const char *, const char *, cpp_db_t *);
135 static const char *parse_base_unresolved_name(const char *, const char *,
136 cpp_db_t *);
137 static const char *parse_unresolved_name(const char *, const char *,
138 cpp_db_t *);
139 static const char *parse_noexcept_expr(const char *, const char *, cpp_db_t *);
140 static const char *parse_alignof(const char *, const char *, cpp_db_t *);
141 static const char *parse_sizeof(const char *, const char *, cpp_db_t *);
142 static const char *parse_unnamed_type_name(const char *, const char *,
143 cpp_db_t *);
144 static const char *parse_ctor_dtor_name(const char *, const char *, cpp_db_t *);
145 static const char *parse_source_name(const char *, const char *, cpp_db_t *);
146 static const char *parse_operator_name(const char *, const char *, cpp_db_t *);
147 static const char *parse_pack_expansion(const char *, const char *, cpp_db_t *);
148 static const char *parse_unresolved_type(const char *, const char *,
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) {
191 errno = EINVAL;
192 goto done;
193 }
194 }
195
196 if (errno != 0)
197 goto done;
198
199 if (nempty(&db)) {
200 errno = EINVAL;
201 goto done;
202 }
203
204 njoin(&db, 1, "");
205
206 if (nlen(&db) > 0) {
207 str_t *s = TOP_L(&db);
208 result = zalloc(ops, s->str_len + 1);
209 if (result == NULL)
210 goto done;
211
212 (void) memcpy(result, s->str_s, s->str_len);
213 }
214
215 done:
216 if (getenv("DEMANGLE_DEBUG") != NULL)
217 dump(&db, stdout);
218
219 db_fini(&db);
220 return (result);
221 }
222
223 static void
224 demangle(const char *first, const char *last, cpp_db_t *db)
225 {
226 const char *t = NULL;
227
228 if (first >= last) {
229 errno = EINVAL;
230 return;
231 }
232
233 if (first[0] != '_') {
234 t = parse_type(first, last, db);
235 if (t == first) {
236 errno = EINVAL;
237 return;
238 }
239 goto done;
240 }
241
242 if (last - first < 4) {
243 errno = EINVAL;
244 return;
245 }
246
247 if (first[1] == 'Z') {
248 t = parse_encoding(first + 2, last, db);
249
250 if (t != first + 2 && t != last && t[0] == '.') {
251 t = parse_dot_suffix(t, last, db);
252 if (nlen(db) > 1)
253 njoin(db, 2, "");
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);
358 if (t == first)
359 goto fail;
360
361 cv = db->cpp_cv;
362 ref = db->cpp_ref;
363
364 if (t == last || t[0] == 'E' || t[0] == '.')
365 goto done;
366
367 db->cpp_tag_templates = B_FALSE;
368 if (nempty(db) || str_length(TOP_L(db)) == 0)
369 goto fail;
370
371 if (!db->cpp_parsed_ctor_dtor_cv && ends_with_template_args) {
372 t2 = parse_type(t, last, db);
373 if (t2 == t || nlen(db) < 2)
374 goto fail;
375
376 str_pair_t *sp = name_top(&db->cpp_name);
377
378 if (str_length(&sp->strp_r) == 0)
379 str_append(&sp->strp_l, " ", 1);
380
381 nfmt(db, "{0:L}{1:L}", "{1:R}{0:R}");
382 t = t2;
383 }
384
385 if (t == last || nempty(db))
386 goto fail;
387
388 size_t n = nlen(db);
389
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));
431 }
432
433 nfmt(db, "{1:L}{0}{1:R}", NULL);
434
435 done:
436 db->cpp_tag_templates = tag_templ_save;
437 db->cpp_depth--;
438 return (t);
439
440 fail:
441 db->cpp_tag_templates = tag_templ_save;
442 db->cpp_depth--;
443 return (first);
444 }
445
446 /*
447 * <special-name> ::= TV <type> # virtual table
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:
557 return (first);
558 }
559 break;
560 default:
561 return (first);
562 }
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
650 /*
651 * <unscoped-name>
652 * <unscoped-name> <template-args>
653 * <substitution> <template-args>
654 */
655 t1 = parse_unscoped_name(t, last, db);
656
657 /* <unscoped-name> */
658 if (t != t1 && t1[0] != 'I')
659 return (t1);
660
661 if (t == t1) {
662 t1 = parse_substitution(t, last, db);
663 if (t == t1 || t1 == last || t1[0] != 'I')
664 return (first);
665 } else {
666 save_top(db, 1);
667 }
668
669 t = parse_template_args(t1, last, db);
670 if (t1 == t || nlen(db) < 2)
671 return (first);
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++;
781 break;
782 case 'S':
783 if (last - first < 2 || t[1] != 't')
784 break;
785 if (last - first == 2)
786 return (first);
787 nadd_l(db, "std", 3);
788 more = B_TRUE;
789 t += 2;
790 break;
791 }
792
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)
955 return (first);
956
957 while (t[0] != 'E') {
958 t1 = parse_template_arg(t, last, db);
959 if (t == t1)
960 return (first);
961 t = t1;
962 }
963
964 /* E */
965 t++;
966 break;
967
968 case 'L':
969 if (first + 1 == last || first[1] != 'Z') {
970 t = parse_expr_primary(first, last, db);
971 } else {
972 t = parse_encoding(first + 2, last, db);
973 if (t == first + 2 || t == last || t[0] != 'E')
974 return (first);
975
976 /* E */
977 t++;
978 }
979 break;
980
981 default:
982 t = parse_type(first, last, db);
983 }
984
985 return (t);
986 }
987
988 /* BEGIN CSTYLED */
989 /*
990 * <expression> ::= <unary operator-name> <expression>
991 * ::= <binary operator-name> <expression> <expression>
992 * ::= <ternary operator-name> <expression> <expression> <expression>
993 * ::= cl <expression>+ E # call
994 * ::= cv <type> <expression> # conversion with one argument
995 * ::= cv <type> _ <expression>* E # conversion with a different number of arguments
996 * ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
997 * ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
998 * ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
999 * ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
1000 * ::= [gs] dl <expression> # delete expression
1001 * ::= [gs] da <expression> # delete[] expression
1002 * ::= pp_ <expression> # prefix ++
1003 * ::= mm_ <expression> # prefix --
1004 * ::= ti <type> # typeid (type)
1005 * ::= te <expression> # typeid (expression)
1006 * ::= dc <type> <expression> # dynamic_cast<type> (expression)
1007 * ::= sc <type> <expression> # static_cast<type> (expression)
1008 * ::= cc <type> <expression> # const_cast<type> (expression)
1009 * ::= rc <type> <expression> # reinterpret_cast<type> (expression)
1010 * ::= st <type> # sizeof (a type)
1011 * ::= sz <expression> # sizeof (an expression)
1012 * ::= at <type> # alignof (a type)
1013 * ::= az <expression> # alignof (an expression)
1014 * ::= nx <expression> # noexcept (expression)
1015 * ::= <template-param>
1016 * ::= <function-param>
1017 * ::= dt <expression> <unresolved-name> # expr.name
1018 * ::= pt <expression> <unresolved-name> # expr->name
1019 * ::= ds <expression> <expression> # expr.*expr
1020 * ::= sZ <template-param> # size of a parameter pack
1021 * ::= sZ <function-param> # size of a function parameter pack
1022 * ::= sp <expression> # pack expansion
1023 * ::= tw <expression> # throw expression
1024 * ::= tr # throw with no operand (rethrow)
1025 * ::= <unresolved-name> # f(p), N::f(p), ::f(p),
1026 * # freestanding dependent name (e.g., T::x),
1027 * # objectless nonstatic member reference
1028 * ::= <expr-primary>
1029 */
1030 /* END CSTYLED */
1031
1032 #define PA(cd, arg, fn) { \
1033 .code = cd, \
1034 .p.parse_expr_arg = fn, \
1035 .fntype = EXPR_ARG, \
1036 .val = arg \
1037 }
1038
1039 #define PN(cd, fn) { \
1040 .code = cd, \
1041 .p.parse_expr_noarg = fn, \
1042 .fntype = EXPR_NOARG \
1043 }
1044
1045 static struct {
1046 const char code[3];
1047 union {
1048 const char *(*parse_expr_arg)(const char *, const char *,
1049 const char *, cpp_db_t *);
1050 const char *(*parse_expr_noarg)(const char *, const char *,
1051 cpp_db_t *);
1052 } p;
1053 enum {
1054 EXPR_ARG,
1055 EXPR_NOARG
1056 } fntype;
1057 const char val[4];
1058 } expr_tbl[] = {
1059 PA("aN", "&=", parse_binary_expr),
1060 PA("aS", "=", parse_binary_expr),
1061 PA("aa", "&&", parse_binary_expr),
1062 PA("ad", "&", parse_prefix_expr),
1063 PA("an", "&", parse_binary_expr),
1064 PN("at", parse_alignof),
1065 PN("az", parse_alignof),
1066 PN("cc", parse_cast_expr),
1067 PN("cl", parse_call_expr),
1068 PA("cm", ",", parse_binary_expr),
1069 PA("co", "~", parse_prefix_expr),
1070 PN("cv", parse_conv_expr),
1071 PN("da", parse_del_expr),
1072 PA("dV", "/=", parse_binary_expr),
1073 PN("dc", parse_cast_expr),
1074 PA("de", "*", parse_prefix_expr),
1075 PN("dl", parse_del_expr),
1076 PN("dn", parse_unresolved_name),
1077 PN("ds", parse_dot_star_expr),
1078 PN("dt", parse_dot_expr),
1079 PA("dv", "/", parse_binary_expr),
1080 PA("eO", "^=", parse_binary_expr),
1081 PA("eo", "^", parse_binary_expr),
1082 PA("eq", "==", parse_binary_expr),
1083 PA("ge", ">=", parse_binary_expr),
1084 PN("gs", parse_gs),
1085 PA("gt", ">", parse_binary_expr),
1086 PN("ix", parse_idx_expr),
1087 PA("lS", "<<=", parse_binary_expr),
1088 PA("le", "<=", parse_binary_expr),
1089 PA("ls", "<<", parse_binary_expr),
1090 PA("lt", "<", parse_binary_expr),
1091 PA("mI", "-=", parse_binary_expr),
1092 PA("mL", "*=", parse_binary_expr),
1093 PN("mm", parse_mm_expr),
1094 PA("mi", "-", parse_binary_expr),
1095 PA("ml", "*", parse_binary_expr),
1096 PN("na", parse_new_expr),
1097 PA("ne", "!=", parse_binary_expr),
1098 PA("ng", "-", parse_prefix_expr),
1099 PA("nt", "!", parse_prefix_expr),
1100 PN("nw", parse_new_expr),
1101 PN("nx", parse_noexcept_expr),
1102 PA("oR", "|=", parse_binary_expr),
1103 PN("on", parse_unresolved_name),
1104 PA("oo", "||", parse_binary_expr),
1105 PA("or", "|", parse_binary_expr),
1106 PA("pL", "+=", parse_binary_expr),
1107 PA("pl", "+", parse_binary_expr),
1108 PA("pm", "->*", parse_binary_expr),
1109 PN("pp", parse_pp_expr),
1110 PA("ps", "+", parse_prefix_expr),
1111 PN("pt", parse_arrow_expr),
1112 PN("qu", parse_trinary_expr),
1113 PA("rM", "%=", parse_binary_expr),
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));
1155 case 'T':
1156 return (parse_template_param(first, last, db));
1157 case 'f':
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')
1303 return (first);
1304
1305 t2 += 2;
1306 const char *t3 = t2;
1307 size_t n1 = nlen(db);
1308
1309 while (t2[0] != 'E' && t2 != last) {
1310 t3 = parse_expression(t2, last, db);
1311
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
1535 paren(str_pair_t *sp)
1536 {
1537 str_t *l = &sp->strp_l;
1538 str_t *r = &sp->strp_r;
1539
1540 if (str_length(r) > 1 &&
1541 r->str_s[0] == ' ' && r->str_s[1] == '[') {
1542 str_append(l, " (", 2);
1543 str_insert(r, 0, ")", 1);
1544 } else if (str_length(r) > 0 && r->str_s[0] == '(') {
1545 str_append(l, "(", 1);
1546 str_insert(r, 0, ")", 1);
1547 }
1548 }
1549
1550 /* BEGIN CSTYLED */
1551 /*
1552 * <type> ::= <builtin-type>
1553 * ::= <function-type>
1554 * ::= <class-enum-type>
1555 * ::= <array-type>
1556 * ::= <pointer-to-member-type>
1557 * ::= <template-param>
1558 * ::= <template-template-param> <template-args>
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);
1600
1601 switch (first[0]) {
1602 case 'A':
1603 t = parse_array_type(first, last, db);
1604 if (t == first || NAMT(db, n) == 0)
1605 return (first);
1606 save_top(db, 1);
1607 return (t);
1608
1609 case 'C':
1610 t = parse_type(first + 1, last, db);
1611 if (t == first + 1 || NAMT(db, n) == 0)
1612 return (first);
1613
1614 str_append(TOP_L(db), " complex", 8);
1615 save_top(db, 1);
1616 return (t);
1617
1618 case 'F':
1619 t = parse_function_type(first, last, db);
1620 if (t == first || NAMT(db, n) == 0)
1621 return (first);
1622 save_top(db, 1);
1623 return (t);
1624
1625 case 'G':
1626 t = parse_type(first + 1, last, db);
1627 if (t == first + 1 || NAMT(db, n) == 0)
1628 return (first);
1629
1630 str_append(TOP_L(db), " imaginary", 10);
1631 save_top(db, 1);
1632 return (t);
1633
1634 case 'M':
1635 t = parse_pointer_to_member_type(first, last, db);
1636 if (t == first || NAMT(db, n) == 0)
1637 return (first);
1638 save_top(db, 1);
1639 return (t);
1640
1641 case 'O':
1642 t = parse_type(first + 1, last, db);
1643 amt = NAMT(db, n);
1644 if (t == first + 1 || amt == 0)
1645 return (first);
1646
1647 sp = name_at(&db->cpp_name, amt - 1);
1648 for (size_t i = 0; i < amt; i++, sp++) {
1649 paren(sp);
1650 if (str_pair_len(sp) > 0)
1651 str_append(&sp->strp_l, "&&", 2);
1652 }
1653
1654 save_top(db, amt);
1655 return (t);
1656
1657 case 'P':
1658 t = parse_type(first + 1, last, db);
1659 amt = NAMT(db, n);
1660 if (t == first + 1 || amt == 0)
1661 return (first);
1662
1663 sp = name_at(&db->cpp_name, amt - 1);
1664 for (size_t i = 0; i < amt; i++, sp++) {
1665 str_t *l = &sp->strp_l;
1666
1667 if (str_pair_len(sp) == 0)
1668 continue;
1669
1670 paren(sp);
1671 if (first[1] != 'U' ||
1672 strncmp(l->str_s, "objc_object<", 12) != 0) {
1673 str_append(l, "*", 1);
1674 } else {
1675 str_erase(l, 0, 11);
1676 str_insert(l, 0, "id", 2);
1677 }
1678 }
1679 save_top(db, amt);
1680 return (t);
1681
1682 case 'R':
1683 t = parse_type(first + 1, last, db);
1684 amt = NAMT(db, n);
1685 if (t == first + 1 || amt == 0)
1686 return (first);
1687
1688 sp = name_at(&db->cpp_name, amt - 1);
1689 for (size_t i = 0; i < amt; i++, sp++) {
1690 if (str_length(&sp->strp_l) == 0 &&
1691 str_length(&sp->strp_r) == 0)
1692 continue;
1693
1694 paren(sp);
1695 str_append(&sp->strp_l, "&", 1);
1696 }
1697
1698 save_top(db, amt);
1699 return (t);
1700
1701 case 'T':
1702 t = parse_template_param(first, last, db);
1703 if (t == first)
1704 return (first);
1705
1706 amt = NAMT(db, n);
1707 save_top(db, amt);
1708 if (!db->cpp_try_to_parse_template_args || amt != 1)
1709 return (t);
1710
1711 t1 = parse_template_args(t, last, db);
1712 if (t1 == t)
1713 return (t);
1714
1715 nfmt(db, "{1:L}{0}", "{1:R}");
1716 save_top(db, 1);
1717 return (t1);
1718
1719 case 'U':
1720 if (first + 1 == last)
1721 return (first);
1722
1723 t = parse_source_name(first + 1, last, db);
1724 if (t == first + 1)
1725 return (first);
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
1770 t = parse_substitution(first, last, db);
1771 if (t == first)
1772 return (first);
1773
1774 /*
1775 * If the substitution is a <template-param>, it might
1776 * be followed by <template-args>
1777 */
1778 t1 = parse_template_args(t, last, db);
1779 if (t1 == t)
1780 return (t);
1781
1782 if (NAMT(db, n) < 2)
1783 return (t);
1784
1785 nfmt(db, "{1:L}{0}", "{1:R}");
1786 save_top(db, 1);
1787 return (t1);
1788
1789 case 'D':
1790 if (first + 1 == last)
1791 return (first);
1792
1793 switch (first[1]) {
1794 case 'p':
1795 t = parse_type(first + 2, last, db);
1796 if (t == first + 2)
1797 break;
1798
1799 save_top(db, NAMT(db, n));
1800 return (t);
1801
1802 case 't':
1803 case 'T':
1804 t = parse_decltype(first, last, db);
1805 if (first == t)
1806 break;
1807
1808 save_top(db, 1);
1809 return (t);
1810
1811 case 'v':
1812 t = parse_vector_type(first, last, db);
1813 if (first == t)
1814 break;
1815
1816 if (NAMT(db, n) == 0)
1817 return (first);
1818
1819 save_top(db, 1);
1820 return (t);
1821 }
1822 break;
1823 }
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
1865 str_pair_t *sp = name_at(&db->cpp_name, amt - 1);
1866
1867 for (size_t i = 0; i < amt; i++, sp++) {
1868 str_t *s = NULL;
1869
1870 if (!is_func) {
1871 s = &sp->strp_l;
1872
1873 if (str_length(s) == 0)
1874 continue;
1875
1876 if (cv & 1)
1877 str_append(s, " const", 6);
1878 if (cv & 2)
1879 str_append(s, " volatile", 9);
1880 if (cv & 4)
1881 str_append(s, " restrict", 9);
1882
1883 continue;
1884 }
1885
1886 s = &sp->strp_r;
1887 size_t pos = str_length(s);
1888
1889 if (pos > 0 && s->str_s[pos - 1] == '&') {
1890 pos--;
1891 if (s->str_s[pos - 1] == '&')
1892 pos--;
1893 }
1894
1895 if (cv & 1) {
1896 str_insert(s, pos, " const", 6);
1897 pos += 6;
1898 }
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
2227 t = t1;
2228 } else {
2229 size_t n1 = nlen(db);
2230
2231 /* skip _ */
2232 t++;
2233 while (t[0] != 'E' && t != last) {
2234 t1 = parse_expression(t, last, db);
2235 if (t1 == t)
2236 return (first);
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)
2460 return (first);
2461 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;
2503 const char *basename;
2504 } aliases[] = {
2505 {
2506 "std::string",
2507 "std::basic_string<char, std::char_traits<char>, "
2508 "std::allocator<char> >",
2509 "basic_string"
2510 },
2511 {
2512 "std::istream",
2513 "std::basic_istream<char, std::char_traits<char> >",
2514 "basic_istream"
2515 },
2516 {
2517 "std::ostream",
2518 "std::basic_ostream<char, std::char_traits<char> >",
2519 "basic_ostream"
2520 },
2521 {
2522 "std::iostream",
2523 "std::basic_iostream<char, std::char_traits<char> >",
2524 "basic_iostream"
2525 }
2526 };
2527
2528 static void
2529 basename(cpp_db_t *db)
2530 {
2531 str_t *s = TOP_L(db);
2532
2533 for (size_t i = 0; i < ARRAY_SIZE(aliases); i++) {
2534 if (str_length(s) != strlen(aliases[i].alias))
2535 continue;
2536 if (strncmp(aliases[i].alias, s->str_s, str_length(s)) != 0)
2537 continue;
2538
2539 /* swap out alias for full name */
2540 sysdem_ops_t *ops = s->str_ops;
2541 str_fini(s);
2542 str_init(s, ops);
2543 str_set(s, aliases[i].fullname, 0);
2544
2545 nadd_l(db, aliases[i].basename, 0);
2546 return;
2547 }
2548
2549 const char *start = s->str_s;
2550 const char *end = s->str_s + s->str_len;
2551
2552 /*
2553 * if name ends with a template i.e. <.....> back up to start
2554 * of outermost template
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':
2628 case '1':
2629 case '2':
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 {
2705 double v;
2706 char buf[sizeof (double)];
2707 } d;
2708 union {
2709 long double v;
2710 char buf[sizeof (long double)];
2711 } ld;
2712 } conv;
2713
2714 const char *t = NULL;
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
2769 switch (first[0]) {
2770 case 'f':
2771 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2772 conv.f.v);
2773 break;
2774 case 'd':
2775 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2776 conv.d.v);
2777 break;
2778 case 'e':
2779 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2780 conv.ld.v);
2781 }
2782
2783 if (n >= fd->max_demangled_size || n <= 0) {
2784 str_fini(&num);
2785 return (first);
2786 }
2787
2788 num.str_len = n;
2789 name_add_str(&db->cpp_name, &num, NULL);
2790
2791 return (t + 1);
2792 }
2793
2794 /*
2795 * <expr-primary> ::= L <type> <value number> E # integer literal
2796 * ::= L <type> <value float> E # floating literal
2797 * ::= L <string type> E # string literal
2798 * ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
2799 *
2800 * ::= L <type> <real-part float> _ <imag-part float> E
2801 * # complex floating point
2802 * # literal (C 2000)
2803 *
2804 * ::= L <mangled-name> E # external name
2805 */
2806 static struct {
2807 int c;
2808 const char *fmt;
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]) {
2850 case '0':
2851 nadd_l(db, "false", 5);
2852 break;
2853 case '1':
2854 nadd_l(db, "true", 4);
2855 break;
2856 default:
2857 return (first);
2858 }
2859 return (first + 4);
2860 case 'd': /* double */
2861 case 'e': /* long double */
2862 case 'f': /* float */
2863 t = parse_floating_literal(first + 1, last, db);
2864 return ((t == first + 1) ? first : t);
2865 case 'T':
2866 /* BEGIN CSTYLED */
2867 /*
2868 * Invalid mangled name per
2869 * http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
2870 *
2871 */
2872 /* END CSTYLED */
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 # =
2914 * ::= cl # ()
2915 * ::= cm # ,
2916 * ::= co # ~
2917 * ::= cv <type> # (cast)
2918 * ::= da # delete[]
2919 * ::= de # * (unary)
2920 * ::= dl # delete
2921 * ::= dv # /
2922 * ::= dV # /=
2923 * ::= eo # ^
2924 * ::= eO # ^=
2925 * ::= eq # ==
2926 * ::= ge # >=
2927 * ::= gt # >
2928 * ::= ix # []
2929 * ::= le # <=
2930 * ::= li <source-name> # operator ""
2931 * ::= ls # <<
2932 * ::= lS # <<=
2933 * ::= lt # <
2934 * ::= mi # -
2935 * ::= mI # -=
2936 * ::= ml # *
2937 * ::= mL # *=
2938 * ::= mm # -- (postfix in <expression> context)
2939 * ::= na # new[]
2940 * ::= ne # !=
2941 * ::= ng # - (unary)
2942 * ::= nt # !
2943 * ::= nw # new
2944 * ::= oo # ||
2945 * ::= or # |
2946 * ::= oR # |=
2947 * ::= pm # ->*
2948 * ::= pl # +
2949 * ::= pL # +=
2950 * ::= pp # ++ (postfix in <expression> context)
2951 * ::= ps # + (unary)
2952 * ::= pt # ->
2953 * ::= qu # ?
2954 * ::= rm # %
2955 * ::= rM # %=
2956 * ::= rs # >>
2957 * ::= rS # >>=
2958 * ::= v <digit> <source-name> # vendor extended operator
2959 */
2960 static struct {
2961 const char code[3];
2962 const char *op;
2963 } op_tbl[] = {
2964 { "aa", "operator&&" },
2965 { "ad", "operator&" },
2966 { "an", "operator&" },
2967 { "aN", "operator&=" },
2968 { "aS", "operator=" },
2969 { "cl", "operator()" },
2970 { "cm", "operator," },
2971 { "co", "operator~" },
2972 { "da", "operator delete[]" },
2973 { "de", "operator*" },
2974 { "dl", "operator delete" },
2975 { "dv", "operator/" },
2976 { "dV", "operator/=" },
2977 { "eo", "operator^" },
2978 { "eO", "operator^=" },
2979 { "eq", "operator==" },
2980 { "ge", "operator>=" },
2981 { "gt", "operator>" },
2982 { "ix", "operator[]" },
2983 { "le", "operator<=" },
2984 { "ls", "operator<<" },
2985 { "lS", "operator<<=" },
2986 { "lt", "operator<" },
2987 { "mi", "operator-" },
2988 { "mI", "operator-=" },
2989 { "ml", "operator*" },
2990 { "mL", "operator*=" },
2991 { "mm", "operator--" },
2992 { "na", "operator new[]" },
2993 { "ne", "operator!=" },
2994 { "ng", "operator-" },
2995 { "nt", "operator!" },
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
3062 if (t == first + 2 || nempty(db))
3063 return (first);
3064
3065 nfmt(db, "operator {0}", NULL);
3066 db->cpp_parsed_ctor_dtor_cv = B_TRUE;
3067 return (t);
3068 }
3069
3070 struct type_tbl_s {
3071 int code;
3072 const char *name;
3073 };
3074
3075 static struct type_tbl_s type_tbl1[] = {
3076 { 'a', "signed char" },
3077 { 'b', "bool" },
3078 { 'c', "char" },
3079 { 'd', "double" },
3080 { 'e', "long double" },
3081 { 'f', "float" },
3082 { 'g', "__float128" },
3083 { 'h', "unsigned char" },
3084 { 'i', "int" },
3085 { 'j', "unsigned int" },
3086 { 'l', "long" },
3087 { 'm', "unsigned long" },
3088 { 'n', "__int128" },
3089 { 'o', "unsigned __int128" },
3090 { 's', "short" },
3091 { 't', "unsigned short" },
3092 { 'v', "void" },
3093 { 'w', "wchar_t" },
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
3304 if (first[2] != '_') {
3305 t1 = parse_expression(first + 2, last, db);
3306 if (first == last || t1 == first + 2 || t1[0] != '_')
3307 return (first);
3308
3309 /* skip _ */
3310 t = t1 + 1;
3311 } else {
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] == '(')
3439 nfmt(db, "{0:L}({1}::*", "){0:R}");
3440 else
3441 nfmt(db, "{0:L} {1}::*", "{0:R}");
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))
3483 return (first);
3484
3485 str_insert(TOP_L(db), 0, "::", 2);
3486 }
3487 return (t2);
3488 }
3489
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 }
3531
3532 t += 2;
3533
3534 t2 = parse_unresolved_type(t, last, db);
3535 if (t != t2) {
3536 t = t2;
3537 t2 = parse_template_args(t, last, db);
3538 if (t2 != t)
3539 nfmt(db, "{1:L}{0}", "{1:R}");
3540 t = t2;
3541
3542 t2 = parse_base_unresolved_name(t, last, db);
3543 if (t == t2 || nlen(db) < 2)
3544 return (first);
3545
3546 nfmt(db, "{1:L}::{0}", "{1:R}");
3547 return (t2);
3548 }
3549
3550 t2 = parse_unresolved_qualifier_level(t, last, db);
3551 if (t2 == t || t2 == last)
3552 return (first);
3553
3554 t = t2;
3555 if (global && nlen(db) > 0)
3556 nfmt(db, "::{0:L}", "{0:R}");
3557
3558 while (t[0] != 'E') {
3559 t2 = parse_unresolved_qualifier_level(t, last, db);
3560 if (t == t2 || t == last || nlen(db) < 2)
3561 return (first);
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);
3621 nfmt(db, "{1:L}{0}", "{1:R}");
3622 }
3623
3624 return (t1);
3625 }
3626
3627 if (first[0] == 'd') {
3628 t = parse_destructor_name(first + 2, last, db);
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;
3701 }
3702
3703 if (t[0] == 'R' && t + 1 != last && t[1] == 'E') {
3704 ref_qual = 1;
3705 t++;
3706 continue;
3707 }
3708
3709 if (t[0] == 'O' && t + 1 != last && t[1] == 'E') {
3710 ref_qual = 2;
3711 t++;
3712 continue;
3713 }
3714
3715
3716 t1 = parse_type(t, last, db);
3717 if (t1 == t || t == last)
3718 return (first);
3719
3720 t = t1;
3721 }
3722
3723 if (t == last)
3724 return (first);
3725
3726 njoin(db, NAMT(db, n), ", ");
3727 nfmt(db, "({0})", NULL);
3728
3729 switch (ref_qual) {
3730 case 1:
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
3993 nadd_l(cpp_db_t *db, const char *s, size_t len)
3994 {
3995 CK(name_add(&db->cpp_name, s, len, NULL, 0));
3996 }
3997
3998 static void
3999 njoin(cpp_db_t *db, size_t amt, const char *sep)
4000 {
4001 name_t *nm = &db->cpp_name;
4002
4003 CK(name_join(nm, amt, sep));
4004 }
4005
4006 static void
4007 nfmt(cpp_db_t *db, const char *fmt_l, const char *fmt_r)
4008 {
4009 CK(name_fmt(&db->cpp_name, fmt_l, fmt_r));
4010 }
4011
4012 static void
4013 save_top(cpp_db_t *db, size_t amt)
4014 {
4015 CK(sub_save(&db->cpp_subs, &db->cpp_name, amt));
4016 }
4017
4018 static void
4019 sub(cpp_db_t *db, size_t n)
4020 {
4021 CK(sub_substitute(&db->cpp_subs, n, &db->cpp_name));
4022 }
4023
4024 static boolean_t
4025 tempty(const cpp_db_t *db)
4026 {
4027 return (templ_empty(&db->cpp_templ) ? B_TRUE : B_FALSE);
4028 }
4029
4030 static size_t
4031 ttlen(const cpp_db_t *db)
4032 {
4033 return (templ_top_len(&db->cpp_templ));
4034 }
4035
4036 static void
4037 tsub(cpp_db_t *db, size_t n)
4038 {
4039 CK(templ_sub(&db->cpp_templ, n, &db->cpp_name));
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
4131 val /= 36;
4132 }
4133
4134 char *q = buf;
4135 while (--p >= tmp)
4136 *q++ = *p;
4137
4138 return (buf);
4139 }
4140
4141 static void
4142 print_sub(const sub_t *sub, FILE *out)
4143 {
4144 const name_t *n = sub->sub_items;
4145
4146 (void) fprintf(out, "Substitutions:\n");
4147
4148 if (sub->sub_len == 0)
4149 return;
4150
4151 for (size_t i = 0; i < sub->sub_len; i++, n++) {
4152 (void) printf(" ");
4153 if (i == 0) {
4154 (void) fprintf(out, "%-4s", "S_");
4155 } else {
4156 char buf[16] = { 0 };
4157 char buf2[16] = { 0 };
4158
4159 (void) snprintf(buf, sizeof (buf), "S%s_",
4160 base36(buf2, i));
4161 (void) fprintf(out, "%-4s", buf);
4162 }
4163 (void) fprintf(out, " = ");
4164
4165 (void) fputc('{', out);
4166 for (size_t j = 0; j < n->nm_len; j++) {
4167 if (j > 0)
4168 (void) fputc(' ', out);
4169 print_sp(&n->nm_items[j], out);
4170 }
4171 (void) fputc('}', out);
4172
4173 (void) fputc('\n', out);
4174 }
4175 (void) fputc('\n', out);
4176 }
4177
4178 static void
4179 print_templ(const templ_t *tpl, FILE *out)
4180 {
4181
4182 (void) fprintf(out, "Template\n");
4183
4184 const sub_t *s = templ_top((templ_t *)tpl);
4185
4186 for (size_t i = 0; i < s->sub_len; i++) {
4187 char buf[16] = { 0 };
4188
4189 if (i == 0)
4190 (void) snprintf(buf, sizeof (buf), "%s", "T_");
4191 else
4192 (void) snprintf(buf, sizeof (buf), "T%zu_", i - 1);
4193
4194 (void) fprintf(out, " %-4s = ", buf);
4195
4196 (void) fputc('{', out);
4197
4198 const name_t *n = &s->sub_items[i];
4199 for (size_t j = 0; j < n->nm_len; j++) {
4200 const str_pair_t *sp = &n->nm_items[j];
4201
4202 if (j > 0)
4203 (void) fputc(' ', out);
4204
4205 (void) fprintf(out, "{%.*s#%.*s}",
4206 (int)sp->strp_l.str_len, sp->strp_l.str_s,
4207 (int)sp->strp_r.str_len, sp->strp_r.str_s);
4208 }
4209 (void) fprintf(out, "}\n");
4210 }
4211 (void) fprintf(out, "\n");
4212 }
4213
4214 static void
4215 dump(cpp_db_t *db, FILE *out)
4216 {
4217 print_name(&db->cpp_name, out);
4218 print_sub(&db->cpp_subs, out);
4219 print_templ(&db->cpp_templ, out);
4220 }