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