OSDN Git Service

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