OSDN Git Service

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