1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2e7f01d1eSArnaldo Carvalho de Melo #include <linux/kernel.h>
3fa0d9846SArnaldo Carvalho de Melo #include <subcmd/pager.h>
4d0761e37SArnaldo Carvalho de Melo #include <stdlib.h>
5d0761e37SArnaldo Carvalho de Melo #include <stdio.h>
6fa0d9846SArnaldo Carvalho de Melo #include <string.h>
786470930SIngo Molnar #include "color.h"
8f77c6e9cSRamkumar Ramachandra #include <math.h>
916b7c9bdSArnaldo Carvalho de Melo #include <unistd.h>
1086470930SIngo Molnar
1186470930SIngo Molnar int perf_use_color_default = -1;
1286470930SIngo Molnar
__color_vsnprintf(char * bf,size_t size,const char * color,const char * fmt,va_list args,const char * trail)13a4e3b956SArnaldo Carvalho de Melo static int __color_vsnprintf(char *bf, size_t size, const char *color,
14a4e3b956SArnaldo Carvalho de Melo const char *fmt, va_list args, const char *trail)
15a4e3b956SArnaldo Carvalho de Melo {
16a4e3b956SArnaldo Carvalho de Melo int r = 0;
17a4e3b956SArnaldo Carvalho de Melo
18a4e3b956SArnaldo Carvalho de Melo /*
19a4e3b956SArnaldo Carvalho de Melo * Auto-detect:
20a4e3b956SArnaldo Carvalho de Melo */
21a4e3b956SArnaldo Carvalho de Melo if (perf_use_color_default < 0) {
22a4e3b956SArnaldo Carvalho de Melo if (isatty(1) || pager_in_use())
23a4e3b956SArnaldo Carvalho de Melo perf_use_color_default = 1;
24a4e3b956SArnaldo Carvalho de Melo else
25a4e3b956SArnaldo Carvalho de Melo perf_use_color_default = 0;
26a4e3b956SArnaldo Carvalho de Melo }
27a4e3b956SArnaldo Carvalho de Melo
28a4e3b956SArnaldo Carvalho de Melo if (perf_use_color_default && *color)
29e7f01d1eSArnaldo Carvalho de Melo r += scnprintf(bf, size, "%s", color);
30e7f01d1eSArnaldo Carvalho de Melo r += vscnprintf(bf + r, size - r, fmt, args);
31a4e3b956SArnaldo Carvalho de Melo if (perf_use_color_default && *color)
32e7f01d1eSArnaldo Carvalho de Melo r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
33a4e3b956SArnaldo Carvalho de Melo if (trail)
34e7f01d1eSArnaldo Carvalho de Melo r += scnprintf(bf + r, size - r, "%s", trail);
35a4e3b956SArnaldo Carvalho de Melo return r;
36a4e3b956SArnaldo Carvalho de Melo }
37a4e3b956SArnaldo Carvalho de Melo
38b7a001d2SAndi Kleen /* Colors are not included in return value */
__color_vfprintf(FILE * fp,const char * color,const char * fmt,va_list args)398f28827aSFrederic Weisbecker static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
408011de7aSJiri Olsa va_list args)
4186470930SIngo Molnar {
4286470930SIngo Molnar int r = 0;
4386470930SIngo Molnar
4486470930SIngo Molnar /*
4586470930SIngo Molnar * Auto-detect:
4686470930SIngo Molnar */
4786470930SIngo Molnar if (perf_use_color_default < 0) {
484aa9015fSStephane Eranian if (isatty(fileno(fp)) || pager_in_use())
4986470930SIngo Molnar perf_use_color_default = 1;
5086470930SIngo Molnar else
5186470930SIngo Molnar perf_use_color_default = 0;
5286470930SIngo Molnar }
5386470930SIngo Molnar
5486470930SIngo Molnar if (perf_use_color_default && *color)
55b7a001d2SAndi Kleen fprintf(fp, "%s", color);
5686470930SIngo Molnar r += vfprintf(fp, fmt, args);
5786470930SIngo Molnar if (perf_use_color_default && *color)
58b7a001d2SAndi Kleen fprintf(fp, "%s", PERF_COLOR_RESET);
5986470930SIngo Molnar return r;
6086470930SIngo Molnar }
6186470930SIngo Molnar
color_vsnprintf(char * bf,size_t size,const char * color,const char * fmt,va_list args)62a4e3b956SArnaldo Carvalho de Melo int color_vsnprintf(char *bf, size_t size, const char *color,
63a4e3b956SArnaldo Carvalho de Melo const char *fmt, va_list args)
64a4e3b956SArnaldo Carvalho de Melo {
65a4e3b956SArnaldo Carvalho de Melo return __color_vsnprintf(bf, size, color, fmt, args, NULL);
66a4e3b956SArnaldo Carvalho de Melo }
67a4e3b956SArnaldo Carvalho de Melo
color_vfprintf(FILE * fp,const char * color,const char * fmt,va_list args)688f28827aSFrederic Weisbecker int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
698f28827aSFrederic Weisbecker {
708011de7aSJiri Olsa return __color_vfprintf(fp, color, fmt, args);
718f28827aSFrederic Weisbecker }
7286470930SIngo Molnar
color_snprintf(char * bf,size_t size,const char * color,const char * fmt,...)73a4e3b956SArnaldo Carvalho de Melo int color_snprintf(char *bf, size_t size, const char *color,
74a4e3b956SArnaldo Carvalho de Melo const char *fmt, ...)
75a4e3b956SArnaldo Carvalho de Melo {
76a4e3b956SArnaldo Carvalho de Melo va_list args;
77a4e3b956SArnaldo Carvalho de Melo int r;
78a4e3b956SArnaldo Carvalho de Melo
79a4e3b956SArnaldo Carvalho de Melo va_start(args, fmt);
80a4e3b956SArnaldo Carvalho de Melo r = color_vsnprintf(bf, size, color, fmt, args);
81a4e3b956SArnaldo Carvalho de Melo va_end(args);
82a4e3b956SArnaldo Carvalho de Melo return r;
83a4e3b956SArnaldo Carvalho de Melo }
8486470930SIngo Molnar
color_fprintf(FILE * fp,const char * color,const char * fmt,...)8586470930SIngo Molnar int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
8686470930SIngo Molnar {
8786470930SIngo Molnar va_list args;
8886470930SIngo Molnar int r;
8986470930SIngo Molnar
9086470930SIngo Molnar va_start(args, fmt);
918f28827aSFrederic Weisbecker r = color_vfprintf(fp, color, fmt, args);
9286470930SIngo Molnar va_end(args);
9386470930SIngo Molnar return r;
9486470930SIngo Molnar }
9586470930SIngo Molnar
9686470930SIngo Molnar /*
9786470930SIngo Molnar * This function splits the buffer by newlines and colors the lines individually.
9886470930SIngo Molnar *
9986470930SIngo Molnar * Returns 0 on success.
10086470930SIngo Molnar */
color_fwrite_lines(FILE * fp,const char * color,size_t count,const char * buf)10186470930SIngo Molnar int color_fwrite_lines(FILE *fp, const char *color,
10286470930SIngo Molnar size_t count, const char *buf)
10386470930SIngo Molnar {
10486470930SIngo Molnar if (!*color)
10586470930SIngo Molnar return fwrite(buf, count, 1, fp) != 1;
106f37a291cSIngo Molnar
10786470930SIngo Molnar while (count) {
10886470930SIngo Molnar char *p = memchr(buf, '\n', count);
109f37a291cSIngo Molnar
11086470930SIngo Molnar if (p != buf && (fputs(color, fp) < 0 ||
111f37a291cSIngo Molnar fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 ||
11286470930SIngo Molnar fputs(PERF_COLOR_RESET, fp) < 0))
11386470930SIngo Molnar return -1;
11486470930SIngo Molnar if (!p)
11586470930SIngo Molnar return 0;
11686470930SIngo Molnar if (fputc('\n', fp) < 0)
11786470930SIngo Molnar return -1;
11886470930SIngo Molnar count -= p + 1 - buf;
11986470930SIngo Molnar buf = p + 1;
12086470930SIngo Molnar }
12186470930SIngo Molnar return 0;
12286470930SIngo Molnar }
12386470930SIngo Molnar
get_percent_color(double percent)12483a0944fSIngo Molnar const char *get_percent_color(double percent)
1251e11fd82SFrederic Weisbecker {
12683a0944fSIngo Molnar const char *color = PERF_COLOR_NORMAL;
12786470930SIngo Molnar
1281e11fd82SFrederic Weisbecker /*
1291e11fd82SFrederic Weisbecker * We color high-overhead entries in red, mid-overhead
1301e11fd82SFrederic Weisbecker * entries in green - and keep the low overhead places
1311e11fd82SFrederic Weisbecker * normal:
1321e11fd82SFrederic Weisbecker */
133f77c6e9cSRamkumar Ramachandra if (fabs(percent) >= MIN_RED)
1341e11fd82SFrederic Weisbecker color = PERF_COLOR_RED;
1351e11fd82SFrederic Weisbecker else {
136f77c6e9cSRamkumar Ramachandra if (fabs(percent) > MIN_GREEN)
1371e11fd82SFrederic Weisbecker color = PERF_COLOR_GREEN;
1381e11fd82SFrederic Weisbecker }
1391e11fd82SFrederic Weisbecker return color;
1401e11fd82SFrederic Weisbecker }
1411e11fd82SFrederic Weisbecker
percent_color_fprintf(FILE * fp,const char * fmt,double percent)1421e11fd82SFrederic Weisbecker int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
1431e11fd82SFrederic Weisbecker {
1441e11fd82SFrederic Weisbecker int r;
14583a0944fSIngo Molnar const char *color;
1461e11fd82SFrederic Weisbecker
1471e11fd82SFrederic Weisbecker color = get_percent_color(percent);
1481e11fd82SFrederic Weisbecker r = color_fprintf(fp, color, fmt, percent);
1491e11fd82SFrederic Weisbecker
1501e11fd82SFrederic Weisbecker return r;
1511e11fd82SFrederic Weisbecker }
152a4e3b956SArnaldo Carvalho de Melo
value_color_snprintf(char * bf,size_t size,const char * fmt,double value)1531f513b2cSRamkumar Ramachandra int value_color_snprintf(char *bf, size_t size, const char *fmt, double value)
1541f513b2cSRamkumar Ramachandra {
1551f513b2cSRamkumar Ramachandra const char *color = get_percent_color(value);
1561f513b2cSRamkumar Ramachandra return color_snprintf(bf, size, color, fmt, value);
1571f513b2cSRamkumar Ramachandra }
1581f513b2cSRamkumar Ramachandra
percent_color_snprintf(char * bf,size_t size,const char * fmt,...)15953805ecaSMichael Hudson-Doyle int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
160a4e3b956SArnaldo Carvalho de Melo {
16153805ecaSMichael Hudson-Doyle va_list args;
16253805ecaSMichael Hudson-Doyle double percent;
16353805ecaSMichael Hudson-Doyle
16453805ecaSMichael Hudson-Doyle va_start(args, fmt);
16553805ecaSMichael Hudson-Doyle percent = va_arg(args, double);
16653805ecaSMichael Hudson-Doyle va_end(args);
1671f513b2cSRamkumar Ramachandra return value_color_snprintf(bf, size, fmt, percent);
168a4e3b956SArnaldo Carvalho de Melo }
169d675107cSNamhyung Kim
percent_color_len_snprintf(char * bf,size_t size,const char * fmt,...)170d675107cSNamhyung Kim int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
171d675107cSNamhyung Kim {
172d675107cSNamhyung Kim va_list args;
173d675107cSNamhyung Kim int len;
174d675107cSNamhyung Kim double percent;
175d675107cSNamhyung Kim const char *color;
176d675107cSNamhyung Kim
177d675107cSNamhyung Kim va_start(args, fmt);
178d675107cSNamhyung Kim len = va_arg(args, int);
179d675107cSNamhyung Kim percent = va_arg(args, double);
180d675107cSNamhyung Kim va_end(args);
181d675107cSNamhyung Kim
182d675107cSNamhyung Kim color = get_percent_color(percent);
183d675107cSNamhyung Kim return color_snprintf(bf, size, color, fmt, len, percent);
184d675107cSNamhyung Kim }
185