parse-events.y (18898B)
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 21void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg); 22 23#define ABORT_ON(val) \ 24do { \ 25 if (val) \ 26 YYABORT; \ 27} while (0) 28 29static 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 41static 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 52static 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 139start: 140PE_START_EVENTS start_events 141| 142PE_START_TERMS start_terms 143 144start_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 152groups: 153groups ',' 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| 163groups ',' 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| 173group 174| 175event 176 177group: 178group_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| 197group_def 198 199group_def: 200PE_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 219events: 220events ',' 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| 230event 231 232event: event_mod 233 234event_mod: 235event_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| 259event_name 260 261event_name: 262PE_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| 275event_def 276 277event_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 286event_pmu_name: 287PE_NAME | PE_PMU_EVENT_PRE 288 289event_pmu: 290event_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| 350PE_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| 362PE_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| 375PE_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| 388PE_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| 401PE_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| 419PE_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 438value_sym: 439PE_VALUE_SYM_HW 440| 441PE_VALUE_SYM_SW 442 443event_legacy_symbol: 444value_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| 462value_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| 474PE_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 484event_legacy_cache: 485PE_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| 507PE_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| 528PE_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 548event_legacy_mem: 549PE_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| 567PE_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| 582PE_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| 600PE_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 615event_legacy_tracepoint: 616tracepoint_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 641tracepoint_name: 642PE_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| 653PE_NAME ':' PE_NAME 654{ 655 struct tracepoint_name tracepoint = {$1, $3}; 656 657 $$ = tracepoint; 658} 659 660event_legacy_numeric: 661PE_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 677event_legacy_raw: 678PE_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 694event_bpf_file: 695PE_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| 713PE_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 729opt_event_config: 730'/' event_config '/' 731{ 732 $$ = $2; 733} 734| 735'/' '/' 736{ 737 $$ = NULL; 738} 739| 740{ 741 $$ = NULL; 742} 743 744opt_pmu_config: 745'/' event_config '/' 746{ 747 $$ = $2; 748} 749| 750'/' '/' 751{ 752 $$ = NULL; 753} 754 755start_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 765event_config: 766event_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| 779event_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 790event_term: 791PE_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| 800PE_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| 813PE_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| 825PE_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| 837PE_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| 849PE_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| 858PE_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| 869PE_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| 877PE_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| 885PE_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| 900PE_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| 914PE_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 929array: 930'[' array_terms ']' 931{ 932 $$ = $2; 933} 934| 935PE_ARRAY_ALL 936{ 937 $$.nr_ranges = 0; 938 $$.ranges = NULL; 939} 940 941array_terms: 942array_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| 957array_term 958 959array_term: 960PE_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| 972PE_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 985sep_dc: ':' | 986 987sep_slash_slash_dc: '/' '/' | ':' | 988 989%% 990 991void 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}