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 /* Colors are not included in return value */ 71 static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, 72 va_list args) 73 { 74 int r = 0; 75 76 /* 77 * Auto-detect: 78 */ 79 if (perf_use_color_default < 0) { 80 if (isatty(fileno(fp)) || pager_in_use()) 81 perf_use_color_default = 1; 82 else 83 perf_use_color_default = 0; 84 } 85 86 if (perf_use_color_default && *color) 87 fprintf(fp, "%s", color); 88 r += vfprintf(fp, fmt, args); 89 if (perf_use_color_default && *color) 90 fprintf(fp, "%s", PERF_COLOR_RESET); 91 return r; 92 } 93 94 int color_vsnprintf(char *bf, size_t size, const char *color, 95 const char *fmt, va_list args) 96 { 97 return __color_vsnprintf(bf, size, color, fmt, args, NULL); 98 } 99 100 int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) 101 { 102 return __color_vfprintf(fp, color, fmt, args); 103 } 104 105 int color_snprintf(char *bf, size_t size, const char *color, 106 const char *fmt, ...) 107 { 108 va_list args; 109 int r; 110 111 va_start(args, fmt); 112 r = color_vsnprintf(bf, size, color, fmt, args); 113 va_end(args); 114 return r; 115 } 116 117 int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) 118 { 119 va_list args; 120 int r; 121 122 va_start(args, fmt); 123 r = color_vfprintf(fp, color, fmt, args); 124 va_end(args); 125 return r; 126 } 127 128 /* 129 * This function splits the buffer by newlines and colors the lines individually. 130 * 131 * Returns 0 on success. 132 */ 133 int color_fwrite_lines(FILE *fp, const char *color, 134 size_t count, const char *buf) 135 { 136 if (!*color) 137 return fwrite(buf, count, 1, fp) != 1; 138 139 while (count) { 140 char *p = memchr(buf, '\n', count); 141 142 if (p != buf && (fputs(color, fp) < 0 || 143 fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 || 144 fputs(PERF_COLOR_RESET, fp) < 0)) 145 return -1; 146 if (!p) 147 return 0; 148 if (fputc('\n', fp) < 0) 149 return -1; 150 count -= p + 1 - buf; 151 buf = p + 1; 152 } 153 return 0; 154 } 155 156 const char *get_percent_color(double percent) 157 { 158 const char *color = PERF_COLOR_NORMAL; 159 160 /* 161 * We color high-overhead entries in red, mid-overhead 162 * entries in green - and keep the low overhead places 163 * normal: 164 */ 165 if (fabs(percent) >= MIN_RED) 166 color = PERF_COLOR_RED; 167 else { 168 if (fabs(percent) > MIN_GREEN) 169 color = PERF_COLOR_GREEN; 170 } 171 return color; 172 } 173 174 int percent_color_fprintf(FILE *fp, const char *fmt, double percent) 175 { 176 int r; 177 const char *color; 178 179 color = get_percent_color(percent); 180 r = color_fprintf(fp, color, fmt, percent); 181 182 return r; 183 } 184 185 int value_color_snprintf(char *bf, size_t size, const char *fmt, double value) 186 { 187 const char *color = get_percent_color(value); 188 return color_snprintf(bf, size, color, fmt, value); 189 } 190 191 int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) 192 { 193 va_list args; 194 double percent; 195 196 va_start(args, fmt); 197 percent = va_arg(args, double); 198 va_end(args); 199 return value_color_snprintf(bf, size, fmt, percent); 200 } 201 202 int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...) 203 { 204 va_list args; 205 int len; 206 double percent; 207 const char *color; 208 209 va_start(args, fmt); 210 len = va_arg(args, int); 211 percent = va_arg(args, double); 212 va_end(args); 213 214 color = get_percent_color(percent); 215 return color_snprintf(bf, size, color, fmt, len, percent); 216 } 217