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)
{
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, ...)
{
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;
}
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);
+}
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);
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;
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) {
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)
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);
}
}
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,
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);
}
}
-/*
- * 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];
} else
newtListboxAppendEntry(tree, s, &self->ms);
- return strlen(s);
+ return ret;
}
static void map_symbol__annotate_browser(const struct map_symbol *self)
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,
};
.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,
};
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 */
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 */
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;
}
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]");
}
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;
};
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);