2 %parse-param {void *_parse_state}
3 %parse-param {void *scanner}
4 %lex-param {void* scanner}
14 #include <linux/compiler.h>
15 #include <linux/types.h>
19 #include "parse-events.h"
20 #include "parse-events-bison.h"
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);
25 #define PE_ABORT(val) \
32 static struct list_head* alloc_list(void)
34 struct list_head *list;
36 list = malloc(sizeof(*list));
44 static void free_list_evsel(struct list_head* list_evsel)
46 struct evsel *evsel, *tmp;
48 list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
49 list_del_init(&evsel->core.node);
57 %token PE_START_EVENTS PE_START_TERMS
58 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
61 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
62 %token PE_LEGACY_CACHE
65 %token PE_DRV_CFG_TERM
68 %type <num> PE_VALUE_SYM_HW
69 %type <num> PE_VALUE_SYM_SW
70 %type <mod> PE_MODIFIER_EVENT
71 %type <term_type> PE_TERM
75 %type <str> PE_LEGACY_CACHE
76 %type <str> PE_MODIFIER_BP
77 %type <str> PE_EVENT_NAME
78 %type <str> PE_DRV_CFG_TERM
79 %type <str> name_or_raw
80 %destructor { free ($$); } <str>
81 %type <term> event_term
82 %destructor { parse_events_term__delete ($$); } <term>
83 %type <list_terms> event_config
84 %type <list_terms> opt_event_config
85 %type <list_terms> opt_pmu_config
86 %destructor { parse_events_terms__delete ($$); } <list_terms>
87 %type <list_evsel> event_pmu
88 %type <list_evsel> event_legacy_symbol
89 %type <list_evsel> event_legacy_cache
90 %type <list_evsel> event_legacy_mem
91 %type <list_evsel> event_legacy_tracepoint
92 %type <list_evsel> event_legacy_numeric
93 %type <list_evsel> event_legacy_raw
94 %type <list_evsel> event_def
95 %type <list_evsel> event_mod
96 %type <list_evsel> event_name
97 %type <list_evsel> event
98 %type <list_evsel> events
99 %type <list_evsel> group_def
100 %type <list_evsel> group
101 %type <list_evsel> groups
102 %destructor { free_list_evsel ($$); } <list_evsel>
103 %type <tracepoint_name> tracepoint_name
104 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
105 %type <hardware_term> PE_TERM_HW
106 %destructor { free ($$.str); } <hardware_term>
112 struct parse_events_modifier mod;
113 enum parse_events__term_type term_type;
114 struct list_head *list_evsel;
115 struct parse_events_terms *list_terms;
116 struct parse_events_term *term;
117 struct tracepoint_name {
121 struct hardware_term {
129 * Entry points. We are either parsing events or terminals. Just terminal
130 * parsing is used for parsing events in sysfs.
133 PE_START_EVENTS start_events
135 PE_START_TERMS start_terms
139 /* Take the parsed events, groups.. and place into parse_state. */
140 struct list_head *groups = $1;
141 struct parse_events_state *parse_state = _parse_state;
143 list_splice_tail(groups, &parse_state->list);
147 groups: /* A list of groups or events. */
150 /* Merge group into the list of events/groups. */
151 struct list_head *groups = $1;
152 struct list_head *group = $3;
154 list_splice_tail(group, groups);
161 /* Merge event into the list of events/groups. */
162 struct list_head *groups = $1;
163 struct list_head *event = $3;
166 list_splice_tail(event, groups);
176 group_def ':' PE_MODIFIER_EVENT
178 /* Apply the modifier to the events in the group_def. */
179 struct list_head *list = $1;
182 err = parse_events__modifier_group(_parse_state, &@3, list, $3);
191 PE_NAME '{' events '}'
193 struct list_head *list = $3;
196 * Set the first entry of list to be the leader. Set the group name on
197 * the leader to $1 taking ownership.
199 parse_events__set_leader($1, list);
205 struct list_head *list = $2;
207 /* Set the first entry of list to be the leader clearing the group name. */
208 parse_events__set_leader(NULL, list);
215 struct list_head *events = $1;
216 struct list_head *event = $3;
218 list_splice_tail(event, events);
228 event_name PE_MODIFIER_EVENT
230 struct list_head *list = $1;
234 * Apply modifier on all events added by single event definition
235 * (there could be more events added for multiple tracepoint
236 * definitions via '*?'.
238 err = parse_events__modifier_event(_parse_state, &@2, list, $2);
247 PE_EVENT_NAME event_def
250 * When an event is parsed the text is rewound and the entire text of
251 * the event is set to the str of PE_EVENT_NAME token matched here. If
252 * no name was on an event via a term, set the name to the entire text
253 * taking ownership of the allocation.
255 int err = parse_events__set_default_name($2, $1);
266 event_def: event_pmu |
267 event_legacy_symbol |
268 event_legacy_cache sep_dc |
269 event_legacy_mem sep_dc |
270 event_legacy_tracepoint sep_dc |
271 event_legacy_numeric sep_dc |
272 event_legacy_raw sep_dc
275 PE_NAME opt_pmu_config
277 /* List of created evsels. */
278 struct list_head *list = NULL;
279 int err = parse_events_multi_pmu_add_or_add_pmu(_parse_state, $1, $2, &list, &@1);
281 parse_events_terms__delete($2);
290 struct list_head *list;
293 err = parse_events_multi_pmu_add(_parse_state, $1, PERF_COUNT_HW_MAX, NULL, &list, &@1);
295 struct parse_events_state *parse_state = _parse_state;
296 struct parse_events_error *error = parse_state->error;
299 if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0)
301 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
315 value_sym '/' event_config '/'
317 struct list_head *list;
319 int config = $1 & 255;
321 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
326 err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
327 parse_events_terms__delete($3);
329 free_list_evsel(list);
335 value_sym sep_slash_slash_dc
337 struct list_head *list;
339 int config = $1 & 255;
340 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
346 err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
353 PE_LEGACY_CACHE opt_event_config
355 struct parse_events_state *parse_state = _parse_state;
356 struct list_head *list;
363 err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
365 parse_events_terms__delete($2);
368 free_list_evsel(list);
375 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
377 struct list_head *list;
384 err = parse_events_add_breakpoint(_parse_state, list,
386 parse_events_terms__delete($7);
395 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
397 struct list_head *list;
404 err = parse_events_add_breakpoint(_parse_state, list,
406 parse_events_terms__delete($5);
414 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
416 struct list_head *list;
423 err = parse_events_add_breakpoint(_parse_state, list,
425 parse_events_terms__delete($5);
434 PE_PREFIX_MEM PE_VALUE opt_event_config
436 struct list_head *list;
442 err = parse_events_add_breakpoint(_parse_state, list,
444 parse_events_terms__delete($3);
452 event_legacy_tracepoint:
453 tracepoint_name opt_event_config
455 struct parse_events_state *parse_state = _parse_state;
456 struct parse_events_error *error = parse_state->error;
457 struct list_head *list;
464 err = parse_events_add_tracepoint(parse_state, list, $1.sys, $1.event,
467 parse_events_terms__delete($2);
480 struct tracepoint_name tracepoint = {$1, $3};
485 event_legacy_numeric:
486 PE_VALUE ':' PE_VALUE opt_event_config
488 struct list_head *list;
494 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
496 parse_events_terms__delete($4);
505 PE_RAW opt_event_config
507 struct list_head *list;
515 num = strtoull($1 + 1, NULL, 16);
516 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
520 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
522 parse_events_terms__delete($2);
556 start_terms: event_config
558 struct parse_events_state *parse_state = _parse_state;
559 if (parse_state->terms) {
560 parse_events_terms__delete ($1);
563 parse_state->terms = $1;
567 event_config ',' event_term
569 struct parse_events_terms *head = $1;
570 struct parse_events_term *term = $3;
573 parse_events_term__delete(term);
576 list_add_tail(&term->list, &head->terms);
582 struct parse_events_terms *head = malloc(sizeof(*head));
583 struct parse_events_term *term = $1;
587 parse_events_terms__init(head);
588 list_add_tail(&term->list, &head->terms);
592 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
602 struct parse_events_term *term;
603 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
604 strdup("raw"), $1, &@1, &@1);
613 name_or_raw '=' name_or_raw
615 struct parse_events_term *term;
616 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
626 name_or_raw '=' PE_VALUE
628 struct parse_events_term *term;
629 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
630 $1, $3, /*novalue=*/false, &@1, &@3);
641 struct parse_events_term *term;
642 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
643 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
654 struct parse_events_term *term;
655 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
656 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
667 struct parse_events_term *term;
668 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
669 $1.str, $1.num & 255, /*novalue=*/false,
670 &@1, /*loc_val=*/NULL);
679 PE_TERM '=' name_or_raw
681 struct parse_events_term *term;
682 int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3);
693 struct parse_events_term *term;
694 int err = parse_events_term__term(&term, $1, $3, &@1, &@3);
704 struct parse_events_term *term;
705 int err = parse_events_term__num(&term, $1,
706 /*config=*/NULL, $3, /*novalue=*/false,
717 struct parse_events_term *term;
718 int err = parse_events_term__num(&term, $1,
719 /*config=*/NULL, /*num=*/1, /*novalue=*/true,
720 &@1, /*loc_val=*/NULL);
730 struct parse_events_term *term;
731 char *config = strdup($1);
736 err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL);
747 sep_slash_slash_dc: '/' '/' | ':' |
751 void parse_events_error(YYLTYPE *loc, void *_parse_state,
752 void *scanner __maybe_unused,
753 char const *msg __maybe_unused)
755 struct parse_events_state *parse_state = _parse_state;
757 if (!parse_state->error || !list_empty(&parse_state->error->list))
760 parse_events_error__handle(parse_state->error, loc->last_column,
761 strdup("Unrecognized input"), NULL);