OSDN Git Service

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