OSDN Git Service

* gcov-io.c (GCOV_CHECK): Use gcc_assert when available.
[pf3gnuchains/gcc-fork.git] / gcc / gcov.c
index 276918f..8351596 100644 (file)
@@ -1,7 +1,7 @@
 /* Gcov.c: prepend line execution counts and branch probabilities to a
    source file.
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by James E. Wilson of Cygnus Support.
    Mangled by Bob Manson of Cygnus Support.
    Mangled further by Nathan Sidwell <nathan@codesourcery.com>
@@ -47,7 +47,6 @@ Boston, MA 02111-1307, USA.  */
 #include "tm.h"
 #include "intl.h"
 #include "version.h"
-#undef abort
 
 #include <getopt.h>
 
@@ -82,6 +81,8 @@ typedef struct arc_info
 
   /* transition counts.  */
   gcov_type count;
+  /* used in cycle search, so that we do not clobber original counts.  */
+  gcov_type cs_count;
 
   unsigned int count_valid : 1;
   unsigned int on_tree : 1;
@@ -371,17 +372,6 @@ fnotice (FILE *file, const char *msgid, ...)
   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 (void) ATTRIBUTE_NORETURN;
-
-void
-fancy_abort (void)
-{
-  fnotice (stderr, "Internal gcov abort.\n");
-  exit (FATAL_EXIT_CODE);
-}
 \f
 /* Print a usage message and exit.  If ERROR_P is nonzero, this is an error,
    otherwise the output of --help.  */
