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