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 <errno.h> 12 #include <fnmatch.h> 13 #include <stdio.h> 14 #include <linux/compiler.h> 15 #include <linux/types.h> 16 #include <linux/zalloc.h> 17 #include "pmu.h" 18 #include "pmus.h" 19 #include "evsel.h" 20 #include "parse-events.h" 21 #include "parse-events-bison.h" 22 23 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg); 24 25 #define PE_ABORT(val) \ 26 do { \ 27 if (val == -ENOMEM) \ 28 YYNOMEM; \ 29 YYABORT; \ 30 } while (0) 31 32 static struct list_head* alloc_list(void) 33 { 34 struct list_head *list; 35 36 list = malloc(sizeof(*list)); 37 if (!list) 38 return NULL; 39 40 INIT_LIST_HEAD(list); 41 return list; 42 } 43 44 static void free_list_evsel(struct list_head* list_evsel) 45 { 46 struct evsel *evsel, *tmp; 47 48 list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) { 49 list_del_init(&evsel->core.node); 50 evsel__delete(evsel); 51 } 52 free(list_evsel); 53 } 54 55 %} 56 57 %token PE_START_EVENTS PE_START_TERMS 58 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM 59 %token PE_VALUE_SYM_TOOL 60 %token PE_EVENT_NAME 61 %token PE_RAW PE_NAME 62 %token PE_BPF_OBJECT PE_BPF_SOURCE 63 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH 64 %token PE_LEGACY_CACHE 65 %token PE_PREFIX_MEM 66 %token PE_ERROR 67 %token PE_ARRAY_ALL PE_ARRAY_RANGE 68 %token PE_DRV_CFG_TERM 69 %token PE_TERM_HW 70 %type <num> PE_VALUE 71 %type <num> PE_VALUE_SYM_HW 72 %type <num> PE_VALUE_SYM_SW 73 %type <num> PE_VALUE_SYM_TOOL 74 %type <num> PE_TERM 75 %type <num> value_sym 76 %type <str> PE_RAW 77 %type <str> PE_NAME 78 %type <str> PE_BPF_OBJECT 79 %type <str> PE_BPF_SOURCE 80 %type <str> PE_LEGACY_CACHE 81 %type <str> PE_MODIFIER_EVENT 82 %type <str> PE_MODIFIER_BP 83 %type <str> PE_EVENT_NAME 84 %type <str> PE_DRV_CFG_TERM 85 %type <str> name_or_raw name_or_legacy 86 %destructor { free ($$); } <str> 87 %type <term> event_term 88 %destructor { parse_events_term__delete ($$); } <term> 89 %type <list_terms> event_config 90 %type <list_terms> opt_event_config 91 %type <list_terms> opt_pmu_config 92 %destructor { parse_events_terms__delete ($$); } <list_terms> 93 %type <list_evsel> event_pmu 94 %type <list_evsel> event_legacy_symbol 95 %type <list_evsel> event_legacy_cache 96 %type <list_evsel> event_legacy_mem 97 %type <list_evsel> event_legacy_tracepoint 98 %type <list_evsel> event_legacy_numeric 99 %type <list_evsel> event_legacy_raw 100 %type <list_evsel> event_bpf_file 101 %type <list_evsel> event_def 102 %type <list_evsel> event_mod 103 %type <list_evsel> event_name 104 %type <list_evsel> event 105 %type <list_evsel> events 106 %type <list_evsel> group_def 107 %type <list_evsel> group 108 %type <list_evsel> groups 109 %destructor { free_list_evsel ($$); } <list_evsel> 110 %type <tracepoint_name> tracepoint_name 111 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name> 112 %type <array> array 113 %type <array> array_term 114 %type <array> array_terms 115 %destructor { free ($$.ranges); } <array> 116 %type <hardware_term> PE_TERM_HW 117 %destructor { free ($$.str); } <hardware_term> 118 119 %union 120 { 121 char *str; 122 u64 num; 123 struct list_head *list_evsel; 124 struct list_head *list_terms; 125 struct parse_events_term *term; 126 struct tracepoint_name { 127 char *sys; 128 char *event; 129 } tracepoint_name; 130 struct parse_events_array array; 131 struct hardware_term { 132 char *str; 133 u64 num; 134 } hardware_term; 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 struct parse_events_state *parse_state = _parse_state; 186 struct parse_events_error *error = parse_state->error; 187 188 parse_events_error__handle(error, @3.first_column, 189 strdup("Bad modifier"), NULL); 190 free_list_evsel(list); 191 YYABORT; 192 } 193 $$ = list; 194 } 195 | 196 group_def 197 198 group_def: 199 PE_NAME '{' events '}' 200 { 201 struct list_head *list = $3; 202 203 /* Takes ownership of $1. */ 204 parse_events__set_leader($1, list); 205 $$ = list; 206 } 207 | 208 '{' events '}' 209 { 210 struct list_head *list = $2; 211 212 parse_events__set_leader(NULL, list); 213 $$ = list; 214 } 215 216 events: 217 events ',' event 218 { 219 struct list_head *event = $3; 220 struct list_head *list = $1; 221 222 /* frees $3 */ 223 parse_events_update_lists(event, list); 224 $$ = list; 225 } 226 | 227 event 228 229 event: event_mod 230 231 event_mod: 232 event_name PE_MODIFIER_EVENT 233 { 234 struct list_head *list = $1; 235 int err; 236 237 /* 238 * Apply modifier on all events added by single event definition 239 * (there could be more events added for multiple tracepoint 240 * definitions via '*?'. 241 */ 242 err = parse_events__modifier_event(list, $2, false); 243 free($2); 244 if (err) { 245 struct parse_events_state *parse_state = _parse_state; 246 struct parse_events_error *error = parse_state->error; 247 248 parse_events_error__handle(error, @2.first_column, 249 strdup("Bad modifier"), NULL); 250 free_list_evsel(list); 251 YYABORT; 252 } 253 $$ = list; 254 } 255 | 256 event_name 257 258 event_name: 259 PE_EVENT_NAME event_def 260 { 261 int err; 262 263 err = parse_events_name($2, $1); 264 free($1); 265 if (err) { 266 free_list_evsel($2); 267 YYNOMEM; 268 } 269 $$ = $2; 270 } 271 | 272 event_def 273 274 event_def: event_pmu | 275 event_legacy_symbol | 276 event_legacy_cache sep_dc | 277 event_legacy_mem sep_dc | 278 event_legacy_tracepoint sep_dc | 279 event_legacy_numeric sep_dc | 280 event_legacy_raw sep_dc | 281 event_bpf_file 282 283 event_pmu: 284 PE_NAME opt_pmu_config 285 { 286 struct parse_events_state *parse_state = _parse_state; 287 struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL; 288 char *pattern = NULL; 289 290 #define CLEANUP \ 291 do { \ 292 parse_events_terms__delete($2); \ 293 parse_events_terms__delete(orig_terms); \ 294 free(list); \ 295 free($1); \ 296 free(pattern); \ 297 } while(0) 298 299 if (parse_events_copy_term_list($2, &orig_terms)) { 300 CLEANUP; 301 YYNOMEM; 302 } 303 304 list = alloc_list(); 305 if (!list) { 306 CLEANUP; 307 YYNOMEM; 308 } 309 /* Attempt to add to list assuming $1 is a PMU name. */ 310 if (parse_events_add_pmu(parse_state, list, $1, $2, /*auto_merge_stats=*/false, &@1)) { 311 struct perf_pmu *pmu = NULL; 312 int ok = 0; 313 314 /* Failure to add, try wildcard expansion of $1 as a PMU name. */ 315 if (asprintf(&pattern, "%s*", $1) < 0) { 316 CLEANUP; 317 YYNOMEM; 318 } 319 320 while ((pmu = perf_pmus__scan(pmu)) != NULL) { 321 char *name = pmu->name; 322 323 if (parse_events__filter_pmu(parse_state, pmu)) 324 continue; 325 326 if (!strncmp(name, "uncore_", 7) && 327 strncmp($1, "uncore_", 7)) 328 name += 7; 329 if (!perf_pmu__match(pattern, name, $1) || 330 !perf_pmu__match(pattern, pmu->alias_name, $1)) { 331 bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu); 332 333 if (parse_events_copy_term_list(orig_terms, &terms)) { 334 CLEANUP; 335 YYNOMEM; 336 } 337 if (!parse_events_add_pmu(parse_state, list, pmu->name, terms, 338 auto_merge_stats, &@1)) { 339 ok++; 340 parse_state->wild_card_pmus = true; 341 } 342 parse_events_terms__delete(terms); 343 } 344 } 345 346 if (!ok) { 347 /* Failure to add, assume $1 is an event name. */ 348 zfree(&list); 349 ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list, &@1); 350 $2 = NULL; 351 } 352 if (!ok) { 353 struct parse_events_error *error = parse_state->error; 354 char *help; 355 356 if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0) 357 help = NULL; 358 parse_events_error__handle(error, @1.first_column, 359 strdup("Bad event or PMU"), 360 help); 361 CLEANUP; 362 YYABORT; 363 } 364 } 365 $$ = list; 366 list = NULL; 367 CLEANUP; 368 #undef CLEANUP 369 } 370 | 371 PE_NAME sep_dc 372 { 373 struct list_head *list; 374 int err; 375 376 err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1); 377 if (err < 0) { 378 struct parse_events_state *parse_state = _parse_state; 379 struct parse_events_error *error = parse_state->error; 380 char *help; 381 382 if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0) 383 help = NULL; 384 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help); 385 free($1); 386 PE_ABORT(err); 387 } 388 free($1); 389 $$ = list; 390 } 391 392 value_sym: 393 PE_VALUE_SYM_HW 394 | 395 PE_VALUE_SYM_SW 396 397 event_legacy_symbol: 398 value_sym '/' event_config '/' 399 { 400 struct list_head *list; 401 int type = $1 >> 16; 402 int config = $1 & 255; 403 int err; 404 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 405 406 list = alloc_list(); 407 if (!list) 408 YYNOMEM; 409 err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard); 410 parse_events_terms__delete($3); 411 if (err) { 412 free_list_evsel(list); 413 PE_ABORT(err); 414 } 415 $$ = list; 416 } 417 | 418 value_sym sep_slash_slash_dc 419 { 420 struct list_head *list; 421 int type = $1 >> 16; 422 int config = $1 & 255; 423 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 424 int err; 425 426 list = alloc_list(); 427 if (!list) 428 YYNOMEM; 429 err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard); 430 if (err) 431 PE_ABORT(err); 432 $$ = list; 433 } 434 | 435 PE_VALUE_SYM_TOOL sep_slash_slash_dc 436 { 437 struct list_head *list; 438 int err; 439 440 list = alloc_list(); 441 if (!list) 442 YYNOMEM; 443 err = parse_events_add_tool(_parse_state, list, $1); 444 if (err) 445 YYNOMEM; 446 $$ = list; 447 } 448 449 event_legacy_cache: 450 PE_LEGACY_CACHE opt_event_config 451 { 452 struct parse_events_state *parse_state = _parse_state; 453 struct list_head *list; 454 int err; 455 456 list = alloc_list(); 457 if (!list) 458 YYNOMEM; 459 460 err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2); 461 462 parse_events_terms__delete($2); 463 free($1); 464 if (err) { 465 free_list_evsel(list); 466 PE_ABORT(err); 467 } 468 $$ = list; 469 } 470 471 event_legacy_mem: 472 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 473 { 474 struct list_head *list; 475 int err; 476 477 list = alloc_list(); 478 if (!list) 479 YYNOMEM; 480 481 err = parse_events_add_breakpoint(_parse_state, list, 482 $2, $6, $4, $7); 483 parse_events_terms__delete($7); 484 free($6); 485 if (err) { 486 free(list); 487 PE_ABORT(err); 488 } 489 $$ = list; 490 } 491 | 492 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config 493 { 494 struct list_head *list; 495 int err; 496 497 list = alloc_list(); 498 if (!list) 499 YYNOMEM; 500 501 err = parse_events_add_breakpoint(_parse_state, list, 502 $2, NULL, $4, $5); 503 parse_events_terms__delete($5); 504 if (err) { 505 free(list); 506 PE_ABORT(err); 507 } 508 $$ = list; 509 } 510 | 511 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 512 { 513 struct list_head *list; 514 int err; 515 516 list = alloc_list(); 517 if (!list) 518 YYNOMEM; 519 520 err = parse_events_add_breakpoint(_parse_state, list, 521 $2, $4, 0, $5); 522 parse_events_terms__delete($5); 523 free($4); 524 if (err) { 525 free(list); 526 PE_ABORT(err); 527 } 528 $$ = list; 529 } 530 | 531 PE_PREFIX_MEM PE_VALUE opt_event_config 532 { 533 struct list_head *list; 534 int err; 535 536 list = alloc_list(); 537 if (!list) 538 YYNOMEM; 539 err = parse_events_add_breakpoint(_parse_state, list, 540 $2, NULL, 0, $3); 541 parse_events_terms__delete($3); 542 if (err) { 543 free(list); 544 PE_ABORT(err); 545 } 546 $$ = list; 547 } 548 549 event_legacy_tracepoint: 550 tracepoint_name opt_event_config 551 { 552 struct parse_events_state *parse_state = _parse_state; 553 struct parse_events_error *error = parse_state->error; 554 struct list_head *list; 555 int err; 556 557 list = alloc_list(); 558 if (!list) 559 YYNOMEM; 560 if (error) 561 error->idx = @1.first_column; 562 563 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event, 564 error, $2, &@1); 565 566 parse_events_terms__delete($2); 567 free($1.sys); 568 free($1.event); 569 if (err) { 570 free(list); 571 PE_ABORT(err); 572 } 573 $$ = list; 574 } 575 576 tracepoint_name: 577 PE_NAME ':' PE_NAME 578 { 579 struct tracepoint_name tracepoint = {$1, $3}; 580 581 $$ = tracepoint; 582 } 583 584 event_legacy_numeric: 585 PE_VALUE ':' PE_VALUE opt_event_config 586 { 587 struct list_head *list; 588 int err; 589 590 list = alloc_list(); 591 if (!list) 592 YYNOMEM; 593 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4, 594 /*wildcard=*/false); 595 parse_events_terms__delete($4); 596 if (err) { 597 free(list); 598 PE_ABORT(err); 599 } 600 $$ = list; 601 } 602 603 event_legacy_raw: 604 PE_RAW opt_event_config 605 { 606 struct list_head *list; 607 int err; 608 u64 num; 609 610 list = alloc_list(); 611 if (!list) 612 YYNOMEM; 613 errno = 0; 614 num = strtoull($1 + 1, NULL, 16); 615 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */ 616 if (errno) 617 YYABORT; 618 free($1); 619 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2, 620 /*wildcard=*/false); 621 parse_events_terms__delete($2); 622 if (err) { 623 free(list); 624 PE_ABORT(err); 625 } 626 $$ = list; 627 } 628 629 event_bpf_file: 630 PE_BPF_OBJECT opt_event_config 631 { 632 struct parse_events_state *parse_state = _parse_state; 633 struct list_head *list; 634 int err; 635 636 list = alloc_list(); 637 if (!list) 638 YYNOMEM; 639 err = parse_events_load_bpf(parse_state, list, $1, false, $2, &@1); 640 parse_events_terms__delete($2); 641 free($1); 642 if (err) { 643 free(list); 644 PE_ABORT(err); 645 } 646 $$ = list; 647 } 648 | 649 PE_BPF_SOURCE opt_event_config 650 { 651 struct list_head *list; 652 int err; 653 654 list = alloc_list(); 655 if (!list) 656 YYNOMEM; 657 err = parse_events_load_bpf(_parse_state, list, $1, true, $2, &@1); 658 parse_events_terms__delete($2); 659 if (err) { 660 free(list); 661 PE_ABORT(err); 662 } 663 $$ = list; 664 } 665 666 opt_event_config: 667 '/' event_config '/' 668 { 669 $$ = $2; 670 } 671 | 672 '/' '/' 673 { 674 $$ = NULL; 675 } 676 | 677 { 678 $$ = NULL; 679 } 680 681 opt_pmu_config: 682 '/' event_config '/' 683 { 684 $$ = $2; 685 } 686 | 687 '/' '/' 688 { 689 $$ = NULL; 690 } 691 692 start_terms: event_config 693 { 694 struct parse_events_state *parse_state = _parse_state; 695 if (parse_state->terms) { 696 parse_events_terms__delete ($1); 697 YYABORT; 698 } 699 parse_state->terms = $1; 700 } 701 702 event_config: 703 event_config ',' event_term 704 { 705 struct list_head *head = $1; 706 struct parse_events_term *term = $3; 707 708 if (!head) { 709 parse_events_term__delete(term); 710 YYABORT; 711 } 712 list_add_tail(&term->list, head); 713 $$ = $1; 714 } 715 | 716 event_term 717 { 718 struct list_head *head = malloc(sizeof(*head)); 719 struct parse_events_term *term = $1; 720 721 if (!head) 722 YYNOMEM; 723 INIT_LIST_HEAD(head); 724 list_add_tail(&term->list, head); 725 $$ = head; 726 } 727 728 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE 729 730 name_or_legacy: PE_NAME | PE_LEGACY_CACHE 731 732 event_term: 733 PE_RAW 734 { 735 struct parse_events_term *term; 736 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW, 737 strdup("raw"), $1, &@1, &@1); 738 739 if (err) { 740 free($1); 741 PE_ABORT(err); 742 } 743 $$ = term; 744 } 745 | 746 name_or_raw '=' name_or_legacy 747 { 748 struct parse_events_term *term; 749 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3); 750 751 if (err) { 752 free($1); 753 free($3); 754 PE_ABORT(err); 755 } 756 $$ = term; 757 } 758 | 759 name_or_raw '=' PE_VALUE 760 { 761 struct parse_events_term *term; 762 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 763 $1, $3, false, &@1, &@3); 764 765 if (err) { 766 free($1); 767 PE_ABORT(err); 768 } 769 $$ = term; 770 } 771 | 772 name_or_raw '=' PE_TERM_HW 773 { 774 struct parse_events_term *term; 775 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 776 $1, $3.str, &@1, &@3); 777 778 if (err) { 779 free($1); 780 free($3.str); 781 PE_ABORT(err); 782 } 783 $$ = term; 784 } 785 | 786 PE_LEGACY_CACHE 787 { 788 struct parse_events_term *term; 789 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, 790 $1, 1, true, &@1, NULL); 791 792 if (err) { 793 free($1); 794 PE_ABORT(err); 795 } 796 $$ = term; 797 } 798 | 799 PE_NAME 800 { 801 struct parse_events_term *term; 802 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 803 $1, 1, true, &@1, NULL); 804 805 if (err) { 806 free($1); 807 PE_ABORT(err); 808 } 809 $$ = term; 810 } 811 | 812 PE_TERM_HW 813 { 814 struct parse_events_term *term; 815 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE, 816 $1.str, $1.num & 255, false, &@1, NULL); 817 818 if (err) { 819 free($1.str); 820 PE_ABORT(err); 821 } 822 $$ = term; 823 } 824 | 825 PE_TERM '=' name_or_legacy 826 { 827 struct parse_events_term *term; 828 int err = parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3); 829 830 if (err) { 831 free($3); 832 PE_ABORT(err); 833 } 834 $$ = term; 835 } 836 | 837 PE_TERM '=' PE_TERM_HW 838 { 839 struct parse_events_term *term; 840 int err = parse_events_term__str(&term, (int)$1, NULL, $3.str, &@1, &@3); 841 842 if (err) { 843 free($3.str); 844 PE_ABORT(err); 845 } 846 $$ = term; 847 } 848 | 849 PE_TERM '=' PE_TERM 850 { 851 struct parse_events_term *term; 852 int err = parse_events_term__term(&term, (int)$1, (int)$3, &@1, &@3); 853 854 if (err) 855 PE_ABORT(err); 856 857 $$ = term; 858 } 859 | 860 PE_TERM '=' PE_VALUE 861 { 862 struct parse_events_term *term; 863 int err = parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3); 864 865 if (err) 866 PE_ABORT(err); 867 868 $$ = term; 869 } 870 | 871 PE_TERM 872 { 873 struct parse_events_term *term; 874 int err = parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL); 875 876 if (err) 877 PE_ABORT(err); 878 879 $$ = term; 880 } 881 | 882 name_or_raw array '=' name_or_legacy 883 { 884 struct parse_events_term *term; 885 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $4, &@1, &@4); 886 887 if (err) { 888 free($1); 889 free($4); 890 free($2.ranges); 891 PE_ABORT(err); 892 } 893 term->array = $2; 894 $$ = term; 895 } 896 | 897 name_or_raw array '=' PE_VALUE 898 { 899 struct parse_events_term *term; 900 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $4, false, &@1, &@4); 901 902 if (err) { 903 free($1); 904 free($2.ranges); 905 PE_ABORT(err); 906 } 907 term->array = $2; 908 $$ = term; 909 } 910 | 911 PE_DRV_CFG_TERM 912 { 913 struct parse_events_term *term; 914 char *config = strdup($1); 915 int err; 916 917 if (!config) 918 YYNOMEM; 919 err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL); 920 if (err) { 921 free($1); 922 free(config); 923 PE_ABORT(err); 924 } 925 $$ = term; 926 } 927 928 array: 929 '[' array_terms ']' 930 { 931 $$ = $2; 932 } 933 | 934 PE_ARRAY_ALL 935 { 936 $$.nr_ranges = 0; 937 $$.ranges = NULL; 938 } 939 940 array_terms: 941 array_terms ',' array_term 942 { 943 struct parse_events_array new_array; 944 945 new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges; 946 new_array.ranges = realloc($1.ranges, 947 sizeof(new_array.ranges[0]) * 948 new_array.nr_ranges); 949 if (!new_array.ranges) 950 YYNOMEM; 951 memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges, 952 $3.nr_ranges * sizeof(new_array.ranges[0])); 953 free($3.ranges); 954 $$ = new_array; 955 } 956 | 957 array_term 958 959 array_term: 960 PE_VALUE 961 { 962 struct parse_events_array array; 963 964 array.nr_ranges = 1; 965 array.ranges = malloc(sizeof(array.ranges[0])); 966 if (!array.ranges) 967 YYNOMEM; 968 array.ranges[0].start = $1; 969 array.ranges[0].length = 1; 970 $$ = array; 971 } 972 | 973 PE_VALUE PE_ARRAY_RANGE PE_VALUE 974 { 975 struct parse_events_array array; 976 977 if ($3 < $1) { 978 struct parse_events_state *parse_state = _parse_state; 979 struct parse_events_error *error = parse_state->error; 980 char *err_str; 981 982 if (asprintf(&err_str, "Expected '%ld' to be less-than '%ld'", $3, $1) < 0) 983 err_str = NULL; 984 985 parse_events_error__handle(error, @1.first_column, err_str, NULL); 986 YYABORT; 987 } 988 array.nr_ranges = 1; 989 array.ranges = malloc(sizeof(array.ranges[0])); 990 if (!array.ranges) 991 YYNOMEM; 992 array.ranges[0].start = $1; 993 array.ranges[0].length = $3 - $1 + 1; 994 $$ = array; 995 } 996 997 sep_dc: ':' | 998 999 sep_slash_slash_dc: '/' '/' | ':' | 1000 1001 %% 1002 1003 void parse_events_error(YYLTYPE *loc, void *parse_state, 1004 void *scanner __maybe_unused, 1005 char const *msg __maybe_unused) 1006 { 1007 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 1008 } 1009