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