diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-06-06 14:33:43 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-06-06 14:33:43 -0400 |
commit | 864709302a80f26fa9da3be5b47304f0b8bae192 (patch) | |
tree | 8c2bab78f141fe43a38914bd3e3aae0a88f958e5 /tools/perf/util/color.c | |
parent | 75b5032212641f6d38ac041416945e70da833b68 (diff) |
perf_counter tools: Move from Documentation/perf_counter/ to tools/perf/
Several people have suggested that 'perf' has become a full-fledged
tool that should be moved out of Documentation/. Move it to the
(new) tools/ directory.
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>
Diffstat (limited to 'tools/perf/util/color.c')
-rw-r--r-- | tools/perf/util/color.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c new file mode 100644 index 00000000000..9a8c20ccc53 --- /dev/null +++ b/tools/perf/util/color.c | |||
@@ -0,0 +1,241 @@ | |||
1 | #include "cache.h" | ||
2 | #include "color.h" | ||
3 | |||
4 | int perf_use_color_default = -1; | ||
5 | |||
6 | static int parse_color(const char *name, int len) | ||
7 | { | ||
8 | static const char * const color_names[] = { | ||
9 | "normal", "black", "red", "green", "yellow", | ||
10 | "blue", "magenta", "cyan", "white" | ||
11 | }; | ||
12 | char *end; | ||
13 | int i; | ||
14 | for (i = 0; i < ARRAY_SIZE(color_names); i++) { | ||
15 | const char *str = color_names[i]; | ||
16 | if (!strncasecmp(name, str, len) && !str[len]) | ||
17 | return i - 1; | ||
18 | } | ||
19 | i = strtol(name, &end, 10); | ||
20 | if (end - name == len && i >= -1 && i <= 255) | ||
21 | return i; | ||
22 | return -2; | ||
23 | } | ||
24 | |||
25 | static int parse_attr(const char *name, int len) | ||
26 | { | ||
27 | static const int attr_values[] = { 1, 2, 4, 5, 7 }; | ||
28 | static const char * const attr_names[] = { | ||
29 | "bold", "dim", "ul", "blink", "reverse" | ||
30 | }; | ||
31 | int i; | ||
32 | for (i = 0; i < ARRAY_SIZE(attr_names); i++) { | ||
33 | const char *str = attr_names[i]; | ||
34 | if (!strncasecmp(name, str, len) && !str[len]) | ||
35 | return attr_values[i]; | ||
36 | } | ||
37 | return -1; | ||
38 | } | ||
39 | |||
40 | void color_parse(const char *value, const char *var, char *dst) | ||
41 | { | ||
42 | color_parse_mem(value, strlen(value), var, dst); | ||
43 | } | ||
44 | |||
45 | void color_parse_mem(const char *value, int value_len, const char *var, | ||
46 | char *dst) | ||
47 | { | ||
48 | const char *ptr = value; | ||
49 | int len = value_len; | ||
50 | int attr = -1; | ||
51 | int fg = -2; | ||
52 | int bg = -2; | ||
53 | |||
54 | if (!strncasecmp(value, "reset", len)) { | ||
55 | strcpy(dst, PERF_COLOR_RESET); | ||
56 | return; | ||
57 | } | ||
58 | |||
59 | /* [fg [bg]] [attr] */ | ||
60 | while (len > 0) { | ||
61 | const char *word = ptr; | ||
62 | int val, wordlen = 0; | ||
63 | |||
64 | while (len > 0 && !isspace(word[wordlen])) { | ||
65 | wordlen++; | ||
66 | len--; | ||
67 | } | ||
68 | |||
69 | ptr = word + wordlen; | ||
70 | while (len > 0 && isspace(*ptr)) { | ||
71 | ptr++; | ||
72 | len--; | ||
73 | } | ||
74 | |||
75 | val = parse_color(word, wordlen); | ||
76 | if (val >= -1) { | ||
77 | if (fg == -2) { | ||
78 | fg = val; | ||
79 | continue; | ||
80 | } | ||
81 | if (bg == -2) { | ||
82 | bg = val; | ||
83 | continue; | ||
84 | } | ||
85 | goto bad; | ||
86 | } | ||
87 | val = parse_attr(word, wordlen); | ||
88 | if (val < 0 || attr != -1) | ||
89 | goto bad; | ||
90 | attr = val; | ||
91 | } | ||
92 | |||
93 | if (attr >= 0 || fg >= 0 || bg >= 0) { | ||
94 | int sep = 0; | ||
95 | |||
96 | *dst++ = '\033'; | ||
97 | *dst++ = '['; | ||
98 | if (attr >= 0) { | ||
99 | *dst++ = '0' + attr; | ||
100 | sep++; | ||
101 | } | ||
102 | if (fg >= 0) { | ||
103 | if (sep++) | ||
104 | *dst++ = ';'; | ||
105 | if (fg < 8) { | ||
106 | *dst++ = '3'; | ||
107 | *dst++ = '0' + fg; | ||
108 | } else { | ||
109 | dst += sprintf(dst, "38;5;%d", fg); | ||
110 | } | ||
111 | } | ||
112 | if (bg >= 0) { | ||
113 | if (sep++) | ||
114 | *dst++ = ';'; | ||
115 | if (bg < 8) { | ||
116 | *dst++ = '4'; | ||
117 | *dst++ = '0' + bg; | ||
118 | } else { | ||
119 | dst += sprintf(dst, "48;5;%d", bg); | ||
120 | } | ||
121 | } | ||
122 | *dst++ = 'm'; | ||
123 | } | ||
124 | *dst = 0; | ||
125 | return; | ||
126 | bad: | ||
127 | die("bad color value '%.*s' for variable '%s'", value_len, value, var); | ||
128 | } | ||
129 | |||
130 | int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty) | ||
131 | { | ||
132 | if (value) { | ||
133 | if (!strcasecmp(value, "never")) | ||
134 | return 0; | ||
135 | if (!strcasecmp(value, "always")) | ||
136 | return 1; | ||
137 | if (!strcasecmp(value, "auto")) | ||
138 | goto auto_color; | ||
139 | } | ||
140 | |||
141 | /* Missing or explicit false to turn off colorization */ | ||
142 | if (!perf_config_bool(var, value)) | ||
143 | return 0; | ||
144 | |||
145 | /* any normal truth value defaults to 'auto' */ | ||
146 | auto_color: | ||
147 | if (stdout_is_tty < 0) | ||
148 | stdout_is_tty = isatty(1); | ||
149 | if (stdout_is_tty || (pager_in_use() && pager_use_color)) { | ||
150 | char *term = getenv("TERM"); | ||
151 | if (term && strcmp(term, "dumb")) | ||
152 | return 1; | ||
153 | } | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | int perf_color_default_config(const char *var, const char *value, void *cb) | ||
158 | { | ||
159 | if (!strcmp(var, "color.ui")) { | ||
160 | perf_use_color_default = perf_config_colorbool(var, value, -1); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | return perf_default_config(var, value, cb); | ||
165 | } | ||
166 | |||
167 | static int color_vfprintf(FILE *fp, const char *color, const char *fmt, | ||
168 | va_list args, const char *trail) | ||
169 | { | ||
170 | int r = 0; | ||
171 | |||
172 | /* | ||
173 | * Auto-detect: | ||
174 | */ | ||
175 | if (perf_use_color_default < 0) { | ||
176 | if (isatty(1) || pager_in_use()) | ||
177 | perf_use_color_default = 1; | ||
178 | else | ||
179 | perf_use_color_default = 0; | ||
180 | } | ||
181 | |||
182 | if (perf_use_color_default && *color) | ||
183 | r += fprintf(fp, "%s", color); | ||
184 | r += vfprintf(fp, fmt, args); | ||
185 | if (perf_use_color_default && *color) | ||
186 | r += fprintf(fp, "%s", PERF_COLOR_RESET); | ||
187 | if (trail) | ||
188 | r += fprintf(fp, "%s", trail); | ||
189 | return r; | ||
190 | } | ||
191 | |||
192 | |||
193 | |||
194 | int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) | ||
195 | { | ||
196 | va_list args; | ||
197 | int r; | ||
198 | |||
199 | va_start(args, fmt); | ||
200 | r = color_vfprintf(fp, color, fmt, args, NULL); | ||
201 | va_end(args); | ||
202 | return r; | ||
203 | } | ||
204 | |||
205 | int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...) | ||
206 | { | ||
207 | va_list args; | ||
208 | int r; | ||
209 | va_start(args, fmt); | ||
210 | r = color_vfprintf(fp, color, fmt, args, "\n"); | ||
211 | va_end(args); | ||
212 | return r; | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * This function splits the buffer by newlines and colors the lines individually. | ||
217 | * | ||
218 | * Returns 0 on success. | ||
219 | */ | ||
220 | int color_fwrite_lines(FILE *fp, const char *color, | ||
221 | size_t count, const char *buf) | ||
222 | { | ||
223 | if (!*color) | ||
224 | return fwrite(buf, count, 1, fp) != 1; | ||
225 | while (count) { | ||
226 | char *p = memchr(buf, '\n', count); | ||
227 | if (p != buf && (fputs(color, fp) < 0 || | ||
228 | fwrite(buf, p ? p - buf : count, 1, fp) != 1 || | ||
229 | fputs(PERF_COLOR_RESET, fp) < 0)) | ||
230 | return -1; | ||
231 | if (!p) | ||
232 | return 0; | ||
233 | if (fputc('\n', fp) < 0) | ||
234 | return -1; | ||
235 | count -= p + 1 - buf; | ||
236 | buf = p + 1; | ||
237 | } | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | |||