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
);