On Fri, Apr 05, 2013 at 11:51:43PM +0200, Manuel López-Ibáñez wrote: > In this patch the default is "never", because for some reason "auto" > triggers colorization during regression testing. I have not found a
That reason is obvious, dejagnu (expect?) creates pseudo terminals, so isatty is true, we'd need to just use -fno-diagnostics-color by default for the testsuite (IMHO not a big deal). Anyway, I've kept the default as never for now, but am sending my review comments in form of a new diff, which fixes formatting, avoids memory leaks and changes it to introduce more color names (for caret, locus, quoted text), change default of note color (for some color compatibility with clang, bold green is there used for caret lines, for notes they use bold black apparently, but that doesn't work too well on white-on-black terminals). Right now the patch is unfinished, because there is no support for the new %[locus]%s:%d:%d%[] style diagnostics strings (where %[locus] and %[] stand for switching to "locus" color and resetting color %back) in the -Wformat code (and gettext). I'm wondering if instead of the %[colorname] and %[] it wouldn't be better to just have some %r or whatever letter isn't taken yet which would consume a const char * colorname from %va_arg, and some other letter with no argument that would do color reset. Ideas for best unused letters for that? Perhaps then -Wformat support for it would be easier. I.e. instead of: pp_printf ("%[locus]%s:%d:%d[]", loc.file, loc.line, loc.column); one would write: pp_printf ("%r%s:%d:%d%R", "locus", loc.file, loc.line, loc.column); Jakub
--- gcc/opts.c.jj 2013-03-05 07:00:46.847494476 +0100 +++ gcc/opts.c 2013-04-08 14:29:20.592412422 +0200 @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. #include "flags.h" #include "params.h" #include "diagnostic.h" +#include "diagnostic-color.h" #include "opts-diagnostic.h" #include "insn-attr-common.h" #include "common/common-target.h" @@ -1497,6 +1498,11 @@ common_handle_option (struct gcc_options dc->show_caret = value; break; + case OPT_fdiagnostics_color_: + pp_show_color (dc->printer) + = colorize_init ((diagnostic_color_rule_t) value); + break; + case OPT_fdiagnostics_show_option: dc->show_option_requested = value; break; --- gcc/Makefile.in.jj 2013-04-04 15:03:29.285380160 +0200 +++ gcc/Makefile.in 2013-04-08 14:44:47.076155748 +0200 @@ -1465,7 +1465,7 @@ OBJS = \ # Objects in libcommon.a, potentially used by all host binaries and with # no target dependencies. -OBJS-libcommon = diagnostic.o pretty-print.o intl.o input.o version.o +OBJS-libcommon = diagnostic.o diagnostic-color.o pretty-print.o intl.o input.o version.o # Objects in libcommon-target.a, used by drivers and by the core # compiler and containing target-dependent code. @@ -2668,11 +2668,12 @@ fold-const.o : fold-const.c $(CONFIG_H) $(GIMPLE_H) realmpfr.h $(TREE_FLOW_H) diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ version.h $(DEMANGLE_H) $(INPUT_H) intl.h $(BACKTRACE_H) $(DIAGNOSTIC_H) \ - diagnostic.def + diagnostic.def diagnostic-color.h +diagnostic-color.o : diagnostic-color.c $(CONFIG_H) $(SYSTEM_H) diagnostic-color.h opts.o : opts.c $(OPTS_H) $(OPTIONS_H) $(DIAGNOSTIC_CORE_H) $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(DUMPFILE_H) $(TM_H) \ $(DIAGNOSTIC_H) insn-attr-common.h intl.h $(COMMON_TARGET_H) \ - $(FLAGS_H) $(PARAMS_H) opts-diagnostic.h + $(FLAGS_H) $(PARAMS_H) opts-diagnostic.h diagnostic-color.h opts-global.o : opts-global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(DIAGNOSTIC_H) $(OPTS_H) $(FLAGS_H) $(GGC_H) $(TREE_H) langhooks.h \ $(TM_H) $(RTL_H) $(DBGCNT_H) debug.h $(LTO_STREAMER_H) output.h \ @@ -3434,7 +3435,8 @@ params.o : params.c $(CONFIG_H) $(SYSTEM $(PARAMS_H) $(DIAGNOSTIC_CORE_H) pointer-set.o: pointer-set.c pointer-set.h $(CONFIG_H) $(SYSTEM_H) hooks.o: hooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(HOOKS_H) -pretty-print.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h $(PRETTY_PRINT_H) +pretty-print.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h $(PRETTY_PRINT_H) \ + diagnostic-color.h errors.o : errors.c $(CONFIG_H) $(SYSTEM_H) errors.h dbgcnt.o: dbgcnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \ $(DIAGNOSTIC_CORE_H) $(DBGCNT_H) --- gcc/common.opt.jj 2013-04-04 15:03:29.285380160 +0200 +++ gcc/common.opt 2013-04-08 11:32:33.438159412 +0200 @@ -1028,6 +1028,30 @@ fdiagnostics-show-caret Common Var(flag_diagnostics_show_caret) Init(1) Show the source line with a caret indicating the column +fdiagnostics-color +Common Alias(fdiagnostics-color=,always,never) +; + +fdiagnostics-color= +Common Joined RejectNegative Enum(diagnostic_color_rule) +-fdiagnostics-color=[never|always|auto] Colorize diagnostics + +; Required for these enum values. +SourceInclude +diagnostic-color.h + +Enum +Name(diagnostic_color_rule) Type(int) + +EnumValue +Enum(diagnostic_color_rule) String(never) Value(DIAGNOSTICS_COLOR_NO) + +EnumValue +Enum(diagnostic_color_rule) String(always) Value(DIAGNOSTICS_COLOR_YES) + +EnumValue +Enum(diagnostic_color_rule) String(auto) Value(DIAGNOSTICS_COLOR_AUTO) + fdiagnostics-show-option Common Var(flag_diagnostics_show_option) Init(1) Amend appropriate diagnostic messages with the command line option that controls them --- gcc/dwarf2out.c.jj 2013-04-02 20:24:35.672921339 +0200 +++ gcc/dwarf2out.c 2013-04-08 10:42:23.411243819 +0200 @@ -18828,6 +18828,7 @@ gen_producer_string (void) case OPT_fdiagnostics_show_location_: case OPT_fdiagnostics_show_option: case OPT_fdiagnostics_show_caret: + case OPT_fdiagnostics_color_: case OPT_fverbose_asm: case OPT____: case OPT__sysroot_: --- gcc/cp/error.c.jj 2013-04-02 20:24:34.000000000 +0200 +++ gcc/cp/error.c 2013-04-08 14:48:29.333716054 +0200 @@ -3022,12 +3022,12 @@ cp_print_error_function (diagnostic_cont { if (context->show_column && s.column != 0) pp_printf (context->printer, - _(" inlined from %qs at %s:%d:%d"), + _(" inlined from %qs at %[locus]%s:%d:%d%[]"), cxx_printable_name_translate (fndecl, 2), s.file, s.line, s.column); else pp_printf (context->printer, - _(" inlined from %qs at %s:%d"), + _(" inlined from %qs at %[locus]%s:%d%[]"), cxx_printable_name_translate (fndecl, 2), s.file, s.line); @@ -3111,10 +3111,10 @@ print_instantiation_partial_context_line xloc = expand_location (loc); if (context->show_column) - pp_verbatim (context->printer, _("%s:%d:%d: "), + pp_verbatim (context->printer, _("%[locus]%s:%d:%d:%[] "), xloc.file, xloc.line, xloc.column); else - pp_verbatim (context->printer, _("%s:%d: "), + pp_verbatim (context->printer, _("%[locus]%s:%d:%[] "), xloc.file, xloc.line); if (t != NULL) @@ -3189,12 +3189,12 @@ print_instantiation_partial_context (dia xloc = expand_location (loc); if (context->show_column) pp_verbatim (context->printer, - _("%s:%d:%d: [ skipping %d instantiation contexts, " + _("%[locus]%s:%d:%d:%[] [ skipping %d instantiation contexts, " "use -ftemplate-backtrace-limit=0 to disable ]\n"), xloc.file, xloc.line, xloc.column, skip); else pp_verbatim (context->printer, - _("%s:%d: [ skipping %d instantiation contexts, " + _("%[locus]%s:%d:%[] [ skipping %d instantiation contexts, " "use -ftemplate-backtrace-limit=0 to disable ]\n"), xloc.file, xloc.line, skip); @@ -3258,11 +3258,11 @@ maybe_print_constexpr_context (diagnosti const char *s = expr_as_string (t, 0); if (context->show_column) pp_verbatim (context->printer, - _("%s:%d:%d: in constexpr expansion of %qs"), + _("%[locus]%s:%d:%d:%[] in constexpr expansion of %qs"), xloc.file, xloc.line, xloc.column, s); else pp_verbatim (context->printer, - _("%s:%d: in constexpr expansion of %qs"), + _("%[locus]%s:%d:%[] in constexpr expansion of %qs"), xloc.file, xloc.line, s); pp_base_newline (context->printer); } --- gcc/langhooks.c.jj 2013-01-11 09:02:55.000000000 +0100 +++ gcc/langhooks.c 2013-04-08 14:46:08.577660803 +0200 @@ -452,12 +452,12 @@ lhd_print_error_function (diagnostic_con { if (context->show_column) pp_printf (context->printer, - _(" inlined from %qs at %s:%d:%d"), + _(" inlined from %qs at %[locus]%s:%d:%d%[]"), identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2)), s.file, s.line, s.column); else pp_printf (context->printer, - _(" inlined from %qs at %s:%d"), + _(" inlined from %qs at %[locus]%s:%d%[]"), identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2)), s.file, s.line); --- gcc/diagnostic.def.jj 2013-03-21 18:36:03.272497597 +0100 +++ gcc/diagnostic.def 2013-04-08 13:08:11.414727209 +0200 @@ -22,26 +22,26 @@ along with GCC; see the file COPYING3. kind specified. I.e. they're uninitialized. Within the diagnostic machinery, this kind also means "don't change the existing kind", meaning "no change is specified". */ -DEFINE_DIAGNOSTIC_KIND (DK_UNSPECIFIED, "") +DEFINE_DIAGNOSTIC_KIND (DK_UNSPECIFIED, "", NULL) /* If a diagnostic is set to DK_IGNORED, it won't get reported at all. This is used by the diagnostic machinery when it wants to disable a diagnostic without disabling the option which causes it. */ -DEFINE_DIAGNOSTIC_KIND (DK_IGNORED, "") +DEFINE_DIAGNOSTIC_KIND (DK_IGNORED, "", NULL) /* The remainder are real diagnostic types. */ -DEFINE_DIAGNOSTIC_KIND (DK_FATAL, "fatal error: ") -DEFINE_DIAGNOSTIC_KIND (DK_ICE, "internal compiler error: ") -DEFINE_DIAGNOSTIC_KIND (DK_ERROR, "error: ") -DEFINE_DIAGNOSTIC_KIND (DK_SORRY, "sorry, unimplemented: ") -DEFINE_DIAGNOSTIC_KIND (DK_WARNING, "warning: ") -DEFINE_DIAGNOSTIC_KIND (DK_ANACHRONISM, "anachronism: ") -DEFINE_DIAGNOSTIC_KIND (DK_NOTE, "note: ") -DEFINE_DIAGNOSTIC_KIND (DK_DEBUG, "debug: ") +DEFINE_DIAGNOSTIC_KIND (DK_FATAL, "fatal error: ", "error") +DEFINE_DIAGNOSTIC_KIND (DK_ICE, "internal compiler error: ", "error") +DEFINE_DIAGNOSTIC_KIND (DK_ERROR, "error: ", "error") +DEFINE_DIAGNOSTIC_KIND (DK_SORRY, "sorry, unimplemented: ", "error") +DEFINE_DIAGNOSTIC_KIND (DK_WARNING, "warning: ", "warning") +DEFINE_DIAGNOSTIC_KIND (DK_ANACHRONISM, "anachronism: ", "warning") +DEFINE_DIAGNOSTIC_KIND (DK_NOTE, "note: ", "note") +DEFINE_DIAGNOSTIC_KIND (DK_DEBUG, "debug: ", "note") /* These two would be re-classified as DK_WARNING or DK_ERROR, so the prefix does not matter. */ -DEFINE_DIAGNOSTIC_KIND (DK_PEDWARN, "pedwarn: ") -DEFINE_DIAGNOSTIC_KIND (DK_PERMERROR, "permerror: ") +DEFINE_DIAGNOSTIC_KIND (DK_PEDWARN, "pedwarn: ", NULL) +DEFINE_DIAGNOSTIC_KIND (DK_PERMERROR, "permerror: ", NULL) /* This one is just for counting DK_WARNING promoted to DK_ERROR due to -Werror and -Werror=warning. */ -DEFINE_DIAGNOSTIC_KIND (DK_WERROR, "error: ") +DEFINE_DIAGNOSTIC_KIND (DK_WERROR, "error: ", NULL) --- gcc/diagnostic-color.c.jj 2013-04-08 10:42:23.415243795 +0200 +++ gcc/diagnostic-color.c 2013-04-08 14:43:57.961435670 +0200 @@ -0,0 +1,307 @@ +/* Output colorization. + Copyright 2011-2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include "config.h" +#include "system.h" +#include "diagnostic-color.h" + +/* Select Graphic Rendition (SGR, "\33[...m") strings. */ +/* Also Erase in Line (EL) to Right ("\33[K") by default. */ +/* Why have EL to Right after SGR? + -- The behavior of line-wrapping when at the bottom of the + terminal screen and at the end of the current line is often + such that a new line is introduced, entirely cleared with + the current background color which may be different from the + default one (see the boolean back_color_erase terminfo(5) + capability), thus scrolling the display by one line. + The end of this new line will stay in this background color + even after reverting to the default background color with + "\33[m', unless it is explicitly cleared again with "\33[K" + (which is the behavior the user would instinctively expect + from the whole thing). There may be some unavoidable + background-color flicker at the end of this new line because + of this (when timing with the monitor's redraw is just right). + -- The behavior of HT (tab, "\t") is usually the same as that of + Cursor Forward Tabulation (CHT) with a default parameter + of 1 ("\33[I"), i.e., it performs pure movement to the next + tab stop, without any clearing of either content or screen + attributes (including background color); try + printf 'asdfqwerzxcv\rASDF\tZXCV\n' + in a bash(1) shell to demonstrate this. This is not what the + user would instinctively expect of HT (but is ok for CHT). + The instinctive behavior would include clearing the terminal + cells that are skipped over by HT with blank cells in the + current screen attributes, including background color; + the boolean dest_tabs_magic_smso terminfo(5) capability + indicates this saner behavior for HT, but only some rare + terminals have it (although it also indicates a special + glitch with standout mode in the Teleray terminal for which + it was initially introduced). The remedy is to add "\33K" + after each SGR sequence, be it START (to fix the behavior + of any HT after that before another SGR) or END (to fix the + behavior of an HT in default background color that would + follow a line-wrapping at the bottom of the screen in another + background color, and to complement doing it after START). + Piping GCC's output through a pager such as less(1) avoids + any HT problems since the pager performs tab expansion. + + Generic disadvantages of this remedy are: + -- Some very rare terminals might support SGR but not EL (nobody + will use "gcc -fdiagnostics-color" on a terminal that does not + support SGR in the first place). + -- Having these extra control sequences might somewhat complicate + the task of any program trying to parse "gcc -fdiagnostics-color" + output in order to extract structuring information from it. + A specific disadvantage to doing it after SGR START is: + -- Even more possible background color flicker (when timing + with the monitor's redraw is just right), even when not at the + bottom of the screen. + There are no additional disadvantages specific to doing it after + SGR END. + + It would be impractical for GCC to become a full-fledged + terminal program linked against ncurses or the like, so it will + not detect terminfo(5) capabilities. */ +#define COLOR_SEPARATOR ";" +#define COLOR_NONE "00" +#define COLOR_BOLD "01" +#define COLOR_UNDERSCORE "04" +#define COLOR_BLINK "05" +#define COLOR_REVERSE "07" +#define COLOR_FG_BLACK "30" +#define COLOR_FG_RED "31" +#define COLOR_FG_GREEN "32" +#define COLOR_FG_YELLOW "33" +#define COLOR_FG_BLUE "34" +#define COLOR_FG_MAGENTA "35" +#define COLOR_FG_CYAN "36" +#define COLOR_FG_WHITE "37" +#define COLOR_BG_BLACK "40" +#define COLOR_BG_RED "41" +#define COLOR_BG_GREEN "42" +#define COLOR_BG_YELLOW "43" +#define COLOR_BG_BLUE "44" +#define COLOR_BG_MAGENTA "45" +#define COLOR_BG_CYAN "46" +#define COLOR_BG_WHITE "47" +#define SGR_START "\33[" +#define SGR_END "m\33[K" +#define SGR_SEQ(str) SGR_START str SGR_END +#define SGR_RESET SGR_SEQ("") + + +/* The context and logic for choosing default --color screen attributes + (foreground and background colors, etc.) are the following. + -- There are eight basic colors available, each with its own + nominal luminosity to the human eye and foreground/background + codes (black [0 %, 30/40], blue [11 %, 34/44], red [30 %, 31/41], + magenta [41 %, 35/45], green [59 %, 32/42], cyan [70 %, 36/46], + yellow [89 %, 33/43], and white [100 %, 37/47]). + -- Sometimes, white as a background is actually implemented using + a shade of light gray, so that a foreground white can be visible + on top of it (but most often not). + -- Sometimes, black as a foreground is actually implemented using + a shade of dark gray, so that it can be visible on top of a + background black (but most often not). + -- Sometimes, more colors are available, as extensions. + -- Other attributes can be selected/deselected (bold [1/22], + underline [4/24], standout/inverse [7/27], blink [5/25], and + invisible/hidden [8/28]). They are sometimes implemented by + using colors instead of what their names imply; e.g., bold is + often achieved by using brighter colors. In practice, only bold + is really available to us, underline sometimes being mapped by + the terminal to some strange color choice, and standout best + being left for use by downstream programs such as less(1). + -- We cannot assume that any of the extensions or special features + are available for the purpose of choosing defaults for everyone. + -- The most prevalent default terminal backgrounds are pure black + and pure white, and are not necessarily the same shades of + those as if they were selected explicitly with SGR sequences. + Some terminals use dark or light pictures as default background, + but those are covered over by an explicit selection of background + color with an SGR sequence; their users will appreciate their + background pictures not be covered like this, if possible. + -- Some uses of colors attributes is to make some output items + more understated (e.g., context lines); this cannot be achieved + by changing the background color. + -- For these reasons, the GCC color defaults should strive not + to change the background color from its default, unless it's + for a short item that should be highlighted, not understated. + -- The GCC foreground color defaults (without an explicitly set + background) should provide enough contrast to be readable on any + terminal with either a black (dark) or white (light) background. + This only leaves red, magenta, green, and cyan (and their bold + counterparts) and possibly bold blue. */ +/* Default colors. The user can overwrite them using environment + variable GCC_COLORS. */ +struct color_cap +{ + const char *name; + const char *val; + unsigned char name_len; + bool free_val; +}; + +/* For GCC_COLORS. */ +static struct color_cap color_dict[] = +{ + { "error", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED), 5, false }, + { "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA), + 7, false }, + { "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN), 4, false }, + { "caret", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN), 5, false }, + { "locus", SGR_SEQ (COLOR_BOLD), 5, false }, + { "quote", SGR_SEQ (COLOR_BOLD), 5, false }, + { NULL, NULL, 0, false } +}; + +const char * +colorize_start (bool show_color, const char *name, size_t name_len) +{ + struct color_cap const *cap; + + if (!show_color) + return ""; + + for (cap = color_dict; cap->name; cap++) + if (cap->name_len == name_len + && memcmp (cap->name, name, name_len) == 0) + break; + if (cap->name == NULL) + return ""; + + return cap->val; +} + +const char * +colorize_stop (bool show_color) +{ + return show_color ? SGR_RESET : ""; +} + +/* Parse GCC_COLORS. The default would look like: + GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' + No character escaping is needed or supported. */ +static bool +parse_gcc_colors (void) +{ + const char *p, *q, *name, *val; + char *b; + size_t name_len = 0, val_len = 0; + + p = getenv ("GCC_COLORS"); /* Plural! */ + if (p == NULL) + return true; + if (*p == '\0') + return false; + + name = q = p; + val = NULL; + /* From now on, be well-formed or you're gone. */ + for (;;) + if (*q == ':' || *q == '\0') + { + struct color_cap *cap; + + if (val) + val_len = q - val; + else + name_len = q - name; + /* Empty name without val (empty cap) + won't match and will be ignored. */ + for (cap = color_dict; cap->name; cap++) + if (cap->name_len == name_len + && memcmp (cap->name, name, name_len) == 0) + break; + /* If name unknown, go on for forward compatibility. */ + if (cap->val && val) + { + if (cap->free_val) + free (CONST_CAST (char *, cap->val)); + b = XNEWVEC (char, val_len + sizeof (SGR_SEQ (""))); + memcpy (b, SGR_START, strlen (SGR_START)); + memcpy (b + strlen (SGR_START), val, val_len); + memcpy (b + strlen (SGR_START) + val_len, SGR_END, + sizeof (SGR_END)); + cap->val = (const char *) b; + cap->free_val = true; + } + if (*q == '\0') + return true; + name = ++q; + val = NULL; + } + else if (*q == '=') + { + if (q == name || val) + return true; + + name_len = q - name; + val = ++q; /* Can be the empty string. */ + } + else if (val == NULL) + q++; /* Accumulate name. */ + else if (*q == ';' || (*q >= '0' && *q <= '9')) + q++; /* Accumulate val. Protect the terminal from being sent + garbage. */ + else + return true; +} + +#if defined(_WIN32) +static bool +should_colorize (void) +{ + return false; +} + +bool +colorize_init (void) +{ + return false; +} +#else + +/* Return true if we should use color when in auto mode, false otherwise. */ +static bool +should_colorize (void) +{ + char const *t = getenv ("TERM"); + return t && strcmp (t, "dumb") != 0 && isatty (STDERR_FILENO); +} + + +bool +colorize_init (diagnostic_color_rule_t rule) +{ + switch (rule) + { + case DIAGNOSTICS_COLOR_NO: + return false; + case DIAGNOSTICS_COLOR_YES: + return parse_gcc_colors (); + case DIAGNOSTICS_COLOR_AUTO: + if (should_colorize ()) + return parse_gcc_colors (); + else + return false; + default: + gcc_unreachable (); + } +} +#endif --- gcc/diagnostic-color.h.jj 2013-04-08 10:42:23.415243795 +0200 +++ gcc/diagnostic-color.h 2013-04-08 12:58:54.196865523 +0200 @@ -0,0 +1,66 @@ +/* Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Manuel Lopez-Ibanez <m...@gcc.gnu.org> + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Based on code from: */ +/* grep.c - main driver file for grep. + Copyright (C) 1992, 1997-2002, 2004-2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. + + Written July 1992 by Mike Haertel. */ + +#ifndef GCC_DIAGNOSTIC_COLOR_H +#define GCC_DIAGNOSTIC_COLOR_H + +/* How often diagnostics are prefixed by their locations: + o DIAGNOSTICS_SHOW_PREFIX_NEVER: never - not yet supported; + o DIAGNOSTICS_SHOW_PREFIX_ONCE: emit only once; + o DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE: emit each time a physical + line is started. */ +typedef enum +{ + DIAGNOSTICS_COLOR_NO = 0, + DIAGNOSTICS_COLOR_YES = 1, + DIAGNOSTICS_COLOR_AUTO = 2 +} diagnostic_color_rule_t; + +const char *colorize_start (bool, const char *, size_t); +const char *colorize_stop (bool); +bool colorize_init (diagnostic_color_rule_t); + +inline const char * +colorize_start (bool show_color, const char *name) +{ + return colorize_start (show_color, name, strlen (name)); +} + +#endif /* ! GCC_DIAGNOSTIC_COLOR_H */ --- gcc/diagnostic-core.h.jj 2013-01-11 09:02:35.720648821 +0100 +++ gcc/diagnostic-core.h 2013-04-08 10:42:23.407243842 +0200 @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3. /* Constants used to discriminate diagnostics. */ typedef enum { -#define DEFINE_DIAGNOSTIC_KIND(K, msgid) K, +#define DEFINE_DIAGNOSTIC_KIND(K, msgid, C) K, #include "diagnostic.def" #undef DEFINE_DIAGNOSTIC_KIND DK_LAST_DIAGNOSTIC_KIND, --- gcc/doc/invoke.texi.jj 2013-04-08 10:15:43.868748794 +0200 +++ gcc/doc/invoke.texi 2013-04-08 15:07:31.049803734 +0200 @@ -226,6 +226,7 @@ Objective-C and Objective-C++ Dialects}. @xref{Language Independent Options,,Options to Control Diagnostic Messages Formatting}. @gccoptlist{-fmessage-length=@var{n} @gol -fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]} @gol +-fdiagnostics-color=@r{[}auto@r{|}never@r{|}always@r{]} @gol -fno-diagnostics-show-option -fno-diagnostics-show-caret} @item Warning Options @@ -2956,6 +2957,76 @@ messages reporter to emit the same sourc prefix) for physical lines that result from the process of breaking a message which is too long to fit on a single line. +@item -fdiagnostics-color[=@var{WHEN}] +@itemx -fno-diagnostics-color +@opindex fdiagnostics-color +@cindex highlight, color, colour +@vindex GCC_COLORS @r{environment variable} +Use color in diagnostics. @var{WHEN} is @samp{never}, @samp{always}, +or @samp{auto}. The default is @samp{auto}, which means to use color +only when the stdandard error is a terminal. The forms +@option{-fdiagnostics-color} and @option{-fno-diagnostics-color} are +aliases for @option{-fdiagnostics-color=always} and +@option{-fdiagnostics-color=never}, respectively. + +The colors are defined by the environment variable @env{GCC_COLORS}. +Its value is a colon-separated list of capabilities and Select Graphic +Rendition (SGR) substrings. SGR commands are interpreted by the +terminal or terminal emulator. (See the section in the documentation +of your text terminal for permitted values and their meanings as +character attributes.) These substring values are integers in decimal +representation and can be concatenated with semicolons. +Common values to concatenate include +@samp{1} for bold, +@samp{4} for underline, +@samp{5} for blink, +@samp{7} for inverse, +@samp{39} for default foreground color, +@samp{30} to @samp{37} for foreground colors, +@samp{90} to @samp{97} for 16-color mode foreground colors, +@samp{38;5;0} to @samp{38;5;255} +for 88-color and 256-color modes foreground colors, +@samp{49} for default background color, +@samp{40} to @samp{47} for background colors, +@samp{100} to @samp{107} for 16-color mode background colors, +and @samp{48;5;0} to @samp{48;5;255} +for 88-color and 256-color modes background colors. + +The default @env{GCC_COLORS} is +@samp{error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01} +where @samp{01;31} is bold red, @samp{01;35} is bold magenta, +@samp{01;36} is bold cyan, @samp{01;32} is bold green and +@samp{01} is bold. Setting @env{GCC_COLORS} to the empty +string disables colors. +Supported capabilities are as follows. + +@table @code +@item error= +@vindex error GREP_COLORS @r{capability} +SGR substring for error: markers. + +@item warning= +@vindex warning GREP_COLORS @r{capability} +SGR substring for warning: markers. + +@item note= +@vindex note GREP_COLORS @r{capability} +SGR substring for note: markers. + +@item caret= +@vindex caret GREP_COLORS @r{capability} +SGR substring for caret line. + +@item locus= +@vindex locus GREP_COLORS @r{capability} +SGR substring for location information, @samp{file:line} or +@samp{file:line:column} etc. + +@item quote= +@vindex quote GREP_COLORS @r{capability} +SGR substring for information printed within quotes. +@end table + @item -fno-diagnostics-show-option @opindex fno-diagnostics-show-option @opindex fdiagnostics-show-option --- gcc/pretty-print.h.jj 2013-01-11 09:02:37.000000000 +0100 +++ gcc/pretty-print.h 2013-04-08 14:29:01.583520856 +0200 @@ -151,6 +151,9 @@ typedef bool (*printer_fn) (pretty_print output. */ #define pp_translate_identifiers(PP) pp_base (PP)->translate_identifiers +/* True if colors should be shown. */ +#define pp_show_color(PP) pp_base (PP)->show_color + /* The data structure that contains the bare minimum required to do proper pretty-printing. Clients may derived from this structure and add additional fields they need. */ @@ -194,6 +197,9 @@ struct pretty_print_info /* Nonzero means identifiers are translated to the locale character set on output. */ bool translate_identifiers; + + /* Nonzero means that text should be colorized. */ + bool show_color; }; #define pp_set_line_maximum_length(PP, L) \ --- gcc/diagnostic.c.jj 2013-03-21 18:36:03.286497533 +0100 +++ gcc/diagnostic.c 2013-04-08 14:50:14.150075625 +0200 @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. #include "intl.h" #include "backtrace.h" #include "diagnostic.h" +#include "diagnostic-color.h" #define pedantic_warning_kind(DC) \ ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING) @@ -53,7 +54,6 @@ const char *progname; /* A diagnostic_context surrogate for stderr. */ static diagnostic_context global_diagnostic_context; diagnostic_context *global_dc = &global_diagnostic_context; - /* Return a malloc'd string containing MSG formatted a la printf. The caller is responsible for freeing the memory. */ @@ -210,12 +210,31 @@ diagnostic_build_prefix (diagnostic_cont const diagnostic_info *diagnostic) { static const char *const diagnostic_kind_text[] = { -#define DEFINE_DIAGNOSTIC_KIND(K, T) (T), +#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T), #include "diagnostic.def" #undef DEFINE_DIAGNOSTIC_KIND "must-not-happen" }; + static const char *const diagnostic_kind_color[] = { +#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C), +#include "diagnostic.def" +#undef DEFINE_DIAGNOSTIC_KIND + NULL + }; const char *text = _(diagnostic_kind_text[diagnostic->kind]); + const char *text_cs = "", *text_ce = ""; + const char *locus_cs, *locus_ce; + pretty_printer *pp = context->printer; + + if (diagnostic_kind_color[diagnostic->kind]) + { + text_cs = colorize_start (pp_show_color (pp), + diagnostic_kind_color[diagnostic->kind]); + text_ce = colorize_stop (pp_show_color (pp)); + } + locus_cs = colorize_start (pp_show_color (pp), "locus"); + locus_ce = colorize_stop (pp_show_color (pp)); + expanded_location s = expand_location_to_spelling_point (diagnostic->location); if (diagnostic->override_column) s.column = diagnostic->override_column; @@ -223,10 +242,13 @@ diagnostic_build_prefix (diagnostic_cont return (s.file == NULL - ? build_message_string ("%s: %s", progname, text) + ? build_message_string ("%s%s:%s %s%s%s", locus_cs, progname, locus_ce, + text_cs, text, text_ce) : context->show_column - ? build_message_string ("%s:%d:%d: %s", s.file, s.line, s.column, text) - : build_message_string ("%s:%d: %s", s.file, s.line, text)); + ? build_message_string ("%s%s:%d:%d:%s %s%s%s", locus_cs, s.file, s.line, + s.column, locus_ce, text_cs, text, text_ce) + : build_message_string ("%s%s:%d:%s %s%s%s", locus_cs, s.file, s.line, locus_ce, + text_cs, text, text_ce)); } /* If LINE is longer than MAX_WIDTH, and COLUMN is not smaller than @@ -262,7 +284,7 @@ diagnostic_show_locus (diagnostic_contex expanded_location s; int max_width; const char *saved_prefix; - + const char *caret_cs, *caret_ce; if (!context->show_caret || diagnostic->location <= BUILTINS_LOCATION @@ -290,9 +312,13 @@ diagnostic_show_locus (diagnostic_contex line++; } pp_newline (context->printer); + caret_cs = colorize_start (pp_show_color (context->printer), "caret"); + caret_ce = colorize_stop (pp_show_color (context->printer)); + /* pp_printf does not implement %*c. */ - buffer = XALLOCAVEC (char, s.column + 3); - snprintf (buffer, s.column + 3, " %*c", s.column, '^'); + size_t len = s.column + 3 + strlen (caret_cs) + strlen (caret_ce); + buffer = XALLOCAVEC (char, len); + snprintf (buffer, len, "%s %*c%s", caret_cs, s.column, '^', caret_ce); pp_string (context->printer, buffer); pp_set_prefix (context->printer, saved_prefix); } --- gcc/pretty-print.c.jj 2013-01-11 09:02:37.000000000 +0100 +++ gcc/pretty-print.c 2013-04-08 15:05:22.531614546 +0200 @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. #include "coretypes.h" #include "intl.h" #include "pretty-print.h" +#include "diagnostic-color.h" #if HAVE_ICONV #include <iconv.h> @@ -230,6 +231,8 @@ pp_base_indent (pretty_printer *pp) %%: '%'. %<: opening quote. %>: closing quote. + %[colorname]: if pp_show_color(pp), switch to color colorname. + %[]: if pp_show_color(pp), reset color. %': apostrophe (should only be used in untranslated messages; translations should use appropriate punctuation directly). %.*s: a substring the length of which is specified by an argument @@ -300,18 +303,46 @@ pp_base_format (pretty_printer *pp, text continue; case '<': - obstack_grow (&buffer->chunk_obstack, - open_quote, strlen (open_quote)); - p++; - continue; + { + obstack_grow (&buffer->chunk_obstack, + open_quote, strlen (open_quote)); + const char *colorstr + = colorize_start (pp_show_color (pp), "quote"); + obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr)); + p++; + continue; + } case '>': + { + const char *colorstr = colorize_stop (pp_show_color (pp)); + obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr)); + } + /* FALLTHRU */ case '\'': obstack_grow (&buffer->chunk_obstack, close_quote, strlen (close_quote)); p++; continue; + case '[': + { + const char *colorname = ++p, *colorstr; + size_t colorname_len; + while (*p && *p != ']') + p++; + gcc_assert (*p == ']'); + colorname_len = p++ - colorname; + if (colorname_len) + colorstr = colorize_start (pp_show_color (pp), + colorname, colorname_len); + else + colorstr = colorize_stop (pp_show_color (pp)); + obstack_grow (&buffer->chunk_obstack, colorstr, + strlen (colorstr)); + continue; + } + case 'm': { const char *errstr = xstrerror (text->err_no); @@ -466,7 +497,10 @@ pp_base_format (pretty_printer *pp, text gcc_assert (!wide || precision == 0); if (quote) - pp_string (pp, open_quote); + { + pp_string (pp, open_quote); + pp_string (pp, colorize_start (pp_show_color (pp), "quote")); + } switch (*p) { @@ -563,7 +597,10 @@ pp_base_format (pretty_printer *pp, text } if (quote) - pp_string (pp, close_quote); + { + pp_string (pp, colorize_stop (pp_show_color (pp))); + pp_string (pp, close_quote); + } obstack_1grow (&buffer->chunk_obstack, '\0'); *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);