Back to home page

OSCL-LXR

 
 

    


0001 %define api.pure full
0002 %parse-param {void *_parse_state}
0003 %parse-param {void *scanner}
0004 %lex-param {void* scanner}
0005 %locations
0006 
0007 %{
0008 
0009 #define YYDEBUG 1
0010 
0011 #include <fnmatch.h>
0012 #include <stdio.h>
0013 #include <linux/compiler.h>
0014 #include <linux/types.h>
0015 #include <linux/zalloc.h>
0016 #include "pmu.h"
0017 #include "evsel.h"
0018 #include "parse-events.h"
0019 #include "parse-events-bison.h"
0020 
0021 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
0022 
0023 #define ABORT_ON(val) \
0024 do { \
0025         if (val) \
0026                 YYABORT; \
0027 } while (0)
0028 
0029 static struct list_head* alloc_list(void)
0030 {
0031         struct list_head *list;
0032 
0033         list = malloc(sizeof(*list));
0034         if (!list)
0035                 return NULL;
0036 
0037         INIT_LIST_HEAD(list);
0038         return list;
0039 }
0040 
0041 static void free_list_evsel(struct list_head* list_evsel)
0042 {
0043         struct evsel *evsel, *tmp;
0044 
0045         list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
0046                 list_del_init(&evsel->core.node);
0047                 evsel__delete(evsel);
0048         }
0049         free(list_evsel);
0050 }
0051 
0052 static void inc_group_count(struct list_head *list,
0053                        struct parse_events_state *parse_state)
0054 {
0055         /* Count groups only have more than 1 members */
0056         if (!list_is_last(list->next, list))
0057                 parse_state->nr_groups++;
0058 }
0059 
0060 %}
0061 
0062 %token PE_START_EVENTS PE_START_TERMS
0063 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
0064 %token PE_VALUE_SYM_TOOL
0065 %token PE_EVENT_NAME
0066 %token PE_NAME
0067 %token PE_BPF_OBJECT PE_BPF_SOURCE
0068 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
0069 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
0070 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
0071 %token PE_ERROR
0072 %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_PMU_EVENT_SUF2 PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE
0073 %token PE_ARRAY_ALL PE_ARRAY_RANGE
0074 %token PE_DRV_CFG_TERM
0075 %type <num> PE_VALUE
0076 %type <num> PE_VALUE_SYM_HW
0077 %type <num> PE_VALUE_SYM_SW
0078 %type <num> PE_VALUE_SYM_TOOL
0079 %type <num> PE_RAW
0080 %type <num> PE_TERM
0081 %type <num> value_sym
0082 %type <str> PE_NAME
0083 %type <str> PE_BPF_OBJECT
0084 %type <str> PE_BPF_SOURCE
0085 %type <str> PE_NAME_CACHE_TYPE
0086 %type <str> PE_NAME_CACHE_OP_RESULT
0087 %type <str> PE_MODIFIER_EVENT
0088 %type <str> PE_MODIFIER_BP
0089 %type <str> PE_EVENT_NAME
0090 %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_PMU_EVENT_SUF2 PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE
0091 %type <str> PE_DRV_CFG_TERM
0092 %type <str> event_pmu_name
0093 %destructor { free ($$); } <str>
0094 %type <term> event_term
0095 %destructor { parse_events_term__delete ($$); } <term>
0096 %type <list_terms> event_config
0097 %type <list_terms> opt_event_config
0098 %type <list_terms> opt_pmu_config
0099 %destructor { parse_events_terms__delete ($$); } <list_terms>
0100 %type <list_evsel> event_pmu
0101 %type <list_evsel> event_legacy_symbol
0102 %type <list_evsel> event_legacy_cache
0103 %type <list_evsel> event_legacy_mem
0104 %type <list_evsel> event_legacy_tracepoint
0105 %type <list_evsel> event_legacy_numeric
0106 %type <list_evsel> event_legacy_raw
0107 %type <list_evsel> event_bpf_file
0108 %type <list_evsel> event_def
0109 %type <list_evsel> event_mod
0110 %type <list_evsel> event_name
0111 %type <list_evsel> event
0112 %type <list_evsel> events
0113 %type <list_evsel> group_def
0114 %type <list_evsel> group
0115 %type <list_evsel> groups
0116 %destructor { free_list_evsel ($$); } <list_evsel>
0117 %type <tracepoint_name> tracepoint_name
0118 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
0119 %type <array> array
0120 %type <array> array_term
0121 %type <array> array_terms
0122 %destructor { free ($$.ranges); } <array>
0123 
0124 %union
0125 {
0126         char *str;
0127         u64 num;
0128         struct list_head *list_evsel;
0129         struct list_head *list_terms;
0130         struct parse_events_term *term;
0131         struct tracepoint_name {
0132                 char *sys;
0133                 char *event;
0134         } tracepoint_name;
0135         struct parse_events_array array;
0136 }
0137 %%
0138 
0139 start:
0140 PE_START_EVENTS start_events
0141 |
0142 PE_START_TERMS  start_terms
0143 
0144 start_events: groups
0145 {
0146         struct parse_events_state *parse_state = _parse_state;
0147 
0148         /* frees $1 */
0149         parse_events_update_lists($1, &parse_state->list);
0150 }
0151 
0152 groups:
0153 groups ',' group
0154 {
0155         struct list_head *list  = $1;
0156         struct list_head *group = $3;
0157 
0158         /* frees $3 */
0159         parse_events_update_lists(group, list);
0160         $$ = list;
0161 }
0162 |
0163 groups ',' event
0164 {
0165         struct list_head *list  = $1;
0166         struct list_head *event = $3;
0167 
0168         /* frees $3 */
0169         parse_events_update_lists(event, list);
0170         $$ = list;
0171 }
0172 |
0173 group
0174 |
0175 event
0176 
0177 group:
0178 group_def ':' PE_MODIFIER_EVENT
0179 {
0180         struct list_head *list = $1;
0181         int err;
0182 
0183         err = parse_events__modifier_group(list, $3);
0184         free($3);
0185         if (err) {
0186                 struct parse_events_state *parse_state = _parse_state;
0187                 struct parse_events_error *error = parse_state->error;
0188 
0189                 parse_events_error__handle(error, @3.first_column,
0190                                            strdup("Bad modifier"), NULL);
0191                 free_list_evsel(list);
0192                 YYABORT;
0193         }
0194         $$ = list;
0195 }
0196 |
0197 group_def
0198 
0199 group_def:
0200 PE_NAME '{' events '}'
0201 {
0202         struct list_head *list = $3;
0203 
0204         inc_group_count(list, _parse_state);
0205         parse_events__set_leader($1, list, _parse_state);
0206         free($1);
0207         $$ = list;
0208 }
0209 |
0210 '{' events '}'
0211 {
0212         struct list_head *list = $2;
0213 
0214         inc_group_count(list, _parse_state);
0215         parse_events__set_leader(NULL, list, _parse_state);
0216         $$ = list;
0217 }
0218 
0219 events:
0220 events ',' event
0221 {
0222         struct list_head *event = $3;
0223         struct list_head *list  = $1;
0224 
0225         /* frees $3 */
0226         parse_events_update_lists(event, list);
0227         $$ = list;
0228 }
0229 |
0230 event
0231 
0232 event: event_mod
0233 
0234 event_mod:
0235 event_name PE_MODIFIER_EVENT
0236 {
0237         struct list_head *list = $1;
0238         int err;
0239 
0240         /*
0241          * Apply modifier on all events added by single event definition
0242          * (there could be more events added for multiple tracepoint
0243          * definitions via '*?'.
0244          */
0245         err = parse_events__modifier_event(list, $2, false);
0246         free($2);
0247         if (err) {
0248                 struct parse_events_state *parse_state = _parse_state;
0249                 struct parse_events_error *error = parse_state->error;
0250 
0251                 parse_events_error__handle(error, @2.first_column,
0252                                            strdup("Bad modifier"), NULL);
0253                 free_list_evsel(list);
0254                 YYABORT;
0255         }
0256         $$ = list;
0257 }
0258 |
0259 event_name
0260 
0261 event_name:
0262 PE_EVENT_NAME event_def
0263 {
0264         int err;
0265 
0266         err = parse_events_name($2, $1);
0267         free($1);
0268         if (err) {
0269                 free_list_evsel($2);
0270                 YYABORT;
0271         }
0272         $$ = $2;
0273 }
0274 |
0275 event_def
0276 
0277 event_def: event_pmu |
0278            event_legacy_symbol |
0279            event_legacy_cache sep_dc |
0280            event_legacy_mem |
0281            event_legacy_tracepoint sep_dc |
0282            event_legacy_numeric sep_dc |
0283            event_legacy_raw sep_dc |
0284            event_bpf_file
0285 
0286 event_pmu_name:
0287 PE_NAME | PE_PMU_EVENT_PRE
0288 
0289 event_pmu:
0290 event_pmu_name opt_pmu_config
0291 {
0292         struct parse_events_state *parse_state = _parse_state;
0293         struct parse_events_error *error = parse_state->error;
0294         struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL;
0295         char *pattern = NULL;
0296 
0297 #define CLEANUP_YYABORT                                 \
0298         do {                                            \
0299                 parse_events_terms__delete($2);         \
0300                 parse_events_terms__delete(orig_terms); \
0301                 free(list);                             \
0302                 free($1);                               \
0303                 free(pattern);                          \
0304                 YYABORT;                                \
0305         } while(0)
0306 
0307         if (parse_events_copy_term_list($2, &orig_terms))
0308                 CLEANUP_YYABORT;
0309 
0310         if (error)
0311                 error->idx = @1.first_column;
0312 
0313         list = alloc_list();
0314         if (!list)
0315                 CLEANUP_YYABORT;
0316         if (parse_events_add_pmu(_parse_state, list, $1, $2, false, false)) {
0317                 struct perf_pmu *pmu = NULL;
0318                 int ok = 0;
0319 
0320                 if (asprintf(&pattern, "%s*", $1) < 0)
0321                         CLEANUP_YYABORT;
0322 
0323                 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
0324                         char *name = pmu->name;
0325 
0326                         if (!strncmp(name, "uncore_", 7) &&
0327                             strncmp($1, "uncore_", 7))
0328                                 name += 7;
0329                         if (!perf_pmu__match(pattern, name, $1) ||
0330                             !perf_pmu__match(pattern, pmu->alias_name, $1)) {
0331                                 if (parse_events_copy_term_list(orig_terms, &terms))
0332                                         CLEANUP_YYABORT;
0333                                 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false))
0334                                         ok++;
0335                                 parse_events_terms__delete(terms);
0336                         }
0337                 }
0338 
0339                 if (!ok)
0340                         CLEANUP_YYABORT;
0341         }
0342         parse_events_terms__delete($2);
0343         parse_events_terms__delete(orig_terms);
0344         free(pattern);
0345         free($1);
0346         $$ = list;
0347 #undef CLEANUP_YYABORT
0348 }
0349 |
0350 PE_KERNEL_PMU_EVENT sep_dc
0351 {
0352         struct list_head *list;
0353         int err;
0354 
0355         err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list);
0356         free($1);
0357         if (err < 0)
0358                 YYABORT;
0359         $$ = list;
0360 }
0361 |
0362 PE_KERNEL_PMU_EVENT opt_pmu_config
0363 {
0364         struct list_head *list;
0365         int err;
0366 
0367         /* frees $2 */
0368         err = parse_events_multi_pmu_add(_parse_state, $1, $2, &list);
0369         free($1);
0370         if (err < 0)
0371                 YYABORT;
0372         $$ = list;
0373 }
0374 |
0375 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF '-' PE_PMU_EVENT_SUF2 sep_dc
0376 {
0377         struct list_head *list;
0378         char pmu_name[128];
0379         snprintf(pmu_name, sizeof(pmu_name), "%s-%s-%s", $1, $3, $5);
0380         free($1);
0381         free($3);
0382         free($5);
0383         if (parse_events_multi_pmu_add(_parse_state, pmu_name, NULL, &list) < 0)
0384                 YYABORT;
0385         $$ = list;
0386 }
0387 |
0388 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
0389 {
0390         struct list_head *list;
0391         char pmu_name[128];
0392 
0393         snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3);
0394         free($1);
0395         free($3);
0396         if (parse_events_multi_pmu_add(_parse_state, pmu_name, NULL, &list) < 0)
0397                 YYABORT;
0398         $$ = list;
0399 }
0400 |
0401 PE_PMU_EVENT_FAKE sep_dc
0402 {
0403         struct list_head *list;
0404         int err;
0405 
0406         list = alloc_list();
0407         if (!list)
0408                 YYABORT;
0409 
0410         err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, false);
0411         free($1);
0412         if (err < 0) {
0413                 free(list);
0414                 YYABORT;
0415         }
0416         $$ = list;
0417 }
0418 |
0419 PE_PMU_EVENT_FAKE opt_pmu_config
0420 {
0421         struct list_head *list;
0422         int err;
0423 
0424         list = alloc_list();
0425         if (!list)
0426                 YYABORT;
0427 
0428         err = parse_events_add_pmu(_parse_state, list, $1, $2, false, false);
0429         free($1);
0430         parse_events_terms__delete($2);
0431         if (err < 0) {
0432                 free(list);
0433                 YYABORT;
0434         }
0435         $$ = list;
0436 }
0437 
0438 value_sym:
0439 PE_VALUE_SYM_HW
0440 |
0441 PE_VALUE_SYM_SW
0442 
0443 event_legacy_symbol:
0444 value_sym '/' event_config '/'
0445 {
0446         struct list_head *list;
0447         int type = $1 >> 16;
0448         int config = $1 & 255;
0449         int err;
0450 
0451         list = alloc_list();
0452         ABORT_ON(!list);
0453         err = parse_events_add_numeric(_parse_state, list, type, config, $3);
0454         parse_events_terms__delete($3);
0455         if (err) {
0456                 free_list_evsel(list);
0457                 YYABORT;
0458         }
0459         $$ = list;
0460 }
0461 |
0462 value_sym sep_slash_slash_dc
0463 {
0464         struct list_head *list;
0465         int type = $1 >> 16;
0466         int config = $1 & 255;
0467 
0468         list = alloc_list();
0469         ABORT_ON(!list);
0470         ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, NULL));
0471         $$ = list;
0472 }
0473 |
0474 PE_VALUE_SYM_TOOL sep_slash_slash_dc
0475 {
0476         struct list_head *list;
0477 
0478         list = alloc_list();
0479         ABORT_ON(!list);
0480         ABORT_ON(parse_events_add_tool(_parse_state, list, $1));
0481         $$ = list;
0482 }
0483 
0484 event_legacy_cache:
0485 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config
0486 {
0487         struct parse_events_state *parse_state = _parse_state;
0488         struct parse_events_error *error = parse_state->error;
0489         struct list_head *list;
0490         int err;
0491 
0492         list = alloc_list();
0493         ABORT_ON(!list);
0494         err = parse_events_add_cache(list, &parse_state->idx, $1, $3, $5, error, $6,
0495                                      parse_state);
0496         parse_events_terms__delete($6);
0497         free($1);
0498         free($3);
0499         free($5);
0500         if (err) {
0501                 free_list_evsel(list);
0502                 YYABORT;
0503         }
0504         $$ = list;
0505 }
0506 |
0507 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config
0508 {
0509         struct parse_events_state *parse_state = _parse_state;
0510         struct parse_events_error *error = parse_state->error;
0511         struct list_head *list;
0512         int err;
0513 
0514         list = alloc_list();
0515         ABORT_ON(!list);
0516         err = parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4,
0517                                      parse_state);
0518         parse_events_terms__delete($4);
0519         free($1);
0520         free($3);
0521         if (err) {
0522                 free_list_evsel(list);
0523                 YYABORT;
0524         }
0525         $$ = list;
0526 }
0527 |
0528 PE_NAME_CACHE_TYPE opt_event_config
0529 {
0530         struct parse_events_state *parse_state = _parse_state;
0531         struct parse_events_error *error = parse_state->error;
0532         struct list_head *list;
0533         int err;
0534 
0535         list = alloc_list();
0536         ABORT_ON(!list);
0537         err = parse_events_add_cache(list, &parse_state->idx, $1, NULL, NULL, error, $2,
0538                                      parse_state);
0539         parse_events_terms__delete($2);
0540         free($1);
0541         if (err) {
0542                 free_list_evsel(list);
0543                 YYABORT;
0544         }
0545         $$ = list;
0546 }
0547 
0548 event_legacy_mem:
0549 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
0550 {
0551         struct parse_events_state *parse_state = _parse_state;
0552         struct list_head *list;
0553         int err;
0554 
0555         list = alloc_list();
0556         ABORT_ON(!list);
0557         err = parse_events_add_breakpoint(list, &parse_state->idx,
0558                                           $2, $6, $4);
0559         free($6);
0560         if (err) {
0561                 free(list);
0562                 YYABORT;
0563         }
0564         $$ = list;
0565 }
0566 |
0567 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
0568 {
0569         struct parse_events_state *parse_state = _parse_state;
0570         struct list_head *list;
0571 
0572         list = alloc_list();
0573         ABORT_ON(!list);
0574         if (parse_events_add_breakpoint(list, &parse_state->idx,
0575                                         $2, NULL, $4)) {
0576                 free(list);
0577                 YYABORT;
0578         }
0579         $$ = list;
0580 }
0581 |
0582 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
0583 {
0584         struct parse_events_state *parse_state = _parse_state;
0585         struct list_head *list;
0586         int err;
0587 
0588         list = alloc_list();
0589         ABORT_ON(!list);
0590         err = parse_events_add_breakpoint(list, &parse_state->idx,
0591                                           $2, $4, 0);
0592         free($4);
0593         if (err) {
0594                 free(list);
0595                 YYABORT;
0596         }
0597         $$ = list;
0598 }
0599 |
0600 PE_PREFIX_MEM PE_VALUE sep_dc
0601 {
0602         struct parse_events_state *parse_state = _parse_state;
0603         struct list_head *list;
0604 
0605         list = alloc_list();
0606         ABORT_ON(!list);
0607         if (parse_events_add_breakpoint(list, &parse_state->idx,
0608                                         $2, NULL, 0)) {
0609                 free(list);
0610                 YYABORT;
0611         }
0612         $$ = list;
0613 }
0614 
0615 event_legacy_tracepoint:
0616 tracepoint_name opt_event_config
0617 {
0618         struct parse_events_state *parse_state = _parse_state;
0619         struct parse_events_error *error = parse_state->error;
0620         struct list_head *list;
0621         int err;
0622 
0623         list = alloc_list();
0624         ABORT_ON(!list);
0625         if (error)
0626                 error->idx = @1.first_column;
0627 
0628         err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event,
0629                                         error, $2);
0630 
0631         parse_events_terms__delete($2);
0632         free($1.sys);
0633         free($1.event);
0634         if (err) {
0635                 free(list);
0636                 YYABORT;
0637         }
0638         $$ = list;
0639 }
0640 
0641 tracepoint_name:
0642 PE_NAME '-' PE_NAME ':' PE_NAME
0643 {
0644         struct tracepoint_name tracepoint;
0645 
0646         ABORT_ON(asprintf(&tracepoint.sys, "%s-%s", $1, $3) < 0);
0647         tracepoint.event = $5;
0648         free($1);
0649         free($3);
0650         $$ = tracepoint;
0651 }
0652 |
0653 PE_NAME ':' PE_NAME
0654 {
0655         struct tracepoint_name tracepoint = {$1, $3};
0656 
0657         $$ = tracepoint;
0658 }
0659 
0660 event_legacy_numeric:
0661 PE_VALUE ':' PE_VALUE opt_event_config
0662 {
0663         struct list_head *list;
0664         int err;
0665 
0666         list = alloc_list();
0667         ABORT_ON(!list);
0668         err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4);
0669         parse_events_terms__delete($4);
0670         if (err) {
0671                 free(list);
0672                 YYABORT;
0673         }
0674         $$ = list;
0675 }
0676 
0677 event_legacy_raw:
0678 PE_RAW opt_event_config
0679 {
0680         struct list_head *list;
0681         int err;
0682 
0683         list = alloc_list();
0684         ABORT_ON(!list);
0685         err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2);
0686         parse_events_terms__delete($2);
0687         if (err) {
0688                 free(list);
0689                 YYABORT;
0690         }
0691         $$ = list;
0692 }
0693 
0694 event_bpf_file:
0695 PE_BPF_OBJECT opt_event_config
0696 {
0697         struct parse_events_state *parse_state = _parse_state;
0698         struct list_head *list;
0699         int err;
0700 
0701         list = alloc_list();
0702         ABORT_ON(!list);
0703         err = parse_events_load_bpf(parse_state, list, $1, false, $2);
0704         parse_events_terms__delete($2);
0705         free($1);
0706         if (err) {
0707                 free(list);
0708                 YYABORT;
0709         }
0710         $$ = list;
0711 }
0712 |
0713 PE_BPF_SOURCE opt_event_config
0714 {
0715         struct list_head *list;
0716         int err;
0717 
0718         list = alloc_list();
0719         ABORT_ON(!list);
0720         err = parse_events_load_bpf(_parse_state, list, $1, true, $2);
0721         parse_events_terms__delete($2);
0722         if (err) {
0723                 free(list);
0724                 YYABORT;
0725         }
0726         $$ = list;
0727 }
0728 
0729 opt_event_config:
0730 '/' event_config '/'
0731 {
0732         $$ = $2;
0733 }
0734 |
0735 '/' '/'
0736 {
0737         $$ = NULL;
0738 }
0739 |
0740 {
0741         $$ = NULL;
0742 }
0743 
0744 opt_pmu_config:
0745 '/' event_config '/'
0746 {
0747         $$ = $2;
0748 }
0749 |
0750 '/' '/'
0751 {
0752         $$ = NULL;
0753 }
0754 
0755 start_terms: event_config
0756 {
0757         struct parse_events_state *parse_state = _parse_state;
0758         if (parse_state->terms) {
0759                 parse_events_terms__delete ($1);
0760                 YYABORT;
0761         }
0762         parse_state->terms = $1;
0763 }
0764 
0765 event_config:
0766 event_config ',' event_term
0767 {
0768         struct list_head *head = $1;
0769         struct parse_events_term *term = $3;
0770 
0771         if (!head) {
0772                 parse_events_term__delete(term);
0773                 YYABORT;
0774         }
0775         list_add_tail(&term->list, head);
0776         $$ = $1;
0777 }
0778 |
0779 event_term
0780 {
0781         struct list_head *head = malloc(sizeof(*head));
0782         struct parse_events_term *term = $1;
0783 
0784         ABORT_ON(!head);
0785         INIT_LIST_HEAD(head);
0786         list_add_tail(&term->list, head);
0787         $$ = head;
0788 }
0789 
0790 event_term:
0791 PE_RAW
0792 {
0793         struct parse_events_term *term;
0794 
0795         ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_CONFIG,
0796                                         NULL, $1, false, &@1, NULL));
0797         $$ = term;
0798 }
0799 |
0800 PE_NAME '=' PE_NAME
0801 {
0802         struct parse_events_term *term;
0803 
0804         if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
0805                                         $1, $3, &@1, &@3)) {
0806                 free($1);
0807                 free($3);
0808                 YYABORT;
0809         }
0810         $$ = term;
0811 }
0812 |
0813 PE_NAME '=' PE_VALUE
0814 {
0815         struct parse_events_term *term;
0816 
0817         if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
0818                                         $1, $3, false, &@1, &@3)) {
0819                 free($1);
0820                 YYABORT;
0821         }
0822         $$ = term;
0823 }
0824 |
0825 PE_NAME '=' PE_VALUE_SYM_HW
0826 {
0827         struct parse_events_term *term;
0828         int config = $3 & 255;
0829 
0830         if (parse_events_term__sym_hw(&term, $1, config)) {
0831                 free($1);
0832                 YYABORT;
0833         }
0834         $$ = term;
0835 }
0836 |
0837 PE_NAME
0838 {
0839         struct parse_events_term *term;
0840 
0841         if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
0842                                         $1, 1, true, &@1, NULL)) {
0843                 free($1);
0844                 YYABORT;
0845         }
0846         $$ = term;
0847 }
0848 |
0849 PE_VALUE_SYM_HW
0850 {
0851         struct parse_events_term *term;
0852         int config = $1 & 255;
0853 
0854         ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
0855         $$ = term;
0856 }
0857 |
0858 PE_TERM '=' PE_NAME
0859 {
0860         struct parse_events_term *term;
0861 
0862         if (parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3)) {
0863                 free($3);
0864                 YYABORT;
0865         }
0866         $$ = term;
0867 }
0868 |
0869 PE_TERM '=' PE_VALUE
0870 {
0871         struct parse_events_term *term;
0872 
0873         ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3));
0874         $$ = term;
0875 }
0876 |
0877 PE_TERM
0878 {
0879         struct parse_events_term *term;
0880 
0881         ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL));
0882         $$ = term;
0883 }
0884 |
0885 PE_NAME array '=' PE_NAME
0886 {
0887         struct parse_events_term *term;
0888 
0889         if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
0890                                         $1, $4, &@1, &@4)) {
0891                 free($1);
0892                 free($4);
0893                 free($2.ranges);
0894                 YYABORT;
0895         }
0896         term->array = $2;
0897         $$ = term;
0898 }
0899 |
0900 PE_NAME array '=' PE_VALUE
0901 {
0902         struct parse_events_term *term;
0903 
0904         if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
0905                                         $1, $4, false, &@1, &@4)) {
0906                 free($1);
0907                 free($2.ranges);
0908                 YYABORT;
0909         }
0910         term->array = $2;
0911         $$ = term;
0912 }
0913 |
0914 PE_DRV_CFG_TERM
0915 {
0916         struct parse_events_term *term;
0917         char *config = strdup($1);
0918 
0919         ABORT_ON(!config);
0920         if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG,
0921                                         config, $1, &@1, NULL)) {
0922                 free($1);
0923                 free(config);
0924                 YYABORT;
0925         }
0926         $$ = term;
0927 }
0928 
0929 array:
0930 '[' array_terms ']'
0931 {
0932         $$ = $2;
0933 }
0934 |
0935 PE_ARRAY_ALL
0936 {
0937         $$.nr_ranges = 0;
0938         $$.ranges = NULL;
0939 }
0940 
0941 array_terms:
0942 array_terms ',' array_term
0943 {
0944         struct parse_events_array new_array;
0945 
0946         new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges;
0947         new_array.ranges = realloc($1.ranges,
0948                                 sizeof(new_array.ranges[0]) *
0949                                 new_array.nr_ranges);
0950         ABORT_ON(!new_array.ranges);
0951         memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges,
0952                $3.nr_ranges * sizeof(new_array.ranges[0]));
0953         free($3.ranges);
0954         $$ = new_array;
0955 }
0956 |
0957 array_term
0958 
0959 array_term:
0960 PE_VALUE
0961 {
0962         struct parse_events_array array;
0963 
0964         array.nr_ranges = 1;
0965         array.ranges = malloc(sizeof(array.ranges[0]));
0966         ABORT_ON(!array.ranges);
0967         array.ranges[0].start = $1;
0968         array.ranges[0].length = 1;
0969         $$ = array;
0970 }
0971 |
0972 PE_VALUE PE_ARRAY_RANGE PE_VALUE
0973 {
0974         struct parse_events_array array;
0975 
0976         ABORT_ON($3 < $1);
0977         array.nr_ranges = 1;
0978         array.ranges = malloc(sizeof(array.ranges[0]));
0979         ABORT_ON(!array.ranges);
0980         array.ranges[0].start = $1;
0981         array.ranges[0].length = $3 - $1 + 1;
0982         $$ = array;
0983 }
0984 
0985 sep_dc: ':' |
0986 
0987 sep_slash_slash_dc: '/' '/' | ':' |
0988 
0989 %%
0990 
0991 void parse_events_error(YYLTYPE *loc, void *parse_state,
0992                         void *scanner __maybe_unused,
0993                         char const *msg __maybe_unused)
0994 {
0995         parse_events_evlist_error(parse_state, loc->last_column, "parser error");
0996 }