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()) { 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, 36 void *cb __maybe_unused) 37 { 38 if (!strcmp(var, "color.ui")) { 39 perf_use_color_default = perf_config_colorbool(var, value, -1); 40 return 0; 41 } 42 43 return 0; 44 } 45 46 static int __color_vsnprintf(char *bf, size_t size, const char *color, 47 const char *fmt, va_list args, const char *trail) 48 { 49 int r = 0; 50 51 /* 52 * Auto-detect: 53 */ 54 if (perf_use_color_default < 0) { 55 if (isatty(1) || pager_in_use()) 56 perf_use_color_default = 1; 57 else 58 perf_use_color_default = 0; 59 } 60 61 if (perf_use_color_default && *color) 62 r += scnprintf(bf, size, "%s", color); 63 r += vscnprintf(bf + r, size - r, fmt, args); 64 if (perf_use_color_default && *color) 65 r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET); 66 if (trail) 67 r += scnprintf(bf + r, size - r, "%s", trail); 68 return r; 69 } 70 71 /* Colors are not included in return value */ 72 static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, 73 va_list args) 74 { 75 int r = 0; 76 77 /* 78 * Auto-detect: 79 */ 80 if (perf_use_color_default < 0) { 81 if (isatty(fileno(fp)) || pager_in_use()) 82 perf_use_color_default = 1; 83 else 84 perf_use_color_default = 0; 85 } 86 87 if (perf_use_color_default && *color) 88 fprintf(fp, "%s", color); 89 r += vfprintf(fp, fmt, args); 90 if (perf_use_color_default && *color) 91 fprintf(fp, "%s", PERF_COLOR_RESET); 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); 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 /* 130 * This function splits the buffer by newlines and colors the lines individually. 131 * 132 * Returns 0 on success. 133 */ 134 int color_fwrite_lines(FILE *fp, const char *color, 135 size_t count, const char *buf) 136 { 137 if (!*color) 138 return fwrite(buf, count, 1, fp) != 1; 139 140 while (count) { 141 char *p = memchr(buf, '\n', count); 142 143 if (p != buf && (fputs(color, fp) < 0 || 144 fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 || 145 fputs(PERF_COLOR_RESET, fp) < 0)) 146 return -1; 147 if (!p) 148 return 0; 149 if (fputc('\n', fp) < 0) 150 return -1; 151 count -= p + 1 - buf; 152 buf = p + 1; 153 } 154 return 0; 155 } 156 157 const char *get_percent_color(double percent) 158 { 159 const char *color = PERF_COLOR_NORMAL; 160 161 /* 162 * We color high-overhead entries in red, mid-overhead 163 * entries in green - and keep the low overhead places 164 * normal: 165 */ 166 if (fabs(percent) >= MIN_RED) 167 color = PERF_COLOR_RED; 168 else { 169 if (fabs(percent) > MIN_GREEN) 170 color = PERF_COLOR_GREEN; 171 } 172 return color; 173 } 174 175 int percent_color_fprintf(FILE *fp, const char *fmt, double percent) 176 { 177 int r; 178 const char *color; 179 180 color = get_percent_color(percent); 181 r = color_fprintf(fp, color, fmt, percent); 182 183 return r; 184 } 185 186 int value_color_snprintf(char *bf, size_t size, const char *fmt, double value) 187 { 188 const char *color = get_percent_color(value); 189 return color_snprintf(bf, size, color, fmt, value); 190 } 191 192 int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) 193 { 194 va_list args; 195 double percent; 196 197 va_start(args, fmt); 198 percent = va_arg(args, double); 199 va_end(args); 200 return value_color_snprintf(bf, size, fmt, percent); 201 } 202 203 int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...) 204 { 205 va_list args; 206 int len; 207 double percent; 208 const char *color; 209 210 va_start(args, fmt); 211 len = va_arg(args, int); 212 percent = va_arg(args, double); 213 va_end(args); 214 215 color = get_percent_color(percent); 216 return color_snprintf(bf, size, color, fmt, len, percent); 217 } 218