perf hist: Replace ->print() routines by ->snprintf() equivalents
authorArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 31 Mar 2010 14:33:40 +0000 (11:33 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 2 Apr 2010 19:28:15 +0000 (16:28 -0300)
Then hist_entry__fprintf will just us the newly introduced
hist_entry__snprintf, add the newline and fprintf it to the supplied
FILE descriptor.

This allows us to remove the use_browser checking in the color_printf
routines, that now got color_snprintf variants too.

The newt TUI browser (and other GUIs that may come in the future) don't
have to worry about stdio specific stuff in the strings they get from
the se->snprintf routines and instead use whatever means to do the
equivalent.

Also the newt TUI browser don't have to use the fmemopen() hack, instead
it can use the se->snprintf routines directly. For now tho use the
hist_entry__snprintf routine to reduce the patch size.

Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/color.c
tools/perf/util/color.h
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/newt.c
tools/perf/util/sort.c
tools/perf/util/sort.h

index 9da01914e0af644461e303650c7021c6fc383013..e191eb9a667f601f7dc52872e8e0258ae39af119 100644 (file)
@@ -166,6 +166,31 @@ int perf_color_default_config(const char *var, const char *value, void *cb)
        return perf_default_config(var, value, cb);
 }
 
+static int __color_vsnprintf(char *bf, size_t size, const char *color,
+                            const char *fmt, va_list args, const char *trail)
+{
+       int r = 0;
+
+       /*
+        * Auto-detect:
+        */
+       if (perf_use_color_default < 0) {
+               if (isatty(1) || pager_in_use())
+                       perf_use_color_default = 1;
+               else
+                       perf_use_color_default = 0;
+       }
+
+       if (perf_use_color_default && *color)
+               r += snprintf(bf, size, "%s", color);
+       r += vsnprintf(bf + r, size - r, fmt, args);
+       if (perf_use_color_default && *color)
+               r += snprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
+       if (trail)
+               r += snprintf(bf + r, size - r, "%s", trail);
+       return r;
+}
+
 static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
                va_list args, const char *trail)
 {
@@ -191,11 +216,28 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
        return r;
 }
 
+int color_vsnprintf(char *bf, size_t size, const char *color,
+                   const char *fmt, va_list args)
+{
+       return __color_vsnprintf(bf, size, color, fmt, args, NULL);
+}
+
 int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
 {
        return __color_vfprintf(fp, color, fmt, args, NULL);
 }
 
+int color_snprintf(char *bf, size_t size, const char *color,
+                  const char *fmt, ...)
+{
+       va_list args;
+       int r;
+
+       va_start(args, fmt);
+       r = color_vsnprintf(bf, size, color, fmt, args);
+       va_end(args);
+       return r;
+}
 
 int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
 {
@@ -203,10 +245,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
        int r;
 
        va_start(args, fmt);
-       if (use_browser)
-               r = vfprintf(fp, fmt, args);
-       else
-               r = color_vfprintf(fp, color, fmt, args);
+       r = color_vfprintf(fp, color, fmt, args);
        va_end(args);
        return r;
 }
@@ -277,3 +316,9 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
 
        return r;
 }
+
+int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent)
+{
+       const char *color = get_percent_color(percent);
+       return color_snprintf(bf, size, color, fmt, percent);
+}
index 24e8809210bbbc8af8e46c8f137b6e1032d199d7..dea082b7960210a17ccd2ee12d71a61a6192a503 100644 (file)
@@ -32,10 +32,14 @@ int perf_color_default_config(const char *var, const char *value, void *cb);
 int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty);
 void color_parse(const char *value, const char *var, char *dst);
 void color_parse_mem(const char *value, int len, const char *var, char *dst);
+int color_vsnprintf(char *bf, size_t size, const char *color,
+                   const char *fmt, va_list args);
 int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args);
 int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
+int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
 int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
 int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
+int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent);
 int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
 const char *get_percent_color(double percent);
 
index a46d093324623007b482d215819c98858f1e5d38..f0794913d575347ceb39b1fd80ccf1b8cd2e4476 100644 (file)
@@ -455,16 +455,17 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
        return ret;
 }
 
