OSDN Git Service

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