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