OSDN Git Service

* Makefile.in (GCOV_OBJS): Add version.o.
[pf3gnuchains/gcc-fork.git] / gcc / gcov.c
index 2a093c6..aad22a8 100644 (file)
@@ -1,6 +1,7 @@
 /* Gcov.c: prepend line execution counts and branch probabilities to a
    source file.
-   Copyright (C) 1990, 91, 92, 93, 94, 96, 97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
+   1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by James E. Wilson of Cygnus Support.
    Mangled by Bob Manson of Cygnus Support.
 
@@ -16,7 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with Gcov; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* ??? The code in final.c that produces the struct bb assumes that there is
    no padding between the fields.  This is not necessary true.  The current
@@ -43,8 +45,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "config.h"
 #include "system.h"
-#include <sys/stat.h>
+#include "intl.h"
+#include "version.h"
+#undef abort
 
+#include <getopt.h>
+
+typedef HOST_WIDEST_INT gcov_type;
 #include "gcov-io.h"
 
 /* The .bb file format consists of several lists of 4-byte integers
@@ -75,8 +82,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* The functions in this file for creating and solution program flow graphs
    are very similar to functions in the gcc source file profile.c.  */
 
-char gcov_version_string[] = "GNU gcov version 1.5\n";
-
 /* This is the size of the buffer used to read in source file lines.  */
 
 #define STRING_SIZE 200
