xref: /openbmc/linux/tools/perf/util/parse-events.y (revision 887069f4)
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(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 
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 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