From: Jiri Olsa <jolsa@redhat.com>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>,
Ian Rogers <irogers@google.com>,
linux-perf-users@vger.kernel.org
Subject: [PATCH 55/59] libperf: Move in parse-events flex/bison parser
Date: Mon, 8 Nov 2021 14:37:06 +0100 [thread overview]
Message-ID: <20211108133710.1352822-56-jolsa@kernel.org> (raw)
In-Reply-To: <20211108133710.1352822-1-jolsa@kernel.org>
Moving parse-events flex/bison parser in libperf.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/lib/perf/Build | 23 +
.../lib/perf/include/internal/parse-events.h | 3 +
tools/lib/perf/parse-events.c | 38 +
tools/lib/perf/parse-events.l | 411 ++++++++
tools/lib/perf/parse-events.y | 992 ++++++++++++++++++
tools/perf/util/Build | 15 -
tools/perf/util/parse-events.c | 38 -
tools/perf/util/parse-events.l | 411 --------
tools/perf/util/parse-events.y | 992 ------------------
9 files changed, 1467 insertions(+), 1456 deletions(-)
create mode 100644 tools/lib/perf/parse-events.l
create mode 100644 tools/lib/perf/parse-events.y
delete mode 100644 tools/perf/util/parse-events.l
delete mode 100644 tools/perf/util/parse-events.y
diff --git a/tools/lib/perf/Build b/tools/lib/perf/Build
index af4663e4421f..3e29d173e0ec 100644
--- a/tools/lib/perf/Build
+++ b/tools/lib/perf/Build
@@ -12,6 +12,8 @@ libperf-y += pmu-bison.o
libperf-y += pmu.o
libperf-y += pmu-hybrid.o
libperf-y += parse-events.o
+libperf-y += parse-events-flex.o
+libperf-y += parse-events-bison.o
$(OUTPUT)zalloc.o: ../../lib/zalloc.c FORCE
$(call rule_mkdir)
@@ -19,6 +21,15 @@ $(OUTPUT)zalloc.o: ../../lib/zalloc.c FORCE
tests-y += tests/
+$(OUTPUT)parse-events-flex.c $(OUTPUT)parse-events-flex.h: parse-events.l $(OUTPUT)parse-events-bison.c
+ $(call rule_mkdir)
+ $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)parse-events-flex.c \
+ --header-file=$(OUTPUT)parse-events-flex.h $(PARSER_DEBUG_FLEX) $<
+
+$(OUTPUT)parse-events-bison.c $(OUTPUT)parse-events-bison.h: parse-events.y
+ $(call rule_mkdir)
+ $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) $(BISON_FILE_PREFIX_MAP) \
+ -o $(OUTPUT)parse-events-bison.c -p parse_events_
$(OUTPUT)pmu-flex.c $(OUTPUT)pmu-flex.h: pmu.l $(OUTPUT)pmu-bison.c
$(call rule_mkdir)
@@ -41,7 +52,19 @@ else
flex_flags := -w
endif
+bison_flags := -DYYENABLE_NLS=0
+BISON_GE_35 := $(shell expr $(shell $(BISON) --version | grep bison | sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 35)
+ifeq ($(BISON_GE_35),1)
+ bison_flags += -Wno-unused-parameter -Wno-nested-externs -Wno-implicit-function-declaration -Wno-switch-enum
+else
+ bison_flags += -w
+endif
+
CFLAGS_pmu-flex.o += $(flex_flags)
CFLAGS_pmu-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags)
+CFLAGS_parse-events-flex.o += $(flex_flags)
+CFLAGS_parse-events-bison.o += $(bison_flags)
+
$(OUTPUT)pmu.o: $(OUTPUT)pmu-flex.c $(OUTPUT)pmu-bison.c
+$(OUTPUT)parse-events.o: $(OUTPUT)parse-events-flex.c $(OUTPUT)parse-events-bison.c
diff --git a/tools/lib/perf/include/internal/parse-events.h b/tools/lib/perf/include/internal/parse-events.h
index 0a8a61219885..5020a1b2bff2 100644
--- a/tools/lib/perf/include/internal/parse-events.h
+++ b/tools/lib/perf/include/internal/parse-events.h
@@ -194,4 +194,7 @@ void parse_events__handle_error(struct parse_events_error *err, int idx,
void parse_events_evlist_error(struct parse_events_state *parse_state,
int idx, const char *str);
int parse_events_name(struct list_head *list, const char *name);
+int parse_events__scanner(const char *str,
+ struct parse_events_state *parse_state,
+ bool terms);
#endif /* __LIBPERF_PARSE_EVENTS_H */
diff --git a/tools/lib/perf/parse-events.c b/tools/lib/perf/parse-events.c
index 6efc2bb73cdf..da684023b273 100644
--- a/tools/lib/perf/parse-events.c
+++ b/tools/lib/perf/parse-events.c
@@ -13,6 +13,13 @@
#include <errno.h>
#include <asm/bug.h>
#include "internal.h"
+#include "parse-events-bison.h"
+#define YY_EXTRA_TYPE void*
+#include "parse-events-flex.h"
+
+#ifdef PARSER_DEBUG
+extern int parse_events_debug;
+#endif
struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_CPU_CYCLES] = {
@@ -592,3 +599,34 @@ int parse_events_name(struct list_head *list, const char *name)
return 0;
}
+
+int parse_events__scanner(const char *str,
+ struct parse_events_state *parse_state,
+ bool terms)
+{
+ YY_BUFFER_STATE buffer;
+ void *scanner;
+ int ret;
+
+ if (terms)
+ parse_state->stoken = PE_START_TERMS;
+ else
+ parse_state->stoken = PE_START_EVENTS;
+
+ ret = parse_events_lex_init_extra(parse_state, &scanner);
+ if (ret)
+ return ret;
+
+ buffer = parse_events__scan_string(str, scanner);
+
+#ifdef PARSER_DEBUG
+ parse_events_debug = 1;
+ parse_events_set_debug(1, scanner);
+#endif
+ ret = parse_events_parse(parse_state, scanner);
+
+ parse_events__flush_buffer(buffer, scanner);
+ parse_events__delete_buffer(buffer, scanner);
+ parse_events_lex_destroy(scanner);
+ return ret;
+}
diff --git a/tools/lib/perf/parse-events.l b/tools/lib/perf/parse-events.l
new file mode 100644
index 000000000000..1d4e0aa5ee31
--- /dev/null
+++ b/tools/lib/perf/parse-events.l
@@ -0,0 +1,411 @@
+
+%option reentrant
+%option bison-bridge
+%option prefix="parse_events_"
+%option stack
+%option bison-locations
+%option yylineno
+%option reject
+
+%{
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <internal/parse-events.h>
+#include "parse-events-bison.h"
+#include <internal/evsel.h>
+
+char *parse_events_get_text(yyscan_t yyscanner);
+YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
+
+static int __value(YYSTYPE *yylval, char *str, int base, int token)
+{
+ u64 num;
+
+ errno = 0;
+ num = strtoull(str, NULL, base);
+ if (errno)
+ return PE_ERROR;
+
+ yylval->num = num;
+ return token;
+}
+
+static int value(yyscan_t scanner, int base)
+{
+ YYSTYPE *yylval = parse_events_get_lval(scanner);
+ char *text = parse_events_get_text(scanner);
+
+ return __value(yylval, text, base, PE_VALUE);
+}
+
+static int str(yyscan_t scanner, int token)
+{
+ YYSTYPE *yylval = parse_events_get_lval(scanner);
+ char *text = parse_events_get_text(scanner);
+
+ if (text[0] != '\'') {
+ yylval->str = strdup(text);
+ } else {
+ /*
+ * If a text tag specified on the command line
+ * contains opening single quite ' then it is
+ * expected that the tag ends with single quote
+ * as well, like this:
+ * name=\'CPU_CLK_UNHALTED.THREAD:cmask=1\'
+ * quotes need to be escaped to bypass shell
+ * processing.
+ */
+ yylval->str = strndup(&text[1], strlen(text) - 2);
+ }
+
+ return token;
+}
+
+static int raw(yyscan_t scanner, struct parse_events_state *parse_state)
+{
+ YYSTYPE *yylval = parse_events_get_lval(scanner);
+ char *text = parse_events_get_text(scanner);
+
+ if (parse_state->ops->parse_check(text) == PMU_EVENT_SYMBOL)
+ return str(scanner, PE_NAME);
+
+ return __value(yylval, text + 1, 16, PE_RAW);
+}
+
+static bool isbpf_suffix(char *text)
+{
+ int len = strlen(text);
+
+ if (len < 2)
+ return false;
+ if ((text[len - 1] == 'c' || text[len - 1] == 'o') &&
+ text[len - 2] == '.')
+ return true;
+ if (len > 4 && !strcmp(text + len - 4, ".obj"))
+ return true;
+ return false;
+}
+
+static bool isbpf(yyscan_t scanner)
+{
+ char *text = parse_events_get_text(scanner);
+ struct stat st;
+
+ if (!isbpf_suffix(text))
+ return false;
+
+ return stat(text, &st) == 0;
+}
+
+/*
+ * This function is called when the parser gets two kind of input:
+ *
+ * @cfg1 or @cfg2=config
+ *
+ * The leading '@' is stripped off before 'cfg1' and 'cfg2=config' are given to
+ * bison. In the latter case it is necessary to keep the string intact so that
+ * the PMU kernel driver can determine what configurable is associated to
+ * 'config'.
+ */
+static int drv_str(yyscan_t scanner, int token)
+{
+ YYSTYPE *yylval = parse_events_get_lval(scanner);
+ char *text = parse_events_get_text(scanner);
+
+ /* Strip off the '@' */
+ yylval->str = strdup(text + 1);
+ return token;
+}
+
+#define REWIND(__alloc) \
+do { \
+ YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \
+ char *text = parse_events_get_text(yyscanner); \
+ \
+ if (__alloc) \
+ __yylval->str = strdup(text); \
+ \
+ yycolumn -= strlen(text); \
+ yyless(0); \
+} while (0)
+
+static int pmu_str_check(yyscan_t scanner, struct parse_events_state *parse_state)
+{
+ YYSTYPE *yylval = parse_events_get_lval(scanner);
+ char *text = parse_events_get_text(scanner);
+
+ yylval->str = strdup(text);
+
+ /*
+ * If we're not testing then parse check determines the PMU event type
+ * which if it isn't a PMU returns PE_NAME. When testing the result of
+ * parse check can't be trusted so we return PE_PMU_EVENT_FAKE unless
+ * an '!' is present in which case the text can't be a PMU name.
+ */
+ switch (parse_state->ops->parse_check(text)) {
+ case PMU_EVENT_SYMBOL_PREFIX:
+ return PE_PMU_EVENT_PRE;
+ case PMU_EVENT_SYMBOL_SUFFIX:
+ return PE_PMU_EVENT_SUF;
+ case PMU_EVENT_SYMBOL:
+ return parse_state->fake_pmu
+ ? PE_PMU_EVENT_FAKE : PE_KERNEL_PMU_EVENT;
+ default:
+ return parse_state->fake_pmu && !strchr(text,'!')
+ ? PE_PMU_EVENT_FAKE : PE_NAME;
+ }
+}
+
+static int sym(yyscan_t scanner, int type, int config)
+{
+ YYSTYPE *yylval = parse_events_get_lval(scanner);
+
+ yylval->num = (type << 16) + config;
+ return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
+}
+
+static int tool(yyscan_t scanner, enum perf_tool_event event)
+{
+ YYSTYPE *yylval = parse_events_get_lval(scanner);
+
+ yylval->num = event;
+ return PE_VALUE_SYM_TOOL;
+}
+
+static int term(yyscan_t scanner, int type)
+{
+ YYSTYPE *yylval = parse_events_get_lval(scanner);
+
+ yylval->num = type;
+ return PE_TERM;
+}
+
+#define YY_USER_ACTION \
+do { \
+ yylloc->last_column = yylloc->first_column; \
+ yylloc->first_column = yycolumn; \
+ yycolumn += yyleng; \
+} while (0);
+
+#define USER_REJECT \
+ yycolumn -= yyleng; \
+ REJECT
+
+%}
+
+%x mem
+%s config
+%x event
+%x array
+
+group [^,{}/]*[{][^}]*[}][^,{}/]*
+event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
+event [^,{}/]+
+bpf_object [^,{}]+\.(o|bpf)[a-zA-Z0-9._]*
+bpf_source [^,{}]+\.c[a-zA-Z0-9._]*
+
+num_dec [0-9]+
+num_hex 0x[a-fA-F0-9]+
+num_raw_hex [a-fA-F0-9]+
+name [a-zA-Z_*?\[\]][a-zA-Z0-9_*?.\[\]!]*
+name_tag [\'][a-zA-Z_*?\[\]][a-zA-Z0-9_*?\-,\.\[\]:=]*[\']
+name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
+drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
+/* If you add a modifier you need to update check_modifier() */
+modifier_event [ukhpPGHSDIWeb]+
+modifier_bp [rwx]{1,3}
+
+%%
+
+%{
+ struct parse_events_state *_parse_state = parse_events_get_extra(yyscanner);
+
+ {
+ int start_token = _parse_state->stoken;
+
+ if (start_token == PE_START_TERMS)
+ BEGIN(config);
+ else if (start_token == PE_START_EVENTS)
+ BEGIN(event);
+
+ if (start_token) {
+ _parse_state->stoken = 0;
+ /*
+ * The flex parser does not init locations variable
+ * via the scan_string interface, so we need do the
+ * init in here.
+ */
+ yycolumn = 0;
+ return start_token;
+ }
+ }
+%}
+
+<event>{
+
+{group} {
+ BEGIN(INITIAL);
+ REWIND(0);
+ }
+
+{event_pmu} |
+{bpf_object} |
+{bpf_source} |
+{event} {
+ BEGIN(INITIAL);
+ REWIND(1);
+ return PE_EVENT_NAME;
+ }
+
+<<EOF>> {
+ BEGIN(INITIAL);
+ REWIND(0);
+ }
+, {
+ return ',';
+ }
+}
+
+<array>{
+"]" { BEGIN(config); return ']'; }
+{num_dec} { return value(yyscanner, 10); }
+{num_hex} { return value(yyscanner, 16); }
+, { return ','; }
+"\.\.\." { return PE_ARRAY_RANGE; }
+}
+
+<config>{
+ /*
+ * Please update config_term_names when new static term is added.
+ */
+config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
+config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
+config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
+name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
+period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
+freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); }
+branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
+time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
+call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
+stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
+max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); }
+nr { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_EVENTS); }
+inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
+no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
+overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
+no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
+percore { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); }
+aux-output { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT); }
+aux-sample-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE); }
+metric-id { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); }
+r{num_raw_hex} { return raw(yyscanner, _parse_state); }
+r0x{num_raw_hex} { return raw(yyscanner, _parse_state); }
+, { return ','; }
+"/" { BEGIN(INITIAL); return '/'; }
+{name_minus} { return str(yyscanner, PE_NAME); }
+\[all\] { return PE_ARRAY_ALL; }
+"[" { BEGIN(array); return '['; }
+@{drv_cfg_term} { return drv_str(yyscanner, PE_DRV_CFG_TERM); }
+}
+
+<mem>{
+{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
+: { return ':'; }
+"/" { return '/'; }
+{num_dec} { return value(yyscanner, 10); }
+{num_hex} { return value(yyscanner, 16); }
+ /*
+ * We need to separate 'mem:' scanner part, in order to get specific
+ * modifier bits parsed out. Otherwise we would need to handle PE_NAME
+ * and we'd need to parse it manually. During the escape from <mem>
+ * state we need to put the escaping char back, so we dont miss it.
+ */
+. { unput(*yytext); BEGIN(INITIAL); }
+ /*
+ * We destroy the scanner after reaching EOF,
+ * but anyway just to be sure get back to INIT state.
+ */
+<<EOF>> { BEGIN(INITIAL); }
+}
+
+cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
+stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
+stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
+instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
+cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
+cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
+branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
+branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
+bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
+ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
+cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
+task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
+page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
+minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
+major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
+context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
+cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
+alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
+emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
+dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
+duration_time { return tool(yyscanner, PERF_TOOL_DURATION_TIME); }
+bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
+cgroup-switches { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); }
+
+ /*
+ * We have to handle the kernel PMU event cycles-ct/cycles-t/mem-loads/mem-stores separately.
+ * Because the prefix cycles is mixed up with cpu-cycles.
+ * loads and stores are mixed up with cache event
+ */
+cycles-ct |
+cycles-t |
+mem-loads |
+mem-loads-aux |
+mem-stores |
+topdown-[a-z-]+ |
+tx-capacity-[a-z-]+ |
+el-capacity-[a-z-]+ { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
+
+L1-dcache|l1-d|l1d|L1-data |
+L1-icache|l1-i|l1i|L1-instruction |
+LLC|L2 |
+dTLB|d-tlb|Data-TLB |
+iTLB|i-tlb|Instruction-TLB |
+branch|branches|bpu|btb|bpc |
+node { return str(yyscanner, PE_NAME_CACHE_TYPE); }
+
+load|loads|read |
+store|stores|write |
+prefetch|prefetches |
+speculative-read|speculative-load |
+refs|Reference|ops|access |
+misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
+
+mem: { BEGIN(mem); return PE_PREFIX_MEM; }
+r{num_raw_hex} { return raw(yyscanner, _parse_state); }
+{num_dec} { return value(yyscanner, 10); }
+{num_hex} { return value(yyscanner, 16); }
+
+{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
+{bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); }
+{bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); }
+{name} { return pmu_str_check(yyscanner, _parse_state); }
+{name_tag} { return str(yyscanner, PE_NAME); }
+"/" { BEGIN(config); return '/'; }
+- { return '-'; }
+, { BEGIN(event); return ','; }
+: { return ':'; }
+"{" { BEGIN(event); return '{'; }
+"}" { return '}'; }
+= { return '='; }
+\n { }
+. { }
+
+%%
+
+int parse_events_wrap(void *scanner __maybe_unused)
+{
+ return 1;
+}
diff --git a/tools/lib/perf/parse-events.y b/tools/lib/perf/parse-events.y
new file mode 100644
index 000000000000..5ed21a4509e5
--- /dev/null
+++ b/tools/lib/perf/parse-events.y
@@ -0,0 +1,992 @@
+%define api.pure full
+%parse-param {void *_parse_state}
+%parse-param {void *scanner}
+%lex-param {void* scanner}
+%locations
+
+%{
+
+#define YYDEBUG 1
+
+#include <fnmatch.h>
+#include <stdio.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/zalloc.h>
+#include <internal/pmu.h>
+#include <internal/evsel.h>
+#include <internal/parse-events.h>
+#include "parse-events-bison.h"
+
+void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
+
+#define ABORT_ON(val) \
+do { \
+ if (val) \
+ YYABORT; \
+} while (0)
+
+static struct list_head* alloc_list(void)
+{
+ struct list_head *list;
+
+ list = malloc(sizeof(*list));
+ if (!list)
+ return NULL;
+
+ INIT_LIST_HEAD(list);
+ return list;
+}
+
+static void free_list_evsel(struct parse_events_state *parse_state,
+ struct list_head* list_evsel)
+{
+ struct perf_evsel *evsel, *tmp;
+
+ list_for_each_entry_safe(evsel, tmp, list_evsel, node) {
+ list_del_init(&evsel->node);
+ parse_state->ops->perf_evsel__delete(evsel);
+ }
+ free(list_evsel);
+}
+
+/* list_event is assumed to point to malloc'ed memory */
+static void update_lists(struct list_head *list_event,
+ struct list_head *list_all)
+{
+ /*
+ * Called for single event definition. Update the
+ * 'all event' list, and reinit the 'single event'
+ * list, for next event definition.
+ */
+ list_splice_tail(list_event, list_all);
+ free(list_event);
+}
+
+static void inc_group_count(struct list_head *list,
+ struct parse_events_state *parse_state)
+{
+ /* Count groups only have more than 1 members */
+ if (!list_is_last(list->next, list))
+ parse_state->nr_groups++;
+}
+
+static int loc_term(void *loc_term_)
+{
+ YYLTYPE *loc_term = loc_term_;
+
+ return loc_term ? loc_term->first_column : 0;
+}
+
+static int loc_val(void *loc_val_)
+{
+ YYLTYPE *loc_val = loc_val_;
+
+ return loc_val ? loc_val->first_column : 0;
+}
+
+%}
+
+%token PE_START_EVENTS PE_START_TERMS
+%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
+%token PE_VALUE_SYM_TOOL
+%token PE_EVENT_NAME
+%token PE_NAME
+%token PE_BPF_OBJECT PE_BPF_SOURCE
+%token PE_MODIFIER_EVENT PE_MODIFIER_BP
+%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
+%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
+%token PE_ERROR
+%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE
+%token PE_ARRAY_ALL PE_ARRAY_RANGE
+%token PE_DRV_CFG_TERM
+%type <num> PE_VALUE
+%type <num> PE_VALUE_SYM_HW
+%type <num> PE_VALUE_SYM_SW
+%type <num> PE_VALUE_SYM_TOOL
+%type <num> PE_RAW
+%type <num> PE_TERM
+%type <num> value_sym
+%type <str> PE_NAME
+%type <str> PE_BPF_OBJECT
+%type <str> PE_BPF_SOURCE
+%type <str> PE_NAME_CACHE_TYPE
+%type <str> PE_NAME_CACHE_OP_RESULT
+%type <str> PE_MODIFIER_EVENT
+%type <str> PE_MODIFIER_BP
+%type <str> PE_EVENT_NAME
+%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE
+%type <str> PE_DRV_CFG_TERM
+%type <str> event_pmu_name
+%destructor { free ($$); } <str>
+%type <term> event_term
+%destructor { parse_events_term__delete ($$); } <term>
+%type <list_terms> event_config
+%type <list_terms> opt_event_config
+%type <list_terms> opt_pmu_config
+%destructor { parse_events_terms__delete ($$); } <list_terms>
+%type <list_evsel> event_pmu
+%type <list_evsel> event_legacy_symbol
+%type <list_evsel> event_legacy_cache
+%type <list_evsel> event_legacy_mem
+%type <list_evsel> event_legacy_tracepoint
+%type <list_evsel> event_legacy_numeric
+%type <list_evsel> event_legacy_raw
+%type <list_evsel> event_bpf_file
+%type <list_evsel> event_def
+%type <list_evsel> event_mod
+%type <list_evsel> event_name
+%type <list_evsel> event
+%type <list_evsel> events
+%type <list_evsel> group_def
+%type <list_evsel> group
+%type <list_evsel> groups
+%destructor { free_list_evsel (_parse_state, $$); } <list_evsel>
+%type <tracepoint_name> tracepoint_name
+%destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
+%type <array> array
+%type <array> array_term
+%type <array> array_terms
+%destructor { free ($$.ranges); } <array>
+
+%union
+{
+ char *str;
+ u64 num;
+ struct list_head *list_evsel;
+ struct list_head *list_terms;
+ struct parse_events_term *term;
+ struct tracepoint_name {
+ char *sys;
+ char *event;
+ } tracepoint_name;
+ struct parse_events_array array;
+}
+%%
+
+start:
+PE_START_EVENTS start_events
+|
+PE_START_TERMS start_terms
+
+start_events: groups
+{
+ struct parse_events_state *parse_state = _parse_state;
+
+ /* frees $1 */
+ update_lists($1, &parse_state->list);
+}
+
+groups:
+groups ',' group
+{
+ struct list_head *list = $1;
+ struct list_head *group = $3;
+
+ /* frees $3 */
+ update_lists(group, list);
+ $$ = list;
+}
+|
+groups ',' event
+{
+ struct list_head *list = $1;
+ struct list_head *event = $3;
+
+ /* frees $3 */
+ update_lists(event, list);
+ $$ = list;
+}
+|
+group
+|
+event
+
+group:
+group_def ':' PE_MODIFIER_EVENT
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list = $1;
+ int err;
+
+ err = parse_events__modifier_group(list, $3, parse_state->guest);
+ free($3);
+ if (err) {
+ struct parse_events_error *error = parse_state->error;
+
+ parse_events__handle_error(error, @3.first_column,
+ strdup("Bad modifier"), NULL);
+ free_list_evsel(parse_state, list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+group_def
+
+group_def:
+PE_NAME '{' events '}'
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list = $3;
+
+ inc_group_count(list, _parse_state);
+ parse_state->ops->set_leader($1, list, parse_state);
+ free($1);
+ $$ = list;
+}
+|
+'{' events '}'
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list = $2;
+
+ inc_group_count(list, _parse_state);
+ parse_state->ops->set_leader(NULL, list, parse_state);
+ $$ = list;
+}
+
+events:
+events ',' event
+{
+ struct list_head *event = $3;
+ struct list_head *list = $1;
+
+ /* frees $3 */
+ update_lists(event, list);
+ $$ = list;
+}
+|
+event
+
+event: event_mod
+
+event_mod:
+event_name PE_MODIFIER_EVENT
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list = $1;
+ int err;
+
+ /*
+ * Apply modifier on all events added by single event definition
+ * (there could be more events added for multiple tracepoint
+ * definitions via '*?'.
+ */
+ err = parse_events__modifier_event(list, $2, false, parse_state->guest);
+ free($2);
+ if (err) {
+ struct parse_events_error *error = parse_state->error;
+
+ parse_events__handle_error(error, @2.first_column,
+ strdup("Bad modifier"), NULL);
+ free_list_evsel(parse_state, list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+event_name
+
+event_name:
+PE_EVENT_NAME event_def
+{
+ int err;
+
+ err = parse_events_name($2, $1);
+ free($1);
+ if (err) {
+ free_list_evsel(_parse_state, $2);
+ YYABORT;
+ }
+ $$ = $2;
+}
+|
+event_def
+
+event_def: event_pmu |
+ event_legacy_symbol |
+ event_legacy_cache sep_dc |
+ event_legacy_mem |
+ event_legacy_tracepoint sep_dc |
+ event_legacy_numeric sep_dc |
+ event_legacy_raw sep_dc |
+ event_bpf_file
+
+event_pmu_name:
+PE_NAME | PE_PMU_EVENT_PRE
+
+event_pmu:
+event_pmu_name opt_pmu_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct parse_events_error *error = parse_state->error;
+ struct list_head *list = NULL, *orig_terms = NULL;
+
+#define CLEANUP_YYABORT \
+ do { \
+ parse_events_terms__delete($2); \
+ parse_events_terms__delete(orig_terms); \
+ free(list); \
+ free($1); \
+ YYABORT; \
+ } while(0)
+
+ if (parse_events_copy_term_list($2, &orig_terms))
+ CLEANUP_YYABORT;
+
+ if (error)
+ error->idx = @1.first_column;
+
+ list = alloc_list();
+ if (!list)
+ CLEANUP_YYABORT;
+ if (parse_state->ops->add_pmu(parse_state, list, $1, $2, orig_terms, false, false))
+ CLEANUP_YYABORT;
+ parse_events_terms__delete($2);
+ parse_events_terms__delete(orig_terms);
+ free($1);
+ $$ = list;
+#undef CLEANUP_YYABORT
+}
+|
+PE_KERNEL_PMU_EVENT sep_dc
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ err = parse_state->ops->add_pmu_multi(parse_state, $1, NULL, &list);
+ free($1);
+ if (err < 0)
+ YYABORT;
+ $$ = list;
+}
+|
+PE_KERNEL_PMU_EVENT opt_pmu_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ /* frees $2 */
+ err = parse_state->ops->add_pmu_multi(_parse_state, $1, $2, &list);
+ free($1);
+ if (err < 0)
+ YYABORT;
+ $$ = list;
+}
+|
+PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ char pmu_name[128];
+
+ snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3);
+ free($1);
+ free($3);
+ if (parse_state->ops->add_pmu_multi(_parse_state, pmu_name, NULL, &list) < 0)
+ YYABORT;
+ $$ = list;
+}
+|
+PE_PMU_EVENT_FAKE sep_dc
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ if (!list)
+ YYABORT;
+
+ err = parse_state->ops->add_pmu(parse_state, list, $1, NULL, NULL, false, false);
+ free($1);
+ if (err < 0) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+PE_PMU_EVENT_FAKE opt_pmu_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ if (!list)
+ YYABORT;
+
+ err = parse_state->ops->add_pmu(parse_state, list, $1, $2, NULL, false, false);
+ free($1);
+ parse_events_terms__delete($2);
+ if (err < 0) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+
+value_sym:
+PE_VALUE_SYM_HW
+|
+PE_VALUE_SYM_SW
+
+event_legacy_symbol:
+value_sym '/' event_config '/'
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int type = $1 >> 16;
+ int config = $1 & 255;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_numeric(parse_state, list, type, config, $3);
+ parse_events_terms__delete($3);
+ if (err) {
+ free_list_evsel(_parse_state, list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+value_sym sep_slash_slash_dc
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int type = $1 >> 16;
+ int config = $1 & 255;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ ABORT_ON(parse_state->ops->add_numeric(parse_state, list, type, config, NULL));
+ $$ = list;
+}
+|
+PE_VALUE_SYM_TOOL sep_slash_slash_dc
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ ABORT_ON(parse_state->ops->add_tool(_parse_state, list, $1));
+ $$ = list;
+}
+
+event_legacy_cache:
+PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct parse_events_error *error = parse_state->error;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_cache(parse_state, list, $1, $3, $5, error, $6);
+ parse_events_terms__delete($6);
+ free($1);
+ free($3);
+ free($5);
+ if (err) {
+ free_list_evsel(parse_state, list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct parse_events_error *error = parse_state->error;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_cache(parse_state, list, $1, $3, NULL, error, $4);
+ parse_events_terms__delete($4);
+ free($1);
+ free($3);
+ if (err) {
+ free_list_evsel(parse_state, list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+PE_NAME_CACHE_TYPE opt_event_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct parse_events_error *error = parse_state->error;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_cache(parse_state, list, $1, NULL, NULL, error, $2);
+ parse_events_terms__delete($2);
+ free($1);
+ if (err) {
+ free_list_evsel(parse_state, list);
+ YYABORT;
+ }
+ $$ = list;
+}
+
+event_legacy_mem:
+PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_breakpoint(parse_state, list, $2, $6, $4);
+ free($6);
+ if (err) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ if (parse_state->ops->add_breakpoint(parse_state, list, $2, NULL, $4)) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_breakpoint(parse_state, list, $2, $4, 0);
+ free($4);
+ if (err) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+PE_PREFIX_MEM PE_VALUE sep_dc
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ if (parse_state->ops->add_breakpoint(parse_state, list, $2, NULL, 0)) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+
+event_legacy_tracepoint:
+tracepoint_name opt_event_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct parse_events_error *error = parse_state->error;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ if (error)
+ error->idx = @1.first_column;
+
+ err = parse_state->ops->add_tracepoint(parse_state, list, $1.sys, $1.event,
+ error, $2);
+
+ parse_events_terms__delete($2);
+ free($1.sys);
+ free($1.event);
+ if (err) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+
+tracepoint_name:
+PE_NAME '-' PE_NAME ':' PE_NAME
+{
+ struct tracepoint_name tracepoint;
+
+ ABORT_ON(asprintf(&tracepoint.sys, "%s-%s", $1, $3) < 0);
+ tracepoint.event = $5;
+ free($1);
+ free($3);
+ $$ = tracepoint;
+}
+|
+PE_NAME ':' PE_NAME
+{
+ struct tracepoint_name tracepoint = {$1, $3};
+
+ $$ = tracepoint;
+}
+
+event_legacy_numeric:
+PE_VALUE ':' PE_VALUE opt_event_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_numeric(_parse_state, list, (u32)$1, $3, $4);
+ parse_events_terms__delete($4);
+ if (err) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+
+event_legacy_raw:
+PE_RAW opt_event_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2);
+ parse_events_terms__delete($2);
+ if (err) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+
+event_bpf_file:
+PE_BPF_OBJECT opt_event_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_bpf(parse_state, list, $1, false, $2);
+ parse_events_terms__delete($2);
+ free($1);
+ if (err) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+|
+PE_BPF_SOURCE opt_event_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ struct list_head *list;
+ int err;
+
+ list = alloc_list();
+ ABORT_ON(!list);
+ err = parse_state->ops->add_bpf(parse_state, list, $1, true, $2);
+ parse_events_terms__delete($2);
+ if (err) {
+ free(list);
+ YYABORT;
+ }
+ $$ = list;
+}
+
+opt_event_config:
+'/' event_config '/'
+{
+ $$ = $2;
+}
+|
+'/' '/'
+{
+ $$ = NULL;
+}
+|
+{
+ $$ = NULL;
+}
+
+opt_pmu_config:
+'/' event_config '/'
+{
+ $$ = $2;
+}
+|
+'/' '/'
+{
+ $$ = NULL;
+}
+
+start_terms: event_config
+{
+ struct parse_events_state *parse_state = _parse_state;
+ if (parse_state->terms) {
+ parse_events_terms__delete ($1);
+ YYABORT;
+ }
+ parse_state->terms = $1;
+}
+
+event_config:
+event_config ',' event_term
+{
+ struct list_head *head = $1;
+ struct parse_events_term *term = $3;
+
+ if (!head) {
+ parse_events_term__delete(term);
+ YYABORT;
+ }
+ list_add_tail(&term->list, head);
+ $$ = $1;
+}
+|
+event_term
+{
+ struct list_head *head = malloc(sizeof(*head));
+ struct parse_events_term *term = $1;
+
+ ABORT_ON(!head);
+ INIT_LIST_HEAD(head);
+ list_add_tail(&term->list, head);
+ $$ = head;
+}
+
+event_term:
+PE_RAW
+{
+ struct parse_events_term *term;
+
+ ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_CONFIG,
+ NULL, $1, false, loc_term(&@1), 0));
+ $$ = term;
+}
+|
+PE_NAME '=' PE_NAME
+{
+ struct parse_events_term *term;
+
+ if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, $3, loc_term(&@1), loc_val(&@3))) {
+ free($1);
+ free($3);
+ YYABORT;
+ }
+ $$ = term;
+}
+|
+PE_NAME '=' PE_VALUE
+{
+ struct parse_events_term *term;
+
+ if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, $3, false, loc_term(&@1), loc_val(&@3))) {
+ free($1);
+ YYABORT;
+ }
+ $$ = term;
+}
+|
+PE_NAME '=' PE_VALUE_SYM_HW
+{
+ struct parse_events_term *term;
+ int config = $3 & 255;
+
+ if (parse_events_term__sym_hw(&term, $1, config)) {
+ free($1);
+ YYABORT;
+ }
+ $$ = term;
+}
+|
+PE_NAME
+{
+ struct parse_events_term *term;
+
+ if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, 1, true, loc_term(&@1), 0)) {
+ free($1);
+ YYABORT;
+ }
+ $$ = term;
+}
+|
+PE_VALUE_SYM_HW
+{
+ struct parse_events_term *term;
+ int config = $1 & 255;
+
+ ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
+ $$ = term;
+}
+|
+PE_TERM '=' PE_NAME
+{
+ struct parse_events_term *term;
+
+ if (parse_events_term__str(&term, (int)$1, NULL, $3,
+ loc_term(&@1), loc_val(&@3))) {
+ free($3);
+ YYABORT;
+ }
+ $$ = term;
+}
+|
+PE_TERM '=' PE_VALUE
+{
+ struct parse_events_term *term;
+
+ ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false,
+ loc_term(&@1), loc_val(&@3)));
+ $$ = term;
+}
+|
+PE_TERM
+{
+ struct parse_events_term *term;
+
+ ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, loc_term(&@1), 0));
+ $$ = term;
+}
+|
+PE_NAME array '=' PE_NAME
+{
+ struct parse_events_term *term;
+
+ if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, $4, loc_term(&@1), loc_val(&@4))) {
+ free($1);
+ free($4);
+ free($2.ranges);
+ YYABORT;
+ }
+ term->array = $2;
+ $$ = term;
+}
+|
+PE_NAME array '=' PE_VALUE
+{
+ struct parse_events_term *term;
+
+ if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+ $1, $4, false, loc_term(&@1), loc_val(&@4))) {
+ free($1);
+ free($2.ranges);
+ YYABORT;
+ }
+ term->array = $2;
+ $$ = term;
+}
+|
+PE_DRV_CFG_TERM
+{
+ struct parse_events_term *term;
+ char *config = strdup($1);
+
+ ABORT_ON(!config);
+ if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG,
+ config, $1, loc_term(&@1), 0)) {
+ free($1);
+ free(config);
+ YYABORT;
+ }
+ $$ = term;
+}
+
+array:
+'[' array_terms ']'
+{
+ $$ = $2;
+}
+|
+PE_ARRAY_ALL
+{
+ $$.nr_ranges = 0;
+ $$.ranges = NULL;
+}
+
+array_terms:
+array_terms ',' array_term
+{
+ struct parse_events_array new_array;
+
+ new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges;
+ new_array.ranges = realloc($1.ranges,
+ sizeof(new_array.ranges[0]) *
+ new_array.nr_ranges);
+ ABORT_ON(!new_array.ranges);
+ memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges,
+ $3.nr_ranges * sizeof(new_array.ranges[0]));
+ free($3.ranges);
+ $$ = new_array;
+}
+|
+array_term
+
+array_term:
+PE_VALUE
+{
+ struct parse_events_array array;
+
+ array.nr_ranges = 1;
+ array.ranges = malloc(sizeof(array.ranges[0]));
+ ABORT_ON(!array.ranges);
+ array.ranges[0].start = $1;
+ array.ranges[0].length = 1;
+ $$ = array;
+}
+|
+PE_VALUE PE_ARRAY_RANGE PE_VALUE
+{
+ struct parse_events_array array;
+
+ ABORT_ON($3 < $1);
+ array.nr_ranges = 1;
+ array.ranges = malloc(sizeof(array.ranges[0]));
+ ABORT_ON(!array.ranges);
+ array.ranges[0].start = $1;
+ array.ranges[0].length = $3 - $1 + 1;
+ $$ = array;
+}
+
+sep_dc: ':' |
+
+sep_slash_slash_dc: '/' '/' | ':' |
+
+%%
+
+void parse_events_error(YYLTYPE *loc, void *parse_state,
+ void *scanner __maybe_unused,
+ char const *msg __maybe_unused)
+{
+ parse_events_evlist_error(parse_state, loc->last_column, "parser error");
+}
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 1d697cecf4ea..ad9e2de899da 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -66,8 +66,6 @@ perf-y += comm.o
perf-y += thread.o
perf-y += thread_map.o
perf-y += trace-event-parse.o
-perf-y += parse-events-flex.o
-perf-y += parse-events-bison.o
perf-y += pmu.o
perf-y += trace-event-read.o
perf-y += trace-event-info.o
@@ -209,16 +207,6 @@ CFLAGS_llvm-utils.o += -DPERF_INCLUDE_DIR="BUILD_STR($(perf_include_dir_SQ))"
# avoid compiler warnings in 32-bit mode
CFLAGS_genelf_debug.o += -Wno-packed
-$(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.h: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
- $(call rule_mkdir)
- $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/parse-events-flex.c \
- --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $<
-
-$(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/parse-events-bison.h: util/parse-events.y
- $(call rule_mkdir)
- $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) $(BISON_FILE_PREFIX_MAP) \
- -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
-
$(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-flex.h: util/expr.l $(OUTPUT)util/expr-bison.c
$(call rule_mkdir)
$(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/expr-flex.c \
@@ -239,7 +227,6 @@ ifeq ($(FLEX_GE_26),1)
else
flex_flags := -w
endif
-CFLAGS_parse-events-flex.o += $(flex_flags)
CFLAGS_expr-flex.o += $(flex_flags)
bison_flags := -DYYENABLE_NLS=0
@@ -249,10 +236,8 @@ ifeq ($(BISON_GE_35),1)
else
bison_flags += -w
endif
-CFLAGS_parse-events-bison.o += $(bison_flags)
CFLAGS_expr-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags)
-$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
$(OUTPUT)util/expr.o: $(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-bison.c
CFLAGS_bitmap.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 7b171252083c..44980b34e367 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -23,9 +23,6 @@
#include "debug.h"
#include <api/fs/tracing_path.h>
#include <perf/cpumap.h>
-#include "parse-events-bison.h"
-#define YY_EXTRA_TYPE void*
-#include "parse-events-flex.h"
#include "pmu.h"
#include "thread_map.h"
#include "probe-file.h"
@@ -41,10 +38,6 @@
#define MAX_NAME_LEN 100
-#ifdef PARSER_DEBUG
-extern int parse_events_debug;
-#endif
-int parse_events_parse(void *parse_state, void *scanner);
static int get_config_terms(struct list_head *head_config,
struct list_head *head_terms __maybe_unused);
static int parse_events__with_hybrid_pmu(struct parse_events_state *parse_state,
@@ -1913,37 +1906,6 @@ perf_pmu__parse_check(const char *name)
return r ? r->type : PMU_EVENT_SYMBOL_ERR;
}
-static int parse_events__scanner(const char *str,
- struct parse_events_state *parse_state,
- bool terms)
-{
- YY_BUFFER_STATE buffer;
- void *scanner;
- int ret;
-
- if (terms)
- parse_state->stoken = PE_START_TERMS;
- else
- parse_state->stoken = PE_START_EVENTS;
-
- ret = parse_events_lex_init_extra(parse_state, &scanner);
- if (ret)
- return ret;
-
- buffer = parse_events__scan_string(str, scanner);
-
-#ifdef PARSER_DEBUG
- parse_events_debug = 1;
- parse_events_set_debug(1, scanner);
-#endif
- ret = parse_events_parse(parse_state, scanner);
-
- parse_events__flush_buffer(buffer, scanner);
- parse_events__delete_buffer(buffer, scanner);
- parse_events_lex_destroy(scanner);
- return ret;
-}
-
/*
* parse event config string, return a list of event terms.
*/
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
deleted file mode 100644
index 1cebd5fcdb5d..000000000000
--- a/tools/perf/util/parse-events.l
+++ /dev/null
@@ -1,411 +0,0 @@
-
-%option reentrant
-%option bison-bridge
-%option prefix="parse_events_"
-%option stack
-%option bison-locations
-%option yylineno
-%option reject
-
-%{
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include "parse-events.h"
-#include "parse-events-bison.h"
-#include "evsel.h"
-
-char *parse_events_get_text(yyscan_t yyscanner);
-YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
-
-static int __value(YYSTYPE *yylval, char *str, int base, int token)
-{
- u64 num;
-
- errno = 0;
- num = strtoull(str, NULL, base);
- if (errno)
- return PE_ERROR;
-
- yylval->num = num;
- return token;
-}
-
-static int value(yyscan_t scanner, int base)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
- char *text = parse_events_get_text(scanner);
-
- return __value(yylval, text, base, PE_VALUE);
-}
-
-static int str(yyscan_t scanner, int token)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
- char *text = parse_events_get_text(scanner);
-
- if (text[0] != '\'') {
- yylval->str = strdup(text);
- } else {
- /*
- * If a text tag specified on the command line
- * contains opening single quite ' then it is
- * expected that the tag ends with single quote
- * as well, like this:
- * name=\'CPU_CLK_UNHALTED.THREAD:cmask=1\'
- * quotes need to be escaped to bypass shell
- * processing.
- */
- yylval->str = strndup(&text[1], strlen(text) - 2);
- }
-
- return token;
-}
-
-static int raw(yyscan_t scanner, struct parse_events_state *parse_state)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
- char *text = parse_events_get_text(scanner);
-
- if (parse_state->ops->parse_check(text) == PMU_EVENT_SYMBOL)
- return str(scanner, PE_NAME);
-
- return __value(yylval, text + 1, 16, PE_RAW);
-}
-
-static bool isbpf_suffix(char *text)
-{
- int len = strlen(text);
-
- if (len < 2)
- return false;
- if ((text[len - 1] == 'c' || text[len - 1] == 'o') &&
- text[len - 2] == '.')
- return true;
- if (len > 4 && !strcmp(text + len - 4, ".obj"))
- return true;
- return false;
-}
-
-static bool isbpf(yyscan_t scanner)
-{
- char *text = parse_events_get_text(scanner);
- struct stat st;
-
- if (!isbpf_suffix(text))
- return false;
-
- return stat(text, &st) == 0;
-}
-
-/*
- * This function is called when the parser gets two kind of input:
- *
- * @cfg1 or @cfg2=config
- *
- * The leading '@' is stripped off before 'cfg1' and 'cfg2=config' are given to
- * bison. In the latter case it is necessary to keep the string intact so that
- * the PMU kernel driver can determine what configurable is associated to
- * 'config'.
- */
-static int drv_str(yyscan_t scanner, int token)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
- char *text = parse_events_get_text(scanner);
-
- /* Strip off the '@' */
- yylval->str = strdup(text + 1);
- return token;
-}
-
-#define REWIND(__alloc) \
-do { \
- YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \
- char *text = parse_events_get_text(yyscanner); \
- \
- if (__alloc) \
- __yylval->str = strdup(text); \
- \
- yycolumn -= strlen(text); \
- yyless(0); \
-} while (0)
-
-static int pmu_str_check(yyscan_t scanner, struct parse_events_state *parse_state)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
- char *text = parse_events_get_text(scanner);
-
- yylval->str = strdup(text);
-
- /*
- * If we're not testing then parse check determines the PMU event type
- * which if it isn't a PMU returns PE_NAME. When testing the result of
- * parse check can't be trusted so we return PE_PMU_EVENT_FAKE unless
- * an '!' is present in which case the text can't be a PMU name.
- */
- switch (parse_state->ops->parse_check(text)) {
- case PMU_EVENT_SYMBOL_PREFIX:
- return PE_PMU_EVENT_PRE;
- case PMU_EVENT_SYMBOL_SUFFIX:
- return PE_PMU_EVENT_SUF;
- case PMU_EVENT_SYMBOL:
- return parse_state->fake_pmu
- ? PE_PMU_EVENT_FAKE : PE_KERNEL_PMU_EVENT;
- default:
- return parse_state->fake_pmu && !strchr(text,'!')
- ? PE_PMU_EVENT_FAKE : PE_NAME;
- }
-}
-
-static int sym(yyscan_t scanner, int type, int config)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
-
- yylval->num = (type << 16) + config;
- return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
-}
-
-static int tool(yyscan_t scanner, enum perf_tool_event event)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
-
- yylval->num = event;
- return PE_VALUE_SYM_TOOL;
-}
-
-static int term(yyscan_t scanner, int type)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
-
- yylval->num = type;
- return PE_TERM;
-}
-
-#define YY_USER_ACTION \
-do { \
- yylloc->last_column = yylloc->first_column; \
- yylloc->first_column = yycolumn; \
- yycolumn += yyleng; \
-} while (0);
-
-#define USER_REJECT \
- yycolumn -= yyleng; \
- REJECT
-
-%}
-
-%x mem
-%s config
-%x event
-%x array
-
-group [^,{}/]*[{][^}]*[}][^,{}/]*
-event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
-event [^,{}/]+
-bpf_object [^,{}]+\.(o|bpf)[a-zA-Z0-9._]*
-bpf_source [^,{}]+\.c[a-zA-Z0-9._]*
-
-num_dec [0-9]+
-num_hex 0x[a-fA-F0-9]+
-num_raw_hex [a-fA-F0-9]+
-name [a-zA-Z_*?\[\]][a-zA-Z0-9_*?.\[\]!]*
-name_tag [\'][a-zA-Z_*?\[\]][a-zA-Z0-9_*?\-,\.\[\]:=]*[\']
-name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
-drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
-/* If you add a modifier you need to update check_modifier() */
-modifier_event [ukhpPGHSDIWeb]+
-modifier_bp [rwx]{1,3}
-
-%%
-
-%{
- struct parse_events_state *_parse_state = parse_events_get_extra(yyscanner);
-
- {
- int start_token = _parse_state->stoken;
-
- if (start_token == PE_START_TERMS)
- BEGIN(config);
- else if (start_token == PE_START_EVENTS)
- BEGIN(event);
-
- if (start_token) {
- _parse_state->stoken = 0;
- /*
- * The flex parser does not init locations variable
- * via the scan_string interface, so we need do the
- * init in here.
- */
- yycolumn = 0;
- return start_token;
- }
- }
-%}
-
-<event>{
-
-{group} {
- BEGIN(INITIAL);
- REWIND(0);
- }
-
-{event_pmu} |
-{bpf_object} |
-{bpf_source} |
-{event} {
- BEGIN(INITIAL);
- REWIND(1);
- return PE_EVENT_NAME;
- }
-
-<<EOF>> {
- BEGIN(INITIAL);
- REWIND(0);
- }
-, {
- return ',';
- }
-}
-
-<array>{
-"]" { BEGIN(config); return ']'; }
-{num_dec} { return value(yyscanner, 10); }
-{num_hex} { return value(yyscanner, 16); }
-, { return ','; }
-"\.\.\." { return PE_ARRAY_RANGE; }
-}
-
-<config>{
- /*
- * Please update config_term_names when new static term is added.
- */
-config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
-config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
-config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
-name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
-period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
-freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); }
-branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
-time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
-call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
-stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
-max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); }
-nr { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_EVENTS); }
-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
-no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
-no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
-percore { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); }
-aux-output { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT); }
-aux-sample-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE); }
-metric-id { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); }
-r{num_raw_hex} { return raw(yyscanner, _parse_state); }
-r0x{num_raw_hex} { return raw(yyscanner, _parse_state); }
-, { return ','; }
-"/" { BEGIN(INITIAL); return '/'; }
-{name_minus} { return str(yyscanner, PE_NAME); }
-\[all\] { return PE_ARRAY_ALL; }
-"[" { BEGIN(array); return '['; }
-@{drv_cfg_term} { return drv_str(yyscanner, PE_DRV_CFG_TERM); }
-}
-
-<mem>{
-{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
-: { return ':'; }
-"/" { return '/'; }
-{num_dec} { return value(yyscanner, 10); }
-{num_hex} { return value(yyscanner, 16); }
- /*
- * We need to separate 'mem:' scanner part, in order to get specific
- * modifier bits parsed out. Otherwise we would need to handle PE_NAME
- * and we'd need to parse it manually. During the escape from <mem>
- * state we need to put the escaping char back, so we dont miss it.
- */
-. { unput(*yytext); BEGIN(INITIAL); }
- /*
- * We destroy the scanner after reaching EOF,
- * but anyway just to be sure get back to INIT state.
- */
-<<EOF>> { BEGIN(INITIAL); }
-}
-
-cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
-stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
-stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
-instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
-cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
-cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
-branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
-branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
-bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
-ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
-cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
-task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
-page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
-minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
-major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
-context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
-cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
-alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
-emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
-dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
-duration_time { return tool(yyscanner, PERF_TOOL_DURATION_TIME); }
-bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
-cgroup-switches { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); }
-
- /*
- * We have to handle the kernel PMU event cycles-ct/cycles-t/mem-loads/mem-stores separately.
- * Because the prefix cycles is mixed up with cpu-cycles.
- * loads and stores are mixed up with cache event
- */
-cycles-ct |
-cycles-t |
-mem-loads |
-mem-loads-aux |
-mem-stores |
-topdown-[a-z-]+ |
-tx-capacity-[a-z-]+ |
-el-capacity-[a-z-]+ { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
-
-L1-dcache|l1-d|l1d|L1-data |
-L1-icache|l1-i|l1i|L1-instruction |
-LLC|L2 |
-dTLB|d-tlb|Data-TLB |
-iTLB|i-tlb|Instruction-TLB |
-branch|branches|bpu|btb|bpc |
-node { return str(yyscanner, PE_NAME_CACHE_TYPE); }
-
-load|loads|read |
-store|stores|write |
-prefetch|prefetches |
-speculative-read|speculative-load |
-refs|Reference|ops|access |
-misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
-
-mem: { BEGIN(mem); return PE_PREFIX_MEM; }
-r{num_raw_hex} { return raw(yyscanner, _parse_state); }
-{num_dec} { return value(yyscanner, 10); }
-{num_hex} { return value(yyscanner, 16); }
-
-{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
-{bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); }
-{bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); }
-{name} { return pmu_str_check(yyscanner, _parse_state); }
-{name_tag} { return str(yyscanner, PE_NAME); }
-"/" { BEGIN(config); return '/'; }
-- { return '-'; }
-, { BEGIN(event); return ','; }
-: { return ':'; }
-"{" { BEGIN(event); return '{'; }
-"}" { return '}'; }
-= { return '='; }
-\n { }
-. { }
-
-%%
-
-int parse_events_wrap(void *scanner __maybe_unused)
-{
- return 1;
-}
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
deleted file mode 100644
index 38d29946fa07..000000000000
--- a/tools/perf/util/parse-events.y
+++ /dev/null
@@ -1,992 +0,0 @@
-%define api.pure full
-%parse-param {void *_parse_state}
-%parse-param {void *scanner}
-%lex-param {void* scanner}
-%locations
-
-%{
-
-#define YYDEBUG 1
-
-#include <fnmatch.h>
-#include <stdio.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/zalloc.h>
-#include "pmu.h"
-#include "evsel.h"
-#include "parse-events.h"
-#include "parse-events-bison.h"
-
-void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
-
-#define ABORT_ON(val) \
-do { \
- if (val) \
- YYABORT; \
-} while (0)
-
-static struct list_head* alloc_list(void)
-{
- struct list_head *list;
-
- list = malloc(sizeof(*list));
- if (!list)
- return NULL;
-
- INIT_LIST_HEAD(list);
- return list;
-}
-
-static void free_list_evsel(struct parse_events_state *parse_state,
- struct list_head* list_evsel)
-{
- struct perf_evsel *evsel, *tmp;
-
- list_for_each_entry_safe(evsel, tmp, list_evsel, node) {
- list_del_init(&evsel->node);
- parse_state->ops->perf_evsel__delete(evsel);
- }
- free(list_evsel);
-}
-
-/* list_event is assumed to point to malloc'ed memory */
-static void update_lists(struct list_head *list_event,
- struct list_head *list_all)
-{
- /*
- * Called for single event definition. Update the
- * 'all event' list, and reinit the 'single event'
- * list, for next event definition.
- */
- list_splice_tail(list_event, list_all);
- free(list_event);
-}
-
-static void inc_group_count(struct list_head *list,
- struct parse_events_state *parse_state)
-{
- /* Count groups only have more than 1 members */
- if (!list_is_last(list->next, list))
- parse_state->nr_groups++;
-}
-
-static int loc_term(void *loc_term_)
-{
- YYLTYPE *loc_term = loc_term_;
-
- return loc_term ? loc_term->first_column : 0;
-}
-
-static int loc_val(void *loc_val_)
-{
- YYLTYPE *loc_val = loc_val_;
-
- return loc_val ? loc_val->first_column : 0;
-}
-
-%}
-
-%token PE_START_EVENTS PE_START_TERMS
-%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
-%token PE_VALUE_SYM_TOOL
-%token PE_EVENT_NAME
-%token PE_NAME
-%token PE_BPF_OBJECT PE_BPF_SOURCE
-%token PE_MODIFIER_EVENT PE_MODIFIER_BP
-%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
-%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
-%token PE_ERROR
-%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE
-%token PE_ARRAY_ALL PE_ARRAY_RANGE
-%token PE_DRV_CFG_TERM
-%type <num> PE_VALUE
-%type <num> PE_VALUE_SYM_HW
-%type <num> PE_VALUE_SYM_SW
-%type <num> PE_VALUE_SYM_TOOL
-%type <num> PE_RAW
-%type <num> PE_TERM
-%type <num> value_sym
-%type <str> PE_NAME
-%type <str> PE_BPF_OBJECT
-%type <str> PE_BPF_SOURCE
-%type <str> PE_NAME_CACHE_TYPE
-%type <str> PE_NAME_CACHE_OP_RESULT
-%type <str> PE_MODIFIER_EVENT
-%type <str> PE_MODIFIER_BP
-%type <str> PE_EVENT_NAME
-%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE
-%type <str> PE_DRV_CFG_TERM
-%type <str> event_pmu_name
-%destructor { free ($$); } <str>
-%type <term> event_term
-%destructor { parse_events_term__delete ($$); } <term>
-%type <list_terms> event_config
-%type <list_terms> opt_event_config
-%type <list_terms> opt_pmu_config
-%destructor { parse_events_terms__delete ($$); } <list_terms>
-%type <list_evsel> event_pmu
-%type <list_evsel> event_legacy_symbol
-%type <list_evsel> event_legacy_cache
-%type <list_evsel> event_legacy_mem
-%type <list_evsel> event_legacy_tracepoint
-%type <list_evsel> event_legacy_numeric
-%type <list_evsel> event_legacy_raw
-%type <list_evsel> event_bpf_file
-%type <list_evsel> event_def
-%type <list_evsel> event_mod
-%type <list_evsel> event_name
-%type <list_evsel> event
-%type <list_evsel> events
-%type <list_evsel> group_def
-%type <list_evsel> group
-%type <list_evsel> groups
-%destructor { free_list_evsel (_parse_state, $$); } <list_evsel>
-%type <tracepoint_name> tracepoint_name
-%destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
-%type <array> array
-%type <array> array_term
-%type <array> array_terms
-%destructor { free ($$.ranges); } <array>
-
-%union
-{
- char *str;
- u64 num;
- struct list_head *list_evsel;
- struct list_head *list_terms;
- struct parse_events_term *term;
- struct tracepoint_name {
- char *sys;
- char *event;
- } tracepoint_name;
- struct parse_events_array array;
-}
-%%
-
-start:
-PE_START_EVENTS start_events
-|
-PE_START_TERMS start_terms
-
-start_events: groups
-{
- struct parse_events_state *parse_state = _parse_state;
-
- /* frees $1 */
- update_lists($1, &parse_state->list);
-}
-
-groups:
-groups ',' group
-{
- struct list_head *list = $1;
- struct list_head *group = $3;
-
- /* frees $3 */
- update_lists(group, list);
- $$ = list;
-}
-|
-groups ',' event
-{
- struct list_head *list = $1;
- struct list_head *event = $3;
-
- /* frees $3 */
- update_lists(event, list);
- $$ = list;
-}
-|
-group
-|
-event
-
-group:
-group_def ':' PE_MODIFIER_EVENT
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list = $1;
- int err;
-
- err = parse_events__modifier_group(list, $3, parse_state->guest);
- free($3);
- if (err) {
- struct parse_events_error *error = parse_state->error;
-
- parse_events__handle_error(error, @3.first_column,
- strdup("Bad modifier"), NULL);
- free_list_evsel(parse_state, list);
- YYABORT;
- }
- $$ = list;
-}
-|
-group_def
-
-group_def:
-PE_NAME '{' events '}'
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list = $3;
-
- inc_group_count(list, _parse_state);
- parse_state->ops->set_leader($1, list, parse_state);
- free($1);
- $$ = list;
-}
-|
-'{' events '}'
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list = $2;
-
- inc_group_count(list, _parse_state);
- parse_state->ops->set_leader(NULL, list, parse_state);
- $$ = list;
-}
-
-events:
-events ',' event
-{
- struct list_head *event = $3;
- struct list_head *list = $1;
-
- /* frees $3 */
- update_lists(event, list);
- $$ = list;
-}
-|
-event
-
-event: event_mod
-
-event_mod:
-event_name PE_MODIFIER_EVENT
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list = $1;
- int err;
-
- /*
- * Apply modifier on all events added by single event definition
- * (there could be more events added for multiple tracepoint
- * definitions via '*?'.
- */
- err = parse_events__modifier_event(list, $2, false, parse_state->guest);
- free($2);
- if (err) {
- struct parse_events_error *error = parse_state->error;
-
- parse_events__handle_error(error, @2.first_column,
- strdup("Bad modifier"), NULL);
- free_list_evsel(parse_state, list);
- YYABORT;
- }
- $$ = list;
-}
-|
-event_name
-
-event_name:
-PE_EVENT_NAME event_def
-{
- int err;
-
- err = parse_events_name($2, $1);
- free($1);
- if (err) {
- free_list_evsel(_parse_state, $2);
- YYABORT;
- }
- $$ = $2;
-}
-|
-event_def
-
-event_def: event_pmu |
- event_legacy_symbol |
- event_legacy_cache sep_dc |
- event_legacy_mem |
- event_legacy_tracepoint sep_dc |
- event_legacy_numeric sep_dc |
- event_legacy_raw sep_dc |
- event_bpf_file
-
-event_pmu_name:
-PE_NAME | PE_PMU_EVENT_PRE
-
-event_pmu:
-event_pmu_name opt_pmu_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct parse_events_error *error = parse_state->error;
- struct list_head *list = NULL, *orig_terms = NULL;
-
-#define CLEANUP_YYABORT \
- do { \
- parse_events_terms__delete($2); \
- parse_events_terms__delete(orig_terms); \
- free(list); \
- free($1); \
- YYABORT; \
- } while(0)
-
- if (parse_events_copy_term_list($2, &orig_terms))
- CLEANUP_YYABORT;
-
- if (error)
- error->idx = @1.first_column;
-
- list = alloc_list();
- if (!list)
- CLEANUP_YYABORT;
- if (parse_state->ops->add_pmu(parse_state, list, $1, $2, orig_terms, false, false))
- CLEANUP_YYABORT;
- parse_events_terms__delete($2);
- parse_events_terms__delete(orig_terms);
- free($1);
- $$ = list;
-#undef CLEANUP_YYABORT
-}
-|
-PE_KERNEL_PMU_EVENT sep_dc
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- err = parse_state->ops->add_pmu_multi(parse_state, $1, NULL, &list);
- free($1);
- if (err < 0)
- YYABORT;
- $$ = list;
-}
-|
-PE_KERNEL_PMU_EVENT opt_pmu_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- /* frees $2 */
- err = parse_state->ops->add_pmu_multi(_parse_state, $1, $2, &list);
- free($1);
- if (err < 0)
- YYABORT;
- $$ = list;
-}
-|
-PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- char pmu_name[128];
-
- snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3);
- free($1);
- free($3);
- if (parse_state->ops->add_pmu_multi(_parse_state, pmu_name, NULL, &list) < 0)
- YYABORT;
- $$ = list;
-}
-|
-PE_PMU_EVENT_FAKE sep_dc
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- if (!list)
- YYABORT;
-
- err = parse_state->ops->add_pmu(parse_state, list, $1, NULL, NULL, false, false);
- free($1);
- if (err < 0) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-|
-PE_PMU_EVENT_FAKE opt_pmu_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- if (!list)
- YYABORT;
-
- err = parse_state->ops->add_pmu(parse_state, list, $1, $2, NULL, false, false);
- free($1);
- parse_events_terms__delete($2);
- if (err < 0) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-
-value_sym:
-PE_VALUE_SYM_HW
-|
-PE_VALUE_SYM_SW
-
-event_legacy_symbol:
-value_sym '/' event_config '/'
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int type = $1 >> 16;
- int config = $1 & 255;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_numeric(parse_state, list, type, config, $3);
- parse_events_terms__delete($3);
- if (err) {
- free_list_evsel(_parse_state, list);
- YYABORT;
- }
- $$ = list;
-}
-|
-value_sym sep_slash_slash_dc
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int type = $1 >> 16;
- int config = $1 & 255;
-
- list = alloc_list();
- ABORT_ON(!list);
- ABORT_ON(parse_state->ops->add_numeric(parse_state, list, type, config, NULL));
- $$ = list;
-}
-|
-PE_VALUE_SYM_TOOL sep_slash_slash_dc
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
-
- list = alloc_list();
- ABORT_ON(!list);
- ABORT_ON(parse_state->ops->add_tool(_parse_state, list, $1));
- $$ = list;
-}
-
-event_legacy_cache:
-PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct parse_events_error *error = parse_state->error;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_cache(parse_state, list, $1, $3, $5, error, $6);
- parse_events_terms__delete($6);
- free($1);
- free($3);
- free($5);
- if (err) {
- free_list_evsel(parse_state, list);
- YYABORT;
- }
- $$ = list;
-}
-|
-PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct parse_events_error *error = parse_state->error;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_cache(parse_state, list, $1, $3, NULL, error, $4);
- parse_events_terms__delete($4);
- free($1);
- free($3);
- if (err) {
- free_list_evsel(parse_state, list);
- YYABORT;
- }
- $$ = list;
-}
-|
-PE_NAME_CACHE_TYPE opt_event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct parse_events_error *error = parse_state->error;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_cache(parse_state, list, $1, NULL, NULL, error, $2);
- parse_events_terms__delete($2);
- free($1);
- if (err) {
- free_list_evsel(parse_state, list);
- YYABORT;
- }
- $$ = list;
-}
-
-event_legacy_mem:
-PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_breakpoint(parse_state, list, $2, $6, $4);
- free($6);
- if (err) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-|
-PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
-
- list = alloc_list();
- ABORT_ON(!list);
- if (parse_state->ops->add_breakpoint(parse_state, list, $2, NULL, $4)) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-|
-PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_breakpoint(parse_state, list, $2, $4, 0);
- free($4);
- if (err) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-|
-PE_PREFIX_MEM PE_VALUE sep_dc
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
-
- list = alloc_list();
- ABORT_ON(!list);
- if (parse_state->ops->add_breakpoint(parse_state, list, $2, NULL, 0)) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-
-event_legacy_tracepoint:
-tracepoint_name opt_event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct parse_events_error *error = parse_state->error;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- if (error)
- error->idx = @1.first_column;
-
- err = parse_state->ops->add_tracepoint(parse_state, list, $1.sys, $1.event,
- error, $2);
-
- parse_events_terms__delete($2);
- free($1.sys);
- free($1.event);
- if (err) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-
-tracepoint_name:
-PE_NAME '-' PE_NAME ':' PE_NAME
-{
- struct tracepoint_name tracepoint;
-
- ABORT_ON(asprintf(&tracepoint.sys, "%s-%s", $1, $3) < 0);
- tracepoint.event = $5;
- free($1);
- free($3);
- $$ = tracepoint;
-}
-|
-PE_NAME ':' PE_NAME
-{
- struct tracepoint_name tracepoint = {$1, $3};
-
- $$ = tracepoint;
-}
-
-event_legacy_numeric:
-PE_VALUE ':' PE_VALUE opt_event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_numeric(_parse_state, list, (u32)$1, $3, $4);
- parse_events_terms__delete($4);
- if (err) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-
-event_legacy_raw:
-PE_RAW opt_event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2);
- parse_events_terms__delete($2);
- if (err) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-
-event_bpf_file:
-PE_BPF_OBJECT opt_event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_bpf(parse_state, list, $1, false, $2);
- parse_events_terms__delete($2);
- free($1);
- if (err) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-|
-PE_BPF_SOURCE opt_event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- ABORT_ON(!list);
- err = parse_state->ops->add_bpf(parse_state, list, $1, true, $2);
- parse_events_terms__delete($2);
- if (err) {
- free(list);
- YYABORT;
- }
- $$ = list;
-}
-
-opt_event_config:
-'/' event_config '/'
-{
- $$ = $2;
-}
-|
-'/' '/'
-{
- $$ = NULL;
-}
-|
-{
- $$ = NULL;
-}
-
-opt_pmu_config:
-'/' event_config '/'
-{
- $$ = $2;
-}
-|
-'/' '/'
-{
- $$ = NULL;
-}
-
-start_terms: event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- if (parse_state->terms) {
- parse_events_terms__delete ($1);
- YYABORT;
- }
- parse_state->terms = $1;
-}
-
-event_config:
-event_config ',' event_term
-{
- struct list_head *head = $1;
- struct parse_events_term *term = $3;
-
- if (!head) {
- parse_events_term__delete(term);
- YYABORT;
- }
- list_add_tail(&term->list, head);
- $$ = $1;
-}
-|
-event_term
-{
- struct list_head *head = malloc(sizeof(*head));
- struct parse_events_term *term = $1;
-
- ABORT_ON(!head);
- INIT_LIST_HEAD(head);
- list_add_tail(&term->list, head);
- $$ = head;
-}
-
-event_term:
-PE_RAW
-{
- struct parse_events_term *term;
-
- ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_CONFIG,
- NULL, $1, false, loc_term(&@1), 0));
- $$ = term;
-}
-|
-PE_NAME '=' PE_NAME
-{
- struct parse_events_term *term;
-
- if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
- $1, $3, loc_term(&@1), loc_val(&@3))) {
- free($1);
- free($3);
- YYABORT;
- }
- $$ = term;
-}
-|
-PE_NAME '=' PE_VALUE
-{
- struct parse_events_term *term;
-
- if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
- $1, $3, false, loc_term(&@1), loc_val(&@3))) {
- free($1);
- YYABORT;
- }
- $$ = term;
-}
-|
-PE_NAME '=' PE_VALUE_SYM_HW
-{
- struct parse_events_term *term;
- int config = $3 & 255;
-
- if (parse_events_term__sym_hw(&term, $1, config)) {
- free($1);
- YYABORT;
- }
- $$ = term;
-}
-|
-PE_NAME
-{
- struct parse_events_term *term;
-
- if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
- $1, 1, true, loc_term(&@1), 0)) {
- free($1);
- YYABORT;
- }
- $$ = term;
-}
-|
-PE_VALUE_SYM_HW
-{
- struct parse_events_term *term;
- int config = $1 & 255;
-
- ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
- $$ = term;
-}
-|
-PE_TERM '=' PE_NAME
-{
- struct parse_events_term *term;
-
- if (parse_events_term__str(&term, (int)$1, NULL, $3,
- loc_term(&@1), loc_val(&@3))) {
- free($3);
- YYABORT;
- }
- $$ = term;
-}
-|
-PE_TERM '=' PE_VALUE
-{
- struct parse_events_term *term;
-
- ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false,
- loc_term(&@1), loc_val(&@3)));
- $$ = term;
-}
-|
-PE_TERM
-{
- struct parse_events_term *term;
-
- ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, loc_term(&@1), 0));
- $$ = term;
-}
-|
-PE_NAME array '=' PE_NAME
-{
- struct parse_events_term *term;
-
- if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
- $1, $4, loc_term(&@1), loc_val(&@4))) {
- free($1);
- free($4);
- free($2.ranges);
- YYABORT;
- }
- term->array = $2;
- $$ = term;
-}
-|
-PE_NAME array '=' PE_VALUE
-{
- struct parse_events_term *term;
-
- if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
- $1, $4, false, loc_term(&@1), loc_val(&@4))) {
- free($1);
- free($2.ranges);
- YYABORT;
- }
- term->array = $2;
- $$ = term;
-}
-|
-PE_DRV_CFG_TERM
-{
- struct parse_events_term *term;
- char *config = strdup($1);
-
- ABORT_ON(!config);
- if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG,
- config, $1, loc_term(&@1), 0)) {
- free($1);
- free(config);
- YYABORT;
- }
- $$ = term;
-}
-
-array:
-'[' array_terms ']'
-{
- $$ = $2;
-}
-|
-PE_ARRAY_ALL
-{
- $$.nr_ranges = 0;
- $$.ranges = NULL;
-}
-
-array_terms:
-array_terms ',' array_term
-{
- struct parse_events_array new_array;
-
- new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges;
- new_array.ranges = realloc($1.ranges,
- sizeof(new_array.ranges[0]) *
- new_array.nr_ranges);
- ABORT_ON(!new_array.ranges);
- memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges,
- $3.nr_ranges * sizeof(new_array.ranges[0]));
- free($3.ranges);
- $$ = new_array;
-}
-|
-array_term
-
-array_term:
-PE_VALUE
-{
- struct parse_events_array array;
-
- array.nr_ranges = 1;
- array.ranges = malloc(sizeof(array.ranges[0]));
- ABORT_ON(!array.ranges);
- array.ranges[0].start = $1;
- array.ranges[0].length = 1;
- $$ = array;
-}
-|
-PE_VALUE PE_ARRAY_RANGE PE_VALUE
-{
- struct parse_events_array array;
-
- ABORT_ON($3 < $1);
- array.nr_ranges = 1;
- array.ranges = malloc(sizeof(array.ranges[0]));
- ABORT_ON(!array.ranges);
- array.ranges[0].start = $1;
- array.ranges[0].length = $3 - $1 + 1;
- $$ = array;
-}
-
-sep_dc: ':' |
-
-sep_slash_slash_dc: '/' '/' | ':' |
-
-%%
-
-void parse_events_error(YYLTYPE *loc, void *parse_state,
- void *scanner __maybe_unused,
- char const *msg __maybe_unused)
-{
- parse_events_evlist_error(parse_state, loc->last_column, "parser error");
-}
--
2.31.1
next prev parent reply other threads:[~2021-11-08 13:42 UTC|newest]
Thread overview: 78+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-08 13:36 [RFC 00/59] libperf: Move in event parse code Jiri Olsa
2021-11-08 13:36 ` [PATCH 01/59] libperf: Move pmu-events.h file to libperf Jiri Olsa
2021-11-08 13:36 ` [PATCH 03/59] libperf: Move pmu-events build " Jiri Olsa
2021-11-08 13:36 ` [PATCH 04/59] libperf: Move perf_pmu__format_parse " Jiri Olsa
2021-11-08 13:36 ` [PATCH 05/59] tools api fs: Move in the fncache from perf Jiri Olsa
2021-11-08 17:46 ` Ian Rogers
2021-11-08 21:15 ` Jiri Olsa
2021-11-08 13:36 ` [PATCH 06/59] libperf: Move in the pmu hybrid support Jiri Olsa
2021-11-08 13:36 ` [PATCH 07/59] libperf: Move name to perf_evsel Jiri Olsa
2021-11-08 13:36 ` [PATCH 08/59] libperf: Move auto_merge_stats " Jiri Olsa
2021-11-08 13:36 ` [PATCH 09/59] libperf: Move config_terms " Jiri Olsa
2021-11-08 13:36 ` [PATCH 10/59] libperf: Move metric_id " Jiri Olsa
2021-11-08 13:36 ` [PATCH 11/59] libperf: Move tool_event " Jiri Olsa
2021-11-08 13:36 ` [PATCH 12/59] libperf: Move unit " Jiri Olsa
2021-11-08 13:36 ` [PATCH 13/59] libperf: Move exclude_GH " Jiri Olsa
2021-11-08 17:53 ` Ian Rogers
2021-11-08 21:16 ` Jiri Olsa
2021-11-08 13:36 ` [PATCH 14/59] libperf: Move sample_read " Jiri Olsa
2021-11-08 13:36 ` [PATCH 15/59] libperf: Move precise_max " Jiri Olsa
2021-11-08 13:36 ` [PATCH 16/59] libperf: Move weak_group " Jiri Olsa
2021-11-08 13:36 ` [PATCH 17/59] libperf: Move bpf_counter " Jiri Olsa
2021-11-08 13:36 ` [PATCH 18/59] libperf: Move group_name " Jiri Olsa
2021-11-08 17:58 ` Ian Rogers
2021-11-08 18:07 ` Arnaldo Carvalho de Melo
2021-11-08 21:19 ` Jiri Olsa
2021-11-08 13:36 ` [PATCH 19/59] perf tools: Fix parse_events_term__num call Jiri Olsa
2021-11-08 18:15 ` Ian Rogers
2021-11-08 21:21 ` Jiri Olsa
2021-11-08 13:36 ` [PATCH 20/59] perf tools: Pass parse_state all the way down to __add_event Jiri Olsa
2021-11-08 13:36 ` [PATCH 21/59] perf tools: Pass parse_state all the way down to add_tracepoint Jiri Olsa
2021-11-08 13:36 ` [PATCH 22/59] perf tools: Add evsel__new callback to parse_state_ops Jiri Olsa
2021-11-08 13:36 ` [PATCH 23/59] perf tools: Add evsel__new_tp " Jiri Olsa
2021-11-08 13:36 ` [PATCH 24/59] perf tools: Add loc_term and loc_val helpers to parse_events_term__str Jiri Olsa
2021-11-08 13:36 ` [PATCH 25/59] perf tools: Add loc_term and loc_val helpers to parse_events_term__num Jiri Olsa
2021-11-08 13:36 ` [PATCH 26/59] libperf: Move in the event_symbols_hw/event_symbols_sw Jiri Olsa
2021-11-08 13:36 ` [PATCH 27/59] libperf: Move in struct parse_events_term code Jiri Olsa
2021-11-08 13:36 ` [PATCH 28/59] perf tools: Add perf_evsel__add_event function Jiri Olsa
2021-11-08 13:36 ` [PATCH 29/59] perf tools: Change struct parse_events_state::evlist to perf_evlist Jiri Olsa
2021-11-08 13:36 ` [PATCH 30/59] libperf: Move in struct parse_events_state Jiri Olsa
2021-11-08 18:21 ` Ian Rogers
2021-11-08 21:24 ` Jiri Olsa
2021-11-08 13:36 ` [PATCH 31/59] perf tools: Move event_attr_init in evsel__new_idx function Jiri Olsa
2021-11-08 13:36 ` [PATCH 32/59] libperf: Move in perf_pmu__warn_invalid_config function Jiri Olsa
2021-11-08 13:36 ` [PATCH 33/59] libperf: Move in perf_evsel__add_event function Jiri Olsa
2021-11-08 13:36 ` [PATCH 34/59] perf tools: Move parse_events_update_lists to parser unit Jiri Olsa
2021-11-08 13:36 ` [PATCH 35/59] libperf: Add perf_evsel__is_group_leader function Jiri Olsa
2021-11-08 13:36 ` [PATCH 36/59] perf tools: Make parse_events__modifier_event work over perf_evsel Jiri Olsa
2021-11-08 13:36 ` [PATCH 37/59] perf tool: Pass perf_guest in struct parse_events_state Jiri Olsa
2021-11-08 13:36 ` [PATCH 38/59] libperf: Move in parse_events__modifier_group/event functions Jiri Olsa
2021-11-08 13:36 ` [PATCH 39/59] libperf: Move in parse_events__handle_error function Jiri Olsa
2021-11-08 13:36 ` [PATCH 40/59] libperf: Move in parse_events_evlist_error function Jiri Olsa
2021-11-08 13:36 ` [PATCH 41/59] perf tools: Add perf_evsel__delete callback to struct parse_events_ops Jiri Olsa
2021-11-08 13:36 ` [PATCH 42/59] libperf: Move in parse_events_name function Jiri Olsa
2021-11-08 18:23 ` Ian Rogers
2021-11-08 21:24 ` Jiri Olsa
2021-11-08 13:36 ` [PATCH 43/59] perf tools: Move out parse_events_add_pmu fallback from parser code Jiri Olsa
2021-11-08 13:36 ` [PATCH 44/59] perf tools: Add add_pmu callback to struct parse_events_ops Jiri Olsa
2021-11-08 13:36 ` [PATCH 45/59] perf tools: Add add_pmu_multi " Jiri Olsa
2021-11-08 13:36 ` [PATCH 46/59] perf tools: Add add_numeric " Jiri Olsa
2021-11-08 18:27 ` Ian Rogers
2021-11-08 21:34 ` Jiri Olsa
2021-11-08 13:36 ` [PATCH 47/59] perf tools: Add add_cache " Jiri Olsa
2021-11-08 13:36 ` [PATCH 48/59] perf tools: Add add_breakpoint " Jiri Olsa
2021-11-08 13:37 ` [PATCH 49/59] perf tools: Add add_tracepoint " Jiri Olsa
2021-11-08 13:37 ` [PATCH 50/59] perf tools: Add add_bpf " Jiri Olsa
2021-11-08 13:37 ` [PATCH 51/59] perf tools: Add add_tool " Jiri Olsa
2021-11-08 13:37 ` [PATCH 52/59] perf tools: Add set_leader " Jiri Olsa
2021-11-08 13:37 ` [PATCH 53/59] perf tools: Add parse_check " Jiri Olsa
2021-11-08 13:37 ` [PATCH 54/59] perf tools: Move PE_* enums in parse_events__scanner Jiri Olsa
2021-11-08 13:37 ` Jiri Olsa [this message]
2021-11-08 13:37 ` [PATCH 56/59] libperf: Move in parse_events_add_breakpoint function Jiri Olsa
2021-11-08 13:37 ` [PATCH 57/59] libperf: Move in some lib objects from perf Jiri Olsa
2021-11-08 13:37 ` [PATCH 58/59] libperf: Add libperf_parse_events function Jiri Olsa
2021-11-08 13:37 ` [PATCH 59/59] libperf: Add parse-events test Jiri Olsa
2021-11-08 18:32 ` Ian Rogers
2021-11-08 21:37 ` Jiri Olsa
2021-11-08 18:50 ` [RFC 00/59] libperf: Move in event parse code Ian Rogers
2021-11-08 21:50 ` Jiri Olsa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211108133710.1352822-56-jolsa@kernel.org \
--to=jolsa@redhat.com \
--cc=acme@kernel.org \
--cc=irogers@google.com \
--cc=linux-perf-users@vger.kernel.org \
--cc=namhyung@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).