]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gcov.c
files.c (file_hash_eq): Use filename_cmp instead of strcmp.
[thirdparty/gcc.git] / gcc / gcov.c
CommitLineData
86144b75
DE
1/* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
a6d6c2c0 3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
9f8e43c0 4 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
0e5997c0 5 Free Software Foundation, Inc.
86144b75 6 Contributed by James E. Wilson of Cygnus Support.
1d300e19 7 Mangled by Bob Manson of Cygnus Support.
4977bab6 8 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
86144b75
DE
9
10Gcov is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
9dcd6f09 12the Free Software Foundation; either version 3, or (at your option)
86144b75
DE
13any later version.
14
15Gcov is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
9dcd6f09
NC
21along with Gcov; see the file COPYING3. If not see
22<http://www.gnu.org/licenses/>. */
86144b75 23
86144b75
DE
24/* ??? Print a list of the ten blocks with the highest execution counts,
25 and list the line numbers corresponding to those blocks. Also, perhaps
26 list the line numbers with the highest execution counts, only printing
27 the first if there are several which are all listed in the same block. */
28
29/* ??? Should have an option to print the number of basic blocks, and the
30 percent of them that are covered. */
31
4977bab6
ZW
32/* Need an option to show individual block counts, and show
33 probabilities of fall through arcs. */
86144b75 34
1d300e19 35#include "config.h"
b04cd507 36#include "system.h"
4977bab6
ZW
37#include "coretypes.h"
38#include "tm.h"
ab87f8c8 39#include "intl.h"
5735c3ea 40#include "version.h"
86144b75 41
5735c3ea
JM
42#include <getopt.h>
43
546d2adb 44#define IN_GCOV 1
86144b75 45#include "gcov-io.h"
d79f9ec9 46#include "gcov-io.c"
86144b75 47
1a9075e2 48/* The gcno file is generated by -ftest-coverage option. The gcda file is
4977bab6
ZW
49 generated by a program compiled with -fprofile-arcs. Their formats
50 are documented in gcov-io.h. */
86144b75
DE
51
52/* The functions in this file for creating and solution program flow graphs
4977bab6
ZW
53 are very similar to functions in the gcc source file profile.c. In
54 some places we make use of the knowledge of how profile.c works to
55 select particular algorithms here. */
86144b75 56
86144b75
DE
57/* This is the size of the buffer used to read in source file lines. */
58
59#define STRING_SIZE 200
60
4977bab6
ZW
61struct function_info;
62struct block_info;
27283c73 63struct source_info;
86144b75 64
4977bab6 65/* Describes an arc between two basic blocks. */
86144b75 66
4977bab6
ZW
67typedef struct arc_info
68{
32dd366d 69 /* source and destination blocks. */
4977bab6
ZW
70 struct block_info *src;
71 struct block_info *dst;
86144b75 72
4977bab6
ZW
73 /* transition counts. */
74 gcov_type count;
3d7ca167
ZD
75 /* used in cycle search, so that we do not clobber original counts. */
76 gcov_type cs_count;
86144b75 77
86144b75
DE
78 unsigned int count_valid : 1;
79 unsigned int on_tree : 1;
80 unsigned int fake : 1;
81 unsigned int fall_through : 1;
86144b75 82
27283c73
NS
83 /* Arc is for a function that abnormally returns. */
84 unsigned int is_call_non_return : 1;
85
fa10beec 86 /* Arc is for catch/setjmp. */
27283c73
NS
87 unsigned int is_nonlocal_return : 1;
88
89 /* Is an unconditional branch. */
90 unsigned int is_unconditional : 1;
91
10b7602f
NS
92 /* Loop making arc. */
93 unsigned int cycle : 1;
94
4977bab6
ZW
95 /* Next branch on line. */
96 struct arc_info *line_next;
f55ade6e 97
4977bab6
ZW
98 /* Links to next arc on src and dst lists. */
99 struct arc_info *succ_next;
100 struct arc_info *pred_next;
101} arc_t;
86144b75 102
4977bab6
ZW
103/* Describes a basic block. Contains lists of arcs to successor and
104 predecessor blocks. */
86144b75 105
4977bab6 106typedef struct block_info
86144b75 107{
4977bab6
ZW
108 /* Chain of exit and entry arcs. */
109 arc_t *succ;
110 arc_t *pred;
111
32dd366d 112 /* Number of unprocessed exit and entry arcs. */
4977bab6
ZW
113 gcov_type num_succ;
114 gcov_type num_pred;
115
32dd366d 116 /* Block execution count. */
4977bab6 117 gcov_type count;
27283c73 118 unsigned flags : 13;
4977bab6
ZW
119 unsigned count_valid : 1;
120 unsigned valid_chain : 1;
121 unsigned invalid_chain : 1;
122
27283c73 123 /* Block is a call instrumenting site. */
10b7602f
NS
124 unsigned is_call_site : 1; /* Does the call. */
125 unsigned is_call_return : 1; /* Is the return. */
4977bab6 126
27283c73
NS
127 /* Block is a landing pad for longjmp or throw. */
128 unsigned is_nonlocal_return : 1;
129
130 union
131 {
132 struct
133 {
134 /* Array of line numbers and source files. source files are
135 introduced by a linenumber of zero, the next 'line number' is
136 the number of the source file. Always starts with a source
137 file. */
138 unsigned *encoding;
139 unsigned num;
140 } line; /* Valid until blocks are linked onto lines */
141 struct
142 {
10b7602f 143 /* Single line graph cycle workspace. Used for all-blocks
71c0e7fc 144 mode. */
10b7602f
NS
145 arc_t *arc;
146 unsigned ident;
147 } cycle; /* Used in all-blocks mode, after blocks are linked onto
71c0e7fc 148 lines. */
27283c73
NS
149 } u;
150
151 /* Temporary chain for solving graph, and for chaining blocks on one
152 line. */
4977bab6 153 struct block_info *chain;
f55ade6e 154
4977bab6 155} block_t;
86144b75 156
4977bab6 157/* Describes a single function. Contains an array of basic blocks. */
86144b75 158
4977bab6 159typedef struct function_info
8b219a76 160{
4977bab6
ZW
161 /* Name of function. */
162 char *name;
796621e8 163 unsigned ident;
4977bab6 164 unsigned checksum;
86144b75 165
4977bab6
ZW
166 /* Array of basic blocks. */
167 block_t *blocks;
168 unsigned num_blocks;
27283c73 169 unsigned blocks_executed;
4977bab6
ZW
170
171 /* Raw arc coverage counts. */
172 gcov_type *counts;
173 unsigned num_counts;
27283c73
NS
174
175 /* First line number. */
176 unsigned line;
177 struct source_info *src;
178
179 /* Next function in same source file. */
180 struct function_info *line_next;
f55ade6e 181
4977bab6
ZW
182 /* Next function. */
183 struct function_info *next;
184} function_t;
185
186/* Describes coverage of a file or function. */
187
188typedef struct coverage_info
8b219a76
NS
189{
190 int lines;
191 int lines_executed;
f55ade6e 192
8b219a76
NS
193 int branches;
194 int branches_executed;
195 int branches_taken;
f55ade6e 196
8b219a76
NS
197 int calls;
198 int calls_executed;
f55ade6e 199
8b219a76 200 char *name;
4977bab6 201} coverage_t;
8b219a76 202
4977bab6
ZW
203/* Describes a single line of source. Contains a chain of basic blocks
204 with code on it. */
86144b75 205
4977bab6
ZW
206typedef struct line_info
207{
208 gcov_type count; /* execution count */
27283c73
NS
209 union
210 {
f55ade6e 211 arc_t *branches; /* branches from blocks that end on this
27283c73 212 line. Used for branch-counts when not
71c0e7fc 213 all-blocks mode. */
27283c73 214 block_t *blocks; /* blocks which start on this line. Used
71c0e7fc 215 in all-blocks mode. */
27283c73 216 } u;
4977bab6
ZW
217 unsigned exists : 1;
218} line_t;
86144b75 219
4977bab6
ZW
220/* Describes a file mentioned in the block graph. Contains an array
221 of line info. */
37b8715b 222
4977bab6
ZW
223typedef struct source_info
224{
225 /* Name of source file. */
226 char *name;
227 unsigned index;
1a9075e2 228 time_t file_time;
37b8715b 229
32dd366d 230 /* Array of line information. */
4977bab6
ZW
231 line_t *lines;
232 unsigned num_lines;
86144b75 233
4977bab6 234 coverage_t coverage;
27283c73
NS
235
236 /* Functions in this source file. These are in ascending line
237 number order. */
238 function_t *functions;
f55ade6e 239
4977bab6
ZW
240 /* Next source file. */
241 struct source_info *next;
242} source_t;
86144b75 243
4977bab6 244/* Holds a list of function basic block graphs. */
86144b75 245
4977bab6 246static function_t *functions;
86144b75 247
1a9075e2
TG
248/* This points to the head of the sourcefile structure list. New elements
249 are always prepended. */
86144b75 250
4977bab6 251static source_t *sources;
86144b75 252
1a9075e2
TG
253/* Next index for a source file. */
254
255static unsigned source_index;
256
27283c73
NS
257/* This holds data summary information. */
258
259static struct gcov_summary object_summary;
260static unsigned program_count;
261
32dd366d 262/* Modification time of graph file. */
86144b75 263
4977bab6 264static time_t bbg_file_time;
86144b75 265
4977bab6 266/* Name and file pointer of the input file for the basic block graph. */
86144b75 267
4977bab6 268static char *bbg_file_name;
86144b75 269
dd486eb2
NS
270/* Stamp of the bbg file */
271static unsigned bbg_stamp;
272
4977bab6 273/* Name and file pointer of the input file for the arc count data. */
86144b75 274
4977bab6 275static char *da_file_name;
86144b75 276
80b3502b
NS
277/* Data file is missing. */
278
279static int no_data_file;
280
1a9075e2
TG
281/* If there is several input files, compute and display results after
282 reading all data files. This way if two or more gcda file refer to
283 the same source file (eg inline subprograms in a .h file), the
284 counts are added. */
285
286static int multiple_files = 0;
287
4977bab6 288/* Output branch probabilities. */
86144b75 289
4977bab6 290static int flag_branches = 0;
86144b75 291
f55ade6e 292/* Show unconditional branches too. */
27283c73
NS
293static int flag_unconditional = 0;
294
86144b75
DE
295/* Output a gcov file if this is true. This is on by default, and can
296 be turned off by the -n option. */
297
4977bab6 298static int flag_gcov_file = 1;
86144b75 299
acdb4da7
NS
300/* Output progress indication if this is true. This is off by default
301 and can be turned on by the -d option. */
302
303static int flag_display_progress = 0;
304
4977bab6
ZW
305/* For included files, make the gcov output file name include the name
306 of the input source file. For example, if x.h is included in a.c,
307 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
86144b75 308
4977bab6 309static int flag_long_names = 0;
86144b75 310
27283c73
NS
311/* Output count information for every basic block, not merely those
312 that contain line number information. */
313
314static int flag_all_blocks = 0;
315
86144b75
DE
316/* Output summary info for each function. */
317
4977bab6 318static int flag_function_summary = 0;
86144b75 319
4977bab6
ZW
320/* Object directory file prefix. This is the directory/file where the
321 graph and data files are looked for, if nonzero. */
86144b75
DE
322
323static char *object_directory = 0;
324
37b8715b 325/* Preserve all pathname components. Needed when object files and
4977bab6
ZW
326 source files are in subdirectories. '/' is mangled as '#', '.' is
327 elided and '..' mangled to '^'. */
328
329static int flag_preserve_paths = 0;
37b8715b 330
8bfa6fc5 331/* Output the number of times a branch was taken as opposed to the percentage
32dd366d 332 of times it was taken. */
23190837 333
4977bab6 334static int flag_counts = 0;
8bfa6fc5 335
86144b75 336/* Forward declarations. */
f55ade6e
AJ
337static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
338static int process_args (int, char **);
339static void print_usage (int) ATTRIBUTE_NORETURN;
340static void print_version (void) ATTRIBUTE_NORETURN;
341static void process_file (const char *);
1a9075e2 342static void generate_results (const char *);
f55ade6e
AJ
343static void create_file_names (const char *);
344static source_t *find_source (const char *);
345static int read_graph_file (void);
346static int read_count_file (void);
347static void solve_flow_graph (function_t *);
348static void add_branch_counts (coverage_t *, const arc_t *);
349static void add_line_counts (coverage_t *, function_t *);
350static void function_summary (const coverage_t *, const char *);
351static const char *format_gcov (gcov_type, gcov_type, int);
352static void accumulate_line_counts (source_t *);
353static int output_branch_count (FILE *, int, const arc_t *);
354static void output_lines (FILE *, const source_t *);
355static char *make_gcov_file_name (const char *, const char *);
356static void release_structures (void);
357extern int main (int, char **);
86144b75
DE
358
359int
f55ade6e 360main (int argc, char **argv)
86144b75 361{
4977bab6 362 int argno;
acdb4da7 363 int first_arg;
f55ade6e 364
98a3dad4 365 /* Unlock the stdio streams. */
2653bb0c 366 unlock_std_streams ();
98a3dad4 367
191bf464 368 gcc_init_libintl ();
ab87f8c8 369
e3536b82
TG
370 /* Handle response files. */
371 expandargv (&argc, &argv);
372
4977bab6
ZW
373 argno = process_args (argc, argv);
374 if (optind == argc)
375 print_usage (true);
86144b75 376
1a9075e2
TG
377 if (argc - argno > 1)
378 multiple_files = 1;
379
acdb4da7
NS
380 first_arg = argno;
381
4977bab6 382 for (; argno != argc; argno++)
acdb4da7
NS
383 {
384 if (flag_display_progress)
385 printf("Processing file %d out of %d\n",
386 argno - first_arg + 1, argc - first_arg);
387 process_file (argv[argno]);
388 }
f55ade6e 389
1a9075e2
TG
390 generate_results (multiple_files ? NULL : argv[argc - 1]);
391
392 release_structures ();
f55ade6e 393
86144b75
DE
394 return 0;
395}
396
ab87f8c8 397static void
4b794eaf 398fnotice (FILE *file, const char *cmsgid, ...)
ab87f8c8 399{
e34d07f2 400 va_list ap;
f55ade6e 401
4b794eaf
JJ
402 va_start (ap, cmsgid);
403 vfprintf (file, _(cmsgid), ap);
e34d07f2 404 va_end (ap);
ab87f8c8 405}
86144b75 406\f
5735c3ea
JM
407/* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
408 otherwise the output of --help. */
86144b75
DE
409
410static void
f55ade6e 411print_usage (int error_p)
86144b75 412{
5735c3ea
JM
413 FILE *file = error_p ? stderr : stdout;
414 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
f55ade6e 415
1a9075e2 416 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
5735c3ea
JM
417 fnotice (file, "Print code coverage information.\n\n");
418 fnotice (file, " -h, --help Print this help, then exit\n");
419 fnotice (file, " -v, --version Print version number, then exit\n");
27283c73 420 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
5735c3ea
JM
421 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
422 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
423 rather than percentages\n");
424 fnotice (file, " -n, --no-output Do not create an output file\n");
425 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
426 source files\n");
427 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
37b8715b
NS
428 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
429 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
27283c73 430 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
acdb4da7 431 fnotice (file, " -d, --display-progress Display progress information\n");
5735c3ea 432 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
a976603e 433 bug_report_url);
5735c3ea
JM
434 exit (status);
435}
436
437/* Print version information and exit. */
438
439static void
f55ade6e 440print_version (void)
5735c3ea 441{
2f41c1d6 442 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
9f8e43c0 443 fprintf (stdout, "Copyright %s 2011 Free Software Foundation, Inc.\n",
9f76f909 444 _("(C)"));
5735c3ea 445 fnotice (stdout,
9f76f909
KH
446 _("This is free software; see the source for copying conditions.\n"
447 "There is NO warranty; not even for MERCHANTABILITY or \n"
448 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
5735c3ea 449 exit (SUCCESS_EXIT_CODE);
86144b75
DE
450}
451
5735c3ea
JM
452static const struct option options[] =
453{
454 { "help", no_argument, NULL, 'h' },
455 { "version", no_argument, NULL, 'v' },
27283c73 456 { "all-blocks", no_argument, NULL, 'a' },
5735c3ea
JM
457 { "branch-probabilities", no_argument, NULL, 'b' },
458 { "branch-counts", no_argument, NULL, 'c' },
459 { "no-output", no_argument, NULL, 'n' },
460 { "long-file-names", no_argument, NULL, 'l' },
461 { "function-summaries", no_argument, NULL, 'f' },
37b8715b
NS
462 { "preserve-paths", no_argument, NULL, 'p' },
463 { "object-directory", required_argument, NULL, 'o' },
464 { "object-file", required_argument, NULL, 'o' },
27283c73 465 { "unconditional-branches", no_argument, NULL, 'u' },
acdb4da7 466 { "display-progress", no_argument, NULL, 'd' },
d90f9882 467 { 0, 0, 0, 0 }
5735c3ea
JM
468};
469
4977bab6 470/* Process args, return index to first non-arg. */
86144b75 471
4977bab6 472static int
f55ade6e 473process_args (int argc, char **argv)
86144b75 474{
5735c3ea 475 int opt;
86144b75 476
acdb4da7 477 while ((opt = getopt_long (argc, argv, "abcdfhlno:puv", options, NULL)) != -1)
86144b75 478 {
5735c3ea 479 switch (opt)
86144b75 480 {
27283c73
NS
481 case 'a':
482 flag_all_blocks = 1;
483 break;
5735c3ea 484 case 'b':
4977bab6 485 flag_branches = 1;
5735c3ea
JM
486 break;
487 case 'c':
4977bab6 488 flag_counts = 1;
5735c3ea 489 break;
27283c73
NS
490 case 'f':
491 flag_function_summary = 1;
5735c3ea 492 break;
27283c73
NS
493 case 'h':
494 print_usage (false);
495 /* print_usage will exit. */
5735c3ea 496 case 'l':
4977bab6 497 flag_long_names = 1;
5735c3ea 498 break;
27283c73
NS
499 case 'n':
500 flag_gcov_file = 0;
5735c3ea
JM
501 break;
502 case 'o':
503 object_directory = optarg;
504 break;
37b8715b 505 case 'p':
4977bab6 506 flag_preserve_paths = 1;
37b8715b 507 break;
27283c73
NS
508 case 'u':
509 flag_unconditional = 1;
510 break;
acdb4da7
NS
511 case 'd':
512 flag_display_progress = 1;
513 break;
27283c73
NS
514 case 'v':
515 print_version ();
516 /* print_version will exit. */
5735c3ea
JM
517 default:
518 print_usage (true);
519 /* print_usage will exit. */
86144b75 520 }
86144b75
DE
521 }
522
4977bab6
ZW
523 return optind;
524}
525
526/* Process a single source file. */
5735c3ea 527
4977bab6 528static void
f55ade6e 529process_file (const char *file_name)
4977bab6 530{
4977bab6 531 function_t *fn;
1a9075e2
TG
532 function_t *fn_p;
533 function_t *old_functions;
534
535 /* Save and clear the list of current functions. They will be appended
536 later. */
537 old_functions = functions;
538 functions = NULL;
f55ade6e 539
4977bab6
ZW
540 create_file_names (file_name);
541 if (read_graph_file ())
542 return;
f55ade6e 543
4977bab6
ZW
544 if (!functions)
545 {
546 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
547 return;
548 }
f55ade6e 549
4977bab6
ZW
550 if (read_count_file ())
551 return;
f55ade6e 552
1a9075e2 553 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn->next)
4977bab6 554 solve_flow_graph (fn);
1a9075e2
TG
555
556 if (fn_p)
557 fn_p->next = old_functions;
558}
559
560static void
561generate_results (const char *file_name)
562{
563 source_t *src;
564 function_t *fn;
565
4977bab6 566 for (src = sources; src; src = src->next)
5ed6ace5 567 src->lines = XCNEWVEC (line_t, src->num_lines);
4977bab6
ZW
568 for (fn = functions; fn; fn = fn->next)
569 {
570 coverage_t coverage;
f55ade6e 571
4977bab6
ZW
572 memset (&coverage, 0, sizeof (coverage));
573 coverage.name = fn->name;
574 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
575 if (flag_function_summary)
576 {
577 function_summary (&coverage, "Function");
578 fnotice (stdout, "\n");
579 }
580 }
f55ade6e 581
4977bab6
ZW
582 for (src = sources; src; src = src->next)
583 {
584 accumulate_line_counts (src);
585 function_summary (&src->coverage, "File");
586 if (flag_gcov_file)
587 {
588 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
589 FILE *gcov_file = fopen (gcov_file_name, "w");
f55ade6e 590
4977bab6
ZW
591 if (gcov_file)
592 {
9e637a26 593 fnotice (stdout, "%s:creating '%s'\n",
4977bab6
ZW
594 src->name, gcov_file_name);
595 output_lines (gcov_file, src);
596 if (ferror (gcov_file))
9e637a26 597 fnotice (stderr, "%s:error writing output file '%s'\n",
4977bab6
ZW
598 src->name, gcov_file_name);
599 fclose (gcov_file);
600 }
601 else
9e637a26 602 fnotice (stderr, "%s:could not open output file '%s'\n",
4977bab6
ZW
603 src->name, gcov_file_name);
604 free (gcov_file_name);
605 }
606 fnotice (stdout, "\n");
607 }
86144b75
DE
608}
609
4977bab6 610/* Release all memory used. */
86144b75 611
4977bab6 612static void
f55ade6e 613release_structures (void)
4977bab6
ZW
614{
615 function_t *fn;
616 source_t *src;
f55ade6e 617
4977bab6
ZW
618 while ((src = sources))
619 {
620 sources = src->next;
621
622 free (src->name);
623 free (src->lines);
624 }
f55ade6e 625
4977bab6
ZW
626 while ((fn = functions))
627 {
628 unsigned ix;
629 block_t *block;
f55ade6e 630
4977bab6
ZW
631 functions = fn->next;
632 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
633 {
634 arc_t *arc, *arc_n;
635
636 for (arc = block->succ; arc; arc = arc_n)
637 {
638 arc_n = arc->succ_next;
639 free (arc);
640 }
4977bab6
ZW
641 }
642 free (fn->blocks);
643 free (fn->counts);
644 }
645}
646
647/* Generate the names of the graph and data files. If OBJECT_DIRECTORY
648 is not specified, these are looked for in the current directory,
649 and named from the basename of the FILE_NAME sans extension. If
37b8715b 650 OBJECT_DIRECTORY is specified and is a directory, the files are in
4977bab6
ZW
651 that directory, but named from the basename of the FILE_NAME, sans
652 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
653 the object *file*, and the data files are named from that. */
86144b75
DE
654
655static void
f55ade6e 656create_file_names (const char *file_name)
86144b75 657{
86144b75 658 char *cptr;
37b8715b 659 char *name;
4977bab6 660 int length = strlen (file_name);
37b8715b 661 int base;
f55ade6e 662
1a9075e2
TG
663 /* Free previous file names. */
664 if (bbg_file_name)
665 free (bbg_file_name);
666 if (da_file_name)
667 free (da_file_name);
668 da_file_name = bbg_file_name = NULL;
669 bbg_file_time = 0;
670 bbg_stamp = 0;
671
37b8715b 672 if (object_directory && object_directory[0])
86144b75 673 {
37b8715b
NS
674 struct stat status;
675
676 length += strlen (object_directory) + 2;
5ed6ace5 677 name = XNEWVEC (char, length);
37b8715b 678 name[0] = 0;
f55ade6e 679
37b8715b
NS
680 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
681 strcat (name, object_directory);
2f07423c 682 if (base && (! IS_DIR_SEPARATOR (name[strlen (name) - 1])))
37b8715b 683 strcat (name, "/");
86144b75
DE
684 }
685 else
686 {
5ed6ace5 687 name = XNEWVEC (char, length + 1);
37b8715b
NS
688 name[0] = 0;
689 base = 1;
86144b75 690 }
f55ade6e 691
37b8715b
NS
692 if (base)
693 {
f9da5064 694 /* Append source file name. */
2f07423c
PO
695 const char *cptr = lbasename (file_name);
696 strcat (name, cptr ? cptr : file_name);
37b8715b 697 }
f55ade6e 698
4b7e68e7 699 /* Remove the extension. */
37b8715b 700 cptr = strrchr (name, '.');
86144b75 701 if (cptr)
37b8715b 702 *cptr = 0;
f55ade6e 703
37b8715b 704 length = strlen (name);
b8698a0f 705
5ed6ace5 706 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
4977bab6 707 strcpy (bbg_file_name, name);
160e2e4f 708 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
37b8715b 709
5ed6ace5 710 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
4977bab6
ZW
711 strcpy (da_file_name, name);
712 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
f55ade6e 713
a14df7da 714 free (name);
4977bab6 715 return;
86144b75 716}
86144b75 717
94de45d9
NS
718/* Find or create a source file structure for FILE_NAME. Copies
719 FILE_NAME on creation */
27283c73
NS
720
721static source_t *
f55ade6e 722find_source (const char *file_name)
27283c73 723{
27283c73 724 source_t *src;
1a9075e2 725 struct stat status;
94de45d9
NS
726
727 if (!file_name)
728 file_name = "<unknown>";
f55ade6e 729
27283c73
NS
730 for (src = sources; src; src = src->next)
731 if (!strcmp (file_name, src->name))
1a9075e2 732 break;
f55ade6e 733
1a9075e2
TG
734 if (!src)
735 {
736 src = XCNEW (source_t);
737 src->name = xstrdup (file_name);
738 src->coverage.name = src->name;
739 src->index = source_index++;
740 src->next = sources;
741 sources = src;
b8698a0f 742
1a9075e2
TG
743 if (!stat (file_name, &status))
744 src->file_time = status.st_mtime;
745 }
746
747 if (src->file_time > bbg_file_time)
748 {
749 static int info_emitted;
750
751 fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
752 src->name, bbg_file_name);
753 if (!info_emitted)
754 {
755 fnotice (stderr,
756 "(the message is only displayed one per source file)\n");
757 info_emitted = 1;
758 }
759 src->file_time = 0;
760 }
94de45d9 761
27283c73
NS
762 return src;
763}
764
272d0bee 765/* Read the graph file. Return nonzero on fatal error. */
86144b75 766
4977bab6 767static int
f55ade6e 768read_graph_file (void)
86144b75 769{
94de45d9 770 unsigned version;
4977bab6 771 unsigned current_tag = 0;
4977bab6 772 struct function_info *fn = NULL;
1a9075e2 773 function_t *old_functions_head = functions;
4977bab6
ZW
774 source_t *src = NULL;
775 unsigned ix;
7d63a2fa 776 unsigned tag;
f55ade6e 777
546d2adb 778 if (!gcov_open (bbg_file_name, 1))
86144b75 779 {
4977bab6
ZW
780 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
781 return 1;
86144b75 782 }
546d2adb 783 bbg_file_time = gcov_time ();
160e2e4f 784 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
b7c9bf28 785 {
4977bab6 786 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
546d2adb 787 gcov_close ();
4977bab6
ZW
788 return 1;
789 }
b7c9bf28 790
94de45d9
NS
791 version = gcov_read_unsigned ();
792 if (version != GCOV_VERSION)
4977bab6
ZW
793 {
794 char v[4], e[4];
f55ade6e 795
330d2e2a
NS
796 GCOV_UNSIGNED2STRING (v, version);
797 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
798
9e637a26 799 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
4977bab6
ZW
800 bbg_file_name, v, e);
801 }
dd486eb2
NS
802 bbg_stamp = gcov_read_unsigned ();
803
7d63a2fa 804 while ((tag = gcov_read_unsigned ()))
4977bab6 805 {
94de45d9 806 unsigned length = gcov_read_unsigned ();
7d63a2fa 807 gcov_position_t base = gcov_position ();
796621e8 808
4977bab6 809 if (tag == GCOV_TAG_FUNCTION)
b7c9bf28 810 {
94de45d9 811 char *function_name;
796621e8 812 unsigned ident, checksum, lineno;
27283c73
NS
813 source_t *src;
814 function_t *probe, *prev;
4977bab6 815
796621e8 816 ident = gcov_read_unsigned ();
94de45d9 817 checksum = gcov_read_unsigned ();
796621e8 818 function_name = xstrdup (gcov_read_string ());
94de45d9
NS
819 src = find_source (gcov_read_string ());
820 lineno = gcov_read_unsigned ();
f55ade6e 821
5ed6ace5 822 fn = XCNEW (function_t);
4977bab6 823 fn->name = function_name;
796621e8 824 fn->ident = ident;
4977bab6 825 fn->checksum = checksum;
27283c73
NS
826 fn->src = src;
827 fn->line = lineno;
4977bab6
ZW
828
829 fn->next = functions;
830 functions = fn;
831 current_tag = tag;
f55ade6e 832
27283c73
NS
833 if (lineno >= src->num_lines)
834 src->num_lines = lineno + 1;
835 /* Now insert it into the source file's list of
836 functions. Normally functions will be encountered in
837 ascending order, so a simple scan is quick. */
838 for (probe = src->functions, prev = NULL;
839 probe && probe->line > lineno;
840 prev = probe, probe = probe->line_next)
841 continue;
842 fn->line_next = probe;
843 if (prev)
844 prev->line_next = fn;
845 else
846 src->functions = fn;
b7c9bf28 847 }
4977bab6 848 else if (fn && tag == GCOV_TAG_BLOCKS)
b7c9bf28 849 {
4977bab6 850 if (fn->blocks)
9e637a26 851 fnotice (stderr, "%s:already seen blocks for '%s'\n",
4977bab6
ZW
852 bbg_file_name, fn->name);
853 else
b7c9bf28 854 {
330d2e2a 855 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
27283c73 856 fn->num_blocks = num_blocks;
f55ade6e 857
5ed6ace5 858 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
27283c73 859 for (ix = 0; ix != num_blocks; ix++)
94de45d9 860 fn->blocks[ix].flags = gcov_read_unsigned ();
b7c9bf28 861 }
4977bab6
ZW
862 }
863 else if (fn && tag == GCOV_TAG_ARCS)
864 {
94de45d9 865 unsigned src = gcov_read_unsigned ();
330d2e2a 866 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
4977bab6 867
94de45d9 868 if (src >= fn->num_blocks || fn->blocks[src].succ)
4977bab6 869 goto corrupt;
f55ade6e 870
4977bab6 871 while (num_dests--)
b7c9bf28 872 {
4977bab6 873 struct arc_info *arc;
94de45d9
NS
874 unsigned dest = gcov_read_unsigned ();
875 unsigned flags = gcov_read_unsigned ();
f55ade6e 876
94de45d9 877 if (dest >= fn->num_blocks)
4977bab6 878 goto corrupt;
5ed6ace5 879 arc = XCNEW (arc_t);
f55ade6e 880
4977bab6
ZW
881 arc->dst = &fn->blocks[dest];
882 arc->src = &fn->blocks[src];
f55ade6e 883
4977bab6
ZW
884 arc->count = 0;
885 arc->count_valid = 0;
886 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
887 arc->fake = !!(flags & GCOV_ARC_FAKE);
888 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
f55ade6e 889
4977bab6
ZW
890 arc->succ_next = fn->blocks[src].succ;
891 fn->blocks[src].succ = arc;
892 fn->blocks[src].num_succ++;
f55ade6e 893
4977bab6
ZW
894 arc->pred_next = fn->blocks[dest].pred;
895 fn->blocks[dest].pred = arc;
896 fn->blocks[dest].num_pred++;
897
27283c73
NS
898 if (arc->fake)
899 {
900 if (src)
901 {
902 /* Exceptional exit from this function, the
903 source block must be a call. */
904 fn->blocks[src].is_call_site = 1;
905 arc->is_call_non_return = 1;
906 }
907 else
908 {
909 /* Non-local return from a callee of this
f55ade6e
AJ
910 function. The destination block is a catch or
911 setjmp. */
27283c73
NS
912 arc->is_nonlocal_return = 1;
913 fn->blocks[dest].is_nonlocal_return = 1;
914 }
915 }
f55ade6e 916
4977bab6
ZW
917 if (!arc->on_tree)
918 fn->num_counts++;
b7c9bf28 919 }
4977bab6
ZW
920 }
921 else if (fn && tag == GCOV_TAG_LINES)
922 {
94de45d9 923 unsigned blockno = gcov_read_unsigned ();
5ed6ace5 924 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
4977bab6 925
94de45d9 926 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
4977bab6 927 goto corrupt;
f55ade6e 928
4977bab6 929 for (ix = 0; ; )
b7c9bf28 930 {
94de45d9 931 unsigned lineno = gcov_read_unsigned ();
f55ade6e 932
4977bab6 933 if (lineno)
b7c9bf28 934 {
4977bab6
ZW
935 if (!ix)
936 {
937 line_nos[ix++] = 0;
938 line_nos[ix++] = src->index;
939 }
940 line_nos[ix++] = lineno;
941 if (lineno >= src->num_lines)
942 src->num_lines = lineno + 1;
b7c9bf28 943 }
4977bab6
ZW
944 else
945 {
94de45d9 946 const char *file_name = gcov_read_string ();
f55ade6e 947
4977bab6 948 if (!file_name)
b7c9bf28 949 break;
27283c73 950 src = find_source (file_name);
f55ade6e 951
4977bab6
ZW
952 line_nos[ix++] = 0;
953 line_nos[ix++] = src->index;
954 }
b7c9bf28 955 }
f55ade6e 956
27283c73
NS
957 fn->blocks[blockno].u.line.encoding = line_nos;
958 fn->blocks[blockno].u.line.num = ix;
4977bab6
ZW
959 }
960 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
961 {
962 fn = NULL;
963 current_tag = 0;
964 }
474f141e 965 gcov_sync (base, length);
94de45d9 966 if (gcov_is_error ())
00cf2913
NS
967 {
968 corrupt:;
969 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
970 gcov_close ();
971 return 1;
972 }
b7c9bf28 973 }
546d2adb 974 gcov_close ();
f55ade6e 975
6614fd40 976 /* We built everything backwards, so nreverse them all. */
f55ade6e 977
4977bab6
ZW
978 /* Reverse sources. Not strictly necessary, but we'll then process
979 them in the 'expected' order. */
980 {
981 source_t *src, *src_p, *src_n;
982
983 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
984 {
985 src_n = src->next;
986 src->next = src_p;
987 }
988 sources = src_p;
989 }
b7c9bf28 990
4977bab6
ZW
991 /* Reverse functions. */
992 {
993 function_t *fn, *fn_p, *fn_n;
b7c9bf28 994
1a9075e2
TG
995 for (fn_p = old_functions_head, fn = functions;
996 fn != old_functions_head;
997 fn_p = fn, fn = fn_n)
4977bab6
ZW
998 {
999 unsigned ix;
f55ade6e 1000
4977bab6
ZW
1001 fn_n = fn->next;
1002 fn->next = fn_p;
b7c9bf28 1003
f9da5064 1004 /* Reverse the arcs. */
4977bab6
ZW
1005 for (ix = fn->num_blocks; ix--;)
1006 {
1007 arc_t *arc, *arc_p, *arc_n;
f55ade6e 1008
4977bab6
ZW
1009 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1010 arc_p = arc, arc = arc_n)
1011 {
1012 arc_n = arc->succ_next;
1013 arc->succ_next = arc_p;
1014 }
1015 fn->blocks[ix].succ = arc_p;
1016
1017 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1018 arc_p = arc, arc = arc_n)
1019 {
1020 arc_n = arc->pred_next;
1021 arc->pred_next = arc_p;
1022 }
1023 fn->blocks[ix].pred = arc_p;
1024 }
1025 }
1026 functions = fn_p;
1027 }
1028 return 0;
b7c9bf28 1029}
86144b75 1030
4977bab6 1031/* Reads profiles from the count file and attach to each
272d0bee 1032 function. Return nonzero if fatal error. */
86144b75 1033
4977bab6 1034static int
f55ade6e 1035read_count_file (void)
86144b75 1036{
4977bab6 1037 unsigned ix;
94de45d9 1038 unsigned version;
7d63a2fa 1039 unsigned tag;
4977bab6 1040 function_t *fn = NULL;
7d63a2fa 1041 int error = 0;
4977bab6 1042
546d2adb 1043 if (!gcov_open (da_file_name, 1))
86144b75 1044 {
80b3502b
NS
1045 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1046 da_file_name);
1047 no_data_file = 1;
1048 return 0;
4977bab6 1049 }
160e2e4f 1050 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
4977bab6
ZW
1051 {
1052 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1053 cleanup:;
546d2adb 1054 gcov_close ();
4977bab6
ZW
1055 return 1;
1056 }
94de45d9
NS
1057 version = gcov_read_unsigned ();
1058 if (version != GCOV_VERSION)
4977bab6 1059 {
330d2e2a
NS
1060 char v[4], e[4];
1061
1062 GCOV_UNSIGNED2STRING (v, version);
1063 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
b8698a0f 1064
9e637a26 1065 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
330d2e2a 1066 da_file_name, v, e);
86144b75 1067 }
dd486eb2
NS
1068 tag = gcov_read_unsigned ();
1069 if (tag != bbg_stamp)
1070 {
1071 fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1072 goto cleanup;
1073 }
f55ade6e 1074
7d63a2fa 1075 while ((tag = gcov_read_unsigned ()))
4977bab6 1076 {
94de45d9
NS
1077 unsigned length = gcov_read_unsigned ();
1078 unsigned long base = gcov_position ();
94de45d9 1079
27283c73 1080 if (tag == GCOV_TAG_OBJECT_SUMMARY)
94de45d9 1081 gcov_read_summary (&object_summary);
cdb23767 1082 else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
94de45d9 1083 program_count++;
27283c73 1084 else if (tag == GCOV_TAG_FUNCTION)
86144b75 1085 {
e1b7793c
ILT
1086 {
1087 unsigned ident = gcov_read_unsigned ();
1088 struct function_info *fn_n = functions;
4977bab6 1089
e1b7793c
ILT
1090 /* Try to find the function in the list.
1091 To speed up the search, first start from the last function
1092 found. */
1093 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1094 {
1095 if (fn)
1096 ;
1097 else if ((fn = fn_n))
1098 fn_n = NULL;
1099 else
1100 {
1101 fnotice (stderr, "%s:unknown function '%u'\n",
1102 da_file_name, ident);
1103 break;
1104 }
1105 if (fn->ident == ident)
4977bab6 1106 break;
e1b7793c
ILT
1107 }
1108 }
4977bab6
ZW
1109
1110 if (!fn)
1111 ;
94de45d9 1112 else if (gcov_read_unsigned () != fn->checksum)
86144b75 1113 {
4977bab6 1114 mismatch:;
9e637a26 1115 fnotice (stderr, "%s:profile mismatch for '%s'\n",
94de45d9 1116 da_file_name, fn->name);
4977bab6
ZW
1117 goto cleanup;
1118 }
1119 }
cdb23767 1120 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
4977bab6 1121 {
330d2e2a 1122 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
4977bab6 1123 goto mismatch;
f55ade6e 1124
4977bab6 1125 if (!fn->counts)
5ed6ace5 1126 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
f55ade6e 1127
4977bab6 1128 for (ix = 0; ix != fn->num_counts; ix++)
94de45d9
NS
1129 fn->counts[ix] += gcov_read_counter ();
1130 }
474f141e 1131 gcov_sync (base, length);
94de45d9 1132 if ((error = gcov_is_error ()))
00cf2913
NS
1133 {
1134 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1135 da_file_name);
1136 goto cleanup;
1137 }
7d63a2fa 1138 }
f55ade6e 1139
546d2adb 1140 gcov_close ();
4977bab6 1141 return 0;
86144b75
DE
1142}
1143
4977bab6
ZW
1144/* Solve the flow graph. Propagate counts from the instrumented arcs
1145 to the blocks and the uninstrumented arcs. */
86144b75
DE
1146
1147static void
f55ade6e 1148solve_flow_graph (function_t *fn)
86144b75 1149{
4977bab6
ZW
1150 unsigned ix;
1151 arc_t *arc;
1152 gcov_type *count_ptr = fn->counts;
27283c73 1153 block_t *blk;
32dd366d
KH
1154 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1155 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
f55ade6e 1156
4977bab6 1157 if (fn->num_blocks < 2)
9e637a26 1158 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
4977bab6
ZW
1159 bbg_file_name, fn->name);
1160 else
86144b75 1161 {
4977bab6 1162 if (fn->blocks[0].num_pred)
9e637a26 1163 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
4977bab6 1164 bbg_file_name, fn->name);
86144b75 1165 else
4977bab6
ZW
1166 /* We can't deduce the entry block counts from the lack of
1167 predecessors. */
1168 fn->blocks[0].num_pred = ~(unsigned)0;
f55ade6e 1169
4977bab6 1170 if (fn->blocks[fn->num_blocks - 1].num_succ)
9e637a26 1171 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
4977bab6
ZW
1172 bbg_file_name, fn->name);
1173 else
1174 /* Likewise, we can't deduce exit block counts from the lack
1175 of its successors. */
1176 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
86144b75
DE
1177 }
1178
4977bab6
ZW
1179 /* Propagate the measured counts, this must be done in the same
1180 order as the code in profile.c */
27283c73 1181 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
86144b75 1182 {
4977bab6
ZW
1183 block_t const *prev_dst = NULL;
1184 int out_of_order = 0;
27283c73 1185 int non_fake_succ = 0;
f55ade6e 1186
27283c73 1187 for (arc = blk->succ; arc; arc = arc->succ_next)
86144b75 1188 {
27283c73
NS
1189 if (!arc->fake)
1190 non_fake_succ++;
f55ade6e 1191
4977bab6 1192 if (!arc->on_tree)
86144b75 1193 {
4977bab6
ZW
1194 if (count_ptr)
1195 arc->count = *count_ptr++;
1196 arc->count_valid = 1;
27283c73 1197 blk->num_succ--;
4977bab6 1198 arc->dst->num_pred--;
86144b75 1199 }
4977bab6
ZW
1200 if (prev_dst && prev_dst > arc->dst)
1201 out_of_order = 1;
1202 prev_dst = arc->dst;
86144b75 1203 }
27283c73
NS
1204 if (non_fake_succ == 1)
1205 {
1206 /* If there is only one non-fake exit, it is an
1207 unconditional branch. */
1208 for (arc = blk->succ; arc; arc = arc->succ_next)
1209 if (!arc->fake)
1210 {
1211 arc->is_unconditional = 1;
1212 /* If this block is instrumenting a call, it might be
e0bb17a8 1213 an artificial block. It is not artificial if it has
10b7602f
NS
1214 a non-fallthrough exit, or the destination of this
1215 arc has more than one entry. Mark the destination
1216 block as a return site, if none of those conditions
1217 hold. */
1218 if (blk->is_call_site && arc->fall_through
1219 && arc->dst->pred == arc && !arc->pred_next)
1220 arc->dst->is_call_return = 1;
27283c73
NS
1221 }
1222 }
f55ade6e 1223
4977bab6
ZW
1224 /* Sort the successor arcs into ascending dst order. profile.c
1225 normally produces arcs in the right order, but sometimes with
1226 one or two out of order. We're not using a particularly
32dd366d 1227 smart sort. */
4977bab6 1228 if (out_of_order)
86144b75 1229 {
27283c73 1230 arc_t *start = blk->succ;
4977bab6 1231 unsigned changes = 1;
f55ade6e 1232
4977bab6
ZW
1233 while (changes)
1234 {
1235 arc_t *arc, *arc_p, *arc_n;
f55ade6e 1236
4977bab6
ZW
1237 changes = 0;
1238 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1239 {
1240 if (arc->dst > arc_n->dst)
1241 {
1242 changes = 1;
1243 if (arc_p)
1244 arc_p->succ_next = arc_n;
1245 else
1246 start = arc_n;
1247 arc->succ_next = arc_n->succ_next;
1248 arc_n->succ_next = arc;
1249 arc_p = arc_n;
1250 }
1251 else
1252 {
1253 arc_p = arc;
1254 arc = arc_n;
1255 }
1256 }
1257 }
27283c73 1258 blk->succ = start;
86144b75 1259 }
f55ade6e 1260
4977bab6
ZW
1261 /* Place it on the invalid chain, it will be ignored if that's
1262 wrong. */
27283c73
NS
1263 blk->invalid_chain = 1;
1264 blk->chain = invalid_blocks;
1265 invalid_blocks = blk;
4977bab6
ZW
1266 }
1267
1268 while (invalid_blocks || valid_blocks)
1269 {
4977bab6 1270 while ((blk = invalid_blocks))
86144b75 1271 {
4977bab6
ZW
1272 gcov_type total = 0;
1273 const arc_t *arc;
f55ade6e 1274
4977bab6
ZW
1275 invalid_blocks = blk->chain;
1276 blk->invalid_chain = 0;
1277 if (!blk->num_succ)
1278 for (arc = blk->succ; arc; arc = arc->succ_next)
1279 total += arc->count;
1280 else if (!blk->num_pred)
1281 for (arc = blk->pred; arc; arc = arc->pred_next)
1282 total += arc->count;
1283 else
1284 continue;
f55ade6e 1285
4977bab6
ZW
1286 blk->count = total;
1287 blk->count_valid = 1;
1288 blk->chain = valid_blocks;
1289 blk->valid_chain = 1;
1290 valid_blocks = blk;
86144b75 1291 }
4977bab6 1292 while ((blk = valid_blocks))
86144b75 1293 {
4977bab6
ZW
1294 gcov_type total;
1295 arc_t *arc, *inv_arc;
1296
1297 valid_blocks = blk->chain;
1298 blk->valid_chain = 0;
1299 if (blk->num_succ == 1)
1300 {
1301 block_t *dst;
f55ade6e 1302
4977bab6
ZW
1303 total = blk->count;
1304 inv_arc = NULL;
1305 for (arc = blk->succ; arc; arc = arc->succ_next)
1306 {
1307 total -= arc->count;
1308 if (!arc->count_valid)
1309 inv_arc = arc;
1310 }
1311 dst = inv_arc->dst;
1312 inv_arc->count_valid = 1;
1313 inv_arc->count = total;
1314 blk->num_succ--;
1315 dst->num_pred--;
1316 if (dst->count_valid)
1317 {
1318 if (dst->num_pred == 1 && !dst->valid_chain)
1319 {
1320 dst->chain = valid_blocks;
1321 dst->valid_chain = 1;
1322 valid_blocks = dst;
1323 }
1324 }
1325 else
1326 {
1327 if (!dst->num_pred && !dst->invalid_chain)
1328 {
1329 dst->chain = invalid_blocks;
1330 dst->invalid_chain = 1;
1331 invalid_blocks = dst;
1332 }
1333 }
1334 }
1335 if (blk->num_pred == 1)
1336 {
1337 block_t *src;
f55ade6e 1338
4977bab6
ZW
1339 total = blk->count;
1340 inv_arc = NULL;
1341 for (arc = blk->pred; arc; arc = arc->pred_next)
1342 {
1343 total -= arc->count;
1344 if (!arc->count_valid)
1345 inv_arc = arc;
1346 }
1347 src = inv_arc->src;
1348 inv_arc->count_valid = 1;
1349 inv_arc->count = total;
1350 blk->num_pred--;
1351 src->num_succ--;
1352 if (src->count_valid)
1353 {
1354 if (src->num_succ == 1 && !src->valid_chain)
1355 {
1356 src->chain = valid_blocks;
1357 src->valid_chain = 1;
1358 valid_blocks = src;
1359 }
1360 }
1361 else
1362 {
1363 if (!src->num_succ && !src->invalid_chain)
1364 {
1365 src->chain = invalid_blocks;
1366 src->invalid_chain = 1;
1367 invalid_blocks = src;
1368 }
1369 }
1370 }
86144b75
DE
1371 }
1372 }
f55ade6e 1373
4977bab6
ZW
1374 /* If the graph has been correctly solved, every block will have a
1375 valid count. */
1376 for (ix = 0; ix < fn->num_blocks; ix++)
1377 if (!fn->blocks[ix].count_valid)
1378 {
9e637a26 1379 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
4977bab6
ZW
1380 bbg_file_name, fn->name);
1381 break;
1382 }
86144b75 1383}
4977bab6 1384
86144b75 1385\f
86144b75 1386
4977bab6 1387/* Increment totals in COVERAGE according to arc ARC. */
8b219a76
NS
1388
1389static void
f55ade6e 1390add_branch_counts (coverage_t *coverage, const arc_t *arc)
8b219a76 1391{
27283c73 1392 if (arc->is_call_non_return)
8b219a76 1393 {
4977bab6
ZW
1394 coverage->calls++;
1395 if (arc->src->count)
1396 coverage->calls_executed++;
8b219a76 1397 }
27283c73 1398 else if (!arc->is_unconditional)
8b219a76 1399 {
4977bab6
ZW
1400 coverage->branches++;
1401 if (arc->src->count)
1402 coverage->branches_executed++;
1403 if (arc->count)
1404 coverage->branches_taken++;
86144b75
DE
1405 }
1406}
1407
37b8715b
NS
1408/* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1409 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1410 If DP is zero, no decimal point is printed. Only print 100% when
1411 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1412 format TOP. Return pointer to a static string. */
1413
1414static char const *
f55ade6e 1415format_gcov (gcov_type top, gcov_type bottom, int dp)
37b8715b
NS
1416{
1417 static char buffer[20];
f55ade6e 1418
37b8715b
NS
1419 if (dp >= 0)
1420 {
1421 float ratio = bottom ? (float)top / bottom : 0;
1422 int ix;
1423 unsigned limit = 100;
1424 unsigned percent;
f55ade6e 1425
37b8715b
NS
1426 for (ix = dp; ix--; )
1427 limit *= 10;
f55ade6e 1428
d19202ba
NS
1429 percent = (unsigned) (ratio * limit + (float)0.5);
1430 if (percent <= 0 && top)
37b8715b 1431 percent = 1;
d19202ba 1432 else if (percent >= limit && top != bottom)
37b8715b
NS
1433 percent = limit - 1;
1434 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1435 if (dp)
1436 {
1437 dp++;
1438 do
1439 {
1440 buffer[ix+1] = buffer[ix];
1441 ix--;
1442 }
1443 while (dp--);
1444 buffer[ix + 1] = '.';
1445 }
1446 }
1447 else
4977bab6 1448 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
f55ade6e 1449
37b8715b
NS
1450 return buffer;
1451}
1452
1453
86144b75
DE
1454/* Output summary info for a function. */
1455
1456static void
f55ade6e 1457function_summary (const coverage_t *coverage, const char *title)
86144b75 1458{
9e637a26 1459 fnotice (stdout, "%s '%s'\n", title, coverage->name);
4977bab6
ZW
1460
1461 if (coverage->lines)
1462 fnotice (stdout, "Lines executed:%s of %d\n",
1463 format_gcov (coverage->lines_executed, coverage->lines, 2),
1464 coverage->lines);
86144b75 1465 else
1457ebf9 1466 fnotice (stdout, "No executable lines\n");
86144b75 1467
4977bab6 1468 if (flag_branches)
86144b75 1469 {
4977bab6 1470 if (coverage->branches)
86144b75 1471 {
4977bab6
ZW
1472 fnotice (stdout, "Branches executed:%s of %d\n",
1473 format_gcov (coverage->branches_executed,
1474 coverage->branches, 2),
1475 coverage->branches);
1476 fnotice (stdout, "Taken at least once:%s of %d\n",
1477 format_gcov (coverage->branches_taken,
1478 coverage->branches, 2),
1479 coverage->branches);
86144b75
DE
1480 }
1481 else
4977bab6
ZW
1482 fnotice (stdout, "No branches\n");
1483 if (coverage->calls)
1484 fnotice (stdout, "Calls executed:%s of %d\n",
1485 format_gcov (coverage->calls_executed, coverage->calls, 2),
1486 coverage->calls);
86144b75 1487 else
4977bab6 1488 fnotice (stdout, "No calls\n");
8b219a76
NS
1489 }
1490}
1491
1492/* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1493 affect name generation. With preserve_paths we create a filename
1494 from all path components of the source file, replacing '/' with
1495 '#', without it we simply take the basename component. With
1496 long_output_names we prepend the processed name of the input file
1497 to each output name (except when the current source file is the
1498 input file, so you don't get a double concatenation). The two
1499 components are separated by '##'. Also '.' filename components are
4b7e68e7 1500 removed and '..' components are renamed to '^'. */
8b219a76
NS
1501
1502static char *
f55ade6e 1503make_gcov_file_name (const char *input_name, const char *src_name)
8b219a76 1504{
2f07423c 1505 const char *cptr;
1a9075e2 1506 char *name;
f55ade6e 1507
1a9075e2 1508 if (flag_long_names && input_name && strcmp (src_name, input_name))
8b219a76 1509 {
1a9075e2
TG
1510 name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10);
1511 name[0] = 0;
8b219a76 1512 /* Generate the input filename part. */
2f07423c
PO
1513 cptr = flag_preserve_paths ? NULL : lbasename (input_name);
1514 strcat (name, cptr ? cptr : input_name);
8b219a76
NS
1515 strcat (name, "##");
1516 }
1a9075e2
TG
1517 else
1518 {
1519 name = XNEWVEC (char, strlen (src_name) + 10);
1520 name[0] = 0;
1521 }
f55ade6e 1522
4b7e68e7 1523 /* Generate the source filename part. */
2f07423c
PO
1524
1525 cptr = flag_preserve_paths ? NULL : lbasename (src_name);
1526 strcat (name, cptr ? cptr : src_name);
f55ade6e 1527
4977bab6 1528 if (flag_preserve_paths)
8b219a76 1529 {
2f07423c
PO
1530 /* Convert '/' and '\' to '#', remove '/./', convert '/../' to '/^/',
1531 convert ':' to '~' on DOS based file system. */
1532 char *pnew = name, *pold = name;
f55ade6e 1533
2f07423c 1534 /* First check for leading drive separator. */
f55ade6e 1535
2f07423c
PO
1536 while (*pold != '\0')
1537 {
1538 if (*pold == '/' || *pold == '\\')
f55ade6e 1539 {
2f07423c
PO
1540 *pnew++ = '#';
1541 pold++;
f55ade6e 1542 }
2f07423c
PO
1543#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
1544 else if (*pold == ':')
f55ade6e 1545 {
2f07423c
PO
1546 *pnew++ = '~';
1547 pold++;
f55ade6e 1548 }
2f07423c
PO
1549#endif
1550 else if ((*pold == '/' && strstr (pold, "/./") == pold)
1551 || (*pold == '\\' && strstr (pold, "\\.\\") == pold))
1552 pold += 3;
1553 else if (*pold == '/' && strstr (pold, "/../") == pold)
f55ade6e 1554 {
2f07423c
PO
1555 strcpy (pnew, "/^/");
1556 pnew += 3;
1557 pold += 4;
f55ade6e 1558 }
2f07423c
PO
1559 else if (*pold == '\\' && strstr (pold, "\\..\\") == pold)
1560 {
1561 strcpy (pnew, "\\^\\");
1562 pnew += 3;
1563 pold += 4;
1564 }
1565 else
1566 *pnew++ = *pold++;
f55ade6e 1567 }
2f07423c
PO
1568
1569 *pnew = '\0';
86144b75 1570 }
f55ade6e 1571
8b219a76
NS
1572 strcat (name, ".gcov");
1573 return name;
86144b75
DE
1574}
1575
4977bab6 1576/* Scan through the bb_data for each line in the block, increment
8b219a76
NS
1577 the line number execution count indicated by the execution count of
1578 the appropriate basic block. */
86144b75
DE
1579
1580static void
f55ade6e 1581add_line_counts (coverage_t *coverage, function_t *fn)
86144b75 1582{
4977bab6 1583 unsigned ix;
beb235f8 1584 line_t *line = NULL; /* This is propagated from one iteration to the
4977bab6
ZW
1585 next. */
1586
32dd366d 1587 /* Scan each basic block. */
4977bab6 1588 for (ix = 0; ix != fn->num_blocks; ix++)
86144b75 1589 {
27283c73 1590 block_t *block = &fn->blocks[ix];
4977bab6
ZW
1591 unsigned *encoding;
1592 const source_t *src = NULL;
1593 unsigned jx;
1594
27283c73
NS
1595 if (block->count && ix && ix + 1 != fn->num_blocks)
1596 fn->blocks_executed++;
1597 for (jx = 0, encoding = block->u.line.encoding;
1598 jx != block->u.line.num; jx++, encoding++)
4977bab6
ZW
1599 if (!*encoding)
1600 {
1601 unsigned src_n = *++encoding;
86144b75 1602
4977bab6
ZW
1603 for (src = sources; src->index != src_n; src = src->next)
1604 continue;
1605 jx++;
1606 }
1607 else
1608 {
1609 line = &src->lines[*encoding];
1610
1611 if (coverage)
1612 {
1613 if (!line->exists)
1614 coverage->lines++;
27283c73 1615 if (!line->count && block->count)
4977bab6
ZW
1616 coverage->lines_executed++;
1617 }
1618 line->exists = 1;
1619 line->count += block->count;
1620 }
27283c73 1621 free (block->u.line.encoding);
10b7602f
NS
1622 block->u.cycle.arc = NULL;
1623 block->u.cycle.ident = ~0U;
f55ade6e 1624
27283c73
NS
1625 if (!ix || ix + 1 == fn->num_blocks)
1626 /* Entry or exit block */;
1627 else if (flag_all_blocks)
86144b75 1628 {
10b7602f 1629 line_t *block_line = line ? line : &fn->src->lines[fn->line];
f55ade6e 1630
10b7602f
NS
1631 block->chain = block_line->u.blocks;
1632 block_line->u.blocks = block;
27283c73
NS
1633 }
1634 else if (flag_branches)
1635 {
1636 arc_t *arc;
1637
4977bab6 1638 for (arc = block->succ; arc; arc = arc->succ_next)
86144b75 1639 {
27283c73
NS
1640 arc->line_next = line->u.branches;
1641 line->u.branches = arc;
1642 if (coverage && !arc->is_unconditional)
4977bab6 1643 add_branch_counts (coverage, arc);
86144b75 1644 }
8b219a76
NS
1645 }
1646 }
4977bab6 1647 if (!line)
9e637a26 1648 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
4977bab6
ZW
1649}
1650
32dd366d 1651/* Accumulate the line counts of a file. */
4977bab6
ZW
1652
1653static void
f55ade6e 1654accumulate_line_counts (source_t *src)
4977bab6
ZW
1655{
1656 line_t *line;
27283c73 1657 function_t *fn, *fn_p, *fn_n;
4977bab6 1658 unsigned ix;
27283c73
NS
1659
1660 /* Reverse the function order. */
1661 for (fn = src->functions, fn_p = NULL; fn;
1662 fn_p = fn, fn = fn_n)
1663 {
1664 fn_n = fn->line_next;
1665 fn->line_next = fn_p;
1666 }
1667 src->functions = fn_p;
f55ade6e 1668
4977bab6 1669 for (ix = src->num_lines, line = src->lines; ix--; line++)
8b219a76 1670 {
27283c73 1671 if (!flag_all_blocks)
8b219a76 1672 {
27283c73 1673 arc_t *arc, *arc_p, *arc_n;
f55ade6e 1674
27283c73
NS
1675 /* Total and reverse the branch information. */
1676 for (arc = line->u.branches, arc_p = NULL; arc;
1677 arc_p = arc, arc = arc_n)
1678 {
1679 arc_n = arc->line_next;
1680 arc->line_next = arc_p;
f55ade6e 1681
27283c73
NS
1682 add_branch_counts (&src->coverage, arc);
1683 }
1684 line->u.branches = arc_p;
8b219a76 1685 }
27283c73
NS
1686 else if (line->u.blocks)
1687 {
1688 /* The user expects the line count to be the number of times
1689 a line has been executed. Simply summing the block count
1690 will give an artificially high number. The Right Thing
10b7602f
NS
1691 is to sum the entry counts to the graph of blocks on this
1692 line, then find the elementary cycles of the local graph
1693 and add the transition counts of those cycles. */
27283c73 1694 block_t *block, *block_p, *block_n;
27283c73 1695 gcov_type count = 0;
f55ade6e 1696
f9da5064 1697 /* Reverse the block information. */
27283c73
NS
1698 for (block = line->u.blocks, block_p = NULL; block;
1699 block_p = block, block = block_n)
1700 {
1701 block_n = block->chain;
1702 block->chain = block_p;
10b7602f 1703 block->u.cycle.ident = ix;
27283c73
NS
1704 }
1705 line->u.blocks = block_p;
f55ade6e 1706
10b7602f
NS
1707 /* Sum the entry arcs. */
1708 for (block = line->u.blocks; block; block = block->chain)
1709 {
1710 arc_t *arc;
86144b75 1711
10b7602f
NS
1712 for (arc = block->pred; arc; arc = arc->pred_next)
1713 {
1714 if (arc->src->u.cycle.ident != ix)
1715 count += arc->count;
1716 if (flag_branches)
1717 add_branch_counts (&src->coverage, arc);
1718 }
3d7ca167
ZD
1719
1720 /* Initialize the cs_count. */
1721 for (arc = block->succ; arc; arc = arc->succ_next)
1722 arc->cs_count = arc->count;
10b7602f
NS
1723 }
1724
1725 /* Find the loops. This uses the algorithm described in
1726 Tiernan 'An Efficient Search Algorithm to Find the
1727 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1728 the P array by having each block point to the arc that
1729 connects to the previous block. The H array is implicitly
1730 held because of the arc ordering, and the block's
1731 previous arc pointer.
1732
1733 Although the algorithm is O(N^3) for highly connected
1734 graphs, at worst we'll have O(N^2), as most blocks have
1735 only one or two exits. Most graphs will be small.
1736
1737 For each loop we find, locate the arc with the smallest
1738 transition count, and add that to the cumulative
3d7ca167
ZD
1739 count. Decrease flow over the cycle and remove the arc
1740 from consideration. */
10b7602f 1741 for (block = line->u.blocks; block; block = block->chain)
27283c73 1742 {
10b7602f
NS
1743 block_t *head = block;
1744 arc_t *arc;
f55ade6e 1745
10b7602f
NS
1746 next_vertex:;
1747 arc = head->succ;
1748 current_vertex:;
1749 while (arc)
27283c73 1750 {
10b7602f
NS
1751 block_t *dst = arc->dst;
1752 if (/* Already used that arc. */
1753 arc->cycle
1754 /* Not to same graph, or before first vertex. */
1755 || dst->u.cycle.ident != ix
1756 /* Already in path. */
1757 || dst->u.cycle.arc)
1758 {
1759 arc = arc->succ_next;
1760 continue;
1761 }
f55ade6e 1762
10b7602f 1763 if (dst == block)
27283c73 1764 {
10b7602f 1765 /* Found a closing arc. */
3d7ca167 1766 gcov_type cycle_count = arc->cs_count;
10b7602f
NS
1767 arc_t *cycle_arc = arc;
1768 arc_t *probe_arc;
f55ade6e 1769
71c0e7fc 1770 /* Locate the smallest arc count of the loop. */
10b7602f
NS
1771 for (dst = head; (probe_arc = dst->u.cycle.arc);
1772 dst = probe_arc->src)
3d7ca167 1773 if (cycle_count > probe_arc->cs_count)
10b7602f 1774 {
3d7ca167 1775 cycle_count = probe_arc->cs_count;
10b7602f
NS
1776 cycle_arc = probe_arc;
1777 }
f55ade6e 1778
10b7602f
NS
1779 count += cycle_count;
1780 cycle_arc->cycle = 1;
3d7ca167
ZD
1781
1782 /* Remove the flow from the cycle. */
1783 arc->cs_count -= cycle_count;
1784 for (dst = head; (probe_arc = dst->u.cycle.arc);
1785 dst = probe_arc->src)
1786 probe_arc->cs_count -= cycle_count;
1787
10b7602f
NS
1788 /* Unwind to the cyclic arc. */
1789 while (head != cycle_arc->src)
27283c73 1790 {
10b7602f 1791 arc = head->u.cycle.arc;
3d7ca167 1792 head->u.cycle.arc = NULL;
10b7602f 1793 head = arc->src;
27283c73 1794 }
10b7602f
NS
1795 /* Move on. */
1796 arc = arc->succ_next;
1797 continue;
27283c73 1798 }
f55ade6e 1799
10b7602f
NS
1800 /* Add new block to chain. */
1801 dst->u.cycle.arc = arc;
1802 head = dst;
1803 goto next_vertex;
27283c73 1804 }
10b7602f
NS
1805 /* We could not add another vertex to the path. Remove
1806 the last vertex from the list. */
1807 arc = head->u.cycle.arc;
1808 if (arc)
27283c73 1809 {
71c0e7fc 1810 /* It was not the first vertex. Move onto next arc. */
10b7602f
NS
1811 head->u.cycle.arc = NULL;
1812 head = arc->src;
1813 arc = arc->succ_next;
1814 goto current_vertex;
27283c73 1815 }
10b7602f
NS
1816 /* Mark this block as unusable. */
1817 block->u.cycle.ident = ~0U;
27283c73 1818 }
10b7602f 1819
27283c73
NS
1820 line->count = count;
1821 }
f55ade6e 1822
4977bab6 1823 if (line->exists)
8b219a76 1824 {
4977bab6
ZW
1825 src->coverage.lines++;
1826 if (line->count)
1827 src->coverage.lines_executed++;
8b219a76 1828 }
8b219a76
NS
1829 }
1830}
86144b75 1831
61ada8ae 1832/* Output information about ARC number IX. Returns nonzero if
27283c73
NS
1833 anything is output. */
1834
1835static int
f55ade6e 1836output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
27283c73 1837{
f55ade6e 1838
27283c73
NS
1839 if (arc->is_call_non_return)
1840 {
1841 if (arc->src->count)
1842 {
1843 fnotice (gcov_file, "call %2d returned %s\n", ix,
1844 format_gcov (arc->src->count - arc->count,
1845 arc->src->count, -flag_counts));
1846 }
1847 else
1848 fnotice (gcov_file, "call %2d never executed\n", ix);
1849 }
1850 else if (!arc->is_unconditional)
1851 {
1852 if (arc->src->count)
1853 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1854 format_gcov (arc->count, arc->src->count, -flag_counts),
1855 arc->fall_through ? " (fallthrough)" : "");
1856 else
1857 fnotice (gcov_file, "branch %2d never executed\n", ix);
1858 }
10b7602f 1859 else if (flag_unconditional && !arc->dst->is_call_return)
27283c73
NS
1860 {
1861 if (arc->src->count)
1862 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1863 format_gcov (arc->count, arc->src->count, -flag_counts));
1864 else
1865 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1866 }
1867 else
1868 return 0;
1869 return 1;
f55ade6e 1870
27283c73
NS
1871}
1872
8b219a76
NS
1873/* Read in the source file one line at a time, and output that line to
1874 the gcov file preceded by its execution count and other
1875 information. */
86144b75 1876
8b219a76 1877static void
f55ade6e 1878output_lines (FILE *gcov_file, const source_t *src)
8b219a76
NS
1879{
1880 FILE *source_file;
f55ade6e 1881 unsigned line_num; /* current line number. */
4977bab6
ZW
1882 const line_t *line; /* current line info ptr. */
1883 char string[STRING_SIZE]; /* line buffer. */
1884 char const *retval = ""; /* status of source file reading. */
f5d39c3d 1885 function_t *fn = NULL;
4977bab6
ZW
1886
1887 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1a9075e2
TG
1888 if (!multiple_files)
1889 {
1890 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1891 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
1892 no_data_file ? "-" : da_file_name);
1893 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1894 object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1895 }
27283c73 1896 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
f55ade6e 1897
4977bab6 1898 source_file = fopen (src->name, "r");
8b219a76
NS
1899 if (!source_file)
1900 {
4977bab6 1901 fnotice (stderr, "%s:cannot open source file\n", src->name);
8b219a76
NS
1902 retval = NULL;
1903 }
1a9075e2
TG
1904 else if (src->file_time == 0)
1905 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
8b219a76 1906
f5d39c3d
NS
1907 if (flag_branches)
1908 fn = src->functions;
1909
4977bab6
ZW
1910 for (line_num = 1, line = &src->lines[line_num];
1911 line_num < src->num_lines; line_num++, line++)
8b219a76 1912 {
27283c73
NS
1913 for (; fn && fn->line == line_num; fn = fn->line_next)
1914 {
1915 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1916 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
b8698a0f 1917
27283c73
NS
1918 for (; arc; arc = arc->pred_next)
1919 if (arc->fake)
1920 return_count -= arc->count;
b8698a0f 1921
27283c73
NS
1922 fprintf (gcov_file, "function %s", fn->name);
1923 fprintf (gcov_file, " called %s",
1924 format_gcov (fn->blocks[0].count, 0, -1));
1925 fprintf (gcov_file, " returned %s",
1926 format_gcov (return_count, fn->blocks[0].count, 0));
1927 fprintf (gcov_file, " blocks executed %s",
1928 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1929 fprintf (gcov_file, "\n");
1930 }
f55ade6e 1931
8b219a76 1932 /* For lines which don't exist in the .bb file, print '-' before
f55ade6e
AJ
1933 the source line. For lines which exist but were never
1934 executed, print '#####' before the source line. Otherwise,
1935 print the execution count before the source line. There are
1936 16 spaces of indentation added before the source line so that
1937 tabs won't be messed up. */
4977bab6
ZW
1938 fprintf (gcov_file, "%9s:%5u:",
1939 !line->exists ? "-" : !line->count ? "#####"
1940 : format_gcov (line->count, 0, -1), line_num);
f55ade6e 1941
8b219a76
NS
1942 if (retval)
1943 {
1944 /* Copy source line. */
1945 do
1946 {
1947 retval = fgets (string, STRING_SIZE, source_file);
1948 if (!retval)
299f79b5 1949 break;
8b219a76 1950 fputs (retval, gcov_file);
37b8715b 1951 }
8b219a76
NS
1952 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1953 }
1954 if (!retval)
299f79b5 1955 fputs ("/*EOF*/\n", gcov_file);
27283c73
NS
1956
1957 if (flag_all_blocks)
8b219a76 1958 {
27283c73 1959 block_t *block;
10b7602f 1960 arc_t *arc;
27283c73 1961 int ix, jx;
f55ade6e 1962
27283c73
NS
1963 for (ix = jx = 0, block = line->u.blocks; block;
1964 block = block->chain)
37b8715b 1965 {
10b7602f 1966 if (!block->is_call_return)
27283c73
NS
1967 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1968 !line->exists ? "-" : !block->count ? "$$$$$"
10b7602f
NS
1969 : format_gcov (block->count, 0, -1),
1970 line_num, ix++);
27283c73
NS
1971 if (flag_branches)
1972 for (arc = block->succ; arc; arc = arc->succ_next)
1973 jx += output_branch_count (gcov_file, jx, arc);
86144b75 1974 }
8b219a76 1975 }
27283c73
NS
1976 else if (flag_branches)
1977 {
1978 int ix;
1979 arc_t *arc;
f55ade6e 1980
27283c73
NS
1981 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1982 ix += output_branch_count (gcov_file, ix, arc);
1983 }
8b219a76 1984 }
f55ade6e 1985
8b219a76
NS
1986 /* Handle all remaining source lines. There may be lines after the
1987 last line of code. */
1988 if (retval)
1989 {
1990 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1991 {
4977bab6 1992 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
f55ade6e 1993
8b219a76 1994 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
37b8715b 1995 {
8b219a76
NS
1996 retval = fgets (string, STRING_SIZE, source_file);
1997 if (!retval)
1998 break;
1999 fputs (retval, gcov_file);
37b8715b 2000 }
8b219a76
NS
2001 }
2002 }
f55ade6e 2003
8b219a76
NS
2004 if (source_file)
2005 fclose (source_file);
2006}