gcov.c: Comments updated.

* gcov.c: Comments updated.
	(source_info): Add file_time field.
	(source_index): New variable.
	(mutiple_files): New variable.
	(generate_results): New function extracted from process_file.
	(process_file): Save and restore chain of functions, generate
	results and free structures only if not merging results.
	(release_structures): File names are now freed in create_file_names
	(create_file_names): Free previous file names.
	(find_source): File date is now read here and modifications in
	source files is checked here.
	(read_graph_file): Only reverse order of functions for the current
	object file.
	(make_gcov_file_name): Do not generate long names if input_name is
	NULL.
	(output_lines): If merging results do not display graph, data and 
	runs informations.
	Checking source file modification is done in find_source.

	* doc/gcov.texi: Append an s to sourcefile.

From-SVN: r125649
This commit is contained in:
Tristan Gingold 2007-06-12 15:39:15 +00:00 committed by Olivier Hainque
parent b18e284e3c
commit 1a9075e289
3 changed files with 133 additions and 56 deletions

View File

@ -1,3 +1,26 @@
2007-06-12 Tristan Gingold <gingold@adacore.com>
* gcov.c: Comments updated.
(source_info): Add file_time field.
(source_index): New variable.
(mutiple_files): New variable.
(generate_results): New function extracted from process_file.
(process_file): Save and restore chain of functions, generate
results and free structures only if not merging results.
(release_structures): File names are now freed in create_file_names
(create_file_names): Free previous file names.
(find_source): File date is now read here and modifications in
source files is checked here.
(read_graph_file): Only reverse order of functions for the current
object file.
(make_gcov_file_name): Do not generate long names if input_name is
NULL.
(output_lines): If merging results do not display graph, data and
runs informations.
Checking source file modification is done in find_source.
* doc/gcov.texi: Append an s to sourcefile.
2007-06-12 Bernd Schmidt <bernd.schmidt@analog.com>
* config/bfin/bfin.md (UNSPEC_NOP): New constant.

View File

@ -113,7 +113,7 @@ compatible with any other profiling or test coverage mechanism.
@section Invoking @command{gcov}
@smallexample
gcov @r{[}@var{options}@r{]} @var{sourcefile}
gcov @r{[}@var{options}@r{]} @var{sourcefiles}
@end smallexample
@command{gcov} accepts the following options:
@ -128,7 +128,7 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}]
[@option{-l}|@option{--long-file-names}]
[@option{-p}|@option{--preserve-paths}]
[@option{-f}|@option{--function-summaries}]
[@option{-o}|@option{--object-directory} @var{directory|file}] @var{sourcefile}
[@option{-o}|@option{--object-directory} @var{directory|file}] @var{sourcefiles}
[@option{-u}|@option{--unconditional-branches}]
@c man end
@c man begin SEEALSO

View File

