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