@@ -101,7 +106,7 @@ struct sourcefile *sources;
 struct adj_list {
   int source;
   int target;
-  int arc_count;
+  gcov_type arc_count;
   unsigned int count_valid : 1;
   unsigned int on_tree : 1;
   unsigned int fake : 1;
@@ -120,9 +125,9 @@ struct adj_list {
 struct bb_info {
   struct adj_list *succ;
   struct adj_list *pred;
-  int succ_count;
-  int pred_count;
-  int exec_count;
+  gcov_type succ_count;
+  gcov_type pred_count;
+  gcov_type exec_count;
   unsigned int count_valid : 1;
   unsigned int on_tree : 1;
 #if 0
@@ -136,7 +141,8 @@ struct bb_info {
 
 struct arcdata
 {
-  int prob;
+  gcov_type hits;
+  gcov_type total;
   int call_insn;
   struct arcdata *next;
 };
@@ -211,20 +217,36 @@ static int output_function_summary = 0;
 
 static char *object_directory = 0;
 
+/* Output the number of times a branch was taken as opposed to the percentage
+   of times it was taken.  Turned on by the -c option */
+
+static int output_branch_counts = 0;
+
 /* Forward declarations.  */
-static void process_args PROTO ((int, char **));
-static void open_files PROTO ((void));
-static void read_files PROTO ((void));
-static void scan_for_source_files PROTO ((void));
-static void output_data PROTO ((void));
-static void print_usage PROTO ((void)) ATTRIBUTE_NORETURN;
-char * xmalloc ();
+static void process_args PARAMS ((int, char **));
+static void open_files PARAMS ((void));
+static void read_files PARAMS ((void));
+static void scan_for_source_files PARAMS ((void));
+static void output_data PARAMS ((void));
+static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
+static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
+static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
+static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
+static void create_program_flow_graph PARAMS ((struct bb_info_list *));
+static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
+static void calculate_branch_probs PARAMS ((struct bb_info_list *, int,
+                                           struct arcdata **, int));
+static void function_summary PARAMS ((void));
+
+extern int main PARAMS ((int, char **));
 
 int
 main (argc, argv)
      int argc;
      char **argv;
 {
+  gcc_init_libintl ();
+
   process_args (argc, argv);
 
   open_files ();
@@ -238,38 +260,80 @@ main (argc, argv)
   return 0;
 }
 
-char *
-xmalloc (size)
-     unsigned size;
+static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
+static void
+fnotice VPARAMS ((FILE *file, const char *msgid, ...))
 {
-  register char *value = (char *) malloc (size);
-  if (value == 0)
-    {
-      fprintf (stderr, "error: virtual memory exhausted");
-      exit (FATAL_EXIT_CODE);
-    }
-  return value;
+  VA_OPEN (ap, msgid);
+  VA_FIXEDARG (ap, FILE *, file);
+  VA_FIXEDARG (ap, const char *, msgid);
+
+  vfprintf (file, _(msgid), ap);
+  VA_CLOSE (ap);
 }
 
 /* More 'friendly' abort that prints the line and file.
    config.h can #define abort fancy_abort if you like that sort of thing.  */
+extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
 
 void
 fancy_abort ()
 {
-  fprintf (stderr, "Internal gcc abort.\n");
+  fnotice (stderr, "Internal gcov abort.\n");
   exit (FATAL_EXIT_CODE);
 }
 \f
-/* Print a usage message and exit.  */
+/* Print a usage message and exit.  If ERROR_P is nonzero, this is an error,
+   otherwise the output of --help.  */
 
 static void
-print_usage ()
+print_usage (error_p)
+     int error_p;
 {
-  fprintf (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
-  exit (FATAL_EXIT_CODE);
+  FILE *file = error_p ? stderr : stdout;
+  int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
+  fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
+  fnotice (file, "Print code coverage information.\n\n");
+  fnotice (file, "  -h, --help                      Print this help, then exit\n");
+  fnotice (file, "  -v, --version                   Print version number, then exit\n");
+  fnotice (file, "  -b, --branch-probabilities      Include branch probabilities in output\n");
+  fnotice (file, "  -c, --branch-counts             Given counts of branches taken\n\
+                                    rather than percentages\n");
+  fnotice (file, "  -n, --no-output                 Do not create an output file\n");
+  fnotice (file, "  -l, --long-file-names           Use long output file names for included\n\
+                                    source files\n");
+  fnotice (file, "  -f, --function-summaries        Output summaries for each function\n");
+  fnotice (file, "  -o, --object-directory OBJDIR   Search for object files in OBJDIR\n");
+  fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
+          GCCBUGURL);
+  exit (status);
 }
 
+/* Print version information and exit.  */
+
+static void
+print_version ()
+{
+  fnotice (stdout, "gcov (GCC) %s\n", version_string);
+  fnotice (stdout, "Copyright (C) 2001 Free Software Foundation, Inc.\n");
+  fnotice (stdout,
+          "This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
+  exit (SUCCESS_EXIT_CODE);
+}
+
+static const struct option options[] =
+{
+  { "help",                 no_argument,       NULL, 'h' },
+  { "version",              no_argument,       NULL, 'v' },
+  { "branch-probabilities", no_argument,       NULL, 'b' },
+  { "branch-counts",        no_argument,       NULL, 'c' },
+  { "no-output",            no_argument,       NULL, 'n' },
+  { "long-file-names",      no_argument,       NULL, 'l' },
+  { "function-summaries",   no_argument,       NULL, 'f' },
+  { "object-directory",     required_argument, NULL, 'o' }
+};
+
 /* Parse the command line.  */
 
 static void
@@ -277,35 +341,46 @@ process_args (argc, argv)
      int argc;
      char **argv;
 {
-  int i;
+  int opt;
 
-  for (i = 1; i < argc; i++)
+  while ((opt = getopt_long (argc, argv, "hvbclnfo:", options, NULL)) != -1)
     {
-      if (argv[i][0] == '-')
+      switch (opt)
        {
-         if (argv[i][1] == 'b')
-           output_branch_probs = 1;
-         else if (argv[i][1] == 'v')
-           fputs (gcov_version_string, stderr);
-         else if (argv[i][1] == 'n')
-           output_gcov_file = 0;
-         else if (argv[i][1] == 'l')
-           output_long_names = 1;
-         else if (argv[i][1] == 'f')
-           output_function_summary = 1;
-         else if (argv[i][1] == 'o' && argv[i][2] == '\0')
-           object_directory = argv[++i];
-         else
-           print_usage ();
+       case 'h':
+         print_usage (false);
+         /* print_usage will exit.  */
+       case 'v':
+         print_version ();
+         /* print_version will exit.  */
+       case 'b':
+         output_branch_probs = 1;
+         break;
+       case 'c':
+         output_branch_counts = 1;
+         break;
+       case 'n':
+         output_gcov_file = 0;
+         break;
+       case 'l':
+         output_long_names = 1;
+         break;
+       case 'f':
+         output_function_summary = 1;
+         break;
+       case 'o':
+         object_directory = optarg;
+         break;
+       default:
+         print_usage (true);
+         /* print_usage will exit.  */
        }
-      else if (! input_file_name)
-       input_file_name = argv[i];
-      else
-       print_usage ();
     }
 
-  if (! input_file_name)
-    print_usage ();
+  if (optind != argc - 1)
+    print_usage (true);
+
+  input_file_name = argv[optind];
 }
 
 
@@ -342,7 +417,7 @@ open_files ()
          strcat (bbg_file_name, "/");
        }
 
-      cptr = rindex (input_file_name, '/');
+      cptr = strrchr (input_file_name, '/');
       if (cptr)
        {
          strcat (da_file_name, cptr + 1);
@@ -363,44 +438,44 @@ open_files ()
       strcpy (bbg_file_name, input_file_name);
     }
 
-  cptr = rindex (bb_file_name, '.');
+  cptr = strrchr (bb_file_name, '.');
   if (cptr)
     strcpy (cptr, ".bb");
   else
     strcat (bb_file_name, ".bb");
 
-  cptr = rindex (da_file_name, '.');
+  cptr = strrchr (da_file_name, '.');
   if (cptr)
     strcpy (cptr, ".da");
   else
     strcat (da_file_name, ".da");
 
-  cptr = rindex (bbg_file_name, '.');
+  cptr = strrchr (bbg_file_name, '.');
   if (cptr)
     strcpy (cptr, ".bbg");
   else
     strcat (bbg_file_name, ".bbg");
 
-  bb_file = fopen (bb_file_name, "r");
+  bb_file = fopen (bb_file_name, "rb");
   if (bb_file == NULL)
     {
-      fprintf (stderr, "Could not open basic block file %s.\n", bb_file_name);
+      fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
       exit (FATAL_EXIT_CODE);
     }
 
   /* If none of the functions in the file were executed, then there won't
      be a .da file.  Just assume that all counts are zero in this case.  */
-  da_file = fopen (da_file_name, "r");
+  da_file = fopen (da_file_name, "rb");
   if (da_file == NULL)
     {
-      fprintf (stderr, "Could not open data file %s.\n", da_file_name);
-      fprintf (stderr, "Assuming that all execution counts are zero.\n");
+      fnotice (stderr, "Could not open data file %s.\n", da_file_name);
+      fnotice (stderr, "Assuming that all execution counts are zero.\n");
     }
-    
-  bbg_file = fopen (bbg_file_name, "r");
+
+  bbg_file = fopen (bbg_file_name, "rb");
   if (bbg_file == NULL)
     {
-      fprintf (stderr, "Could not open program flow graph file %s.\n",
+      fnotice (stderr, "Could not open program flow graph file %s.\n",
               bbg_file_name);
       exit (FATAL_EXIT_CODE);
     }
@@ -411,7 +486,7 @@ open_files ()
   ungetc (getc (bbg_file), bbg_file);
   if (feof (bbg_file))
     {
-      fprintf (stderr, "No executable code associated with file %s.\n",
+      fnotice (stderr, "No executable code associated with file %s.\n",
               input_file_name);
       exit (FATAL_EXIT_CODE);
     }
@@ -444,7 +519,7 @@ init_arc (arcptr, source, target, bb_graph)
 }
 
 
-/* Reverse the arcs on a arc list.  */
+/* Reverse the arcs on an arc list.  */
 
 static struct adj_list *
 reverse_arcs (arcptr)
@@ -479,10 +554,8 @@ create_program_flow_graph (bptr)
   /* Read the number of blocks.  */
   __read_long (&num_blocks, bbg_file, 4);
 
-  /* Create an array of size bb number of bb_info structs.  Bzero it.  */
-  bb_graph = (struct bb_info *) xmalloc (num_blocks
-                                        * sizeof (struct bb_info));
-  bzero ((char *) bb_graph, sizeof (struct bb_info) * num_blocks);
+  /* Create an array of size bb number of bb_info structs.  */
+  bb_graph = (struct bb_info *) xcalloc (num_blocks, sizeof (struct bb_info));
 
   bptr->bb_graph = bb_graph;
   bptr->num_blocks = num_blocks;
@@ -540,8 +613,8 @@ create_program_flow_graph (bptr)
     for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
       if (! arcptr->on_tree)
        {
-         long tmp_count = 0;;
-         if (da_file && __read_long (&tmp_count, da_file, 8))
+         gcov_type tmp_count = 0;
+         if (da_file && __read_gcov_type (&tmp_count, da_file, 8))
            abort();
 
          arcptr->arc_count = tmp_count;
@@ -550,12 +623,13 @@ create_program_flow_graph (bptr)
          bb_graph[arcptr->target].pred_count--;
        }
 }
-  
+
 static void
 solve_program_flow_graph (bptr)
      struct bb_info_list *bptr;
 {
-  int passes, changes, total;
+  int passes, changes;
+  gcov_type total;
   int i;
   struct adj_list *arcptr;
   struct bb_info *bb_graph;
@@ -666,7 +740,7 @@ solve_program_flow_graph (bptr)
            }
        }
     }
-             
+
   /* If the graph has been correctly solved, every block will have a
      succ and pred count of zero.  */
   for (i = 0; i < num_blocks; i++)
@@ -712,10 +786,10 @@ read_files ()
   if (da_file)
     {
       if (feof (da_file))
-       fprintf (stderr, ".da file contents exhausted too early\n");
+       fnotice (stderr, ".da file contents exhausted too early\n");
       /* Should be at end of file now.  */
       if (__read_long (&total, da_file, 8) == 0)
-       fprintf (stderr, ".da file contents not exhausted\n");
+       fnotice (stderr, ".da file contents not exhausted\n");
     }
 
   /* Calculate all of the basic block execution counts and branch
@@ -731,7 +805,7 @@ read_files ()
 
   bb_data = (char *) xmalloc ((unsigned) buf.st_size);
   fread (bb_data, sizeof (char), buf.st_size, bb_file);
-  
+
   fclose (bb_file);
   if (da_file)
     fclose (da_file);
@@ -747,7 +821,7 @@ scan_for_source_files ()
 {
   struct sourcefile *s_ptr = NULL;
   char *ptr;
-  int count;
+  long count;
   long line_num;
 
   /* Search the bb_data to find:
@@ -773,8 +847,7 @@ scan_for_source_files ()
              /* No sourcefile structure for this file name exists, create
                 a new one, and append it to the front of the sources list.  */
              s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
-             s_ptr->name = xmalloc (strlen ((char *) ptr) + 1);
-             strcpy (s_ptr->name, (char *) ptr);
+             s_ptr->name = xstrdup (ptr);
              s_ptr->maxlineno = 0;
              s_ptr->next = sources;
              sources = s_ptr;
@@ -811,7 +884,7 @@ scan_for_source_files ()
        }
       else if (line_num < 0)
        {
-         /* Don't know what this is, but it's garbage. */
+         /* Don't know what this is, but it's garbage.  */
          abort();
        }
     }
