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