Linux-libre 4.9.46-gnu
[librecmc/linux-libre.git] / tools / perf / util / color.c
1 #include <linux/kernel.h>
2 #include "cache.h"
3 #include "config.h"
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include "color.h"
7 #include <math.h>
8 #include <unistd.h>
9
10 int perf_use_color_default = -1;
11
12 int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty)
13 {
14         if (value) {
15                 if (!strcasecmp(value, "never"))
16                         return 0;
17                 if (!strcasecmp(value, "always"))
18                         return 1;
19                 if (!strcasecmp(value, "auto"))
20                         goto auto_color;
21         }
22
23         /* Missing or explicit false to turn off colorization */
24         if (!perf_config_bool(var, value))
25                 return 0;
26
27         /* any normal truth value defaults to 'auto' */
28  auto_color:
29         if (stdout_is_tty < 0)
30                 stdout_is_tty = isatty(1);
31         if (stdout_is_tty || pager_in_use()) {
32                 char *term = getenv("TERM");
33                 if (term && strcmp(term, "dumb"))
34                         return 1;
35         }
36         return 0;
37 }
38
39 int perf_color_default_config(const char *var, const char *value,
40                               void *cb __maybe_unused)
41 {
42         if (!strcmp(var, "color.ui")) {
43                 perf_use_color_default = perf_config_colorbool(var, value, -1);
44                 return 0;
45         }
46
47         return 0;
48 }
49
50 static int __color_vsnprintf(char *bf, size_t size, const char *color,
51                              const char *fmt, va_list args, const char *trail)
52 {
53         int r = 0;
54
55         /*
56          * Auto-detect:
57          */
58         if (perf_use_color_default < 0) {
59                 if (isatty(1) || pager_in_use())
60                         perf_use_color_default = 1;
61                 else
62                         perf_use_color_default = 0;
63         }
64
65         if (perf_use_color_default && *color)
66                 r += scnprintf(bf, size, "%s", color);
67         r += vscnprintf(bf + r, size - r, fmt, args);
68         if (perf_use_color_default && *color)
69                 r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
70         if (trail)
71                 r += scnprintf(bf + r, size - r, "%s", trail);
72         return r;
73 }
74
75 /* Colors are not included in return value */
76 static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
77                 va_list args)
78 {
79         int r = 0;
80
81         /*
82          * Auto-detect:
83          */
84         if (perf_use_color_default < 0) {
85                 if (isatty(fileno(fp)) || pager_in_use())
86                         perf_use_color_default = 1;
87                 else
88                         perf_use_color_default = 0;
89         }
90
91         if (perf_use_color_default && *color)
92                 fprintf(fp, "%s", color);
93         r += vfprintf(fp, fmt, args);
94         if (perf_use_color_default && *color)
95                 fprintf(fp, "%s", PERF_COLOR_RESET);
96         return r;
97 }
98
99 int color_vsnprintf(char *bf, size_t size, const char *color,
100                     const char *fmt, va_list args)
101 {
102         return __color_vsnprintf(bf, size, color, fmt, args, NULL);
103 }
104
105 int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
106 {
107         return __color_vfprintf(fp, color, fmt, args);
108 }
109
110 int color_snprintf(char *bf, size_t size, const char *color,
111                    const char *fmt, ...)
112 {
113         va_list args;
114         int r;
115
116         va_start(args, fmt);
117         r = color_vsnprintf(bf, size, color, fmt, args);
118         va_end(args);
119         return r;
120 }
121
122 int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
123 {
124         va_list args;
125         int r;
126
127         va_start(args, fmt);
128         r = color_vfprintf(fp, color, fmt, args);
129         va_end(args);
130         return r;
131 }
132
133 /*
134  * This function splits the buffer by newlines and colors the lines individually.
135  *
136  * Returns 0 on success.
137  */
138 int color_fwrite_lines(FILE *fp, const char *color,
139                 size_t count, const char *buf)
140 {
141         if (!*color)
142                 return fwrite(buf, count, 1, fp) != 1;
143
144         while (count) {
145                 char *p = memchr(buf, '\n', count);
146
147                 if (p != buf && (fputs(color, fp) < 0 ||
148                                 fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 ||
149                                 fputs(PERF_COLOR_RESET, fp) < 0))
150                         return -1;
151                 if (!p)
152                         return 0;
153                 if (fputc('\n', fp) < 0)
154                         return -1;
155                 count -= p + 1 - buf;
156                 buf = p + 1;
157         }
158         return 0;
159 }
160
161 const char *get_percent_color(double percent)
162 {
163         const char *color = PERF_COLOR_NORMAL;
164
165         /*
166          * We color high-overhead entries in red, mid-overhead
167          * entries in green - and keep the low overhead places
168          * normal:
169          */
170         if (fabs(percent) >= MIN_RED)
171                 color = PERF_COLOR_RED;
172         else {
173                 if (fabs(percent) > MIN_GREEN)
174                         color = PERF_COLOR_GREEN;
175         }
176         return color;
177 }
178
179 int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
180 {
181         int r;
182         const char *color;
183
184         color = get_percent_color(percent);
185         r = color_fprintf(fp, color, fmt, percent);
186
187         return r;
188 }
189
190 int value_color_snprintf(char *bf, size_t size, const char *fmt, double value)
191 {
192         const char *color = get_percent_color(value);
193         return color_snprintf(bf, size, color, fmt, value);
194 }
195
196 int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
197 {
198         va_list args;
199         double percent;
200
201         va_start(args, fmt);
202         percent = va_arg(args, double);
203         va_end(args);
204         return value_color_snprintf(bf, size, fmt, percent);
205 }
206
207 int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
208 {
209         va_list args;
210         int len;
211         double percent;
212         const char *color;
213
214         va_start(args, fmt);
215         len = va_arg(args, int);
216         percent = va_arg(args, double);
217         va_end(args);
218
219         color = get_percent_color(percent);
220         return color_snprintf(bf, size, color, fmt, len, percent);
221 }