OSDN Git Service

* config/xtensa/xtensa.c (xtensa_multibss_section_type_flags): Add
[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 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   fnotice (stdout, "Copyright (C) 2003 Free Software Foundation, Inc.\n");
424   fnotice (stdout,
425            "This is free software; see the source for copying conditions.\n"
426            "There is NO warranty; not even for MERCHANTABILITY or \n"
427            "FITNESS FOR A PARTICULAR PURPOSE.\n\n");
428   exit (SUCCESS_EXIT_CODE);
429 }
430
431 static const struct option options[] =
432 {
433   { "help",                 no_argument,       NULL, 'h' },
434   { "version",              no_argument,       NULL, 'v' },
435   { "all-blocks",           no_argument,       NULL, 'a' },
436   { "branch-probabilities", no_argument,       NULL, 'b' },
437   { "branch-counts",        no_argument,       NULL, 'c' },
438   { "no-output",            no_argument,       NULL, 'n' },
439   { "long-file-names",      no_argument,       NULL, 'l' },
440   { "function-summaries",   no_argument,       NULL, 'f' },
441   { "preserve-paths",       no_argument,       NULL, 'p' },
442   { "object-directory",     required_argument, NULL, 'o' },
443   { "object-file",          required_argument, NULL, 'o' },
444   { "unconditional-branches", no_argument,     NULL, 'u' },
445   { 0, 0, 0, 0 }
446 };
447
448 /* Process args, return index to first non-arg.  */
449
450 static int
451 process_args (int argc, char **argv)
452 {
453   int opt;
454
455   while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
456     {
457       switch (opt)
458         {
459         case 'a':
460           flag_all_blocks = 1;
461           break;
462         case 'b':
463           flag_branches = 1;
464           break;
465         case 'c':
466           flag_counts = 1;
467           break;
468         case 'f':
469           flag_function_summary = 1;
470           break;
471         case 'h':
472           print_usage (false);
473           /* print_usage will exit.  */
474         case 'l':
475           flag_long_names = 1;
476           break;
477         case 'n':
478           flag_gcov_file = 0;
479           break;
480         case 'o':
481           object_directory = optarg;
482           break;
483         case 'p':
484           flag_preserve_paths = 1;
485           break;
486         case 'u':
487           flag_unconditional = 1;
488           break;
489         case 'v':
490           print_version ();
491           /* print_version will exit.  */
492         default:
493           print_usage (true);
494           /* print_usage will exit.  */
495         }
496     }
497
498   return optind;
499 }
500
501 /* Process a single source file.  */
502
503 static void
504 process_file (const char *file_name)
505 {
506   source_t *src;
507   function_t *fn;
508
509   create_file_names (file_name);
510   if (read_graph_file ())
511     return;
512
513   if (!functions)
514     {
515       fnotice (stderr, "%s:no functions found\n", bbg_file_name);
516       return;
517     }
518
519   if (read_count_file ())
520     return;
521
522   for (fn = functions; fn; fn = fn->next)
523     solve_flow_graph (fn);
524   for (src = sources; src; src = src->next)
525     src->lines = xcalloc (src->num_lines, sizeof (line_t));
526   for (fn = functions; fn; fn = fn->next)
527     {
528       coverage_t coverage;
529
530       memset (&coverage, 0, sizeof (coverage));
531       coverage.name = fn->name;
532       add_line_counts (flag_function_summary ? &coverage : NULL, fn);
533       if (flag_function_summary)
534         {
535           function_summary (&coverage, "Function");
536           fnotice (stdout, "\n");
537         }
538     }
539
540   for (src = sources; src; src = src->next)
541     {
542       accumulate_line_counts (src);
543       function_summary (&src->coverage, "File");
544       if (flag_gcov_file)
545         {
546           char *gcov_file_name = make_gcov_file_name (file_name, src->name);
547           FILE *gcov_file = fopen (gcov_file_name, "w");
548
549           if (gcov_file)
550             {
551               fnotice (stdout, "%s:creating `%s'\n",
552                        src->name, gcov_file_name);
553               output_lines (gcov_file, src);
554               if (ferror (gcov_file))
555                     fnotice (stderr, "%s:error writing output file `%s'\n",
556                              src->name, gcov_file_name);
557               fclose (gcov_file);
558             }
559           else
560             fnotice (stderr, "%s:could not open output file `%s'\n",
561                      src->name, gcov_file_name);
562           free (gcov_file_name);
563         }
564       fnotice (stdout, "\n");
565     }
566 }
567
568 /* Release all memory used.  */
569
570 static void
571 release_structures (void)
572 {
573   function_t *fn;
574   source_t *src;
575
576   free (bbg_file_name);
577   free (da_file_name);
578   da_file_name = bbg_file_name = NULL;
579   bbg_file_time = 0;
580   bbg_stamp = 0;
581
582   while ((src = sources))
583     {
584       sources = src->next;
585
586       free (src->name);
587       free (src->lines);
588     }
589
590   while ((fn = functions))
591     {
592       unsigned ix;
593       block_t *block;
594
595       functions = fn->next;
596       for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
597         {
598           arc_t *arc, *arc_n;
599
600           for (arc = block->succ; arc; arc = arc_n)
601             {
602               arc_n = arc->succ_next;
603               free (arc);
604             }
605         }
606       free (fn->blocks);
607       free (fn->counts);
608     }
609 }
610
611 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
612    is not specified, these are looked for in the current directory,
613    and named from the basename of the FILE_NAME sans extension. If
614    OBJECT_DIRECTORY is specified and is a directory, the files are in
615    that directory, but named from the basename of the FILE_NAME, sans
616    extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
617    the object *file*, and the data files are named from that.  */
618
619 static void
620 create_file_names (const char *file_name)
621 {
622   char *cptr;
623   char *name;
624   int length = strlen (file_name);
625   int base;
626
627   if (object_directory && object_directory[0])
628     {
629       struct stat status;
630
631       length += strlen (object_directory) + 2;
632       name = xmalloc (length);
633       name[0] = 0;
634
635       base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
636       strcat (name, object_directory);
637       if (base && name[strlen (name) - 1] != '/')
638         strcat (name, "/");
639     }
640   else
641     {
642       name = xmalloc (length + 1);
643       name[0] = 0;
644       base = 1;
645     }
646
647   if (base)
648     {
649       /* Append source file name.  */
650       cptr = strrchr (file_name, '/');
651       strcat (name, cptr ? cptr + 1 : file_name);
652     }
653
654   /* Remove the extension.  */
655   cptr = strrchr (name, '.');
656   if (cptr)
657     *cptr = 0;
658
659   length = strlen (name);
660   
661   bbg_file_name = xmalloc (length + strlen (GCOV_NOTE_SUFFIX) + 1);
662   strcpy (bbg_file_name, name);
663   strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
664
665   da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
666   strcpy (da_file_name, name);
667   strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
668
669   return;
670 }
671
672 /* Find or create a source file structure for FILE_NAME. Copies
673    FILE_NAME on creation */
674
675 static source_t *
676 find_source (const char *file_name)
677 {
678   source_t *src;
679
680   if (!file_name)
681     file_name = "<unknown>";
682
683   for (src = sources; src; src = src->next)
684     if (!strcmp (file_name, src->name))
685       return src;
686
687   src = xcalloc (1, sizeof (source_t));
688   src->name = xstrdup (file_name);
689   src->coverage.name = src->name;
690   src->index = sources ? sources->index + 1 : 1;
691   src->next = sources;
692   sources = src;
693
694   return src;
695 }
696
697 /* Read the graph file. Return nonzero on fatal error.  */
698
699 static int
700 read_graph_file (void)
701 {
702   unsigned version;
703   unsigned current_tag = 0;
704   struct function_info *fn = NULL;
705   source_t *src = NULL;
706   unsigned ix;
707   unsigned tag;
708
709   if (!gcov_open (bbg_file_name, 1))
710     {
711       fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
712       return 1;
713     }
714   bbg_file_time = gcov_time ();
715   if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
716     {
717       fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
718       gcov_close ();
719       return 1;
720     }
721
722   version = gcov_read_unsigned ();
723   if (version != GCOV_VERSION)
724     {
725       char v[4], e[4];
726
727       GCOV_UNSIGNED2STRING (v, version);
728       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
729
730       fnotice (stderr, "%s:version `%.4s', prefer `%.4s'\n",
731                bbg_file_name, v, e);
732     }
733   bbg_stamp = gcov_read_unsigned ();
734
735   while ((tag = gcov_read_unsigned ()))
736     {
737       unsigned length = gcov_read_unsigned ();
738       gcov_position_t base = gcov_position ();
739
740       if (tag == GCOV_TAG_FUNCTION)
741         {
742           char *function_name;
743           unsigned ident, checksum, lineno;
744           source_t *src;
745           function_t *probe, *prev;
746
747           ident = gcov_read_unsigned ();
748           checksum = gcov_read_unsigned ();
749           function_name = xstrdup (gcov_read_string ());
750           src = find_source (gcov_read_string ());
751           lineno = gcov_read_unsigned ();
752
753           fn = xcalloc (1, sizeof (function_t));
754           fn->name = function_name;
755           fn->ident = ident;
756           fn->checksum = checksum;
757           fn->src = src;
758           fn->line = lineno;
759
760           fn->next = functions;
761           functions = fn;
762           current_tag = tag;
763
764           if (lineno >= src->num_lines)
765             src->num_lines = lineno + 1;
766           /* Now insert it into the source file's list of
767              functions. Normally functions will be encountered in
768              ascending order, so a simple scan is quick.  */
769           for (probe = src->functions, prev = NULL;
770                probe && probe->line > lineno;
771                prev = probe, probe = probe->line_next)
772             continue;
773           fn->line_next = probe;
774           if (prev)
775             prev->line_next = fn;
776           else
777             src->functions = fn;
778         }
779       else if (fn && tag == GCOV_TAG_BLOCKS)
780         {
781           if (fn->blocks)
782             fnotice (stderr, "%s:already seen blocks for `%s'\n",
783                      bbg_file_name, fn->name);
784           else
785             {
786               unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
787               fn->num_blocks = num_blocks;
788
789               fn->blocks = xcalloc (fn->num_blocks, sizeof (block_t));
790               for (ix = 0; ix != num_blocks; ix++)
791                 fn->blocks[ix].flags = gcov_read_unsigned ();
792             }
793         }
794       else if (fn && tag == GCOV_TAG_ARCS)
795         {
796           unsigned src = gcov_read_unsigned ();
797           unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
798
799           if (src >= fn->num_blocks || fn->blocks[src].succ)
800             goto corrupt;
801
802           while (num_dests--)
803             {
804               struct arc_info *arc;
805               unsigned dest = gcov_read_unsigned ();
806               unsigned flags = gcov_read_unsigned ();
807
808               if (dest >= fn->num_blocks)
809                 goto corrupt;
810               arc = xcalloc (1, sizeof (arc_t));
811
812               arc->dst = &fn->blocks[dest];
813               arc->src = &fn->blocks[src];
814
815               arc->count = 0;
816               arc->count_valid = 0;
817               arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
818               arc->fake = !!(flags & GCOV_ARC_FAKE);
819               arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
820
821               arc->succ_next = fn->blocks[src].succ;
822               fn->blocks[src].succ = arc;
823               fn->blocks[src].num_succ++;
824
825               arc->pred_next = fn->blocks[dest].pred;
826               fn->blocks[dest].pred = arc;
827               fn->blocks[dest].num_pred++;
828
829               if (arc->fake)
830                 {
831                   if (src)
832                     {
833                       /* Exceptional exit from this function, the
834                          source block must be a call.  */
835                       fn->blocks[src].is_call_site = 1;
836                       arc->is_call_non_return = 1;
837                     }
838                   else
839                     {
840                       /* Non-local return from a callee of this
841                          function. The destination block is a catch or
842                          setjmp.  */
843                       arc->is_nonlocal_return = 1;
844                       fn->blocks[dest].is_nonlocal_return = 1;
845                     }
846                 }
847
848               if (!arc->on_tree)
849                 fn->num_counts++;
850             }
851         }
852       else if (fn && tag == GCOV_TAG_LINES)
853         {
854           unsigned blockno = gcov_read_unsigned ();
855           unsigned *line_nos = xcalloc (length - 1, sizeof (unsigned));
856
857           if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
858             goto corrupt;
859
860           for (ix = 0; ;  )
861             {
862               unsigned lineno = gcov_read_unsigned ();
863
864               if (lineno)
865                 {
866                   if (!ix)
867                     {
868                       line_nos[ix++] = 0;
869                       line_nos[ix++] = src->index;
870                     }
871                   line_nos[ix++] = lineno;
872                   if (lineno >= src->num_lines)
873                     src->num_lines = lineno + 1;
874                 }
875               else
876                 {
877                   const char *file_name = gcov_read_string ();
878
879                   if (!file_name)
880                     break;
881                   src = find_source (file_name);
882
883                   line_nos[ix++] = 0;
884                   line_nos[ix++] = src->index;
885                 }
886             }
887
888           fn->blocks[blockno].u.line.encoding = line_nos;
889           fn->blocks[blockno].u.line.num = ix;
890         }
891       else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
892         {
893           fn = NULL;
894           current_tag = 0;
895         }
896       gcov_sync (base, length);
897       if (gcov_is_error ())
898         break;
899     }
900   if (!gcov_is_eof ())
901     {
902     corrupt:;
903       fnotice (stderr, "%s:corrupted\n", bbg_file_name);
904       gcov_close ();
905       return 1;
906     }
907   gcov_close ();
908
909   /* We built everything backwards, so nreverse them all */
910
911   /* Reverse sources. Not strictly necessary, but we'll then process
912      them in the 'expected' order.  */
913   {
914     source_t *src, *src_p, *src_n;
915
916     for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
917       {
918         src_n = src->next;
919         src->next = src_p;
920       }
921     sources =  src_p;
922   }
923
924   /* Reverse functions.  */
925   {
926     function_t *fn, *fn_p, *fn_n;
927
928     for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
929       {
930         unsigned ix;
931
932         fn_n = fn->next;
933         fn->next = fn_p;
934
935         /* Reverse the arcs.  */
936         for (ix = fn->num_blocks; ix--;)
937           {
938             arc_t *arc, *arc_p, *arc_n;
939
940             for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
941                  arc_p = arc, arc = arc_n)
942               {
943                 arc_n = arc->succ_next;
944                 arc->succ_next = arc_p;
945               }
946             fn->blocks[ix].succ = arc_p;
947
948             for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
949                  arc_p = arc, arc = arc_n)
950               {
951                 arc_n = arc->pred_next;
952                 arc->pred_next = arc_p;
953               }
954             fn->blocks[ix].pred = arc_p;
955           }
956       }
957     functions = fn_p;
958   }
959   return 0;
960 }
961
962 /* Reads profiles from the count file and attach to each
963    function. Return nonzero if fatal error.  */
964
965 static int
966 read_count_file (void)
967 {
968   unsigned ix;
969   unsigned version;
970   unsigned tag;
971   function_t *fn = NULL;
972   int error = 0;
973
974   if (!gcov_open (da_file_name, 1))
975     {
976       fnotice (stderr, "%s:cannot open data file\n", da_file_name);
977       return 1;
978     }
979   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
980     {
981       fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
982     cleanup:;
983       gcov_close ();
984       return 1;
985     }
986   version = gcov_read_unsigned ();
987   if (version != GCOV_VERSION)
988     {
989       char v[4], e[4];
990
991       GCOV_UNSIGNED2STRING (v, version);
992       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
993       
994       fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
995                da_file_name, v, e);
996     }
997   tag = gcov_read_unsigned ();
998   if (tag != bbg_stamp)
999     {
1000       fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1001       goto cleanup;
1002     }
1003
1004   while ((tag = gcov_read_unsigned ()))
1005     {
1006       unsigned length = gcov_read_unsigned ();
1007       unsigned long base = gcov_position ();
1008
1009       if (tag == GCOV_TAG_OBJECT_SUMMARY)
1010         gcov_read_summary (&object_summary);
1011       else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1012         program_count++;
1013       else if (tag == GCOV_TAG_FUNCTION)
1014         {
1015           unsigned ident = gcov_read_unsigned ();
1016           struct function_info *fn_n = functions;
1017
1018           for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1019             {
1020               if (fn)
1021                 ;
1022               else if ((fn = fn_n))
1023                 fn_n = NULL;
1024               else
1025                 {
1026                   fnotice (stderr, "%s:unknown function `%u'\n",
1027                            da_file_name, ident);
1028                   break;
1029                 }
1030               if (fn->ident == ident)
1031                 break;
1032             }
1033
1034           if (!fn)
1035             ;
1036           else if (gcov_read_unsigned () != fn->checksum)
1037             {
1038             mismatch:;
1039               fnotice (stderr, "%s:profile mismatch for `%s'\n",
1040                        da_file_name, fn->name);
1041               goto cleanup;
1042             }
1043         }
1044       else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1045         {
1046           if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1047             goto mismatch;
1048
1049           if (!fn->counts)
1050             fn->counts = xcalloc (fn->num_counts, sizeof (gcov_type));
1051
1052           for (ix = 0; ix != fn->num_counts; ix++)
1053             fn->counts[ix] += gcov_read_counter ();
1054         }
1055       gcov_sync (base, length);
1056       if ((error = gcov_is_error ()))
1057         break;
1058     }
1059
1060   if (!gcov_is_eof ())
1061     {
1062       fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1063                da_file_name);
1064       goto cleanup;
1065     }
1066
1067   gcov_close ();
1068   return 0;
1069 }
1070
1071 /* Solve the flow graph. Propagate counts from the instrumented arcs
1072    to the blocks and the uninstrumented arcs.  */
1073
1074 static void
1075 solve_flow_graph (function_t *fn)
1076 {
1077   unsigned ix;
1078   arc_t *arc;
1079   gcov_type *count_ptr = fn->counts;
1080   block_t *blk;
1081   block_t *valid_blocks = NULL;    /* valid, but unpropagated blocks.  */
1082   block_t *invalid_blocks = NULL;  /* invalid, but inferable blocks.  */
1083
1084   if (fn->num_blocks < 2)
1085     fnotice (stderr, "%s:`%s' lacks entry and/or exit blocks\n",
1086              bbg_file_name, fn->name);
1087   else
1088     {
1089       if (fn->blocks[0].num_pred)
1090         fnotice (stderr, "%s:`%s' has arcs to entry block\n",
1091                  bbg_file_name, fn->name);
1092       else
1093         /* We can't deduce the entry block counts from the lack of
1094            predecessors.  */
1095         fn->blocks[0].num_pred = ~(unsigned)0;
1096
1097       if (fn->blocks[fn->num_blocks - 1].num_succ)
1098         fnotice (stderr, "%s:`%s' has arcs from exit block\n",
1099                  bbg_file_name, fn->name);
1100       else
1101         /* Likewise, we can't deduce exit block counts from the lack
1102            of its successors.  */
1103         fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1104     }
1105
1106   /* Propagate the measured counts, this must be done in the same
1107      order as the code in profile.c  */
1108   for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1109     {
1110       block_t const *prev_dst = NULL;
1111       int out_of_order = 0;
1112       int non_fake_succ = 0;
1113
1114       for (arc = blk->succ; arc; arc = arc->succ_next)
1115         {
1116           if (!arc->fake)
1117             non_fake_succ++;
1118
1119           if (!arc->on_tree)
1120             {
1121               if (count_ptr)
1122                 arc->count = *count_ptr++;
1123               arc->count_valid = 1;
1124               blk->num_succ--;
1125               arc->dst->num_pred--;
1126             }
1127           if (prev_dst && prev_dst > arc->dst)
1128             out_of_order = 1;
1129           prev_dst = arc->dst;
1130         }
1131       if (non_fake_succ == 1)
1132         {
1133           /* If there is only one non-fake exit, it is an
1134              unconditional branch.  */
1135           for (arc = blk->succ; arc; arc = arc->succ_next)
1136             if (!arc->fake)
1137               {
1138                 arc->is_unconditional = 1;
1139                 /* If this block is instrumenting a call, it might be
1140                    an artificial block. It is not artificial if it has
1141                    a non-fallthrough exit, or the destination of this
1142                    arc has more than one entry.  Mark the destination
1143                    block as a return site, if none of those conditions
1144                    hold.  */
1145                 if (blk->is_call_site && arc->fall_through
1146                     && arc->dst->pred == arc && !arc->pred_next)
1147                   arc->dst->is_call_return = 1;
1148               }
1149         }
1150
1151       /* Sort the successor arcs into ascending dst order. profile.c
1152          normally produces arcs in the right order, but sometimes with
1153          one or two out of order.  We're not using a particularly
1154          smart sort.  */
1155       if (out_of_order)
1156         {
1157           arc_t *start = blk->succ;
1158           unsigned changes = 1;
1159
1160           while (changes)
1161             {
1162               arc_t *arc, *arc_p, *arc_n;
1163
1164               changes = 0;
1165               for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1166                 {
1167                   if (arc->dst > arc_n->dst)
1168                     {
1169                       changes = 1;
1170                       if (arc_p)
1171                         arc_p->succ_next = arc_n;
1172                       else
1173                         start = arc_n;
1174                       arc->succ_next = arc_n->succ_next;
1175                       arc_n->succ_next = arc;
1176                       arc_p = arc_n;
1177                     }
1178                   else
1179                     {
1180                       arc_p = arc;
1181                       arc = arc_n;
1182                     }
1183                 }
1184             }
1185           blk->succ = start;
1186         }
1187
1188       /* Place it on the invalid chain, it will be ignored if that's
1189          wrong.  */
1190       blk->invalid_chain = 1;
1191       blk->chain = invalid_blocks;
1192       invalid_blocks = blk;
1193     }
1194
1195   while (invalid_blocks || valid_blocks)
1196     {
1197       while ((blk = invalid_blocks))
1198         {
1199           gcov_type total = 0;
1200           const arc_t *arc;
1201
1202           invalid_blocks = blk->chain;
1203           blk->invalid_chain = 0;
1204           if (!blk->num_succ)
1205             for (arc = blk->succ; arc; arc = arc->succ_next)
1206               total += arc->count;
1207           else if (!blk->num_pred)
1208             for (arc = blk->pred; arc; arc = arc->pred_next)
1209               total += arc->count;
1210           else
1211             continue;
1212
1213           blk->count = total;
1214           blk->count_valid = 1;
1215           blk->chain = valid_blocks;
1216           blk->valid_chain = 1;
1217           valid_blocks = blk;
1218         }
1219       while ((blk = valid_blocks))
1220         {
1221           gcov_type total;
1222           arc_t *arc, *inv_arc;
1223
1224           valid_blocks = blk->chain;
1225           blk->valid_chain = 0;
1226           if (blk->num_succ == 1)
1227             {
1228               block_t *dst;
1229
1230               total = blk->count;
1231               inv_arc = NULL;
1232               for (arc = blk->succ; arc; arc = arc->succ_next)
1233                 {
1234                   total -= arc->count;
1235                   if (!arc->count_valid)
1236                     inv_arc = arc;
1237                 }
1238               dst = inv_arc->dst;
1239               inv_arc->count_valid = 1;
1240               inv_arc->count = total;
1241               blk->num_succ--;
1242               dst->num_pred--;
1243               if (dst->count_valid)
1244                 {
1245                   if (dst->num_pred == 1 && !dst->valid_chain)
1246                     {
1247                       dst->chain = valid_blocks;
1248                       dst->valid_chain = 1;
1249                       valid_blocks = dst;
1250                     }
1251                 }
1252               else
1253                 {
1254                   if (!dst->num_pred && !dst->invalid_chain)
1255                     {
1256                       dst->chain = invalid_blocks;
1257                       dst->invalid_chain = 1;
1258                       invalid_blocks = dst;
1259                     }
1260                 }
1261             }
1262           if (blk->num_pred == 1)
1263             {
1264               block_t *src;
1265
1266               total = blk->count;
1267               inv_arc = NULL;
1268               for (arc = blk->pred; arc; arc = arc->pred_next)
1269                 {
1270                   total -= arc->count;
1271                   if (!arc->count_valid)
1272                     inv_arc = arc;
1273                 }
1274               src = inv_arc->src;
1275               inv_arc->count_valid = 1;
1276               inv_arc->count = total;
1277               blk->num_pred--;
1278               src->num_succ--;
1279               if (src->count_valid)
1280                 {
1281                   if (src->num_succ == 1 && !src->valid_chain)
1282                     {
1283                       src->chain = valid_blocks;
1284                       src->valid_chain = 1;
1285                       valid_blocks = src;
1286                     }
1287                 }
1288               else
1289                 {
1290                   if (!src->num_succ && !src->invalid_chain)
1291                     {
1292                       src->chain = invalid_blocks;
1293                       src->invalid_chain = 1;
1294                       invalid_blocks = src;
1295                     }
1296                 }
1297             }
1298         }
1299     }
1300
1301   /* If the graph has been correctly solved, every block will have a
1302      valid count.  */
1303   for (ix = 0; ix < fn->num_blocks; ix++)
1304     if (!fn->blocks[ix].count_valid)
1305       {
1306         fnotice (stderr, "%s:graph is unsolvable for `%s'\n",
1307                  bbg_file_name, fn->name);
1308         break;
1309       }
1310 }
1311
1312 \f
1313
1314 /* Increment totals in COVERAGE according to arc ARC.  */
1315
1316 static void
1317 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1318 {
1319   if (arc->is_call_non_return)
1320     {
1321       coverage->calls++;
1322       if (arc->src->count)
1323         coverage->calls_executed++;
1324     }
1325   else if (!arc->is_unconditional)
1326     {
1327       coverage->branches++;
1328       if (arc->src->count)
1329         coverage->branches_executed++;
1330       if (arc->count)
1331         coverage->branches_taken++;
1332     }
1333 }
1334
1335 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1336    count.  If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1337    If DP is zero, no decimal point is printed. Only print 100% when
1338    TOP==BOTTOM and only print 0% when TOP=0.  If dp < 0, then simply
1339    format TOP.  Return pointer to a static string.  */
1340
1341 static char const *
1342 format_gcov (gcov_type top, gcov_type bottom, int dp)
1343 {
1344   static char buffer[20];
1345
1346   if (dp >= 0)
1347     {
1348       float ratio = bottom ? (float)top / bottom : 0;
1349       int ix;
1350       unsigned limit = 100;
1351       unsigned percent;
1352
1353       for (ix = dp; ix--; )
1354         limit *= 10;
1355
1356       percent = (unsigned) (ratio * limit + (float)0.5);
1357       if (percent <= 0 && top)
1358         percent = 1;
1359       else if (percent >= limit && top != bottom)
1360         percent = limit - 1;
1361       ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1362       if (dp)
1363         {
1364           dp++;
1365           do
1366             {
1367               buffer[ix+1] = buffer[ix];
1368               ix--;
1369             }
1370           while (dp--);
1371           buffer[ix + 1] = '.';
1372         }
1373     }
1374   else
1375     sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1376
1377   return buffer;
1378 }
1379
1380
1381 /* Output summary info for a function.  */
1382
1383 static void
1384 function_summary (const coverage_t *coverage, const char *title)
1385 {
1386   fnotice (stdout, "%s `%s'\n", title, coverage->name);
1387
1388   if (coverage->lines)
1389     fnotice (stdout, "Lines executed:%s of %d\n",
1390              format_gcov (coverage->lines_executed, coverage->lines, 2),
1391              coverage->lines);
1392   else
1393     fnotice (stdout, "No executable lines");
1394
1395   if (flag_branches)
1396     {
1397       if (coverage->branches)
1398         {
1399           fnotice (stdout, "Branches executed:%s of %d\n",
1400                    format_gcov (coverage->branches_executed,
1401                                 coverage->branches, 2),
1402                    coverage->branches);
1403           fnotice (stdout, "Taken at least once:%s of %d\n",
1404                    format_gcov (coverage->branches_taken,
1405                                 coverage->branches, 2),
1406                    coverage->branches);
1407         }
1408       else
1409         fnotice (stdout, "No branches\n");
1410       if (coverage->calls)
1411         fnotice (stdout, "Calls executed:%s of %d\n",
1412                  format_gcov (coverage->calls_executed, coverage->calls, 2),
1413                  coverage->calls);
1414       else
1415         fnotice (stdout, "No calls\n");
1416     }
1417 }
1418
1419 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1420    affect name generation. With preserve_paths we create a filename
1421    from all path components of the source file, replacing '/' with
1422    '#', without it we simply take the basename component. With
1423    long_output_names we prepend the processed name of the input file
1424    to each output name (except when the current source file is the
1425    input file, so you don't get a double concatenation). The two
1426    components are separated by '##'. Also '.' filename components are
1427    removed and '..'  components are renamed to '^'.  */
1428
1429 static char *
1430 make_gcov_file_name (const char *input_name, const char *src_name)
1431 {
1432   char *cptr;
1433   char *name = xmalloc (strlen (src_name) + strlen (input_name) + 10);
1434
1435   name[0] = 0;
1436   if (flag_long_names && strcmp (src_name, input_name))
1437     {
1438       /* Generate the input filename part.  */
1439       cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1440       strcat (name, cptr ? cptr + 1 : input_name);
1441       strcat (name, "##");
1442     }
1443
1444   /* Generate the source filename part.  */
1445   cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1446   strcat (name, cptr ? cptr + 1 : src_name);
1447
1448   if (flag_preserve_paths)
1449     {
1450       /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1451       char *prev;
1452
1453       for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1454         {
1455           unsigned shift = 0;
1456
1457           if (prev + 1 == cptr && prev[0] == '.')
1458             {
1459               /* Remove '.' */
1460               shift = 2;
1461             }
1462           else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1463             {
1464               /* Convert '..' */
1465               shift = 1;
1466               prev[1] = '^';
1467             }
1468           else
1469             *cptr++ = '#';
1470           if (shift)
1471             {
1472               cptr = prev;
1473               do
1474                 prev[0] = prev[shift];
1475               while (*prev++);
1476             }
1477         }
1478     }
1479
1480   strcat (name, ".gcov");
1481   return name;
1482 }
1483
1484 /* Scan through the bb_data for each line in the block, increment
1485    the line number execution count indicated by the execution count of
1486    the appropriate basic block.  */
1487
1488 static void
1489 add_line_counts (coverage_t *coverage, function_t *fn)
1490 {
1491   unsigned ix;
1492   line_t *line = NULL; /* This is propagated from one iteration to the
1493                           next.  */
1494
1495   /* Scan each basic block.  */
1496   for (ix = 0; ix != fn->num_blocks; ix++)
1497     {
1498       block_t *block = &fn->blocks[ix];
1499       unsigned *encoding;
1500       const source_t *src = NULL;
1501       unsigned jx;
1502
1503       if (block->count && ix && ix + 1 != fn->num_blocks)
1504         fn->blocks_executed++;
1505       for (jx = 0, encoding = block->u.line.encoding;
1506            jx != block->u.line.num; jx++, encoding++)
1507         if (!*encoding)
1508           {
1509             unsigned src_n = *++encoding;
1510
1511             for (src = sources; src->index != src_n; src = src->next)
1512               continue;
1513             jx++;
1514           }
1515         else
1516           {
1517             line = &src->lines[*encoding];
1518
1519             if (coverage)
1520               {
1521                 if (!line->exists)
1522                   coverage->lines++;
1523                 if (!line->count && block->count)
1524                   coverage->lines_executed++;
1525               }
1526             line->exists = 1;
1527             line->count += block->count;
1528           }
1529       free (block->u.line.encoding);
1530       block->u.cycle.arc = NULL;
1531       block->u.cycle.ident = ~0U;
1532
1533       if (!ix || ix + 1 == fn->num_blocks)
1534         /* Entry or exit block */;
1535       else if (flag_all_blocks)
1536         {
1537           line_t *block_line = line ? line : &fn->src->lines[fn->line];
1538
1539           block->chain = block_line->u.blocks;
1540           block_line->u.blocks = block;
1541         }
1542       else if (flag_branches)
1543         {
1544           arc_t *arc;
1545
1546           for (arc = block->succ; arc; arc = arc->succ_next)
1547             {
1548               arc->line_next = line->u.branches;
1549               line->u.branches = arc;
1550               if (coverage && !arc->is_unconditional)
1551                 add_branch_counts (coverage, arc);
1552             }
1553         }
1554     }
1555   if (!line)
1556     fnotice (stderr, "%s:no lines for `%s'\n", bbg_file_name, fn->name);
1557 }
1558
1559 /* Accumulate the line counts of a file.  */
1560
1561 static void
1562 accumulate_line_counts (source_t *src)
1563 {
1564   line_t *line;
1565   function_t *fn, *fn_p, *fn_n;
1566   unsigned ix;
1567
1568   /* Reverse the function order.  */
1569   for (fn = src->functions, fn_p = NULL; fn;
1570        fn_p = fn, fn = fn_n)
1571     {
1572       fn_n = fn->line_next;
1573       fn->line_next = fn_p;
1574     }
1575   src->functions = fn_p;
1576
1577   for (ix = src->num_lines, line = src->lines; ix--; line++)
1578     {
1579       if (!flag_all_blocks)
1580         {
1581           arc_t *arc, *arc_p, *arc_n;
1582
1583           /* Total and reverse the branch information.  */
1584           for (arc = line->u.branches, arc_p = NULL; arc;
1585                arc_p = arc, arc = arc_n)
1586             {
1587               arc_n = arc->line_next;
1588               arc->line_next = arc_p;
1589
1590               add_branch_counts (&src->coverage, arc);
1591             }
1592           line->u.branches = arc_p;
1593         }
1594       else if (line->u.blocks)
1595         {
1596           /* The user expects the line count to be the number of times
1597              a line has been executed. Simply summing the block count
1598              will give an artificially high number.  The Right Thing
1599              is to sum the entry counts to the graph of blocks on this
1600              line, then find the elementary cycles of the local graph
1601              and add the transition counts of those cycles.  */
1602           block_t *block, *block_p, *block_n;
1603           gcov_type count = 0;
1604
1605           /* Reverse the block information.  */
1606           for (block = line->u.blocks, block_p = NULL; block;
1607                block_p = block, block = block_n)
1608             {
1609               block_n = block->chain;
1610               block->chain = block_p;
1611               block->u.cycle.ident = ix;
1612             }
1613           line->u.blocks = block_p;
1614
1615           /* Sum the entry arcs.  */
1616           for (block = line->u.blocks; block; block = block->chain)
1617             {
1618               arc_t *arc;
1619
1620               for (arc = block->pred; arc; arc = arc->pred_next)
1621                 {
1622                   if (arc->src->u.cycle.ident != ix)
1623                     count += arc->count;
1624                   if (flag_branches)
1625                     add_branch_counts (&src->coverage, arc);
1626                 }
1627
1628               /* Initialize the cs_count.  */
1629               for (arc = block->succ; arc; arc = arc->succ_next)
1630                 arc->cs_count = arc->count;
1631             }
1632
1633           /* Find the loops. This uses the algorithm described in
1634              Tiernan 'An Efficient Search Algorithm to Find the
1635              Elementary Circuits of a Graph', CACM Dec 1970. We hold
1636              the P array by having each block point to the arc that
1637              connects to the previous block. The H array is implicitly
1638              held because of the arc ordering, and the block's
1639              previous arc pointer.
1640
1641              Although the algorithm is O(N^3) for highly connected
1642              graphs, at worst we'll have O(N^2), as most blocks have
1643              only one or two exits. Most graphs will be small.
1644
1645              For each loop we find, locate the arc with the smallest
1646              transition count, and add that to the cumulative
1647              count.  Decrease flow over the cycle and remove the arc
1648              from consideration.  */
1649           for (block = line->u.blocks; block; block = block->chain)
1650             {
1651               block_t *head = block;
1652               arc_t *arc;
1653
1654             next_vertex:;
1655               arc = head->succ;
1656             current_vertex:;
1657               while (arc)
1658                 {
1659                   block_t *dst = arc->dst;
1660                   if (/* Already used that arc.  */
1661                       arc->cycle
1662                       /* Not to same graph, or before first vertex.  */
1663                       || dst->u.cycle.ident != ix
1664                       /* Already in path.  */
1665                       || dst->u.cycle.arc)
1666                     {
1667                       arc = arc->succ_next;
1668                       continue;
1669                     }
1670
1671                   if (dst == block)
1672                     {
1673                       /* Found a closing arc.  */
1674                       gcov_type cycle_count = arc->cs_count;
1675                       arc_t *cycle_arc = arc;
1676                       arc_t *probe_arc;
1677
1678                       /* Locate the smallest arc count of the loop.  */
1679                       for (dst = head; (probe_arc = dst->u.cycle.arc);
1680                            dst = probe_arc->src)
1681                         if (cycle_count > probe_arc->cs_count)
1682                           {
1683                             cycle_count = probe_arc->cs_count;
1684                             cycle_arc = probe_arc;
1685                           }
1686
1687                       count += cycle_count;
1688                       cycle_arc->cycle = 1;
1689
1690                       /* Remove the flow from the cycle.  */
1691                       arc->cs_count -= cycle_count;
1692                       for (dst = head; (probe_arc = dst->u.cycle.arc);
1693                            dst = probe_arc->src)
1694                         probe_arc->cs_count -= cycle_count;
1695
1696                       /* Unwind to the cyclic arc.  */
1697                       while (head != cycle_arc->src)
1698                         {
1699                           arc = head->u.cycle.arc;
1700                           head->u.cycle.arc = NULL;
1701                           head = arc->src;
1702                         }
1703                       /* Move on.  */
1704                       arc = arc->succ_next;
1705                       continue;
1706                     }
1707
1708                   /* Add new block to chain.  */
1709                   dst->u.cycle.arc = arc;
1710                   head = dst;
1711                   goto next_vertex;
1712                 }
1713               /* We could not add another vertex to the path. Remove
1714                  the last vertex from the list.  */
1715               arc = head->u.cycle.arc;
1716               if (arc)
1717                 {
1718                   /* It was not the first vertex. Move onto next arc.  */
1719                   head->u.cycle.arc = NULL;
1720                   head = arc->src;
1721                   arc = arc->succ_next;
1722                   goto current_vertex;
1723                 }
1724               /* Mark this block as unusable.  */
1725               block->u.cycle.ident = ~0U;
1726             }
1727
1728           line->count = count;
1729         }
1730
1731       if (line->exists)
1732         {
1733           src->coverage.lines++;
1734           if (line->count)
1735             src->coverage.lines_executed++;
1736         }
1737     }
1738 }
1739
1740 /* Ouput information about ARC number IX.  Returns nonzero if
1741    anything is output.  */
1742
1743 static int
1744 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
1745 {
1746
1747   if (arc->is_call_non_return)
1748     {
1749       if (arc->src->count)
1750         {
1751           fnotice (gcov_file, "call   %2d returned %s\n", ix,
1752                    format_gcov (arc->src->count - arc->count,
1753                                 arc->src->count, -flag_counts));
1754         }
1755       else
1756         fnotice (gcov_file, "call   %2d never executed\n", ix);
1757     }
1758   else if (!arc->is_unconditional)
1759     {
1760       if (arc->src->count)
1761         fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1762                  format_gcov (arc->count, arc->src->count, -flag_counts),
1763                  arc->fall_through ? " (fallthrough)" : "");
1764       else
1765         fnotice (gcov_file, "branch %2d never executed\n", ix);
1766     }
1767   else if (flag_unconditional && !arc->dst->is_call_return)
1768     {
1769       if (arc->src->count)
1770         fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1771                  format_gcov (arc->count, arc->src->count, -flag_counts));
1772       else
1773         fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1774     }
1775   else
1776     return 0;
1777   return 1;
1778
1779 }
1780
1781 /* Read in the source file one line at a time, and output that line to
1782    the gcov file preceded by its execution count and other
1783    information.  */
1784
1785 static void
1786 output_lines (FILE *gcov_file, const source_t *src)
1787 {
1788   FILE *source_file;
1789   unsigned line_num;    /* current line number.  */
1790   const line_t *line;           /* current line info ptr.  */
1791   char string[STRING_SIZE];     /* line buffer.  */
1792   char const *retval = "";      /* status of source file reading.  */
1793   function_t *fn = src->functions;
1794
1795   fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1796   fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1797   fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
1798   fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
1799            object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
1800   fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1801
1802   source_file = fopen (src->name, "r");
1803   if (!source_file)
1804     {
1805       fnotice (stderr, "%s:cannot open source file\n", src->name);
1806       retval = NULL;
1807     }
1808   else
1809     {
1810       struct stat status;
1811
1812       if (!fstat (fileno (source_file), &status)
1813           && status.st_mtime > bbg_file_time)
1814         {
1815           fnotice (stderr, "%s:source file is newer than graph file `%s'\n",
1816                    src->name, bbg_file_name);
1817           fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1818                    "-", 0);
1819         }
1820     }
1821
1822   for (line_num = 1, line = &src->lines[line_num];
1823        line_num < src->num_lines; line_num++, line++)
1824     {
1825       for (; fn && fn->line == line_num; fn = fn->line_next)
1826         {
1827           arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1828           gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1829
1830           for (; arc; arc = arc->pred_next)
1831             if (arc->fake)
1832               return_count -= arc->count;
1833
1834           fprintf (gcov_file, "function %s", fn->name);
1835           fprintf (gcov_file, " called %s",
1836                    format_gcov (fn->blocks[0].count, 0, -1));
1837           fprintf (gcov_file, " returned %s",
1838                    format_gcov (return_count, fn->blocks[0].count, 0));
1839           fprintf (gcov_file, " blocks executed %s",
1840                    format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1841           fprintf (gcov_file, "\n");
1842         }
1843
1844       /* For lines which don't exist in the .bb file, print '-' before
1845          the source line.  For lines which exist but were never
1846          executed, print '#####' before the source line.  Otherwise,
1847          print the execution count before the source line.  There are
1848          16 spaces of indentation added before the source line so that
1849          tabs won't be messed up.  */
1850       fprintf (gcov_file, "%9s:%5u:",
1851                !line->exists ? "-" : !line->count ? "#####"
1852                : format_gcov (line->count, 0, -1), line_num);
1853
1854       if (retval)
1855         {
1856           /* Copy source line.  */
1857           do
1858             {
1859               retval = fgets (string, STRING_SIZE, source_file);
1860               if (!retval)
1861                 break;
1862               fputs (retval, gcov_file);
1863             }
1864           while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1865         }
1866       if (!retval)
1867         fputs ("/*EOF*/\n", gcov_file);
1868
1869       if (flag_all_blocks)
1870         {
1871           block_t *block;
1872           arc_t *arc;
1873           int ix, jx;
1874
1875           for (ix = jx = 0, block = line->u.blocks; block;
1876                block = block->chain)
1877             {
1878               if (!block->is_call_return)
1879                 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1880                          !line->exists ? "-" : !block->count ? "$$$$$"
1881                          : format_gcov (block->count, 0, -1),
1882                          line_num, ix++);
1883               if (flag_branches)
1884                 for (arc = block->succ; arc; arc = arc->succ_next)
1885                   jx += output_branch_count (gcov_file, jx, arc);
1886             }
1887         }
1888       else if (flag_branches)
1889         {
1890           int ix;
1891           arc_t *arc;
1892
1893           for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1894             ix += output_branch_count (gcov_file, ix, arc);
1895         }
1896     }
1897
1898   /* Handle all remaining source lines.  There may be lines after the
1899      last line of code.  */
1900   if (retval)
1901     {
1902       for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1903         {
1904           fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1905
1906           while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1907             {
1908               retval = fgets (string, STRING_SIZE, source_file);
1909               if (!retval)
1910                 break;
1911               fputs (retval, gcov_file);
1912             }
1913         }
1914     }
1915
1916   if (source_file)
1917     fclose (source_file);
1918 }