@@ -838,7 +911,7 @@ calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
      struct arcdata **branch_probs;
      int last_line_num;
 {
-  int total;
+  gcov_type total;
   struct adj_list *arcptr;
   struct arcdata *end_ptr, *a_ptr;
 
@@ -850,12 +923,13 @@ calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
 
       if (arcptr->fall_through)
        continue;
-                     
+
       a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
+      a_ptr->total = total;
       if (total == 0)
-       a_ptr->prob = -1;
+          a_ptr->hits = 0;
       else
-       a_ptr->prob = ((arcptr->arc_count * 100) + (total >> 1)) / total;
+          a_ptr->hits = arcptr->arc_count;
       a_ptr->call_insn = arcptr->fake;
 
       if (output_function_summary)
@@ -863,15 +937,15 @@ calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
          if (a_ptr->call_insn)
            {
              function_calls++;
-             if (a_ptr->prob != -1)
+             if (a_ptr->total != 0)
                function_calls_executed++;
            }
          else
            {
              function_branches++;
-             if (a_ptr->prob != -1)
+             if (a_ptr->total != 0)
                function_branches_executed++;
-             if (a_ptr->prob > 0)
+             if (a_ptr->hits > 0)
                function_branches_taken++;
            }
        }
@@ -896,33 +970,33 @@ static void
 function_summary ()
 {
   if (function_source_lines)
-    fprintf (stdout, "%6.2f%% of %d source lines executed in function %s\n",
+    fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
             (((double) function_source_lines_executed / function_source_lines)
              * 100), function_source_lines, function_name);
   else
-    fprintf (stdout, "No executable source lines in function %s\n",
+    fnotice (stdout, "No executable source lines in function %s\n",
             function_name);
 
   if (output_branch_probs)
     {
       if (function_branches)
        {
-         fprintf (stdout, "%6.2f%% of %d branches executed in function %s\n",
+         fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
                   (((double) function_branches_executed / function_branches)
                    * 100), function_branches, function_name);
-         fprintf (stdout,
+         fnotice (stdout,
                "%6.2f%% of %d branches taken at least once in function %s\n",
                   (((double) function_branches_taken / function_branches)
                    * 100), function_branches, function_name);
        }
       else
-       fprintf (stdout, "No branches in function %s\n", function_name);
+       fnotice (stdout, "No branches in function %s\n", function_name);
       if (function_calls)
-       fprintf (stdout, "%6.2f%% of %d calls executed in function %s\n",
+       fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
                 (((double) function_calls_executed / function_calls)
                  * 100), function_calls, function_name);
       else
-       fprintf (stdout, "No calls in function %s\n", function_name);
+       fnotice (stdout, "No calls in function %s\n", function_name);
     }
 }
 
@@ -936,7 +1010,7 @@ output_data ()
   int this_file;
   /* An array indexed by line number which indicates how many times that line
      was executed.  */
-  long *line_counts;
+  gcov_type *line_counts;
   /* An array indexed by line number which indicates whether the line was
      present in the bb file (i.e. whether it had code associate with it).
      Lines never executed are those which both exist, and have zero execution
@@ -949,7 +1023,7 @@ output_data ()
   char *source_file_name;
   FILE *source_file;
   struct bb_info_list *current_graph;
-  int count;
+  long count;
   char *cptr;
   long block_num;
   long line_num;
@@ -977,7 +1051,13 @@ output_data ()
     {
       /* If this is a relative file name, and an object directory has been
         specified, then make it relative to the object directory name.  */
-      if (*s_ptr->name != '/' && object_directory != 0
+      if (! (*s_ptr->name == '/' || *s_ptr->name == DIR_SEPARATOR
+            /* Check for disk name on MS-DOS-based systems.  */
+            || (DIR_SEPARATOR == '\\'
+                && s_ptr->name[1] == ':'
+                && (s_ptr->name[2] == DIR_SEPARATOR
+                    || s_ptr->name[2] == '/')))
+         && object_directory != 0
          && *object_directory != '\0')
        {
          int objdir_count = strlen (object_directory);
@@ -990,18 +1070,12 @@ output_data ()
       else
        source_file_name = s_ptr->name;
 
-      line_counts = (long *) xmalloc (sizeof (long) * s_ptr->maxlineno);
-      bzero ((char *) line_counts, sizeof (long) * s_ptr->maxlineno);
-      line_exists = xmalloc (s_ptr->maxlineno);
-      bzero (line_exists, s_ptr->maxlineno);
+      line_counts = (gcov_type *) xcalloc (sizeof (gcov_type), s_ptr->maxlineno);
+      line_exists = xcalloc (1, s_ptr->maxlineno);
       if (output_branch_probs)
-       {
-         branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata *)
-                                                     * s_ptr->maxlineno);
-         bzero ((char *) branch_probs, 
-                sizeof (struct arcdata *) * s_ptr->maxlineno);
-       }
-      
+       branch_probs = (struct arcdata **)
+         xcalloc (sizeof (struct arcdata *), s_ptr->maxlineno);
+
       /* There will be a zero at the beginning of the bb info, before the
         first list of line numbers, so must initialize block_num to 0.  */
       block_num = 0;
@@ -1025,7 +1099,7 @@ output_data ()
                  this_file = 0;
                else
                  this_file = 1;
-             
+
                /* Scan past the file name.  */
                do {
                  count++;
@@ -1053,10 +1127,10 @@ output_data ()
                      }
                    else
                      {
-                       fprintf (stderr,
+                       fnotice (stderr,
                                 "didn't use all bb entries of graph, function %s\n",
                                 function_name);
-                       fprintf (stderr, "block_num = %ld, num_blocks = %d\n",
+                       fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
                                 block_num, current_graph->num_blocks);
                      }
 
@@ -1094,11 +1168,11 @@ output_data ()
 
                if (block_num >= current_graph->num_blocks)
                  {
-                   fprintf (stderr, "ERROR: too many basic blocks in .bb file %s\n",
+                   fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
                             function_name);
                    abort ();
                  }
-                 
+
                if (output_branch_probs && this_file)
                  calculate_branch_probs (current_graph, block_num,
                                          branch_probs, last_line_num);
@@ -1154,15 +1228,15 @@ output_data ()
                  if (a_ptr->call_insn)
                    {
                      total_calls++;
-                     if (a_ptr->prob != -1)
+                     if (a_ptr->total != 0)
                        total_calls_executed++;
                    }
                  else
                    {
                      total_branches++;
-                     if (a_ptr->prob != -1)
+                     if (a_ptr->total != 0)
                        total_branches_executed++;
-                     if (a_ptr->prob > 0)
+                     if (a_ptr->hits > 0)
                        total_branches_taken++;
                    }
                }
@@ -1170,34 +1244,34 @@ output_data ()
        }
 
       if (total_source_lines)
-       fprintf (stdout,
+       fnotice (stdout,
                 "%6.2f%% of %d source lines executed in file %s\n",
                 (((double) total_source_lines_executed / total_source_lines)
                  * 100), total_source_lines, source_file_name);
       else
-       fprintf (stdout, "No executable source lines in file %s\n",
+       fnotice (stdout, "No executable source lines in file %s\n",
                 source_file_name);
 
       if (output_branch_probs)
        {
          if (total_branches)
            {
-             fprintf (stdout, "%6.2f%% of %d branches executed in file %s\n",
+             fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
                       (((double) total_branches_executed / total_branches)
                        * 100), total_branches, source_file_name);
-             fprintf (stdout,
+             fnotice (stdout,
                    "%6.2f%% of %d branches taken at least once in file %s\n",
                       (((double) total_branches_taken / total_branches)
                        * 100), total_branches, source_file_name);
            }
          else
-           fprintf (stdout, "No branches in file %s\n", source_file_name);
+           fnotice (stdout, "No branches in file %s\n", source_file_name);
          if (total_calls)
-           fprintf (stdout, "%6.2f%% of %d calls executed in file %s\n",
+           fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
                     (((double) total_calls_executed / total_calls)
                      * 100), total_calls, source_file_name);
          else
-           fprintf (stdout, "No calls in file %s\n", source_file_name);
+           fnotice (stdout, "No calls in file %s\n", source_file_name);
        }
 
       if (output_gcov_file)
@@ -1205,11 +1279,11 @@ output_data ()
          /* Now the statistics are ready.  Read in the source file one line
             at a time, and output that line to the gcov file preceded by
             its execution count if non zero.  */
-      
+
          source_file = fopen (source_file_name, "r");
          if (source_file == NULL)
            {
-             fprintf (stderr, "Could not open source file %s.\n",
+             fnotice (stderr, "Could not open source file %s.\n",
                       source_file_name);
              free (line_counts);
              free (line_exists);
@@ -1217,7 +1291,7 @@ output_data ()
            }
 
          count = strlen (source_file_name);
-         cptr = rindex (s_ptr->name, '/');
+         cptr = strrchr (s_ptr->name, '/');
          if (cptr)
            cptr = cptr + 1;
          else
@@ -1225,8 +1299,8 @@ output_data ()
          if (output_long_names && strcmp (cptr, input_file_name))
            {
              gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
-             
-             cptr = rindex (input_file_name, '/');
+
+             cptr = strrchr (input_file_name, '/');
              if (cptr)
                strcpy (gcov_file_name, cptr + 1);
              else
@@ -1234,7 +1308,7 @@ output_data ()
 
              strcat (gcov_file_name, ".");
 
-             cptr = rindex (source_file_name, '/');
+             cptr = strrchr (source_file_name, '/');
              if (cptr)
                strcat (gcov_file_name, cptr + 1);
              else
@@ -1243,7 +1317,7 @@ output_data ()
          else
            {
              gcov_file_name = xmalloc (count + 6);
-             cptr = rindex (source_file_name, '/');
+             cptr = strrchr (source_file_name, '/');
              if (cptr)
                strcpy (gcov_file_name, cptr + 1);
              else
@@ -1259,7 +1333,7 @@ output_data ()
 
          if (gcov_file == NULL)
            {
-             fprintf (stderr, "Could not open output file %s.\n",
+             fnotice (stderr, "Could not open output file %s.\n",
                       gcov_file_name);
              fclose (source_file);
              free (line_counts);
@@ -1267,7 +1341,7 @@ output_data ()
              continue;
            }
 
-         fprintf (stdout, "Creating %s.\n", gcov_file_name);
+         fnotice (stdout, "Creating %s.\n", gcov_file_name);
 
          for (count = 1; count < s_ptr->maxlineno; count++)
            {
@@ -1285,8 +1359,12 @@ output_data ()
              if (line_exists[count])
                {
                  if (line_counts[count])
-                   fprintf (gcov_file, "%12ld    %s", line_counts[count],
-                            string);
+                   {
+                     char c[20];
+                     sprintf (c, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)line_counts[count]);
+                     fprintf (gcov_file, "%12s    %s", c,
+                              string);
+                   }
                  else
                    fprintf (gcov_file, "      ######    %s", string);
                }
@@ -1310,29 +1388,64 @@ output_data ()
                    {
                      if (a_ptr->call_insn)
                        {
-                         if (a_ptr->prob == -1)
-                           fprintf (gcov_file, "call %d never executed\n", i);
-                         else
-                           fprintf (gcov_file,
-                                    "call %d returns = %d%%\n",
-                                    i, 100 - a_ptr->prob);
+                         if (a_ptr->total == 0)
+                           fnotice (gcov_file, "call %d never executed\n", i);
+                           else
+                             {
+                               if (output_branch_counts)
+                                 {
+                                   char c[20];
+                                   sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
+                                            a_ptr->total - a_ptr->hits);
+                                   fnotice (gcov_file,
+                                            "call %d returns = %s\n", i, c);
+                                 }
+                               else
+                                 {
+                                   char c[20];
+                                   sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
+                                            100 - ((a_ptr->hits * 100)
+                                                   + (a_ptr->total >> 1))
+                                            / a_ptr->total);
+                                   fnotice (gcov_file,
+                                            "call %d returns = %s%%\n", i, c);
+                                 }
+                             }
                        }
                      else
                        {
-                         if (a_ptr->prob == -1)
-                           fprintf (gcov_file, "branch %d never executed\n",
+                         if (a_ptr->total == 0)
+                           fnotice (gcov_file, "branch %d never executed\n",
                                     i);
                          else
-                           fprintf (gcov_file, "branch %d taken = %d%%\n", i,
-                                    a_ptr->prob);
+                           {
+                             if (output_branch_counts)
+                               {
+                                 char c[20];
+                                 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
+                                          a_ptr->hits);
+                                 fnotice (gcov_file,
+                                          "branch %d taken = %s\n", i, c);
+                               }
+                             else
+                               {
+                                 char c[20];
+                                 sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
+                                          ((a_ptr->hits * 100)
+                                           + (a_ptr->total >> 1))
+                                          / a_ptr->total);
+                                fnotice (gcov_file,
+                                         "branch %d taken = %s%%\n", i, c);
+                               }
+                           }
                        }
-                   }
-               }
+                  }
+             }
 
              /* Gracefully handle errors while reading the source file.  */
              if (retval == NULL)
                {
-                 fprintf (stderr,
+                 fnotice (stderr,
                           "Unexpected EOF while reading source file %s.\n",
                           source_file_name);
                  break;