-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
perf_counter tools: Add color terminal output support
Add Git's color printing library to util/color.[ch]. Add it to perf report, with a trivial example to print high-overhead entries in red, low-overhead entries in green. Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
- Loading branch information
Ingo Molnar
committed
Jun 4, 2009
1 parent
71dd894
commit 8fc0321
Showing
6 changed files
with
300 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
#include "cache.h" | ||
#include "color.h" | ||
|
||
int perf_use_color_default = 0; | ||
|
||
static int parse_color(const char *name, int len) | ||
{ | ||
static const char * const color_names[] = { | ||
"normal", "black", "red", "green", "yellow", | ||
"blue", "magenta", "cyan", "white" | ||
}; | ||
char *end; | ||
int i; | ||
for (i = 0; i < ARRAY_SIZE(color_names); i++) { | ||
const char *str = color_names[i]; | ||
if (!strncasecmp(name, str, len) && !str[len]) | ||
return i - 1; | ||
} | ||
i = strtol(name, &end, 10); | ||
if (end - name == len && i >= -1 && i <= 255) | ||
return i; | ||
return -2; | ||
} | ||
|
||
static int parse_attr(const char *name, int len) | ||
{ | ||
static const int attr_values[] = { 1, 2, 4, 5, 7 }; | ||
static const char * const attr_names[] = { | ||
"bold", "dim", "ul", "blink", "reverse" | ||
}; | ||
int i; | ||
for (i = 0; i < ARRAY_SIZE(attr_names); i++) { | ||
const char *str = attr_names[i]; | ||
if (!strncasecmp(name, str, len) && !str[len]) | ||
return attr_values[i]; | ||
} | ||
return -1; | ||
} | ||
|
||
void color_parse(const char *value, const char *var, char *dst) | ||
{ | ||
color_parse_mem(value, strlen(value), var, dst); | ||
} | ||
|
||
void color_parse_mem(const char *value, int value_len, const char *var, | ||
char *dst) | ||
{ | ||
const char *ptr = value; | ||
int len = value_len; | ||
int attr = -1; | ||
int fg = -2; | ||
int bg = -2; | ||
|
||
if (!strncasecmp(value, "reset", len)) { | ||
strcpy(dst, PERF_COLOR_RESET); | ||
return; | ||
} | ||
|
||
/* [fg [bg]] [attr] */ | ||
while (len > 0) { | ||
const char *word = ptr; | ||
int val, wordlen = 0; | ||
|
||
while (len > 0 && !isspace(word[wordlen])) { | ||
wordlen++; | ||
len--; | ||
} | ||
|
||
ptr = word + wordlen; | ||
while (len > 0 && isspace(*ptr)) { | ||
ptr++; | ||
len--; | ||
} | ||
|
||
val = parse_color(word, wordlen); | ||
if (val >= -1) { | ||
if (fg == -2) { | ||
fg = val; | ||
continue; | ||
} | ||
if (bg == -2) { | ||
bg = val; | ||
continue; | ||
} | ||
goto bad; | ||
} | ||
val = parse_attr(word, wordlen); | ||
if (val < 0 || attr != -1) | ||
goto bad; | ||
attr = val; | ||
} | ||
|
||
if (attr >= 0 || fg >= 0 || bg >= 0) { | ||
int sep = 0; | ||
|
||
*dst++ = '\033'; | ||
*dst++ = '['; | ||
if (attr >= 0) { | ||
*dst++ = '0' + attr; | ||
sep++; | ||
} | ||
if (fg >= 0) { | ||
if (sep++) | ||
*dst++ = ';'; | ||
if (fg < 8) { | ||
*dst++ = '3'; | ||
*dst++ = '0' + fg; | ||
} else { | ||
dst += sprintf(dst, "38;5;%d", fg); | ||
} | ||
} | ||
if (bg >= 0) { | ||
if (sep++) | ||
*dst++ = ';'; | ||
if (bg < 8) { | ||
*dst++ = '4'; | ||
*dst++ = '0' + bg; | ||
} else { | ||
dst += sprintf(dst, "48;5;%d", bg); | ||
} | ||
} | ||
*dst++ = 'm'; | ||
} | ||
*dst = 0; | ||
return; | ||
bad: | ||
die("bad color value '%.*s' for variable '%s'", value_len, value, var); | ||
} | ||
|
||
int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty) | ||
{ | ||
if (value) { | ||
if (!strcasecmp(value, "never")) | ||
return 0; | ||
if (!strcasecmp(value, "always")) | ||
return 1; | ||
if (!strcasecmp(value, "auto")) | ||
goto auto_color; | ||
} | ||
|
||
/* Missing or explicit false to turn off colorization */ | ||
if (!perf_config_bool(var, value)) | ||
return 0; | ||
|
||
/* any normal truth value defaults to 'auto' */ | ||
auto_color: | ||
if (stdout_is_tty < 0) | ||
stdout_is_tty = isatty(1); | ||
if (stdout_is_tty || (pager_in_use() && pager_use_color)) { | ||
char *term = getenv("TERM"); | ||
if (term && strcmp(term, "dumb")) | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
int perf_color_default_config(const char *var, const char *value, void *cb) | ||
{ | ||
if (!strcmp(var, "color.ui")) { | ||
perf_use_color_default = perf_config_colorbool(var, value, -1); | ||
return 0; | ||
} | ||
|
||
return perf_default_config(var, value, cb); | ||
} | ||
|
||
static int color_vfprintf(FILE *fp, const char *color, const char *fmt, | ||
va_list args, const char *trail) | ||
{ | ||
int r = 0; | ||
|
||
if (*color) | ||
r += fprintf(fp, "%s", color); | ||
r += vfprintf(fp, fmt, args); | ||
if (*color) | ||
r += fprintf(fp, "%s", PERF_COLOR_RESET); | ||
if (trail) | ||
r += fprintf(fp, "%s", trail); | ||
return r; | ||
} | ||
|
||
|
||
|
||
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) | ||
{ | ||
va_list args; | ||
int r; | ||
va_start(args, fmt); | ||
r = color_vfprintf(fp, color, fmt, args, NULL); | ||
va_end(args); | ||
return r; | ||
} | ||
|
||
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...) | ||
{ | ||
va_list args; | ||
int r; | ||
va_start(args, fmt); | ||
r = color_vfprintf(fp, color, fmt, args, "\n"); | ||
va_end(args); | ||
return r; | ||
} | ||
|
||
/* | ||
* This function splits the buffer by newlines and colors the lines individually. | ||
* | ||
* Returns 0 on success. | ||
*/ | ||
int color_fwrite_lines(FILE *fp, const char *color, | ||
size_t count, const char *buf) | ||
{ | ||
if (!*color) | ||
return fwrite(buf, count, 1, fp) != 1; | ||
while (count) { | ||
char *p = memchr(buf, '\n', count); | ||
if (p != buf && (fputs(color, fp) < 0 || | ||
fwrite(buf, p ? p - buf : count, 1, fp) != 1 || | ||
fputs(PERF_COLOR_RESET, fp) < 0)) | ||
return -1; | ||
if (!p) | ||
return 0; | ||
if (fputc('\n', fp) < 0) | ||
return -1; | ||
count -= p + 1 - buf; | ||
buf = p + 1; | ||
} | ||
return 0; | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#ifndef COLOR_H | ||
#define COLOR_H | ||
|
||
/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ | ||
#define COLOR_MAXLEN 24 | ||
|
||
#define PERF_COLOR_NORMAL "" | ||
#define PERF_COLOR_RESET "\033[m" | ||
#define PERF_COLOR_BOLD "\033[1m" | ||
#define PERF_COLOR_RED "\033[31m" | ||
#define PERF_COLOR_GREEN "\033[32m" | ||
#define PERF_COLOR_YELLOW "\033[33m" | ||
#define PERF_COLOR_BLUE "\033[34m" | ||
#define PERF_COLOR_MAGENTA "\033[35m" | ||
#define PERF_COLOR_CYAN "\033[36m" | ||
#define PERF_COLOR_BG_RED "\033[41m" | ||
|
||
/* | ||
* This variable stores the value of color.ui | ||
*/ | ||
extern int perf_use_color_default; | ||
|
||
|
||
/* | ||
* Use this instead of perf_default_config if you need the value of color.ui. | ||
*/ | ||
int perf_color_default_config(const char *var, const char *value, void *cb); | ||
|
||
int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty); | ||
void color_parse(const char *value, const char *var, char *dst); | ||
void color_parse_mem(const char *value, int len, const char *var, char *dst); | ||
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); | ||
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); | ||
int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); | ||
|
||
#endif /* COLOR_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,4 @@ | |
#include "cache.h" | ||
|
||
const char *pager_program; | ||
int pager_use_color = 1; |