color.c (3988B)
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 11int perf_use_color_default = -1; 12 13static 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 */ 39static 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 62int 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 68int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) 69{ 70 return __color_vfprintf(fp, color, fmt, args); 71} 72 73int 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 85int 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 */ 101int 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 124const 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 142int 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 153int 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 159int 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 170int 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}