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