Add prototype for ciss_print0 in place.
[dragonfly.git] / contrib / gcc-3.4 / 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         break;
900     }
901   if (!gcov_is_eof ())
902     {
903     corrupt:;
904       fnotice (stderr, "%s:corrupted\n", bbg_file_name);
905       gcov_close ();
906       return 1;
907     }
908   gcov_close ();
909
910   /* We built everything backwards, so nreverse them all.  */
911
912   /* Reverse sources. Not strictly necessary, but we'll then process
913      them in the 'expected' order.  */
914   {
915     source_t *src, *src_p, *src_n;
916
917     for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
918       {
919         src_n = src->next;
920         src->next = src_p;
921       }
922     sources =  src_p;
923   }
924
925   /* Reverse functions.  */
926   {
927     function_t *fn, *fn_p, *fn_n;
928
929     for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
930       {
931         unsigned ix;
932
933         fn_n = fn->next;
934         fn->next = fn_p;
935
936         /* Reverse the arcs.  */
937         for (ix = fn->num_blocks; ix--;)
938           {
939             arc_t *arc, *arc_p, *arc_n;
940
941             for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
942                  arc_p = arc, arc = arc_n)
943               {
944                 arc_n = arc->succ_next;
945                 arc->succ_next = arc_p;
946               }
947             fn->blocks[ix].succ = arc_p;
948
949             for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
950                  arc_p = arc, arc = arc_n)
951               {
952                 arc_n = arc->pred_next;
953                 arc->pred_next = arc_p;
954               }
955             fn->blocks[ix].pred = arc_p;
956           }
957       }
958     functions = fn_p;
959   }
960   return 0;
961 }
962
963 /* Reads profiles from the count file and attach to each
964    function. Return nonzero if fatal error.  */
965
966 static int
967 read_count_file (void)
968 {
969   unsigned ix;
970   unsigned version;
971   unsigned tag;
972   function_t *fn = NULL;
973   int error = 0;
974
975   if (!gcov_open (da_file_name, 1))
976     {
977       fnotice (stderr, "%s:cannot open data file\n", da_file_name);
978       return 1;
979     }
980   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
981     {
982       fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
983     cleanup:;
984       gcov_close ();
985       return 1;
986     }
987   version = gcov_read_unsigned ();
988   if (version != GCOV_VERSION)
989     {
990       char v[4], e[4];
991
992       GCOV_UNSIGNED2STRING (v, version);
993       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
994       
995       fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
996                da_file_name, v, e);
997     }
998   tag = gcov_read_unsigned ();
999   if (tag != bbg_stamp)
1000     {
1001       fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1002       goto cleanup;
1003     }
1004
1005   while ((tag = gcov_read_unsigned ()))
1006     {
1007       unsigned length = gcov_read_unsigned ();
1008       unsigned long base = gcov_position ();
1009
1010       if (tag == GCOV_TAG_OBJECT_SUMMARY)
1011         gcov_read_summary (&object_summary);
1012       else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1013         program_count++;
1014       else if (tag == GCOV_TAG_FUNCTION)
1015         {
1016           unsigned ident = gcov_read_unsigned ();
1017           struct function_info *fn_n = functions;
1018
1019           for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1020             {
1021               if (fn)
1022                 ;
1023               else if ((fn = fn_n))
1024                 fn_n = NULL;
1025               else
1026                 {
1027                   fnotice (stderr, "%s:unknown function `%u'\n",
1028                            da_file_name, ident);
1029                   break;
1030                 }
1031               if (fn->ident == ident)
1032                 break;
1033             }
1034
1035           if (!fn)
1036             ;
1037           else if (gcov_read_unsigned () != fn->checksum)
1038             {
1039             mismatch:;
1040               fnotice (stderr, "%s:profile mismatch for `%s'\n",
1041                        da_file_name, fn->name);
1042               goto cleanup;
1043             }
1044         }
1045       else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1046         {
1047           if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1048             goto mismatch;
1049
1050           if (!fn->counts)
1051             fn->counts = xcalloc (fn->num_counts, sizeof (gcov_type));
1052
1053           for (ix = 0; ix != fn->num_counts; ix++)
1054             fn->counts[ix] += gcov_read_counter ();
1055         }
1056       gcov_sync (base, length);
1057       if ((error = gcov_is_error ()))
1058         break;
1059     }
1060
1061   if (!gcov_is_eof ())
1062     {
1063       fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1064                da_file_name);
1065       goto cleanup;
1066     }
1067
1068   gcov_close ();
1069   return 0;
1070 }
1071
1072 /* Solve the flow graph. Propagate counts from the instrumented arcs
1073    to the blocks and the uninstrumented arcs.  */
1074
1075 static void
1076 solve_flow_graph (function_t *fn)
1077 {
1078   unsigned ix;
1079   arc_t *arc;
1080   gcov_type *count_ptr = fn->counts;
1081   block_t *blk;
1082   block_t *valid_blocks = NULL;    /* valid, but unpropagated blocks.  */
1083   block_t *invalid_blocks = NULL;  /* invalid, but inferable blocks.  */
1084
1085   if (fn->num_blocks < 2)
1086     fnotice (stderr, "%s:`%s' lacks entry and/or exit blocks\n",
1087              bbg_file_name, fn->name);
1088   else
1089     {
1090       if (fn->blocks[0].num_pred)
1091         fnotice (stderr, "%s:`%s' has arcs to entry block\n",
1092                  bbg_file_name, fn->name);
1093       else
1094         /* We can't deduce the entry block counts from the lack of
1095            predecessors.  */
1096         fn->blocks[0].num_pred = ~(unsigned)0;
1097
1098       if (fn->blocks[fn->num_blocks - 1].num_succ)
1099         fnotice (stderr, "%s:`%s' has arcs from exit block\n",
1100                  bbg_file_name, fn->name);
1101       else
1102         /* Likewise, we can't deduce exit block counts from the lack
1103            of its successors.  */
1104         fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1105     }
1106
1107   /* Propagate the measured counts, this must be done in the same
1108      order as the code in profile.c  */
1109   for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1110     {
1111       block_t const *prev_dst = NULL;
1112       int out_of_order = 0;
1113       int non_fake_succ = 0;
1114
1115       for (arc = blk->succ; arc; arc = arc->succ_next)
1116         {
1117           if (!arc->fake)
1118             non_fake_succ++;
1119
1120           if (!arc->on_tree)
1121             {
1122               if (count_ptr)
1123                 arc->count = *count_ptr++;
1124               arc->count_valid = 1;
1125               blk->num_succ--;
1126               arc->dst->num_pred--;
1127             }
1128           if (prev_dst && prev_dst > arc->dst)
1129             out_of_order = 1;
1130           prev_dst = arc->dst;
1131         }
1132       if (non_fake_succ == 1)
1133         {
1134           /* If there is only one non-fake exit, it is an
1135              unconditional branch.  */
1136           for (arc = blk->succ; arc; arc = arc->succ_next)
1137             if (!arc->fake)
1138               {
1139                 arc->is_unconditional = 1;
1140                 /* If this block is instrumenting a call, it might be
1141                    an artificial block. It is not artificial if it has
1142                    a non-fallthrough exit, or the destination of this
1143                    arc has more than one entry.  Mark the destination
1144                    block as a return site, if none of those conditions
1145                    hold.  */
1146                 if (blk->is_call_site && arc->fall_through
1147                     && arc->dst->pred == arc && !arc->pred_next)
1148                   arc->dst->is_call_return = 1;
1149               }
1150         }
1151
1152       /* Sort the successor arcs into ascending dst order. profile.c
1153          normally produces arcs in the right order, but sometimes with
1154          one or two out of order.  We're not using a particularly
1155          smart sort.  */
1156       if (out_of_order)
1157         {
1158           arc_t *start = blk->succ;
1159           unsigned changes = 1;
1160
1161           while (changes)
1162             {
1163               arc_t *arc, *arc_p, *arc_n;
1164
1165               changes = 0;
1166               for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1167                 {
1168                   if (arc->dst > arc_n->dst)
1169                     {
1170                       changes = 1;
1171                       if (arc_p)
1172                         arc_p->succ_next = arc_n;
1173                       else
1174                         start = arc_n;
1175                       arc->succ_next = arc_n->succ_next;
1176                       arc_n->succ_next = arc;
1177                       arc_p = arc_n;
1178                     }
1179                   else
1180                     {
1181                       arc_p = arc;
1182                       arc = arc_n;
1183                     }
1184                 }
1185             }
1186           blk->succ = start;
1187         }
1188
1189       /* Place it on the invalid chain, it will be ignored if that's
1190          wrong.  */
1191       blk->invalid_chain = 1;
1192       blk->chain = invalid_blocks;
1193       invalid_blocks = blk;
1194     }
1195
1196   while (invalid_blocks || valid_blocks)
1197     {
1198       while ((blk = invalid_blocks))
1199         {
1200           gcov_type total = 0;
1201           const arc_t *arc;
1202
1203           invalid_blocks = blk->chain;
1204           blk->invalid_chain = 0;
1205           if (!blk->num_succ)
1206             for (arc = blk->succ; arc; arc = arc->succ_next)
1207               total += arc->count;
1208           else if (!blk->num_pred)
1209             for (arc = blk->pred; arc; arc = arc->pred_next)
1210               total += arc->count;
1211           else
1212             continue;
1213
1214           blk->count = total;
1215           blk->count_valid = 1;
1216           blk->chain = valid_blocks;
1217           blk->valid_chain = 1;
1218           valid_blocks = blk;
1219         }
1220       while ((blk = valid_blocks))
1221         {
1222           gcov_type total;
1223           arc_t *arc, *inv_arc;
1224
1225           valid_blocks = blk->chain;
1226           blk->valid_chain = 0;
1227           if (blk->num_succ == 1)
1228             {
1229               block_t *dst;
1230
1231               total = blk->count;
1232               inv_arc = NULL;
1233               for (arc = blk->succ; arc; arc = arc->succ_next)
1234                 {
1235                   total -= arc->count;
1236                   if (!arc->count_valid)
1237                     inv_arc = arc;
1238                 }
1239               dst = inv_arc->dst;
1240               inv_arc->count_valid = 1;
1241               inv_arc->count = total;
1242               blk->num_succ--;
1243               dst->num_pred--;
1244               if (dst->count_valid)
1245                 {
1246                   if (dst->num_pred == 1 && !dst->valid_chain)
1247                     {
1248                       dst->chain = valid_blocks;
1249                       dst->valid_chain = 1;
1250                       valid_blocks = dst;
1251                     }
1252                 }
1253               else
1254                 {
1255                   if (!dst->num_pred && !dst->invalid_chain)
1256                     {
1257                       dst->chain = invalid_blocks;
1258                       dst->invalid_chain = 1;
1259                       invalid_blocks = dst;
1260                     }
1261                 }
1262             }
1263           if (blk->num_pred == 1)
1264             {
1265               block_t *src;
1266
1267               total = blk->count;
1268               inv_arc = NULL;
1269               for (arc = blk->pred; arc; arc = arc->pred_next)
1270                 {
1271                   total -= arc->count;
1272                   if (!arc->count_valid)
1273                     inv_arc = arc;
1274                 }
1275               src = inv_arc->src;
1276               inv_arc->count_valid = 1;
1277               inv_arc->count = total;
1278               blk->num_pred--;
1279               src->num_succ--;
1280               if (src->count_valid)
1281                 {
1282                   if (src->num_succ == 1 && !src->valid_chain)
1283                     {
1284                       src->chain = valid_blocks;
1285                       src->valid_chain = 1;
1286                       valid_blocks = src;
1287                     }
1288                 }
1289               else
1290                 {
1291                   if (!src->num_succ && !src->invalid_chain)
1292                     {
1293                       src->chain = invalid_blocks;
1294                       src->invalid_chain = 1;
1295                       invalid_blocks = src;
1296                     }
1297                 }
1298             }
1299         }
1300     }
1301
1302   /* If the graph has been correctly solved, every block will have a
1303      valid count.  */
1304   for (ix = 0; ix < fn->num_blocks; ix++)
1305     if (!fn->blocks[ix].count_valid)
1306       {
1307         fnotice (stderr, "%s:graph is unsolvable for `%s'\n",
1308                  bbg_file_name, fn->name);
1309         break;
1310       }
1311 }
1312
1313 \f
1314
1315 /* Increment totals in COVERAGE according to arc ARC.  */
1316
1317 static void
1318 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1319 {
1320   if (arc->is_call_non_return)
1321     {
1322       coverage->calls++;
1323       if (arc->src->count)
1324         coverage->calls_executed++;
1325     }
1326   else if (!arc->is_unconditional)
1327     {
1328       coverage->branches++;
1329       if (arc->src->count)
1330         coverage->branches_executed++;
1331       if (arc->count)
1332         coverage->branches_taken++;
1333     }
1334 }
1335
1336 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1337    count.  If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1338    If DP is zero, no decimal point is printed. Only print 100% when
1339    TOP==BOTTOM and only print 0% when TOP=0.  If dp < 0, then simply
1340    format TOP.  Return pointer to a static string.  */
1341
1342 static char const *
1343 format_gcov (gcov_type top, gcov_type bottom, int dp)
1344 {
1345   static char buffer[20];
1346
1347   if (dp >= 0)
1348     {
1349       float ratio = bottom ? (float)top / bottom : 0;
1350       int ix;
1351       unsigned limit = 100;
1352       unsigned percent;
1353
1354       for (ix = dp; ix--; )
1355         limit *= 10;
1356
1357       percent = (unsigned) (ratio * limit + (float)0.5);
1358       if (percent <= 0 && top)
1359         percent = 1;
1360       else if (percent >= limit && top != bottom)
1361         percent = limit - 1;
1362       ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1363       if (dp)
1364         {
1365           dp++;
1366           do
1367             {
1368               buffer[ix+1] = buffer[ix];
1369               ix--;
1370             }
1371           while (dp--);
1372           buffer[ix + 1] = '.';
1373         }
1374     }
1375   else
1376     sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1377
1378   return buffer;
1379 }
1380
1381
1382 /* Output summary info for a function.  */
1383
1384 static void
1385 function_summary (const coverage_t *coverage, const char *title)
1386 {
1387   fnotice (stdout, "%s `%s'\n", title, coverage->name);
1388
1389   if (coverage->lines)
1390     fnotice (stdout, "Lines executed:%s of %d\n",
1391              format_gcov (coverage->lines_executed, coverage->lines, 2),
1392              coverage->lines);
1393   else
1394     fnotice (stdout, "No executable lines");
1395
1396   if (flag_branches)
1397     {
1398       if (coverage->branches)
1399         {
1400           fnotice (stdout, "Branches executed:%s of %d\n",
1401                    format_gcov (coverage->branches_executed,
1402                                 coverage->branches, 2),
1403                    coverage->branches);
1404           fnotice (stdout, "Taken at least once:%s of %d\n",
1405                    format_gcov (coverage->branches_taken,
1406                                 coverage->branches, 2),
1407                    coverage->branches);
1408         }
1409       else
1410         fnotice (stdout, "No branches\n");
1411       if (coverage->calls)
1412         fnotice (stdout, "Calls executed:%s of %d\n",
1413                  format_gcov (coverage->calls_executed, coverage->calls, 2),
1414                  coverage->calls);
1415       else
1416         fnotice (stdout, "No calls\n");
1417     }
1418 }
1419
1420 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1421    affect name generation. With preserve_paths we create a filename
1422    from all path components of the source file, replacing '/' with
1423    '#', without it we simply take the basename component. With
1424    long_output_names we prepend the processed name of the input file
1425    to each output name (except when the current source file is the
1426    input file, so you don't get a double concatenation). The two
1427    components are separated by '##'. Also '.' filename components are
1428    removed and '..'  components are renamed to '^'.  */
1429
1430 static char *
1431 make_gcov_file_name (const char *input_name, const char *src_name)
1432 {
1433   char *cptr;
1434   char *name = xmalloc (strlen (src_name) + strlen (input_name) + 10);
1435
1436   name[0] = 0;
1437   if (flag_long_names && strcmp (src_name, input_name))
1438     {
1439       /* Generate the input filename part.  */
1440       cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1441       strcat (name, cptr ? cptr + 1 : input_name);
1442       strcat (name, "##");
1443     }
1444
1445   /* Generate the source filename part.  */
1446   cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1447   strcat (name, cptr ? cptr + 1 : src_name);
1448
1449   if (flag_preserve_paths)
1450     {
1451       /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1452       char *prev;
1453
1454       for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1455         {
1456           unsigned shift = 0;
1457
1458           if (prev + 1 == cptr && prev[0] == '.')
1459             {
1460               /* Remove '.' */
1461               shift = 2;
1462             }
1463           else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1464             {
1465               /* Convert '..' */
1466               shift = 1;
1467               prev[1] = '^';
1468             }
1469           else
1470             *cptr++ = '#';
1471           if (shift)
1472             {
1473               cptr = prev;
1474               do
1475                 prev[0] = prev[shift];
1476               while (*prev++);
1477             }
1478         }
1479     }
1480
1481   strcat (name, ".gcov");
1482   return name;
1483 }
1484
1485 /* Scan through the bb_data for each line in the block, increment
1486    the line number execution count indicated by the execution count of
1487    the appropriate basic block.  */
1488
1489 static void
1490 add_line_counts (coverage_t *coverage, function_t *fn)
1491 {
1492   unsigned ix;
1493   line_t *line = NULL; /* This is propagated from one iteration to the
1494                           next.  */
1495
1496   /* Scan each basic block.  */
1497   for (ix = 0; ix != fn->num_blocks; ix++)
1498     {
1499       block_t *block = &fn->blocks[ix];
1500       unsigned *encoding;
1501       const source_t *src = NULL;
1502       unsigned jx;
1503
1504       if (block->count && ix && ix + 1 != fn->num_blocks)
1505         fn->blocks_executed++;
1506       for (jx = 0, encoding = block->u.line.encoding;
1507            jx != block->u.line.num; jx++, encoding++)
1508         if (!*encoding)
1509           {
1510             unsigned src_n = *++encoding;
1511
1512             for (src = sources; src->index != src_n; src = src->next)
1513               continue;
1514             jx++;
1515           }
1516         else
1517           {
1518             line = &src->lines[*encoding];
1519
1520             if (coverage)
1521               {
1522                 if (!line->exists)
1523                   coverage->lines++;
1524                 if (!line->count && block->count)
1525                   coverage->lines_executed++;
1526               }
1527             line->exists = 1;
1528             line->count += block->count;
1529           }
1530       free (block->u.line.encoding);
1531       block->u.cycle.arc = NULL;
1532       block->u.cycle.ident = ~0U;
1533
1534       if (!ix || ix + 1 == fn->num_blocks)
1535         /* Entry or exit block */;
1536       else if (flag_all_blocks)
1537         {
1538           line_t *block_line = line ? line : &fn->src->lines[fn->line];
1539
1540           block->chain = block_line->u.blocks;
1541           block_line->u.blocks = block;
1542         }
1543       else if (flag_branches)
1544         {
1545           arc_t *arc;
1546
1547           for (arc = block->succ; arc; arc = arc->succ_next)
1548             {
1549               arc->line_next = line->u.branches;
1550               line->u.branches = arc;
1551               if (coverage && !arc->is_unconditional)
1552                 add_branch_counts (coverage, arc);
1553             }
1554         }
1555     }
1556   if (!line)
1557     fnotice (stderr, "%s:no lines for `%s'\n", bbg_file_name, fn->name);
1558 }
1559
1560 /* Accumulate the line counts of a file.  */
1561
1562 static void
1563 accumulate_line_counts (source_t *src)
1564 {
1565   line_t *line;
1566   function_t *fn, *fn_p, *fn_n;
1567   unsigned ix;
1568
1569   /* Reverse the function order.  */
1570   for (fn = src->functions, fn_p = NULL; fn;
1571        fn_p = fn, fn = fn_n)
1572     {
1573       fn_n = fn->line_next;
1574       fn->line_next = fn_p;
1575     }
1576   src->functions = fn_p;
1577
1578   for (ix = src->num_lines, line = src->lines; ix--; line++)
1579     {
1580       if (!flag_all_blocks)
1581         {
1582           arc_t *arc, *arc_p, *arc_n;
1583
1584           /* Total and reverse the branch information.  */
1585           for (arc = line->u.branches, arc_p = NULL; arc;
1586                arc_p = arc, arc = arc_n)
1587             {
1588               arc_n = arc->line_next;
1589               arc->line_next = arc_p;
1590
1591               add_branch_counts (&src->coverage, arc);
1592             }
1593           line->u.branches = arc_p;
1594         }
1595       else if (line->u.blocks)
1596         {
1597           /* The user expects the line count to be the number of times
1598              a line has been executed. Simply summing the block count
1599              will give an artificially high number.  The Right Thing
1600              is to sum the entry counts to the graph of blocks on this
1601              line, then find the elementary cycles of the local graph
1602              and add the transition counts of those cycles.  */
1603           block_t *block, *block_p, *block_n;
1604           gcov_type count = 0;
1605
1606           /* Reverse the block information.  */
1607           for (block = line->u.blocks, block_p = NULL; block;
1608                block_p = block, block = block_n)
1609             {
1610               block_n = block->chain;
1611               block->chain = block_p;
1612               block->u.cycle.ident = ix;
1613             }
1614           line->u.blocks = block_p;
1615
1616           /* Sum the entry arcs.  */
1617           for (block = line->u.blocks; block; block = block->chain)
1618             {
1619               arc_t *arc;
1620
1621               for (arc = block->pred; arc; arc = arc->pred_next)
1622                 {
1623                   if (arc->src->u.cycle.ident != ix)
1624                     count += arc->count;
1625                   if (flag_branches)
1626                     add_branch_counts (&src->coverage, arc);
1627                 }
1628
1629               /* Initialize the cs_count.  */
1630               for (arc = block->succ; arc; arc = arc->succ_next)
1631                 arc->cs_count = arc->count;
1632             }
1633
1634           /* Find the loops. This uses the algorithm described in
1635              Tiernan 'An Efficient Search Algorithm to Find the
1636              Elementary Circuits of a Graph', CACM Dec 1970. We hold
1637              the P array by having each block point to the arc that
1638              connects to the previous block. The H array is implicitly
1639              held because of the arc ordering, and the block's
1640              previous arc pointer.
1641
1642              Although the algorithm is O(N^3) for highly connected
1643              graphs, at worst we'll have O(N^2), as most blocks have
1644              only one or two exits. Most graphs will be small.
1645
1646              For each loop we find, locate the arc with the smallest
1647              transition count, and add that to the cumulative
1648              count.  Decrease flow over the cycle and remove the arc
1649              from consideration.  */
1650           for (block = line->u.blocks; block; block = block->chain)
1651             {
1652               block_t *head = block;
1653               arc_t *arc;
1654
1655             next_vertex:;
1656               arc = head->succ;
1657             current_vertex:;
1658               while (arc)
1659                 {
1660                   block_t *dst = arc->dst;
1661                   if (/* Already used that arc.  */
1662                       arc->cycle
1663                       /* Not to same graph, or before first vertex.  */
1664                       || dst->u.cycle.ident != ix
1665                       /* Already in path.  */
1666                       || dst->u.cycle.arc)
1667                     {
1668                       arc = arc->succ_next;
1669                       continue;
1670                     }
1671
1672                   if (dst == block)
1673                     {
1674                       /* Found a closing arc.  */
1675                       gcov_type cycle_count = arc->cs_count;
1676                       arc_t *cycle_arc = arc;
1677                       arc_t *probe_arc;
1678
1679                       /* Locate the smallest arc count of the loop.  */
1680                       for (dst = head; (probe_arc = dst->u.cycle.arc);
1681                            dst = probe_arc->src)
1682                         if (cycle_count > probe_arc->cs_count)
1683                           {
1684                             cycle_count = probe_arc->cs_count;
1685                             cycle_arc = probe_arc;
1686                           }
1687
1688                       count += cycle_count;
1689                       cycle_arc->cycle = 1;
1690
1691                       /* Remove the flow from the cycle.  */
1692                       arc->cs_count -= cycle_count;
1693                       for (dst = head; (probe_arc = dst->u.cycle.arc);
1694                            dst = probe_arc->src)
1695                         probe_arc->cs_count -= cycle_count;
1696
1697                       /* Unwind to the cyclic arc.  */
1698                       while (head != cycle_arc->src)
1699                         {
1700                           arc = head->u.cycle.arc;
1701                           head->u.cycle.arc = NULL;
1702                           head = arc->src;
1703                         }
1704                       /* Move on.  */
1705                       arc = arc->succ_next;
1706                       continue;
1707                     }
1708
1709                   /* Add new block to chain.  */
1710                   dst->u.cycle.arc = arc;
1711                   head = dst;
1712                   goto next_vertex;
1713                 }
1714               /* We could not add another vertex to the path. Remove
1715                  the last vertex from the list.  */
1716               arc = head->u.cycle.arc;
1717               if (arc)
1718                 {
1719                   /* It was not the first vertex. Move onto next arc.  */
1720                   head->u.cycle.arc = NULL;
1721                   head = arc->src;
1722                   arc = arc->succ_next;
1723                   goto current_vertex;
1724                 }
1725               /* Mark this block as unusable.  */
1726               block->u.cycle.ident = ~0U;
1727             }
1728
1729           line->count = count;
1730         }
1731
1732       if (line->exists)
1733         {
1734           src->coverage.lines++;
1735           if (line->count)
1736             src->coverage.lines_executed++;
1737         }
1738     }
1739 }
1740
1741 /* Ouput information about ARC number IX.  Returns nonzero if
1742    anything is output.  */
1743
1744 static int
1745 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1746 {
1747
1748   if (arc->is_call_non_return)
1749     {
1750       if (arc->src->count)
1751         {
1752           fnotice (gcov_file, "call   %2d returned %s\n", ix,
1753                    format_gcov (arc->src->count - arc->count,
1754                                 arc->src->count, -flag_counts));
1755         }
1756       else
1757         fnotice (gcov_file, "call   %2d never executed\n", ix);
1758     }
1759   else if (!arc->is_unconditional)
1760     {
1761       if (arc->src->count)
1762         fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1763                  format_gcov (arc->count, arc->src->count, -flag_counts),
1764                  arc->fall_through ? " (fallthrough)" : "");
1765       else
1766         fnotice (gcov_file, "branch %2d never executed\n", ix);
1767     }
1768   else if (flag_unconditional && !arc->dst->is_call_return)
1769     {
1770       if (arc->src->count)
1771         fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1772                  format_gcov (arc->count, arc->src->count, -flag_counts));
1773       else
1774         fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1775     }
1776   else
1777     return 0;
1778   return 1;
1779
1780 }
1781
1782 /* Read in the source file one line at a time, and output that line to
1783    the gcov file preceded by its execution count and other
1784    information.  */
1785
1786 static void
1787 output_lines (FILE *gcov_file, const source_t *src)
1788 {
1789   FILE *source_file;
1790   unsigned line_num;    /* current line number.  */
1791   const line_t *line;           /* current line info ptr.  */
1792   char string[STRING_SIZE];     /* line buffer.  */
1793   char const *retval = "";      /* status of source file reading.  */
1794   function_t *fn = src->functions;
1795
1796   fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1797   fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1798   fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
1799   fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1800            object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1801   fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1802
1803   source_file = fopen (src->name, "r");
1804   if (!source_file)
1805     {
1806       fnotice (stderr, "%s:cannot open source file\n", src->name);
1807       retval = NULL;
1808     }
1809   else
1810     {
1811       struct stat status;
1812
1813       if (!fstat (fileno (source_file), &status)
1814           && status.st_mtime > bbg_file_time)
1815         {
1816           fnotice (stderr, "%s:source file is newer than graph file `%s'\n",
1817                    src->name, bbg_file_name);
1818           fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1819                    "-", 0);
1820         }
1821     }
1822
1823   for (line_num = 1, line = &src->lines[line_num];
1824        line_num < src->num_lines; line_num++, line++)
1825     {
1826       for (; fn && fn->line == line_num; fn = fn->line_next)
1827         {
1828           arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1829           gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1830
1831           for (; arc; arc = arc->pred_next)
1832             if (arc->fake)
1833               return_count -= arc->count;
1834
1835           fprintf (gcov_file, "function %s", fn->name);
1836           fprintf (gcov_file, " called %s",
1837                    format_gcov (fn->blocks[0].count, 0, -1));
1838           fprintf (gcov_file, " returned %s",
1839                    format_gcov (return_count, fn->blocks[0].count, 0));
1840           fprintf (gcov_file, " blocks executed %s",
1841                    format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1842           fprintf (gcov_file, "\n");
1843         }
1844
1845       /* For lines which don't exist in the .bb file, print '-' before
1846          the source line.  For lines which exist but were never
1847          executed, print '#####' before the source line.  Otherwise,
1848          print the execution count before the source line.  There are
1849          16 spaces of indentation added before the source line so that
1850          tabs won't be messed up.  */
1851       fprintf (gcov_file, "%9s:%5u:",
1852                !line->exists ? "-" : !line->count ? "#####"
1853                : format_gcov (line->count, 0, -1), line_num);
1854
1855       if (retval)
1856         {
1857           /* Copy source line.  */
1858           do
1859             {
1860               retval = fgets (string, STRING_SIZE, source_file);
1861               if (!retval)
1862                 break;
1863               fputs (retval, gcov_file);
1864             }
1865           while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1866         }
1867       if (!retval)
1868         fputs ("/*EOF*/\n", gcov_file);
1869
1870       if (flag_all_blocks)
1871         {
1872           block_t *block;
1873           arc_t *arc;
1874           int ix, jx;
1875
1876           for (ix = jx = 0, block = line->u.blocks; block;
1877                block = block->chain)
1878             {
1879               if (!block->is_call_return)
1880                 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1881                          !line->exists ? "-" : !block->count ? "$$$$$"
1882                          : format_gcov (block->count, 0, -1),
1883                          line_num, ix++);
1884               if (flag_branches)
1885                 for (arc = block->succ; arc; arc = arc->succ_next)
1886                   jx += output_branch_count (gcov_file, jx, arc);
1887             }
1888         }
1889       else if (flag_branches)
1890         {
1891           int ix;
1892           arc_t *arc;
1893
1894           for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1895             ix += output_branch_count (gcov_file, ix, arc);
1896         }
1897     }
1898
1899   /* Handle all remaining source lines.  There may be lines after the
1900      last line of code.  */
1901   if (retval)
1902     {
1903       for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1904         {
1905           fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1906
1907           while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1908             {
1909               retval = fgets (string, STRING_SIZE, source_file);
1910               if (!retval)
1911                 break;
1912               fputs (retval, gcov_file);
1913             }
1914         }
1915     }
1916
1917   if (source_file)
1918     fclose (source_file);
1919 }