Home | History | Annotate | Download | only in util
      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 "types.h"
     13 #include "util.h"
     14 #include "parse-events.h"
     15 #include "parse-events-bison.h"
     16 
     17 extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
     18 
     19 #define ABORT_ON(val) \
     20 do { \
     21 	if (val) \
     22 		YYABORT; \
     23 } while (0)
     24 
     25 #define ALLOC_LIST(list) \
     26 do { \
     27 	list = malloc(sizeof(*list)); \
     28 	ABORT_ON(!list);              \
     29 	INIT_LIST_HEAD(list);         \
     30 } while (0)
     31 
     32 static 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 %type <num> PE_VALUE
     51 %type <num> PE_VALUE_SYM_HW
     52 %type <num> PE_VALUE_SYM_SW
     53 %type <num> PE_RAW
     54 %type <num> PE_TERM
     55 %type <str> PE_NAME
     56 %type <str> PE_NAME_CACHE_TYPE
     57 %type <str> PE_NAME_CACHE_OP_RESULT
     58 %type <str> PE_MODIFIER_EVENT
     59 %type <str> PE_MODIFIER_BP
     60 %type <str> PE_EVENT_NAME
     61 %type <num> value_sym
     62 %type <head> event_config
     63 %type <term> event_term
     64 %type <head> event_pmu
     65 %type <head> event_legacy_symbol
     66 %type <head> event_legacy_cache
     67 %type <head> event_legacy_mem
     68 %type <head> event_legacy_tracepoint
     69 %type <head> event_legacy_numeric
     70 %type <head> event_legacy_raw
     71 %type <head> event_def
     72 %type <head> event_mod
     73 %type <head> event_name
     74 %type <head> event
     75 %type <head> events
     76 %type <head> group_def
     77 %type <head> group
     78 %type <head> groups
     79 
     80 %union
     81 {
     82 	char *str;
     83 	u64 num;
     84 	struct list_head *head;
     85 	struct parse_events_term *term;
     86 }
     87 %%
     88 
     89 start:
     90 PE_START_EVENTS start_events
     91 |
     92 PE_START_TERMS  start_terms
     93 
     94 start_events: groups
     95 {
     96 	struct parse_events_evlist *data = _data;
     97 
     98 	parse_events_update_lists($1, &data->list);
     99 }
    100 
    101 groups:
    102 groups ',' group
    103 {
    104 	struct list_head *list  = $1;
    105 	struct list_head *group = $3;
    106 
    107 	parse_events_update_lists(group, list);
    108 	$$ = list;
    109 }
    110 |
    111 groups ',' event
    112 {
    113 	struct list_head *list  = $1;
    114 	struct list_head *event = $3;
    115 
    116 	parse_events_update_lists(event, list);
    117 	$$ = list;
    118 }
    119 |
    120 group
    121 |
    122 event
    123 
    124 group:
    125 group_def ':' PE_MODIFIER_EVENT
    126 {
    127 	struct list_head *list = $1;
    128 
    129 	ABORT_ON(parse_events__modifier_group(list, $3));
    130 	$$ = list;
    131 }
    132 |
    133 group_def
    134 
    135 group_def:
    136 PE_NAME '{' events '}'
    137 {
    138 	struct list_head *list = $3;
    139 
    140 	inc_group_count(list, _data);
    141 	parse_events__set_leader($1, list);
    142 	$$ = list;
    143 }
    144 |
    145 '{' events '}'
    146 {
    147 	struct list_head *list = $2;
    148 
    149 	inc_group_count(list, _data);
    150 	parse_events__set_leader(NULL, list);
    151 	$$ = list;
    152 }
    153 
    154 events:
    155 events ',' event
    156 {
    157 	struct list_head *event = $3;
    158 	struct list_head *list  = $1;
    159 
    160 	parse_events_update_lists(event, list);
    161 	$$ = list;
    162 }
    163 |
    164 event
    165 
    166 event: event_mod
    167 
    168 event_mod:
    169 event_name PE_MODIFIER_EVENT
    170 {
    171 	struct list_head *list = $1;
    172 
    173 	/*
    174 	 * Apply modifier on all events added by single event definition
    175 	 * (there could be more events added for multiple tracepoint
    176 	 * definitions via '*?'.
    177 	 */
    178 	ABORT_ON(parse_events__modifier_event(list, $2, false));
    179 	$$ = list;
    180 }
    181 |
    182 event_name
    183 
    184 event_name:
    185 PE_EVENT_NAME event_def
    186 {
    187 	ABORT_ON(parse_events_name($2, $1));
    188 	free($1);
    189 	$$ = $2;
    190 }
    191 |
    192 event_def
    193 
    194 event_def: event_pmu |
    195 	   event_legacy_symbol |
    196 	   event_legacy_cache sep_dc |
    197 	   event_legacy_mem |
    198 	   event_legacy_tracepoint sep_dc |
    199 	   event_legacy_numeric sep_dc |
    200 	   event_legacy_raw sep_dc
    201 
    202 event_pmu:
    203 PE_NAME '/' event_config '/'
    204 {
    205 	struct parse_events_evlist *data = _data;
    206 	struct list_head *list;
    207 
    208 	ALLOC_LIST(list);
    209 	ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, $3));
    210 	parse_events__free_terms($3);
    211 	$$ = list;
    212 }
    213 
    214 value_sym:
    215 PE_VALUE_SYM_HW
    216 |
    217 PE_VALUE_SYM_SW
    218 
    219 event_legacy_symbol:
    220 value_sym '/' event_config '/'
    221 {
    222 	struct parse_events_evlist *data = _data;
    223 	struct list_head *list;
    224 	int type = $1 >> 16;
    225 	int config = $1 & 255;
    226 
    227 	ALLOC_LIST(list);
    228 	ABORT_ON(parse_events_add_numeric(list, &data->idx,
    229 					  type, config, $3));
    230 	parse_events__free_terms($3);
    231 	$$ = list;
    232 }
    233 |
    234 value_sym sep_slash_dc
    235 {
    236 	struct parse_events_evlist *data = _data;
    237 	struct list_head *list;
    238 	int type = $1 >> 16;
    239 	int config = $1 & 255;
    240 
    241 	ALLOC_LIST(list);
    242 	ABORT_ON(parse_events_add_numeric(list, &data->idx,
    243 					  type, config, NULL));
    244 	$$ = list;
    245 }
    246 
    247 event_legacy_cache:
    248 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
    249 {
    250 	struct parse_events_evlist *data = _data;
    251 	struct list_head *list;
    252 
    253 	ALLOC_LIST(list);
    254 	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5));
    255 	$$ = list;
    256 }
    257 |
    258 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
    259 {
    260 	struct parse_events_evlist *data = _data;
    261 	struct list_head *list;
    262 
    263 	ALLOC_LIST(list);
    264 	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL));
    265 	$$ = list;
    266 }
    267 |
    268 PE_NAME_CACHE_TYPE
    269 {
    270 	struct parse_events_evlist *data = _data;
    271 	struct list_head *list;
    272 
    273 	ALLOC_LIST(list);
    274 	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL));
    275 	$$ = list;
    276 }
    277 
    278 event_legacy_mem:
    279 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
    280 {
    281 	struct parse_events_evlist *data = _data;
    282 	struct list_head *list;
    283 
    284 	ALLOC_LIST(list);
    285 	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
    286 					     (void *) $2, $4));
    287 	$$ = list;
    288 }
    289 |
    290 PE_PREFIX_MEM PE_VALUE sep_dc
    291 {
    292 	struct parse_events_evlist *data = _data;
    293 	struct list_head *list;
    294 
    295 	ALLOC_LIST(list);
    296 	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
    297 					     (void *) $2, NULL));
    298 	$$ = list;
    299 }
    300 
    301 event_legacy_tracepoint:
    302 PE_NAME ':' PE_NAME
    303 {
    304 	struct parse_events_evlist *data = _data;
    305 	struct list_head *list;
    306 
    307 	ALLOC_LIST(list);
    308 	ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3));
    309 	$$ = list;
    310 }
    311 
    312 event_legacy_numeric:
    313 PE_VALUE ':' PE_VALUE
    314 {
    315 	struct parse_events_evlist *data = _data;
    316 	struct list_head *list;
    317 
    318 	ALLOC_LIST(list);
    319 	ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL));
    320 	$$ = list;
    321 }
    322 
    323 event_legacy_raw:
    324 PE_RAW
    325 {
    326 	struct parse_events_evlist *data = _data;
    327 	struct list_head *list;
    328 
    329 	ALLOC_LIST(list);
    330 	ABORT_ON(parse_events_add_numeric(list, &data->idx,
    331 					  PERF_TYPE_RAW, $1, NULL));
    332 	$$ = list;
    333 }
    334 
    335 start_terms: event_config
    336 {
    337 	struct parse_events_terms *data = _data;
    338 	data->terms = $1;
    339 }
    340 
    341 event_config:
    342 event_config ',' event_term
    343 {
    344 	struct list_head *head = $1;
    345 	struct parse_events_term *term = $3;
    346 
    347 	ABORT_ON(!head);
    348 	list_add_tail(&term->list, head);
    349 	$$ = $1;
    350 }
    351 |
    352 event_term
    353 {
    354 	struct list_head *head = malloc(sizeof(*head));
    355 	struct parse_events_term *term = $1;
    356 
    357 	ABORT_ON(!head);
    358 	INIT_LIST_HEAD(head);
    359 	list_add_tail(&term->list, head);
    360 	$$ = head;
    361 }
    362 
    363 event_term:
    364 PE_NAME '=' PE_NAME
    365 {
    366 	struct parse_events_term *term;
    367 
    368 	ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
    369 					$1, $3));
    370 	$$ = term;
    371 }
    372 |
    373 PE_NAME '=' PE_VALUE
    374 {
    375 	struct parse_events_term *term;
    376 
    377 	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
    378 					$1, $3));
    379 	$$ = term;
    380 }
    381 |
    382 PE_NAME '=' PE_VALUE_SYM_HW
    383 {
    384 	struct parse_events_term *term;
    385 	int config = $3 & 255;
    386 
    387 	ABORT_ON(parse_events_term__sym_hw(&term, $1, config));
    388 	$$ = term;
    389 }
    390 |
    391 PE_NAME
    392 {
    393 	struct parse_events_term *term;
    394 
    395 	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
    396 					$1, 1));
    397 	$$ = term;
    398 }
    399 |
    400 PE_VALUE_SYM_HW
    401 {
    402 	struct parse_events_term *term;
    403 	int config = $1 & 255;
    404 
    405 	ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
    406 	$$ = term;
    407 }
    408 |
    409 PE_TERM '=' PE_NAME
    410 {
    411 	struct parse_events_term *term;
    412 
    413 	ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3));
    414 	$$ = term;
    415 }
    416 |
    417 PE_TERM '=' PE_VALUE
    418 {
    419 	struct parse_events_term *term;
    420 
    421 	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3));
    422 	$$ = term;
    423 }
    424 |
    425 PE_TERM
    426 {
    427 	struct parse_events_term *term;
    428 
    429 	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1));
    430 	$$ = term;
    431 }
    432 
    433 sep_dc: ':' |
    434 
    435 sep_slash_dc: '/' | ':' |
    436 
    437 %%
    438 
    439 void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused,
    440 			char const *msg __maybe_unused)
    441 {
    442 }
    443