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