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 static void inc_group_count(struct list_head *list, 53 struct parse_events_state *parse_state) 54 { 55 /* Count groups only have more than 1 members */ 56 if (!list_is_last(list->next, list)) 57 parse_state->nr_groups++; 58 } 59 60 %} 61 62 %token PE_START_EVENTS PE_START_TERMS 63 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 64 %token PE_VALUE_SYM_TOOL 65 %token PE_EVENT_NAME 66 %token PE_NAME 67 %token PE_BPF_OBJECT PE_BPF_SOURCE 68 %token PE_MODIFIER_EVENT PE_MODIFIER_BP 69 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 70 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 71 %token PE_ERROR 72 %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_PMU_EVENT_SUF2 PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE 73 %token PE_ARRAY_ALL PE_ARRAY_RANGE 74 %token PE_DRV_CFG_TERM 75 %type <num> PE_VALUE 76 %type <num> PE_VALUE_SYM_HW 77 %type <num> PE_VALUE_SYM_SW 78 %type <num> PE_VALUE_SYM_TOOL 79 %type <num> PE_RAW 80 %type <num> PE_TERM 81 %type <num> value_sym 82 %type <str> PE_NAME 83 %type <str> PE_BPF_OBJECT 84 %type <str> PE_BPF_SOURCE 85 %type <str> PE_NAME_CACHE_TYPE 86 %type <str> PE_NAME_CACHE_OP_RESULT 87 %type <str> PE_MODIFIER_EVENT 88 %type <str> PE_MODIFIER_BP 89 %type <str> PE_EVENT_NAME 90 %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_PMU_EVENT_SUF2 PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE 91 %type <str> PE_DRV_CFG_TERM 92 %type <str> event_pmu_name 93 %destructor { free ($$); } <str> 94 %type <term> event_term 95 %destructor { parse_events_term__delete ($$); } <term> 96 %type <list_terms> event_config 97 %type <list_terms> opt_event_config 98 %type <list_terms> opt_pmu_config 99 %destructor { parse_events_terms__delete ($$); } <list_terms> 100 %type <list_evsel> event_pmu 101 %type <list_evsel> event_legacy_symbol 102 %type <list_evsel> event_legacy_cache 103 %type <list_evsel> event_legacy_mem 104 %type <list_evsel> event_legacy_tracepoint 105 %type <list_evsel> event_legacy_numeric 106 %type <list_evsel> event_legacy_raw 107 %type <list_evsel> event_bpf_file 108 %type <list_evsel> event_def 109 %type <list_evsel> event_mod 110 %type <list_evsel> event_name 111 %type <list_evsel> event 112 %type <list_evsel> events 113 %type <list_evsel> group_def 114 %type <list_evsel> group 115 %type <list_evsel> groups 116 %destructor { free_list_evsel ($$); } <list_evsel> 117 %type <tracepoint_name> tracepoint_name 118 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name> 119 %type <array> array 120 %type <array> array_term 121 %type <array> array_terms 122 %destructor { free ($$.ranges); } <array> 123 124 %union 125 { 126 char *str; 127 u64 num; 128 struct list_head *list_evsel; 129 struct list_head *list_terms; 130 struct parse_events_term *term; 131 struct tracepoint_name { 132 char *sys; 133 char *event; 134 } tracepoint_name; 135 struct parse_events_array array; 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 inc_group_count(list, _parse_state); 205 parse_events__set_leader($1, list, _parse_state); 206 free($1); 207 $$ = list; 208 } 209 | 210 '{' events '}' 211 { 212 struct list_head *list = $2; 213 214 inc_group_count(list, _parse_state); 215 parse_events__set_leader(NULL, list, _parse_state); 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 | 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_name: 287 PE_NAME | PE_PMU_EVENT_PRE 288 289 event_pmu: 290 event_pmu_name opt_pmu_config 291 { 292 struct parse_events_state *parse_state = _parse_state; 293 struct parse_events_error *error = parse_state->error; 294 struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL; 295 char *pattern = NULL; 296 297 #define CLEANUP_YYABORT \ 298 do { \ 299 parse_events_terms__delete($2); \ 300 parse_events_terms__delete(orig_terms); \ 301 free(list); \ 302 free($1); \ 303 free(pattern); \ 304 YYABORT; \ 305 } while(0) 306 307 if (parse_events_copy_term_list($2, &orig_terms)) 308 CLEANUP_YYABORT; 309 310 if (error) 311 error->idx = @1.first_column; 312 313 list = alloc_list(); 314 if (!list) 315 CLEANUP_YYABORT; 316 if (parse_events_add_pmu(_parse_state, list, $1, $2, false, false)) { 317 struct perf_pmu *pmu = NULL; 318 int ok = 0; 319 320 if (asprintf(&pattern, "%s*", $1) < 0) 321 CLEANUP_YYABORT; 322 323 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 324 char *name = pmu->name; 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 if (parse_events_copy_term_list(orig_terms, &terms)) 332 CLEANUP_YYABORT; 333 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false)) 334 ok++; 335 parse_events_terms__delete(terms); 336 } 337 } 338 339 if (!ok) 340 CLEANUP_YYABORT; 341 } 342 parse_events_terms__delete($2); 343 parse_events_terms__delete(orig_terms); 344 free(pattern); 345 free($1); 346 $$ = list; 347 #undef CLEANUP_YYABORT 348 } 349 | 350 PE_KERNEL_PMU_EVENT sep_dc 351 { 352 struct list_head *list; 353 int err; 354 355 err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list); 356 free($1); 357 if (err < 0) 358 YYABORT; 359 $$ = list; 360 } 361 | 362 PE_KERNEL_PMU_EVENT opt_pmu_config 363 { 364 struct list_head *list; 365 int err; 366 367 /* frees $2 */ 368 err = parse_events_multi_pmu_add(_parse_state, $1, $2, &list); 369 free($1); 370 if (err < 0) 371 YYABORT; 372 $$ = list; 373 } 374 | 375 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF '-' PE_PMU_EVENT_SUF2 sep_dc 376 { 377 struct list_head *list; 378 char pmu_name[128]; 379 snprintf(pmu_name, sizeof(pmu_name), "%s-%s-%s", $1, $3, $5); 380 free($1); 381 free($3); 382 free($5); 383 if (parse_events_multi_pmu_add(_parse_state, pmu_name, NULL, &list) < 0) 384 YYABORT; 385 $$ = list; 386 } 387 | 388 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc 389 { 390 struct list_head *list; 391 char pmu_name[128]; 392 393 snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3); 394 free($1); 395 free($3); 396 if (parse_events_multi_pmu_add(_parse_state, pmu_name, NULL, &list) < 0) 397 YYABORT; 398 $$ = list; 399 } 400 | 401 PE_PMU_EVENT_FAKE sep_dc 402 { 403 struct list_head *list; 404 int err; 405 406 list = alloc_list(); 407 if (!list) 408 YYABORT; 409 410 err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, 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, false, 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 451 list = alloc_list(); 452 ABORT_ON(!list); 453 err = parse_events_add_numeric(_parse_state, list, type, config, $3); 454 parse_events_terms__delete($3); 455 if (err) { 456 free_list_evsel(list); 457 YYABORT; 458 } 459 $$ = list; 460 } 461 | 462 value_sym sep_slash_slash_dc 463 { 464 struct list_head *list; 465 int type = $1 >> 16; 466 int config = $1 & 255; 467 468 list = alloc_list(); 469 ABORT_ON(!list); 470 ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, NULL)); 471 $$ = list; 472 } 473 | 474 PE_VALUE_SYM_TOOL sep_slash_slash_dc 475 { 476 struct list_head *list; 477 478 list = alloc_list(); 479 ABORT_ON(!list); 480 ABORT_ON(parse_events_add_tool(_parse_state, list, $1)); 481 $$ = list; 482 } 483 484 event_legacy_cache: 485 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config 486 { 487 struct parse_events_state *parse_state = _parse_state; 488 struct parse_events_error *error = parse_state->error; 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, $3, $5, error, $6, 495 parse_state); 496 parse_events_terms__delete($6); 497 free($1); 498 free($3); 499 free($5); 500 if (err) { 501 free_list_evsel(list); 502 YYABORT; 503 } 504 $$ = list; 505 } 506 | 507 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config 508 { 509 struct parse_events_state *parse_state = _parse_state; 510 struct parse_events_error *error = parse_state->error; 511 struct list_head *list; 512 int err; 513 514 list = alloc_list(); 515 ABORT_ON(!list); 516 err = parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4, 517 parse_state); 518 parse_events_terms__delete($4); 519 free($1); 520 free($3); 521 if (err) { 522 free_list_evsel(list); 523 YYABORT; 524 } 525 $$ = list; 526 } 527 | 528 PE_NAME_CACHE_TYPE opt_event_config 529 { 530 struct parse_events_state *parse_state = _parse_state; 531 struct parse_events_error *error = parse_state->error; 532 struct list_head *list; 533 int err; 534 535 list = alloc_list(); 536 ABORT_ON(!list); 537 err = parse_events_add_cache(list, &parse_state->idx, $1, NULL, NULL, error, $2, 538 parse_state); 539 parse_events_terms__delete($2); 540 free($1); 541 if (err) { 542 free_list_evsel(list); 543 YYABORT; 544 } 545 $$ = list; 546 } 547 548 event_legacy_mem: 549 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc 550 { 551 struct parse_events_state *parse_state = _parse_state; 552 struct list_head *list; 553 int err; 554 555 list = alloc_list(); 556 ABORT_ON(!list); 557 err = parse_events_add_breakpoint(list, &parse_state->idx, 558 $2, $6, $4); 559 free($6); 560 if (err) { 561 free(list); 562 YYABORT; 563 } 564 $$ = list; 565 } 566 | 567 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc 568 { 569 struct parse_events_state *parse_state = _parse_state; 570 struct list_head *list; 571 572 list = alloc_list(); 573 ABORT_ON(!list); 574 if (parse_events_add_breakpoint(list, &parse_state->idx, 575 $2, NULL, $4)) { 576 free(list); 577 YYABORT; 578 } 579 $$ = list; 580 } 581 | 582 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 583 { 584 struct parse_events_state *parse_state = _parse_state; 585 struct list_head *list; 586 int err; 587 588 list = alloc_list(); 589 ABORT_ON(!list); 590 err = parse_events_add_breakpoint(list, &parse_state->idx, 591 $2, $4, 0); 592 free($4); 593 if (err) { 594 free(list); 595 YYABORT; 596 } 597 $$ = list; 598 } 599 | 600 PE_PREFIX_MEM PE_VALUE sep_dc 601 { 602 struct parse_events_state *parse_state = _parse_state; 603 struct list_head *list; 604 605 list = alloc_list(); 606 ABORT_ON(!list); 607 if (parse_events_add_breakpoint(list, &parse_state->idx, 608 $2, NULL, 0)) { 609 free(list); 610 YYABORT; 611 } 612 $$ = list; 613 } 614 615 event_legacy_tracepoint: 616 tracepoint_name opt_event_config 617 { 618 struct parse_events_state *parse_state = _parse_state; 619 struct parse_events_error *error = parse_state->error; 620 struct list_head *list; 621 int err; 622 623 list = alloc_list(); 624 ABORT_ON(!list); 625 if (error) 626 error->idx = @1.first_column; 627 628 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event, 629 error, $2); 630 631 parse_events_terms__delete($2); 632 free($1.sys); 633 free($1.event); 634 if (err) { 635 free(list); 636 YYABORT; 637 } 638 $$ = list; 639 } 640 641 tracepoint_name: 642 PE_NAME '-' PE_NAME ':' PE_NAME 643 { 644 struct tracepoint_name tracepoint; 645 646 ABORT_ON(asprintf(&tracepoint.sys, "%s-%s", $1, $3) < 0); 647 tracepoint.event = $5; 648 free($1); 649 free($3); 650 $$ = tracepoint; 651 } 652 | 653 PE_NAME ':' PE_NAME 654 { 655 struct tracepoint_name tracepoint = {$1, $3}; 656 657 $$ = tracepoint; 658 } 659 660 event_legacy_numeric: 661 PE_VALUE ':' PE_VALUE opt_event_config 662 { 663 struct list_head *list; 664 int err; 665 666 list = alloc_list(); 667 ABORT_ON(!list); 668 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4); 669 parse_events_terms__delete($4); 670 if (err) { 671 free(list); 672 YYABORT; 673 } 674 $$ = list; 675 } 676 677 event_legacy_raw: 678 PE_RAW opt_event_config 679 { 680 struct list_head *list; 681 int err; 682 683 list = alloc_list(); 684 ABORT_ON(!list); 685 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2); 686 parse_events_terms__delete($2); 687 if (err) { 688 free(list); 689 YYABORT; 690 } 691 $$ = list; 692 } 693 694 event_bpf_file: 695 PE_BPF_OBJECT opt_event_config 696 { 697 struct parse_events_state *parse_state = _parse_state; 698 struct list_head *list; 699 int err; 700 701 list = alloc_list(); 702 ABORT_ON(!list); 703 err = parse_events_load_bpf(parse_state, list, $1, false, $2); 704 parse_events_terms__delete($2); 705 free($1); 706 if (err) { 707 free(list); 708 YYABORT; 709 } 710 $$ = list; 711 } 712 | 713 PE_BPF_SOURCE opt_event_config 714 { 715 struct list_head *list; 716 int err; 717 718 list = alloc_list(); 719 ABORT_ON(!list); 720 err = parse_events_load_bpf(_parse_state, list, $1, true, $2); 721 parse_events_terms__delete($2); 722 if (err) { 723 free(list); 724 YYABORT; 725 } 726 $$ = list; 727 } 728 729 opt_event_config: 730 '/' event_config '/' 731 { 732 $$ = $2; 733 } 734 | 735 '/' '/' 736 { 737 $$ = NULL; 738 } 739 | 740 { 741 $$ = NULL; 742 } 743 744 opt_pmu_config: 745 '/' event_config '/' 746 { 747 $$ = $2; 748 } 749 | 750 '/' '/' 751 { 752 $$ = NULL; 753 } 754 755 start_terms: event_config 756 { 757 struct parse_events_state *parse_state = _parse_state; 758 if (parse_state->terms) { 759 parse_events_terms__delete ($1); 760 YYABORT; 761 } 762 parse_state->terms = $1; 763 } 764 765 event_config: 766 event_config ',' event_term 767 { 768 struct list_head *head = $1; 769 struct parse_events_term *term = $3; 770 771 if (!head) { 772 parse_events_term__delete(term); 773 YYABORT; 774 } 775 list_add_tail(&term->list, head); 776 $$ = $1; 777 } 778 | 779 event_term 780 { 781 struct list_head *head = malloc(sizeof(*head)); 782 struct parse_events_term *term = $1; 783 784 ABORT_ON(!head); 785 INIT_LIST_HEAD(head); 786 list_add_tail(&term->list, head); 787 $$ = head; 788 } 789 790 event_term: 791 PE_RAW 792 { 793 struct parse_events_term *term; 794 795 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_CONFIG, 796 NULL, $1, false, &@1, NULL)); 797 $$ = term; 798 } 799 | 800 PE_NAME '=' PE_NAME 801 { 802 struct parse_events_term *term; 803 804 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 805 $1, $3, &@1, &@3)) { 806 free($1); 807 free($3); 808 YYABORT; 809 } 810 $$ = term; 811 } 812 | 813 PE_NAME '=' PE_VALUE 814 { 815 struct parse_events_term *term; 816 817 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 818 $1, $3, false, &@1, &@3)) { 819 free($1); 820 YYABORT; 821 } 822 $$ = term; 823 } 824 | 825 PE_NAME '=' PE_VALUE_SYM_HW 826 { 827 struct parse_events_term *term; 828 int config = $3 & 255; 829 830 if (parse_events_term__sym_hw(&term, $1, config)) { 831 free($1); 832 YYABORT; 833 } 834 $$ = term; 835 } 836 | 837 PE_NAME 838 { 839 struct parse_events_term *term; 840 841 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 842 $1, 1, true, &@1, NULL)) { 843 free($1); 844 YYABORT; 845 } 846 $$ = term; 847 } 848 | 849 PE_VALUE_SYM_HW 850 { 851 struct parse_events_term *term; 852 int config = $1 & 255; 853 854 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 855 $$ = term; 856 } 857 | 858 PE_TERM '=' PE_NAME 859 { 860 struct parse_events_term *term; 861 862 if (parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3)) { 863 free($3); 864 YYABORT; 865 } 866 $$ = term; 867 } 868 | 869 PE_TERM '=' PE_VALUE 870 { 871 struct parse_events_term *term; 872 873 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3)); 874 $$ = term; 875 } 876 | 877 PE_TERM 878 { 879 struct parse_events_term *term; 880 881 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL)); 882 $$ = term; 883 } 884 | 885 PE_NAME array '=' PE_NAME 886 { 887 struct parse_events_term *term; 888 889 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 890 $1, $4, &@1, &@4)) { 891 free($1); 892 free($4); 893 free($2.ranges); 894 YYABORT; 895 } 896 term->array = $2; 897 $$ = term; 898 } 899 | 900 PE_NAME array '=' PE_VALUE 901 { 902 struct parse_events_term *term; 903 904 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 905 $1, $4, false, &@1, &@4)) { 906 free($1); 907 free($2.ranges); 908 YYABORT; 909 } 910 term->array = $2; 911 $$ = term; 912 } 913 | 914 PE_DRV_CFG_TERM 915 { 916 struct parse_events_term *term; 917 char *config = strdup($1); 918 919 ABORT_ON(!config); 920 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, 921 config, $1, &@1, NULL)) { 922 free($1); 923 free(config); 924 YYABORT; 925 } 926 $$ = term; 927 } 928 929 array: 930 '[' array_terms ']' 931 { 932 $$ = $2; 933 } 934 | 935 PE_ARRAY_ALL 936 { 937 $$.nr_ranges = 0; 938 $$.ranges = NULL; 939 } 940 941 array_terms: 942 array_terms ',' array_term 943 { 944 struct parse_events_array new_array; 945 946 new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges; 947 new_array.ranges = realloc($1.ranges, 948 sizeof(new_array.ranges[0]) * 949 new_array.nr_ranges); 950 ABORT_ON(!new_array.ranges); 951 memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges, 952 $3.nr_ranges * sizeof(new_array.ranges[0])); 953 free($3.ranges); 954 $$ = new_array; 955 } 956 | 957 array_term 958 959 array_term: 960 PE_VALUE 961 { 962 struct parse_events_array array; 963 964 array.nr_ranges = 1; 965 array.ranges = malloc(sizeof(array.ranges[0])); 966 ABORT_ON(!array.ranges); 967 array.ranges[0].start = $1; 968 array.ranges[0].length = 1; 969 $$ = array; 970 } 971 | 972 PE_VALUE PE_ARRAY_RANGE PE_VALUE 973 { 974 struct parse_events_array array; 975 976 ABORT_ON($3 < $1); 977 array.nr_ranges = 1; 978 array.ranges = malloc(sizeof(array.ranges[0])); 979 ABORT_ON(!array.ranges); 980 array.ranges[0].start = $1; 981 array.ranges[0].length = $3 - $1 + 1; 982 $$ = array; 983 } 984 985 sep_dc: ':' | 986 987 sep_slash_slash_dc: '/' '/' | ':' | 988 989 %% 990 991 void parse_events_error(YYLTYPE *loc, void *parse_state, 992 void *scanner __maybe_unused, 993 char const *msg __maybe_unused) 994 { 995 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 996 } 997