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