color.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. int perf_use_color_default = -1;
  11. static int __color_vsnprintf(char *bf, size_t size, const char *color,
  12. const char *fmt, va_list args, const char *trail)
  13. {
  14. int r = 0;
  15. /*
  16. * Auto-detect:
  17. */
  18. if (perf_use_color_default < 0) {
  19. if (isatty(1) || pager_in_use())
  20. perf_use_color_default = 1;
  21. else
  22. perf_use_color_default = 0;
  23. }
  24. if (perf_use_color_default && *color)
  25. r += scnprintf(bf, size, "%s", color);
  26. r += vscnprintf(bf + r, size - r, fmt, args);
  27. if (perf_use_color_default && *color)
  28. r += scnprintf(bf + r, size - r, "%s", PERF_COLOR_RESET);
  29. if (trail)
  30. r += scnprintf(bf + r, size - r, "%s", trail);
  31. return r;
  32. }
  33. /* Colors are not included in return value */
  34. static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
  35. va_list args)
  36. {
  37. int r = 0;
  38. /*
  39. * Auto-detect:
  40. */
  41. if (perf_use_color_default < 0) {
  42. if (isatty(fileno(fp)) || pager_in_use())
  43. perf_use_color_default = 1;
  44. else
  45. perf_use_color_default = 0;
  46. }
  47. if (perf_use_color_default && *color)
  48. fprintf(fp, "%s", color);
  49. r += vfprintf(fp, fmt, args);
  50. if (perf_use_color_default && *color)
  51. fprintf(fp, "%s", PERF_COLOR_RESET);
  52. return r;
  53. }
  54. int color_vsnprintf(char *bf, size_t size, const char *color,
  55. const char *fmt, va_list args)
  56. {
  57. return __color_vsnprintf(bf, size, color, fmt, args, NULL);
  58. }
  59. int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
  60. {
  61. return __color_vfprintf(fp, color, fmt, args);
  62. }
  63. int color_snprintf(char *bf, size_t size, const char *color,
  64. const char *fmt, ...)
  65. {
  66. va_list args;
  67. int r;
  68. va_start(args, fmt);
  69. r = color_vsnprintf(bf, size, color, fmt, args);
  70. va_end(args);
  71. return r;
  72. }
  73. int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
  74. {
  75. va_list args;
  76. int r;
  77. va_start(args, fmt);
  78. r = color_vfprintf(fp, color, fmt, args);
  79. va_end(args);
  80. return r;
  81. }
  82. /*
  83. * This function splits the buffer by newlines and colors the lines individually.
  84. *
  85. * Returns 0 on success.
  86. */
  87. int color_fwrite_lines(FILE *fp, const char *color,
  88. size_t count, const char *buf)
  89. {
  90. if (!*color)
  91. return fwrite(buf, count, 1, fp) != 1;
  92. while (count) {
  93. char *p = memchr(buf, '\n', count);
  94. if (p != buf && (fputs(color, fp) < 0 ||
  95. fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 ||
  96. fputs(PERF_COLOR_RESET, fp) < 0))
  97. return -1;
  98. if (!p)
  99. return 0;
  100. if (fputc('\n', fp) < 0)
  101. return -1;
  102. count -= p + 1 - buf;
  103. buf = p + 1;
  104. }
  105. return 0;
  106. }
  107. const char *get_percent_color(double percent)
  108. {
  109. const char *color = PERF_COLOR_NORMAL;
  110. /*
  111. * We color high-overhead entries in red, mid-overhead
  112. * entries in green - and keep the low overhead places
  113. * normal:
  114. */
  115. if (fabs(percent) >= MIN_RED)
  116. color = PERF_COLOR_RED;
  117. else {
  118. if (fabs(percent) > MIN_GREEN)
  119. color = PERF_COLOR_GREEN;
  120. }
  121. return color;
  122. }
  123. int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
  124. {
  125. int r;
  126. const char *color;
  127. color = get_percent_color(percent);
  128. r = color_fprintf(fp, color, fmt, percent);
  129. return r;
  130. }
  131. int value_color_snprintf(char *bf, size_t size, const char *fmt, double value)
  132. {
  133. const char *color = get_percent_color(value);
  134. return color_snprintf(bf, size, color, fmt, value);
  135. }
  136. int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
  137. {
  138. va_list args;
  139. double percent;
  140. va_start(args, fmt);
  141. percent = va_arg(args, double);
  142. va_end(args);
  143. return value_color_snprintf(bf, size, fmt, percent);
  144. }
  145. int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
  146. {
  147. va_list args;
  148. int len;
  149. double percent;
  150. const char *color;
  151. va_start(args, fmt);
  152. len = va_arg(args, int);
  153. percent = va_arg(args, double);
  154. va_end(args);
  155. color = get_percent_color(percent);
  156. return color_snprintf(bf, size, color, fmt, len, percent);
  157. }