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 } 222