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