/* 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>
#include "tm.h"
#include "intl.h"
#include "version.h"
-#undef abort
#include <getopt.h>
/* 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;
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. */
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);
}
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;
*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);
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;
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 ();
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);
}
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;
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 ();
}
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;
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];
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;
}
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. */
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:;
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);
}
}
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 ();
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)
{
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. */
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
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;
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. */
}
}
-/* Ouput information about ARC number IX. Returns nonzero if
+/* Output information about ARC number IX. Returns nonzero if
anything is output. */
static int