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