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