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