1%pure-parser
2%parse-param {void *_data}
3%parse-param {void *scanner}
4%lex-param {void* scanner}
5
6%{
7
8#define YYDEBUG 1
9
10#include <linux/compiler.h>
11#include <linux/list.h>
12#include <linux/types.h>
13#include "util.h"
14#include "parse-events.h"
15#include "parse-events-bison.h"
16
17extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
18
19#define ABORT_ON(val) \
20do { \
21	if (val) \
22		YYABORT; \
23} while (0)
24
25#define ALLOC_LIST(list) \
26do { \
27	list = malloc(sizeof(*list)); \
28	ABORT_ON(!list);              \
29	INIT_LIST_HEAD(list);         \
30} while (0)
31
32static inc_group_count(struct list_head *list,
33		       struct parse_events_evlist *data)
34{
35	/* Count groups only have more than 1 members */
36	if (!list_is_last(list->next, list))
37		data->nr_groups++;
38}
39
40%}
41
42%token PE_START_EVENTS PE_START_TERMS
43%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
44%token PE_EVENT_NAME
45%token PE_NAME
46%token PE_MODIFIER_EVENT PE_MODIFIER_BP
47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
49%token PE_ERROR
50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
51%type <num> PE_VALUE
52%type <num> PE_VALUE_SYM_HW
53%type <num> PE_VALUE_SYM_SW
54%type <num> PE_RAW
55%type <num> PE_TERM
56%type <str> PE_NAME
57%type <str> PE_NAME_CACHE_TYPE
58%type <str> PE_NAME_CACHE_OP_RESULT
59%type <str> PE_MODIFIER_EVENT
60%type <str> PE_MODIFIER_BP
61%type <str> PE_EVENT_NAME
62%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
63%type <num> value_sym
64%type <head> event_config
65%type <term> event_term
66%type <head> event_pmu
67%type <head> event_legacy_symbol
68%type <head> event_legacy_cache
69%type <head> event_legacy_mem
70%type <head> event_legacy_tracepoint
71%type <head> event_legacy_numeric
72%type <head> event_legacy_raw
73%type <head> event_def
74%type <head> event_mod
75%type <head> event_name
76%type <head> event
77%type <head> events
78%type <head> group_def
79%type <head> group
80%type <head> groups
81
82%union
83{
84	char *str;
85	u64 num;
86	struct list_head *head;
87	struct parse_events_term *term;
88}
89%%
90
91start:
92PE_START_EVENTS start_events
93|
94PE_START_TERMS  start_terms
95
96start_events: groups
97{
98	struct parse_events_evlist *data = _data;
99
100	parse_events_update_lists($1, &data->list);
101}
102
103groups:
104groups ',' group
105{
106	struct list_head *list  = $1;
107	struct list_head *group = $3;
108
109	parse_events_update_lists(group, list);
110	$$ = list;
111}
112|
113groups ',' event
114{
115	struct list_head *list  = $1;
116	struct list_head *event = $3;
117
118	parse_events_update_lists(event, list);
119	$$ = list;
120}
121|
122group
123|
124event
125
126group:
127group_def ':' PE_MODIFIER_EVENT
128{
129	struct list_head *list = $1;
130
131	ABORT_ON(parse_events__modifier_group(list, $3));
132	$$ = list;
133}
134|
135group_def
136
137group_def:
138PE_NAME '{' events '}'
139{
140	struct list_head *list = $3;
141
142	inc_group_count(list, _data);
143	parse_events__set_leader($1, list);
144	$$ = list;
145}
146|
147'{' events '}'
148{
149	struct list_head *list = $2;
150
151	inc_group_count(list, _data);
152	parse_events__set_leader(NULL, list);
153	$$ = list;
154}
155
156events:
157events ',' event
158{
159	struct list_head *event = $3;
160	struct list_head *list  = $1;
161
162	parse_events_update_lists(event, list);
163	$$ = list;
164}
165|
166event
167
168event: event_mod
169
170event_mod:
171event_name PE_MODIFIER_EVENT
172{
173	struct list_head *list = $1;
174
175	/*
176	 * Apply modifier on all events added by single event definition
177	 * (there could be more events added for multiple tracepoint
178	 * definitions via '*?'.
179	 */
180	ABORT_ON(parse_events__modifier_event(list, $2, false));
181	$$ = list;
182}
183|
184event_name
185
186event_name:
187PE_EVENT_NAME event_def
188{
189	ABORT_ON(parse_events_name($2, $1));
190	free($1);
191	$$ = $2;
192}
193|
194event_def
195
196event_def: event_pmu |
197	   event_legacy_symbol |
198	   event_legacy_cache sep_dc |
199	   event_legacy_mem |
200	   event_legacy_tracepoint sep_dc |
201	   event_legacy_numeric sep_dc |
202	   event_legacy_raw sep_dc
203
204event_pmu:
205PE_NAME '/' event_config '/'
206{
207	struct parse_events_evlist *data = _data;
208	struct list_head *list;
209
210	ALLOC_LIST(list);
211	ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, $3));
212	parse_events__free_terms($3);
213	$$ = list;
214}
215|
216PE_NAME '/' '/'
217{
218	struct parse_events_evlist *data = _data;
219	struct list_head *list;
220
221	ALLOC_LIST(list);
222	ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL));
223	$$ = list;
224}
225|
226PE_KERNEL_PMU_EVENT sep_dc
227{
228	struct parse_events_evlist *data = _data;
229	struct list_head *head;
230	struct parse_events_term *term;
231	struct list_head *list;
232
233	ALLOC_LIST(head);
234	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
235					$1, 1));
236	list_add_tail(&term->list, head);
237
238	ALLOC_LIST(list);
239	ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head));
240	parse_events__free_terms(head);
241	$$ = list;
242}
243|
244PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
245{
246	struct parse_events_evlist *data = _data;
247	struct list_head *head;
248	struct parse_events_term *term;
249	struct list_head *list;
250	char pmu_name[128];
251	snprintf(&pmu_name, 128, "%s-%s", $1, $3);
252
253	ALLOC_LIST(head);
254	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
255					&pmu_name, 1));
256	list_add_tail(&term->list, head);
257
258	ALLOC_LIST(list);
259	ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head));
260	parse_events__free_terms(head);
261	$$ = list;
262}
263
264value_sym:
265PE_VALUE_SYM_HW
266|
267PE_VALUE_SYM_SW
268
269event_legacy_symbol:
270value_sym '/' event_config '/'
271{
272	struct parse_events_evlist *data = _data;
273	struct list_head *list;
274	int type = $1 >> 16;
275	int config = $1 & 255;
276
277	ALLOC_LIST(list);
278	ABORT_ON(parse_events_add_numeric(list, &data->idx,
279					  type, config, $3));
280	parse_events__free_terms($3);
281	$$ = list;
282}
283|
284value_sym sep_slash_dc
285{
286	struct parse_events_evlist *data = _data;
287	struct list_head *list;
288	int type = $1 >> 16;
289	int config = $1 & 255;
290
291	ALLOC_LIST(list);
292	ABORT_ON(parse_events_add_numeric(list, &data->idx,
293					  type, config, NULL));
294	$$ = list;
295}
296
297event_legacy_cache:
298PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
299{
300	struct parse_events_evlist *data = _data;
301	struct list_head *list;
302
303	ALLOC_LIST(list);
304	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5));
305	$$ = list;
306}
307|
308PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
309{
310	struct parse_events_evlist *data = _data;
311	struct list_head *list;
312
313	ALLOC_LIST(list);
314	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL));
315	$$ = list;
316}
317|
318PE_NAME_CACHE_TYPE
319{
320	struct parse_events_evlist *data = _data;
321	struct list_head *list;
322
323	ALLOC_LIST(list);
324	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL));
325	$$ = list;
326}
327
328event_legacy_mem:
329PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
330{
331	struct parse_events_evlist *data = _data;
332	struct list_head *list;
333
334	ALLOC_LIST(list);
335	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
336					     (void *) $2, $6, $4));
337	$$ = list;
338}
339|
340PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
341{
342	struct parse_events_evlist *data = _data;
343	struct list_head *list;
344
345	ALLOC_LIST(list);
346	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
347					     (void *) $2, NULL, $4));
348	$$ = list;
349}
350|
351PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
352{
353	struct parse_events_evlist *data = _data;
354	struct list_head *list;
355
356	ALLOC_LIST(list);
357	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
358					     (void *) $2, $4, 0));
359	$$ = list;
360}
361|
362PE_PREFIX_MEM PE_VALUE sep_dc
363{
364	struct parse_events_evlist *data = _data;
365	struct list_head *list;
366
367	ALLOC_LIST(list);
368	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
369					     (void *) $2, NULL, 0));
370	$$ = list;
371}
372
373event_legacy_tracepoint:
374PE_NAME '-' PE_NAME ':' PE_NAME
375{
376	struct parse_events_evlist *data = _data;
377	struct list_head *list;
378	char sys_name[128];
379	snprintf(&sys_name, 128, "%s-%s", $1, $3);
380
381	ALLOC_LIST(list);
382	ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5));
383	$$ = list;
384}
385|
386PE_NAME ':' PE_NAME
387{
388	struct parse_events_evlist *data = _data;
389	struct list_head *list;
390
391	ALLOC_LIST(list);
392	ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3));
393	$$ = list;
394}
395
396event_legacy_numeric:
397PE_VALUE ':' PE_VALUE
398{
399	struct parse_events_evlist *data = _data;
400	struct list_head *list;
401
402	ALLOC_LIST(list);
403	ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL));
404	$$ = list;
405}
406
407event_legacy_raw:
408PE_RAW
409{
410	struct parse_events_evlist *data = _data;
411	struct list_head *list;
412
413	ALLOC_LIST(list);
414	ABORT_ON(parse_events_add_numeric(list, &data->idx,
415					  PERF_TYPE_RAW, $1, NULL));
416	$$ = list;
417}
418
419start_terms: event_config
420{
421	struct parse_events_terms *data = _data;
422	data->terms = $1;
423}
424
425event_config:
426event_config ',' event_term
427{
428	struct list_head *head = $1;
429	struct parse_events_term *term = $3;
430
431	ABORT_ON(!head);
432	list_add_tail(&term->list, head);
433	$$ = $1;
434}
435|
436event_term
437{
438	struct list_head *head = malloc(sizeof(*head));
439	struct parse_events_term *term = $1;
440
441	ABORT_ON(!head);
442	INIT_LIST_HEAD(head);
443	list_add_tail(&term->list, head);
444	$$ = head;
445}
446
447event_term:
448PE_NAME '=' PE_NAME
449{
450	struct parse_events_term *term;
451
452	ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
453					$1, $3));
454	$$ = term;
455}
456|
457PE_NAME '=' PE_VALUE
458{
459	struct parse_events_term *term;
460
461	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
462					$1, $3));
463	$$ = term;
464}
465|
466PE_NAME '=' PE_VALUE_SYM_HW
467{
468	struct parse_events_term *term;
469	int config = $3 & 255;
470
471	ABORT_ON(parse_events_term__sym_hw(&term, $1, config));
472	$$ = term;
473}
474|
475PE_NAME
476{
477	struct parse_events_term *term;
478
479	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
480					$1, 1));
481	$$ = term;
482}
483|
484PE_VALUE_SYM_HW
485{
486	struct parse_events_term *term;
487	int config = $1 & 255;
488
489	ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
490	$$ = term;
491}
492|
493PE_TERM '=' PE_NAME
494{
495	struct parse_events_term *term;
496
497	ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3));
498	$$ = term;
499}
500|
501PE_TERM '=' PE_VALUE
502{
503	struct parse_events_term *term;
504
505	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3));
506	$$ = term;
507}
508|
509PE_TERM
510{
511	struct parse_events_term *term;
512
513	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1));
514	$$ = term;
515}
516
517sep_dc: ':' |
518
519sep_slash_dc: '/' | ':' |
520
521%%
522
523void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused,
524			char const *msg __maybe_unused)
525{
526}
527