perf tools: Asprintf like functions to format integer filter expression
authorArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 2 Jul 2015 20:48:23 +0000 (17:48 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 6 Jul 2015 13:21:46 +0000 (10:21 -0300)
  char *asprintf_expr_in_ints(const char *var, size_t nints, int *ints);
  char *asprintf_expr_not_in_ints(const char *var, size_t nints, int *ints);

Example of output formatted with those functions:

  # ./tp_filter 6 12 2015
  asprintf_expr_in_ints:     id == 6 || id == 12 || id == 2015
  asprintf_expr_not_in_ints: id != 6 && id != 12 && id != 2015
  #

It'll be used with, for instance, perf_evsel__set_filter_in_ints(), that
will be used in turn to ask the kernel to filter out all raw_syscalls:*
except for the ones specified by the user via:

 $ perf trace -e some,list,of,syscalls

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-jt07vfp6bd8y50c05j1t7hrn@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/string.c
tools/perf/util/util.h

index 6afd6106ceb51c8d5d3997acb161a255cacffa84..fc8781de62dbbed618e1f220225dfaeb195ef7f0 100644 (file)
@@ -357,3 +357,42 @@ void *memdup(const void *src, size_t len)
 
        return p;
 }
+
+char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints)
+{
+       /*
+        * FIXME: replace this with an expression using log10() when we
+        * find a suitable implementation, maybe the one in the dvb drivers...
+        *
+        * "%s == %d || " = log10(MAXINT) * 2 + 8 chars for the operators
+        */
+       size_t size = nints * 28 + 1; /* \0 */
+       size_t i, printed = 0;
+       char *expr = malloc(size);
+
+       if (expr) {
+               const char *or_and = "||", *eq_neq = "==";
+               char *e = expr;
+
+               if (!in) {
+                       or_and = "&&";
+                       eq_neq = "!=";
+               }
+
+               for (i = 0; i < nints; ++i) {
+                       if (printed == size)
+                               goto out_err_overflow;
+
+                       if (i > 0)
+                               printed += snprintf(e + printed, size - printed, " %s ", or_and);
+                       printed += scnprintf(e + printed, size - printed,
+                                            "%s %s %d", var, eq_neq, ints[i]);
+               }
+       }
+
+       return expr;
+
+out_err_overflow:
+       free(expr);
+       return NULL;
+}
index 8bce58b47a826918db8f395e3e6c2711e9bbba8e..20d625a4cacf665f186d0cd44428cb3c593d62a3 100644 (file)
@@ -339,4 +339,16 @@ int gzip_decompress_to_file(const char *input, int output_fd);
 int lzma_decompress_to_file(const char *input, int output_fd);
 #endif
 
+char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints);
+
+static inline char *asprintf_expr_in_ints(const char *var, size_t nints, int *ints)
+{
+       return asprintf_expr_inout_ints(var, true, nints, ints);
+}
+
+static inline char *asprintf_expr_not_in_ints(const char *var, size_t nints, int *ints)
+{
+       return asprintf_expr_inout_ints(var, false, nints, ints);
+}
+
 #endif /* GIT_COMPAT_UTIL_H */