[PATCH 38/64] perf tools: Add term support for parse_events_error

2015-04-28 Thread Arnaldo Carvalho de Melo
From: Jiri Olsa 

Allowing event's term processing to report back error, like:

  $ perf record -e 'cpu/even=0x1/' ls
  event syntax error: 'cpu/even=0x1/'
   \___ unknown term

  valid terms: 
pc,any,inv,edge,cmask,event,in_tx,ldlat,umask,in_tx_cp,offcore_rsp,config,config1,config2,name,period,branch_type

Signed-off-by: Jiri Olsa 
Tested-by: Arnaldo Carvalho de Melo 
Cc: David Ahern 
Cc: Namhyung Kim 
Cc: Paul Mackerras 
Cc: Peter Zijlstra 
Link: 
http://lkml.kernel.org/r/1429729824-13932-7-git-send-email-jo...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/tests/pmu.c |  3 ++-
 tools/perf/util/parse-events.c |  2 +-
 tools/perf/util/parse-events.l |  4 +++
 tools/perf/util/pmu.c  | 57 +-
 tools/perf/util/pmu.h  |  6 +++--
 5 files changed, 62 insertions(+), 10 deletions(-)

diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index eeb68bb1972d..faa04e9d5d5f 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -152,7 +152,8 @@ int test__pmu(void)
if (ret)
break;
 
-   ret = perf_pmu__config_terms(, , terms, false);
+   ret = perf_pmu__config_terms(, , terms,
+false, NULL);
if (ret)
break;
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index d3f4567bd622..9c2e1aece477 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -675,7 +675,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
if (config_attr(, head_config))
return -EINVAL;
 
-   if (perf_pmu__config(pmu, , head_config))
+   if (perf_pmu__config(pmu, , head_config, data->error))
return -EINVAL;
 