@ -29,15 +29,6 @@ Boston, MA 02110-1301, USA. */
/* ??? Should have an option to print the number of basic blocks, and the
percent of them that are covered. */
/* ??? Does not correctly handle the case where two .bb files refer to
the same included source file. For example, if one has a short
file containing only inline functions, which is then included in
two other files, then there will be two .bb files which refer to
the include file, but there is no way to get the total execution
counts for the included file, can only get execution counts for one
or the other of the including files. this can be fixed by --ratios
--long-file-names --preserve-paths and perl. */
/* Need an option to show individual block counts, and show
probabilities of fall through arcs. */
@ -54,7 +45,7 @@ Boston, MA 02110-1301, USA. */
#include "gcov-io.h"
#include "gcov-io.c"
/* The bbg file is generated by -ftest-coverage option. The da file is
/* The gcno file is generated by -ftest-coverage option. The gcda file is
generated by a program compiled with -fprofile-arcs. Their formats
are documented in gcov-io.h. */
@ -234,6 +225,7 @@ typedef struct source_info
/* Name of source file. */
char *name;
unsigned index;
time_t file_time;
/* Array of line information. */
line_t *lines;
@ -253,10 +245,15 @@ typedef struct source_info
static function_t *functions;
/* This points to the head of the sourcefile structure list. */
/* This points to the head of the sourcefile structure list. New elements
are always prepended. */
static source_t *sources;
/* Next index for a source file. */
static unsigned source_index;
/* This holds data summary information. */
static struct gcov_summary object_summary;
@ -281,6 +278,13 @@ static char *da_file_name;
static int no_data_file;
/* If there is several input files, compute and display results after
reading all data files. This way if two or more gcda file refer to
the same source file (eg inline subprograms in a .h file), the
counts are added. */
static int multiple_files = 0;
/* Output branch probabilities. */
static int flag_branches = 0;
@ -330,6 +334,7 @@ static int process_args (int, char **);
static void print_usage (int) ATTRIBUTE_NORETURN;
static void print_version (void) ATTRIBUTE_NORETURN;
static void process_file (const char *);
static void generate_results (const char *);
static void create_file_names (const char *);
static source_t *find_source (const char *);
static int read_graph_file (void);
@ -360,12 +365,15 @@ main (int argc, char **argv)
if (optind == argc)
print_usage (true);
for (; argno != argc; argno++)
{
release_structures ();
if (argc - argno > 1)
multiple_files = 1;
for (; argno != argc; argno++)
process_file (argv[argno]);
}
generate_results (multiple_files ? NULL : argv[argc - 1]);
release_structures ();
return 0;
}
@ -389,7 +397,7 @@ print_usage (int error_p)
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, "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");
@ -499,8 +507,14 @@ process_args (int argc, char **argv)
static void
process_file (const char *file_name)
{
source_t *src;
function_t *fn;
function_t *fn_p;
function_t *old_functions;
/* Save and clear the list of current functions. They will be appended
later. */
old_functions = functions;
functions = NULL;
create_file_names (file_name);
if (read_graph_file ())
@ -515,8 +529,19 @@ process_file (const char *file_name)
if (read_count_file ())
return;
for (fn = functions; fn; fn = fn->next)
for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn->next)
solve_flow_graph (fn);
if (fn_p)
fn_p->next = old_functions;
}
static void
generate_results (const char *file_name)
{
source_t *src;
function_t *fn;
for (src = sources; src; src = src->next)
src->lines = XCNEWVEC (line_t, src->num_lines);
for (fn = functions; fn; fn = fn->next)
@ -569,12 +594,6 @@ release_structures (void)
function_t *fn;
source_t *src;
free (bbg_file_name);
free (da_file_name);
da_file_name = bbg_file_name = NULL;
bbg_file_time = 0;
bbg_stamp = 0;
while ((src = sources))
{
sources = src->next;
@ -620,6 +639,15 @@ create_file_names (const char *file_name)
int length = strlen (file_name);
int base;
/* Free previous file names. */
if (bbg_file_name)
free (bbg_file_name);
if (da_file_name)
free (da_file_name);
da_file_name = bbg_file_name = NULL;
bbg_file_time = 0;
bbg_stamp = 0;
if (object_directory && object_directory[0])
{
struct stat status;
@ -673,21 +701,43 @@ static source_t *
find_source (const char *file_name)
{
source_t *src;
struct stat status;
if (!file_name)
file_name = "<unknown>";
for (src = sources; src; src = src->next)
if (!strcmp (file_name, src->name))
return src;
break;
if (!src)
{
src = XCNEW (source_t);
src->name = xstrdup (file_name);
src->coverage.name = src->name;
src->index = sources ? sources->index + 1 : 1;
src->index = source_index++;
src->next = sources;
sources = src;
if (!stat (file_name, &status))
src->file_time = status.st_mtime;
}
if (src->file_time > bbg_file_time)
{
static int info_emitted;
fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
src->name, bbg_file_name);
if (!info_emitted)
{
fnotice (stderr,
"(the message is only displayed one per source file)\n");
info_emitted = 1;
}
src->file_time = 0;
}
return src;
}
@ -699,6 +749,7 @@ read_graph_file (void)
unsigned version;
unsigned current_tag = 0;
struct function_info *fn = NULL;
function_t *old_functions_head = functions;
source_t *src = NULL;
unsigned ix;
unsigned tag;
@ -920,7 +971,9 @@ read_graph_file (void)
{
function_t *fn, *fn_p, *fn_n;
for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
for (fn_p = old_functions_head, fn = functions;
fn != old_functions_head;
fn_p = fn, fn = fn_n)
{
unsigned ix;
@ -1012,6 +1065,9 @@ read_count_file (void)
unsigned ident = gcov_read_unsigned ();
struct function_info *fn_n = functions;
/* Try to find the function in the list.
To speed up the search, first start from the last function
found. */
for (fn = fn ? fn->next : NULL; ; fn = fn->next)
{
if (fn)
@ -1424,16 +1480,22 @@ static char *
make_gcov_file_name (const char *input_name, const char *src_name)
{
char *cptr;
char *name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
char *name;
name[0] = 0;
if (flag_long_names && strcmp (src_name, input_name))
if (flag_long_names && input_name && strcmp (src_name, input_name))
{
name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
name[0] = 0;
/* Generate the input filename part. */
cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
strcat (name, cptr ? cptr + 1 : input_name);
strcat (name, "##");
}
else
{
name = XNEWVEC (char, strlen (src_name) + 10);
name[0] = 0;
}
/* Generate the source filename part. */
cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
@ -1787,11 +1849,14 @@ output_lines (FILE *gcov_file, const source_t *src)
function_t *fn = NULL;
fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
if (!multiple_files)
{
fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
no_data_file ? "-" : da_file_name);
fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
}
fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
source_file = fopen (src->name, "r");
@ -1800,19 +1865,8 @@ output_lines (FILE *gcov_file, const source_t *src)
fnotice (stderr, "%s:cannot open source file\n", src->name);
retval = NULL;
}
else
{
struct stat status;
if (!fstat (fileno (source_file), &status)
&& status.st_mtime > bbg_file_time)
{
fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
src->name, bbg_file_name);
fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
"-", 0);
}
}
else if (src->file_time == 0)
fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
if (flag_branches)
fn = src->functions;