color.c 4.9 KB

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