diff mbox

gcov patch, source prefixes

Message ID 4EBF9C2B.6030600@acm.org
State New
Headers show

Commit Message

Nathan Sidwell Nov. 13, 2011, 10:30 a.m. UTC
I've committed this patch to gcov, to add two new options.

*) a --source-prefix (-s) option, which allows you to specify a source path 
prefix that you want eliding from source file names.  You'd usually use this if 
you're building in a separate directory.

*) a --relative-only (-r) option, which will elide information for source files 
with an absolute path (after detecting any source prefix).  Usually absolute 
paths are system include files, and coverage of any inline functions they 
contain is uninteresting.

tested on i686-pc-linux-gnu.

nathan
2011-11-13  Nathan Sidwell  <nathan@acm.org>

	* gcov.c (source_prefix, source_length): New globals.
	(flag_relative_only): Likewise.
	(print_usage, options, process_args): Update.
	(generate_results): Use coverage.name, check
	flag_relative_only. Adjust messages.
	(find_source): Check source_prefix.
	(output_lines): Use coverage.name, adjust messages.
	* doc/gcov.texi (Invoking Gcov): Document new options.
diff mbox

Patch

Index: doc/gcov.texi
===================================================================
--- doc/gcov.texi	(revision 181309)
+++ doc/gcov.texi	(working copy)
@@ -124,13 +124,16 @@  gcov [@option{-v}|@option{--version}] [@
      [@option{-a}|@option{--all-blocks}]
      [@option{-b}|@option{--branch-probabilities}]
      [@option{-c}|@option{--branch-counts}]
+     [@option{-u}|@option{--unconditional-branches}]
      [@option{-n}|@option{--no-output}]
      [@option{-l}|@option{--long-file-names}]
      [@option{-p}|@option{--preserve-paths}]
+     [@option{-r}|@option{--relative-only}]
      [@option{-f}|@option{--function-summaries}]
-     [@option{-o}|@option{--object-directory} @var{directory|file}] @var{sourcefiles}
-     [@option{-u}|@option{--unconditional-branches}]
+     [@option{-o}|@option{--object-directory} @var{directory|file}]
+     [@option{-s}|@option{--source-prefix} @var{directory}]
      [@option{-d}|@option{--display-progress}]
+     @var{files}
 @c man end
 @c man begin SEEALSO
 gpl(7), gfdl(7), fsf-funding(7), gcc(1) and the Info entry for @file{gcc}.
@@ -193,6 +196,13 @@  removed and unremoveable @file{..}
 components renamed to @samp{^}.  This is useful if sourcefiles are in several
 different directories.
 
+@item -r
+@itemx --relative-only
+Only output information about source files with a relative pathname
+(after source prefix elision).  Absolute paths are usually system
+header files and coverage of any inline functions therein is normally
+uninteresting.
+
 @item -f
 @itemx --function-summaries
 Output summaries for each function in addition to the file level summary.
@@ -207,6 +217,14 @@  is specified, the data files are in that
 input file name, without its extension.  If a file is specified here,
 the data files are named after that file, without its extension.
 
+@item -s @var{directory}
+@itemx --source-prefix @var{directory}
+A prefix for source file names to remove when generating the output
+coverage files.  This option is useful when building in a separate
+directory, and the pathname to the source directory is not wanted when
+determining the output file names.  Note that this prefix detection is
+applied before determining whether the source file is absolute.
+
 @item -u
 @itemx --unconditional-branches
 When branch probabilities are given, include those of unconditional branches.
Index: gcov.c
===================================================================
--- gcov.c	(revision 181309)
+++ gcov.c	(working copy)
@@ -333,6 +333,17 @@  static int flag_function_summary = 0;
 
 static char *object_directory = 0;
 
+/* Source directory prefix.  This is removed from source pathnames
+   that match, when generating the output file name.  */
+
+static char *source_prefix = 0;
+static size_t source_length = 0;
+
+/* Only show data for sources with relative pathnames.  Absolute ones
+   usually indicate a system header file, which although it may
+   contain inline functions, is usually uninteresting.  */
+static int flag_relative_only = 0;
+
 /* Preserve all pathname components. Needed when object files and
    source files are in subdirectories. '/' is mangled as '#', '.' is
    elided and '..' mangled to '^'.  */
@@ -441,6 +452,8 @@  print_usage (int error_p)
                                     source files\n");
   fnotice (file, "  -f, --function-summaries        Output summaries for each function\n");
   fnotice (file, "  -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
+  fnotice (file, "  -s, --source-prefix DIR         Source prefix to elide\n");
+  fnotice (file, "  -r, --relative-only             Only show data for relative sources\n");
   fnotice (file, "  -p, --preserve-paths            Preserve all pathname components\n");
   fnotice (file, "  -u, --unconditional-branches    Show unconditional branch counts too\n");
   fnotice (file, "  -d, --display-progress          Display progress information\n");
@@ -475,8 +488,10 @@  static const struct option options[] =
   { "long-file-names",      no_argument,       NULL, 'l' },
   { "function-summaries",   no_argument,       NULL, 'f' },
   { "preserve-paths",       no_argument,       NULL, 'p' },
+  { "relative-only",        no_argument,       NULL, 'r' },
   { "object-directory",     required_argument, NULL, 'o' },
   { "object-file",          required_argument, NULL, 'o' },
+  { "source-prefix",        required_argument, NULL, 's' },
   { "unconditional-branches", no_argument,     NULL, 'u' },
   { "display-progress",     no_argument,       NULL, 'd' },
   { 0, 0, 0, 0 }
@@ -489,7 +504,7 @@  process_args (int argc, char **argv)
 {
   int opt;
 
-  while ((opt = getopt_long (argc, argv, "abcdfhlno:puv", options, NULL)) != -1)
+  while ((opt = getopt_long (argc, argv, "abcdfhlno:s:pruv", options, NULL)) != -1)
     {
       switch (opt)
 	{
@@ -517,6 +532,13 @@  process_args (int argc, char **argv)
 	case 'o':
 	  object_directory = optarg;
 	  break;
+	case 's':
+	  source_prefix = optarg;
+	  source_length = strlen (source_prefix);
+	  break;
+	case 'r':
+	  flag_relative_only = 1;
+	  break;
 	case 'p':
 	  flag_preserve_paths = 1;
 	  break;
@@ -641,33 +663,47 @@  generate_results (const char *file_name)
       name_map_t *name_map = (name_map_t *)bsearch
 	(file_name, names, n_names, sizeof (*names), name_search);
       if (name_map)
-	file_name = sources[name_map->src].name;
+	file_name = sources[name_map->src].coverage.name;
       else
 	file_name = canonicalize_name (file_name);
     }
   
   for (ix = n_sources, src = sources; ix--; src++)
     {
+      if (flag_relative_only)
+	{
+	  /* Ignore this source, if it is an absolute path (after
+	     source prefix removal).  */
+	  char first = src->coverage.name[0];
+      
+#if HAVE_DOS_BASED_FILE_SYSTEM
+	  if (first && src->coverage.name[1] == ':')
+	    first = src->coverage.name[2]
+#endif
+	    if (IS_DIR_SEPARATOR (first))
+	      continue;
+	}
+      
       accumulate_line_counts (src);
       function_summary (&src->coverage, "File");
       if (flag_gcov_file && src->coverage.lines)
 	{
-	  char *gcov_file_name = make_gcov_file_name (file_name, src->name);
+	  char *gcov_file_name
+	    = make_gcov_file_name (file_name, src->coverage.name);
 	  FILE *gcov_file = fopen (gcov_file_name, "w");
 
 	  if (gcov_file)
 	    {
-	      fnotice (stdout, "%s:creating '%s'\n",
-		       src->name, gcov_file_name);
+	      fnotice (stdout, "Creating '%s'\n", gcov_file_name);
 	      output_lines (gcov_file, src);
 	      if (ferror (gcov_file))
-		    fnotice (stderr, "%s:error writing output file '%s'\n",
-			     src->name, gcov_file_name);
+		    fnotice (stderr, "Error writing output file '%s'\n",
+			     gcov_file_name);
 	      fclose (gcov_file);
 	    }
 	  else
-	    fnotice (stderr, "%s:could not open output file '%s'\n",
-		     src->name, gcov_file_name);
+	    fnotice (stderr, "Could not open output file '%s'\n",
+		     gcov_file_name);
 	  free (gcov_file_name);
 	}
       fnotice (stdout, "\n");
@@ -877,6 +913,16 @@  find_source (const char *file_name)
       memset (src, 0, sizeof (*src));
       src->name = canon;
       src->coverage.name = src->name;
+      if (source_length
+#if HAVE_DOS_BASED_FILE_SYSTEM
+	  /* You lose if separators don't match exactly in the
+	     prefix.  */
+	  && !strncasecmp (source_prefix, src->coverage.name, source_length)
+#else
+	  && !strncmp (source_prefix, src->coverage.name, source_length)
+#endif
+	  && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
+	src->coverage.name += source_length + 1;
       if (!stat (src->name, &status))
 	src->file_time = status.st_mtime;
     }
@@ -2079,7 +2125,7 @@  output_lines (FILE *gcov_file, const sou
   char const *retval = "";	/* status of source file reading.  */
   function_t *fn = NULL;
 
-  fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
+  fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
   if (!multiple_files)
     {
       fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
@@ -2092,7 +2138,7 @@  output_lines (FILE *gcov_file, const sou
   source_file = fopen (src->name, "r");
   if (!source_file)
     {
-      fnotice (stderr, "%s:cannot open source file\n", src->name);
+      fnotice (stderr, "Cannot open source file %s\n", src->name);
       retval = NULL;
     }
   else if (src->file_time == 0)