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