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