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