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