-size_t hist_entry__fprintf(struct hist_entry *self,
+int hist_entry__snprintf(struct hist_entry *self,
+                          char *s, size_t size,
                           struct perf_session *pair_session,
                           bool show_displacement,
-                          long displacement, FILE *fp,
+                          long displacement, bool color,
                           u64 session_total)
 {
        struct sort_entry *se;
        u64 count, total;
        const char *sep = symbol_conf.field_sep;
-       size_t ret;
+       int ret;
 
        if (symbol_conf.exclude_other && !self->parent)
                return 0;
@@ -477,17 +478,22 @@ size_t hist_entry__fprintf(struct hist_entry *self,
                total = session_total;
        }
 
-       if (total)
-               ret = percent_color_fprintf(fp, sep ? "%.2f" : "   %6.2f%%",
-                                           (count * 100.0) / total);
-       else
-               ret = fprintf(fp, sep ? "%lld" : "%12lld ", count);
+       if (total) {
+               if (color)
+                       ret = percent_color_snprintf(s, size,
+                                                    sep ? "%.2f" : "   %6.2f%%",
+                                                    (count * 100.0) / total);
+               else
+                       ret = snprintf(s, size, sep ? "%.2f" : "   %6.2f%%",
+                                      (count * 100.0) / total);
+       } else
+               ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count);
 
        if (symbol_conf.show_nr_samples) {
                if (sep)
-                       ret += fprintf(fp, "%c%lld", *sep, count);
+                       ret += snprintf(s + ret, size - ret, "%c%lld", *sep, count);
                else
-                       ret += fprintf(fp, "%11lld", count);
+                       ret += snprintf(s + ret, size - ret, "%11lld", count);
        }
 
        if (pair_session) {
@@ -507,9 +513,9 @@ size_t hist_entry__fprintf(struct hist_entry *self,
                        snprintf(bf, sizeof(bf), " ");
 
                if (sep)
-                       ret += fprintf(fp, "%c%s", *sep, bf);
+                       ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf);
                else
-                       ret += fprintf(fp, "%11.11s", bf);
+                       ret += snprintf(s + ret, size - ret, "%11.11s", bf);
 
                if (show_displacement) {
                        if (displacement)
@@ -518,9 +524,9 @@ size_t hist_entry__fprintf(struct hist_entry *self,
                                snprintf(bf, sizeof(bf), " ");
 
                        if (sep)
-                               ret += fprintf(fp, "%c%s", *sep, bf);
+                               ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf);
                        else
-                               ret += fprintf(fp, "%6.6s", bf);
+                               ret += snprintf(s + ret, size - ret, "%6.6s", bf);
                }
        }
 
@@ -528,11 +534,25 @@ size_t hist_entry__fprintf(struct hist_entry *self,
                if (se->elide)
                        continue;
 
-               ret += fprintf(fp, "%s", sep ?: "  ");
-               ret += se->print(fp, self, se->width ? *se->width : 0);
+               ret += snprintf(s + ret, size - ret, "%s", sep ?: "  ");
+               ret += se->snprintf(self, s + ret, size - ret,
+                                   se->width ? *se->width : 0);
        }
 
-       return ret + fprintf(fp, "\n");
+       return ret;
+}
+
+int hist_entry__fprintf(struct hist_entry *self,
+                       struct perf_session *pair_session,
+                       bool show_displacement,
+                       long displacement, FILE *fp,
+                       u64 session_total)
+{
+       char bf[512];
+       hist_entry__snprintf(self, bf, sizeof(bf), pair_session,
+                            show_displacement, displacement,
+                            true, session_total);
+       return fprintf(fp, "%s\n", bf);
 }
 
 static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp,
index da6a8c1320fa4741dc4f00d44c326874f722441c..ad17f0ad798bb38dee8e345a49fec9ba9e9b7120 100644 (file)
@@ -18,11 +18,16 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
                                                  u64 count, bool *hit);
 extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
 extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
-size_t hist_entry__fprintf(struct hist_entry *self,
+int hist_entry__fprintf(struct hist_entry *self,
                           struct perf_session *pair_session,
                           bool show_displacement,
                           long displacement, FILE *fp,
                           u64 session_total);
+int hist_entry__snprintf(struct hist_entry *self,
+                        char *bf, size_t size,
+                        struct perf_session *pair_session,
+                        bool show_displacement, long displacement,
+                        bool color, u64 session_total);
 void hist_entry__free(struct hist_entry *);
 
 u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples);
