1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <linux/kernel.h> 2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "cache.h" 3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "color.h" 4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint perf_use_color_default = -1; 6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int parse_color(const char *name, int len) 8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng static const char * const color_names[] = { 10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "normal", "black", "red", "green", "yellow", 11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "blue", "magenta", "cyan", "white" 12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *end; 14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < (int)ARRAY_SIZE(color_names); i++) { 17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *str = color_names[i]; 18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strncasecmp(name, str, len) && !str[len]) 19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return i - 1; 20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng i = strtol(name, &end, 10); 22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (end - name == len && i >= -1 && i <= 255) 23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return i; 24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -2; 25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int parse_attr(const char *name, int len) 28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng static const int attr_values[] = { 1, 2, 4, 5, 7 }; 30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng static const char * const attr_names[] = { 31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "bold", "dim", "ul", "blink", "reverse" 32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned int i; 34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < ARRAY_SIZE(attr_names); i++) { 36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *str = attr_names[i]; 37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strncasecmp(name, str, len) && !str[len]) 38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return attr_values[i]; 39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid color_parse(const char *value, const char *var, char *dst) 44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng color_parse_mem(value, strlen(value), var, dst); 46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid color_parse_mem(const char *value, int value_len, const char *var, 49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *dst) 50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *ptr = value; 52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int len = value_len; 53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int attr = -1; 54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int fg = -2; 55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int bg = -2; 56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strncasecmp(value, "reset", len)) { 58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng strcpy(dst, PERF_COLOR_RESET); 59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* [fg [bg]] [attr] */ 63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (len > 0) { 64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *word = ptr; 65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int val, wordlen = 0; 66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (len > 0 && !isspace(word[wordlen])) { 68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng wordlen++; 69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng len--; 70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ptr = word + wordlen; 73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (len > 0 && isspace(*ptr)) { 74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ptr++; 75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng len--; 76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng val = parse_color(word, wordlen); 79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (val >= -1) { 80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (fg == -2) { 81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fg = val; 82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (bg == -2) { 85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bg = val; 86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto bad; 89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng val = parse_attr(word, wordlen); 91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (val < 0 || attr != -1) 92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto bad; 93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng attr = val; 94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (attr >= 0 || fg >= 0 || bg >= 0) { 97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int sep = 0; 98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = '\033'; 100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = '['; 101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (attr >= 0) { 102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = '0' + attr; 103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sep++; 104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (fg >= 0) { 106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sep++) 107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = ';'; 108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (fg < 8) { 109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = '3'; 110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = '0' + fg; 111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dst += sprintf(dst, "38;5;%d", fg); 113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (bg >= 0) { 116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sep++) 117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = ';'; 118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (bg < 8) { 119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = '4'; 120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = '0' + bg; 121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng dst += sprintf(dst, "48;5;%d", bg); 123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst++ = 'm'; 126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *dst = 0; 128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengbad: 130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng die("bad color value '%.*s' for variable '%s'", value_len, value, var); 131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint perf_config_colorbool(const char *var, const char *value, int stdout_is_tty) 134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (value) { 136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strcasecmp(value, "never")) 137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strcasecmp(value, "always")) 139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strcasecmp(value, "auto")) 141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto auto_color; 142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Missing or explicit false to turn off colorization */ 145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!perf_config_bool(var, value)) 146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* any normal truth value defaults to 'auto' */ 149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng auto_color: 150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (stdout_is_tty < 0) 151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng stdout_is_tty = isatty(1); 152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (stdout_is_tty || (pager_in_use() && pager_use_color)) { 153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *term = getenv("TERM"); 154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (term && strcmp(term, "dumb")) 155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint perf_color_default_config(const char *var, const char *value, void *cb) 161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strcmp(var, "color.ui")) { 163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_use_color_default = perf_config_colorbool(var, value, -1); 164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return perf_default_config(var, value, cb); 168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int __color_vsnprintf(char *bf, size_t size, const char *color, 171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *fmt, va_list args, const char *trail) 172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int r = 0; 174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Auto-detect: 177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_use_color_default < 0) { 179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (isatty(1) || pager_in_use()) 180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_use_color_default = 1; 181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_use_color_default = 0; 183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_use_color_default && *color) 186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r += scnprintf(bf, size, "%s", color); 187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r += vscnprintf(bf + r, size - r, fmt, args); 188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_use_color_default && *color) 189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET); 190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (trail) 191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r += scnprintf(bf + r, size - r, "%s", trail); 192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return r; 193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int __color_vfprintf(FILE *fp, const char *color, const char *fmt, 196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_list args, const char *trail) 197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int r = 0; 199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Auto-detect: 202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_use_color_default < 0) { 204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (isatty(fileno(fp)) || pager_in_use()) 205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_use_color_default = 1; 206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_use_color_default = 0; 208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_use_color_default && *color) 211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r += fprintf(fp, "%s", color); 212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r += vfprintf(fp, fmt, args); 213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_use_color_default && *color) 214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r += fprintf(fp, "%s", PERF_COLOR_RESET); 215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (trail) 216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r += fprintf(fp, "%s", trail); 217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return r; 218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint color_vsnprintf(char *bf, size_t size, const char *color, 221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *fmt, va_list args) 222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return __color_vsnprintf(bf, size, color, fmt, args, NULL); 224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) 227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return __color_vfprintf(fp, color, fmt, args, NULL); 229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint color_snprintf(char *bf, size_t size, const char *color, 232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *fmt, ...) 233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_list args; 235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int r; 236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_start(args, fmt); 238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r = color_vsnprintf(bf, size, color, fmt, args); 239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_end(args); 240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return r; 241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint color_fprintf(FILE *fp, const char *color, const char *fmt, ...) 244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_list args; 246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int r; 247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_start(args, fmt); 249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r = color_vfprintf(fp, color, fmt, args); 250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_end(args); 251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return r; 252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...) 255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_list args; 257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int r; 258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_start(args, fmt); 259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r = __color_vfprintf(fp, color, fmt, args, "\n"); 260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng va_end(args); 261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return r; 262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* 265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * This function splits the buffer by newlines and colors the lines individually. 266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * 267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Returns 0 on success. 268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint color_fwrite_lines(FILE *fp, const char *color, 270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t count, const char *buf) 271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!*color) 273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return fwrite(buf, count, 1, fp) != 1; 274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (count) { 276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *p = memchr(buf, '\n', count); 277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (p != buf && (fputs(color, fp) < 0 || 279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 || 280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fputs(PERF_COLOR_RESET, fp) < 0)) 281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!p) 283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (fputc('\n', fp) < 0) 285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng count -= p + 1 - buf; 287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng buf = p + 1; 288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengconst char *get_percent_color(double percent) 293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *color = PERF_COLOR_NORMAL; 295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * We color high-overhead entries in red, mid-overhead 298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * entries in green - and keep the low overhead places 299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * normal: 300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (percent >= MIN_RED) 302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng color = PERF_COLOR_RED; 303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else { 304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (percent > MIN_GREEN) 305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng color = PERF_COLOR_GREEN; 306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return color; 308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint percent_color_fprintf(FILE *fp, const char *fmt, double percent) 311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int r; 313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *color; 314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng color = get_percent_color(percent); 316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng r = color_fprintf(fp, color, fmt, percent); 317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return r; 319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 321f0ccdc5a2da8301af17b902901255002b59115ffElliott Hughesint percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) 322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 323f0ccdc5a2da8301af17b902901255002b59115ffElliott Hughes va_list args; 324f0ccdc5a2da8301af17b902901255002b59115ffElliott Hughes double percent; 325f0ccdc5a2da8301af17b902901255002b59115ffElliott Hughes const char *color; 326f0ccdc5a2da8301af17b902901255002b59115ffElliott Hughes 327f0ccdc5a2da8301af17b902901255002b59115ffElliott Hughes va_start(args, fmt); 328f0ccdc5a2da8301af17b902901255002b59115ffElliott Hughes percent = va_arg(args, double); 329f0ccdc5a2da8301af17b902901255002b59115ffElliott Hughes va_end(args); 330f0ccdc5a2da8301af17b902901255002b59115ffElliott Hughes color = get_percent_color(percent); 331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return color_snprintf(bf, size, color, fmt, percent); 332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 333