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