+2017-10-31 Martin Liska <mliska@suse.cz>
+
+ * 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 <mliska@suse.cz>
PR gcov-profile/82633
--- /dev/null
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+#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 */
# include <windows.h>
#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.
[@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}]
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
#include "config.h"
#define INCLUDE_ALGORITHM
#define INCLUDE_VECTOR
+#define INCLUDE_STRING
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "diagnostic.h"
#include "version.h"
#include "demangle.h"
+#include "color-macros.h"
#include <getopt.h>
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. */
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");
{ "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 }
};
{
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)
case 'l':
flag_long_names = 1;
break;
+ case 'k':
+ flag_use_colors = 1;
+ break;
case 'm':
flag_demangled_names = 1;
break;
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. */
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)
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;
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)
{
{
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");