Branch data Line data Source code
1 : : /* Handling of color output.
2 : : Copyright (C) 2011 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2011.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include <argp.h>
35 : : #include <stdlib.h>
36 : : #include <string.h>
37 : : #include "system.h"
38 : : #include "libeu.h"
39 : : #include "color.h"
40 : :
41 : : /* Prototype for option handler. */
42 : : static error_t parse_opt (int key, char *arg, struct argp_state *state);
43 : :
44 : : /* Option values. */
45 : : #define OPT_COLOR 0x100100
46 : :
47 : : /* Definitions of arguments for argp functions. */
48 : : static const struct argp_option options[] =
49 : : {
50 : : { "color", OPT_COLOR, "WHEN", OPTION_ARG_OPTIONAL,
51 : : N_("colorize the output. WHEN defaults to 'always' or can be 'auto' or 'never'"), 0 },
52 : :
53 : : { NULL, 0, NULL, 0, NULL, 0 }
54 : : };
55 : :
56 : : /* Parser data structure. */
57 : : const struct argp color_argp =
58 : : {
59 : : options, parse_opt, NULL, NULL, NULL, NULL, NULL
60 : : };
61 : :
62 : : /* Coloring mode. */
63 : : enum color_enum color_mode;
64 : :
65 : : /* Colors to use for the various components. */
66 : : char *color_address = "";
67 : : char *color_bytes = "";
68 : : char *color_mnemonic = "";
69 : : char *color_operand = NULL;
70 : : char *color_operand1 = "";
71 : : char *color_operand2 = "";
72 : : char *color_operand3 = "";
73 : : char *color_operand4 = "";
74 : : char *color_operand5 = "";
75 : : char *color_label = "";
76 : : char *color_undef = "";
77 : : char *color_undef_tls = "";
78 : : char *color_undef_weak = "";
79 : : char *color_symbol = "";
80 : : char *color_tls = "";
81 : : char *color_weak = "";
82 : :
83 : : const char color_off[] = "\e[0m";
84 : :
85 : :
86 : : /* Handle program arguments. */
87 : : static error_t
88 : 1110 : parse_opt (int key, char *arg,
89 : : struct argp_state *state __attribute__ ((unused)))
90 : : {
91 [ - + ]: 1110 : switch (key)
92 : : {
93 : 0 : case OPT_COLOR:
94 [ # # ]: 0 : if (arg == NULL)
95 : 0 : color_mode = color_always;
96 : : else
97 : : {
98 : : static const struct
99 : : {
100 : : const char str[7];
101 : : enum color_enum mode;
102 : : } values[] =
103 : : {
104 : : { "always", color_always },
105 : : { "yes", color_always },
106 : : { "force", color_always },
107 : : { "never", color_never },
108 : : { "no", color_never },
109 : : { "none", color_never },
110 : : { "auto", color_auto },
111 : : { "tty", color_auto },
112 : : { "if-tty", color_auto }
113 : : };
114 : 0 : const int nvalues = sizeof (values) / sizeof (values[0]);
115 : : int i;
116 [ # # ]: 0 : for (i = 0; i < nvalues; ++i)
117 [ # # ]: 0 : if (strcmp (arg, values[i].str) == 0)
118 : : {
119 : 0 : color_mode = values[i].mode;
120 [ # # ]: 0 : if (color_mode == color_auto)
121 : : color_mode
122 : 0 : = isatty (STDOUT_FILENO) ? color_always : color_never;
123 : 0 : break;
124 : : }
125 [ # # ]: 0 : if (i == nvalues)
126 : : {
127 : 0 : error (0, 0, _("\
128 : : %s: invalid argument '%s' for '--color'\n\
129 : : valid arguments are:\n\
130 : : - 'always', 'yes', 'force'\n\
131 : : - 'never', 'no', 'none'\n\
132 : : - 'auto', 'tty', 'if-tty'\n"),
133 : : program_invocation_short_name, arg);
134 : 0 : argp_help (&color_argp, stderr, ARGP_HELP_SEE,
135 : : (char *) program_invocation_short_name);
136 : 0 : exit (EXIT_FAILURE);
137 : : }
138 : : }
139 : :
140 [ # # ]: 0 : if (color_mode == color_always)
141 : : {
142 : 0 : const char *env = getenv ("ELFUTILS_COLORS");
143 [ # # ]: 0 : if (env != NULL)
144 : : {
145 : : do
146 : : {
147 : 0 : const char *start = env;
148 [ # # # # ]: 0 : while (*env != '=' && *env != '\0')
149 : 0 : ++env;
150 [ # # # # ]: 0 : if (*env == '=' && env != start)
151 : : {
152 : 0 : size_t name_len = env - start;
153 : 0 : const char *val = ++env;
154 : 0 : env = strchrnul (env, ':');
155 [ # # ]: 0 : if (val != env)
156 : : {
157 : : static const struct
158 : : {
159 : : unsigned char len;
160 : : const char name[sizeof (char *) - 1];
161 : : char **varp;
162 : : } known[] =
163 : : {
164 : : #define E(name, var) { sizeof (#name) - 1, #name, &color_##var }
165 : : E (a, address),
166 : : E (b, bytes),
167 : : E (m, mnemonic),
168 : : E (o, operand),
169 : : E (o1, operand1),
170 : : E (o2, operand2),
171 : : E (o3, operand3),
172 : : E (o4, operand4),
173 : : E (o5, operand5),
174 : : E (l, label),
175 : : E (u, undef),
176 : : E (ut, undef_tls),
177 : : E (uw, undef_weak),
178 : : E (sy, symbol),
179 : : E (st, tls),
180 : : E (sw, weak),
181 : : };
182 : 0 : const size_t nknown = (sizeof (known)
183 : : / sizeof (known[0]));
184 : :
185 [ # # ]: 0 : for (size_t i = 0; i < nknown; ++i)
186 [ # # ]: 0 : if (name_len == known[i].len
187 [ # # ]: 0 : && memcmp (start, known[i].name, name_len) == 0)
188 : : {
189 : 0 : *known[i].varp =
190 : 0 : xasprintf ("\e[%.*sm", (int) (env - val), val);
191 : 0 : break;
192 : : }
193 : : }
194 [ # # ]: 0 : if (*env == ':')
195 : 0 : ++env;
196 : : }
197 : : }
198 [ # # ]: 0 : while (*env != '\0');
199 : :
200 [ # # ]: 0 : if (color_operand != NULL)
201 : : {
202 [ # # ]: 0 : if (color_operand1[0] == '\0')
203 : 0 : color_operand1 = color_operand;
204 [ # # ]: 0 : if (color_operand2[0] == '\0')
205 : 0 : color_operand2 = color_operand;
206 [ # # ]: 0 : if (color_operand3[0] == '\0')
207 : 0 : color_operand3 = color_operand;
208 [ # # ]: 0 : if (color_operand4[0] == '\0')
209 : 0 : color_operand4 = color_operand;
210 [ # # ]: 0 : if (color_operand5[0] == '\0')
211 : 0 : color_operand5 = color_operand;
212 : : }
213 : : }
214 : : #if 0
215 : : else
216 : : {
217 : : // XXX Just for testing.
218 : : color_address = xstrdup ("\e[38;5;166;1m");
219 : : color_bytes = xstrdup ("\e[38;5;141m");
220 : : color_mnemonic = xstrdup ("\e[38;5;202;1m");
221 : : color_operand1 = xstrdup ("\e[38;5;220m");
222 : : color_operand2 = xstrdup ("\e[38;5;48m");
223 : : color_operand = xstrdup ("\e[38;5;112m");
224 : : color_label = xstrdup ("\e[38;5;21m");
225 : : }
226 : : #endif
227 : : }
228 : 0 : break;
229 : :
230 : 1110 : default:
231 : 1110 : return ARGP_ERR_UNKNOWN;
232 : : }
233 : 0 : return 0;
234 : : }
|