evsel = __add_event(list, >idx, ,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 330dd2d35f5a..09e738fe9ea2 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -174,6 +174,10 @@ modifier_bp[rwx]{1,3}
 }
 
 {
+   /*
+* Please update formats_error_string any time
+* 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); }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 48411674da0f..4cd4f84caad7 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -579,6 +579,38 @@ static int pmu_resolve_param_term(struct parse_events_term 
*term,
return -1;
 }
 
+static char *formats_error_string(struct list_head *formats)
+{
+   struct perf_pmu_format *format;
+   char *error, *str;
+   static const char *static_terms = 
"config,config1,config2,name,period,branch_type\n";
+   unsigned i = 0;
+
+   if (!asprintf(, "valid terms:"))
+   return NULL;
+
+   /* sysfs exported terms */
+   list_for_each_entry(format, formats, list) {
+   char c = i++ ? ',' : ' ';
+
+   error = str;
+   if (!asprintf(, "%s%c%s", error, c, format->name))
+   goto fail;
+   free(error);
+   }
+
+   /* static terms */
+   error = str;
+   if (!asprintf(, "%s,%s", error, static_terms))
+   goto fail;
+
+   free(error);
+   return str;
+fail:
+   free(error);
+   return NULL;
+}
+
 /*
  * Setup one of config[12] attr members based on the
  * user input data - term parameter.
@@ -587,7 +619,7 @@ static int pmu_config_term(struct list_head *formats,
   struct perf_event_attr *attr,
   struct parse_events_term *term,
   struct list_head *head_terms,
-  bool zero)
+  bool zero, struct parse_events_error *error)
 {
struct perf_pmu_format *format;
__u64 *vp;
@@ -611,6 +643,11 @@ static int pmu_config_term(struct list_head *formats,
if (!format) {
if (verbose)
printf("Invalid event/parameter '%s'\n", term->config);
+   if (error) {
+   error->idx  = term->err_term;
+   error->str  = strdup("unknown term");
+   error->help = formats_error_string(formats);
+   }
return -EINVAL;
}
 
@@ -636,9 +673,14 @@ static int pmu_config_term(struct list_head *formats,
val = term->val.num;
else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
if (strcmp(term->val.str, "?")) {
-   if (verbose)
+   if (verbose) {

[PATCH 38/64] perf tools: Add term support for parse_events_error

2015-04-28 Thread Arnaldo Carvalho de Melo
From: Jiri Olsa jo...@kernel.org

Allowing event's term processing to report back error, like:

  $ perf record -e 'cpu/even=0x1/' ls
  event syntax error: 'cpu/even=0x1/'
   \___ unknown term

  valid terms: 
pc,any,inv,edge,cmask,event,in_tx,ldlat,umask,in_tx_cp,offcore_rsp,config,config1,config2,name,period,branch_type

Signed-off-by: Jiri Olsa jo...@kernel.org
Tested-by: Arnaldo Carvalho de Melo a...@redhat.com
Cc: David Ahern dsah...@gmail.com
Cc: Namhyung Kim namhy...@kernel.org
Cc: Paul Mackerras pau...@samba.org
Cc: Peter Zijlstra a.p.zijls...@chello.nl
Link: 
http://lkml.kernel.org/r/1429729824-13932-7-git-send-email-jo...@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo a...@redhat.com
---
 tools/perf/tests/pmu.c |  3 ++-
 tools/perf/util/parse-events.c |  2 +-
 tools/perf/util/parse-events.l |  4 +++
 tools/perf/util/pmu.c  | 57 +-
 tools/perf/util/pmu.h  |  6 +++--
 5 files changed, 62 insertions(+), 10 deletions(-)

diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index eeb68bb1972d..faa04e9d5d5f 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -152,7 +152,8 @@ int test__pmu(void)
if (ret)
break;
 
-   ret = perf_pmu__config_terms(formats, attr, terms, false);
+   ret = perf_pmu__config_terms(formats, attr, terms,
+false, NULL);
if (ret)
break;
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index d3f4567bd622..9c2e1aece477 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -675,7 +675,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
if (config_attr(attr, head_config))
return -EINVAL;
 
-   if (perf_pmu__config(pmu, attr, head_config))
+   if (perf_pmu__config(pmu, attr, head_config, data-error))
return -EINVAL;
 
evsel = __add_event(list, data-idx, attr,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 330dd2d35f5a..09e738fe9ea2 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -174,6 +174,10 @@ modifier_bp[rwx]{1,3}
 }
 
 config{
+   /*
+* Please update formats_error_string any time
+* 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); }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 48411674da0f..4cd4f84caad7 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -579,6 +579,38 @@ static int pmu_resolve_param_term(struct parse_events_term 
*term,
return -1;
 }
 
+static char *formats_error_string(struct list_head *formats)
+{
+   struct perf_pmu_format *format;
+   char *error, *str;
+   static const char *static_terms = 
config,config1,config2,name,period,branch_type\n;
+   unsigned i = 0;
+
+   if (!asprintf(str, valid terms:))
+   return NULL;
+
+   /* sysfs exported terms */
+   list_for_each_entry(format, formats, list) {
+   char c = i++ ? ',' : ' ';
+
+   error = str;
+   if (!asprintf(str, %s%c%s, error, c, format-name))
+   goto fail;
+   free(error);
+   }
+
+   /* static terms */
+   error = str;
+   if (!asprintf(str, %s,%s, error, static_terms))
+   goto fail;
+
+   free(error);
+   return str;
+fail:
+   free(error);
+   return NULL;
+}
+
 /*
  * Setup one of config[12] attr members based on the
  * user input data - term parameter.
@@ -587,7 +619,7 @@ static int pmu_config_term(struct list_head *formats,
   struct perf_event_attr *attr,
   struct parse_events_term *term,
   struct list_head *head_terms,
-  bool zero)
+  bool zero, struct parse_events_error *error)
 {
struct perf_pmu_format *format;
__u64 *vp;
@@ -611,6 +643,11 @@ static int pmu_config_term(struct list_head *formats,
if (!format) {
if (verbose)
printf(Invalid event/parameter '%s'\n, term-config);
+   if (error) {
+   error-idx  = term-err_term;
+   error-str  = strdup(unknown term);
+   error-help = formats_error_string(formats);
+   }
return -EINVAL;
}
 
@@ -636,9 +673,14 @@ static int pmu_config_term(struct list_head *formats,
val = term-val.num;
else if (term-type_val