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:
parent
b18e284e3c
commit
1a9075e289
@ -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.
|
||||
|
@ -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
|
||||
|
162
gcc/gcov.c
162
gcc/gcov.c
@ -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;
|
||||
|
||||
process_file (argv[argno]);
|
||||
}
|
||||
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,20 +701,42 @@ 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;
|
||||
|
||||
src = XCNEW (source_t);
|
||||
src->name = xstrdup (file_name);
|
||||
src->coverage.name = src->name;
|
||||
src->index = sources ? sources->index + 1 : 1;
|
||||
src->next = sources;
|
||||
sources = src;
|
||||
if (!src)
|
||||
{
|
||||
src = XCNEW (source_t);
|
||||
src->name = xstrdup (file_name);
|
||||
src->coverage.name = src->name;
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user