@@ -417,17 +407,13 @@ print_usage (int error_p)
 static void
 print_version (void)
 {
-  char v[4];
-  unsigned version = GCOV_VERSION;
-  unsigned ix;
-
-  for (ix = 4; ix--; version >>= 8)
-    v[ix] = version;
-  fnotice (stdout, "gcov %.4s (GCC %s)\n", v, version_string);
-  fnotice (stdout, "Copyright (C) 2002 Free Software Foundation, Inc.\n");
+  fnotice (stdout, "gcov (GCC) %s\n", version_string);
+  fprintf (stdout, "Copyright %s 2004 Free Software Foundation, Inc.\n",
+          _("(C)"));
   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");
+          _("This is free software; see the source for copying conditions.\n"
+            "There is NO warranty; not even for MERCHANTABILITY or \n"
+            "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
   exit (SUCCESS_EXIT_CODE);
 }
 
@@ -525,7 +511,7 @@ process_file (const char *file_name)
   for (fn = functions; fn; fn = fn->next)
     solve_flow_graph (fn);
   for (src = sources; src; src = src->next)
-    src->lines = (line_t *) xcalloc (src->num_lines, sizeof (line_t));
+    src->lines = xcalloc (src->num_lines, sizeof (line_t));
   for (fn = functions; fn; fn = fn->next)
     {
       coverage_t coverage;
@@ -660,10 +646,10 @@ create_file_names (const char *file_name)
     *cptr = 0;
 
   length = strlen (name);
-
-  bbg_file_name = xmalloc (length + strlen (GCOV_GRAPH_SUFFIX) + 1);
+  
+  bbg_file_name = xmalloc (length + strlen (GCOV_NOTE_SUFFIX) + 1);
   strcpy (bbg_file_name, name);
-  strcpy (bbg_file_name + length, GCOV_GRAPH_SUFFIX);
+  strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
 
   da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
   strcpy (da_file_name, name);
@@ -687,7 +673,7 @@ find_source (const char *file_name)
     if (!strcmp (file_name, src->name))
       return src;
 
-  src = (source_t *)xcalloc (1, sizeof (source_t));
+  src = xcalloc (1, sizeof (source_t));
   src->name = xstrdup (file_name);
   src->coverage.name = src->name;
   src->index = sources ? sources->index + 1 : 1;
@@ -715,7 +701,7 @@ read_graph_file (void)
       return 1;
     }
   bbg_file_time = gcov_time ();
-  if (gcov_read_unsigned () != GCOV_GRAPH_MAGIC)
+  if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
     {
       fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
       gcov_close ();
@@ -726,13 +712,10 @@ read_graph_file (void)
   if (version != GCOV_VERSION)
     {
       char v[4], e[4];
-      unsigned required = GCOV_VERSION;
 
-      for (ix = 4; ix--; required >>= 8, version >>= 8)
-       {
-         v[ix] = version;
-         e[ix] = required;
-       }
+      GCOV_UNSIGNED2STRING (v, version);
+      GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
+
       fnotice (stderr, "%s:version `%.4s', prefer `%.4s'\n",
               bbg_file_name, v, e);
     }
@@ -756,7 +739,7 @@ read_graph_file (void)
          src = find_source (gcov_read_string ());
          lineno = gcov_read_unsigned ();
 
-         fn = (function_t *)xcalloc (1, sizeof (function_t));
+         fn = xcalloc (1, sizeof (function_t));
          fn->name = function_name;
          fn->ident = ident;
          fn->checksum = checksum;
@@ -789,11 +772,10 @@ read_graph_file (void)
                     bbg_file_name, fn->name);
          else
            {
-             unsigned ix, num_blocks = length / 4;
+             unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
              fn->num_blocks = num_blocks;
 
-             fn->blocks
-               = (block_t *)xcalloc (fn->num_blocks, sizeof (block_t));
+             fn->blocks = xcalloc (fn->num_blocks, sizeof (block_t));
              for (ix = 0; ix != num_blocks; ix++)
                fn->blocks[ix].flags = gcov_read_unsigned ();
            }
@@ -801,7 +783,7 @@ read_graph_file (void)
       else if (fn && tag == GCOV_TAG_ARCS)
        {
          unsigned src = gcov_read_unsigned ();
-         unsigned num_dests = (length - 4) / 8;
+         unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
 
          if (src >= fn->num_blocks || fn->blocks[src].succ)
            goto corrupt;
@@ -814,7 +796,7 @@ read_graph_file (void)
 
              if (dest >= fn->num_blocks)
                goto corrupt;
-             arc = (arc_t *) xcalloc (1, sizeof (arc_t));
+             arc = xcalloc (1, sizeof (arc_t));
 
              arc->dst = &fn->blocks[dest];
              arc->src = &fn->blocks[src];
@@ -859,8 +841,7 @@ read_graph_file (void)
       else if (fn && tag == GCOV_TAG_LINES)
        {
          unsigned blockno = gcov_read_unsigned ();
-         unsigned *line_nos
-           = (unsigned *)xcalloc ((length - 4) / 4, sizeof (unsigned));
+         unsigned *line_nos = xcalloc (length - 1, sizeof (unsigned));
 
          if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
            goto corrupt;
@@ -903,18 +884,16 @@ read_graph_file (void)
        }
       gcov_sync (base, length);
       if (gcov_is_error ())
-       break;
-    }
-  if (!gcov_is_eof ())
-    {
-    corrupt:;
-      fnotice (stderr, "%s:corrupted\n", bbg_file_name);
-      gcov_close ();
-      return 1;
+       {
+       corrupt:;
+         fnotice (stderr, "%s:corrupted\n", bbg_file_name);
+         gcov_close ();
+         return 1;
+       }
     }
   gcov_close ();
 
-  /* We built everything backwards, so nreverse them all */
+  /* We built everything backwards, so nreverse them all */
 
   /* Reverse sources. Not strictly necessary, but we'll then process
      them in the 'expected' order.  */
@@ -984,7 +963,7 @@ read_count_file (void)
       fnotice (stderr, "%s:cannot open data file\n", da_file_name);
       return 1;
     }
-  if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
+  if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
     {
       fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
     cleanup:;
@@ -995,13 +974,10 @@ read_count_file (void)
   if (version != GCOV_VERSION)
     {
       char v[4], e[4];
-      unsigned desired = GCOV_VERSION;
 
-      for (ix = 4; ix--; desired >>= 8, version >>= 8)
-       {
-         v[ix] = version;
-         e[ix] = desired;
-       }
+      GCOV_UNSIGNED2STRING (v, version);
+      GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
+      
       fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
               da_file_name, v, e);
     }
