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