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