@@ -1054,26 +1030,22 @@ read_count_file (void)
        }
       else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
        {
-         if (length != 8 * fn->num_counts)
+         if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
            goto mismatch;
 
          if (!fn->counts)
-           fn->counts
-             = (gcov_type *)xcalloc (fn->num_counts, sizeof (gcov_type));
+           fn->counts = xcalloc (fn->num_counts, sizeof (gcov_type));
 
          for (ix = 0; ix != fn->num_counts; ix++)
            fn->counts[ix] += gcov_read_counter ();
        }
       gcov_sync (base, length);
       if ((error = gcov_is_error ()))
-       break;
-    }
-
-  if (!gcov_is_eof ())
-    {
-      fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
-              da_file_name);
-      goto cleanup;
+       {
+         fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
+                  da_file_name);
+         goto cleanup;
+       }
     }
 
   gcov_close ();
@@ -1402,7 +1374,7 @@ function_summary (const coverage_t *coverage, const char *title)
             format_gcov (coverage->lines_executed, coverage->lines, 2),
             coverage->lines);
   else
-    fnotice (stdout, "No executable lines");
+    fnotice (stdout, "No executable lines\n");
 
   if (flag_branches)
     {
@@ -1501,7 +1473,7 @@ static void
 add_line_counts (coverage_t *coverage, function_t *fn)
 {
   unsigned ix;
-  line_t *line = NULL; /* this is propagated from one iteration to the
+  line_t *line = NULL; /* This is propagated from one iteration to the
                          next.  */
 
   /* Scan each basic block.  */
@@ -1636,6 +1608,10 @@ accumulate_line_counts (source_t *src)
                  if (flag_branches)
                    add_branch_counts (&src->coverage, arc);
                }
+
+             /* Initialize the cs_count.  */
+             for (arc = block->succ; arc; arc = arc->succ_next)
+               arc->cs_count = arc->count;
            }
 
          /* Find the loops. This uses the algorithm described in
@@ -1652,7 +1628,8 @@ accumulate_line_counts (source_t *src)
 
             For each loop we find, locate the arc with the smallest
             transition count, and add that to the cumulative
-            count. Remove the arc from consideration.  */
+            count.  Decrease flow over the cycle and remove the arc
+            from consideration.  */
          for (block = line->u.blocks; block; block = block->chain)
            {
              block_t *head = block;
@@ -1678,25 +1655,33 @@ accumulate_line_counts (source_t *src)
                  if (dst == block)
                    {
                      /* Found a closing arc.  */
-                     gcov_type cycle_count = arc->count;
+                     gcov_type cycle_count = arc->cs_count;
                      arc_t *cycle_arc = arc;
                      arc_t *probe_arc;
 
                      /* Locate the smallest arc count of the loop.  */
                      for (dst = head; (probe_arc = dst->u.cycle.arc);
                           dst = probe_arc->src)
-                       if (cycle_count > probe_arc->count)
+                       if (cycle_count > probe_arc->cs_count)
                          {
-                           cycle_count = probe_arc->count;
+                           cycle_count = probe_arc->cs_count;
                            cycle_arc = probe_arc;
                          }
 
                      count += cycle_count;
                      cycle_arc->cycle = 1;
+
+                     /* Remove the flow from the cycle.  */
+                     arc->cs_count -= cycle_count;
+                     for (dst = head; (probe_arc = dst->u.cycle.arc);
+                          dst = probe_arc->src)
+                       probe_arc->cs_count -= cycle_count;
+
                      /* Unwind to the cyclic arc.  */
                      while (head != cycle_arc->src)
                        {
                          arc = head->u.cycle.arc;
+                         head->u.cycle.arc = NULL;
                          head = arc->src;
                        }
                      /* Move on.  */
@@ -1736,7 +1721,7 @@ accumulate_line_counts (source_t *src)
     }
 }
 
-/* Ouput information about ARC number IX.  Returns nonzero if
+/* Output information about ARC number IX.  Returns nonzero if
    anything is output.  */
 
 static int