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