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#ifndef NDEBUG
10#define YYDEBUG 1
11#endif
12
13#include <errno.h>
14#include <linux/compiler.h>
15#include <linux/types.h>
16#include "pmu.h"
17#include "pmus.h"
18#include "evsel.h"
19#include "parse-events.h"
20#include "parse-events-bison.h"
21
22int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner);
23void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
24
25#define PE_ABORT(val) \
26do { \
27	if (val == -ENOMEM) \
28		YYNOMEM; \
29	YYABORT; \
30} while (0)
31
32static struct list_head* alloc_list(void)
33{
34	struct list_head *list;
35
36	list = malloc(sizeof(*list));
37	if (!list)
38		return NULL;
39
40	INIT_LIST_HEAD(list);
41	return list;
42}
43
44static void free_list_evsel(struct list_head* list_evsel)
45{
46	struct evsel *evsel, *tmp;
47
48	list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
49		list_del_init(&evsel->core.node);
50		evsel__delete(evsel);
51	}
52	free(list_evsel);
53}
54
55%}
56
57%token PE_START_EVENTS PE_START_TERMS
58%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
59%token PE_VALUE_SYM_TOOL
60%token PE_EVENT_NAME
61%token PE_RAW PE_NAME
62%token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
63%token PE_LEGACY_CACHE
64%token PE_PREFIX_MEM
65%token PE_ERROR
66%token PE_DRV_CFG_TERM
67%token PE_TERM_HW
68%type <num> PE_VALUE
69%type <num> PE_VALUE_SYM_HW
70%type <num> PE_VALUE_SYM_SW
71%type <num> PE_VALUE_SYM_TOOL
72%type <mod> PE_MODIFIER_EVENT
73%type <term_type> PE_TERM
74%type <num> value_sym
75%type <str> PE_RAW
76%type <str> PE_NAME
77%type <str> PE_LEGACY_CACHE
78%type <str> PE_MODIFIER_BP
79%type <str> PE_EVENT_NAME
80%type <str> PE_DRV_CFG_TERM
81%type <str> name_or_raw
82%destructor { free ($$); } <str>
83%type <term> event_term
84%destructor { parse_events_term__delete ($$); } <term>
85%type <list_terms> event_config
86%type <list_terms> opt_event_config
87%type <list_terms> opt_pmu_config
88%destructor { parse_events_terms__delete ($$); } <list_terms>
89%type <list_evsel> event_pmu
90%type <list_evsel> event_legacy_symbol
91%type <list_evsel> event_legacy_cache
92%type <list_evsel> event_legacy_mem
93%type <list_evsel> event_legacy_tracepoint
94%type <list_evsel> event_legacy_numeric
95%type <list_evsel> event_legacy_raw
96%type <list_evsel> event_def
97%type <list_evsel> event_mod
98%type <list_evsel> event_name
99%type <list_evsel> event
100%type <list_evsel> events
101%type <list_evsel> group_def
102%type <list_evsel> group
103%type <list_evsel> groups
104%destructor { free_list_evsel ($$); } <list_evsel>
105%type <tracepoint_name> tracepoint_name
106%destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
107%type <hardware_term> PE_TERM_HW
108%destructor { free ($$.str); } <hardware_term>
109
110%union
111{
112	char *str;
113	u64 num;
114	struct parse_events_modifier mod;
115	enum parse_events__term_type term_type;
116	struct list_head *list_evsel;
117	struct parse_events_terms *list_terms;
118	struct parse_events_term *term;
119	struct tracepoint_name {
120		char *sys;
121		char *event;
122	} tracepoint_name;
123	struct hardware_term {
124		char *str;
125		u64 num;
126	} hardware_term;
127}
128%%
129
130 /*
131  * Entry points. We are either parsing events or terminals. Just terminal
132  * parsing is used for parsing events in sysfs.
133  */
134start:
135PE_START_EVENTS start_events
136|
137PE_START_TERMS  start_terms
138
139start_events: groups
140{
141	/* Take the parsed events, groups.. and place into parse_state. */
142	struct list_head *groups  = $1;
143	struct parse_events_state *parse_state = _parse_state;
144
145	list_splice_tail(groups, &parse_state->list);
146	free(groups);
147}
148
149groups: /* A list of groups or events. */
150groups ',' group
151{
152	/* Merge group into the list of events/groups. */
153	struct list_head *groups  = $1;
154	struct list_head *group  = $3;
155
156	list_splice_tail(group, groups);
157	free(group);
158	$$ = groups;
159}
160|
161groups ',' event
162{
163	/* Merge event into the list of events/groups. */
164	struct list_head *groups  = $1;
165	struct list_head *event = $3;
166
167
168	list_splice_tail(event, groups);
169	free(event);
170	$$ = groups;
171}
172|
173group
174|
175event
176
177group:
178group_def ':' PE_MODIFIER_EVENT
179{
180	/* Apply the modifier to the events in the group_def. */
181	struct list_head *list = $1;
182	int err;
183
184	err = parse_events__modifier_group(_parse_state, &@3, list, $3);
185	if (err)
186		YYABORT;
187	$$ = list;
188}
189|
190group_def
191
192group_def:
193PE_NAME '{' events '}'
194{
195	struct list_head *list = $3;
196
197	/*
198	 * Set the first entry of list to be the leader. Set the group name on
199	 * the leader to $1 taking ownership.
200	 */
201	parse_events__set_leader($1, list);
202	$$ = list;
203}
204|
205'{' events '}'
206{
207	struct list_head *list = $2;
208
209	/* Set the first entry of list to be the leader clearing the group name. */
210	parse_events__set_leader(NULL, list);
211	$$ = list;
212}
213
214events:
215events ',' event
216{
217	struct list_head *events  = $1;
218	struct list_head *event = $3;
219
220	list_splice_tail(event, events);
221	free(event);
222	$$ = events;
223}
224|
225event
226
227event: event_mod
228
229event_mod:
230event_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(_parse_state, &@2, list, $2);
241	if (err)
242		YYABORT;
243	$$ = list;
244}
245|
246event_name
247
248event_name:
249PE_EVENT_NAME event_def
250{
251	/*
252	 * When an event is parsed the text is rewound and the entire text of
253	 * the event is set to the str of PE_EVENT_NAME token matched here. If
254	 * no name was on an event via a term, set the name to the entire text
255	 * taking ownership of the allocation.
256	 */
257	int err = parse_events__set_default_name($2, $1);
258
259	if (err) {
260		free_list_evsel($2);
261		YYNOMEM;
262	}
263	$$ = $2;
264}
265|
266event_def
267
268event_def: event_pmu |
269	   event_legacy_symbol |
270	   event_legacy_cache sep_dc |
271	   event_legacy_mem sep_dc |
272	   event_legacy_tracepoint sep_dc |
273	   event_legacy_numeric sep_dc |
274	   event_legacy_raw sep_dc
275
276event_pmu:
277PE_NAME opt_pmu_config
278{
279	/* List of created evsels. */
280	struct list_head *list = NULL;
281	int err = parse_events_multi_pmu_add_or_add_pmu(_parse_state, $1, $2, &list, &@1);
282
283	parse_events_terms__delete($2);
284	free($1);
285	if (err)
286		PE_ABORT(err);
287	$$ = list;
288}
289|
290PE_NAME sep_dc
291{
292	struct list_head *list;
293	int err;
294
295	err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);
296	if (err < 0) {
297		struct parse_events_state *parse_state = _parse_state;
298		struct parse_events_error *error = parse_state->error;
299		char *help;
300
301		if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0)
302			help = NULL;
303		parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
304		free($1);
305		PE_ABORT(err);
306	}
307	free($1);
308	$$ = list;
309}
310
311value_sym:
312PE_VALUE_SYM_HW
313|
314PE_VALUE_SYM_SW
315
316event_legacy_symbol:
317value_sym '/' event_config '/'
318{
319	struct list_head *list;
320	int type = $1 >> 16;
321	int config = $1 & 255;
322	int err;
323	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
324
325	list = alloc_list();
326	if (!list)
327		YYNOMEM;
328	err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
329	parse_events_terms__delete($3);
330	if (err) {
331		free_list_evsel(list);
332		PE_ABORT(err);
333	}
334	$$ = list;
335}
336|
337value_sym sep_slash_slash_dc
338{
339	struct list_head *list;
340	int type = $1 >> 16;
341	int config = $1 & 255;
342	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
343	int err;
344
345	list = alloc_list();
346	if (!list)
347		YYNOMEM;
348	err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
349	if (err)
350		PE_ABORT(err);
351	$$ = list;
352}
353|
354PE_VALUE_SYM_TOOL sep_slash_slash_dc
355{
356	struct list_head *list;
357	int err;
358
359	list = alloc_list();
360	if (!list)
361		YYNOMEM;
362	err = parse_events_add_tool(_parse_state, list, $1);
363	if (err)
364		YYNOMEM;
365	$$ = list;
366}
367
368event_legacy_cache:
369PE_LEGACY_CACHE opt_event_config
370{
371	struct parse_events_state *parse_state = _parse_state;
372	struct list_head *list;
373	int err;
374
375	list = alloc_list();
376	if (!list)
377		YYNOMEM;
378
379	err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
380
381	parse_events_terms__delete($2);
382	free($1);
383	if (err) {
384		free_list_evsel(list);
385		PE_ABORT(err);
386	}
387	$$ = list;
388}
389
390event_legacy_mem:
391PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
392{
393	struct list_head *list;
394	int err;
395
396	list = alloc_list();
397	if (!list)
398		YYNOMEM;
399
400	err = parse_events_add_breakpoint(_parse_state, list,
401					  $2, $6, $4, $7);
402	parse_events_terms__delete($7);
403	free($6);
404	if (err) {
405		free(list);
406		PE_ABORT(err);
407	}
408	$$ = list;
409}
410|
411PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
412{
413	struct list_head *list;
414	int err;
415
416	list = alloc_list();
417	if (!list)
418		YYNOMEM;
419
420	err = parse_events_add_breakpoint(_parse_state, list,
421					  $2, NULL, $4, $5);
422	parse_events_terms__delete($5);
423	if (err) {
424		free(list);
425		PE_ABORT(err);
426	}
427	$$ = list;
428}
429|
430PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
431{
432	struct list_head *list;
433	int err;
434
435	list = alloc_list();
436	if (!list)
437		YYNOMEM;
438
439	err = parse_events_add_breakpoint(_parse_state, list,
440					  $2, $4, 0, $5);
441	parse_events_terms__delete($5);
442	free($4);
443	if (err) {
444		free(list);
445		PE_ABORT(err);
446	}
447	$$ = list;
448}
449|
450PE_PREFIX_MEM PE_VALUE opt_event_config
451{
452	struct list_head *list;
453	int err;
454
455	list = alloc_list();
456	if (!list)
457		YYNOMEM;
458	err = parse_events_add_breakpoint(_parse_state, list,
459					  $2, NULL, 0, $3);
460	parse_events_terms__delete($3);
461	if (err) {
462		free(list);
463		PE_ABORT(err);
464	}
465	$$ = list;
466}
467
468event_legacy_tracepoint:
469tracepoint_name opt_event_config
470{
471	struct parse_events_state *parse_state = _parse_state;
472	struct parse_events_error *error = parse_state->error;
473	struct list_head *list;
474	int err;
475
476	list = alloc_list();
477	if (!list)
478		YYNOMEM;
479
480	err = parse_events_add_tracepoint(parse_state, list, $1.sys, $1.event,
481					error, $2, &@1);
482
483	parse_events_terms__delete($2);
484	free($1.sys);
485	free($1.event);
486	if (err) {
487		free(list);
488		PE_ABORT(err);
489	}
490	$$ = list;
491}
492
493tracepoint_name:
494PE_NAME ':' PE_NAME
495{
496	struct tracepoint_name tracepoint = {$1, $3};
497
498	$$ = tracepoint;
499}
500
501event_legacy_numeric:
502PE_VALUE ':' PE_VALUE opt_event_config
503{
504	struct list_head *list;
505	int err;
506
507	list = alloc_list();
508	if (!list)
509		YYNOMEM;
510	err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
511				       /*wildcard=*/false);
512	parse_events_terms__delete($4);
513	if (err) {
514		free(list);
515		PE_ABORT(err);
516	}
517	$$ = list;
518}
519
520event_legacy_raw:
521PE_RAW opt_event_config
522{
523	struct list_head *list;
524	int err;
525	u64 num;
526
527	list = alloc_list();
528	if (!list)
529		YYNOMEM;
530	errno = 0;
531	num = strtoull($1 + 1, NULL, 16);
532	/* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
533	if (errno)
534		YYABORT;
535	free($1);
536	err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
537				       /*wildcard=*/false);
538	parse_events_terms__delete($2);
539	if (err) {
540		free(list);
541		PE_ABORT(err);
542	}
543	$$ = list;
544}
545
546opt_event_config:
547'/' event_config '/'
548{
549	$$ = $2;
550}
551|
552'/' '/'
553{
554	$$ = NULL;
555}
556|
557{
558	$$ = NULL;
559}
560
561opt_pmu_config:
562'/' event_config '/'
563{
564	$$ = $2;
565}
566|
567'/' '/'
568{
569	$$ = NULL;
570}
571
572start_terms: event_config
573{
574	struct parse_events_state *parse_state = _parse_state;
575	if (parse_state->terms) {
576		parse_events_terms__delete ($1);
577		YYABORT;
578	}
579	parse_state->terms = $1;
580}
581
582event_config:
583event_config ',' event_term
584{
585	struct parse_events_terms *head = $1;
586	struct parse_events_term *term = $3;
587
588	if (!head) {
589		parse_events_term__delete(term);
590		YYABORT;
591	}
592	list_add_tail(&term->list, &head->terms);
593	$$ = $1;
594}
595|
596event_term
597{
598	struct parse_events_terms *head = malloc(sizeof(*head));
599	struct parse_events_term *term = $1;
600
601	if (!head)
602		YYNOMEM;
603	parse_events_terms__init(head);
604	list_add_tail(&term->list, &head->terms);
605	$$ = head;
606}
607
608name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
609|
610PE_TERM_HW
611{
612	$$ = $1.str;
613}
614
615event_term:
616PE_RAW
617{
618	struct parse_events_term *term;
619	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
620					 strdup("raw"), $1, &@1, &@1);
621
622	if (err) {
623		free($1);
624		PE_ABORT(err);
625	}
626	$$ = term;
627}
628|
629name_or_raw '=' name_or_raw
630{
631	struct parse_events_term *term;
632	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
633
634	if (err) {
635		free($1);
636		free($3);
637		PE_ABORT(err);
638	}
639	$$ = term;
640}
641|
642name_or_raw '=' PE_VALUE
643{
644	struct parse_events_term *term;
645	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
646					 $1, $3, /*novalue=*/false, &@1, &@3);
647
648	if (err) {
649		free($1);
650		PE_ABORT(err);
651	}
652	$$ = term;
653}
654|
655PE_LEGACY_CACHE
656{
657	struct parse_events_term *term;
658	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
659					 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
660
661	if (err) {
662		free($1);
663		PE_ABORT(err);
664	}
665	$$ = term;
666}
667|
668PE_NAME
669{
670	struct parse_events_term *term;
671	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
672					 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
673
674	if (err) {
675		free($1);
676		PE_ABORT(err);
677	}
678	$$ = term;
679}
680|
681PE_TERM_HW
682{
683	struct parse_events_term *term;
684	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
685					 $1.str, $1.num & 255, /*novalue=*/false,
686					 &@1, /*loc_val=*/NULL);
687
688	if (err) {
689		free($1.str);
690		PE_ABORT(err);
691	}
692	$$ = term;
693}
694|
695PE_TERM '=' name_or_raw
696{
697	struct parse_events_term *term;
698	int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3);
699
700	if (err) {
701		free($3);
702		PE_ABORT(err);
703	}
704	$$ = term;
705}
706|
707PE_TERM '=' PE_TERM
708{
709	struct parse_events_term *term;
710	int err = parse_events_term__term(&term, $1, $3, &@1, &@3);
711
712	if (err)
713		PE_ABORT(err);
714
715	$$ = term;
716}
717|
718PE_TERM '=' PE_VALUE
719{
720	struct parse_events_term *term;
721	int err = parse_events_term__num(&term, $1,
722					 /*config=*/NULL, $3, /*novalue=*/false,
723					 &@1, &@3);
724
725	if (err)
726		PE_ABORT(err);
727
728	$$ = term;
729}
730|
731PE_TERM
732{
733	struct parse_events_term *term;
734	int err = parse_events_term__num(&term, $1,
735					 /*config=*/NULL, /*num=*/1, /*novalue=*/true,
736					 &@1, /*loc_val=*/NULL);
737
738	if (err)
739		PE_ABORT(err);
740
741	$$ = term;
742}
743|
744PE_DRV_CFG_TERM
745{
746	struct parse_events_term *term;
747	char *config = strdup($1);
748	int err;
749
750	if (!config)
751		YYNOMEM;
752	err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL);
753	if (err) {
754		free($1);
755		free(config);
756		PE_ABORT(err);
757	}
758	$$ = term;
759}
760
761sep_dc: ':' |
762
763sep_slash_slash_dc: '/' '/' | ':' |
764
765%%
766
767void parse_events_error(YYLTYPE *loc, void *_parse_state,
768			void *scanner __maybe_unused,
769			char const *msg __maybe_unused)
770{
771	struct parse_events_state *parse_state = _parse_state;
772
773	if (!parse_state->error || !list_empty(&parse_state->error->list))
774		return;
775
776	parse_events_error__handle(parse_state->error, loc->last_column,
777				   strdup("Unrecognized input"), NULL);
778}
779