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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.