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_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_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 sep_dc 376 { 377 struct list_head *list; 378 char pmu_name[128]; 379 380 snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3); 381 free($1); 382 free($3); 383 if (parse_events_multi_pmu_add(_parse_state, pmu_name, NULL, &list) < 0) 384 YYABORT; 385 $$ = list; 386 } 387 | 388 PE_PMU_EVENT_FAKE sep_dc 389 { 390 struct list_head *list; 391 int err; 392 393 list = alloc_list(); 394 if (!list) 395 YYABORT; 396 397 err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, false); 398 free($1); 399 if (err < 0) { 400 free(list); 401 YYABORT; 402 } 403 $$ = list; 404 } 405 | 406 PE_PMU_EVENT_FAKE opt_pmu_config 407 { 408 struct list_head *list; 409 int err; 410 411 list = alloc_list(); 412 if (!list) 413 YYABORT; 414 415 err = parse_events_add_pmu(_parse_state, list, $1, $2, false, false); 416 free($1); 417 parse_events_terms__delete($2); 418 if (err < 0) { 419 free(list); 420 YYABORT; 421 } 422 $$ = list; 423 } 424 425 value_sym: 426 PE_VALUE_SYM_HW 427 | 428 PE_VALUE_SYM_SW 429 430 event_legacy_symbol: 431 value_sym '/' event_config '/' 432 { 433 struct list_head *list; 434 int type = $1 >> 16; 435 int config = $1 & 255; 436 int err; 437 438 list = alloc_list(); 439 ABORT_ON(!list); 440 err = parse_events_add_numeric(_parse_state, list, type, config, $3); 441 parse_events_terms__delete($3); 442 if (err) { 443 free_list_evsel(list); 444 YYABORT; 445 } 446 $$ = list; 447 } 448 | 449 value_sym sep_slash_slash_dc 450 { 451 struct list_head *list; 452 int type = $1 >> 16; 453 int config = $1 & 255; 454 455 list = alloc_list(); 456 ABORT_ON(!list); 457 ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, NULL)); 458 $$ = list; 459 } 460 | 461 PE_VALUE_SYM_TOOL sep_slash_slash_dc 462 { 463 struct list_head *list; 464 465 list = alloc_list(); 466 ABORT_ON(!list); 467 ABORT_ON(parse_events_add_tool(_parse_state, list, $1)); 468 $$ = list; 469 } 470 471 event_legacy_cache: 472 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config 473 { 474 struct parse_events_state *parse_state = _parse_state; 475 struct parse_events_error *error = parse_state->error; 476 struct list_head *list; 477 int err; 478 479 list = alloc_list(); 480 ABORT_ON(!list); 481 err = parse_events_add_cache(list, &parse_state->idx, $1, $3, $5, error, $6, 482 parse_state); 483 parse_events_terms__delete($6); 484 free($1); 485 free($3); 486 free($5); 487 if (err) { 488 free_list_evsel(list); 489 YYABORT; 490 } 491 $$ = list; 492 } 493 | 494 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config 495 { 496 struct parse_events_state *parse_state = _parse_state; 497 struct parse_events_error *error = parse_state->error; 498 struct list_head *list; 499 int err; 500 501 list = alloc_list(); 502 ABORT_ON(!list); 503 err = parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4, 504 parse_state); 505 parse_events_terms__delete($4); 506 free($1); 507 free($3); 508 if (err) { 509 free_list_evsel(list); 510 YYABORT; 511 } 512 $$ = list; 513 } 514 | 515 PE_NAME_CACHE_TYPE opt_event_config 516 { 517 struct parse_events_state *parse_state = _parse_state; 518 struct parse_events_error *error = parse_state->error; 519 struct list_head *list; 520 int err; 521 522 list = alloc_list(); 523 ABORT_ON(!list); 524 err = parse_events_add_cache(list, &parse_state->idx, $1, NULL, NULL, error, $2, 525 parse_state); 526 parse_events_terms__delete($2); 527 free($1); 528 if (err) { 529 free_list_evsel(list); 530 YYABORT; 531 } 532 $$ = list; 533 } 534 535 event_legacy_mem: 536 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc 537 { 538 struct parse_events_state *parse_state = _parse_state; 539 struct list_head *list; 540 int err; 541 542 list = alloc_list(); 543 ABORT_ON(!list); 544 err = parse_events_add_breakpoint(list, &parse_state->idx, 545 $2, $6, $4); 546 free($6); 547 if (err) { 548 free(list); 549 YYABORT; 550 } 551 $$ = list; 552 } 553 | 554 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc 555 { 556 struct parse_events_state *parse_state = _parse_state; 557 struct list_head *list; 558 559 list = alloc_list(); 560 ABORT_ON(!list); 561 if (parse_events_add_breakpoint(list, &parse_state->idx, 562 $2, NULL, $4)) { 563 free(list); 564 YYABORT; 565 } 566 $$ = list; 567 } 568 | 569 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 570 { 571 struct parse_events_state *parse_state = _parse_state; 572 struct list_head *list; 573 int err; 574 575 list = alloc_list(); 576 ABORT_ON(!list); 577 err = parse_events_add_breakpoint(list, &parse_state->idx, 578 $2, $4, 0); 579 free($4); 580 if (err) { 581 free(list); 582 YYABORT; 583 } 584 $$ = list; 585 } 586 | 587 PE_PREFIX_MEM PE_VALUE sep_dc 588 { 589 struct parse_events_state *parse_state = _parse_state; 590 struct list_head *list; 591 592 list = alloc_list(); 593 ABORT_ON(!list); 594 if (parse_events_add_breakpoint(list, &parse_state->idx, 595 $2, NULL, 0)) { 596 free(list); 597 YYABORT; 598 } 599 $$ = list; 600 } 601 602 event_legacy_tracepoint: 603 tracepoint_name opt_event_config 604 { 605 struct parse_events_state *parse_state = _parse_state; 606 struct parse_events_error *error = parse_state->error; 607 struct list_head *list; 608 int err; 609 610 list = alloc_list(); 611 ABORT_ON(!list); 612 if (error) 613 error->idx = @1.first_column; 614 615 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event, 616 error, $2); 617 618 parse_events_terms__delete($2); 619 free($1.sys); 620 free($1.event); 621 if (err) { 622 free(list); 623 YYABORT; 624 } 625 $$ = list; 626 } 627 628 tracepoint_name: 629 PE_NAME '-' PE_NAME ':' PE_NAME 630 { 631 struct tracepoint_name tracepoint; 632 633 ABORT_ON(asprintf(&tracepoint.sys, "%s-%s", $1, $3) < 0); 634 tracepoint.event = $5; 635 free($1); 636 free($3); 637 $$ = tracepoint; 638 } 639 | 640 PE_NAME ':' PE_NAME 641 { 642 struct tracepoint_name tracepoint = {$1, $3}; 643 644 $$ = tracepoint; 645 } 646 647 event_legacy_numeric: 648 PE_VALUE ':' PE_VALUE opt_event_config 649 { 650 struct list_head *list; 651 int err; 652 653 list = alloc_list(); 654 ABORT_ON(!list); 655 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4); 656 parse_events_terms__delete($4); 657 if (err) { 658 free(list); 659 YYABORT; 660 } 661 $$ = list; 662 } 663 664 event_legacy_raw: 665 PE_RAW opt_event_config 666 { 667 struct list_head *list; 668 int err; 669 670 list = alloc_list(); 671 ABORT_ON(!list); 672 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2); 673 parse_events_terms__delete($2); 674 if (err) { 675 free(list); 676 YYABORT; 677 } 678 $$ = list; 679 } 680 681 event_bpf_file: 682 PE_BPF_OBJECT opt_event_config 683 { 684 struct parse_events_state *parse_state = _parse_state; 685 struct list_head *list; 686 int err; 687 688 list = alloc_list(); 689 ABORT_ON(!list); 690 err = parse_events_load_bpf(parse_state, list, $1, false, $2); 691 parse_events_terms__delete($2); 692 free($1); 693 if (err) { 694 free(list); 695 YYABORT; 696 } 697 $$ = list; 698 } 699 | 700 PE_BPF_SOURCE opt_event_config 701 { 702 struct list_head *list; 703 int err; 704 705 list = alloc_list(); 706 ABORT_ON(!list); 707 err = parse_events_load_bpf(_parse_state, list, $1, true, $2); 708 parse_events_terms__delete($2); 709 if (err) { 710 free(list); 711 YYABORT; 712 } 713 $$ = list; 714 } 715 716 opt_event_config: 717 '/' event_config '/' 718 { 719 $$ = $2; 720 } 721 | 722 '/' '/' 723 { 724 $$ = NULL; 725 } 726 | 727 { 728 $$ = NULL; 729 } 730 731 opt_pmu_config: 732 '/' event_config '/' 733 { 734 $$ = $2; 735 } 736 | 737 '/' '/' 738 { 739 $$ = NULL; 740 } 741 742 start_terms: event_config 743 { 744 struct parse_events_state *parse_state = _parse_state; 745 if (parse_state->terms) { 746 parse_events_terms__delete ($1); 747 YYABORT; 748 } 749 parse_state->terms = $1; 750 } 751 752 event_config: 753 event_config ',' event_term 754 { 755 struct list_head *head = $1; 756 struct parse_events_term *term = $3; 757 758 if (!head) { 759 parse_events_term__delete(term); 760 YYABORT; 761 } 762 list_add_tail(&term->list, head); 763 $$ = $1; 764 } 765 | 766 event_term 767 { 768 struct list_head *head = malloc(sizeof(*head)); 769 struct parse_events_term *term = $1; 770 771 ABORT_ON(!head); 772 INIT_LIST_HEAD(head); 773 list_add_tail(&term->list, head); 774 $$ = head; 775 } 776 777 event_term: 778 PE_RAW 779 { 780 struct parse_events_term *term; 781 782 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_CONFIG, 783 NULL, $1, false, &@1, NULL)); 784 $$ = term; 785 } 786 | 787 PE_NAME '=' PE_NAME 788 { 789 struct parse_events_term *term; 790 791 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 792 $1, $3, &@1, &@3)) { 793 free($1); 794 free($3); 795 YYABORT; 796 } 797 $$ = term; 798 } 799 | 800 PE_NAME '=' PE_VALUE 801 { 802 struct parse_events_term *term; 803 804 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 805 $1, $3, false, &@1, &@3)) { 806 free($1); 807 YYABORT; 808 } 809 $$ = term; 810 } 811 | 812 PE_NAME '=' PE_VALUE_SYM_HW 813 { 814 struct parse_events_term *term; 815 int config = $3 & 255; 816 817 if (parse_events_term__sym_hw(&term, $1, config)) { 818 free($1); 819 YYABORT; 820 } 821 $$ = term; 822 } 823 | 824 PE_NAME 825 { 826 struct parse_events_term *term; 827 828 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 829 $1, 1, true, &@1, NULL)) { 830 free($1); 831 YYABORT; 832 } 833 $$ = term; 834 } 835 | 836 PE_VALUE_SYM_HW 837 { 838 struct parse_events_term *term; 839 int config = $1 & 255; 840 841 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 842 $$ = term; 843 } 844 | 845 PE_TERM '=' PE_NAME 846 { 847 struct parse_events_term *term; 848 849 if (parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3)) { 850 free($3); 851 YYABORT; 852 } 853 $$ = term; 854 } 855 | 856 PE_TERM '=' PE_VALUE 857 { 858 struct parse_events_term *term; 859 860 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3)); 861 $$ = term; 862 } 863 | 864 PE_TERM 865 { 866 struct parse_events_term *term; 867 868 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL)); 869 $$ = term; 870 } 871 | 872 PE_NAME array '=' PE_NAME 873 { 874 struct parse_events_term *term; 875 876 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 877 $1, $4, &@1, &@4)) { 878 free($1); 879 free($4); 880 free($2.ranges); 881 YYABORT; 882 } 883 term->array = $2; 884 $$ = term; 885 } 886 | 887 PE_NAME array '=' PE_VALUE 888 { 889 struct parse_events_term *term; 890 891 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 892 $1, $4, false, &@1, &@4)) { 893 free($1); 894 free($2.ranges); 895 YYABORT; 896 } 897 term->array = $2; 898 $$ = term; 899 } 900 | 901 PE_DRV_CFG_TERM 902 { 903 struct parse_events_term *term; 904 char *config = strdup($1); 905 906 ABORT_ON(!config); 907 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, 908 config, $1, &@1, NULL)) { 909 free($1); 910 free(config); 911 YYABORT; 912 } 913 $$ = term; 914 } 915 916 array: 917 '[' array_terms ']' 918 { 919 $$ = $2; 920 } 921 | 922 PE_ARRAY_ALL 923 { 924 $$.nr_ranges = 0; 925 $$.ranges = NULL; 926 } 927 928 array_terms: 929 array_terms ',' array_term 930 { 931 struct parse_events_array new_array; 932 933 new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges; 934 new_array.ranges = realloc($1.ranges, 935 sizeof(new_array.ranges[0]) * 936 new_array.nr_ranges); 937 ABORT_ON(!new_array.ranges); 938 memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges, 939 $3.nr_ranges * sizeof(new_array.ranges[0])); 940 free($3.ranges); 941 $$ = new_array; 942 } 943 | 944 array_term 945 946 array_term: 947 PE_VALUE 948 { 949 struct parse_events_array array; 950 951 array.nr_ranges = 1; 952 array.ranges = malloc(sizeof(array.ranges[0])); 953 ABORT_ON(!array.ranges); 954 array.ranges[0].start = $1; 955 array.ranges[0].length = 1; 956 $$ = array; 957 } 958 | 959 PE_VALUE PE_ARRAY_RANGE PE_VALUE 960 { 961 struct parse_events_array array; 962 963 ABORT_ON($3 < $1); 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 = $3 - $1 + 1; 969 $$ = array; 970 } 971 972 sep_dc: ':' | 973 974 sep_slash_slash_dc: '/' '/' | ':' | 975 976 %% 977 978 void parse_events_error(YYLTYPE *loc, void *parse_state, 979 void *scanner __maybe_unused, 980 char const *msg __maybe_unused) 981 { 982 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 983 } 984