c3517e3498d7be29977bf8626fc879f8d91f8698
[platform/kernel/linux-starfive.git] / tools / perf / util / parse-events.y
1 %define api.pure full
2 %parse-param {void *_parse_state}
3 %parse-param {void *scanner}
4 %lex-param {void* scanner}
5 %locations
6
7 %{
8
9 #define YYDEBUG 1
10
11 #include <errno.h>
12 #include <fnmatch.h>
13 #include <stdio.h>
14 #include <linux/compiler.h>
15 #include <linux/types.h>
16 #include <linux/zalloc.h>
17 #include "pmu.h"
18 #include "pmus.h"
19 #include "evsel.h"
20 #include "parse-events.h"
21 #include "parse-events-bison.h"
22
23 int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner);
24 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
25
26 #define PE_ABORT(val) \
27 do { \
28         if (val == -ENOMEM) \
29                 YYNOMEM; \
30         YYABORT; \
31 } while (0)
32
33 static struct list_head* alloc_list(void)
34 {
35         struct list_head *list;
36
37         list = malloc(sizeof(*list));
38         if (!list)
39                 return NULL;
40
41         INIT_LIST_HEAD(list);
42         return list;
43 }
44
45 static void free_list_evsel(struct list_head* list_evsel)
46 {
47         struct evsel *evsel, *tmp;
48
49         list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
50                 list_del_init(&evsel->core.node);
51                 evsel__delete(evsel);
52         }
53         free(list_evsel);
54 }
55
56 %}
57
58 %token PE_START_EVENTS PE_START_TERMS
59 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
60 %token PE_VALUE_SYM_TOOL
61 %token PE_EVENT_NAME
62 %token PE_RAW PE_NAME
63 %token PE_BPF_OBJECT PE_BPF_SOURCE
64 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
65 %token PE_LEGACY_CACHE
66 %token PE_PREFIX_MEM
67 %token PE_ERROR
68 %token PE_DRV_CFG_TERM
69 %token PE_TERM_HW
70 %type <num> PE_VALUE
71 %type <num> PE_VALUE_SYM_HW
72 %type <num> PE_VALUE_SYM_SW
73 %type <num> PE_VALUE_SYM_TOOL
74 %type <num> PE_TERM
75 %type <num> value_sym
76 %type <str> PE_RAW
77 %type <str> PE_NAME
78 %type <str> PE_BPF_OBJECT
79 %type <str> PE_BPF_SOURCE
80 %type <str> PE_LEGACY_CACHE
81 %type <str> PE_MODIFIER_EVENT
82 %type <str> PE_MODIFIER_BP
83 %type <str> PE_EVENT_NAME
84 %type <str> PE_DRV_CFG_TERM
85 %type <str> name_or_raw name_or_legacy
86 %destructor { free ($$); } <str>
87 %type <term> event_term
88 %destructor { parse_events_term__delete ($$); } <term>
89 %type <list_terms> event_config
90 %type <list_terms> opt_event_config
91 %type <list_terms> opt_pmu_config
92 %destructor { parse_events_terms__delete ($$); } <list_terms>
93 %type <list_evsel> event_pmu
94 %type <list_evsel> event_legacy_symbol
95 %type <list_evsel> event_legacy_cache
96 %type <list_evsel> event_legacy_mem
97 %type <list_evsel> event_legacy_tracepoint
98 %type <list_evsel> event_legacy_numeric
99 %type <list_evsel> event_legacy_raw
100 %type <list_evsel> event_bpf_file
101 %type <list_evsel> event_def
102 %type <list_evsel> event_mod
103 %type <list_evsel> event_name
104 %type <list_evsel> event
105 %type <list_evsel> events
106 %type <list_evsel> group_def
107 %type <list_evsel> group
108 %type <list_evsel> groups
109 %destructor { free_list_evsel ($$); } <list_evsel>
110 %type <tracepoint_name> tracepoint_name
111 %type <hardware_term> PE_TERM_HW
112 %destructor { free ($$.str); } <hardware_term>
113
114 %union
115 {
116         char *str;
117         u64 num;
118         struct list_head *list_evsel;
119         struct list_head *list_terms;
120         struct parse_events_term *term;
121         struct tracepoint_name {
122                 char *sys;
123                 char *event;
124         } tracepoint_name;
125         struct hardware_term {
126                 char *str;
127                 u64 num;
128         } hardware_term;
129 }
130 %%
131
132 start:
133 PE_START_EVENTS start_events
134 |
135 PE_START_TERMS  start_terms
136
137 start_events: groups
138 {
139         struct parse_events_state *parse_state = _parse_state;
140
141         /* frees $1 */
142         parse_events_update_lists($1, &parse_state->list);
143 }
144
145 groups:
146 groups ',' group
147 {
148         struct list_head *list  = $1;
149         struct list_head *group = $3;
150
151         /* frees $3 */
152         parse_events_update_lists(group, list);
153         $$ = list;
154 }
155 |
156 groups ',' event
157 {
158         struct list_head *list  = $1;
159         struct list_head *event = $3;
160
161         /* frees $3 */
162         parse_events_update_lists(event, list);
163         $$ = list;
164 }
165 |
166 group
167 |
168 event
169
170 group:
171 group_def ':' PE_MODIFIER_EVENT
172 {
173         struct list_head *list = $1;
174         int err;
175
176         err = parse_events__modifier_group(list, $3);
177         free($3);
178         if (err) {
179                 struct parse_events_state *parse_state = _parse_state;
180                 struct parse_events_error *error = parse_state->error;
181
182                 parse_events_error__handle(error, @3.first_column,
183                                            strdup("Bad modifier"), NULL);
184                 free_list_evsel(list);
185                 YYABORT;
186         }
187         $$ = list;
188 }
189 |
190 group_def
191
192 group_def:
193 PE_NAME '{' events '}'
194 {
195         struct list_head *list = $3;
196
197         /* Takes ownership of $1. */
198         parse_events__set_leader($1, list);
199         $$ = list;
200 }
201 |
202 '{' events '}'
203 {
204         struct list_head *list = $2;
205
206         parse_events__set_leader(NULL, list);
207         $$ = list;
208 }
209
210 events:
211 events ',' event
212 {
213         struct list_head *event = $3;
214         struct list_head *list  = $1;
215
216         /* frees $3 */
217         parse_events_update_lists(event, list);
218         $$ = list;
219 }
220 |
221 event
222
223 event: event_mod
224
225 event_mod:
226 event_name PE_MODIFIER_EVENT
227 {
228         struct list_head *list = $1;
229         int err;
230
231         /*
232          * Apply modifier on all events added by single event definition
233          * (there could be more events added for multiple tracepoint
234          * definitions via '*?'.
235          */
236         err = parse_events__modifier_event(list, $2, false);
237         free($2);
238         if (err) {
239                 struct parse_events_state *parse_state = _parse_state;
240                 struct parse_events_error *error = parse_state->error;
241
242                 parse_events_error__handle(error, @2.first_column,
243                                            strdup("Bad modifier"), NULL);
244                 free_list_evsel(list);
245                 YYABORT;
246         }
247         $$ = list;
248 }
249 |
250 event_name
251
252 event_name:
253 PE_EVENT_NAME event_def
254 {
255         int err;
256
257         err = parse_events_name($2, $1);
258         free($1);
259         if (err) {
260                 free_list_evsel($2);
261                 YYNOMEM;
262         }
263         $$ = $2;
264 }
265 |
266 event_def
267
268 event_def: event_pmu |
269            event_legacy_symbol |
270            event_legacy_cache sep_dc |
271            event_legacy_mem sep_dc |
272            event_legacy_tracepoint sep_dc |
273            event_legacy_numeric sep_dc |
274            event_legacy_raw sep_dc |
275            event_bpf_file
276
277 event_pmu:
278 PE_NAME opt_pmu_config
279 {
280         struct parse_events_state *parse_state = _parse_state;
281         struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL;
282         char *pattern = NULL;
283
284 #define CLEANUP                                         \
285         do {                                            \
286                 parse_events_terms__delete($2);         \
287                 parse_events_terms__delete(orig_terms); \
288                 free(list);                             \
289                 free($1);                               \
290                 free(pattern);                          \
291         } while(0)
292
293         if (parse_events_copy_term_list($2, &orig_terms)) {
294                 CLEANUP;
295                 YYNOMEM;
296         }
297
298         list = alloc_list();
299         if (!list) {
300                 CLEANUP;
301                 YYNOMEM;
302         }
303         /* Attempt to add to list assuming $1 is a PMU name. */
304         if (parse_events_add_pmu(parse_state, list, $1, $2, /*auto_merge_stats=*/false, &@1)) {
305                 struct perf_pmu *pmu = NULL;
306                 int ok = 0;
307
308                 /* Failure to add, try wildcard expansion of $1 as a PMU name. */
309                 if (asprintf(&pattern, "%s*", $1) < 0) {
310                         CLEANUP;
311                         YYNOMEM;
312                 }
313
314                 while ((pmu = perf_pmus__scan(pmu)) != NULL) {
315                         char *name = pmu->name;
316
317                         if (parse_events__filter_pmu(parse_state, pmu))
318                                 continue;
319
320                         if (!strncmp(name, "uncore_", 7) &&
321                             strncmp($1, "uncore_", 7))
322                                 name += 7;
323                         if (!perf_pmu__match(pattern, name, $1) ||
324                             !perf_pmu__match(pattern, pmu->alias_name, $1)) {
325                                 bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu);
326
327                                 if (parse_events_copy_term_list(orig_terms, &terms)) {
328                                         CLEANUP;
329                                         YYNOMEM;
330                                 }
331                                 if (!parse_events_add_pmu(parse_state, list, pmu->name, terms,
332                                                           auto_merge_stats, &@1)) {
333                                         ok++;
334                                         parse_state->wild_card_pmus = true;
335                                 }
336                                 parse_events_terms__delete(terms);
337                         }
338                 }
339
340                 if (!ok) {
341                         /* Failure to add, assume $1 is an event name. */
342                         zfree(&list);
343                         ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list, &@1);
344                         $2 = NULL;
345                 }
346                 if (!ok) {
347                         struct parse_events_error *error = parse_state->error;
348                         char *help;
349
350                         if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0)
351                                 help = NULL;
352                         parse_events_error__handle(error, @1.first_column,
353                                                    strdup("Bad event or PMU"),
354                                                    help);
355                         CLEANUP;
356                         YYABORT;
357                 }
358         }
359         $$ = list;
360         list = NULL;
361         CLEANUP;
362 #undef CLEANUP
363 }
364 |
365 PE_NAME sep_dc
366 {
367         struct list_head *list;
368         int err;
369
370         err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);
371         if (err < 0) {
372                 struct parse_events_state *parse_state = _parse_state;
373                 struct parse_events_error *error = parse_state->error;
374                 char *help;
375
376                 if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0)
377                         help = NULL;
378                 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
379                 free($1);
380                 PE_ABORT(err);
381         }
382         free($1);
383         $$ = list;
384 }
385
386 value_sym:
387 PE_VALUE_SYM_HW
388 |
389 PE_VALUE_SYM_SW
390
391 event_legacy_symbol:
392 value_sym '/' event_config '/'
393 {
394         struct list_head *list;
395         int type = $1 >> 16;
396         int config = $1 & 255;
397         int err;
398         bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
399
400         list = alloc_list();
401         if (!list)
402                 YYNOMEM;
403         err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
404         parse_events_terms__delete($3);
405         if (err) {
406                 free_list_evsel(list);
407                 PE_ABORT(err);
408         }
409         $$ = list;
410 }
411 |
412 value_sym sep_slash_slash_dc
413 {
414         struct list_head *list;
415         int type = $1 >> 16;
416         int config = $1 & 255;
417         bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
418         int err;
419
420         list = alloc_list();
421         if (!list)
422                 YYNOMEM;
423         err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
424         if (err)
425                 PE_ABORT(err);
426         $$ = list;
427 }
428 |
429 PE_VALUE_SYM_TOOL sep_slash_slash_dc
430 {
431         struct list_head *list;
432         int err;
433
434         list = alloc_list();
435         if (!list)
436                 YYNOMEM;
437         err = parse_events_add_tool(_parse_state, list, $1);
438         if (err)
439                 YYNOMEM;
440         $$ = list;
441 }
442
443 event_legacy_cache:
444 PE_LEGACY_CACHE opt_event_config
445 {
446         struct parse_events_state *parse_state = _parse_state;
447         struct list_head *list;
448         int err;
449
450         list = alloc_list();
451         if (!list)
452                 YYNOMEM;
453
454         err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
455
456         parse_events_terms__delete($2);
457         free($1);
458         if (err) {
459                 free_list_evsel(list);
460                 PE_ABORT(err);
461         }
462         $$ = list;
463 }
464
465 event_legacy_mem:
466 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
467 {
468         struct list_head *list;
469         int err;
470
471         list = alloc_list();
472         if (!list)
473                 YYNOMEM;
474
475         err = parse_events_add_breakpoint(_parse_state, list,
476                                           $2, $6, $4, $7);
477         parse_events_terms__delete($7);
478         free($6);
479         if (err) {
480                 free(list);
481                 PE_ABORT(err);
482         }
483         $$ = list;
484 }
485 |
486 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
487 {
488         struct list_head *list;
489         int err;
490
491         list = alloc_list();
492         if (!list)
493                 YYNOMEM;
494
495         err = parse_events_add_breakpoint(_parse_state, list,
496                                           $2, NULL, $4, $5);
497         parse_events_terms__delete($5);
498         if (err) {
499                 free(list);
500                 PE_ABORT(err);
501         }
502         $$ = list;
503 }
504 |
505 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
506 {
507         struct list_head *list;
508         int err;
509
510         list = alloc_list();
511         if (!list)
512                 YYNOMEM;
513
514         err = parse_events_add_breakpoint(_parse_state, list,
515                                           $2, $4, 0, $5);
516         parse_events_terms__delete($5);
517         free($4);
518         if (err) {
519                 free(list);
520                 PE_ABORT(err);
521         }
522         $$ = list;
523 }
524 |
525 PE_PREFIX_MEM PE_VALUE opt_event_config
526 {
527         struct list_head *list;
528         int err;
529
530         list = alloc_list();
531         if (!list)
532                 YYNOMEM;
533         err = parse_events_add_breakpoint(_parse_state, list,
534                                           $2, NULL, 0, $3);
535         parse_events_terms__delete($3);
536         if (err) {
537                 free(list);
538                 PE_ABORT(err);
539         }
540         $$ = list;
541 }
542
543 event_legacy_tracepoint:
544 tracepoint_name opt_event_config
545 {
546         struct parse_events_state *parse_state = _parse_state;
547         struct parse_events_error *error = parse_state->error;
548         struct list_head *list;
549         int err;
550
551         list = alloc_list();
552         if (!list)
553                 YYNOMEM;
554         if (error)
555                 error->idx = @1.first_column;
556
557         err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event,
558                                         error, $2, &@1);
559
560         parse_events_terms__delete($2);
561         free($1.sys);
562         free($1.event);
563         if (err) {
564                 free(list);
565                 PE_ABORT(err);
566         }
567         $$ = list;
568 }
569
570 tracepoint_name:
571 PE_NAME ':' PE_NAME
572 {
573         struct tracepoint_name tracepoint = {$1, $3};
574
575         $$ = tracepoint;
576 }
577
578 event_legacy_numeric:
579 PE_VALUE ':' PE_VALUE opt_event_config
580 {
581         struct list_head *list;
582         int err;
583
584         list = alloc_list();
585         if (!list)
586                 YYNOMEM;
587         err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
588                                        /*wildcard=*/false);
589         parse_events_terms__delete($4);
590         if (err) {
591                 free(list);
592                 PE_ABORT(err);
593         }
594         $$ = list;
595 }
596
597 event_legacy_raw:
598 PE_RAW opt_event_config
599 {
600         struct list_head *list;
601         int err;
602         u64 num;
603
604         list = alloc_list();
605         if (!list)
606                 YYNOMEM;
607         errno = 0;
608         num = strtoull($1 + 1, NULL, 16);
609         /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
610         if (errno)
611                 YYABORT;
612         free($1);
613         err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
614                                        /*wildcard=*/false);
615         parse_events_terms__delete($2);
616         if (err) {
617                 free(list);
618                 PE_ABORT(err);
619         }
620         $$ = list;
621 }
622
623 event_bpf_file:
624 PE_BPF_OBJECT opt_event_config
625 {
626         struct parse_events_state *parse_state = _parse_state;
627         struct list_head *list;
628         int err;
629
630         list = alloc_list();
631         if (!list)
632                 YYNOMEM;
633         err = parse_events_load_bpf(parse_state, list, $1, false, $2, &@1);
634         parse_events_terms__delete($2);
635         free($1);
636         if (err) {
637                 free(list);
638                 PE_ABORT(err);
639         }
640         $$ = list;
641 }
642 |
643 PE_BPF_SOURCE opt_event_config
644 {
645         struct list_head *list;
646         int err;
647
648         list = alloc_list();
649         if (!list)
650                 YYNOMEM;
651         err = parse_events_load_bpf(_parse_state, list, $1, true, $2, &@1);
652         parse_events_terms__delete($2);
653         if (err) {
654                 free(list);
655                 PE_ABORT(err);
656         }
657         $$ = list;
658 }
659
660 opt_event_config:
661 '/' event_config '/'
662 {
663         $$ = $2;
664 }
665 |
666 '/' '/'
667 {
668         $$ = NULL;
669 }
670 |
671 {
672         $$ = NULL;
673 }
674
675 opt_pmu_config:
676 '/' event_config '/'
677 {
678         $$ = $2;
679 }
680 |
681 '/' '/'
682 {
683         $$ = NULL;
684 }
685
686 start_terms: event_config
687 {
688         struct parse_events_state *parse_state = _parse_state;
689         if (parse_state->terms) {
690                 parse_events_terms__delete ($1);
691                 YYABORT;
692         }
693         parse_state->terms = $1;
694 }
695
696 event_config:
697 event_config ',' event_term
698 {
699         struct list_head *head = $1;
700         struct parse_events_term *term = $3;
701
702         if (!head) {
703                 parse_events_term__delete(term);
704                 YYABORT;
705         }
706         list_add_tail(&term->list, head);
707         $$ = $1;
708 }
709 |
710 event_term
711 {
712         struct list_head *head = malloc(sizeof(*head));
713         struct parse_events_term *term = $1;
714
715         if (!head)
716                 YYNOMEM;
717         INIT_LIST_HEAD(head);
718         list_add_tail(&term->list, head);
719         $$ = head;
720 }
721
722 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
723
724 name_or_legacy: PE_NAME | PE_LEGACY_CACHE
725
726 event_term:
727 PE_RAW
728 {
729         struct parse_events_term *term;
730         int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
731                                          strdup("raw"), $1, &@1, &@1);
732
733         if (err) {
734                 free($1);
735                 PE_ABORT(err);
736         }
737         $$ = term;
738 }
739 |
740 name_or_raw '=' name_or_legacy
741 {
742         struct parse_events_term *term;
743         int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
744
745         if (err) {
746                 free($1);
747                 free($3);
748                 PE_ABORT(err);
749         }
750         $$ = term;
751 }
752 |
753 name_or_raw '=' PE_VALUE
754 {
755         struct parse_events_term *term;
756         int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
757                                          $1, $3, false, &@1, &@3);
758
759         if (err) {
760                 free($1);
761                 PE_ABORT(err);
762         }
763         $$ = term;
764 }
765 |
766 name_or_raw '=' PE_TERM_HW
767 {
768         struct parse_events_term *term;
769         int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
770                                          $1, $3.str, &@1, &@3);
771
772         if (err) {
773                 free($1);
774                 free($3.str);
775                 PE_ABORT(err);
776         }
777         $$ = term;
778 }
779 |
780 PE_LEGACY_CACHE
781 {
782         struct parse_events_term *term;
783         int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
784                                          $1, 1, true, &@1, NULL);
785
786         if (err) {
787                 free($1);
788                 PE_ABORT(err);
789         }
790         $$ = term;
791 }
792 |
793 PE_NAME
794 {
795         struct parse_events_term *term;
796         int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
797                                          $1, 1, true, &@1, NULL);
798
799         if (err) {
800                 free($1);
801                 PE_ABORT(err);
802         }
803         $$ = term;
804 }
805 |
806 PE_TERM_HW
807 {
808         struct parse_events_term *term;
809         int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
810                                          $1.str, $1.num & 255, false, &@1, NULL);
811
812         if (err) {
813                 free($1.str);
814                 PE_ABORT(err);
815         }
816         $$ = term;
817 }
818 |
819 PE_TERM '=' name_or_legacy
820 {
821         struct parse_events_term *term;
822         int err = parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3);
823
824         if (err) {
825                 free($3);
826                 PE_ABORT(err);
827         }
828         $$ = term;
829 }
830 |
831 PE_TERM '=' PE_TERM_HW
832 {
833         struct parse_events_term *term;
834         int err = parse_events_term__str(&term, (int)$1, NULL, $3.str, &@1, &@3);
835
836         if (err) {
837                 free($3.str);
838                 PE_ABORT(err);
839         }
840         $$ = term;
841 }
842 |
843 PE_TERM '=' PE_TERM
844 {
845         struct parse_events_term *term;
846         int err = parse_events_term__term(&term, (int)$1, (int)$3, &@1, &@3);
847
848         if (err)
849                 PE_ABORT(err);
850
851         $$ = term;
852 }
853 |
854 PE_TERM '=' PE_VALUE
855 {
856         struct parse_events_term *term;
857         int err = parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3);
858
859         if (err)
860                 PE_ABORT(err);
861
862         $$ = term;
863 }
864 |
865 PE_TERM
866 {
867         struct parse_events_term *term;
868         int err = parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL);
869
870         if (err)
871                 PE_ABORT(err);
872
873         $$ = term;
874 }
875
876 sep_dc: ':' |
877
878 sep_slash_slash_dc: '/' '/' | ':' |
879
880 %%
881
882 void parse_events_error(YYLTYPE *loc, void *parse_state,
883                         void *scanner __maybe_unused,
884                         char const *msg __maybe_unused)
885 {
886         parse_events_evlist_error(parse_state, loc->last_column, "parser error");
887 }