OSDN Git Service

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