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