1 /* Output colorization.
2 Copyright (C) 2011-2017 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21 #include "diagnostic-color.h"
27 #include "color-macros.h"
29 /* The context and logic for choosing default --color screen attributes
30 (foreground and background colors, etc.) are the following.
31 -- There are eight basic colors available, each with its own
32 nominal luminosity to the human eye and foreground/background
33 codes (black [0 %, 30/40], blue [11 %, 34/44], red [30 %, 31/41],
34 magenta [41 %, 35/45], green [59 %, 32/42], cyan [70 %, 36/46],
35 yellow [89 %, 33/43], and white [100 %, 37/47]).
36 -- Sometimes, white as a background is actually implemented using
37 a shade of light gray, so that a foreground white can be visible
38 on top of it (but most often not).
39 -- Sometimes, black as a foreground is actually implemented using
40 a shade of dark gray, so that it can be visible on top of a
41 background black (but most often not).
42 -- Sometimes, more colors are available, as extensions.
43 -- Other attributes can be selected/deselected (bold [1/22],
44 underline [4/24], standout/inverse [7/27], blink [5/25], and
45 invisible/hidden [8/28]). They are sometimes implemented by
46 using colors instead of what their names imply; e.g., bold is
47 often achieved by using brighter colors. In practice, only bold
48 is really available to us, underline sometimes being mapped by
49 the terminal to some strange color choice, and standout best
50 being left for use by downstream programs such as less(1).
51 -- We cannot assume that any of the extensions or special features
52 are available for the purpose of choosing defaults for everyone.
53 -- The most prevalent default terminal backgrounds are pure black
54 and pure white, and are not necessarily the same shades of
55 those as if they were selected explicitly with SGR sequences.
56 Some terminals use dark or light pictures as default background,
57 but those are covered over by an explicit selection of background
58 color with an SGR sequence; their users will appreciate their
59 background pictures not be covered like this, if possible.
60 -- Some uses of colors attributes is to make some output items
61 more understated (e.g., context lines); this cannot be achieved
62 by changing the background color.
63 -- For these reasons, the GCC color defaults should strive not
64 to change the background color from its default, unless it's
65 for a short item that should be highlighted, not understated.
66 -- The GCC foreground color defaults (without an explicitly set
67 background) should provide enough contrast to be readable on any
68 terminal with either a black (dark) or white (light) background.
69 This only leaves red, magenta, green, and cyan (and their bold
70 counterparts) and possibly bold blue. */
71 /* Default colors. The user can overwrite them using environment
72 variable GCC_COLORS. */
77 unsigned char name_len
;
82 static struct color_cap color_dict
[] =
84 { "error", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED
), 5, false },
85 { "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA
),
87 { "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN
), 4, false },
88 { "range1", SGR_SEQ (COLOR_FG_GREEN
), 6, false },
89 { "range2", SGR_SEQ (COLOR_FG_BLUE
), 6, false },
90 { "locus", SGR_SEQ (COLOR_BOLD
), 5, false },
91 { "quote", SGR_SEQ (COLOR_BOLD
), 5, false },
92 { "fixit-insert", SGR_SEQ (COLOR_FG_GREEN
), 12, false },
93 { "fixit-delete", SGR_SEQ (COLOR_FG_RED
), 12, false },
94 { "diff-filename", SGR_SEQ (COLOR_BOLD
), 13, false },
95 { "diff-hunk", SGR_SEQ (COLOR_FG_CYAN
), 9, false },
96 { "diff-delete", SGR_SEQ (COLOR_FG_RED
), 11, false },
97 { "diff-insert", SGR_SEQ (COLOR_FG_GREEN
), 11, false },
98 { "type-diff", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN
), 9, false },
99 { NULL
, NULL
, 0, false }
103 colorize_start (bool show_color
, const char *name
, size_t name_len
)
105 struct color_cap
const *cap
;
110 for (cap
= color_dict
; cap
->name
; cap
++)
111 if (cap
->name_len
== name_len
112 && memcmp (cap
->name
, name
, name_len
) == 0)
114 if (cap
->name
== NULL
)
121 colorize_stop (bool show_color
)
123 return show_color
? SGR_RESET
: "";
126 /* Parse GCC_COLORS. The default would look like:
127 GCC_COLORS='error=01;31:warning=01;35:note=01;36:\
128 range1=32:range2=34:locus=01:quote=01:\
129 fixit-insert=32:fixit-delete=31:'\
130 diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\
132 No character escaping is needed or supported. */
134 parse_gcc_colors (void)
136 const char *p
, *q
, *name
, *val
;
138 size_t name_len
= 0, val_len
= 0;
140 p
= getenv ("GCC_COLORS"); /* Plural! */
148 /* From now on, be well-formed or you're gone. */
150 if (*q
== ':' || *q
== '\0')
152 struct color_cap
*cap
;
158 /* Empty name without val (empty cap)
159 won't match and will be ignored. */
160 for (cap
= color_dict
; cap
->name
; cap
++)
161 if (cap
->name_len
== name_len
162 && memcmp (cap
->name
, name
, name_len
) == 0)
164 /* If name unknown, go on for forward compatibility. */
168 free (CONST_CAST (char *, cap
->val
));
169 b
= XNEWVEC (char, val_len
+ sizeof (SGR_SEQ ("")));
170 memcpy (b
, SGR_START
, strlen (SGR_START
));
171 memcpy (b
+ strlen (SGR_START
), val
, val_len
);
172 memcpy (b
+ strlen (SGR_START
) + val_len
, SGR_END
,
174 cap
->val
= (const char *) b
;
175 cap
->free_val
= true;
184 if (q
== name
|| val
)
188 val
= ++q
; /* Can be the empty string. */
190 else if (val
== NULL
)
191 q
++; /* Accumulate name. */
192 else if (*q
== ';' || (*q
>= '0' && *q
<= '9'))
193 q
++; /* Accumulate val. Protect the terminal from being sent
199 /* Return true if we should use color when in auto mode, false otherwise. */
201 should_colorize (void)
204 /* For consistency reasons, one should check the handle returned by
205 _get_osfhandle(_fileno(stderr)) because the function
206 pp_write_text_to_stream() in pretty-print.c calls fputs() on
207 that stream. However, the code below for non-Windows doesn't seem
208 to care about it either... */
212 h
= GetStdHandle (STD_ERROR_HANDLE
);
213 return (h
!= INVALID_HANDLE_VALUE
) && (h
!= NULL
)
214 && GetConsoleMode (h
, &m
);
216 char const *t
= getenv ("TERM");
217 return t
&& strcmp (t
, "dumb") != 0 && isatty (STDERR_FILENO
);
222 colorize_init (diagnostic_color_rule_t rule
)
226 case DIAGNOSTICS_COLOR_NO
:
228 case DIAGNOSTICS_COLOR_YES
:
229 return parse_gcc_colors ();
230 case DIAGNOSTICS_COLOR_AUTO
:
231 if (should_colorize ())
232 return parse_gcc_colors ();