From: Andi Kleen <a...@linux.intel.com>

When the user specifies a pmu directly, expand it automatically
with a prefix match, similar as we do for the normal aliases now.

This allows to specify attributes for duplicated boxes quickly.
For example uncore_cbox_{0,8}/.../ can be now specified as cbox/.../
and it gets automatically expanded.

Signed-off-by: Andi Kleen <a...@linux.intel.com>
---
 tools/perf/util/parse-events.c | 25 +++++++++++++++++++++++++
 tools/perf/util/parse-events.h |  3 +++
 tools/perf/util/parse-events.y | 27 +++++++++++++++++++++++++--
 3 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a2bbd17a0dc3..8b2333278988 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -2399,6 +2399,31 @@ int parse_events_term__clone(struct parse_events_term 
**new,
                        term->err_term, term->err_val);
 }
 
+int parse_events_copy_term_list(struct list_head *old,
+                                struct list_head **new)
+{
+       struct parse_events_term *term, *n;
+       int ret;
+
+       if (!old) {
+               *new = NULL;
+               return 0;
+       }
+
+       *new = malloc(sizeof(struct list_head));
+       if (!*new)
+               return -ENOMEM;
+       INIT_LIST_HEAD(*new);
+
+       list_for_each_entry (term, old, list) {
+               ret = parse_events_term__clone(&n, term);
+               if (ret)
+                       return ret;
+               list_add_tail(&n->list, *new);
+       }
+       return 0;
+}
+
 void parse_events_terms__purge(struct list_head *terms)
 {
        struct parse_events_term *term, *h;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index da246a3ddb69..7ea95c35095c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -164,6 +164,9 @@ int parse_events_add_breakpoint(struct list_head *list, int 
*idx,
 int parse_events_add_pmu(struct parse_events_evlist *data,
                         struct list_head *list, char *name,
                         struct list_head *head_config);
+int parse_events_copy_term_list(struct list_head *old,
+                                struct list_head **new);
+
 enum perf_pmu_event_symbol_type
 perf_pmu__parse_check(const char *name);
 void parse_events__set_leader(char *name, struct list_head *list);
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 3a5196380609..790f0dd598b9 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -224,11 +224,34 @@ event_pmu:
 PE_NAME opt_event_config
 {
        struct parse_events_evlist *data = _data;
-       struct list_head *list;
+       struct list_head *list, *orig_terms, *terms;
+
+       if (parse_events_copy_term_list($2, &orig_terms))
+               YYABORT;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_pmu(data, list, $1, $2));
+       if (parse_events_add_pmu(data, list, $1, $2)) {
+               struct perf_pmu *pmu = NULL;
+               int ok = 0;
+
+               while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+                       char *name = pmu->name;
+
+                       if (!strncmp(name, "uncore_", 7))
+                               name += 7;
+                       if (!strncmp($1, name, strlen($1))) {
+                               if (parse_events_copy_term_list(orig_terms, 
&terms))
+                                       YYABORT;
+                               if (!parse_events_add_pmu(data, list, 
pmu->name, terms))
+                                       ok++;
+                               parse_events_terms__delete(terms);
+                       }
+               }
+               if (!ok)
+                       YYABORT;
+       }
        parse_events_terms__delete($2);
+       parse_events_terms__delete(orig_terms);
        $$ = list;
 }
 |
-- 
2.5.5

Reply via email to