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 const char *get_percent_color(double percent) 97 { 98 const char *color = PERF_COLOR_NORMAL; 99 100 /* 101 * We color high-overhead entries in red, mid-overhead 102 * entries in green - and keep the low overhead places 103 * normal: 104 */ 105 if (fabs(percent) >= MIN_RED) 106 color = PERF_COLOR_RED; 107 else { 108 if (fabs(percent) > MIN_GREEN) 109 color = PERF_COLOR_GREEN; 110 } 111 return color; 112 } 113 114 int percent_color_fprintf(FILE *fp, const char *fmt, double percent) 115 { 116 int r; 117 const char *color; 118 119 color = get_percent_color(percent); 120 r = color_fprintf(fp, color, fmt, percent); 121 122 return r; 123 } 124 125 int value_color_snprintf(char *bf, size_t size, const char *fmt, double value) 126 { 127 const char *color = get_percent_color(value); 128 return color_snprintf(bf, size, color, fmt, value); 129 } 130 131 int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) 132 { 133 va_list args; 134 double percent; 135 136 va_start(args, fmt); 137 percent = va_arg(args, double); 138 va_end(args); 139 return value_color_snprintf(bf, size, fmt, percent); 140 } 141 142 int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...) 143 { 144 va_list args; 145 int len; 146 double percent; 147 const char *color; 148 149 va_start(args, fmt); 150 len = va_arg(args, int); 151 percent = va_arg(args, double); 152 va_end(args); 153 154 color = get_percent_color(percent); 155 return color_snprintf(bf, size, color, fmt, len, percent); 156 } 157