1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/kernel.h> 3 #include <subcmd/pager.h> 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <string.h> 7 #include "color.h" 8 #include <math.h> 9 #include <unistd.h> 10 11 int perf_use_color_default = -1; 12 13 static int __color_vsnprintf(char *bf, size_t size, const char *color, 14 const char *fmt, va_list args, const char *trail) 15 { 16 int r = 0; 17 18 /* 19 * Auto-detect: 20 */ 21 if (perf_use_color_default < 0) { 22 if (isatty(1) || pager_in_use()) 23 perf_use_color_default = 1; 24 else 25 perf_use_color_default = 0; 26 } 27 28 if (perf_use_color_default && *color) 29 r += scnprintf(bf, size, "%s", color); 30 r += vscnprintf(bf + r, size - r, fmt, args); 31 if (perf_use_color_default && *color) 32 r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET); 33 if (trail) 34 r += scnprintf(bf + r, size - r, "%s", trail); 35 return r; 36 } 37 38 /* Colors are not included in return value */ 39 static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, 40 va_list args) 41 { 42 int r = 0; 43 44 /* 45 * Auto-detect: 46 */ 47 if (perf_use_color_default < 0) { 48 if (isatty(fileno(fp)) || pager_in_use()) 49 perf_use_color_default = 1; 50 else 51 perf_use_color_default = 0; 52 } 53 54 if (perf_use_color_default && *color) 55 fprintf(fp, "%s", color); 56 r += vfprintf(fp, fmt, args); 57 if (perf_use_color_default && *color) 58 fprintf(fp, "%s", PERF_COLOR_RESET); 59 return r; 60 } 61 62 int color_vsnprintf(char *bf, size_t size, const char *color, 63 const char *fmt, va_list args) 64 { 65 return __color_vsnprintf(bf, size, color, fmt, args, NULL); 66 } 67 68 int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) 69 { 70 return __color_vfprintf(fp, color, fmt, args); 71 } 72 73 int color_snprintf(char *bf, size_t size, const char *color, 74 const char *fmt, ...) 75 { 76 va_list args; 77 int r; 78 79 va_start(args, fmt); 80 r = color_vsnprintf(bf, size, color, fmt, args); 81 va_end(args); 82 return r; 83 } 84 85 int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) 86 { 87 va_list args; 88 int r; 89 90 va_start(args, fmt); 91 r = color_vfprintf(fp, color, fmt, args); 92 va_end(args); 93 return r; 94 } 95 96 /* 97 * This function splits the buffer by newlines and colors the lines individually. 98 * 99 * Returns 0 on success. 100 */ 101 int color_fwrite_lines(FILE *fp, const char *color, 102 size_t count, const char *buf) 103 { 104 if (!*color) 105 return fwrite(buf, count, 1, fp) != 1; 106 107 while (count) { 108 char *p = memchr(buf, '\n', count); 109 110 if (p != buf && (fputs(color, fp) < 0 || 111 fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 || 112 fputs(PERF_COLOR_RESET, fp) < 0)) 113 return -1; 114 if (!p) 115 return 0; 116 if (fputc('\n', fp) < 0) 117 return -1; 118 count -= p + 1 - buf; 119 buf = p + 1; 120 } 121 return 0; 122 } 123 124 const char *get_percent_color(double percent) 125 { 126 const char *color = PERF_COLOR_NORMAL; 127 128 /* 129 * We color high-overhead entries in red, mid-overhead 130 * entries in green - and keep the low overhead places 131 * normal: 132 */ 133 if (fabs(percent) >= MIN_RED) 134 color = PERF_COLOR_RED; 135 else { 136 if (fabs(percent) > MIN_GREEN) 137 color = PERF_COLOR_GREEN; 138 } 139 return color; 140 } 141 142 int percent_color_fprintf(FILE *fp, const char *fmt, double percent) 143 { 144 int r; 145 const char *color; 146 147 color = get_percent_color(percent); 148 r = color_fprintf(fp, color, fmt, percent); 149 150 return r; 151 } 152 153 int value_color_snprintf(char *bf, size_t size, const char *fmt, double value) 154 { 155 const char *color = get_percent_color(value); 156 return color_snprintf(bf, size, color, fmt, value); 157 } 158 159 int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) 160 { 161 va_list args; 162 double percent; 163 164 va_start(args, fmt); 165 percent = va_arg(args, double); 166 va_end(args); 167 return value_color_snprintf(bf, size, fmt, percent); 168 } 169 170 int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...) 171 { 172 va_list args; 173 int len; 174 double percent; 175 const char *color; 176 177 va_start(args, fmt); 178 len = va_arg(args, int); 179 percent = va_arg(args, double); 180 va_end(args); 181 182 color = get_percent_color(percent); 183 return color_snprintf(bf, size, color, fmt, len, percent); 184 } 185