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
22 int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner);
23 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
24
25 #define PE_ABORT(val) \
26 do { \
27 if (val == -ENOMEM) \
28 YYNOMEM; \
29 YYABORT; \
30 } while (0)
31
alloc_list(void)32 static 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
free_list_evsel(struct list_head * list_evsel)44 static 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_TERM
59 %token PE_EVENT_NAME
60 %token PE_RAW PE_NAME
61 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
62 %token PE_PREFIX_MEM
63 %token PE_ERROR
64 %token PE_DRV_CFG_TERM
65 %type <num> PE_VALUE
66 %type <mod> PE_MODIFIER_EVENT
67 %type <term_type> PE_TERM
68 %type <str> PE_RAW
69 %type <str> PE_NAME
70 %type <str> PE_MODIFIER_BP
71 %type <str> PE_EVENT_NAME
72 %type <str> PE_DRV_CFG_TERM
73 %type <str> name_or_raw
74 %destructor { free ($$); } <str>
75 %type <term> event_term
76 %destructor { parse_events_term__delete ($$); } <term>
77 %type <list_terms> event_config
78 %type <list_terms> opt_event_config
79 %type <list_terms> opt_pmu_config
80 %destructor { parse_events_terms__delete ($$); } <list_terms>
81 %type <list_evsel> event_pmu
82 %type <list_evsel> event_legacy_mem
83 %type <list_evsel> event_legacy_tracepoint
84 %type <list_evsel> event_legacy_numeric
85 %type <list_evsel> event_legacy_raw
86 %type <list_evsel> event_def
87 %type <list_evsel> event_mod
88 %type <list_evsel> event_name
89 %type <list_evsel> event
90 %type <list_evsel> events
91 %type <list_evsel> group_def
92 %type <list_evsel> group
93 %type <list_evsel> groups
94 %destructor { free_list_evsel ($$); } <list_evsel>
95 %type <tracepoint_name> tracepoint_name
96 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
97
98 %union
99 {
100 char *str;
101 u64 num;
102 struct parse_events_modifier mod;
103 enum parse_events__term_type term_type;
104 struct list_head *list_evsel;
105 struct parse_events_terms *list_terms;
106 struct parse_events_term *term;
107 struct tracepoint_name {
108 char *sys;
109 char *event;
110 } tracepoint_name;
111 }
112 %%
113
114 /*
115 * Entry points. We are either parsing events or terminals. Just terminal
116 * parsing is used for parsing events in sysfs.
117 */
118 start:
119 PE_START_EVENTS start_events
120 |
121 PE_START_TERMS start_terms
122
123 start_events: groups
124 {
125 /* Take the parsed events, groups.. and place into parse_state. */
126 struct list_head *groups = $1;
127 struct parse_events_state *parse_state = _parse_state;
128
129 list_splice_tail(groups, &parse_state->list);
130 free(groups);
131 }
132
133 groups: /* A list of groups or events. */
134 groups ',' group
135 {
136 /* Merge group into the list of events/groups. */
137 struct list_head *groups = $1;
138 struct list_head *group = $3;
139
140 list_splice_tail(group, groups);
141 free(group);
142 $$ = groups;
143 }
144 |
145 groups ',' event
146 {
147 /* Merge event into the list of events/groups. */
148 struct list_head *groups = $1;
149 struct list_head *event = $3;
150
151
152 list_splice_tail(event, groups);
153 free(event);
154 $$ = groups;
155 }
156 |
157 group
158 |
159 event
160
161 group:
162 group_def ':' PE_MODIFIER_EVENT
163 {
164 /* Apply the modifier to the events in the group_def. */
165 struct list_head *list = $1;
166 int err;
167
168 err = parse_events__modifier_group(_parse_state, &@3, list, $3);
169 if (err)
170 YYABORT;
171 $$ = list;
172 }
173 |
174 group_def
175
176 group_def:
177 PE_NAME '{' events '}'
178 {
179 struct list_head *list = $3;
180
181 /*
182 * Set the first entry of list to be the leader. Set the group name on
183 * the leader to $1 taking ownership.
184 */
185 parse_events__set_leader($1, list);
186 $$ = list;
187 }
188 |
189 '{' events '}'
190 {
191 struct list_head *list = $2;
192
193 /* Set the first entry of list to be the leader clearing the group name. */
194 parse_events__set_leader(NULL, list);
195 $$ = list;
196 }
197
198 events:
199 events ',' event
200 {
201 struct list_head *events = $1;
202 struct list_head *event = $3;
203
204 list_splice_tail(event, events);
205 free(event);
206 $$ = events;
207 }
208 |
209 event
210
211 event: event_mod
212
213 event_mod:
214 event_name PE_MODIFIER_EVENT
215 {
216 struct list_head *list = $1;
217 int err;
218
219 /*
220 * Apply modifier on all events added by single event definition
221 * (there could be more events added for multiple tracepoint
222 * definitions via '*?'.
223 */
224 err = parse_events__modifier_event(_parse_state, &@2, list, $2);
225 if (err)
226 YYABORT;
227 $$ = list;
228 }
229 |
230 event_name
231
232 event_name:
233 PE_EVENT_NAME event_def
234 {
235 /*
236 * When an event is parsed the text is rewound and the entire text of
237 * the event is set to the str of PE_EVENT_NAME token matched here. If
238 * no name was on an event via a term, set the name to the entire text
239 * taking ownership of the allocation.
240 */
241 int err = parse_events__set_default_name($2, $1);
242
243 if (err) {
244 free_list_evsel($2);
245 YYNOMEM;
246 }
247 $$ = $2;
248 }
249 |
250 event_def
251
252 event_def: event_pmu |
253 event_legacy_mem sep_dc |
254 event_legacy_tracepoint sep_dc |
255 event_legacy_numeric sep_dc |
256 event_legacy_raw sep_dc
257
258 event_pmu:
259 PE_NAME opt_pmu_config
260 {
261 /* List of created evsels. */
262 struct list_head *list = NULL;
263 int err = parse_events_multi_pmu_add_or_add_pmu(_parse_state, $1, $2, &list, &@1);
264
265 parse_events_terms__delete($2);
266 free($1);
267 if (err)
268 PE_ABORT(err);
269 $$ = list;
270 }
271 |
272 PE_NAME sep_dc
273 {
274 struct list_head *list;
275 int err;
276
277 err = parse_events_multi_pmu_add(_parse_state, $1, /*const_parsed_terms*/NULL, &list, &@1);
278 if (err < 0) {
279 struct parse_events_state *parse_state = _parse_state;
280 struct parse_events_error *error = parse_state->error;
281 char *help;
282
283 if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0)
284 help = NULL;
285 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
286 free($1);
287 PE_ABORT(err);
288 }
289 free($1);
290 $$ = list;
291 }
292
293 event_legacy_mem:
294 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
295 {
296 struct list_head *list;
297 int err;
298
299 list = alloc_list();
300 if (!list)
301 YYNOMEM;
302
303 err = parse_events_add_breakpoint(_parse_state, list,
304 $2, $6, $4, $7);
305 parse_events_terms__delete($7);
306 free($6);
307 if (err) {
308 free(list);
309 PE_ABORT(err);
310 }
311 $$ = list;
312 }
313 |
314 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
315 {
316 struct list_head *list;
317 int err;
318
319 list = alloc_list();
320 if (!list)
321 YYNOMEM;
322
323 err = parse_events_add_breakpoint(_parse_state, list,
324 $2, NULL, $4, $5);
325 parse_events_terms__delete($5);
326 if (err) {
327 free(list);
328 PE_ABORT(err);
329 }
330 $$ = list;
331 }
332 |
333 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
334 {
335 struct list_head *list;
336 int err;
337
338 list = alloc_list();
339 if (!list)
340 YYNOMEM;
341
342 err = parse_events_add_breakpoint(_parse_state, list,
343 $2, $4, 0, $5);
344 parse_events_terms__delete($5);
345 free($4);
346 if (err) {
347 free(list);
348 PE_ABORT(err);
349 }
350 $$ = list;
351 }
352 |
353 PE_PREFIX_MEM PE_VALUE opt_event_config
354 {
355 struct list_head *list;
356 int err;
357
358 list = alloc_list();
359 if (!list)
360 YYNOMEM;
361 err = parse_events_add_breakpoint(_parse_state, list,
362 $2, NULL, 0, $3);
363 parse_events_terms__delete($3);
364 if (err) {
365 free(list);
366 PE_ABORT(err);
367 }
368 $$ = list;
369 }
370
371 event_legacy_tracepoint:
372 tracepoint_name opt_event_config
373 {
374 struct parse_events_state *parse_state = _parse_state;
375 struct parse_events_error *error = parse_state->error;
376 struct list_head *list;
377 int err;
378
379 list = alloc_list();
380 if (!list)
381 YYNOMEM;
382
383 err = parse_events_add_tracepoint(parse_state, list, $1.sys, $1.event,
384 error, $2, &@1);
385
386 parse_events_terms__delete($2);
387 free($1.sys);
388 free($1.event);
389 if (err) {
390 free(list);
391 PE_ABORT(err);
392 }
393 $$ = list;
394 }
395
396 tracepoint_name:
397 PE_NAME ':' PE_NAME
398 {
399 struct tracepoint_name tracepoint = {$1, $3};
400
401 $$ = tracepoint;
402 }
403
404 event_legacy_numeric:
405 PE_VALUE ':' PE_VALUE opt_event_config
406 {
407 struct list_head *list;
408 int err;
409
410 list = alloc_list();
411 if (!list)
412 YYNOMEM;
413 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
414 /*wildcard=*/false);
415 parse_events_terms__delete($4);
416 if (err) {
417 free(list);
418 PE_ABORT(err);
419 }
420 $$ = list;
421 }
422
423 event_legacy_raw:
424 PE_RAW opt_event_config
425 {
426 struct list_head *list;
427 int err;
428 u64 num;
429
430 list = alloc_list();
431 if (!list)
432 YYNOMEM;
433 errno = 0;
434 num = strtoull($1 + 1, NULL, 16);
435 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
436 if (errno)
437 YYABORT;
438 free($1);
439 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
440 /*wildcard=*/false);
441 parse_events_terms__delete($2);
442 if (err) {
443 free(list);
444 PE_ABORT(err);
445 }
446 $$ = list;
447 }
448
449 opt_event_config:
450 '/' event_config '/'
451 {
452 $$ = $2;
453 }
454 |
455 '/' '/'
456 {
457 $$ = NULL;
458 }
459 |
460 {
461 $$ = NULL;
462 }
463
464 opt_pmu_config:
465 '/' event_config '/'
466 {
467 $$ = $2;
468 }
469 |
470 '/' '/'
471 {
472 $$ = NULL;
473 }
474
475 start_terms: event_config
476 {
477 struct parse_events_state *parse_state = _parse_state;
478 if (parse_state->terms) {
479 parse_events_terms__delete ($1);
480 YYABORT;
481 }
482 parse_state->terms = $1;
483 }
484
485 event_config:
486 event_config ',' event_term
487 {
488 struct parse_events_terms *head = $1;
489 struct parse_events_term *term = $3;
490
491 if (!head) {
492 parse_events_term__delete(term);
493 YYABORT;
494 }
495 list_add_tail(&term->list, &head->terms);
496 $$ = $1;
497 }
498 |
499 event_term
500 {
501 struct parse_events_terms *head = malloc(sizeof(*head));
502 struct parse_events_term *term = $1;
503
504 if (!head)
505 YYNOMEM;
506 parse_events_terms__init(head);
507 list_add_tail(&term->list, &head->terms);
508 $$ = head;
509 }
510
511 name_or_raw: PE_RAW | PE_NAME
512
513 event_term:
514 PE_RAW
515 {
516 struct parse_events_term *term;
517 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
518 strdup("raw"), $1, &@1, &@1);
519
520 if (err) {
521 free($1);
522 PE_ABORT(err);
523 }
524 $$ = term;
525 }
526 |
527 name_or_raw '=' name_or_raw
528 {
529 struct parse_events_term *term;
530 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
531
532 if (err) {
533 free($1);
534 free($3);
535 PE_ABORT(err);
536 }
537 $$ = term;
538 }
539 |
540 name_or_raw '=' PE_VALUE
541 {
542 struct parse_events_term *term;
543 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
544 $1, $3, /*novalue=*/false, &@1, &@3);
545
546 if (err) {
547 free($1);
548 PE_ABORT(err);
549 }
550 $$ = term;
551 }
552 |
553 PE_NAME
554 {
555 struct parse_events_term *term;
556 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
557 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
558
559 if (err) {
560 free($1);
561 PE_ABORT(err);
562 }
563 $$ = term;
564 }
565 |
566 PE_TERM '=' name_or_raw
567 {
568 struct parse_events_term *term;
569 int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3);
570
571 if (err) {
572 free($3);
573 PE_ABORT(err);
574 }
575 $$ = term;
576 }
577 |
578 PE_TERM '=' PE_TERM
579 {
580 struct parse_events_term *term;
581 int err = parse_events_term__term(&term, $1, $3, &@1, &@3);
582
583 if (err)
584 PE_ABORT(err);
585
586 $$ = term;
587 }
588 |
589 PE_TERM '=' PE_VALUE
590 {
591 struct parse_events_term *term;
592 int err = parse_events_term__num(&term, $1,
593 /*config=*/NULL, $3, /*novalue=*/false,
594 &@1, &@3);
595
596 if (err)
597 PE_ABORT(err);
598
599 $$ = term;
600 }
601 |
602 PE_TERM
603 {
604 struct parse_events_term *term;
605 int err = parse_events_term__num(&term, $1,
606 /*config=*/NULL, /*num=*/1, /*novalue=*/true,
607 &@1, /*loc_val=*/NULL);
608
609 if (err)
610 PE_ABORT(err);
611
612 $$ = term;
613 }
614 |
615 PE_DRV_CFG_TERM
616 {
617 struct parse_events_term *term;
618 char *config = strdup($1);
619 int err;
620
621 if (!config)
622 YYNOMEM;
623 err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL);
624 if (err) {
625 free($1);
626 free(config);
627 PE_ABORT(err);
628 }
629 $$ = term;
630 }
631
632 sep_dc: ':' |
633
634 %%
635
636 void parse_events_error(YYLTYPE *loc, void *_parse_state,
637 void *scanner __maybe_unused,
638 char const *msg __maybe_unused)
639 {
640 struct parse_events_state *parse_state = _parse_state;
641
642 if (!parse_state->error || !list_empty(&parse_state->error->list))
643 return;
644
645 parse_events_error__handle(parse_state->error, loc->last_column,
646 strdup("Unrecognized input"), NULL);
647 }
648