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