1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "cache.h"
2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "color.h"
3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_use_color_default = -1;
5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_color(const char *name, int len)
7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	static const char * const color_names[] = {
9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		"normal", "black", "red", "green", "yellow",
10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		"blue", "magenta", "cyan", "white"
11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	};
12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *end;
13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i;
14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < (int)ARRAY_SIZE(color_names); i++) {
16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		const char *str = color_names[i];
17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!strncasecmp(name, str, len) && !str[len])
18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return i - 1;
19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	i = strtol(name, &end, 10);
21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (end - name == len && i >= -1 && i <= 255)
22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return i;
23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return -2;
24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_attr(const char *name, int len)
27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	static const int attr_values[] = { 1, 2, 4, 5, 7 };
29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	static const char * const attr_names[] = {
30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		"bold", "dim", "ul", "blink", "reverse"
31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	};
32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	unsigned int i;
33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		const char *str = attr_names[i];
36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!strncasecmp(name, str, len) && !str[len])
37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return attr_values[i];
38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return -1;
40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid color_parse(const char *value, const char *var, char *dst)
43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	color_parse_mem(value, strlen(value), var, dst);
45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid color_parse_mem(const char *value, int value_len, const char *var,
48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		char *dst)
49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *ptr = value;
51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int len = value_len;
52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int attr = -1;
53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int fg = -2;
54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int bg = -2;
55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!strncasecmp(value, "reset", len)) {
57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		strcpy(dst, PERF_COLOR_RESET);
58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return;
59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* [fg [bg]] [attr] */
62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (len > 0) {
63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		const char *word = ptr;
64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int val, wordlen = 0;
65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (len > 0 && !isspace(word[wordlen])) {
67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			wordlen++;
68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			len--;
69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ptr = word + wordlen;
72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (len > 0 && isspace(*ptr)) {
73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ptr++;
74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			len--;
75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		val = parse_color(word, wordlen);
78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (val >= -1) {
79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (fg == -2) {
80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				fg = val;
81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				continue;
82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (bg == -2) {
84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				bg = val;
85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				continue;
86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto bad;
88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		val = parse_attr(word, wordlen);
90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (val < 0 || attr != -1)
91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto bad;
92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		attr = val;
93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (attr >= 0 || fg >= 0 || bg >= 0) {
96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		int sep = 0;
97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*dst++ = '\033';
99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*dst++ = '[';
100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (attr >= 0) {
101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			*dst++ = '0' + attr;
102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			sep++;
103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (fg >= 0) {
105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (sep++)
106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				*dst++ = ';';
107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (fg < 8) {
108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				*dst++ = '3';
109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				*dst++ = '0' + fg;
110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else {
111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				dst += sprintf(dst, "38;5;%d", fg);
112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (bg >= 0) {
115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (sep++)
116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				*dst++ = ';';
117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (bg < 8) {
118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				*dst++ = '4';
119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				*dst++ = '0' + bg;
120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else {
121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				dst += sprintf(dst, "48;5;%d", bg);
122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*dst++ = 'm';
125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	*dst = 0;
127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return;
128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengbad:
129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	die("bad color value '%.*s' for variable '%s'", value_len, value, var);
130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_config_colorbool(const char *var, const char *value, int stdout_is_tty)
133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (value) {
135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!strcasecmp(value, "never"))
136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return 0;
137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!strcasecmp(value, "always"))
138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return 1;
139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!strcasecmp(value, "auto"))
140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto auto_color;
141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Missing or explicit false to turn off colorization */
144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!perf_config_bool(var, value))
145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 0;
146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* any normal truth value defaults to 'auto' */
148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng auto_color:
149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (stdout_is_tty < 0)
150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		stdout_is_tty = isatty(1);
151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (stdout_is_tty || (pager_in_use() && pager_use_color)) {
152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		char *term = getenv("TERM");
153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (term && strcmp(term, "dumb"))
154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return 1;
155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_color_default_config(const char *var, const char *value, void *cb)
160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!strcmp(var, "color.ui")) {
162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		perf_use_color_default = perf_config_colorbool(var, value, -1);
163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 0;
164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return perf_default_config(var, value, cb);
167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __color_vsnprintf(char *bf, size_t size, const char *color,
170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			     const char *fmt, va_list args, const char *trail)
171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int r = 0;
173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/*
175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * Auto-detect:
176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 */
177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (perf_use_color_default < 0) {
178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (isatty(1) || pager_in_use())
179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			perf_use_color_default = 1;
180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			perf_use_color_default = 0;
182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (perf_use_color_default && *color)
185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		r += snprintf(bf, size, "%s", color);
186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	r += vsnprintf(bf + r, size - r, fmt, args);
187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (perf_use_color_default && *color)
188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		r += snprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (trail)
190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		r += snprintf(bf + r, size - r, "%s", trail);
191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return r;
192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		va_list args, const char *trail)
196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int r = 0;
198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/*
200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * Auto-detect:
201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 */
202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (perf_use_color_default < 0) {
203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (isatty(1) || pager_in_use())
204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			perf_use_color_default = 1;
205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			perf_use_color_default = 0;
207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (perf_use_color_default && *color)
210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		r += fprintf(fp, "%s", color);
211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	r += vfprintf(fp, fmt, args);
212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (perf_use_color_default && *color)
213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		r += fprintf(fp, "%s", PERF_COLOR_RESET);
214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (trail)
215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		r += fprintf(fp, "%s", trail);
216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return r;
217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint color_vsnprintf(char *bf, size_t size, const char *color,
220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    const char *fmt, va_list args)
221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return __color_vsnprintf(bf, size, color, fmt, args, NULL);
223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return __color_vfprintf(fp, color, fmt, args, NULL);
228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint color_snprintf(char *bf, size_t size, const char *color,
231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		   const char *fmt, ...)
232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_list args;
234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int r;
235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_start(args, fmt);
237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	r = color_vsnprintf(bf, size, color, fmt, args);
238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_end(args);
239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return r;
240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_list args;
245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int r;
246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_start(args, fmt);
248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	r = color_vfprintf(fp, color, fmt, args);
249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_end(args);
250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return r;
251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)
254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_list args;
256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int r;
257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_start(args, fmt);
258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	r = __color_vfprintf(fp, color, fmt, args, "\n");
259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_end(args);
260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return r;
261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * This function splits the buffer by newlines and colors the lines individually.
265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Returns 0 on success.
267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint color_fwrite_lines(FILE *fp, const char *color,
269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		size_t count, const char *buf)
270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!*color)
272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return fwrite(buf, count, 1, fp) != 1;
273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (count) {
275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		char *p = memchr(buf, '\n', count);
276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (p != buf && (fputs(color, fp) < 0 ||
278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 ||
279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				fputs(PERF_COLOR_RESET, fp) < 0))
280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -1;
281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!p)
282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return 0;
283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (fputc('\n', fp) < 0)
284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -1;
285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		count -= p + 1 - buf;
286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		buf = p + 1;
287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengconst char *get_percent_color(double percent)
292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *color = PERF_COLOR_NORMAL;
294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/*
296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * We color high-overhead entries in red, mid-overhead
297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * entries in green - and keep the low overhead places
298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * normal:
299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 */
300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (percent >= MIN_RED)
301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		color = PERF_COLOR_RED;
302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else {
303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (percent > MIN_GREEN)
304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			color = PERF_COLOR_GREEN;
305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return color;
307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint percent_color_fprintf(FILE *fp, const char *fmt, double percent)
310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int r;
312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *color;
313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	color = get_percent_color(percent);
315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	r = color_fprintf(fp, color, fmt, percent);
316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return r;
318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent)
321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *color = get_percent_color(percent);
323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return color_snprintf(bf, size, color, fmt, percent);
324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
325