color.c 4.7 KB

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