1 /*
2 * Ported from LLVM's libcxxabi trunk/src/cxa_demangle.cpp
3 * LICENSE.TXT contents is available as ../THIRDPARTYLICENSE
4 *
5 * The LLVM Compiler Infrastructure
6 *
7 * This file is dual licensed under the MIT and the University of Illinois Open
8 * Source Licenses. See LICENSE.TXT for details.
9 *
10 */
11
12 /*
13 * Copyright 2017 Jason King.
14 */
15 #include <ctype.h>
16 #include <errno.h>
17 #include <locale.h>
18 #include <string.h>
19 #include <setjmp.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/isa_defs.h>
23 #include <sys/debug.h>
24 #include "sysdemangle.h"
25 #include "sysdemangle_int.h"
26 #include "cxx.h"
27
28 #ifndef ARRAY_SIZE
29 #define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
30 #endif
31
32 #define CPP_QUAL_CONST (1U)
33 #define CPP_QUAL_VOLATILE (2U)
34 #define CPP_QUAL_RESTRICT (4U)
35
36 typedef struct cpp_db_s {
37 sysdem_ops_t *cpp_ops;
38 jmp_buf cpp_jmp;
39 name_t cpp_name;
40 sub_t cpp_subs;
41 templ_t cpp_templ;
42 unsigned cpp_cv;
43 unsigned cpp_ref;
44 unsigned cpp_depth;
45 boolean_t cpp_parsed_ctor_dtor_cv;
46 boolean_t cpp_tag_templates;
47 boolean_t cpp_fix_forward_references;
48 boolean_t cpp_try_to_parse_template_args;
49 locale_t cpp_loc;
50 } cpp_db_t;
51
52 #define CK(x) \
53 do { \
54 if (!(x)) \
55 longjmp(db->cpp_jmp, 1); \
56 } while (0)
57
58 #define TOP_L(db) (&(name_top(&(db)->cpp_name)->strp_l))
59 #define RLEN(f, l) ((size_t)((l) - (f)))
60 #define NAMT(db, n) (nlen(db) - n)
61
62 static inline boolean_t is_xdigit(int);
63
64 static boolean_t nempty(cpp_db_t *);
65 static size_t nlen(cpp_db_t *);
66 static void nadd_l(cpp_db_t *, const char *, size_t);
67 static void njoin(cpp_db_t *, size_t, const char *);
68 static void nfmt(cpp_db_t *, const char *, const char *);
69
70 static void save_top(cpp_db_t *, size_t);
71 static void sub(cpp_db_t *, size_t);
72
73 static boolean_t tempty(const cpp_db_t *);
74 static size_t ttlen(const cpp_db_t *);
75
198 if (errno != 0)
199 goto done;
200
201 if (nempty(&db)) {
202 errno = EINVAL;
203 goto done;
204 }
205
206 njoin(&db, 1, "");
207
208 if (nlen(&db) > 0) {
209 str_t *s = TOP_L(&db);
210 result = zalloc(ops, s->str_len + 1);
211 if (result == NULL)
212 goto done;
213
214 (void) memcpy(result, s->str_s, s->str_len);
215 }
216
217 done:
218 if (getenv("DEMANGLE_DEBUG") != NULL)
219 dump(&db, stdout);
220
221 db_fini(&db);
222 return (result);
223 }
224
225 static void
226 demangle(const char *first, const char *last, cpp_db_t *db)
227 {
228 const char *t = NULL;
229
230 if (first >= last) {
231 errno = EINVAL;
232 return;
233 }
234
235 if (first[0] != '_') {
236 t = parse_type(first, last, db);
237 if (t == first) {
238 errno = EINVAL;
272
273 static const char *
274 parse_dot_suffix(const char *first, const char *last, cpp_db_t *db)
275 {
276 VERIFY3P(first, <=, last);
277
278 if (first == last || first[0] != '.')
279 return (first);
280
281 if (nempty(db))
282 return (first);
283
284 nadd_l(db, first, RLEN(first, last));
285 nfmt(db, " ({0})", NULL);
286
287 return (last);
288 }
289
290 /*
291 * _block_invoke
292 * _block_invoke<digit>+ XXX: should it be <digit>* ?
293 * _block_invoke_<digit>+
294 */
295 static const char *
296 parse_block_invoke(const char *first, const char *last, cpp_db_t *db)
297 {
298 VERIFY3P(first, <=, last);
299
300 if (last - first < 13)
301 return (first);
302
303 const char test[] = "_block_invoke";
304 const char *t = first;
305
306 if (strncmp(first, test, sizeof (test) - 1) != 0)
307 return (first);
308
309 t += sizeof (test);
310 if (t == last)
311 goto done;
312
361 goto fail;
362
363 cv = db->cpp_cv;
364 ref = db->cpp_ref;
365
366 if (t == last || t[0] == 'E' || t[0] == '.')
367 goto done;
368
369 db->cpp_tag_templates = B_FALSE;
370 if (nempty(db) || str_length(TOP_L(db)) == 0)
371 goto fail;
372
373 if (!db->cpp_parsed_ctor_dtor_cv && ends_with_template_args) {
374 t2 = parse_type(t, last, db);
375 if (t2 == t || nlen(db) < 2)
376 goto fail;
377
378 str_pair_t *sp = name_top(&db->cpp_name);
379
380 if (str_length(&sp->strp_r) == 0)
381 str_append(&sp->strp_l, " ", 1);
382
383 nfmt(db, "{0:L}{1:L}", "{1:R}{0:R}");
384 t = t2;
385 }
386
387 if (t == last || nempty(db))
388 goto fail;
389
390 size_t n = nlen(db);
391
392 if (t[0] == 'v') {
393 t++;
394 } else {
395
396 /*CONSTCOND*/
397 while (1) {
398 t2 = parse_type(t, last, db);
399 if (t2 == t || t == last)
400 break;
401
402 t = t2;
403 }
404 }
405
406 /*
407 * a bit of a hack, but a template substitution can apparently be
408 * an empty string at the end of an argument list, so avoid
409 * <...., >
410 */
411 if (NAMT(db, n) > 1 && str_pair_len(name_top(&db->cpp_name)) == 0)
412 name_pop(&db->cpp_name, NULL);
413
414 njoin(db, NAMT(db, n), ", ");
415 nfmt(db, "({0})", NULL);
416
417 str_t *s = TOP_L(db);
1524 if (t1 == first + 2)
1525 return (first);
1526
1527 const char *t2 = parse_expression(t1, last, db);
1528 if (t2 == t1 || NAMT(db, n) != 2)
1529 return (first);
1530
1531 nfmt(db, "{1}->{0}", NULL);
1532 return (t2);
1533 }
1534
1535 /* wrap value in () when necessary */
1536 static void
1537 paren(str_pair_t *sp)
1538 {
1539 str_t *l = &sp->strp_l;
1540 str_t *r = &sp->strp_r;
1541
1542 if (str_length(r) > 1 &&
1543 r->str_s[0] == ' ' && r->str_s[1] == '[') {
1544 str_append(l, " (", 2);
1545 str_insert(r, 0, ")", 1);
1546 } else if (str_length(r) > 0 && r->str_s[0] == '(') {
1547 str_append(l, "(", 1);
1548 str_insert(r, 0, ")", 1);
1549 }
1550 }
1551
1552 /* BEGIN CSTYLED */
1553 /*
1554 * <type> ::= <builtin-type>
1555 * ::= <function-type>
1556 * ::= <class-enum-type>
1557 * ::= <array-type>
1558 * ::= <pointer-to-member-type>
1559 * ::= <template-param>
1560 * ::= <template-template-param> <template-args>
1561 * ::= <decltype>
1562 * ::= <substitution>
1563 * ::= <CV-qualifiers> <type>
1564 * ::= P <type> # pointer-to
1565 * ::= R <type> # reference-to
1566 * ::= O <type> # rvalue reference-to (C++0x)
1567 * ::= C <type> # complex pair (C 2000)
1568 * ::= G <type> # imaginary (C 2000)
1596 size_t n = nlen(db);
1597 size_t amt = 0;
1598
1599 t = parse_builtin_type(first, last, db);
1600 if (t != first)
1601 return (t);
1602
1603 switch (first[0]) {
1604 case 'A':
1605 t = parse_array_type(first, last, db);
1606 if (t == first || NAMT(db, n) == 0)
1607 return (first);
1608 save_top(db, 1);
1609 return (t);
1610
1611 case 'C':
1612 t = parse_type(first + 1, last, db);
1613 if (t == first + 1 || NAMT(db, n) == 0)
1614 return (first);
1615
1616 str_append(TOP_L(db), " complex", 8);
1617 save_top(db, 1);
1618 return (t);
1619
1620 case 'F':
1621 t = parse_function_type(first, last, db);
1622 if (t == first || NAMT(db, n) == 0)
1623 return (first);
1624 save_top(db, 1);
1625 return (t);
1626
1627 case 'G':
1628 t = parse_type(first + 1, last, db);
1629 if (t == first + 1 || NAMT(db, n) == 0)
1630 return (first);
1631
1632 str_append(TOP_L(db), " imaginary", 10);
1633 save_top(db, 1);
1634 return (t);
1635
1636 case 'M':
1637 t = parse_pointer_to_member_type(first, last, db);
1638 if (t == first || NAMT(db, n) == 0)
1639 return (first);
1640 save_top(db, 1);
1641 return (t);
1642
1643 case 'O':
1644 t = parse_type(first + 1, last, db);
1645 amt = NAMT(db, n);
1646 if (t == first + 1 || amt == 0)
1647 return (first);
1648
1649 sp = name_at(&db->cpp_name, amt - 1);
1650 for (size_t i = 0; i < amt; i++, sp++) {
1651 paren(sp);
1652 if (str_pair_len(sp) > 0)
1653 str_append(&sp->strp_l, "&&", 2);
1654 }
1655
1656 save_top(db, amt);
1657 return (t);
1658
1659 case 'P':
1660 t = parse_type(first + 1, last, db);
1661 amt = NAMT(db, n);
1662 if (t == first + 1 || amt == 0)
1663 return (first);
1664
1665 sp = name_at(&db->cpp_name, amt - 1);
1666 for (size_t i = 0; i < amt; i++, sp++) {
1667 str_t *l = &sp->strp_l;
1668
1669 if (str_pair_len(sp) == 0)
1670 continue;
1671
1672 paren(sp);
1673 if (first[1] != 'U' ||
1674 strncmp(l->str_s, "objc_object<", 12) != 0) {
1675 str_append(l, "*", 1);
1676 } else {
1677 str_erase(l, 0, 11);
1678 str_insert(l, 0, "id", 2);
1679 }
1680 }
1681 save_top(db, amt);
1682 return (t);
1683
1684 case 'R':
1685 t = parse_type(first + 1, last, db);
1686 amt = NAMT(db, n);
1687 if (t == first + 1 || amt == 0)
1688 return (first);
1689
1690 sp = name_at(&db->cpp_name, amt - 1);
1691 for (size_t i = 0; i < amt; i++, sp++) {
1692 if (str_length(&sp->strp_l) == 0 &&
1693 str_length(&sp->strp_r) == 0)
1694 continue;
1695
1696 paren(sp);
1697 str_append(&sp->strp_l, "&", 1);
1698 }
1699
1700 save_top(db, amt);
1701 return (t);
1702
1703 case 'T':
1704 t = parse_template_param(first, last, db);
1705 if (t == first)
1706 return (first);
1707
1708 amt = NAMT(db, n);
1709 save_top(db, amt);
1710 if (!db->cpp_try_to_parse_template_args || amt != 1)
1711 return (t);
1712
1713 t1 = parse_template_args(t, last, db);
1714 if (t1 == t)
1715 return (t);
1716
1717 nfmt(db, "{1:L}{0}", "{1:R}");
1859 t1 = parse_type(t, last, db);
1860 size_t amt = NAMT(db, n);
1861 if (t == t1 || amt == 0)
1862 return (first);
1863
1864 if (is_func)
1865 sub_pop(&db->cpp_subs);
1866
1867 str_pair_t *sp = name_at(&db->cpp_name, amt - 1);
1868
1869 for (size_t i = 0; i < amt; i++, sp++) {
1870 str_t *s = NULL;
1871
1872 if (!is_func) {
1873 s = &sp->strp_l;
1874
1875 if (str_length(s) == 0)
1876 continue;
1877
1878 if (cv & 1)
1879 str_append(s, " const", 6);
1880 if (cv & 2)
1881 str_append(s, " volatile", 9);
1882 if (cv & 4)
1883 str_append(s, " restrict", 9);
1884
1885 continue;
1886 }
1887
1888 s = &sp->strp_r;
1889 size_t pos = str_length(s);
1890
1891 if (pos > 0 && s->str_s[pos - 1] == '&') {
1892 pos--;
1893 if (s->str_s[pos - 1] == '&')
1894 pos--;
1895 }
1896
1897 if (cv & 1) {
1898 str_insert(s, pos, " const", 6);
1899 pos += 6;
1900 }
1901 if (cv & 2) {
1902 str_insert(s, pos, " volatile", 9);
1903 pos += 9;
1904 }
1905 if (cv & 4) {
1906 str_insert(s, pos, " restrict", 9);
1907 }
1908 }
1909
1910 save_top(db, amt);
1911 return (t1);
1912 }
1913
1914 /*
1915 * at <type> # alignof (a type)
1916 * az <expression> # alignof (a expression)
1917 */
1918 static const char *
1919 parse_alignof(const char *first, const char *last, cpp_db_t *db)
1920 {
1921 VERIFY3P(first, <=, last);
1922
1923 if (last - first < 2)
1924 return (first);
1925
1926 const char *(*fn)(const char *, const char *, cpp_db_t *);
2615 switch (first[0]) {
2616 case 'C':
2617 switch (first[1]) {
2618 case '1':
2619 case '2':
2620 case '3':
2621 case '5':
2622 basename(db);
2623 break;
2624 default:
2625 return (first);
2626 }
2627 break;
2628 case 'D':
2629 switch (first[1]) {
2630 case '0':
2631 case '1':
2632 case '2':
2633 case '5':
2634 basename(db);
2635 str_insert(TOP_L(db), 0, "~", 1);
2636 break;
2637 default:
2638 return (first);
2639 }
2640 break;
2641 default:
2642 return (first);
2643 }
2644
2645 db->cpp_parsed_ctor_dtor_cv = B_TRUE;
2646 return (first + 2);
2647 }
2648
2649 static const char *
2650 parse_integer_literal(const char *first, const char *last, const char *fmt,
2651 cpp_db_t *db)
2652 {
2653 VERIFY3P(first, <=, last);
2654
2655 const char *t = parse_number(first, last, db->cpp_loc);
2772 switch (first[0]) {
2773 case 'f':
2774 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2775 conv.f.v);
2776 break;
2777 case 'd':
2778 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2779 conv.d.v);
2780 break;
2781 case 'e':
2782 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2783 conv.ld.v);
2784 }
2785
2786 if (n >= fd->max_demangled_size || n <= 0) {
2787 str_fini(&num);
2788 return (first);
2789 }
2790
2791 num.str_len = n;
2792 name_add_str(&db->cpp_name, &num, NULL);
2793
2794 return (t + 1);
2795 }
2796
2797 /*
2798 * <expr-primary> ::= L <type> <value number> E # integer literal
2799 * ::= L <type> <value float> E # floating literal
2800 * ::= L <string type> E # string literal
2801 * ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
2802 *
2803 * ::= L <type> <real-part float> _ <imag-part float> E
2804 * # complex floating point
2805 * # literal (C 2000)
2806 *
2807 * ::= L <mangled-name> E # external name
2808 */
2809 static struct {
2810 int c;
2811 const char *fmt;
2812 } int_lits[] = {
3386 if (t1[0] != '_')
3387 return (first);
3388
3389 t = t1;
3390 } else {
3391 nadd_l(db, "", 0);
3392 }
3393
3394 VERIFY3U(t[0], ==, '_');
3395
3396 t1 = parse_type(t + 1, last, db);
3397 if (t1 == t + 1 || NAMT(db, n) != 2)
3398 return (first);
3399
3400 /*
3401 * if we have " [xxx]" already, want new result to be
3402 * " [yyy][xxx]"
3403 */
3404 str_t *r = &name_top(&db->cpp_name)->strp_r;
3405 if (r->str_len > 1 && r->str_s[0] == ' ' && r->str_s[1] == '[')
3406 str_erase(r, 0, 1);
3407
3408 nfmt(db, "{0:L}", " [{1}]{0:R}");
3409 return (t1);
3410 }
3411
3412 /* <pointer-to-member-type> ::= M <class type> <member type> */
3413 static const char *
3414 parse_pointer_to_member_type(const char *first, const char *last, cpp_db_t *db)
3415 {
3416 VERIFY3P(first, <=, last);
3417
3418 if (last - first < 3)
3419 return (first);
3420
3421 VERIFY3U(first[0], ==, 'M');
3422
3423 const char *t1 = first + 1;
3424 const char *t2 = NULL;
3425 size_t n = nlen(db);
3426
3468 return (first);
3469
3470 const char *t = first;
3471 const char *t2 = NULL;
3472 boolean_t global = B_FALSE;
3473 size_t n;
3474
3475 if (t[0] == 'g' && t[1] == 's') {
3476 global = B_TRUE;
3477 t += 2;
3478 }
3479 if (t == last)
3480 return (first);
3481
3482 t2 = parse_base_unresolved_name(t, last, db);
3483 if (t != t2) {
3484 if (global) {
3485 if (nempty(db))
3486 return (first);
3487
3488 str_insert(TOP_L(db), 0, "::", 2);
3489 }
3490 return (t2);
3491 }
3492
3493 if (t[0] != 's' || t[1] != 'r' || last - t < 2)
3494 return (first);
3495
3496 n = nlen(db);
3497 if (t[2] == 'N') {
3498 t += 3;
3499 t2 = parse_unresolved_type(t, last, db);
3500 if (t2 == t || t2 == last)
3501 return (first);
3502 t = t2;
3503
3504 t2 = parse_template_args(t, last, db);
3505 if (t2 != t) {
3506 if (NAMT(db, n) < 2 || t2 == last)
3507 return (first);
3508
|
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
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;
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
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);
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)
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}");
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 *);
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);
2773 switch (first[0]) {
2774 case 'f':
2775 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2776 conv.f.v);
2777 break;
2778 case 'd':
2779 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2780 conv.d.v);
2781 break;
2782 case 'e':
2783 n = snprintf(num.str_s, fd->max_demangled_size, fd->spec,
2784 conv.ld.v);
2785 }
2786
2787 if (n >= fd->max_demangled_size || n <= 0) {
2788 str_fini(&num);
2789 return (first);
2790 }
2791
2792 num.str_len = n;
2793 (void) name_add_str(&db->cpp_name, &num, NULL);
2794
2795 return (t + 1);
2796 }
2797
2798 /*
2799 * <expr-primary> ::= L <type> <value number> E # integer literal
2800 * ::= L <type> <value float> E # floating literal
2801 * ::= L <string type> E # string literal
2802 * ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
2803 *
2804 * ::= L <type> <real-part float> _ <imag-part float> E
2805 * # complex floating point
2806 * # literal (C 2000)
2807 *
2808 * ::= L <mangled-name> E # external name
2809 */
2810 static struct {
2811 int c;
2812 const char *fmt;
2813 } int_lits[] = {
3387 if (t1[0] != '_')
3388 return (first);
3389
3390 t = t1;
3391 } else {
3392 nadd_l(db, "", 0);
3393 }
3394
3395 VERIFY3U(t[0], ==, '_');
3396
3397 t1 = parse_type(t + 1, last, db);
3398 if (t1 == t + 1 || NAMT(db, n) != 2)
3399 return (first);
3400
3401 /*
3402 * if we have " [xxx]" already, want new result to be
3403 * " [yyy][xxx]"
3404 */
3405 str_t *r = &name_top(&db->cpp_name)->strp_r;
3406 if (r->str_len > 1 && r->str_s[0] == ' ' && r->str_s[1] == '[')
3407 (void) str_erase(r, 0, 1);
3408
3409 nfmt(db, "{0:L}", " [{1}]{0:R}");
3410 return (t1);
3411 }
3412
3413 /* <pointer-to-member-type> ::= M <class type> <member type> */
3414 static const char *
3415 parse_pointer_to_member_type(const char *first, const char *last, cpp_db_t *db)
3416 {
3417 VERIFY3P(first, <=, last);
3418
3419 if (last - first < 3)
3420 return (first);
3421
3422 VERIFY3U(first[0], ==, 'M');
3423
3424 const char *t1 = first + 1;
3425 const char *t2 = NULL;
3426 size_t n = nlen(db);
3427
3469 return (first);
3470
3471 const char *t = first;
3472 const char *t2 = NULL;
3473 boolean_t global = B_FALSE;
3474 size_t n;
3475
3476 if (t[0] == 'g' && t[1] == 's') {
3477 global = B_TRUE;
3478 t += 2;
3479 }
3480 if (t == last)
3481 return (first);
3482
3483 t2 = parse_base_unresolved_name(t, last, db);
3484 if (t != t2) {
3485 if (global) {
3486 if (nempty(db))
3487 return (first);
3488
3489 (void) str_insert(TOP_L(db), 0, "::", 2);
3490 }
3491 return (t2);
3492 }
3493
3494 if (t[0] != 's' || t[1] != 'r' || last - t < 2)
3495 return (first);
3496
3497 n = nlen(db);
3498 if (t[2] == 'N') {
3499 t += 3;
3500 t2 = parse_unresolved_type(t, last, db);
3501 if (t2 == t || t2 == last)
3502 return (first);
3503 t = t2;
3504
3505 t2 = parse_template_args(t, last, db);
3506 if (t2 != t) {
3507 if (NAMT(db, n) < 2 || t2 == last)
3508 return (first);
3509
|