xref: /openbmc/linux/tools/perf/util/color.c (revision fa0d9846)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2e7f01d1eSArnaldo Carvalho de Melo #include <linux/kernel.h>
3fa0d9846SArnaldo Carvalho de Melo #include <subcmd/pager.h>
4d0761e37SArnaldo Carvalho de Melo #include <stdlib.h>
5d0761e37SArnaldo Carvalho de Melo #include <stdio.h>
6fa0d9846SArnaldo Carvalho de Melo #include <string.h>
786470930SIngo Molnar #include "color.h"
8f77c6e9cSRamkumar Ramachandra #include <math.h>
916b7c9bdSArnaldo Carvalho de Melo #include <unistd.h>
1086470930SIngo Molnar 
1186470930SIngo Molnar int perf_use_color_default = -1;
1286470930SIngo Molnar 
__color_vsnprintf(char * bf,size_t size,const char * color,const char * fmt,va_list args,const char * trail)13a4e3b956SArnaldo Carvalho de Melo static int __color_vsnprintf(char *bf, size_t size, const char *color,
14a4e3b956SArnaldo Carvalho de Melo 			     const char *fmt, va_list args, const char *trail)
15a4e3b956SArnaldo Carvalho de Melo {
16a4e3b956SArnaldo Carvalho de Melo 	int r = 0;
17a4e3b956SArnaldo Carvalho de Melo 
18a4e3b956SArnaldo Carvalho de Melo 	/*
19a4e3b956SArnaldo Carvalho de Melo 	 * Auto-detect:
20a4e3b956SArnaldo Carvalho de Melo 	 */
21a4e3b956SArnaldo Carvalho de Melo 	if (perf_use_color_default < 0) {
22a4e3b956SArnaldo Carvalho de Melo 		if (isatty(1) || pager_in_use())
23a4e3b956SArnaldo Carvalho de Melo 			perf_use_color_default = 1;
24a4e3b956SArnaldo Carvalho de Melo 		else
25a4e3b956SArnaldo Carvalho de Melo 			perf_use_color_default = 0;
26a4e3b956SArnaldo Carvalho de Melo 	}
27a4e3b956SArnaldo Carvalho de Melo 
28a4e3b956SArnaldo Carvalho de Melo 	if (perf_use_color_default && *color)
29e7f01d1eSArnaldo Carvalho de Melo 		r += scnprintf(bf, size, "%s", color);
30e7f01d1eSArnaldo Carvalho de Melo 	r += vscnprintf(bf + r, size - r, fmt, args);
31a4e3b956SArnaldo Carvalho de Melo 	if (perf_use_color_default && *color)
32e7f01d1eSArnaldo Carvalho de Melo 		r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
33a4e3b956SArnaldo Carvalho de Melo 	if (trail)
34e7f01d1eSArnaldo Carvalho de Melo 		r += scnprintf(bf + r, size - r, "%s", trail);
35a4e3b956SArnaldo Carvalho de Melo 	return r;
36a4e3b956SArnaldo Carvalho de Melo }
37a4e3b956SArnaldo Carvalho de Melo 
38b7a001d2SAndi Kleen /* Colors are not included in return value */
__color_vfprintf(FILE * fp,const char * color,const char * fmt,va_list args)398f28827aSFrederic Weisbecker static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
408011de7aSJiri Olsa 		va_list args)
4186470930SIngo Molnar {
4286470930SIngo Molnar 	int r = 0;
4386470930SIngo Molnar 
4486470930SIngo Molnar 	/*
4586470930SIngo Molnar 	 * Auto-detect:
4686470930SIngo Molnar 	 */
4786470930SIngo Molnar 	if (perf_use_color_default < 0) {
484aa9015fSStephane Eranian 		if (isatty(fileno(fp)) || pager_in_use())
4986470930SIngo Molnar 			perf_use_color_default = 1;
5086470930SIngo Molnar 		else
5186470930SIngo Molnar 			perf_use_color_default = 0;
5286470930SIngo Molnar 	}
5386470930SIngo Molnar 
5486470930SIngo Molnar 	if (perf_use_color_default && *color)
55b7a001d2SAndi Kleen 		fprintf(fp, "%s", color);
5686470930SIngo Molnar 	r += vfprintf(fp, fmt, args);
5786470930SIngo Molnar 	if (perf_use_color_default && *color)
58b7a001d2SAndi Kleen 		fprintf(fp, "%s", PERF_COLOR_RESET);
5986470930SIngo Molnar 	return r;
6086470930SIngo Molnar }
6186470930SIngo Molnar 
color_vsnprintf(char * bf,size_t size,const char * color,const char * fmt,va_list args)62a4e3b956SArnaldo Carvalho de Melo int color_vsnprintf(char *bf, size_t size, const char *color,
63a4e3b956SArnaldo Carvalho de Melo 		    const char *fmt, va_list args)
64a4e3b956SArnaldo Carvalho de Melo {
65a4e3b956SArnaldo Carvalho de Melo 	return __color_vsnprintf(bf, size, color, fmt, args, NULL);
66a4e3b956SArnaldo Carvalho de Melo }
67a4e3b956SArnaldo Carvalho de Melo 
color_vfprintf(FILE * fp,const char * color,const char * fmt,va_list args)688f28827aSFrederic Weisbecker int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
698f28827aSFrederic Weisbecker {
708011de7aSJiri Olsa 	return __color_vfprintf(fp, color, fmt, args);
718f28827aSFrederic Weisbecker }
7286470930SIngo Molnar 
color_snprintf(char * bf,size_t size,const char * color,const char * fmt,...)73a4e3b956SArnaldo Carvalho de Melo int color_snprintf(char *bf, size_t size, const char *color,
74a4e3b956SArnaldo Carvalho de Melo 		   const char *fmt, ...)
75a4e3b956SArnaldo Carvalho de Melo {
76a4e3b956SArnaldo Carvalho de Melo 	va_list args;
77a4e3b956SArnaldo Carvalho de Melo 	int r;
78a4e3b956SArnaldo Carvalho de Melo 
79a4e3b956SArnaldo Carvalho de Melo 	va_start(args, fmt);
80a4e3b956SArnaldo Carvalho de Melo 	r = color_vsnprintf(bf, size, color, fmt, args);
81a4e3b956SArnaldo Carvalho de Melo 	va_end(args);
82a4e3b956SArnaldo Carvalho de Melo 	return r;
83a4e3b956SArnaldo Carvalho de Melo }
8486470930SIngo Molnar 
color_fprintf(FILE * fp,const char * color,const char * fmt,...)8586470930SIngo Molnar int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
8686470930SIngo Molnar {
8786470930SIngo Molnar 	va_list args;
8886470930SIngo Molnar 	int r;
8986470930SIngo Molnar 
9086470930SIngo Molnar 	va_start(args, fmt);
918f28827aSFrederic Weisbecker 	r = color_vfprintf(fp, color, fmt, args);
9286470930SIngo Molnar 	va_end(args);
9386470930SIngo Molnar 	return r;
9486470930SIngo Molnar }
9586470930SIngo Molnar 
9686470930SIngo Molnar /*
9786470930SIngo Molnar  * This function splits the buffer by newlines and colors the lines individually.
9886470930SIngo Molnar  *
9986470930SIngo Molnar  * Returns 0 on success.
10086470930SIngo Molnar  */
color_fwrite_lines(FILE * fp,const char * color,size_t count,const char * buf)10186470930SIngo Molnar int color_fwrite_lines(FILE *fp, const char *color,
10286470930SIngo Molnar 		size_t count, const char *buf)
10386470930SIngo Molnar {
10486470930SIngo Molnar 	if (!*color)
10586470930SIngo Molnar 		return fwrite(buf, count, 1, fp) != 1;
106f37a291cSIngo Molnar 
10786470930SIngo Molnar 	while (count) {
10886470930SIngo Molnar 		char *p = memchr(buf, '\n', count);
109f37a291cSIngo Molnar 
11086470930SIngo Molnar 		if (p != buf && (fputs(color, fp) < 0 ||
111f37a291cSIngo Molnar 				fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 ||
11286470930SIngo Molnar 				fputs(PERF_COLOR_RESET, fp) < 0))
11386470930SIngo Molnar 			return -1;
11486470930SIngo Molnar 		if (!p)
11586470930SIngo Molnar 			return 0;
11686470930SIngo Molnar 		if (fputc('\n', fp) < 0)
11786470930SIngo Molnar 			return -1;
11886470930SIngo Molnar 		count -= p + 1 - buf;
11986470930SIngo Molnar 		buf = p + 1;
12086470930SIngo Molnar 	}
12186470930SIngo Molnar 	return 0;
12286470930SIngo Molnar }
12386470930SIngo Molnar 
get_percent_color(double percent)12483a0944fSIngo Molnar const char *get_percent_color(double percent)
1251e11fd82SFrederic Weisbecker {
12683a0944fSIngo Molnar 	const char *color = PERF_COLOR_NORMAL;
12786470930SIngo Molnar 
1281e11fd82SFrederic Weisbecker 	/*
1291e11fd82SFrederic Weisbecker 	 * We color high-overhead entries in red, mid-overhead
1301e11fd82SFrederic Weisbecker 	 * entries in green - and keep the low overhead places
1311e11fd82SFrederic Weisbecker 	 * normal:
1321e11fd82SFrederic Weisbecker 	 */
133f77c6e9cSRamkumar Ramachandra 	if (fabs(percent) >= MIN_RED)
1341e11fd82SFrederic Weisbecker 		color = PERF_COLOR_RED;
1351e11fd82SFrederic Weisbecker 	else {
136f77c6e9cSRamkumar Ramachandra 		if (fabs(percent) > MIN_GREEN)
1371e11fd82SFrederic Weisbecker 			color = PERF_COLOR_GREEN;
1381e11fd82SFrederic Weisbecker 	}
1391e11fd82SFrederic Weisbecker 	return color;
1401e11fd82SFrederic Weisbecker }
1411e11fd82SFrederic Weisbecker 
percent_color_fprintf(FILE * fp,const char * fmt,double percent)1421e11fd82SFrederic Weisbecker int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
1431e11fd82SFrederic Weisbecker {
1441e11fd82SFrederic Weisbecker 	int r;
14583a0944fSIngo Molnar 	const char *color;
1461e11fd82SFrederic Weisbecker 
1471e11fd82SFrederic Weisbecker 	color = get_percent_color(percent);
1481e11fd82SFrederic Weisbecker 	r = color_fprintf(fp, color, fmt, percent);
1491e11fd82SFrederic Weisbecker 
1501e11fd82SFrederic Weisbecker 	return r;
1511e11fd82SFrederic Weisbecker }
152a4e3b956SArnaldo Carvalho de Melo 
value_color_snprintf(char * bf,size_t size,const char * fmt,double value)1531f513b2cSRamkumar Ramachandra int value_color_snprintf(char *bf, size_t size, const char *fmt, double value)
1541f513b2cSRamkumar Ramachandra {
1551f513b2cSRamkumar Ramachandra 	const char *color = get_percent_color(value);
1561f513b2cSRamkumar Ramachandra 	return color_snprintf(bf, size, color, fmt, value);
1571f513b2cSRamkumar Ramachandra }
1581f513b2cSRamkumar Ramachandra 
percent_color_snprintf(char * bf,size_t size,const char * fmt,...)15953805ecaSMichael Hudson-Doyle int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
160a4e3b956SArnaldo Carvalho de Melo {
16153805ecaSMichael Hudson-Doyle 	va_list args;
16253805ecaSMichael Hudson-Doyle 	double percent;
16353805ecaSMichael Hudson-Doyle 
16453805ecaSMichael Hudson-Doyle 	va_start(args, fmt);
16553805ecaSMichael Hudson-Doyle 	percent = va_arg(args, double);
16653805ecaSMichael Hudson-Doyle 	va_end(args);
1671f513b2cSRamkumar Ramachandra 	return value_color_snprintf(bf, size, fmt, percent);
168a4e3b956SArnaldo Carvalho de Melo }
169d675107cSNamhyung Kim 
percent_color_len_snprintf(char * bf,size_t size,const char * fmt,...)170d675107cSNamhyung Kim int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
171d675107cSNamhyung Kim {
172d675107cSNamhyung Kim 	va_list args;
173d675107cSNamhyung Kim 	int len;
174d675107cSNamhyung Kim 	double percent;
175d675107cSNamhyung Kim 	const char *color;
176d675107cSNamhyung Kim 
177d675107cSNamhyung Kim 	va_start(args, fmt);
178d675107cSNamhyung Kim 	len = va_arg(args, int);
179d675107cSNamhyung Kim 	percent = va_arg(args, double);
180d675107cSNamhyung Kim 	va_end(args);
181d675107cSNamhyung Kim 
182d675107cSNamhyung Kim 	color = get_percent_color(percent);
183d675107cSNamhyung Kim 	return color_snprintf(bf, size, color, fmt, len, percent);
184d675107cSNamhyung Kim }
185