[PATCH 1/4] perf, tool: Add support to parse event group syntax

2012-07-19 Thread Jiri Olsa
Adding scanner/parser bits to parse event groups.

The grammar for group is:
  groups:  groups ',' group | group
  group:   group_name '{' events '}' group_mod
  group_name:  name | empty
  group_mod:   ':' group_mods | empty
  group_mods:  event_mod

It's possible to use standard event modifier as a modifier
for group. It'll be used as an update to existing event
modifiers.

It's necessary to use quoting ("'\) when specifying group on
command line, since {} characters are interpreted by most of
the shells.

It is now possible to specify groups in event syntax like:

  '{cycles,faults}'
   - anonymous group

  'group1{cycles,faults}
   - group with name 'group1'

  '{cycles,faults}:k
   - anonymous group with event modifier 'k'

  '{cpu-clock,task-clock},{minor-faults,major-faults}'
   - two anonymous groups

The grouping functionality itself is coming shortly.

Signed-off-by: Jiri Olsa 
---
 tools/perf/util/parse-events.c |   14 +-
 tools/perf/util/parse-events.h |4 +-
 tools/perf/util/parse-events.l |2 +
 tools/perf/util/parse-events.y |   93 ++--
 4 files changed, 97 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1aa721d..82938df 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -609,19 +609,29 @@ int parse_events_add_pmu(struct list_head **list, int 
*idx,
 pmu_event_name(head_config));
 }
 
+int parse_events__modifier_group(struct list_head *list __used,
+char *event_mod __used)
+{
+   return 0;
+}
+
+void parse_events__group(char *name __used, struct list_head *list __used)
+{
+}
+
 void parse_events_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 'signle event'
+* 'all event' list, and reinit the 'single event'
 * list, for next event definition.
 */
list_splice_tail(list_event, list_all);
free(list_event);
 }
 
