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