OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / gcov.c
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2    source file.
3    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
4    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
5    Free Software Foundation, Inc.
6    Contributed by James E. Wilson of Cygnus Support.
7    Mangled by Bob Manson of Cygnus Support.
8    Mangled further by Nathan Sidwell <nathan@codesourcery.com>
9
10 Gcov is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
13 any later version.
14
15 Gcov is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with Gcov; see the file COPYING3.  If not see
22 <http://www.gnu.org/licenses/>.  */
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 /* Need an option to show individual block counts, and show
33    probabilities of fall through arcs.  */
34
35 #include "config.h"
36 #include "system.h"
37 #include "coretypes.h"
38 #include "tm.h"
39 #include "intl.h"
40 #include "diagnostic.h"
41 #include "version.h"
42
43 #include <getopt.h>
44
45 #define IN_GCOV 1
46 #include "gcov-io.h"
47 #include "gcov-io.c"
48
49 /* The gcno file is generated by -ftest-coverage option. The gcda file is
50    generated by a program compiled with -fprofile-arcs. Their formats
51    are documented in gcov-io.h.  */
52
53 /* The functions in this file for creating and solution program flow graphs
54    are very similar to functions in the gcc source file profile.c.  In
55    some places we make use of the knowledge of how profile.c works to
56    select particular algorithms here.  */
57
58 /* The code validates that the profile information read in corresponds
59    to the code currently being compiled.  Rather than checking for
60    identical files, the code below computes a checksum on the CFG
61    (based on the order of basic blocks and the arcs in the CFG).  If
62    the CFG checksum in the gcda file match the CFG checksum for the
63    code currently being compiled, the profile data will be used.  */
64
65 /* This is the size of the buffer used to read in source file lines.  */
66
67 struct function_info;
68 struct block_info;
69 struct source_info;
70
71 /* Describes an arc between two basic blocks.  */
72
73 typedef struct arc_info
74 {
75   /* source and destination blocks.  */
76   struct block_info *src;
77   struct block_info *dst;
78
79   /* transition counts.  */
80   gcov_type count;
81   /* used in cycle search, so that we do not clobber original counts.  */
82   gcov_type cs_count;
83
84   unsigned int count_valid : 1;
85   unsigned int on_tree : 1;
86   unsigned int fake : 1;
87   unsigned int fall_through : 1;
88
89   /* Arc to a catch handler.  */
90   unsigned int is_throw : 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/setjmp.  */
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 : 12;
128   unsigned count_valid : 1;
129   unsigned valid_chain : 1;
130   unsigned invalid_chain : 1;
131   unsigned exceptional : 1;
132
133   /* Block is a call instrumenting site.  */
134   unsigned is_call_site : 1; /* Does the call.  */
135   unsigned is_call_return : 1; /* Is the return.  */
136
137   /* Block is a landing pad for longjmp or throw.  */
138   unsigned is_nonlocal_return : 1;
139
140   union
141   {
142     struct
143     {
144      /* Array of line numbers and source files. source files are
145         introduced by a linenumber of zero, the next 'line number' is
146         the number of the source file.  Always starts with a source
147         file.  */
148       unsigned *encoding;
149       unsigned num;
150     } line; /* Valid until blocks are linked onto lines */
151     struct
152     {
153       /* Single line graph cycle workspace.  Used for all-blocks
154          mode.  */
155       arc_t *arc;
156       unsigned ident;
157     } cycle; /* Used in all-blocks mode, after blocks are linked onto
158                lines.  */
159   } u;
160
161   /* Temporary chain for solving graph, and for chaining blocks on one
162      line.  */
163   struct block_info *chain;
164
165 } block_t;
166
167 /* Describes a single function. Contains an array of basic blocks.  */
168
169 typedef struct function_info
170 {
171   /* Name of function.  */
172   char *name;
173   unsigned ident;
174   unsigned lineno_checksum;
175   unsigned cfg_checksum;
176
177   /* The graph contains at least one fake incoming edge.  */
178   unsigned has_catch : 1;
179
180   /* Array of basic blocks.  */
181   block_t *blocks;
182   unsigned num_blocks;
183   unsigned blocks_executed;
184
185   /* Raw arc coverage counts.  */
186   gcov_type *counts;
187   unsigned num_counts;
188
189   /* First line number & file.  */
190   unsigned line;
191   unsigned src;
192
193   /* Next function in same source file.  */
194   struct function_info *line_next;
195
196   /* Next function.  */
197   struct function_info *next;
198 } function_t;
199
200 /* Describes coverage of a file or function.  */
201
202 typedef struct coverage_info
203 {
204   int lines;
205   int lines_executed;
206
207   int branches;
208   int branches_executed;
209   int branches_taken;
210
211   int calls;
212   int calls_executed;
213
214   char *name;
215 } coverage_t;
216
217 /* Describes a single line of source. Contains a chain of basic blocks
218    with code on it.  */
219
220 typedef struct line_info
221 {
222   gcov_type count;         /* execution count */
223   union
224   {
225     arc_t *branches;       /* branches from blocks that end on this
226                               line. Used for branch-counts when not
227                               all-blocks mode.  */
228     block_t *blocks;       /* blocks which start on this line.  Used
229                               in all-blocks mode.  */
230   } u;
231   unsigned exists : 1;
232   unsigned unexceptional : 1;
233 } line_t;
234
235 /* Describes a file mentioned in the block graph.  Contains an array
236    of line info.  */
237
238 typedef struct source_info
239 {
240   /* Canonical name of source file.  */
241   char *name;
242   time_t file_time;
243
244   /* Array of line information.  */
245   line_t *lines;
246   unsigned num_lines;
247
248   coverage_t coverage;
249
250   /* Functions in this source file.  These are in ascending line
251      number order.  */
252   function_t *functions;
253 } source_t;
254
255 typedef struct name_map
256 {
257   char *name;  /* Source file name */
258   unsigned src;  /* Source file */
259 } name_map_t;
260
261 /* Holds a list of function basic block graphs.  */
262
263 static function_t *functions;
264 static function_t **fn_end = &functions;
265
266 static source_t *sources;   /* Array of source files  */
267 static unsigned n_sources;  /* Number of sources */
268 static unsigned a_sources;  /* Allocated sources */
269
270 static name_map_t *names;   /* Mapping of file names to sources */
271 static unsigned n_names;    /* Number of names */
272 static unsigned a_names;    /* Allocated names */
273
274 /* This holds data summary information.  */
275
276 static unsigned object_runs;
277 static unsigned program_count;
278
279 static unsigned total_lines;
280 static unsigned total_executed;
281
282 /* Modification time of graph file.  */
283
284 static time_t bbg_file_time;
285
286 /* Name and file pointer of the input file for the basic block graph.  */
287
288 static char *bbg_file_name;
289
290 /* Stamp of the bbg file */
291 static unsigned bbg_stamp;
292
293 /* Name and file pointer of the input file for the arc count data.  */
294
295 static char *da_file_name;
296
297 /* Data file is missing.  */
298
299 static int no_data_file;
300
301 /* If there is several input files, compute and display results after
302    reading all data files.  This way if two or more gcda file refer to
303    the same source file (eg inline subprograms in a .h file), the
304    counts are added.  */
305
306 static int multiple_files = 0;
307
308 /* Output branch probabilities.  */
309
310 static int flag_branches = 0;
311
312 /* Show unconditional branches too.  */
313 static int flag_unconditional = 0;
314
315 /* Output a gcov file if this is true.  This is on by default, and can
316    be turned off by the -n option.  */
317
318 static int flag_gcov_file = 1;
319
320 /* Output progress indication if this is true.  This is off by default
321    and can be turned on by the -d option.  */
322
323 static int flag_display_progress = 0;
324
325 /* For included files, make the gcov output file name include the name
326    of the input source file.  For example, if x.h is included in a.c,
327    then the output file name is a.c##x.h.gcov instead of x.h.gcov.  */
328
329 static int flag_long_names = 0;
330
331 /* Output count information for every basic block, not merely those
332    that contain line number information.  */
333
334 static int flag_all_blocks = 0;
335
336 /* Output summary info for each function.  */
337
338 static int flag_function_summary = 0;
339
340 /* Object directory file prefix.  This is the directory/file where the
341    graph and data files are looked for, if nonzero.  */
342
343 static char *object_directory = 0;
344
345 /* Source directory prefix.  This is removed from source pathnames
346    that match, when generating the output file name.  */
347
348 static char *source_prefix = 0;
349 static size_t source_length = 0;
350
351 /* Only show data for sources with relative pathnames.  Absolute ones
352    usually indicate a system header file, which although it may
353    contain inline functions, is usually uninteresting.  */
354 static int flag_relative_only = 0;
355
356 /* Preserve all pathname components. Needed when object files and
357    source files are in subdirectories. '/' is mangled as '#', '.' is
358    elided and '..' mangled to '^'.  */
359
360 static int flag_preserve_paths = 0;
361
362 /* Output the number of times a branch was taken as opposed to the percentage
363    of times it was taken.  */
364
365 static int flag_counts = 0;
366
367 /* Forward declarations.  */
368 static int process_args (int, char **);
369 static void print_usage (int) ATTRIBUTE_NORETURN;
370 static void print_version (void) ATTRIBUTE_NORETURN;
371 static void process_file (const char *);
372 static void generate_results (const char *);
373 static void create_file_names (const char *);
374 static int name_search (const void *, const void *);
375 static int name_sort (const void *, const void *);
376 static char *canonicalize_name (const char *);
377 static unsigned find_source (const char *);
378 static function_t *read_graph_file (void);
379 static int read_count_file (function_t *);
380 static void solve_flow_graph (function_t *);
381 static void find_exception_blocks (function_t *);
382 static void add_branch_counts (coverage_t *, const arc_t *);
383 static void add_line_counts (coverage_t *, function_t *);
384 static void executed_summary (unsigned, unsigned);
385 static void function_summary (const coverage_t *, const char *);
386 static const char *format_gcov (gcov_type, gcov_type, int);
387 static void accumulate_line_counts (source_t *);
388 static int output_branch_count (FILE *, int, const arc_t *);
389 static void output_lines (FILE *, const source_t *);
390 static char *make_gcov_file_name (const char *, const char *);
391 static char *mangle_name (const char *, char *);
392 static void release_structures (void);
393 static void release_function (function_t *);
394 extern int main (int, char **);
395
396 int
397 main (int argc, char **argv)
398 {
399   int argno;
400   int first_arg;
401   const char *p;
402
403   p = argv[0] + strlen (argv[0]);
404   while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
405     --p;
406   progname = p;
407
408   xmalloc_set_program_name (progname);
409
410   /* Unlock the stdio streams.  */
411   unlock_std_streams ();
412
413   gcc_init_libintl ();
414
415   diagnostic_initialize (global_dc, 0);
416
417   /* Handle response files.  */
418   expandargv (&argc, &argv);
419
420   a_names = 10;
421   names = XNEWVEC (name_map_t, a_names);
422   a_sources = 10;
423   sources = XNEWVEC (source_t, a_sources);
424   
425   argno = process_args (argc, argv);
426   if (optind == argc)
427     print_usage (true);
428
429   if (argc - argno > 1)
430     multiple_files = 1;
431
432   first_arg = argno;
433   
434   for (; argno != argc; argno++)
435     {
436       if (flag_display_progress)
437         printf("Processing file %d out of %d\n",  
438                argno - first_arg + 1, argc - first_arg);
439       process_file (argv[argno]);
440     }
441
442   generate_results (multiple_files ? NULL : argv[argc - 1]);
443
444   release_structures ();
445
446   return 0;
447 }
448 \f
449 /* Print a usage message and exit.  If ERROR_P is nonzero, this is an error,
450    otherwise the output of --help.  */
451
452 static void
453 print_usage (int error_p)
454 {
455   FILE *file = error_p ? stderr : stdout;
456   int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
457
458   fnotice (file, "Usage: gcov [OPTION]... SOURCE|OBJ...\n\n");
459   fnotice (file, "Print code coverage information.\n\n");
460   fnotice (file, "  -h, --help                      Print this help, then exit\n");
461   fnotice (file, "  -v, --version                   Print version number, then exit\n");
462   fnotice (file, "  -a, --all-blocks                Show information for every basic block\n");
463   fnotice (file, "  -b, --branch-probabilities      Include branch probabilities in output\n");
464   fnotice (file, "  -c, --branch-counts             Given counts of branches taken\n\
465                                     rather than percentages\n");
466   fnotice (file, "  -n, --no-output                 Do not create an output file\n");
467   fnotice (file, "  -l, --long-file-names           Use long output file names for included\n\
468                                     source files\n");
469   fnotice (file, "  -f, --function-summaries        Output summaries for each function\n");
470   fnotice (file, "  -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
471   fnotice (file, "  -s, --source-prefix DIR         Source prefix to elide\n");
472   fnotice (file, "  -r, --relative-only             Only show data for relative sources\n");
473   fnotice (file, "  -p, --preserve-paths            Preserve all pathname components\n");
474   fnotice (file, "  -u, --unconditional-branches    Show unconditional branch counts too\n");
475   fnotice (file, "  -d, --display-progress          Display progress information\n");
476   fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
477            bug_report_url);
478   exit (status);
479 }
480
481 /* Print version information and exit.  */
482
483 static void
484 print_version (void)
485 {
486   fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
487   fprintf (stdout, "Copyright %s 2012 Free Software Foundation, Inc.\n",
488            _("(C)"));
489   fnotice (stdout,
490            _("This is free software; see the source for copying conditions.\n"
491              "There is NO warranty; not even for MERCHANTABILITY or \n"
492              "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
493   exit (SUCCESS_EXIT_CODE);
494 }
495
496 static const struct option options[] =
497 {
498   { "help",                 no_argument,       NULL, 'h' },
499   { "version",              no_argument,       NULL, 'v' },
500   { "all-blocks",           no_argument,       NULL, 'a' },
501   { "branch-probabilities", no_argument,       NULL, 'b' },
502   { "branch-counts",        no_argument,       NULL, 'c' },
503   { "no-output",            no_argument,       NULL, 'n' },
504   { "long-file-names",      no_argument,       NULL, 'l' },
505   { "function-summaries",   no_argument,       NULL, 'f' },
506   { "preserve-paths",       no_argument,       NULL, 'p' },
507   { "relative-only",        no_argument,       NULL, 'r' },
508   { "object-directory",     required_argument, NULL, 'o' },
509   { "object-file",          required_argument, NULL, 'o' },
510   { "source-prefix",        required_argument, NULL, 's' },
511   { "unconditional-branches", no_argument,     NULL, 'u' },
512   { "display-progress",     no_argument,       NULL, 'd' },
513   { 0, 0, 0, 0 }
514 };
515
516 /* Process args, return index to first non-arg.  */
517
518 static int
519 process_args (int argc, char **argv)
520 {
521   int opt;
522
523   while ((opt = getopt_long (argc, argv, "abcdfhlno:s:pruv", options, NULL)) != -1)
524     {
525       switch (opt)
526         {
527         case 'a':
528           flag_all_blocks = 1;
529           break;
530         case 'b':
531           flag_branches = 1;
532           break;
533         case 'c':
534           flag_counts = 1;
535           break;
536         case 'f':
537           flag_function_summary = 1;
538           break;
539         case 'h':
540           print_usage (false);
541           /* print_usage will exit.  */
542         case 'l':
543           flag_long_names = 1;
544           break;
545         case 'n':
546           flag_gcov_file = 0;
547           break;
548         case 'o':
549           object_directory = optarg;
550           break;
551         case 's':
552           source_prefix = optarg;
553           source_length = strlen (source_prefix);
554           break;
555         case 'r':
556           flag_relative_only = 1;
557           break;
558         case 'p':
559           flag_preserve_paths = 1;
560           break;
561         case 'u':
562           flag_unconditional = 1;
563           break;
564         case 'd':
565           flag_display_progress = 1;
566           break;
567         case 'v':
568           print_version ();
569           /* print_version will exit.  */
570         default:
571           print_usage (true);
572           /* print_usage will exit.  */
573         }
574     }
575
576   return optind;
577 }
578
579 /* Process a single input file.  */
580
581 static void
582 process_file (const char *file_name)
583 {
584   function_t *fns;
585
586   create_file_names (file_name);
587   fns = read_graph_file ();
588   if (!fns)
589     return;
590   
591   read_count_file (fns);
592   while (fns)
593     {
594       function_t *fn = fns;
595
596       fns = fn->next;
597       fn->next = NULL;
598       if (fn->counts)
599         {
600           unsigned src = fn->src;
601           unsigned line = fn->line;
602           unsigned block_no;
603           function_t *probe, **prev;
604           
605           /* Now insert it into the source file's list of
606              functions. Normally functions will be encountered in
607              ascending order, so a simple scan is quick.  Note we're
608              building this list in reverse order.  */
609           for (prev = &sources[src].functions;
610                (probe = *prev); prev = &probe->line_next)
611             if (probe->line <= line)
612               break;
613           fn->line_next = probe;
614           *prev = fn;
615
616           /* Mark last line in files touched by function.  */
617           for (block_no = 0; block_no != fn->num_blocks; block_no++)
618             {
619               unsigned *enc = fn->blocks[block_no].u.line.encoding;
620               unsigned num = fn->blocks[block_no].u.line.num;
621
622               for (; num--; enc++)
623                 if (!*enc)
624                   {
625                     if (enc[1] != src)
626                       {
627                         if (line >= sources[src].num_lines)
628                           sources[src].num_lines = line + 1;
629                         line = 0;
630                         src = enc[1];
631                       }
632                     enc++;
633                     num--;
634                   }
635                 else if (*enc > line)
636                   line = *enc;
637             }
638           if (line >= sources[src].num_lines)
639             sources[src].num_lines = line + 1;
640           
641           solve_flow_graph (fn);
642           if (fn->has_catch)
643             find_exception_blocks (fn);
644           *fn_end = fn;
645           fn_end = &fn->next;
646         }
647       else
648         /* The function was not in the executable -- some other
649            instance must have been selected.  */
650         release_function (fn);
651     }
652 }
653
654 static void
655 generate_results (const char *file_name)
656 {
657   unsigned ix;
658   source_t *src;
659   function_t *fn;
660
661   for (ix = n_sources, src = sources; ix--; src++)
662     if (src->num_lines)
663       src->lines = XCNEWVEC (line_t, src->num_lines);
664
665   for (fn = functions; fn; fn = fn->next)
666     {
667       coverage_t coverage;
668
669       memset (&coverage, 0, sizeof (coverage));
670       coverage.name = fn->name;
671       add_line_counts (flag_function_summary ? &coverage : NULL, fn);
672       if (flag_function_summary)
673         {
674           function_summary (&coverage, "Function");
675           fnotice (stdout, "\n");
676         }
677     }
678
679   if (file_name)
680     {
681       name_map_t *name_map = (name_map_t *)bsearch
682         (file_name, names, n_names, sizeof (*names), name_search);
683       if (name_map)
684         file_name = sources[name_map->src].coverage.name;
685       else
686         file_name = canonicalize_name (file_name);
687     }
688   
689   for (ix = n_sources, src = sources; ix--; src++)
690     {
691       if (flag_relative_only)
692         {
693           /* Ignore this source, if it is an absolute path (after
694              source prefix removal).  */
695           char first = src->coverage.name[0];
696       
697 #if HAVE_DOS_BASED_FILE_SYSTEM
698           if (first && src->coverage.name[1] == ':')
699             first = src->coverage.name[2];
700 #endif
701           if (IS_DIR_SEPARATOR (first))
702             continue;
703         }
704       
705       accumulate_line_counts (src);
706       function_summary (&src->coverage, "File");
707       total_lines += src->coverage.lines;
708       total_executed += src->coverage.lines_executed;
709       if (flag_gcov_file)
710         {
711           char *gcov_file_name
712             = make_gcov_file_name (file_name, src->coverage.name);
713
714           if (src->coverage.lines)
715             {
716               FILE *gcov_file = fopen (gcov_file_name, "w");
717
718               if (gcov_file)
719                 {
720                   fnotice (stdout, "Creating '%s'\n", gcov_file_name);
721                   output_lines (gcov_file, src);
722                   if (ferror (gcov_file))
723                     fnotice (stderr, "Error writing output file '%s'\n",
724                              gcov_file_name);
725                   fclose (gcov_file);
726                 }
727               else
728                 fnotice (stderr, "Could not open output file '%s'\n",
729                          gcov_file_name);
730             }
731           else
732             {
733               unlink (gcov_file_name);
734               fnotice (stdout, "Removing '%s'\n", gcov_file_name);
735             }
736           free (gcov_file_name);
737         }
738       fnotice (stdout, "\n");
739     }
740
741   if (!file_name)
742     executed_summary (total_lines, total_executed);
743 }
744
745 /* Release a function structure */
746
747 static void
748 release_function (function_t *fn)
749 {
750   unsigned ix;
751   block_t *block;
752
753   for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
754     {
755       arc_t *arc, *arc_n;
756
757       for (arc = block->succ; arc; arc = arc_n)
758         {
759           arc_n = arc->succ_next;
760           free (arc);
761         }
762     }
763   free (fn->blocks);
764   free (fn->counts);
765 }
766
767 /* Release all memory used.  */
768
769 static void
770 release_structures (void)
771 {
772   unsigned ix;
773   function_t *fn;
774
775   for (ix = n_sources; ix--;)
776     free (sources[ix].lines);
777   free (sources);
778   
779   for (ix = n_names; ix--;)
780     free (names[ix].name);
781   free (names);
782
783   while ((fn = functions))
784     {
785       functions = fn->next;
786       release_function (fn);
787     }
788 }
789
790 /* Generate the names of the graph and data files.  If OBJECT_DIRECTORY
791    is not specified, these are named from FILE_NAME sans extension.  If
792    OBJECT_DIRECTORY is specified and is a directory, the files are in that
793    directory, but named from the basename of the FILE_NAME, sans extension.
794    Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
795    and the data files are named from that.  */
796
797 static void
798 create_file_names (const char *file_name)
799 {
800   char *cptr;
801   char *name;
802   int length = strlen (file_name);
803   int base;
804
805   /* Free previous file names.  */
806   free (bbg_file_name);
807   free (da_file_name);
808   da_file_name = bbg_file_name = NULL;
809   bbg_file_time = 0;
810   bbg_stamp = 0;
811
812   if (object_directory && object_directory[0])
813     {
814       struct stat status;
815
816       length += strlen (object_directory) + 2;
817       name = XNEWVEC (char, length);
818       name[0] = 0;
819
820       base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
821       strcat (name, object_directory);
822       if (base && (! IS_DIR_SEPARATOR (name[strlen (name) - 1])))
823         strcat (name, "/");
824     }
825   else
826     {
827       name = XNEWVEC (char, length + 1);
828       strcpy (name, file_name);
829       base = 0;
830     }
831
832   if (base)
833     {
834       /* Append source file name.  */
835       const char *cptr = lbasename (file_name);
836       strcat (name, cptr ? cptr : file_name);
837     }
838
839   /* Remove the extension.  */
840   cptr = strrchr (name, '.');
841   if (cptr)
842     *cptr = 0;
843
844   length = strlen (name);
845
846   bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
847   strcpy (bbg_file_name, name);
848   strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
849
850   da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
851   strcpy (da_file_name, name);
852   strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
853
854   free (name);
855   return;
856 }
857
858 /* A is a string and B is a pointer to name_map_t.  Compare for file
859    name orderability.  */
860
861 static int
862 name_search (const void *a_, const void *b_)
863 {
864   const char *a = (const char *)a_;
865   const name_map_t *b = (const name_map_t *)b_;
866
867 #if HAVE_DOS_BASED_FILE_SYSTEM
868   return strcasecmp (a, b->name);
869 #else
870   return strcmp (a, b->name);
871 #endif
872 }
873
874 /* A and B are a pointer to name_map_t.  Compare for file name
875    orderability.  */
876
877 static int
878 name_sort (const void *a_, const void *b_)
879 {
880   const name_map_t *a = (const name_map_t *)a_;
881   return name_search (a->name, b_);
882 }
883
884 /* Find or create a source file structure for FILE_NAME. Copies
885    FILE_NAME on creation */
886
887 static unsigned
888 find_source (const char *file_name)
889 {
890   name_map_t *name_map;
891   char *canon;
892   unsigned idx;
893   struct stat status;
894
895   if (!file_name)
896     file_name = "<unknown>";
897   name_map = (name_map_t *)bsearch
898     (file_name, names, n_names, sizeof (*names), name_search);
899   if (name_map)
900     {
901       idx = name_map->src;
902       goto check_date;
903     }
904
905   if (n_names + 2 > a_names)
906     {
907       /* Extend the name map array -- we'll be inserting one or two
908          entries.  */
909       a_names *= 2;
910       name_map = XNEWVEC (name_map_t, a_names);
911       memcpy (name_map, names, n_names * sizeof (*names));
912       free (names);
913       names = name_map;
914     }
915   
916   /* Not found, try the canonical name. */
917   canon = canonicalize_name (file_name);
918   name_map = (name_map_t *)bsearch
919     (canon, names, n_names, sizeof (*names), name_search);
920   if (!name_map)
921     {
922       /* Not found with canonical name, create a new source.  */
923       source_t *src;
924       
925       if (n_sources == a_sources)
926         {
927           a_sources *= 2;
928           src = XNEWVEC (source_t, a_sources);
929           memcpy (src, sources, n_sources * sizeof (*sources));
930           free (sources);
931           sources = src;
932         }
933
934       idx = n_sources;
935
936       name_map = &names[n_names++];
937       name_map->name = canon;
938       name_map->src = idx;
939
940       src = &sources[n_sources++];
941       memset (src, 0, sizeof (*src));
942       src->name = canon;
943       src->coverage.name = src->name;
944       if (source_length
945 #if HAVE_DOS_BASED_FILE_SYSTEM
946           /* You lose if separators don't match exactly in the
947              prefix.  */
948           && !strncasecmp (source_prefix, src->coverage.name, source_length)
949 #else
950           && !strncmp (source_prefix, src->coverage.name, source_length)
951 #endif
952           && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
953         src->coverage.name += source_length + 1;
954       if (!stat (src->name, &status))
955         src->file_time = status.st_mtime;
956     }
957   else
958     idx = name_map->src;
959
960   if (name_search (file_name, name_map))
961     {
962       /* Append the non-canonical name.  */
963       name_map = &names[n_names++];
964       name_map->name = xstrdup (file_name);
965       name_map->src = idx;
966     }
967
968   /* Resort the name map.  */
969   qsort (names, n_names, sizeof (*names), name_sort);
970   
971  check_date:
972   if (sources[idx].file_time > bbg_file_time)
973     {
974       static int info_emitted;
975
976       fnotice (stderr, "%s:source file is newer than graph file '%s'\n",
977                file_name, bbg_file_name);
978       if (!info_emitted)
979         {
980           fnotice (stderr,
981                    "(the message is only displayed one per source file)\n");
982           info_emitted = 1;
983         }
984       sources[idx].file_time = 0;
985     }
986
987   return idx;
988 }
989
990 /* Read the graph file.  Return list of functions read -- in reverse order.  */
991
992 static function_t *
993 read_graph_file (void)
994 {
995   unsigned version;
996   unsigned current_tag = 0;
997   function_t *fn = NULL;
998   function_t *fns = NULL;
999   function_t **fns_end = &fns;
1000   unsigned src_idx = 0;
1001   unsigned ix;
1002   unsigned tag;
1003
1004   if (!gcov_open (bbg_file_name, 1))
1005     {
1006       fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
1007       return fns;
1008     }
1009   bbg_file_time = gcov_time ();
1010   if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1011     {
1012       fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
1013       gcov_close ();
1014       return fns;
1015     }
1016
1017   version = gcov_read_unsigned ();
1018   if (version != GCOV_VERSION)
1019     {
1020       char v[4], e[4];
1021
1022       GCOV_UNSIGNED2STRING (v, version);
1023       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1024
1025       fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1026                bbg_file_name, v, e);
1027     }
1028   bbg_stamp = gcov_read_unsigned ();
1029
1030   while ((tag = gcov_read_unsigned ()))
1031     {
1032       unsigned length = gcov_read_unsigned ();
1033       gcov_position_t base = gcov_position ();
1034
1035       if (tag == GCOV_TAG_FUNCTION)
1036         {
1037           char *function_name;
1038           unsigned ident, lineno;
1039           unsigned lineno_checksum, cfg_checksum;
1040
1041           ident = gcov_read_unsigned ();
1042           lineno_checksum = gcov_read_unsigned ();
1043           cfg_checksum = gcov_read_unsigned ();
1044           function_name = xstrdup (gcov_read_string ());
1045           src_idx = find_source (gcov_read_string ());
1046           lineno = gcov_read_unsigned ();
1047
1048           fn = XCNEW (function_t);
1049           fn->name = function_name;
1050           fn->ident = ident;
1051           fn->lineno_checksum = lineno_checksum;
1052           fn->cfg_checksum = cfg_checksum;
1053           fn->src = src_idx;
1054           fn->line = lineno;
1055
1056           fn->line_next = NULL;
1057           fn->next = NULL;
1058           *fns_end = fn;
1059           fns_end = &fn->next;
1060           current_tag = tag;
1061         }
1062       else if (fn && tag == GCOV_TAG_BLOCKS)
1063         {
1064           if (fn->blocks)
1065             fnotice (stderr, "%s:already seen blocks for '%s'\n",
1066                      bbg_file_name, fn->name);
1067           else
1068             {
1069               unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
1070               fn->num_blocks = num_blocks;
1071
1072               fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
1073               for (ix = 0; ix != num_blocks; ix++)
1074                 fn->blocks[ix].flags = gcov_read_unsigned ();
1075             }
1076         }
1077       else if (fn && tag == GCOV_TAG_ARCS)
1078         {
1079           unsigned src = gcov_read_unsigned ();
1080           unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1081           block_t *src_blk = &fn->blocks[src];
1082           unsigned mark_catches = 0;
1083           struct arc_info *arc;
1084
1085           if (src >= fn->num_blocks || fn->blocks[src].succ)
1086             goto corrupt;
1087
1088           while (num_dests--)
1089             {
1090               unsigned dest = gcov_read_unsigned ();
1091               unsigned flags = gcov_read_unsigned ();
1092
1093               if (dest >= fn->num_blocks)
1094                 goto corrupt;
1095               arc = XCNEW (arc_t);
1096
1097               arc->dst = &fn->blocks[dest];
1098               arc->src = src_blk;
1099
1100               arc->count = 0;
1101               arc->count_valid = 0;
1102               arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1103               arc->fake = !!(flags & GCOV_ARC_FAKE);
1104               arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1105
1106               arc->succ_next = src_blk->succ;
1107               src_blk->succ = arc;
1108               src_blk->num_succ++;
1109
1110               arc->pred_next = fn->blocks[dest].pred;
1111               fn->blocks[dest].pred = arc;
1112               fn->blocks[dest].num_pred++;
1113
1114               if (arc->fake)
1115                 {
1116                   if (src)
1117                     {
1118                       /* Exceptional exit from this function, the
1119                          source block must be a call.  */
1120                       fn->blocks[src].is_call_site = 1;
1121                       arc->is_call_non_return = 1;
1122                       mark_catches = 1;
1123                     }
1124                   else
1125                     {
1126                       /* Non-local return from a callee of this
1127                          function. The destination block is a setjmp.  */
1128                       arc->is_nonlocal_return = 1;
1129                       fn->blocks[dest].is_nonlocal_return = 1;
1130                     }
1131                 }
1132
1133               if (!arc->on_tree)
1134                 fn->num_counts++;
1135             }
1136           
1137           if (mark_catches)
1138             {
1139               /* We have a fake exit from this block.  The other
1140                  non-fall through exits must be to catch handlers.
1141                  Mark them as catch arcs.  */
1142
1143               for (arc = src_blk->succ; arc; arc = arc->succ_next)
1144                 if (!arc->fake && !arc->fall_through)
1145                   {
1146                     arc->is_throw = 1;
1147                     fn->has_catch = 1;
1148                   }
1149             }
1150         }
1151       else if (fn && tag == GCOV_TAG_LINES)
1152         {
1153           unsigned blockno = gcov_read_unsigned ();
1154           unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
1155
1156           if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
1157             goto corrupt;
1158
1159           for (ix = 0; ;  )
1160             {
1161               unsigned lineno = gcov_read_unsigned ();
1162
1163               if (lineno)
1164                 {
1165                   if (!ix)
1166                     {
1167                       line_nos[ix++] = 0;
1168                       line_nos[ix++] = src_idx;
1169                     }
1170                   line_nos[ix++] = lineno;
1171                 }
1172               else
1173                 {
1174                   const char *file_name = gcov_read_string ();
1175
1176                   if (!file_name)
1177                     break;
1178                   src_idx = find_source (file_name);
1179                   line_nos[ix++] = 0;
1180                   line_nos[ix++] = src_idx;
1181                 }
1182             }
1183
1184           fn->blocks[blockno].u.line.encoding = line_nos;
1185           fn->blocks[blockno].u.line.num = ix;
1186         }
1187       else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1188         {
1189           fn = NULL;
1190           current_tag = 0;
1191         }
1192       gcov_sync (base, length);
1193       if (gcov_is_error ())
1194         {
1195         corrupt:;
1196           fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1197           break;
1198         }
1199     }
1200   gcov_close ();
1201
1202   if (!fns)
1203     fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1204
1205   return fns;
1206 }
1207
1208 /* Reads profiles from the count file and attach to each
1209    function. Return nonzero if fatal error.  */
1210
1211 static int
1212 read_count_file (function_t *fns)
1213 {
1214   unsigned ix;
1215   unsigned version;
1216   unsigned tag;
1217   function_t *fn = NULL;
1218   int error = 0;
1219
1220   if (!gcov_open (da_file_name, 1))
1221     {
1222       fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1223                da_file_name);
1224       no_data_file = 1;
1225       return 0;
1226     }
1227   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1228     {
1229       fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1230     cleanup:;
1231       gcov_close ();
1232       return 1;
1233     }
1234   version = gcov_read_unsigned ();
1235   if (version != GCOV_VERSION)
1236     {
1237       char v[4], e[4];
1238
1239       GCOV_UNSIGNED2STRING (v, version);
1240       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1241
1242       fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1243                da_file_name, v, e);
1244     }
1245   tag = gcov_read_unsigned ();
1246   if (tag != bbg_stamp)
1247     {
1248       fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
1249       goto cleanup;
1250     }
1251
1252   while ((tag = gcov_read_unsigned ()))
1253     {
1254       unsigned length = gcov_read_unsigned ();
1255       unsigned long base = gcov_position ();
1256
1257       if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1258         {
1259           struct gcov_summary summary;
1260           gcov_read_summary (&summary);
1261           object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1262           program_count++;
1263         }
1264       else if (tag == GCOV_TAG_FUNCTION && !length)
1265         ; /* placeholder  */
1266       else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1267         {
1268           unsigned ident;
1269           struct function_info *fn_n;
1270
1271           /* Try to find the function in the list.  To speed up the
1272              search, first start from the last function found.  */
1273           ident = gcov_read_unsigned ();
1274           fn_n = fns;
1275           for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1276             {
1277               if (fn)
1278                 ;
1279               else if ((fn = fn_n))
1280                 fn_n = NULL;
1281               else
1282                 {
1283                   fnotice (stderr, "%s:unknown function '%u'\n",
1284                            da_file_name, ident);
1285                   break;
1286                 }
1287               if (fn->ident == ident)
1288                 break;
1289             }
1290
1291           if (!fn)
1292             ;
1293           else if (gcov_read_unsigned () != fn->lineno_checksum
1294                    || gcov_read_unsigned () != fn->cfg_checksum)
1295             {
1296             mismatch:;
1297               fnotice (stderr, "%s:profile mismatch for '%s'\n",
1298                        da_file_name, fn->name);
1299               goto cleanup;
1300             }
1301         }
1302       else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1303         {
1304           if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
1305             goto mismatch;
1306
1307           if (!fn->counts)
1308             fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
1309
1310           for (ix = 0; ix != fn->num_counts; ix++)
1311             fn->counts[ix] += gcov_read_counter ();
1312         }
1313       gcov_sync (base, length);
1314       if ((error = gcov_is_error ()))
1315         {
1316           fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1317                    da_file_name);
1318           goto cleanup;
1319         }
1320     }
1321
1322   gcov_close ();
1323   return 0;
1324 }
1325
1326 /* Solve the flow graph. Propagate counts from the instrumented arcs
1327    to the blocks and the uninstrumented arcs.  */
1328
1329 static void
1330 solve_flow_graph (function_t *fn)
1331 {
1332   unsigned ix;
1333   arc_t *arc;
1334   gcov_type *count_ptr = fn->counts;
1335   block_t *blk;
1336   block_t *valid_blocks = NULL;    /* valid, but unpropagated blocks.  */
1337   block_t *invalid_blocks = NULL;  /* invalid, but inferable blocks.  */
1338
1339   /* The arcs were built in reverse order.  Fix that now.  */
1340   for (ix = fn->num_blocks; ix--;)
1341     {
1342       arc_t *arc_p, *arc_n;
1343
1344       for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1345            arc_p = arc, arc = arc_n)
1346         {
1347           arc_n = arc->succ_next;
1348           arc->succ_next = arc_p;
1349         }
1350       fn->blocks[ix].succ = arc_p;
1351
1352       for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1353            arc_p = arc, arc = arc_n)
1354         {
1355           arc_n = arc->pred_next;
1356           arc->pred_next = arc_p;
1357         }
1358       fn->blocks[ix].pred = arc_p;
1359     }
1360
1361   if (fn->num_blocks < 2)
1362     fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1363              bbg_file_name, fn->name);
1364   else
1365     {
1366       if (fn->blocks[0].num_pred)
1367         fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1368                  bbg_file_name, fn->name);
1369       else
1370         /* We can't deduce the entry block counts from the lack of
1371            predecessors.  */
1372         fn->blocks[0].num_pred = ~(unsigned)0;
1373
1374       if (fn->blocks[fn->num_blocks - 1].num_succ)
1375         fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1376                  bbg_file_name, fn->name);
1377       else
1378         /* Likewise, we can't deduce exit block counts from the lack
1379            of its successors.  */
1380         fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1381     }
1382
1383   /* Propagate the measured counts, this must be done in the same
1384      order as the code in profile.c  */
1385   for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1386     {
1387       block_t const *prev_dst = NULL;
1388       int out_of_order = 0;
1389       int non_fake_succ = 0;
1390
1391       for (arc = blk->succ; arc; arc = arc->succ_next)
1392         {
1393           if (!arc->fake)
1394             non_fake_succ++;
1395
1396           if (!arc->on_tree)
1397             {
1398               if (count_ptr)
1399                 arc->count = *count_ptr++;
1400               arc->count_valid = 1;
1401               blk->num_succ--;
1402               arc->dst->num_pred--;
1403             }
1404           if (prev_dst && prev_dst > arc->dst)
1405             out_of_order = 1;
1406           prev_dst = arc->dst;
1407         }
1408       if (non_fake_succ == 1)
1409         {
1410           /* If there is only one non-fake exit, it is an
1411              unconditional branch.  */
1412           for (arc = blk->succ; arc; arc = arc->succ_next)
1413             if (!arc->fake)
1414               {
1415                 arc->is_unconditional = 1;
1416                 /* If this block is instrumenting a call, it might be
1417                    an artificial block. It is not artificial if it has
1418                    a non-fallthrough exit, or the destination of this
1419                    arc has more than one entry.  Mark the destination
1420                    block as a return site, if none of those conditions
1421                    hold.  */
1422                 if (blk->is_call_site && arc->fall_through
1423                     && arc->dst->pred == arc && !arc->pred_next)
1424                   arc->dst->is_call_return = 1;
1425               }
1426         }
1427
1428       /* Sort the successor arcs into ascending dst order. profile.c
1429          normally produces arcs in the right order, but sometimes with
1430          one or two out of order.  We're not using a particularly
1431          smart sort.  */
1432       if (out_of_order)
1433         {
1434           arc_t *start = blk->succ;
1435           unsigned changes = 1;
1436
1437           while (changes)
1438             {
1439               arc_t *arc, *arc_p, *arc_n;
1440
1441               changes = 0;
1442               for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1443                 {
1444                   if (arc->dst > arc_n->dst)
1445                     {
1446                       changes = 1;
1447                       if (arc_p)
1448                         arc_p->succ_next = arc_n;
1449                       else
1450                         start = arc_n;
1451                       arc->succ_next = arc_n->succ_next;
1452                       arc_n->succ_next = arc;
1453                       arc_p = arc_n;
1454                     }
1455                   else
1456                     {
1457                       arc_p = arc;
1458                       arc = arc_n;
1459                     }
1460                 }
1461             }
1462           blk->succ = start;
1463         }
1464
1465       /* Place it on the invalid chain, it will be ignored if that's
1466          wrong.  */
1467       blk->invalid_chain = 1;
1468       blk->chain = invalid_blocks;
1469       invalid_blocks = blk;
1470     }
1471
1472   while (invalid_blocks || valid_blocks)
1473     {
1474       while ((blk = invalid_blocks))
1475         {
1476           gcov_type total = 0;
1477           const arc_t *arc;
1478
1479           invalid_blocks = blk->chain;
1480           blk->invalid_chain = 0;
1481           if (!blk->num_succ)
1482             for (arc = blk->succ; arc; arc = arc->succ_next)
1483               total += arc->count;
1484           else if (!blk->num_pred)
1485             for (arc = blk->pred; arc; arc = arc->pred_next)
1486               total += arc->count;
1487           else
1488             continue;
1489
1490           blk->count = total;
1491           blk->count_valid = 1;
1492           blk->chain = valid_blocks;
1493           blk->valid_chain = 1;
1494           valid_blocks = blk;
1495         }
1496       while ((blk = valid_blocks))
1497         {
1498           gcov_type total;
1499           arc_t *arc, *inv_arc;
1500
1501           valid_blocks = blk->chain;
1502           blk->valid_chain = 0;
1503           if (blk->num_succ == 1)
1504             {
1505               block_t *dst;
1506
1507               total = blk->count;
1508               inv_arc = NULL;
1509               for (arc = blk->succ; arc; arc = arc->succ_next)
1510                 {
1511                   total -= arc->count;
1512                   if (!arc->count_valid)
1513                     inv_arc = arc;
1514                 }
1515               dst = inv_arc->dst;
1516               inv_arc->count_valid = 1;
1517               inv_arc->count = total;
1518               blk->num_succ--;
1519               dst->num_pred--;
1520               if (dst->count_valid)
1521                 {
1522                   if (dst->num_pred == 1 && !dst->valid_chain)
1523                     {
1524                       dst->chain = valid_blocks;
1525                       dst->valid_chain = 1;
1526                       valid_blocks = dst;
1527                     }
1528                 }
1529               else
1530                 {
1531                   if (!dst->num_pred && !dst->invalid_chain)
1532                     {
1533                       dst->chain = invalid_blocks;
1534                       dst->invalid_chain = 1;
1535                       invalid_blocks = dst;
1536                     }
1537                 }
1538             }
1539           if (blk->num_pred == 1)
1540             {
1541               block_t *src;
1542
1543               total = blk->count;
1544               inv_arc = NULL;
1545               for (arc = blk->pred; arc; arc = arc->pred_next)
1546                 {
1547                   total -= arc->count;
1548                   if (!arc->count_valid)
1549                     inv_arc = arc;
1550                 }
1551               src = inv_arc->src;
1552               inv_arc->count_valid = 1;
1553               inv_arc->count = total;
1554               blk->num_pred--;
1555               src->num_succ--;
1556               if (src->count_valid)
1557                 {
1558                   if (src->num_succ == 1 && !src->valid_chain)
1559                     {
1560                       src->chain = valid_blocks;
1561                       src->valid_chain = 1;
1562                       valid_blocks = src;
1563                     }
1564                 }
1565               else
1566                 {
1567                   if (!src->num_succ && !src->invalid_chain)
1568                     {
1569                       src->chain = invalid_blocks;
1570                       src->invalid_chain = 1;
1571                       invalid_blocks = src;
1572                     }
1573                 }
1574             }
1575         }
1576     }
1577
1578   /* If the graph has been correctly solved, every block will have a
1579      valid count.  */
1580   for (ix = 0; ix < fn->num_blocks; ix++)
1581     if (!fn->blocks[ix].count_valid)
1582       {
1583         fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
1584                  bbg_file_name, fn->name);
1585         break;
1586       }
1587 }
1588
1589 /* Mark all the blocks only reachable via an incoming catch.  */
1590
1591 static void
1592 find_exception_blocks (function_t *fn)
1593 {
1594   unsigned ix;
1595   block_t **queue = XALLOCAVEC (block_t *, fn->num_blocks);
1596
1597   /* First mark all blocks as exceptional.  */
1598   for (ix = fn->num_blocks; ix--;)
1599     fn->blocks[ix].exceptional = 1;
1600
1601   /* Now mark all the blocks reachable via non-fake edges */
1602   queue[0] = fn->blocks;
1603   queue[0]->exceptional = 0;
1604   for (ix = 1; ix;)
1605     {
1606       block_t *block = queue[--ix];
1607       const arc_t *arc;
1608       
1609       for (arc = block->succ; arc; arc = arc->succ_next)
1610         if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
1611           {
1612             arc->dst->exceptional = 0;
1613             queue[ix++] = arc->dst;
1614           }
1615     }
1616 }
1617 \f
1618
1619 /* Increment totals in COVERAGE according to arc ARC.  */
1620
1621 static void
1622 add_branch_counts (coverage_t *coverage, const arc_t *arc)
1623 {
1624   if (arc->is_call_non_return)
1625     {
1626       coverage->calls++;
1627       if (arc->src->count)
1628         coverage->calls_executed++;
1629     }
1630   else if (!arc->is_unconditional)
1631     {
1632       coverage->branches++;
1633       if (arc->src->count)
1634         coverage->branches_executed++;
1635       if (arc->count)
1636         coverage->branches_taken++;
1637     }
1638 }
1639
1640 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1641    count.  If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1642    If DP is zero, no decimal point is printed. Only print 100% when
1643    TOP==BOTTOM and only print 0% when TOP=0.  If dp < 0, then simply
1644    format TOP.  Return pointer to a static string.  */
1645
1646 static char const *
1647 format_gcov (gcov_type top, gcov_type bottom, int dp)
1648 {
1649   static char buffer[20];
1650
1651   if (dp >= 0)
1652     {
1653       float ratio = bottom ? (float)top / bottom : 0;
1654       int ix;
1655       unsigned limit = 100;
1656       unsigned percent;
1657
1658       for (ix = dp; ix--; )
1659         limit *= 10;
1660
1661       percent = (unsigned) (ratio * limit + (float)0.5);
1662       if (percent <= 0 && top)
1663         percent = 1;
1664       else if (percent >= limit && top != bottom)
1665         percent = limit - 1;
1666       ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1667       if (dp)
1668         {
1669           dp++;
1670           do
1671             {
1672               buffer[ix+1] = buffer[ix];
1673               ix--;
1674             }
1675           while (dp--);
1676           buffer[ix + 1] = '.';
1677         }
1678     }
1679   else
1680     sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1681
1682   return buffer;
1683 }
1684
1685 /* Summary of execution */
1686
1687 static void
1688 executed_summary (unsigned lines, unsigned executed)
1689 {
1690   if (lines)
1691     fnotice (stdout, "Lines executed:%s of %d\n",
1692              format_gcov (executed, lines, 2), lines);
1693   else
1694     fnotice (stdout, "No executable lines\n");
1695 }
1696   
1697 /* Output summary info for a function or file.  */
1698
1699 static void
1700 function_summary (const coverage_t *coverage, const char *title)
1701 {
1702   fnotice (stdout, "%s '%s'\n", title, coverage->name);
1703   executed_summary (coverage->lines, coverage->lines_executed);
1704
1705   if (flag_branches)
1706     {
1707       if (coverage->branches)
1708         {
1709           fnotice (stdout, "Branches executed:%s of %d\n",
1710                    format_gcov (coverage->branches_executed,
1711                                 coverage->branches, 2),
1712                    coverage->branches);
1713           fnotice (stdout, "Taken at least once:%s of %d\n",
1714                    format_gcov (coverage->branches_taken,
1715                                 coverage->branches, 2),
1716                    coverage->branches);
1717         }
1718       else
1719         fnotice (stdout, "No branches\n");
1720       if (coverage->calls)
1721         fnotice (stdout, "Calls executed:%s of %d\n",
1722                  format_gcov (coverage->calls_executed, coverage->calls, 2),
1723                  coverage->calls);
1724       else
1725         fnotice (stdout, "No calls\n");
1726     }
1727 }
1728
1729 /* Canonicalize the filename NAME by canonicalizing directory
1730    separators, eliding . components and resolving .. components
1731    appropriately.  Always returns a unique string.  */
1732
1733 static char *
1734 canonicalize_name (const char *name)
1735 {
1736   /* The canonical name cannot be longer than the incoming name.  */
1737   char *result = XNEWVEC (char, strlen (name) + 1);
1738   const char *base = name, *probe;
1739   char *ptr = result;
1740   char *dd_base;
1741   int slash = 0;
1742
1743 #if HAVE_DOS_BASED_FILE_SYSTEM
1744   if (base[0] && base[1] == ':')
1745     {
1746       result[0] = base[0];
1747       result[1] = ':';
1748       base += 2;
1749       ptr += 2;
1750     }
1751 #endif
1752   for (dd_base = ptr; *base; base = probe)
1753     {
1754       size_t len;
1755       
1756       for (probe = base; *probe; probe++)
1757         if (IS_DIR_SEPARATOR (*probe))
1758           break;
1759
1760       len = probe - base;
1761       if (len == 1 && base[0] == '.')
1762         /* Elide a '.' directory */
1763         ;
1764       else if (len == 2 && base[0] == '.' && base[1] == '.')
1765         {
1766           /* '..', we can only elide it and the previous directory, if
1767              we're not a symlink.  */
1768           struct stat ATTRIBUTE_UNUSED buf;
1769
1770           *ptr = 0;
1771           if (dd_base == ptr
1772 #if defined (S_ISLNK)
1773               /* S_ISLNK is not POSIX.1-1996.  */
1774               || stat (result, &buf) || S_ISLNK (buf.st_mode)
1775 #endif
1776               )
1777             {
1778               /* Cannot elide, or unreadable or a symlink.  */
1779               dd_base = ptr + 2 + slash;
1780               goto regular;
1781             }
1782           while (ptr != dd_base && *ptr != '/')
1783             ptr--;
1784           slash = ptr != result;
1785         }
1786       else
1787         {
1788         regular:
1789           /* Regular pathname component.  */
1790           if (slash)
1791             *ptr++ = '/';
1792           memcpy (ptr, base, len);
1793           ptr += len;
1794           slash = 1;
1795         }
1796
1797       for (; IS_DIR_SEPARATOR (*probe); probe++)
1798         continue;
1799     }
1800   *ptr = 0;
1801
1802   return result;
1803 }
1804
1805 /* Generate an output file name. INPUT_NAME is the canonicalized main
1806    input file and SRC_NAME is the canonicalized file name.
1807    LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation.  With
1808    long_output_names we prepend the processed name of the input file
1809    to each output name (except when the current source file is the
1810    input file, so you don't get a double concatenation). The two
1811    components are separated by '##'.  With preserve_paths we create a
1812    filename from all path components of the source file, replacing '/'
1813    with '#', and .. with '^', without it we simply take the basename
1814    component.  (Remember, the canonicalized name will already have
1815    elided '.' components and converted \\ separators.)  */
1816
1817 static char *
1818 make_gcov_file_name (const char *input_name, const char *src_name)
1819 {
1820   char *ptr;
1821   char *result;
1822
1823   if (flag_long_names && input_name && strcmp (src_name, input_name))
1824     {
1825       /* Generate the input filename part.  */
1826       result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
1827   
1828       ptr = result;
1829       ptr = mangle_name (input_name, ptr);
1830       ptr[0] = ptr[1] = '#';
1831       ptr += 2;
1832     }
1833   else
1834     {
1835       result = XNEWVEC (char, strlen (src_name) + 10);
1836       ptr = result;
1837     }
1838
1839   ptr = mangle_name (src_name, ptr);
1840   strcpy (ptr, ".gcov");
1841   
1842   return result;
1843 }
1844
1845 static char *
1846 mangle_name (char const *base, char *ptr)
1847 {
1848   size_t len;
1849   
1850   /* Generate the source filename part.  */
1851   if (!flag_preserve_paths)
1852     {
1853       base = lbasename (base);
1854       len = strlen (base);
1855       memcpy (ptr, base, len);
1856       ptr += len;
1857     }
1858   else
1859     {
1860       /* Convert '/' to '#', convert '..' to '^',
1861          convert ':' to '~' on DOS based file system.  */
1862       const char *probe;
1863
1864 #if HAVE_DOS_BASED_FILE_SYSTEM
1865       if (base[0] && base[1] == ':')
1866         {
1867           ptr[0] = base[0];
1868           ptr[1] = '~';
1869           ptr += 2;
1870           base += 2;
1871         }
1872 #endif
1873       for (; *base; base = probe)
1874         {
1875           size_t len;
1876
1877           for (probe = base; *probe; probe++)
1878             if (*probe == '/')
1879               break;
1880           len = probe - base;
1881           if (len == 2 && base[0] == '.' && base[1] == '.')
1882             *ptr++ = '^';
1883           else
1884             {
1885               memcpy (ptr, base, len);
1886               ptr += len;
1887             }
1888           if (*probe)
1889             {
1890               *ptr++ = '#';
1891               probe++;
1892             }
1893         }
1894     }
1895   
1896   return ptr;
1897 }
1898
1899 /* Scan through the bb_data for each line in the block, increment
1900    the line number execution count indicated by the execution count of
1901    the appropriate basic block.  */
1902
1903 static void
1904 add_line_counts (coverage_t *coverage, function_t *fn)
1905 {
1906   unsigned ix;
1907   line_t *line = NULL; /* This is propagated from one iteration to the
1908                           next.  */
1909
1910   /* Scan each basic block.  */
1911   for (ix = 0; ix != fn->num_blocks; ix++)
1912     {
1913       block_t *block = &fn->blocks[ix];
1914       unsigned *encoding;
1915       const source_t *src = NULL;
1916       unsigned jx;
1917
1918       if (block->count && ix && ix + 1 != fn->num_blocks)
1919         fn->blocks_executed++;
1920       for (jx = 0, encoding = block->u.line.encoding;
1921            jx != block->u.line.num; jx++, encoding++)
1922         if (!*encoding)
1923           {
1924             src = &sources[*++encoding];
1925             jx++;
1926           }
1927         else
1928           {
1929             line = &src->lines[*encoding];
1930
1931             if (coverage)
1932               {
1933                 if (!line->exists)
1934                   coverage->lines++;
1935                 if (!line->count && block->count)
1936                   coverage->lines_executed++;
1937               }
1938             line->exists = 1;
1939             if (!block->exceptional)
1940               line->unexceptional = 1;
1941             line->count += block->count;
1942           }
1943       free (block->u.line.encoding);
1944       block->u.cycle.arc = NULL;
1945       block->u.cycle.ident = ~0U;
1946
1947       if (!ix || ix + 1 == fn->num_blocks)
1948         /* Entry or exit block */;
1949       else if (flag_all_blocks)
1950         {
1951           line_t *block_line = line;
1952
1953           if (!block_line)
1954             block_line = &sources[fn->src].lines[fn->line];
1955
1956           block->chain = block_line->u.blocks;
1957           block_line->u.blocks = block;
1958         }
1959       else if (flag_branches)
1960         {
1961           arc_t *arc;
1962
1963           for (arc = block->succ; arc; arc = arc->succ_next)
1964             {
1965               arc->line_next = line->u.branches;
1966               line->u.branches = arc;
1967               if (coverage && !arc->is_unconditional)
1968                 add_branch_counts (coverage, arc);
1969             }
1970         }
1971     }
1972   if (!line)
1973     fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
1974 }
1975
1976 /* Accumulate the line counts of a file.  */
1977
1978 static void
1979 accumulate_line_counts (source_t *src)
1980 {
1981   line_t *line;
1982   function_t *fn, *fn_p, *fn_n;
1983   unsigned ix;
1984
1985   /* Reverse the function order.  */
1986   for (fn = src->functions, fn_p = NULL; fn;
1987        fn_p = fn, fn = fn_n)
1988     {
1989       fn_n = fn->line_next;
1990       fn->line_next = fn_p;
1991     }
1992   src->functions = fn_p;
1993
1994   for (ix = src->num_lines, line = src->lines; ix--; line++)
1995     {
1996       if (!flag_all_blocks)
1997         {
1998           arc_t *arc, *arc_p, *arc_n;
1999
2000           /* Total and reverse the branch information.  */
2001           for (arc = line->u.branches, arc_p = NULL; arc;
2002                arc_p = arc, arc = arc_n)
2003             {
2004               arc_n = arc->line_next;
2005               arc->line_next = arc_p;
2006
2007               add_branch_counts (&src->coverage, arc);
2008             }
2009           line->u.branches = arc_p;
2010         }
2011       else if (line->u.blocks)
2012         {
2013           /* The user expects the line count to be the number of times
2014              a line has been executed. Simply summing the block count
2015              will give an artificially high number.  The Right Thing
2016              is to sum the entry counts to the graph of blocks on this
2017              line, then find the elementary cycles of the local graph
2018              and add the transition counts of those cycles.  */
2019           block_t *block, *block_p, *block_n;
2020           gcov_type count = 0;
2021
2022           /* Reverse the block information.  */
2023           for (block = line->u.blocks, block_p = NULL; block;
2024                block_p = block, block = block_n)
2025             {
2026               block_n = block->chain;
2027               block->chain = block_p;
2028               block->u.cycle.ident = ix;
2029             }
2030           line->u.blocks = block_p;
2031
2032           /* Sum the entry arcs.  */
2033           for (block = line->u.blocks; block; block = block->chain)
2034             {
2035               arc_t *arc;
2036
2037               for (arc = block->pred; arc; arc = arc->pred_next)
2038                 {
2039                   if (arc->src->u.cycle.ident != ix)
2040                     count += arc->count;
2041                   if (flag_branches)
2042                     add_branch_counts (&src->coverage, arc);
2043                 }
2044
2045               /* Initialize the cs_count.  */
2046               for (arc = block->succ; arc; arc = arc->succ_next)
2047                 arc->cs_count = arc->count;
2048             }
2049
2050           /* Find the loops. This uses the algorithm described in
2051              Tiernan 'An Efficient Search Algorithm to Find the
2052              Elementary Circuits of a Graph', CACM Dec 1970. We hold
2053              the P array by having each block point to the arc that
2054              connects to the previous block. The H array is implicitly
2055              held because of the arc ordering, and the block's
2056              previous arc pointer.
2057
2058              Although the algorithm is O(N^3) for highly connected
2059              graphs, at worst we'll have O(N^2), as most blocks have
2060              only one or two exits. Most graphs will be small.
2061
2062              For each loop we find, locate the arc with the smallest
2063              transition count, and add that to the cumulative
2064              count.  Decrease flow over the cycle and remove the arc
2065              from consideration.  */
2066           for (block = line->u.blocks; block; block = block->chain)
2067             {
2068               block_t *head = block;
2069               arc_t *arc;
2070
2071             next_vertex:;
2072               arc = head->succ;
2073             current_vertex:;
2074               while (arc)
2075                 {
2076                   block_t *dst = arc->dst;
2077                   if (/* Already used that arc.  */
2078                       arc->cycle
2079                       /* Not to same graph, or before first vertex.  */
2080                       || dst->u.cycle.ident != ix
2081                       /* Already in path.  */
2082                       || dst->u.cycle.arc)
2083                     {
2084                       arc = arc->succ_next;
2085                       continue;
2086                     }
2087
2088                   if (dst == block)
2089                     {
2090                       /* Found a closing arc.  */
2091                       gcov_type cycle_count = arc->cs_count;
2092                       arc_t *cycle_arc = arc;
2093                       arc_t *probe_arc;
2094
2095                       /* Locate the smallest arc count of the loop.  */
2096                       for (dst = head; (probe_arc = dst->u.cycle.arc);
2097                            dst = probe_arc->src)
2098                         if (cycle_count > probe_arc->cs_count)
2099                           {
2100                             cycle_count = probe_arc->cs_count;
2101                             cycle_arc = probe_arc;
2102                           }
2103
2104                       count += cycle_count;
2105                       cycle_arc->cycle = 1;
2106
2107                       /* Remove the flow from the cycle.  */
2108                       arc->cs_count -= cycle_count;
2109                       for (dst = head; (probe_arc = dst->u.cycle.arc);
2110                            dst = probe_arc->src)
2111                         probe_arc->cs_count -= cycle_count;
2112
2113                       /* Unwind to the cyclic arc.  */
2114                       while (head != cycle_arc->src)
2115                         {
2116                           arc = head->u.cycle.arc;
2117                           head->u.cycle.arc = NULL;
2118                           head = arc->src;
2119                         }
2120                       /* Move on.  */
2121                       arc = arc->succ_next;
2122                       continue;
2123                     }
2124
2125                   /* Add new block to chain.  */
2126                   dst->u.cycle.arc = arc;
2127                   head = dst;
2128                   goto next_vertex;
2129                 }
2130               /* We could not add another vertex to the path. Remove
2131                  the last vertex from the list.  */
2132               arc = head->u.cycle.arc;
2133               if (arc)
2134                 {
2135                   /* It was not the first vertex. Move onto next arc.  */
2136                   head->u.cycle.arc = NULL;
2137                   head = arc->src;
2138                   arc = arc->succ_next;
2139                   goto current_vertex;
2140                 }
2141               /* Mark this block as unusable.  */
2142               block->u.cycle.ident = ~0U;
2143             }
2144
2145           line->count = count;
2146         }
2147
2148       if (line->exists)
2149         {
2150           src->coverage.lines++;
2151           if (line->count)
2152             src->coverage.lines_executed++;
2153         }
2154     }
2155 }
2156
2157 /* Output information about ARC number IX.  Returns nonzero if
2158    anything is output.  */
2159
2160 static int
2161 output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
2162 {
2163   if (arc->is_call_non_return)
2164     {
2165       if (arc->src->count)
2166         {
2167           fnotice (gcov_file, "call   %2d returned %s\n", ix,
2168                    format_gcov (arc->src->count - arc->count,
2169                                 arc->src->count, -flag_counts));
2170         }
2171       else
2172         fnotice (gcov_file, "call   %2d never executed\n", ix);
2173     }
2174   else if (!arc->is_unconditional)
2175     {
2176       if (arc->src->count)
2177         fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
2178                  format_gcov (arc->count, arc->src->count, -flag_counts),
2179                  arc->fall_through ? " (fallthrough)"
2180                  : arc->is_throw ? " (throw)" : "");
2181       else
2182         fnotice (gcov_file, "branch %2d never executed\n", ix);
2183     }
2184   else if (flag_unconditional && !arc->dst->is_call_return)
2185     {
2186       if (arc->src->count)
2187         fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2188                  format_gcov (arc->count, arc->src->count, -flag_counts));
2189       else
2190         fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2191     }
2192   else
2193     return 0;
2194   return 1;
2195
2196 }
2197
2198 static const char *
2199 read_line (FILE *file)
2200 {
2201   static char *string;
2202   static size_t string_len;
2203   size_t pos = 0;
2204   char *ptr;
2205
2206   if (!string_len)
2207     {
2208       string_len = 200;
2209       string = XNEWVEC (char, string_len);
2210     }
2211
2212   while ((ptr = fgets (string + pos, string_len - pos, file)))
2213     {
2214       size_t len = strlen (string + pos);
2215
2216       if (string[pos + len - 1] == '\n')
2217         {
2218           string[pos + len - 1] = 0;
2219           return string;
2220         }
2221       pos += len;
2222       ptr = XNEWVEC (char, string_len * 2);
2223       if (ptr)
2224         {
2225           memcpy (ptr, string, pos);
2226           string = ptr;
2227           string_len += 2;
2228         }
2229       else
2230         pos = 0;
2231     }
2232       
2233   return pos ? string : NULL;
2234 }
2235
2236 /* Read in the source file one line at a time, and output that line to
2237    the gcov file preceded by its execution count and other
2238    information.  */
2239
2240 static void
2241 output_lines (FILE *gcov_file, const source_t *src)
2242 {
2243   FILE *source_file;
2244   unsigned line_num;    /* current line number.  */
2245   const line_t *line;           /* current line info ptr.  */
2246   const char *retval = "";      /* status of source file reading.  */
2247   function_t *fn = NULL;
2248
2249   fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
2250   if (!multiple_files)
2251     {
2252       fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
2253       fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
2254                no_data_file ? "-" : da_file_name);
2255       fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs);
2256     }
2257   fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
2258
2259   source_file = fopen (src->name, "r");
2260   if (!source_file)
2261     {
2262       fnotice (stderr, "Cannot open source file %s\n", src->name);
2263       retval = NULL;
2264     }
2265   else if (src->file_time == 0)
2266     fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
2267
2268   if (flag_branches)
2269     fn = src->functions;
2270
2271   for (line_num = 1, line = &src->lines[line_num];
2272        line_num < src->num_lines; line_num++, line++)
2273     {
2274       for (; fn && fn->line == line_num; fn = fn->line_next)
2275         {
2276           arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
2277           gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
2278
2279           for (; arc; arc = arc->pred_next)
2280             if (arc->fake)
2281               return_count -= arc->count;
2282
2283           fprintf (gcov_file, "function %s", fn->name);
2284           fprintf (gcov_file, " called %s",
2285                    format_gcov (fn->blocks[0].count, 0, -1));
2286           fprintf (gcov_file, " returned %s",
2287                    format_gcov (return_count, fn->blocks[0].count, 0));
2288           fprintf (gcov_file, " blocks executed %s",
2289                    format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
2290           fprintf (gcov_file, "\n");
2291         }
2292
2293       if (retval)
2294         retval = read_line (source_file);
2295
2296       /* For lines which don't exist in the .bb file, print '-' before
2297          the source line.  For lines which exist but were never
2298          executed, print '#####' or '=====' before the source line.
2299          Otherwise, print the execution count before the source line.
2300          There are 16 spaces of indentation added before the source
2301          line so that tabs won't be messed up.  */
2302       fprintf (gcov_file, "%9s:%5u:%s\n",
2303                !line->exists ? "-" : line->count
2304                ? format_gcov (line->count, 0, -1)
2305                : line->unexceptional ? "#####" : "=====", line_num,
2306                retval ? retval : "/*EOF*/");
2307
2308       if (flag_all_blocks)
2309         {
2310           block_t *block;
2311           arc_t *arc;
2312           int ix, jx;
2313
2314           for (ix = jx = 0, block = line->u.blocks; block;
2315                block = block->chain)
2316             {
2317               if (!block->is_call_return)
2318                 fprintf (gcov_file, "%9s:%5u-block %2d\n",
2319                          !line->exists ? "-" : block->count
2320                          ? format_gcov (block->count, 0, -1)
2321                          : block->exceptional ? "%%%%%" : "$$$$$",
2322                          line_num, ix++);
2323               if (flag_branches)
2324                 for (arc = block->succ; arc; arc = arc->succ_next)
2325                   jx += output_branch_count (gcov_file, jx, arc);
2326             }
2327         }
2328       else if (flag_branches)
2329         {
2330           int ix;
2331           arc_t *arc;
2332
2333           for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
2334             ix += output_branch_count (gcov_file, ix, arc);
2335         }
2336     }
2337
2338   /* Handle all remaining source lines.  There may be lines after the
2339      last line of code.  */
2340   if (retval)
2341     {
2342       for (; (retval = read_line (source_file)); line_num++)
2343         fprintf (gcov_file, "%9s:%5u:%s\n", "-", line_num, retval);
2344     }
2345
2346   if (source_file)
2347     fclose (source_file);
2348 }