GCOV: introduce usage of terminal colors.
authorMartin Liska <mliska@suse.cz>
Tue, 31 Oct 2017 11:57:10 +0000 (12:57 +0100)
committerMartin Liska <marxin@gcc.gnu.org>
Tue, 31 Oct 2017 11:57:10 +0000 (11:57 +0000)
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.

From-SVN: r254258

gcc/ChangeLog
gcc/color-macros.h [new file with mode: 0644]
gcc/diagnostic-color.c
gcc/doc/gcov.texi
gcc/gcov.c

index b15dc955dc5d9042d53828684025de7540a59208..b1d984ad0c7a019036d0efd4e8ab473ebb55b4e7 100644 (file)
@@ -1,3 +1,17 @@
+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
diff --git a/gcc/color-macros.h b/gcc/color-macros.h
new file mode 100644 (file)
index 0000000..37ed4d1
--- /dev/null
@@ -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
+<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 */
index b8cf6f2c04556594f97b2b377864fd42d01c1935..ccbae4ba22363172f0842f6cf25600717d731cc7 100644 (file)
 #  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.
index 88b8d6d9071181cc35aad458867703a8e61dc6b5..9abc6030c2144b6e708bb2bd7f3dd377b4f2cd72 100644 (file)
@@ -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
index c56bac2027831fe6ee0f575c9bfb2795a6635588..e53bcf0fd88ee57f3c37f18e350e8994ce6ad5fc 100644 (file)
@@ -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 <getopt.h>
 
@@ -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");