summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/color.c53
-rw-r--r--tools/perf/util/color.h4
-rw-r--r--tools/perf/util/hist.c54
-rw-r--r--tools/perf/util/hist.h7
-rw-r--r--tools/perf/util/newt.c53
-rw-r--r--tools/perf/util/sort.c88
-rw-r--r--tools/perf/util/sort.h4
7 files changed, 149 insertions, 114 deletions
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 9da01914e0af..e191eb9a667f 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -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);
+}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 24e8809210bb..dea082b79602 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -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);
 
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index a46d09332462..f0794913d575 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -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,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index da6a8c1320fa..ad17f0ad798b 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -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);
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index b0210ae5b93c..edd628f5337b 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -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)
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 9b80c13cae46..31329a1cd324 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -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]");
 }
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 598568696f97..439ec5fa0f5f 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -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);