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