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