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