index b0210ae5b93c73fc4a81f5a8b9510266c5f8e02f..edd628f5337b1138a7a0e519bfa6a128bb1a555b 100644 (file)
@@ -294,60 +294,17 @@ static void hist_entry__append_callchain_browser(struct hist_entry *self,
        }
 }
 
-/*
- * FIXME: get lib/string.c linked with perf somehow
- */
-static char *skip_spaces(const char *str)
-{
-       while (isspace(*str))
-               ++str;
-       return (char *)str;
-}
-
-static char *strim(char *s)
-{
-       size_t size;
-       char *end;
-
-       s = skip_spaces(s);
-       size = strlen(s);
-       if (!size)
-               return s;
-
-       end = s + size - 1;
-       while (end >= s && isspace(*end))
-               end--;
-       *(end + 1) = '\0';
-
-       return s;
-}
-
 static size_t hist_entry__append_browser(struct hist_entry *self,
                                         newtComponent tree, u64 total)
 {
-       char bf[1024], *s;
-       FILE *fp;
+       char s[256];
+       size_t ret;
 
        if (symbol_conf.exclude_other && !self->parent)
                return 0;
 
-       fp = fmemopen(bf, sizeof(bf), "w");
-       if (fp == NULL)
-               return 0;
-
-       hist_entry__fprintf(self, NULL, false, 0, fp, total);
-       fclose(fp);
-
-       /*
-        * FIXME: We shouldn't need to trim, as the printing routines shouldn't
-        * add spaces it in the first place, the stdio output routines should
-        * call a __snprintf method instead of the current __print (that
-        * actually is a __fprintf) one, but get the raw string and _then_ add
-        * the newline, as this is a detail of stdio printing, not needed in
-        * other UIs, e.g. newt.
-        */
-       s = strim(bf);
-
+       ret = hist_entry__snprintf(self, s, sizeof(s), NULL,
+                                  false, 0, false, total);
        if (symbol_conf.use_callchain) {
                int indexes[2];
 
@@ -357,7 +314,7 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
        } else
                newtListboxAppendEntry(tree, s, &self->ms);
 
-       return strlen(s);
+       return ret;
 }
 
 static void map_symbol__annotate_browser(const struct map_symbol *self)
index 9b80c13cae466a0d5f3292f4b2fa6f596c06f75b..31329a1cd32442c7d77956de7af87d02be408ae1 100644 (file)
@@ -18,10 +18,21 @@ char * field_sep;
 
 LIST_HEAD(hist_entry__sort_list);
 
+static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
+                                      size_t size, unsigned int width);
+static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
+                                    size_t size, unsigned int width);
+static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
+                                   size_t size, unsigned int width);
+static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
+                                   size_t size, unsigned int width);
+static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
+                                      size_t size, unsigned int width);
+
 struct sort_entry sort_thread = {
        .header = "Command:  Pid",
        .cmp    = sort__thread_cmp,
-       .print  = sort__thread_print,
+       .snprintf = hist_entry__thread_snprintf,
        .width  = &threads__col_width,
 };
 
@@ -29,27 +40,27 @@ struct sort_entry sort_comm = {
        .header         = "Command",
        .cmp            = sort__comm_cmp,
        .collapse       = sort__comm_collapse,
-       .print          = sort__comm_print,
+       .snprintf       = hist_entry__comm_snprintf,
        .width          = &comms__col_width,
 };
 
 struct sort_entry sort_dso = {
        .header = "Shared Object",
        .cmp    = sort__dso_cmp,
-       .print  = sort__dso_print,
+       .snprintf = hist_entry__dso_snprintf,
        .width  = &dsos__col_width,
 };
 
 struct sort_entry sort_sym = {
        .header = "Symbol",
        .cmp    = sort__sym_cmp,
-       .print  = sort__sym_print,
+       .snprintf = hist_entry__sym_snprintf,
 };
 
 struct sort_entry sort_parent = {
        .header = "Parent symbol",
        .cmp    = sort__parent_cmp,
-       .print  = sort__parent_print,
+       .snprintf = hist_entry__parent_snprintf,
        .width  = &parent_symbol__col_width,
 };
 
