linux/tools/perf/util/color.c
<<
>>
Prefs
   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
  10int perf_use_color_default = -1;
  11
  12static 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 */
  38static 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
  61int 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
  67int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
  68{
  69        return __color_vfprintf(fp, color, fmt, args);
  70}
  71
  72int 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
  84int 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 */
 100int 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
 123const 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
 141int 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
 152int 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
 158int 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
 169int 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