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