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