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