OSDN Git Service

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