OSDN Git Service

* gcov.c (output_data): Use HOST_WIDEST_INT_PRINT_DEC to output
[pf3gnuchains/gcc-fork.git] / gcc / gcov.c
index 102b14d..0251a65 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,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "config.h"
 #include "system.h"
-#include <sys/stat.h>
+#include "intl.h"
+#undef abort
 
+typedef HOST_WIDEST_INT gcov_type;
 #include "gcov-io.h"
 
 /* The .bb file format consists of several lists of 4-byte integers
@@ -101,7 +105,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 +124,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 +140,8 @@ struct bb_info {
 
 struct arcdata
 {
-  int prob;
+  gcov_type hits;
+  gcov_type total;
   int call_insn;
   struct arcdata *next;
 };
@@ -211,19 +216,46 @@ 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;
+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 ((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;
 {
+/* LC_CTYPE determines the character set used by the terminal so it has be set
+   to output messages correctly.  */
+
+#ifdef HAVE_LC_MESSAGES
+  setlocale (LC_CTYPE, "");
+  setlocale (LC_MESSAGES, "");
+#else
+  setlocale (LC_ALL, "");
+#endif
+
+  (void) bindtextdomain (PACKAGE, localedir);
+  (void) textdomain (PACKAGE);
+
   process_args (argc, argv);
 
   open_files ();
@@ -237,26 +269,35 @@ main (argc, argv)
   return 0;
 }
 
-PTR
-xmalloc (size)
-  size_t size;
+static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
+static void
+fnotice VPARAMS ((FILE *file, const char *msgid, ...))
 {
-  register PTR value = (PTR) malloc (size);
-  if (value == 0)
-    {
-      fprintf (stderr, "error: virtual memory exhausted");
-      exit (FATAL_EXIT_CODE);
-    }
-  return value;
+#ifndef ANSI_PROTOTYPES
+  FILE *file;
+  const char *msgid;
+#endif
+  va_list ap;
+
+  VA_START (ap, msgid);
+
+#ifndef ANSI_PROTOTYPES
+  file = va_arg (ap, FILE *);
+  msgid = va_arg (ap, const char *);
+#endif
+
+  vfprintf (file, _(msgid), ap);
+  va_end (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
@@ -265,7 +306,7 @@ fancy_abort ()
 static void
 print_usage ()
 {
-  fprintf (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
+  fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
   exit (FATAL_EXIT_CODE);
 }
 
@@ -284,6 +325,8 @@ process_args (argc, argv)
        {
          if (argv[i][1] == 'b')
            output_branch_probs = 1;
+         else if (argv[i][1] == 'c')
+           output_branch_counts = 1;
          else if (argv[i][1] == 'v')
            fputs (gcov_version_string, stderr);
          else if (argv[i][1] == 'n')
@@ -341,7 +384,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);
@@ -362,44 +405,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);
     }
@@ -410,7 +453,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);
     }
@@ -478,10 +521,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;
@@ -539,8 +580,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;
@@ -549,12 +590,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;
@@ -665,7 +707,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++)
@@ -711,10 +753,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
@@ -730,7 +772,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);
@@ -772,8 +814,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;
@@ -849,12 +890,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)
@@ -862,15 +904,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++;
            }
        }
@@ -895,33 +937,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);
     }
 }
 
@@ -935,7 +977,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
@@ -976,7 +1018,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);
@@ -989,18 +1037,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;
@@ -1024,7 +1066,7 @@ output_data ()
                  this_file = 0;
                else
                  this_file = 1;
-             
+
                /* Scan past the file name.  */
                do {
                  count++;
@@ -1052,10 +1094,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);
                      }
 
@@ -1093,11 +1135,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);
@@ -1153,15 +1195,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++;
                    }
                }
@@ -1169,34 +1211,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)
@@ -1204,11 +1246,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);
@@ -1216,7 +1258,7 @@ output_data ()
            }
 
          count = strlen (source_file_name);
-         cptr = rindex (s_ptr->name, '/');
+         cptr = strrchr (s_ptr->name, '/');
          if (cptr)
            cptr = cptr + 1;
          else
@@ -1224,8 +1266,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
@@ -1233,7 +1275,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
@@ -1242,7 +1284,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
@@ -1258,7 +1300,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);
@@ -1266,7 +1308,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++)
            {
@@ -1284,8 +1326,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);
                }
@@ -1309,29 +1355,52 @@ 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)
+                                 fnotice (gcov_file,
+                                          "call %d returns = "
+                                          HOST_WIDEST_INT_PRINT_DEC "\n",
+                                          i, a_ptr->total - a_ptr->hits);
+                               else
+                                  fnotice (gcov_file,
+                                          "call %d returns = "
+                                          HOST_WIDEST_INT_PRINT_DEC "%%\n",
+                                           i, 100 - ((a_ptr->hits * 100) +
+                                           (a_ptr->total >> 1))/a_ptr->total);
+                             }
                        }
                      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)
+                               fnotice (gcov_file,
+                                        "branch %d taken = "
+                                        HOST_WIDEST_INT_PRINT_DEC "\n",
+                                         i, a_ptr->hits);
+                             else
+                                fnotice (gcov_file,
+                                         "branch %d taken = "
+                                        HOST_WIDEST_INT_PRINT_DEC "%%\n", i,
+                                         ((a_ptr->hits * 100) +
+                                          (a_ptr->total >> 1))/
+                                          a_ptr->total);
+
+                           }
                        }
-                   }
-               }
+                  }
+             }
 
              /* 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;