@@ -85,45 +96,38 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
        return right->thread->pid - left->thread->pid;
 }
 
-int repsep_fprintf(FILE *fp, const char *fmt, ...)
+static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
 {
        int n;
        va_list ap;
 
        va_start(ap, fmt);
-       if (!field_sep)
-               n = vfprintf(fp, fmt, ap);
-       else {
-               char *bf = NULL;
-               n = vasprintf(&bf, fmt, ap);
-               if (n > 0) {
-                       char *sep = bf;
-
-                       while (1) {
-                               sep = strchr(sep, *field_sep);
-                               if (sep == NULL)
-                                       break;
-                               *sep = '.';
-                       }
+       n = vsnprintf(bf, size, fmt, ap);
+       if (field_sep && n > 0) {
+               char *sep = bf;
+
+               while (1) {
+                       sep = strchr(sep, *field_sep);
+                       if (sep == NULL)
+                               break;
+                       *sep = '.';
                }
-               fputs(bf, fp);
-               free(bf);
        }
        va_end(ap);
        return n;
 }
 
-size_t
-sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
+static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
+                                      size_t size, unsigned int width)
 {
-       return repsep_fprintf(fp, "%*s:%5d", width - 6,
+       return repsep_snprintf(bf, size, "%*s:%5d", width,
                              self->thread->comm ?: "", self->thread->pid);
 }
 
-size_t
-sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
+static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
+                                    size_t size, unsigned int width)
 {
-       return repsep_fprintf(fp, "%*s", width, self->thread->comm);
+       return repsep_snprintf(bf, size, "%*s", width, self->thread->comm);
 }
 
 /* --sort dso */
@@ -149,16 +153,16 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
        return strcmp(dso_name_l, dso_name_r);
 }
 
-size_t
-sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
+static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
+                                   size_t size, unsigned int width)
 {
        if (self->ms.map && self->ms.map->dso) {
                const char *dso_name = !verbose ? self->ms.map->dso->short_name :
                                                  self->ms.map->dso->long_name;
-               return repsep_fprintf(fp, "%-*s", width, dso_name);
+               return repsep_snprintf(bf, size, "%-*s", width, dso_name);
        }
 
-       return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
+       return repsep_snprintf(bf, size, "%*Lx", width, self->ip);
 }
 
 /* --sort symbol */
@@ -177,22 +181,22 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
        return (int64_t)(ip_r - ip_l);
 }
 
-
-size_t
-sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
+static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
+                                   size_t size, unsigned int width __used)
 {
        size_t ret = 0;
 
        if (verbose) {
                char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
-               ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o);
+               ret += repsep_snprintf(bf, size, "%#018llx %c ", self->ip, o);
        }
 
-       ret += repsep_fprintf(fp, "[%c] ", self->level);
+       ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level);
        if (self->ms.sym)
-               ret += repsep_fprintf(fp, "%s", self->ms.sym->name);
+               ret += repsep_snprintf(bf + ret, size - ret, "%s",
+                                      self->ms.sym->name);
        else
-               ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
+               ret += repsep_snprintf(bf + ret, size - ret, "%#016llx", self->ip);
 
        return ret;
 }
@@ -231,10 +235,10 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
        return strcmp(sym_l->name, sym_r->name);
 }
 
-size_t
-sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
+static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
+                                      size_t size, unsigned int width)
 {
-       return repsep_fprintf(fp, "%-*s", width,
+       return repsep_snprintf(bf, size, "%-*s", width,
                              self->parent ? self->parent->name : "[other]");
 }
 
index 598568696f97239a0c96b4c694f4202959db86ef..439ec5fa0f5f94fa542f5d0f0dcb4343554c59ba 100644 (file)
@@ -76,7 +76,8 @@ struct sort_entry {
 
        int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
        int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
-       size_t  (*print)(FILE *fp, struct hist_entry *, unsigned int width);
+       int     (*snprintf)(struct hist_entry *self, char *bf, size_t size,
+                           unsigned int width);
        unsigned int *width;
        bool    elide;
 };
@@ -86,7 +87,6 @@ extern struct list_head hist_entry__sort_list;
 
 void setup_sorting(const char * const usagestr[], const struct option *opts);
 
-extern int repsep_fprintf(FILE *fp, const char *fmt, ...);
 extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int);
 extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int);
 extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int);