-int parse_events_modifier(struct list_head *list, char *str)
+int parse_events__modifier_event(struct list_head *list, char *str)
 {
struct perf_evsel *evsel;
int exclude = 0, exclude_GH = 0;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ee9c218..c2f2ed9 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -79,7 +79,8 @@ int parse_events__term_str(struct parse_events__term **_term,
 int parse_events__term_clone(struct parse_events__term **new,
 struct parse_events__term *term);
 void parse_events__free_terms(struct list_head *terms);
-int parse_events_modifier(struct list_head *list, char *str);
+int parse_events__modifier_event(struct list_head *list, char *str);
+int parse_events__modifier_group(struct list_head *list, char *event_mod);
 int parse_events_add_tracepoint(struct list_head **list, int *idx,
char *sys, char *event);
 int parse_events_add_numeric(struct list_head **list, int *idx,
@@ -91,6 +92,7 @@ int parse_events_add_breakpoint(struct list_head **list, int 
*idx,
void *ptr, char *type);
 int parse_events_add_pmu(struct list_head **list, int *idx,
 char *pmu , struct list_head *head_config);
+void parse_events__group(char *name, struct list_head *list);
 void parse_events_update_lists(struct list_head *list_event,
   struct list_head *list_all);
 void parse_events_error(void *data, void *scanner, char const *msg);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 384ca74..153c6ee 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -151,6 +151,8 @@ r{num_raw_hex}  { return raw(yyscanner); }
 -  { return '-'; }
 ,  { return ','; }
 :  { return ':'; }
+"{"{ return '{'; }
+"}"{ return '}'; }
 =  { return '='; }
 \n { }
 
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 2bc5fbf..11b6972 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -30,7 +30,7 @@ do { \
 %token PE_NAME
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
-%token PE_PREFIX_MEM PE_PREFIX_RAW
+%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
 %token PE_ERROR
 %type  PE_VALUE
 %type  PE_VALUE_SYM_HW
@@ -53,6 +53,11 @@ do { \
 %type  event_legacy_numeric
 %type  event_legacy_raw
 %type  event_def
+%type  event
+%type  events
+%type  group_def
+%type  group
+%type  groups
 
 %union
 {
@@ -64,33 +69,95 @@ do { \
 %%
 
 start:
-PE_START_EVENTS events

[PATCH 1/4] perf, tool: Add support to parse event group syntax

2012-07-19 Thread Jiri Olsa
Adding scanner/parser bits to parse event groups.

The grammar for group is:
  groups:  groups ',' group | group
  group:   group_name '{' events '}' group_mod
  group_name:  name | empty
  group_mod:   ':' group_mods | empty
  group_mods:  event_mod

It's possible to use standard event modifier as a modifier
for group. It'll be used as an update to existing event
modifiers.

It's necessary to use quoting ('\) when specifying group on
command line, since {} characters are interpreted by most of
the shells.

It is now possible to specify groups in event syntax like:

  '{cycles,faults}'
   - anonymous group

  'group1{cycles,faults}
   - group with name 'group1'

  '{cycles,faults}:k
   - anonymous group with event modifier 'k'

  '{cpu-clock,task-clock},{minor-faults,major-faults}'
   - two anonymous groups

The grouping functionality itself is coming shortly.

Signed-off-by: Jiri Olsa jo...@redhat.com
---
 tools/perf/util/parse-events.c |   14 +-
 tools/perf/util/parse-events.h |4 +-
 tools/perf/util/parse-events.l |2 +
 tools/perf/util/parse-events.y |   93 ++--
 4 files changed, 97 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1aa721d..82938df 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -609,19 +609,29 @@ int parse_events_add_pmu(struct list_head **list, int 
*idx,
 pmu_event_name(head_config));
 }
 
+int parse_events__modifier_group(struct list_head *list __used,
+char *event_mod __used)
+{
+   return 0;
+}
+
+void parse_events__group(char *name __used, struct list_head *list __used)
+{
+}
+
 void parse_events_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 'signle event'
+* 'all event' list, and reinit the 'single event'
 * list, for next event definition.
 */
list_splice_tail(list_event, list_all);
free(list_event);
 }
 
-int parse_events_modifier(struct list_head *list, char *str)
+int parse_events__modifier_event(struct list_head *list, char *str)
 {
struct perf_evsel *evsel;
int exclude = 0, exclude_GH = 0;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ee9c218..c2f2ed9 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -79,7 +79,8 @@ int parse_events__term_str(struct parse_events__term **_term,
 int parse_events__term_clone(struct parse_events__term **new,
 struct parse_events__term *term);
 void parse_events__free_terms(struct list_head *terms);
-int parse_events_modifier(struct list_head *list, char *str);
+int parse_events__modifier_event(struct list_head *list, char *str);
+int parse_events__modifier_group(struct list_head *list, char *event_mod);
 int parse_events_add_tracepoint(struct list_head **list, int *idx,
char *sys, char *event);
 int parse_events_add_numeric(struct list_head **list, int *idx,
@@ -91,6 +92,7 @@ int parse_events_add_breakpoint(struct list_head **list, int 
*idx,
void *ptr, char *type);
 int parse_events_add_pmu(struct list_head **list, int *idx,
 char *pmu , struct list_head *head_config);
+void parse_events__group(char *name, struct list_head *list);
 void parse_events_update_lists(struct list_head *list_event,
   struct list_head *list_all);
 void parse_events_error(void *data, void *scanner, char const *msg);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 384ca74..153c6ee 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -151,6 +151,8 @@ r{num_raw_hex}  { return raw(yyscanner); }
 -  { return '-'; }
 ,  { return ','; }
 :  { return ':'; }
+{{ return '{'; }
+}{ return '}'; }
 =  { return '='; }
 \n { }
 
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 2bc5fbf..11b6972 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -30,7 +30,7 @@ do { \
 %token PE_NAME
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
-%token PE_PREFIX_MEM PE_PREFIX_RAW
+%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
 %token PE_ERROR
 %type num PE_VALUE
 %type num PE_VALUE_SYM_HW
@@ -53,6 +53,11 @@ do { \
 %type head event_legacy_numeric
 %type head event_legacy_raw
 %type head event_def
+%type head event
+%type head events
+%type head group_def
+%type head group
+%type head groups
 
 %union
 {
@@ -64,33 +69,95 @@