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 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 | 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 449 list = alloc_list(); 450 ABORT_ON(!list); 451 err = parse_events_add_numeric(_parse_state, list, type, config, $3, 452 /*wildcard=*/false); 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 467 list = alloc_list(); 468 ABORT_ON(!list); 469 ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, 470 /*head_config=*/NULL, 471 /*wildcard=*/false)); 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_VALUE ':' PE_MODIFIER_BP sep_dc 507 { 508 struct parse_events_state *parse_state = _parse_state; 509 struct list_head *list; 510 int err; 511 512 list = alloc_list(); 513 ABORT_ON(!list); 514 err = parse_events_add_breakpoint(list, &parse_state->idx, 515 $2, $6, $4); 516 free($6); 517 if (err) { 518 free(list); 519 YYABORT; 520 } 521 $$ = list; 522 } 523 | 524 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc 525 { 526 struct parse_events_state *parse_state = _parse_state; 527 struct list_head *list; 528 529 list = alloc_list(); 530 ABORT_ON(!list); 531 if (parse_events_add_breakpoint(list, &parse_state->idx, 532 $2, NULL, $4)) { 533 free(list); 534 YYABORT; 535 } 536 $$ = list; 537 } 538 | 539 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 540 { 541 struct parse_events_state *parse_state = _parse_state; 542 struct list_head *list; 543 int err; 544 545 list = alloc_list(); 546 ABORT_ON(!list); 547 err = parse_events_add_breakpoint(list, &parse_state->idx, 548 $2, $4, 0); 549 free($4); 550 if (err) { 551 free(list); 552 YYABORT; 553 } 554 $$ = list; 555 } 556 | 557 PE_PREFIX_MEM PE_VALUE sep_dc 558 { 559 struct parse_events_state *parse_state = _parse_state; 560 struct list_head *list; 561 562 list = alloc_list(); 563 ABORT_ON(!list); 564 if (parse_events_add_breakpoint(list, &parse_state->idx, 565 $2, NULL, 0)) { 566 free(list); 567 YYABORT; 568 } 569 $$ = list; 570 } 571 572 event_legacy_tracepoint: 573 tracepoint_name opt_event_config 574 { 575 struct parse_events_state *parse_state = _parse_state; 576 struct parse_events_error *error = parse_state->error; 577 struct list_head *list; 578 int err; 579 580 list = alloc_list(); 581 ABORT_ON(!list); 582 if (error) 583 error->idx = @1.first_column; 584 585 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event, 586 error, $2); 587 588 parse_events_terms__delete($2); 589 free($1.sys); 590 free($1.event); 591 if (err) { 592 free(list); 593 YYABORT; 594 } 595 $$ = list; 596 } 597 598 tracepoint_name: 599 PE_NAME ':' PE_NAME 600 { 601 struct tracepoint_name tracepoint = {$1, $3}; 602 603 $$ = tracepoint; 604 } 605 606 event_legacy_numeric: 607 PE_VALUE ':' PE_VALUE opt_event_config 608 { 609 struct list_head *list; 610 int err; 611 612 list = alloc_list(); 613 ABORT_ON(!list); 614 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4, 615 /*wildcard=*/false); 616 parse_events_terms__delete($4); 617 if (err) { 618 free(list); 619 YYABORT; 620 } 621 $$ = list; 622 } 623 624 event_legacy_raw: 625 PE_RAW opt_event_config 626 { 627 struct list_head *list; 628 int err; 629 u64 num; 630 631 list = alloc_list(); 632 ABORT_ON(!list); 633 errno = 0; 634 num = strtoull($1 + 1, NULL, 16); 635 ABORT_ON(errno); 636 free($1); 637 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2, 638 /*wildcard=*/true); 639 parse_events_terms__delete($2); 640 if (err) { 641 free(list); 642 YYABORT; 643 } 644 $$ = list; 645 } 646 647 event_bpf_file: 648 PE_BPF_OBJECT opt_event_config 649 { 650 struct parse_events_state *parse_state = _parse_state; 651 struct list_head *list; 652 int err; 653 654 list = alloc_list(); 655 ABORT_ON(!list); 656 err = parse_events_load_bpf(parse_state, list, $1, false, $2); 657 parse_events_terms__delete($2); 658 free($1); 659 if (err) { 660 free(list); 661 YYABORT; 662 } 663 $$ = list; 664 } 665 | 666 PE_BPF_SOURCE opt_event_config 667 { 668 struct list_head *list; 669 int err; 670 671 list = alloc_list(); 672 ABORT_ON(!list); 673 err = parse_events_load_bpf(_parse_state, list, $1, true, $2); 674 parse_events_terms__delete($2); 675 if (err) { 676 free(list); 677 YYABORT; 678 } 679 $$ = list; 680 } 681 682 opt_event_config: 683 '/' event_config '/' 684 { 685 $$ = $2; 686 } 687 | 688 '/' '/' 689 { 690 $$ = NULL; 691 } 692 | 693 { 694 $$ = NULL; 695 } 696 697 opt_pmu_config: 698 '/' event_config '/' 699 { 700 $$ = $2; 701 } 702 | 703 '/' '/' 704 { 705 $$ = NULL; 706 } 707 708 start_terms: event_config 709 { 710 struct parse_events_state *parse_state = _parse_state; 711 if (parse_state->terms) { 712 parse_events_terms__delete ($1); 713 YYABORT; 714 } 715 parse_state->terms = $1; 716 } 717 718 event_config: 719 event_config ',' event_term 720 { 721 struct list_head *head = $1; 722 struct parse_events_term *term = $3; 723 724 if (!head) { 725 parse_events_term__delete(term); 726 YYABORT; 727 } 728 list_add_tail(&term->list, head); 729 $$ = $1; 730 } 731 | 732 event_term 733 { 734 struct list_head *head = malloc(sizeof(*head)); 735 struct parse_events_term *term = $1; 736 737 ABORT_ON(!head); 738 INIT_LIST_HEAD(head); 739 list_add_tail(&term->list, head); 740 $$ = head; 741 } 742 743 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE 744 745 name_or_legacy: PE_NAME | PE_LEGACY_CACHE 746 747 event_term: 748 PE_RAW 749 { 750 struct parse_events_term *term; 751 752 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW, 753 strdup("raw"), $1, &@1, &@1)) { 754 free($1); 755 YYABORT; 756 } 757 $$ = term; 758 } 759 | 760 name_or_raw '=' name_or_legacy 761 { 762 struct parse_events_term *term; 763 764 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 765 $1, $3, &@1, &@3)) { 766 free($1); 767 free($3); 768 YYABORT; 769 } 770 $$ = term; 771 } 772 | 773 name_or_raw '=' PE_VALUE 774 { 775 struct parse_events_term *term; 776 777 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 778 $1, $3, false, &@1, &@3)) { 779 free($1); 780 YYABORT; 781 } 782 $$ = term; 783 } 784 | 785 name_or_raw '=' PE_TERM_HW 786 { 787 struct parse_events_term *term; 788 789 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 790 $1, $3.str, &@1, &@3)) { 791 free($1); 792 free($3.str); 793 YYABORT; 794 } 795 $$ = term; 796 } 797 | 798 PE_LEGACY_CACHE 799 { 800 struct parse_events_term *term; 801 802 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, 803 $1, 1, true, &@1, NULL)) { 804 free($1); 805 YYABORT; 806 } 807 $$ = term; 808 } 809 | 810 PE_NAME 811 { 812 struct parse_events_term *term; 813 814 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 815 $1, 1, true, &@1, NULL)) { 816 free($1); 817 YYABORT; 818 } 819 $$ = term; 820 } 821 | 822 PE_TERM_HW 823 { 824 struct parse_events_term *term; 825 826 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE, 827 $1.str, $1.num & 255, false, &@1, NULL)) { 828 free($1.str); 829 YYABORT; 830 } 831 $$ = term; 832 } 833 | 834 PE_TERM '=' name_or_legacy 835 { 836 struct parse_events_term *term; 837 838 if (parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3)) { 839 free($3); 840 YYABORT; 841 } 842 $$ = term; 843 } 844 | 845 PE_TERM '=' PE_TERM_HW 846 { 847 struct parse_events_term *term; 848 849 if (parse_events_term__str(&term, (int)$1, NULL, $3.str, &@1, &@3)) { 850 free($3.str); 851 YYABORT; 852 } 853 $$ = term; 854 } 855 | 856 PE_TERM '=' PE_TERM 857 { 858 struct parse_events_term *term; 859 860 ABORT_ON(parse_events_term__term(&term, (int)$1, (int)$3, &@1, &@3)); 861 $$ = term; 862 } 863 | 864 PE_TERM '=' PE_VALUE 865 { 866 struct parse_events_term *term; 867 868 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3)); 869 $$ = term; 870 } 871 | 872 PE_TERM 873 { 874 struct parse_events_term *term; 875 876 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL)); 877 $$ = term; 878 } 879 | 880 name_or_raw array '=' name_or_legacy 881 { 882 struct parse_events_term *term; 883 884 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 885 $1, $4, &@1, &@4)) { 886 free($1); 887 free($4); 888 free($2.ranges); 889 YYABORT; 890 } 891 term->array = $2; 892 $$ = term; 893 } 894 | 895 name_or_raw array '=' PE_VALUE 896 { 897 struct parse_events_term *term; 898 899 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 900 $1, $4, false, &@1, &@4)) { 901 free($1); 902 free($2.ranges); 903 YYABORT; 904 } 905 term->array = $2; 906 $$ = term; 907 } 908 | 909 PE_DRV_CFG_TERM 910 { 911 struct parse_events_term *term; 912 char *config = strdup($1); 913 914 ABORT_ON(!config); 915 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, 916 config, $1, &@1, NULL)) { 917 free($1); 918 free(config); 919 YYABORT; 920 } 921 $$ = term; 922 } 923 924 array: 925 '[' array_terms ']' 926 { 927 $$ = $2; 928 } 929 | 930 PE_ARRAY_ALL 931 { 932 $$.nr_ranges = 0; 933 $$.ranges = NULL; 934 } 935 936 array_terms: 937 array_terms ',' array_term 938 { 939 struct parse_events_array new_array; 940 941 new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges; 942 new_array.ranges = realloc($1.ranges, 943 sizeof(new_array.ranges[0]) * 944 new_array.nr_ranges); 945 ABORT_ON(!new_array.ranges); 946 memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges, 947 $3.nr_ranges * sizeof(new_array.ranges[0])); 948 free($3.ranges); 949 $$ = new_array; 950 } 951 | 952 array_term 953 954 array_term: 955 PE_VALUE 956 { 957 struct parse_events_array array; 958 959 array.nr_ranges = 1; 960 array.ranges = malloc(sizeof(array.ranges[0])); 961 ABORT_ON(!array.ranges); 962 array.ranges[0].start = $1; 963 array.ranges[0].length = 1; 964 $$ = array; 965 } 966 | 967 PE_VALUE PE_ARRAY_RANGE PE_VALUE 968 { 969 struct parse_events_array array; 970 971 ABORT_ON($3 < $1); 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 = $3 - $1 + 1; 977 $$ = array; 978 } 979 980 sep_dc: ':' | 981 982 sep_slash_slash_dc: '/' '/' | ':' | 983 984 %% 985 986 void parse_events_error(YYLTYPE *loc, void *parse_state, 987 void *scanner __maybe_unused, 988 char const *msg __maybe_unused) 989 { 990 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 991 } 992