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 %destructor { free ($$); } <str> 93 %type <term> event_term 94 %destructor { parse_events_term__delete ($$); } <term> 95 %type <list_terms> event_config 96 %type <list_terms> opt_event_config 97 %type <list_terms> opt_pmu_config 98 %destructor { parse_events_terms__delete ($$); } <list_terms> 99 %type <list_evsel> event_pmu 100 %type <list_evsel> event_legacy_symbol 101 %type <list_evsel> event_legacy_cache 102 %type <list_evsel> event_legacy_mem 103 %type <list_evsel> event_legacy_tracepoint 104 %type <list_evsel> event_legacy_numeric 105 %type <list_evsel> event_legacy_raw 106 %type <list_evsel> event_bpf_file 107 %type <list_evsel> event_def 108 %type <list_evsel> event_mod 109 %type <list_evsel> event_name 110 %type <list_evsel> event 111 %type <list_evsel> events 112 %type <list_evsel> group_def 113 %type <list_evsel> group 114 %type <list_evsel> groups 115 %destructor { free_list_evsel ($$); } <list_evsel> 116 %type <tracepoint_name> tracepoint_name 117 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name> 118 %type <array> array 119 %type <array> array_term 120 %type <array> array_terms 121 %destructor { free ($$.ranges); } <array> 122 123 %union 124 { 125 char *str; 126 u64 num; 127 struct list_head *list_evsel; 128 struct list_head *list_terms; 129 struct parse_events_term *term; 130 struct tracepoint_name { 131 char *sys; 132 char *event; 133 } tracepoint_name; 134 struct parse_events_array array; 135 } 136 %% 137 138 start: 139 PE_START_EVENTS start_events 140 | 141 PE_START_TERMS start_terms 142 143 start_events: groups 144 { 145 struct parse_events_state *parse_state = _parse_state; 146 147 /* frees $1 */ 148 parse_events_update_lists($1, &parse_state->list); 149 } 150 151 groups: 152 groups ',' group 153 { 154 struct list_head *list = $1; 155 struct list_head *group = $3; 156 157 /* frees $3 */ 158 parse_events_update_lists(group, list); 159 $$ = list; 160 } 161 | 162 groups ',' event 163 { 164 struct list_head *list = $1; 165 struct list_head *event = $3; 166 167 /* frees $3 */ 168 parse_events_update_lists(event, list); 169 $$ = list; 170 } 171 | 172 group 173 | 174 event 175 176 group: 177 group_def ':' PE_MODIFIER_EVENT 178 { 179 struct list_head *list = $1; 180 int err; 181 182 err = parse_events__modifier_group(list, $3); 183 free($3); 184 if (err) { 185 free_list_evsel(list); 186 YYABORT; 187 } 188 $$ = list; 189 } 190 | 191 group_def 192 193 group_def: 194 PE_NAME '{' events '}' 195 { 196 struct list_head *list = $3; 197 198 inc_group_count(list, _parse_state); 199 parse_events__set_leader($1, list, _parse_state); 200 free($1); 201 $$ = list; 202 } 203 | 204 '{' events '}' 205 { 206 struct list_head *list = $2; 207 208 inc_group_count(list, _parse_state); 209 parse_events__set_leader(NULL, list, _parse_state); 210 $$ = list; 211 } 212 213 events: 214 events ',' event 215 { 216 struct list_head *event = $3; 217 struct list_head *list = $1; 218 219 /* frees $3 */ 220 parse_events_update_lists(event, list); 221 $$ = list; 222 } 223 | 224 event 225 226 event: event_mod 227 228 event_mod: 229 event_name PE_MODIFIER_EVENT 230 { 231 struct list_head *list = $1; 232 int err; 233 234 /* 235 * Apply modifier on all events added by single event definition 236 * (there could be more events added for multiple tracepoint 237 * definitions via '*?'. 238 */ 239 err = parse_events__modifier_event(list, $2, false); 240 free($2); 241 if (err) { 242 free_list_evsel(list); 243 YYABORT; 244 } 245 $$ = list; 246 } 247 | 248 event_name 249 250 event_name: 251 PE_EVENT_NAME event_def 252 { 253 int err; 254 255 err = parse_events_name($2, $1); 256 free($1); 257 if (err) { 258 free_list_evsel($2); 259 YYABORT; 260 } 261 $$ = $2; 262 } 263 | 264 event_def 265 266 event_def: event_pmu | 267 event_legacy_symbol | 268 event_legacy_cache sep_dc | 269 event_legacy_mem | 270 event_legacy_tracepoint sep_dc | 271 event_legacy_numeric sep_dc | 272 event_legacy_raw sep_dc | 273 event_bpf_file 274 275 event_pmu: 276 PE_NAME opt_pmu_config 277 { 278 struct parse_events_state *parse_state = _parse_state; 279 struct parse_events_error *error = parse_state->error; 280 struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL; 281 char *pattern = NULL; 282 283 #define CLEANUP_YYABORT \ 284 do { \ 285 parse_events_terms__delete($2); \ 286 parse_events_terms__delete(orig_terms); \ 287 free(list); \ 288 free($1); \ 289 free(pattern); \ 290 YYABORT; \ 291 } while(0) 292 293 if (parse_events_copy_term_list($2, &orig_terms)) 294 CLEANUP_YYABORT; 295 296 if (error) 297 error->idx = @1.first_column; 298 299 list = alloc_list(); 300 if (!list) 301 CLEANUP_YYABORT; 302 if (parse_events_add_pmu(_parse_state, list, $1, $2, false, false)) { 303 struct perf_pmu *pmu = NULL; 304 int ok = 0; 305 306 if (asprintf(&pattern, "%s*", $1) < 0) 307 CLEANUP_YYABORT; 308 309 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 310 char *name = pmu->name; 311 312 if (!strncmp(name, "uncore_", 7) && 313 strncmp($1, "uncore_", 7)) 314 name += 7; 315 if (!fnmatch(pattern, name, 0)) { 316 if (parse_events_copy_term_list(orig_terms, &terms)) 317 CLEANUP_YYABORT; 318 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false)) 319 ok++; 320 parse_events_terms__delete(terms); 321 } 322 } 323 324 if (!ok) 325 CLEANUP_YYABORT; 326 } 327 parse_events_terms__delete($2); 328 parse_events_terms__delete(orig_terms); 329 free(pattern); 330 free($1); 331 $$ = list; 332 #undef CLEANUP_YYABORT 333 } 334 | 335 PE_KERNEL_PMU_EVENT sep_dc 336 { 337 struct list_head *list; 338 int err; 339 340 err = parse_events_multi_pmu_add(_parse_state, $1, &list); 341 free($1); 342 if (err < 0) 343 YYABORT; 344 $$ = list; 345 } 346 | 347 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc 348 { 349 struct list_head *list; 350 char pmu_name[128]; 351 352 snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3); 353 free($1); 354 free($3); 355 if (parse_events_multi_pmu_add(_parse_state, pmu_name, &list) < 0) 356 YYABORT; 357 $$ = list; 358 } 359 | 360 PE_PMU_EVENT_FAKE sep_dc 361 { 362 struct list_head *list; 363 int err; 364 365 list = alloc_list(); 366 if (!list) 367 YYABORT; 368 369 err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, false); 370 free($1); 371 if (err < 0) { 372 free(list); 373 YYABORT; 374 } 375 $$ = list; 376 } 377 | 378 PE_PMU_EVENT_FAKE opt_pmu_config 379 { 380 struct list_head *list; 381 int err; 382 383 list = alloc_list(); 384 if (!list) 385 YYABORT; 386 387 err = parse_events_add_pmu(_parse_state, list, $1, $2, false, false); 388 free($1); 389 parse_events_terms__delete($2); 390 if (err < 0) { 391 free(list); 392 YYABORT; 393 } 394 $$ = list; 395 } 396 397 value_sym: 398 PE_VALUE_SYM_HW 399 | 400 PE_VALUE_SYM_SW 401 402 event_legacy_symbol: 403 value_sym '/' event_config '/' 404 { 405 struct list_head *list; 406 int type = $1 >> 16; 407 int config = $1 & 255; 408 int err; 409 410 list = alloc_list(); 411 ABORT_ON(!list); 412 err = parse_events_add_numeric(_parse_state, list, type, config, $3); 413 parse_events_terms__delete($3); 414 if (err) { 415 free_list_evsel(list); 416 YYABORT; 417 } 418 $$ = list; 419 } 420 | 421 value_sym sep_slash_slash_dc 422 { 423 struct list_head *list; 424 int type = $1 >> 16; 425 int config = $1 & 255; 426 427 list = alloc_list(); 428 ABORT_ON(!list); 429 ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, NULL)); 430 $$ = list; 431 } 432 | 433 PE_VALUE_SYM_TOOL sep_slash_slash_dc 434 { 435 struct list_head *list; 436 437 list = alloc_list(); 438 ABORT_ON(!list); 439 ABORT_ON(parse_events_add_tool(_parse_state, list, $1)); 440 $$ = list; 441 } 442 443 event_legacy_cache: 444 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config 445 { 446 struct parse_events_state *parse_state = _parse_state; 447 struct parse_events_error *error = parse_state->error; 448 struct list_head *list; 449 int err; 450 451 list = alloc_list(); 452 ABORT_ON(!list); 453 err = parse_events_add_cache(list, &parse_state->idx, $1, $3, $5, error, $6); 454 parse_events_terms__delete($6); 455 free($1); 456 free($3); 457 free($5); 458 if (err) { 459 free_list_evsel(list); 460 YYABORT; 461 } 462 $$ = list; 463 } 464 | 465 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config 466 { 467 struct parse_events_state *parse_state = _parse_state; 468 struct parse_events_error *error = parse_state->error; 469 struct list_head *list; 470 int err; 471 472 list = alloc_list(); 473 ABORT_ON(!list); 474 err = parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4); 475 parse_events_terms__delete($4); 476 free($1); 477 free($3); 478 if (err) { 479 free_list_evsel(list); 480 YYABORT; 481 } 482 $$ = list; 483 } 484 | 485 PE_NAME_CACHE_TYPE 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, NULL, NULL, error, $2); 495 parse_events_terms__delete($2); 496 free($1); 497 if (err) { 498 free_list_evsel(list); 499 YYABORT; 500 } 501 $$ = list; 502 } 503 504 event_legacy_mem: 505 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc 506 { 507 struct parse_events_state *parse_state = _parse_state; 508 struct list_head *list; 509 int err; 510 511 list = alloc_list(); 512 ABORT_ON(!list); 513 err = parse_events_add_breakpoint(list, &parse_state->idx, 514 (void *) $2, $6, $4); 515 free($6); 516 if (err) { 517 free(list); 518 YYABORT; 519 } 520 $$ = list; 521 } 522 | 523 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc 524 { 525 struct parse_events_state *parse_state = _parse_state; 526 struct list_head *list; 527 528 list = alloc_list(); 529 ABORT_ON(!list); 530 if (parse_events_add_breakpoint(list, &parse_state->idx, 531 (void *) $2, NULL, $4)) { 532 free(list); 533 YYABORT; 534 } 535 $$ = list; 536 } 537 | 538 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 539 { 540 struct parse_events_state *parse_state = _parse_state; 541 struct list_head *list; 542 int err; 543 544 list = alloc_list(); 545 ABORT_ON(!list); 546 err = parse_events_add_breakpoint(list, &parse_state->idx, 547 (void *) $2, $4, 0); 548 free($4); 549 if (err) { 550 free(list); 551 YYABORT; 552 } 553 $$ = list; 554 } 555 | 556 PE_PREFIX_MEM PE_VALUE sep_dc 557 { 558 struct parse_events_state *parse_state = _parse_state; 559 struct list_head *list; 560 561 list = alloc_list(); 562 ABORT_ON(!list); 563 if (parse_events_add_breakpoint(list, &parse_state->idx, 564 (void *) $2, NULL, 0)) { 565 free(list); 566 YYABORT; 567 } 568 $$ = list; 569 } 570 571 event_legacy_tracepoint: 572 tracepoint_name opt_event_config 573 { 574 struct parse_events_state *parse_state = _parse_state; 575 struct parse_events_error *error = parse_state->error; 576 struct list_head *list; 577 int err; 578 579 list = alloc_list(); 580 ABORT_ON(!list); 581 if (error) 582 error->idx = @1.first_column; 583 584 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event, 585 error, $2); 586 587 parse_events_terms__delete($2); 588 free($1.sys); 589 free($1.event); 590 if (err) { 591 free(list); 592 YYABORT; 593 } 594 $$ = list; 595 } 596 597 tracepoint_name: 598 PE_NAME '-' PE_NAME ':' PE_NAME 599 { 600 struct tracepoint_name tracepoint; 601 602 ABORT_ON(asprintf(&tracepoint.sys, "%s-%s", $1, $3) < 0); 603 tracepoint.event = $5; 604 free($1); 605 free($3); 606 $$ = tracepoint; 607 } 608 | 609 PE_NAME ':' PE_NAME 610 { 611 struct tracepoint_name tracepoint = {$1, $3}; 612 613 $$ = tracepoint; 614 } 615 616 event_legacy_numeric: 617 PE_VALUE ':' PE_VALUE opt_event_config 618 { 619 struct list_head *list; 620 int err; 621 622 list = alloc_list(); 623 ABORT_ON(!list); 624 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4); 625 parse_events_terms__delete($4); 626 if (err) { 627 free(list); 628 YYABORT; 629 } 630 $$ = list; 631 } 632 633 event_legacy_raw: 634 PE_RAW opt_event_config 635 { 636 struct list_head *list; 637 int err; 638 639 list = alloc_list(); 640 ABORT_ON(!list); 641 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2); 642 parse_events_terms__delete($2); 643 if (err) { 644 free(list); 645 YYABORT; 646 } 647 $$ = list; 648 } 649 650 event_bpf_file: 651 PE_BPF_OBJECT opt_event_config 652 { 653 struct parse_events_state *parse_state = _parse_state; 654 struct list_head *list; 655 int err; 656 657 list = alloc_list(); 658 ABORT_ON(!list); 659 err = parse_events_load_bpf(parse_state, list, $1, false, $2); 660 parse_events_terms__delete($2); 661 free($1); 662 if (err) { 663 free(list); 664 YYABORT; 665 } 666 $$ = list; 667 } 668 | 669 PE_BPF_SOURCE opt_event_config 670 { 671 struct list_head *list; 672 int err; 673 674 list = alloc_list(); 675 ABORT_ON(!list); 676 err = parse_events_load_bpf(_parse_state, list, $1, true, $2); 677 parse_events_terms__delete($2); 678 if (err) { 679 free(list); 680 YYABORT; 681 } 682 $$ = list; 683 } 684 685 opt_event_config: 686 '/' event_config '/' 687 { 688 $$ = $2; 689 } 690 | 691 '/' '/' 692 { 693 $$ = NULL; 694 } 695 | 696 { 697 $$ = NULL; 698 } 699 700 opt_pmu_config: 701 '/' event_config '/' 702 { 703 $$ = $2; 704 } 705 | 706 '/' '/' 707 { 708 $$ = NULL; 709 } 710 711 start_terms: event_config 712 { 713 struct parse_events_state *parse_state = _parse_state; 714 if (parse_state->terms) { 715 parse_events_terms__delete ($1); 716 YYABORT; 717 } 718 parse_state->terms = $1; 719 } 720 721 event_config: 722 event_config ',' event_term 723 { 724 struct list_head *head = $1; 725 struct parse_events_term *term = $3; 726 727 if (!head) { 728 parse_events_term__delete(term); 729 YYABORT; 730 } 731 list_add_tail(&term->list, head); 732 $$ = $1; 733 } 734 | 735 event_term 736 { 737 struct list_head *head = malloc(sizeof(*head)); 738 struct parse_events_term *term = $1; 739 740 ABORT_ON(!head); 741 INIT_LIST_HEAD(head); 742 list_add_tail(&term->list, head); 743 $$ = head; 744 } 745 746 event_term: 747 PE_RAW 748 { 749 struct parse_events_term *term; 750 751 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_CONFIG, 752 NULL, $1, false, &@1, NULL)); 753 $$ = term; 754 } 755 | 756 PE_NAME '=' PE_NAME 757 { 758 struct parse_events_term *term; 759 760 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 761 $1, $3, &@1, &@3)) { 762 free($1); 763 free($3); 764 YYABORT; 765 } 766 $$ = term; 767 } 768 | 769 PE_NAME '=' PE_VALUE 770 { 771 struct parse_events_term *term; 772 773 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 774 $1, $3, false, &@1, &@3)) { 775 free($1); 776 YYABORT; 777 } 778 $$ = term; 779 } 780 | 781 PE_NAME '=' PE_VALUE_SYM_HW 782 { 783 struct parse_events_term *term; 784 int config = $3 & 255; 785 786 if (parse_events_term__sym_hw(&term, $1, config)) { 787 free($1); 788 YYABORT; 789 } 790 $$ = term; 791 } 792 | 793 PE_NAME 794 { 795 struct parse_events_term *term; 796 797 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 798 $1, 1, true, &@1, NULL)) { 799 free($1); 800 YYABORT; 801 } 802 $$ = term; 803 } 804 | 805 PE_VALUE_SYM_HW 806 { 807 struct parse_events_term *term; 808 int config = $1 & 255; 809 810 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 811 $$ = term; 812 } 813 | 814 PE_TERM '=' PE_NAME 815 { 816 struct parse_events_term *term; 817 818 if (parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3)) { 819 free($3); 820 YYABORT; 821 } 822 $$ = term; 823 } 824 | 825 PE_TERM '=' PE_VALUE 826 { 827 struct parse_events_term *term; 828 829 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3)); 830 $$ = term; 831 } 832 | 833 PE_TERM 834 { 835 struct parse_events_term *term; 836 837 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL)); 838 $$ = term; 839 } 840 | 841 PE_NAME array '=' PE_NAME 842 { 843 struct parse_events_term *term; 844 845 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 846 $1, $4, &@1, &@4)) { 847 free($1); 848 free($4); 849 free($2.ranges); 850 YYABORT; 851 } 852 term->array = $2; 853 $$ = term; 854 } 855 | 856 PE_NAME array '=' PE_VALUE 857 { 858 struct parse_events_term *term; 859 860 if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 861 $1, $4, false, &@1, &@4)) { 862 free($1); 863 free($2.ranges); 864 YYABORT; 865 } 866 term->array = $2; 867 $$ = term; 868 } 869 | 870 PE_DRV_CFG_TERM 871 { 872 struct parse_events_term *term; 873 char *config = strdup($1); 874 875 ABORT_ON(!config); 876 if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, 877 config, $1, &@1, NULL)) { 878 free($1); 879 free(config); 880 YYABORT; 881 } 882 $$ = term; 883 } 884 885 array: 886 '[' array_terms ']' 887 { 888 $$ = $2; 889 } 890 | 891 PE_ARRAY_ALL 892 { 893 $$.nr_ranges = 0; 894 $$.ranges = NULL; 895 } 896 897 array_terms: 898 array_terms ',' array_term 899 { 900 struct parse_events_array new_array; 901 902 new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges; 903 new_array.ranges = realloc($1.ranges, 904 sizeof(new_array.ranges[0]) * 905 new_array.nr_ranges); 906 ABORT_ON(!new_array.ranges); 907 memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges, 908 $3.nr_ranges * sizeof(new_array.ranges[0])); 909 free($3.ranges); 910 $$ = new_array; 911 } 912 | 913 array_term 914 915 array_term: 916 PE_VALUE 917 { 918 struct parse_events_array array; 919 920 array.nr_ranges = 1; 921 array.ranges = malloc(sizeof(array.ranges[0])); 922 ABORT_ON(!array.ranges); 923 array.ranges[0].start = $1; 924 array.ranges[0].length = 1; 925 $$ = array; 926 } 927 | 928 PE_VALUE PE_ARRAY_RANGE PE_VALUE 929 { 930 struct parse_events_array array; 931 932 ABORT_ON($3 < $1); 933 array.nr_ranges = 1; 934 array.ranges = malloc(sizeof(array.ranges[0])); 935 ABORT_ON(!array.ranges); 936 array.ranges[0].start = $1; 937 array.ranges[0].length = $3 - $1 + 1; 938 $$ = array; 939 } 940 941 sep_dc: ':' | 942 943 sep_slash_slash_dc: '/' '/' | ':' | 944 945 %% 946 947 void parse_events_error(YYLTYPE *loc, void *parse_state, 948 void *scanner __maybe_unused, 949 char const *msg __maybe_unused) 950 { 951 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 952 } 953