OSDN Git Service

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