From: Martin Liska Date: Tue, 31 Oct 2017 11:57:10 +0000 (+0100) Subject: GCOV: introduce usage of terminal colors. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=28f4a4a85f3b95f7ccf7585eaa5cbd50cbe1677d;p=gcc.git GCOV: introduce usage of terminal colors. 2017-10-31 Martin Liska * color-macros.h: New file. * diagnostic-color.c: Factor out color related to macros to color-macros.h. * doc/gcov.texi: Document -k option. * gcov.c (INCLUDE_STRING): Include string.h. (print_usage): Add -k option. (process_args): Parse it. (pad_count_string): New function. (output_line_beginning): Likewise. (DEFAULT_LINE_START): New macro. (output_lines): Support color output. From-SVN: r254258 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b15dc955dc5..b1d984ad0c7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2017-10-31 Martin Liska + + * color-macros.h: New file. + * diagnostic-color.c: Factor out color related to macros to + color-macros.h. + * doc/gcov.texi: Document -k option. + * gcov.c (INCLUDE_STRING): Include string.h. + (print_usage): Add -k option. + (process_args): Parse it. + (pad_count_string): New function. + (output_line_beginning): Likewise. + (DEFAULT_LINE_START): New macro. + (output_lines): Support color output. + 2017-10-31 Martin Liska PR gcov-profile/82633 diff --git a/gcc/color-macros.h b/gcc/color-macros.h new file mode 100644 index 00000000000..37ed4d197cf --- /dev/null +++ b/gcc/color-macros.h @@ -0,0 +1,108 @@ +/* Terminal color manipulation macros. + Copyright (C) 2005-2017 Free Software Foundation, Inc. + +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 +. */ + +#ifndef GCC_COLOR_MACROS_H +#define GCC_COLOR_MACROS_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("") + +#endif /* GCC_COLOR_MACROS_H */ diff --git a/gcc/diagnostic-color.c b/gcc/diagnostic-color.c index b8cf6f2c045..ccbae4ba223 100644 --- a/gcc/diagnostic-color.c +++ b/gcc/diagnostic-color.c @@ -24,90 +24,7 @@ # include #endif -/* 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("") - +#include "color-macros.h" /* The context and logic for choosing default --color screen attributes (foreground and background colors, etc.) are the following. diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi index 88b8d6d9071..9abc6030c21 100644 --- a/gcc/doc/gcov.texi +++ b/gcc/doc/gcov.texi @@ -125,6 +125,7 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}] [@option{-d}|@option{--display-progress}] [@option{-f}|@option{--function-summaries}] [@option{-i}|@option{--intermediate-format}] + [@option{-k}|@option{--use-colors}] [@option{-l}|@option{--long-file-names}] [@option{-m}|@option{--demangled-names}] [@option{-n}|@option{--no-output}] @@ -215,6 +216,14 @@ lcount:26,1 branch:28,nottaken @end smallexample +@item -k +@itemx --use-colors + +Use colors for lines of code that have zero coverage. We use red color for +non-exceptional lines and cyan for exceptional. Same colors are used for +basic blocks with @option{-a} option. + + @item -l @itemx --long-file-names Create long file names for included source files. For example, if the diff --git a/gcc/gcov.c b/gcc/gcov.c index c56bac20278..e53bcf0fd88 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -33,6 +33,7 @@ along with Gcov; see the file COPYING3. If not see #include "config.h" #define INCLUDE_ALGORITHM #define INCLUDE_VECTOR +#define INCLUDE_STRING #include "system.h" #include "coretypes.h" #include "tm.h" @@ -40,6 +41,7 @@ along with Gcov; see the file COPYING3. If not see #include "diagnostic.h" #include "version.h" #include "demangle.h" +#include "color-macros.h" #include @@ -381,6 +383,10 @@ static int flag_hash_filenames = 0; static int flag_verbose = 0; +/* Print colored output. */ + +static int flag_use_colors = 0; + /* Output count information for every basic block, not merely those that contain line number information. */ @@ -703,6 +709,7 @@ print_usage (int error_p) fnotice (file, " -f, --function-summaries Output summaries for each function\n"); fnotice (file, " -h, --help Print this help, then exit\n"); fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n"); + fnotice (file, " -k, --use-colors Emit colored output\n"); fnotice (file, " -l, --long-file-names Use long output file names for included\n\ source files\n"); fnotice (file, " -m, --demangled-names Output demangled function names\n"); @@ -756,6 +763,7 @@ static const struct option options[] = { "unconditional-branches", no_argument, NULL, 'u' }, { "display-progress", no_argument, NULL, 'd' }, { "hash-filenames", no_argument, NULL, 'x' }, + { "use-colors", no_argument, NULL, 'k' }, { 0, 0, 0, 0 } }; @@ -766,7 +774,7 @@ process_args (int argc, char **argv) { int opt; - const char *opts = "abcdfhilmno:prs:uvwx"; + const char *opts = "abcdfhiklmno:prs:uvwx"; while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1) { switch (opt) @@ -789,6 +797,9 @@ process_args (int argc, char **argv) case 'l': flag_long_names = 1; break; + case 'k': + flag_use_colors = 1; + break; case 'm': flag_demangled_names = 1; break; @@ -2468,6 +2479,65 @@ read_line (FILE *file) return pos ? string : NULL; } +/* Pad string S with spaces from left to have total width equal to 9. */ + +static void +pad_count_string (string &s) +{ + if (s.size () < 9) + s.insert (0, 9 - s.size (), ' '); +} + +/* Print GCOV line beginning to F stream. If EXISTS is set to true, the + line exists in source file. UNEXCEPTIONAL indicated that it's not in + an exceptional statement. The output is printed for LINE_NUM of given + COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are + used to indicate non-executed blocks. */ + +static void +output_line_beginning (FILE *f, bool exists, bool unexceptional, + gcov_type count, unsigned line_num, + const char *exceptional_string, + const char *unexceptional_string) +{ + string s; + if (exists) + { + if (count > 0) + { + s = format_gcov (count, 0, -1); + pad_count_string (s); + } + else + { + if (flag_use_colors) + { + s = "0"; + pad_count_string (s); + if (unexceptional) + s.insert (0, SGR_SEQ (COLOR_BG_RED + COLOR_SEPARATOR COLOR_FG_WHITE)); + else + s.insert (0, SGR_SEQ (COLOR_BG_CYAN + COLOR_SEPARATOR COLOR_FG_WHITE)); + s += SGR_RESET; + } + else + { + s = unexceptional ? unexceptional_string : exceptional_string; + pad_count_string (s); + } + } + } + else + { + s = "-"; + pad_count_string (s); + } + + fprintf (f, "%s:%5u", s.c_str (), line_num); +} + /* Read in the source file one line at a time, and output that line to the gcov file preceded by its execution count and other information. */ @@ -2475,21 +2545,23 @@ read_line (FILE *file) static void output_lines (FILE *gcov_file, const source_t *src) { +#define DEFAULT_LINE_START " -: 0:" + FILE *source_file; unsigned line_num; /* current line number. */ const line_t *line; /* current line info ptr. */ const char *retval = ""; /* status of source file reading. */ function_t *fn = NULL; - fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name); + fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name); if (!multiple_files) { - fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name); - fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, + fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name); + fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n", no_data_file ? "-" : da_file_name); - fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs); + fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs); } - fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count); + fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count); source_file = fopen (src->name, "r"); if (!source_file) @@ -2498,7 +2570,7 @@ output_lines (FILE *gcov_file, const source_t *src) retval = NULL; } else if (src->file_time == 0) - fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0); + fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n"); if (flag_branches) fn = src->functions; @@ -2537,11 +2609,10 @@ output_lines (FILE *gcov_file, const source_t *src) Otherwise, print the execution count before the source line. There are 16 spaces of indentation added before the source line so that tabs won't be messed up. */ - fprintf (gcov_file, "%9s:%5u:%s\n", - !line->exists ? "-" : line->count - ? format_gcov (line->count, 0, -1) - : line->unexceptional ? "#####" : "=====", line_num, - retval ? retval : "/*EOF*/"); + output_line_beginning (gcov_file, line->exists, line->unexceptional, + line->count, line_num, + "=====", "#####"); + fprintf (gcov_file, ":%s\n", retval ? retval : "/*EOF*/"); if (flag_all_blocks) { @@ -2554,11 +2625,11 @@ output_lines (FILE *gcov_file, const source_t *src) { if (!block->is_call_return) { - fprintf (gcov_file, "%9s:%5u-block %2d", - !line->exists ? "-" : block->count - ? format_gcov (block->count, 0, -1) - : block->exceptional ? "%%%%%" : "$$$$$", - line_num, ix++); + output_line_beginning (gcov_file, line->exists, + block->exceptional, + block->count, line_num, + "%%%%%", "$$$$$"); + fprintf (gcov_file, "-block %2d", ix++); if (flag_verbose) fprintf (gcov_file, " (BB %u)", block->id); fprintf (gcov_file, "\n");