1e7f01d1eSArnaldo Carvalho de Melo #include <linux/kernel.h> 286470930SIngo Molnar #include "cache.h" 386470930SIngo Molnar #include "color.h" 4f77c6e9cSRamkumar Ramachandra #include <math.h> 586470930SIngo Molnar 686470930SIngo Molnar int perf_use_color_default = -1; 786470930SIngo Molnar 886470930SIngo Molnar int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty) 986470930SIngo Molnar { 1086470930SIngo Molnar if (value) { 1186470930SIngo Molnar if (!strcasecmp(value, "never")) 1286470930SIngo Molnar return 0; 1386470930SIngo Molnar if (!strcasecmp(value, "always")) 1486470930SIngo Molnar return 1; 1586470930SIngo Molnar if (!strcasecmp(value, "auto")) 1686470930SIngo Molnar goto auto_color; 1786470930SIngo Molnar } 1886470930SIngo Molnar 1986470930SIngo Molnar /* Missing or explicit false to turn off colorization */ 2086470930SIngo Molnar if (!perf_config_bool(var, value)) 2186470930SIngo Molnar return 0; 2286470930SIngo Molnar 2386470930SIngo Molnar /* any normal truth value defaults to 'auto' */ 2486470930SIngo Molnar auto_color: 2586470930SIngo Molnar if (stdout_is_tty < 0) 2686470930SIngo Molnar stdout_is_tty = isatty(1); 2786470930SIngo Molnar if (stdout_is_tty || (pager_in_use() && pager_use_color)) { 2886470930SIngo Molnar char *term = getenv("TERM"); 2986470930SIngo Molnar if (term && strcmp(term, "dumb")) 3086470930SIngo Molnar return 1; 3186470930SIngo Molnar } 3286470930SIngo Molnar return 0; 3386470930SIngo Molnar } 3486470930SIngo Molnar 3586470930SIngo Molnar int perf_color_default_config(const char *var, const char *value, void *cb) 3686470930SIngo Molnar { 3786470930SIngo Molnar if (!strcmp(var, "color.ui")) { 3886470930SIngo Molnar perf_use_color_default = perf_config_colorbool(var, value, -1); 3986470930SIngo Molnar return 0; 4086470930SIngo Molnar } 4186470930SIngo Molnar 4286470930SIngo Molnar return perf_default_config(var, value, cb); 4386470930SIngo Molnar } 4486470930SIngo Molnar 45a4e3b956SArnaldo Carvalho de Melo static int __color_vsnprintf(char *bf, size_t size, const char *color, 46a4e3b956SArnaldo Carvalho de Melo const char *fmt, va_list args, const char *trail) 47a4e3b956SArnaldo Carvalho de Melo { 48a4e3b956SArnaldo Carvalho de Melo int r = 0; 49a4e3b956SArnaldo Carvalho de Melo 50a4e3b956SArnaldo Carvalho de Melo /* 51a4e3b956SArnaldo Carvalho de Melo * Auto-detect: 52a4e3b956SArnaldo Carvalho de Melo */ 53a4e3b956SArnaldo Carvalho de Melo if (perf_use_color_default < 0) { 54a4e3b956SArnaldo Carvalho de Melo if (isatty(1) || pager_in_use()) 55a4e3b956SArnaldo Carvalho de Melo perf_use_color_default = 1; 56a4e3b956SArnaldo Carvalho de Melo else 57a4e3b956SArnaldo Carvalho de Melo perf_use_color_default = 0; 58a4e3b956SArnaldo Carvalho de Melo } 59a4e3b956SArnaldo Carvalho de Melo 60a4e3b956SArnaldo Carvalho de Melo if (perf_use_color_default && *color) 61e7f01d1eSArnaldo Carvalho de Melo r += scnprintf(bf, size, "%s", color); 62e7f01d1eSArnaldo Carvalho de Melo r += vscnprintf(bf + r, size - r, fmt, args); 63a4e3b956SArnaldo Carvalho de Melo if (perf_use_color_default && *color) 64e7f01d1eSArnaldo Carvalho de Melo r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET); 65a4e3b956SArnaldo Carvalho de Melo if (trail) 66e7f01d1eSArnaldo Carvalho de Melo r += scnprintf(bf + r, size - r, "%s", trail); 67a4e3b956SArnaldo Carvalho de Melo return r; 68a4e3b956SArnaldo Carvalho de Melo } 69a4e3b956SArnaldo Carvalho de Melo 70b7a001d2SAndi Kleen /* Colors are not included in return value */ 718f28827aSFrederic Weisbecker static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, 728011de7aSJiri Olsa va_list args) 7386470930SIngo Molnar { 7486470930SIngo Molnar int r = 0; 7586470930SIngo Molnar 7686470930SIngo Molnar /* 7786470930SIngo Molnar * Auto-detect: 7886470930SIngo Molnar */ 7986470930SIngo Molnar if (perf_use_color_default < 0) { 804aa9015fSStephane Eranian if (isatty(fileno(fp)) || pager_in_use()) 8186470930SIngo Molnar perf_use_color_default = 1; 8286470930SIngo Molnar else 8386470930SIngo Molnar perf_use_color_default = 0; 8486470930SIngo Molnar } 8586470930SIngo Molnar 8686470930SIngo Molnar if (perf_use_color_default && *color) 87b7a001d2SAndi Kleen fprintf(fp, "%s", color); 8886470930SIngo Molnar r += vfprintf(fp, fmt, args); 8986470930SIngo Molnar if (perf_use_color_default && *color) 90b7a001d2SAndi Kleen fprintf(fp, "%s", PERF_COLOR_RESET); 9186470930SIngo Molnar return r; 9286470930SIngo Molnar } 9386470930SIngo Molnar 94a4e3b956SArnaldo Carvalho de Melo int color_vsnprintf(char *bf, size_t size, const char *color, 95a4e3b956SArnaldo Carvalho de Melo const char *fmt, va_list args) 96a4e3b956SArnaldo Carvalho de Melo { 97a4e3b956SArnaldo Carvalho de Melo return __color_vsnprintf(bf, size, color, fmt, args, NULL); 98a4e3b956SArnaldo Carvalho de Melo } 99a4e3b956SArnaldo Carvalho de Melo 1008f28827aSFrederic Weisbecker int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) 1018f28827aSFrederic Weisbecker { 1028011de7aSJiri Olsa return __color_vfprintf(fp, color, fmt, args); 1038f28827aSFrederic Weisbecker } 10486470930SIngo Molnar 105a4e3b956SArnaldo Carvalho de Melo int color_snprintf(char *bf, size_t size, const char *color, 106a4e3b956SArnaldo Carvalho de Melo const char *fmt, ...) 107a4e3b956SArnaldo Carvalho de Melo { 108a4e3b956SArnaldo Carvalho de Melo va_list args; 109a4e3b956SArnaldo Carvalho de Melo int r; 110a4e3b956SArnaldo Carvalho de Melo 111a4e3b956SArnaldo Carvalho de Melo va_start(args, fmt); 112a4e3b956SArnaldo Carvalho de Melo r = color_vsnprintf(bf, size, color, fmt, args); 113a4e3b956SArnaldo Carvalho de Melo va_end(args); 114a4e3b956SArnaldo Carvalho de Melo return r; 115a4e3b956SArnaldo Carvalho de Melo } 11686470930SIngo Molnar 11786470930SIngo Molnar int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) 11886470930SIngo Molnar { 11986470930SIngo Molnar va_list args; 12086470930SIngo Molnar int r; 12186470930SIngo Molnar 12286470930SIngo Molnar va_start(args, fmt); 1238f28827aSFrederic Weisbecker r = color_vfprintf(fp, color, fmt, args); 12486470930SIngo Molnar va_end(args); 12586470930SIngo Molnar return r; 12686470930SIngo Molnar } 12786470930SIngo Molnar 12886470930SIngo Molnar /* 12986470930SIngo Molnar * This function splits the buffer by newlines and colors the lines individually. 13086470930SIngo Molnar * 13186470930SIngo Molnar * Returns 0 on success. 13286470930SIngo Molnar */ 13386470930SIngo Molnar int color_fwrite_lines(FILE *fp, const char *color, 13486470930SIngo Molnar size_t count, const char *buf) 13586470930SIngo Molnar { 13686470930SIngo Molnar if (!*color) 13786470930SIngo Molnar return fwrite(buf, count, 1, fp) != 1; 138f37a291cSIngo Molnar 13986470930SIngo Molnar while (count) { 14086470930SIngo Molnar char *p = memchr(buf, '\n', count); 141f37a291cSIngo Molnar 14286470930SIngo Molnar if (p != buf && (fputs(color, fp) < 0 || 143f37a291cSIngo Molnar fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 || 14486470930SIngo Molnar fputs(PERF_COLOR_RESET, fp) < 0)) 14586470930SIngo Molnar return -1; 14686470930SIngo Molnar if (!p) 14786470930SIngo Molnar return 0; 14886470930SIngo Molnar if (fputc('\n', fp) < 0) 14986470930SIngo Molnar return -1; 15086470930SIngo Molnar count -= p + 1 - buf; 15186470930SIngo Molnar buf = p + 1; 15286470930SIngo Molnar } 15386470930SIngo Molnar return 0; 15486470930SIngo Molnar } 15586470930SIngo Molnar 15683a0944fSIngo Molnar const char *get_percent_color(double percent) 1571e11fd82SFrederic Weisbecker { 15883a0944fSIngo Molnar const char *color = PERF_COLOR_NORMAL; 15986470930SIngo Molnar 1601e11fd82SFrederic Weisbecker /* 1611e11fd82SFrederic Weisbecker * We color high-overhead entries in red, mid-overhead 1621e11fd82SFrederic Weisbecker * entries in green - and keep the low overhead places 1631e11fd82SFrederic Weisbecker * normal: 1641e11fd82SFrederic Weisbecker */ 165f77c6e9cSRamkumar Ramachandra if (fabs(percent) >= MIN_RED) 1661e11fd82SFrederic Weisbecker color = PERF_COLOR_RED; 1671e11fd82SFrederic Weisbecker else { 168f77c6e9cSRamkumar Ramachandra if (fabs(percent) > MIN_GREEN) 1691e11fd82SFrederic Weisbecker color = PERF_COLOR_GREEN; 1701e11fd82SFrederic Weisbecker } 1711e11fd82SFrederic Weisbecker return color; 1721e11fd82SFrederic Weisbecker } 1731e11fd82SFrederic Weisbecker 1741e11fd82SFrederic Weisbecker int percent_color_fprintf(FILE *fp, const char *fmt, double percent) 1751e11fd82SFrederic Weisbecker { 1761e11fd82SFrederic Weisbecker int r; 17783a0944fSIngo Molnar const char *color; 1781e11fd82SFrederic Weisbecker 1791e11fd82SFrederic Weisbecker color = get_percent_color(percent); 1801e11fd82SFrederic Weisbecker r = color_fprintf(fp, color, fmt, percent); 1811e11fd82SFrederic Weisbecker 1821e11fd82SFrederic Weisbecker return r; 1831e11fd82SFrederic Weisbecker } 184a4e3b956SArnaldo Carvalho de Melo 1851f513b2cSRamkumar Ramachandra int value_color_snprintf(char *bf, size_t size, const char *fmt, double value) 1861f513b2cSRamkumar Ramachandra { 1871f513b2cSRamkumar Ramachandra const char *color = get_percent_color(value); 1881f513b2cSRamkumar Ramachandra return color_snprintf(bf, size, color, fmt, value); 1891f513b2cSRamkumar Ramachandra } 1901f513b2cSRamkumar Ramachandra 19153805ecaSMichael Hudson-Doyle int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) 192a4e3b956SArnaldo Carvalho de Melo { 19353805ecaSMichael Hudson-Doyle va_list args; 19453805ecaSMichael Hudson-Doyle double percent; 19553805ecaSMichael Hudson-Doyle 19653805ecaSMichael Hudson-Doyle va_start(args, fmt); 19753805ecaSMichael Hudson-Doyle percent = va_arg(args, double); 19853805ecaSMichael Hudson-Doyle va_end(args); 1991f513b2cSRamkumar Ramachandra return value_color_snprintf(bf, size, fmt, percent); 200a4e3b956SArnaldo Carvalho de Melo } 201d675107cSNamhyung Kim 202d675107cSNamhyung Kim int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...) 203d675107cSNamhyung Kim { 204d675107cSNamhyung Kim va_list args; 205d675107cSNamhyung Kim int len; 206d675107cSNamhyung Kim double percent; 207d675107cSNamhyung Kim const char *color; 208d675107cSNamhyung Kim 209d675107cSNamhyung Kim va_start(args, fmt); 210d675107cSNamhyung Kim len = va_arg(args, int); 211d675107cSNamhyung Kim percent = va_arg(args, double); 212d675107cSNamhyung Kim va_end(args); 213d675107cSNamhyung Kim 214d675107cSNamhyung Kim color = get_percent_color(percent); 215d675107cSNamhyung Kim return color_snprintf(bf, size, color, fmt, len, percent); 216d675107cSNamhyung Kim } 217