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