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