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