1 %define api.pure full 2 %parse-param {void *_parse_state} 3 %parse-param {void *scanner} 4 %lex-param {void* scanner} 5 %locations 6 7 %{ 8 9 #define YYDEBUG 1 10 11 #include <errno.h> 12 #include <fnmatch.h> 13 #include <stdio.h> 14 #include <linux/compiler.h> 15 #include <linux/types.h> 16 #include <linux/zalloc.h> 17 #include "pmu.h" 18 #include "pmus.h" 19 #include "evsel.h" 20 #include "parse-events.h" 21 #include "parse-events-bison.h" 22 23 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg); 24 25 #define ABORT_ON(val) \ 26 do { \ 27 if (val) \ 28 YYABORT; \ 29 } while (0) 30 31 static struct list_head* alloc_list(void) 32 { 33 struct list_head *list; 34 35 list = malloc(sizeof(*list)); 36 if (!list) 37 return NULL; 38 39 INIT_LIST_HEAD(list); 40 return list; 41 } 42 43 static void free_list_evsel(struct list_head* list_evsel) 44 { 45 struct evsel *evsel, *tmp; 46 47 list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) { 48 list_del_init(&evsel->core.node); 49 evsel__delete(evsel); 50 } 51 free(list_evsel); 52 } 53 54 %} 55 56 %token PE_START_EVENTS PE_START_TERMS 57 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM 58 %token PE_VALUE_SYM_TOOL 59 %token PE_EVENT_NAME 60 %token PE_RAW PE_NAME 61 %token PE_BPF_OBJECT PE_BPF_SOURCE 62 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH 63 %token PE_LEGACY_CACHE 64 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 65 %token PE_ERROR 66 %token PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE 67 %token PE_ARRAY_ALL PE_ARRAY_RANGE 68 %token PE_DRV_CFG_TERM 69 %token PE_TERM_HW 70 %type <num> PE_VALUE 71 %type <num> PE_VALUE_SYM_HW 72 %type <num> PE_VALUE_SYM_SW 73 %type <num> PE_VALUE_SYM_TOOL 74 %type <num> PE_TERM 75 %type <num> value_sym 76 %type <str> PE_RAW 77 %type <str> PE_NAME 78 %type <str> PE_BPF_OBJECT 79 %type <str> PE_BPF_SOURCE 80 %type <str> PE_LEGACY_CACHE 81 %type <str> PE_MODIFIER_EVENT 82 %type <str> PE_MODIFIER_BP 83 %type <str> PE_BP_COLON 84 %type <str> PE_BP_SLASH 85 %type <str> PE_EVENT_NAME 86 %type <str> PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE 87 %type <str> PE_DRV_CFG_TERM 88 %type <str> name_or_raw name_or_legacy 89 %destructor { free ($$); } <str> 90 %type <term> event_term 91 %destructor { parse_events_term__delete ($$); } <term> 92 %type <list_terms> event_config 93 %type <list_terms> opt_event_config 94 %type <list_terms> opt_pmu_config 95 %destructor { parse_events_terms__delete ($$); } <list_terms> 96 %type <list_evsel> event_pmu 97 %type <list_evsel> event_legacy_symbol 98 %type <list_evsel> event_legacy_cache 99 %type <list_evsel> event_legacy_mem 100 %type <list_evsel> event_legacy_tracepoint 101 %type <list_evsel> event_legacy_numeric 102 %type <list_evsel> event_legacy_raw 103 %type <list_evsel> event_bpf_file 104 %type <list_evsel> event_def 105 %type <list_evsel> event_mod 106 %type <list_evsel> event_name 107 %type <list_evsel> event 108 %type <list_evsel> events 109 %type <list_evsel> group_def 110 %type <list_evsel> group 111 %type <list_evsel> groups 112 %destructor { free_list_evsel ($$); } <list_evsel> 113 %type <tracepoint_name> tracepoint_name 114 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name> 115 %type <array> array 116 %type <array> array_term 117 %type <array> array_terms 118 %destructor { free ($$.ranges); } <array> 119 %type <hardware_term> PE_TERM_HW 120 %destructor { free ($$.str); } <hardware_term> 121 122 %union 123 { 124 char *str; 125 u64 num; 126 struct list_head *list_evsel; 127 struct list_head *list_terms; 128 struct parse_events_term *term; 129 struct tracepoint_name { 130 char *sys; 131 char *event; 132 } tracepoint_name; 133 struct parse_events_array array; 134 struct hardware_term { 135 char *str; 136 u64 num; 137 } hardware_term; 138 } 139 %% 140 141 start: 142 PE_START_EVENTS start_events 143 | 144 PE_START_TERMS start_terms 145 146 start_events: groups 147 { 148 struct parse_events_state *parse_state = _parse_state; 149 150 /* frees $1 */ 151 parse_events_update_lists($1, &parse_state->list); 152 } 153 154 groups: 155 groups ',' group 156 { 157 struct list_head *list = $1; 158 struct list_head *group = $3; 159 160 /* frees $3 */ 161 parse_events_update_lists(group, list); 162 $$ = list; 163 } 164 | 165 groups ',' event 166 { 167 struct list_head *list = $1; 168 struct list_head *event = $3; 169 170 /* frees $3 */ 171 parse_events_update_lists(event, list); 172 $$ = list; 173 } 174 | 175 group 176 | 177 event 178 179 group: 180 group_def ':' PE_MODIFIER_EVENT 181 { 182 struct list_head *list = $1; 183 int err; 184 185 err = parse_events__modifier_group(list, $3); 186 free($3); 187 if (err) { 188 struct parse_events_state *parse_state = _parse_state; 189 struct parse_events_error *error = parse_state->error; 190 191 parse_events_error__handle(error, @3.first_column, 192 strdup("Bad modifier"), NULL); 193 free_list_evsel(list); 194 YYABORT; 195 } 196 $$ = list; 197 } 198 | 199 group_def 200 201 group_def: 202 PE_NAME '{' events '}' 203 { 204 struct list_head *list = $3; 205 206 /* Takes ownership of $1. */ 207 parse_events__set_leader($1, list); 208 $$ = list; 209 } 210 | 211 '{' events '}' 212 { 213 struct list_head *list = $2; 214 215 parse_events__set_leader(NULL, list); 216 $$ = list; 217 } 218 219 events: 220 events ',' event 221 { 222 struct list_head *event = $3; 223 struct list_head *list = $1; 224 225 /* frees $3 */ 226 parse_events_update_lists(event, list); 227 $$ = list; 228 } 229 | 230 event 231 232 event: event_mod 233 234 event_mod: 235 event_name PE_MODIFIER_EVENT 236 { 237 struct list_head *list = $1; 238 int err; 239 240 /* 241 * Apply modifier on all events added by single event definition 242 * (there could be more events added for multiple tracepoint 243 * definitions via '*?'. 244 */ 245 err = parse_events__modifier_event(list, $2, false); 246 free($2); 247 if (err) { 248 struct parse_events_state *parse_state = _parse_state; 249 struct parse_events_error *error = parse_state->error; 250 251 parse_events_error__handle(error, @2.first_column, 252 strdup("Bad modifier"), NULL); 253 free_list_evsel(list); 254 YYABORT; 255 } 256 $$ = list; 257 } 258 | 259 event_name 260 261 event_name: 262 PE_EVENT_NAME event_def 263 { 264 int err; 265 266 err = parse_events_name($2, $1); 267 free($1); 268 if (err) { 269 free_list_evsel($2); 270 YYABORT; 271 } 272 $$ = $2; 273 } 274 | 275 event_def 276 277 event_def: event_pmu | 278 event_legacy_symbol | 279 event_legacy_cache sep_dc | 280 event_legacy_mem sep_dc | 281 event_legacy_tracepoint sep_dc | 282 event_legacy_numeric sep_dc | 283 event_legacy_raw sep_dc | 284 event_bpf_file 285 286 event_pmu: 287 PE_NAME opt_pmu_config 288 { 289 struct parse_events_state *parse_state = _parse_state; 290 struct parse_events_error *error = parse_state->error; 291 struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL; 292 char *pattern = NULL; 293 294 #define CLEANUP_YYABORT \ 295 do { \ 296 parse_events_terms__delete($2); \ 297 parse_events_terms__delete(orig_terms); \ 298 free(list); \ 299 free($1); \ 300 free(pattern); \ 301 YYABORT; \ 302 } while(0) 303 304 if (parse_events_copy_term_list($2, &orig_terms)) 305 CLEANUP_YYABORT; 306 307 if (error) 308 error->idx = @1.first_column; 309 310 list = alloc_list(); 311 if (!list) 312 CLEANUP_YYABORT; 313 /* Attempt to add to list assuming $1 is a PMU name. */ 314 if (parse_events_add_pmu(parse_state, list, $1, $2, /*auto_merge_stats=*/false)) { 315 struct perf_pmu *pmu = NULL; 316 int ok = 0; 317 318 /* Failure to add, try wildcard expansion of $1 as a PMU name. */ 319 if (asprintf(&pattern, "%s*", $1) < 0) 320 CLEANUP_YYABORT; 321 322 while ((pmu = perf_pmus__scan(pmu)) != NULL) { 323 char *name = pmu->name; 324 325 if (parse_events__filter_pmu(parse_state, pmu)) 326 continue; 327 328 if (!strncmp(name, "uncore_", 7) && 329 strncmp($1, "uncore_", 7)) 330 name += 7; 331 if (!perf_pmu__match(pattern, name, $1) || 332 !perf_pmu__match(pattern, pmu->alias_name, $1)) { 333 bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu); 334 335 if (parse_events_copy_term_list(orig_terms, &terms)) 336 CLEANUP_YYABORT; 337 if (!parse_events_add_pmu(parse_state, list, pmu->name, terms, 338 auto_merge_stats)) { 339 ok++; 340 parse_state->wild_card_pmus = true; 341 } 342 parse_events_terms__delete(terms); 343 } 344 } 345 346 if (!ok) { 347 /* Failure to add, assume $1 is an event name. */ 348 zfree(&list); 349 ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list); 350 $2 = NULL; 351 } 352 if (!ok) 353 CLEANUP_YYABORT; 354 } 355 parse_events_terms__delete($2); 356 parse_events_terms__delete(orig_terms); 357 free(pattern); 358 free($1); 359 $$ = list; 360 #undef CLEANUP_YYABORT 361 } 362 | 363 PE_KERNEL_PMU_EVENT sep_dc 364 { 365 struct list_head *list; 366 int err; 367 368 err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list); 369 free($1); 370 if (err < 0) 371 YYABORT; 372 $$ = list; 373 } 374 | 375 PE_NAME sep_dc 376 { 377 struct list_head *list; 378 int err; 379 380 err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list); 381 free($1); 382 if (err < 0) 383 YYABORT; 384 $$ = list; 385 } 386 | 387 PE_KERNEL_PMU_EVENT opt_pmu_config 388 { 389 struct list_head *list; 390 int err; 391 392 /* frees $2 */ 393 err = parse_events_multi_pmu_add(_parse_state, $1, $2, &list); 394 free($1); 395 if (err < 0) 396 YYABORT; 397 $$ = list; 398 } 399 | 400 PE_PMU_EVENT_FAKE sep_dc 401 { 402 struct list_head *list; 403 int err; 404 405 list = alloc_list(); 406 if (!list) 407 YYABORT; 408 409 err = parse_events_add_pmu(_parse_state, list, $1, /*head_config=*/NULL, 410 /*auto_merge_stats=*/false); 411 free($1); 412 if (err < 0) { 413 free(list); 414 YYABORT; 415 } 416 $$ = list; 417 } 418 | 419 PE_PMU_EVENT_FAKE opt_pmu_config 420 { 421 struct list_head *list; 422 int err; 423 424 list = alloc_list(); 425 if (!list) 426 YYABORT; 427 428 err = parse_events_add_pmu(_parse_state, list, $1, $2, /*auto_merge_stats=*/false); 429 free($1); 430 parse_events_terms__delete($2); 431 if (err < 0) { 432 free(list); 433 YYABORT; 434 } 435 $$ = list; 436 } 437 438 value_sym: 439 PE_VALUE_SYM_HW 440 | 441 PE_VALUE_SYM_SW 442 443 event_legacy_symbol: 444 value_sym '/' event_config '/' 445 { 446 struct list_head *list; 447 int type = $1 >> 16; 448 int config = $1 & 255; 449 int err; 450 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 451 452 list = alloc_list(); 453 ABORT_ON(!list); 454 err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard); 455 parse_events_terms__delete($3); 456 if (err) { 457 free_list_evsel(list); 458 YYABORT; 459 } 460 $$ = list; 461 } 462 | 463 value_sym sep_slash_slash_dc 464 { 465 struct list_head *list; 466 int type = $1 >> 16; 467 int config = $1 & 255; 468 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 469 470 list = alloc_list(); 471 ABORT_ON(!list); 472 ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, 473 /*head_config=*/NULL, wildcard)); 474 $$ = list; 475 } 476 | 477 PE_VALUE_SYM_TOOL sep_slash_slash_dc 478 { 479 struct list_head *list; 480 481 list = alloc_list(); 482 ABORT_ON(!list); 483 ABORT_ON(parse_events_add_tool(_parse_state, list, $1)); 484 $$ = list; 485 } 486 487 event_legacy_cache: 488 PE_LEGACY_CACHE opt_event_config 489 { 490 struct parse_events_state *parse_state = _parse_state; 491 struct list_head *list; 492 int err; 493 494 list = alloc_list(); 495 ABORT_ON(!list); 496 err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2); 497 498 parse_events_terms__delete($2); 499 free($1); 500 if (err) { 501 free_list_evsel(list); 502 YYABORT; 503 } 504 $$ = list; 505 } 506 507 event_legacy_mem: 508 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 509 { 510 struct list_head *list; 511 int err; 512 513 parse_events_unused_value(&$3); 514 parse_events_unused_value(&$5); 515 516 list = alloc_list(); 517 ABORT_ON(!list); 518 err = parse_events_add_breakpoint(_parse_state, list, 519 $2, $6, $4, $7); 520 parse_events_terms__delete($7); 521 free($6); 522 if (err) { 523 free(list); 524 YYABORT; 525 } 526 $$ = list; 527 } 528 | 529 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config 530 { 531 struct list_head *list; 532 int err; 533 534 parse_events_unused_value(&$3); 535 536 list = alloc_list(); 537 ABORT_ON(!list); 538 err = parse_events_add_breakpoint(_parse_state, list, 539 $2, NULL, $4, $5); 540 parse_events_terms__delete($5); 541 if (err) { 542 free(list); 543 YYABORT; 544 } 545 $$ = list; 546 } 547 | 548 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 549 { 550 struct list_head *list; 551 int err; 552 553 parse_events_unused_value(&$3); 554 555 list = alloc_list(); 556 ABORT_ON(!list); 557 err = parse_events_add_breakpoint(_parse_state, list, 558 $2, $4, 0, $5); 559 parse_events_terms__delete($5); 560 free($4); 561 if (err) { 562 free(list); 563 YYABORT; 564 } 565 $$ = list; 566 } 567 | 568 PE_PREFIX_MEM PE_VALUE opt_event_config 569 { 570 struct list_head *list; 571 int err; 572 573 list = alloc_list(); 574 ABORT_ON(!list); 575 err = parse_events_add_breakpoint(_parse_state, list, 576 $2, NULL, 0, $3); 577 parse_events_terms__delete($3); 578 if (err) { 579 free(list); 580 YYABORT; 581 } 582 $$ = list; 583 } 584 585 event_legacy_tracepoint: 586 tracepoint_name opt_event_config 587 { 588 struct parse_events_state *parse_state = _parse_state; 589 struct parse_events_error *error = parse_state->error; 590 struct list_head *list; 591 int err; 592 593 list = alloc_list(); 594 ABORT_ON(!list); 595 if (error) 596 error->idx = @1.first_column; 597 598 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event, 599 error, $2); 600 601 parse_events_terms__delete($2); 602 free($1.sys); 603 free($1.event); 604 if (err) { 605 free(list); 606 YYABORT; 607 } 608 $$ = list; 609 } 610 611 tracepoint_name: 612 PE_NAME ':' PE_NAME 613 { 614 struct tracepoint_name tracepoint = {$1, $3}; 615 616 $$ = tracepoint; 617 } 618 619 event_legacy_numeric: 620 PE_VALUE ':' PE_VALUE opt_event_config 621 { 622 struct list_head *list; 623 int err; 624 625 list = alloc_list(); 626 ABORT_ON(!list); 627 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4, 628 /*wildcard=*/false); 629 parse_events_terms__delete($4); 630 if (err) { 631 free(list); 632 YYABORT; 633 } 634 $$ = list; 635 } 636 637 event_legacy_raw: 638 PE_RAW opt_event_config 639 { 640 struct list_head *list; 641 int err; 642 u64 num; 643 644 list = alloc_list(); 645 ABORT_ON(!list); 646 errno = 0; 647 num = strtoull($1 + 1, NULL, 16); 648 ABORT_ON(errno); 649 free($1); 650 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2, 651 /*wildcard=*/false); 652 parse_events_terms__delete($2); 653 if (err) { 654 free(list); 655 YYABORT; 656 } 657 $$ = list; 658 } 659 660 event_bpf_file: 661 PE_BPF_OBJECT opt_event_config 662 { 663 struct parse_events_state *parse_state = _parse_state; 664 struct list_head *list; 665 int err; 666 667 list = alloc_list(); 668 ABORT_ON(!list); 669 err = parse_events_load_bpf(parse_state, list, $1, false, $2); 670 parse_events_terms__delete($2); 671 free($1); 672 if (err) { 673 free(list); 674 YYABORT; 675 } 676 $$ = list; 677 } 678 | 679 PE_BPF_SOURCE opt_event_config 680 { 681 struct list_head *list; 682 int err; 683 684 list = alloc_list(); 685 ABORT_ON(!list); 686 err = parse_events_load_bpf(_parse_state, list, $1, true, $2); 687 parse_events_terms__delete($2); 688 if (err) { 689 free(list); 690 YYABORT; 691 } 692 $$ = list; 693 } 694 695 opt_event_config: 696 '/' event_config '/' 697 { 698 $$ = $2; 699 } 700 | 701 '/' '/' 702 { 703 $$ = NULL; 704 } 705 | 706 { 707 $$ = NULL; 708 } 709 710 opt_pmu_config: 711 '/' event_config '/' 712 { 713 $$ = $2; 714 } 715 | 716 '/' '/' 717 { 718 $$ = NULL; 719 } 720 721 start_terms: event_config 722 { 723 struct parse_events_state *parse_state = _parse_state; 724 if (parse_state->terms) { 725 parse_events_terms__delete ($1); 726 YYABORT; 727 } 728 parse_state->terms = $1; 729 } 730 731 event_config: 732 event_config ',' event_term 733 { 734 struct list_head *head = $1; 735 struct parse_events_term *term = $3; 736 737 if (!head) { 738 parse_events_term__delete(term); 739 YYABORT; 740 } 741 list_add_tail(&term->list, head); 742 $$ = $1; 743 } 744 | 745 event_term 746 { 747 struct list_head *head = malloc(sizeof(*head)); 748 struct parse_events_term *term = $1; 749 750 ABORT_ON(!head); 751 INIT_LIST_HEAD(head); 752 list_add_tail(&term->list, head); 753 $$ = head; 754 } 755 756 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE 757 758 name_or_legacy: PE_NAME | PE_LEGACY_CACHE 759 760 event_term: 761 PE_RAW 762 { 763 struct parse_events_term *term; 764 765 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW, 766 strdup("raw"), $1, &@1, &@1)) { 767 free($1); 768 YYABORT; 769 } 770 $$ = term; 771 } 772 | 773 name_or_raw '=' name_or_legacy 774 { 775 struct parse_events_term *term; 776 777 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 778 $1, $3, &@1, &@3)) { 779 free($1); 780 free($3); 781 YYABORT; 782 } 783 $$ = term; 784 } 785 | 786 name_or_raw '=' PE_VALUE 787 { 788 struct parse_events_term *term; 789 790 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 791 $1, $3, false, &@1, &@3)) { 792 free($1); 793 YYABORT; 794 } 795 $$ = term; 796 } 797 | 798 name_or_raw '=' PE_TERM_HW 799 { 800 struct parse_events_term *term; 801 802 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 803 $1, $3.str, &@1, &@3)) { 804 free($1); 805 free($3.str); 806 YYABORT; 807 } 808 $$ = term; 809 } 810 | 811 PE_LEGACY_CACHE 812 { 813 struct parse_events_term *term; 814 815 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, 816 $1, 1, true, &@1, NULL)) { 817 free($1); 818 YYABORT; 819 } 820 $$ = term; 821 } 822 | 823 PE_NAME 824 { 825 struct parse_events_term *term; 826 827 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 828 $1, 1, true, &@1, NULL)) { 829 free($1); 830 YYABORT; 831 } 832 $$ = term; 833 } 834 | 835 PE_TERM_HW 836 { 837 struct parse_events_term *term; 838 839 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE, 840 $1.str, $1.num & 255, false, &@1, NULL)) { 841 free($1.str); 842 YYABORT; 843 } 844 $$ = term; 845 } 846 | 847 PE_TERM '=' name_or_legacy 848 { 849 struct parse_events_term *term; 850 851 if (parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3)) { 852 free($3); 853 YYABORT; 854 } 855 $$ = term; 856 } 857 | 858 PE_TERM '=' PE_TERM_HW 859 { 860 struct parse_events_term *term; 861 862 if (parse_events_term__str(&term, (int)$1, NULL, $3.str, &@1, &@3)) { 863 free($3.str); 864 YYABORT; 865 } 866 $$ = term; 867 } 868 | 869 PE_TERM '=' PE_TERM 870 { 871 struct parse_events_term *term; 872 873 ABORT_ON(parse_events_term__term(&term, (int)$1, (int)$3, &@1, &@3)); 874 $$ = term; 875 } 876 | 877 PE_TERM '=' PE_VALUE 878 { 879 struct parse_events_term *term; 880 881 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3)); 882 $$ = term; 883 } 884 | 885 PE_TERM 886 { 887 struct parse_events_term *term; 888 889 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL)); 890 $$ = term; 891 } 892 | 893 name_or_raw array '=' name_or_legacy 894 { 895 struct parse_events_term *term; 896 897 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 898 $1, $4, &@1, &@4)) { 899 free($1); 900 free($4); 901 free($2.ranges); 902 YYABORT; 903 } 904 term->array = $2; 905 $$ = term; 906 } 907 | 908 name_or_raw array '=' PE_VALUE 909 { 910 struct parse_events_term *term; 911 912 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 913 $1, $4, false, &@1, &@4)) { 914 free($1); 915 free($2.ranges); 916 YYABORT; 917 } 918 term->array = $2; 919 $$ = term; 920 } 921 | 922 PE_DRV_CFG_TERM 923 { 924 struct parse_events_term *term; 925 char *config = strdup($1); 926 927 ABORT_ON(!config); 928 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, 929 config, $1, &@1, NULL)) { 930 free($1); 931 free(config); 932 YYABORT; 933 } 934 $$ = term; 935 } 936 937 array: 938 '[' array_terms ']' 939 { 940 $$ = $2; 941 } 942 | 943 PE_ARRAY_ALL 944 { 945 $$.nr_ranges = 0; 946 $$.ranges = NULL; 947 } 948 949 array_terms: 950 array_terms ',' array_term 951 { 952 struct parse_events_array new_array; 953 954 new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges; 955 new_array.ranges = realloc($1.ranges, 956 sizeof(new_array.ranges[0]) * 957 new_array.nr_ranges); 958 ABORT_ON(!new_array.ranges); 959 memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges, 960 $3.nr_ranges * sizeof(new_array.ranges[0])); 961 free($3.ranges); 962 $$ = new_array; 963 } 964 | 965 array_term 966 967 array_term: 968 PE_VALUE 969 { 970 struct parse_events_array array; 971 972 array.nr_ranges = 1; 973 array.ranges = malloc(sizeof(array.ranges[0])); 974 ABORT_ON(!array.ranges); 975 array.ranges[0].start = $1; 976 array.ranges[0].length = 1; 977 $$ = array; 978 } 979 | 980 PE_VALUE PE_ARRAY_RANGE PE_VALUE 981 { 982 struct parse_events_array array; 983 984 ABORT_ON($3 < $1); 985 array.nr_ranges = 1; 986 array.ranges = malloc(sizeof(array.ranges[0])); 987 ABORT_ON(!array.ranges); 988 array.ranges[0].start = $1; 989 array.ranges[0].length = $3 - $1 + 1; 990 $$ = array; 991 } 992 993 sep_dc: ':' | 994 995 sep_slash_slash_dc: '/' '/' | ':' | 996 997 %% 998 999 void parse_events_error(YYLTYPE *loc, void *parse_state, 1000 void *scanner __maybe_unused, 1001 char const *msg __maybe_unused) 1002 { 1003 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 1004 } 1005