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