OSDN Git Service

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