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