185 lines · c
1// SPDX-License-Identifier: GPL-2.02#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 else25 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 else51 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-overhead130 * entries in green - and keep the low overhead places131 * 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}185