xref: /openbmc/linux/tools/perf/util/color.c (revision b7a001d2)
1e7f01d1eSArnaldo Carvalho de Melo #include <linux/kernel.h>
286470930SIngo Molnar #include "cache.h"
386470930SIngo Molnar #include "color.h"
4f77c6e9cSRamkumar Ramachandra #include <math.h>
586470930SIngo Molnar 
686470930SIngo Molnar int perf_use_color_default = -1;
786470930SIngo Molnar 
886470930SIngo Molnar int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty)
986470930SIngo Molnar {
1086470930SIngo Molnar 	if (value) {
1186470930SIngo Molnar 		if (!strcasecmp(value, "never"))
1286470930SIngo Molnar 			return 0;
1386470930SIngo Molnar 		if (!strcasecmp(value, "always"))
1486470930SIngo Molnar 			return 1;
1586470930SIngo Molnar 		if (!strcasecmp(value, "auto"))
1686470930SIngo Molnar 			goto auto_color;
1786470930SIngo Molnar 	}
1886470930SIngo Molnar 
1986470930SIngo Molnar 	/* Missing or explicit false to turn off colorization */
2086470930SIngo Molnar 	if (!perf_config_bool(var, value))
2186470930SIngo Molnar 		return 0;
2286470930SIngo Molnar 
2386470930SIngo Molnar 	/* any normal truth value defaults to 'auto' */
2486470930SIngo Molnar  auto_color:
2586470930SIngo Molnar 	if (stdout_is_tty < 0)
2686470930SIngo Molnar 		stdout_is_tty = isatty(1);
2786470930SIngo Molnar 	if (stdout_is_tty || (pager_in_use() && pager_use_color)) {
2886470930SIngo Molnar 		char *term = getenv("TERM");
2986470930SIngo Molnar 		if (term && strcmp(term, "dumb"))
3086470930SIngo Molnar 			return 1;
3186470930SIngo Molnar 	}
3286470930SIngo Molnar 	return 0;
3386470930SIngo Molnar }
3486470930SIngo Molnar 
3586470930SIngo Molnar int perf_color_default_config(const char *var, const char *value, void *cb)
3686470930SIngo Molnar {
3786470930SIngo Molnar 	if (!strcmp(var, "color.ui")) {
3886470930SIngo Molnar 		perf_use_color_default = perf_config_colorbool(var, value, -1);
3986470930SIngo Molnar 		return 0;
4086470930SIngo Molnar 	}
4186470930SIngo Molnar 
4286470930SIngo Molnar 	return perf_default_config(var, value, cb);
4386470930SIngo Molnar }
4486470930SIngo Molnar 
45a4e3b956SArnaldo Carvalho de Melo static int __color_vsnprintf(char *bf, size_t size, const char *color,
46a4e3b956SArnaldo Carvalho de Melo 			     const char *fmt, va_list args, const char *trail)
47a4e3b956SArnaldo Carvalho de Melo {
48a4e3b956SArnaldo Carvalho de Melo 	int r = 0;
49a4e3b956SArnaldo Carvalho de Melo 
50a4e3b956SArnaldo Carvalho de Melo 	/*
51a4e3b956SArnaldo Carvalho de Melo 	 * Auto-detect:
52a4e3b956SArnaldo Carvalho de Melo 	 */
53a4e3b956SArnaldo Carvalho de Melo 	if (perf_use_color_default < 0) {
54a4e3b956SArnaldo Carvalho de Melo 		if (isatty(1) || pager_in_use())
55a4e3b956SArnaldo Carvalho de Melo 			perf_use_color_default = 1;
56a4e3b956SArnaldo Carvalho de Melo 		else
57a4e3b956SArnaldo Carvalho de Melo 			perf_use_color_default = 0;
58a4e3b956SArnaldo Carvalho de Melo 	}
59a4e3b956SArnaldo Carvalho de Melo 
60a4e3b956SArnaldo Carvalho de Melo 	if (perf_use_color_default && *color)
61e7f01d1eSArnaldo Carvalho de Melo 		r += scnprintf(bf, size, "%s", color);
62e7f01d1eSArnaldo Carvalho de Melo 	r += vscnprintf(bf + r, size - r, fmt, args);
63a4e3b956SArnaldo Carvalho de Melo 	if (perf_use_color_default && *color)
64e7f01d1eSArnaldo Carvalho de Melo 		r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
65a4e3b956SArnaldo Carvalho de Melo 	if (trail)
66e7f01d1eSArnaldo Carvalho de Melo 		r += scnprintf(bf + r, size - r, "%s", trail);
67a4e3b956SArnaldo Carvalho de Melo 	return r;
68a4e3b956SArnaldo Carvalho de Melo }
69a4e3b956SArnaldo Carvalho de Melo 
70b7a001d2SAndi Kleen /* Colors are not included in return value */
718f28827aSFrederic Weisbecker static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
728011de7aSJiri Olsa 		va_list args)
7386470930SIngo Molnar {
7486470930SIngo Molnar 	int r = 0;
7586470930SIngo Molnar 
7686470930SIngo Molnar 	/*
7786470930SIngo Molnar 	 * Auto-detect:
7886470930SIngo Molnar 	 */
7986470930SIngo Molnar 	if (perf_use_color_default < 0) {
804aa9015fSStephane Eranian 		if (isatty(fileno(fp)) || pager_in_use())
8186470930SIngo Molnar 			perf_use_color_default = 1;
8286470930SIngo Molnar 		else
8386470930SIngo Molnar 			perf_use_color_default = 0;
8486470930SIngo Molnar 	}
8586470930SIngo Molnar 
8686470930SIngo Molnar 	if (perf_use_color_default && *color)
87b7a001d2SAndi Kleen 		fprintf(fp, "%s", color);
8886470930SIngo Molnar 	r += vfprintf(fp, fmt, args);
8986470930SIngo Molnar 	if (perf_use_color_default && *color)
90b7a001d2SAndi Kleen 		fprintf(fp, "%s", PERF_COLOR_RESET);
9186470930SIngo Molnar 	return r;
9286470930SIngo Molnar }
9386470930SIngo Molnar 
94a4e3b956SArnaldo Carvalho de Melo int color_vsnprintf(char *bf, size_t size, const char *color,
95a4e3b956SArnaldo Carvalho de Melo 		    const char *fmt, va_list args)
96a4e3b956SArnaldo Carvalho de Melo {
97a4e3b956SArnaldo Carvalho de Melo 	return __color_vsnprintf(bf, size, color, fmt, args, NULL);
98a4e3b956SArnaldo Carvalho de Melo }
99a4e3b956SArnaldo Carvalho de Melo 
1008f28827aSFrederic Weisbecker int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
1018f28827aSFrederic Weisbecker {
1028011de7aSJiri Olsa 	return __color_vfprintf(fp, color, fmt, args);
1038f28827aSFrederic Weisbecker }
10486470930SIngo Molnar 
105a4e3b956SArnaldo Carvalho de Melo int color_snprintf(char *bf, size_t size, const char *color,
106a4e3b956SArnaldo Carvalho de Melo 		   const char *fmt, ...)
107a4e3b956SArnaldo Carvalho de Melo {
108a4e3b956SArnaldo Carvalho de Melo 	va_list args;
109a4e3b956SArnaldo Carvalho de Melo 	int r;
110a4e3b956SArnaldo Carvalho de Melo 
111a4e3b956SArnaldo Carvalho de Melo 	va_start(args, fmt);
112a4e3b956SArnaldo Carvalho de Melo 	r = color_vsnprintf(bf, size, color, fmt, args);
113a4e3b956SArnaldo Carvalho de Melo 	va_end(args);
114a4e3b956SArnaldo Carvalho de Melo 	return r;
115a4e3b956SArnaldo Carvalho de Melo }
11686470930SIngo Molnar 
11786470930SIngo Molnar int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
11886470930SIngo Molnar {
11986470930SIngo Molnar 	va_list args;
12086470930SIngo Molnar 	int r;
12186470930SIngo Molnar 
12286470930SIngo Molnar 	va_start(args, fmt);
1238f28827aSFrederic Weisbecker 	r = color_vfprintf(fp, color, fmt, args);
12486470930SIngo Molnar 	va_end(args);
12586470930SIngo Molnar 	return r;
12686470930SIngo Molnar }
12786470930SIngo Molnar 
12886470930SIngo Molnar /*
12986470930SIngo Molnar  * This function splits the buffer by newlines and colors the lines individually.
13086470930SIngo Molnar  *
13186470930SIngo Molnar  * Returns 0 on success.
13286470930SIngo Molnar  */
13386470930SIngo Molnar int color_fwrite_lines(FILE *fp, const char *color,
13486470930SIngo Molnar 		size_t count, const char *buf)
13586470930SIngo Molnar {
13686470930SIngo Molnar 	if (!*color)
13786470930SIngo Molnar 		return fwrite(buf, count, 1, fp) != 1;
138f37a291cSIngo Molnar 
13986470930SIngo Molnar 	while (count) {
14086470930SIngo Molnar 		char *p = memchr(buf, '\n', count);
141f37a291cSIngo Molnar 
14286470930SIngo Molnar 		if (p != buf && (fputs(color, fp) < 0 ||
143f37a291cSIngo Molnar 				fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 ||
14486470930SIngo Molnar 				fputs(PERF_COLOR_RESET, fp) < 0))
14586470930SIngo Molnar 			return -1;
14686470930SIngo Molnar 		if (!p)
14786470930SIngo Molnar 			return 0;
14886470930SIngo Molnar 		if (fputc('\n', fp) < 0)
14986470930SIngo Molnar 			return -1;
15086470930SIngo Molnar 		count -= p + 1 - buf;
15186470930SIngo Molnar 		buf = p + 1;
15286470930SIngo Molnar 	}
15386470930SIngo Molnar 	return 0;
15486470930SIngo Molnar }
15586470930SIngo Molnar 
15683a0944fSIngo Molnar const char *get_percent_color(double percent)
1571e11fd82SFrederic Weisbecker {
15883a0944fSIngo Molnar 	const char *color = PERF_COLOR_NORMAL;
15986470930SIngo Molnar 
1601e11fd82SFrederic Weisbecker 	/*
1611e11fd82SFrederic Weisbecker 	 * We color high-overhead entries in red, mid-overhead
1621e11fd82SFrederic Weisbecker 	 * entries in green - and keep the low overhead places
1631e11fd82SFrederic Weisbecker 	 * normal:
1641e11fd82SFrederic Weisbecker 	 */
165f77c6e9cSRamkumar Ramachandra 	if (fabs(percent) >= MIN_RED)
1661e11fd82SFrederic Weisbecker 		color = PERF_COLOR_RED;
1671e11fd82SFrederic Weisbecker 	else {
168f77c6e9cSRamkumar Ramachandra 		if (fabs(percent) > MIN_GREEN)
1691e11fd82SFrederic Weisbecker 			color = PERF_COLOR_GREEN;
1701e11fd82SFrederic Weisbecker 	}
1711e11fd82SFrederic Weisbecker 	return color;
1721e11fd82SFrederic Weisbecker }
1731e11fd82SFrederic Weisbecker 
1741e11fd82SFrederic Weisbecker int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
1751e11fd82SFrederic Weisbecker {
1761e11fd82SFrederic Weisbecker 	int r;
17783a0944fSIngo Molnar 	const char *color;
1781e11fd82SFrederic Weisbecker 
1791e11fd82SFrederic Weisbecker 	color = get_percent_color(percent);
1801e11fd82SFrederic Weisbecker 	r = color_fprintf(fp, color, fmt, percent);
1811e11fd82SFrederic Weisbecker 
1821e11fd82SFrederic Weisbecker 	return r;
1831e11fd82SFrederic Weisbecker }
184a4e3b956SArnaldo Carvalho de Melo 
1851f513b2cSRamkumar Ramachandra int value_color_snprintf(char *bf, size_t size, const char *fmt, double value)
1861f513b2cSRamkumar Ramachandra {
1871f513b2cSRamkumar Ramachandra 	const char *color = get_percent_color(value);
1881f513b2cSRamkumar Ramachandra 	return color_snprintf(bf, size, color, fmt, value);
1891f513b2cSRamkumar Ramachandra }
1901f513b2cSRamkumar Ramachandra 
19153805ecaSMichael Hudson-Doyle int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
192a4e3b956SArnaldo Carvalho de Melo {
19353805ecaSMichael Hudson-Doyle 	va_list args;
19453805ecaSMichael Hudson-Doyle 	double percent;
19553805ecaSMichael Hudson-Doyle 
19653805ecaSMichael Hudson-Doyle 	va_start(args, fmt);
19753805ecaSMichael Hudson-Doyle 	percent = va_arg(args, double);
19853805ecaSMichael Hudson-Doyle 	va_end(args);
1991f513b2cSRamkumar Ramachandra 	return value_color_snprintf(bf, size, fmt, percent);
200a4e3b956SArnaldo Carvalho de Melo }
201d675107cSNamhyung Kim 
202d675107cSNamhyung Kim int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
203d675107cSNamhyung Kim {
204d675107cSNamhyung Kim 	va_list args;
205d675107cSNamhyung Kim 	int len;
206d675107cSNamhyung Kim 	double percent;
207d675107cSNamhyung Kim 	const char *color;
208d675107cSNamhyung Kim 
209d675107cSNamhyung Kim 	va_start(args, fmt);
210d675107cSNamhyung Kim 	len = va_arg(args, int);
211d675107cSNamhyung Kim 	percent = va_arg(args, double);
212d675107cSNamhyung Kim 	va_end(args);
213d675107cSNamhyung Kim 
214d675107cSNamhyung Kim 	color = get_percent_color(percent);
215d675107cSNamhyung Kim 	return color_snprintf(bf, size, color, fmt, len, percent);
216d675107cSNamhyung Kim }
217