xref: /dragonfly/contrib/gcc-8.0/gcc/gcov.c (revision abf903a5)
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2    source file.
3    Copyright (C) 1990-2018 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 #define INCLUDE_ALGORITHM
35 #define INCLUDE_VECTOR
36 #define INCLUDE_STRING
37 #define INCLUDE_MAP
38 #define INCLUDE_SET
39 #include "system.h"
40 #include "coretypes.h"
41 #include "tm.h"
42 #include "intl.h"
43 #include "diagnostic.h"
44 #include "version.h"
45 #include "demangle.h"
46 #include "color-macros.h"
47 
48 #include <getopt.h>
49 
50 #include "md5.h"
51 
52 using namespace std;
53 
54 #define IN_GCOV 1
55 #include "gcov-io.h"
56 #include "gcov-io.c"
57 
58 /* The gcno file is generated by -ftest-coverage option. The gcda file is
59    generated by a program compiled with -fprofile-arcs. Their formats
60    are documented in gcov-io.h.  */
61 
62 /* The functions in this file for creating and solution program flow graphs
63    are very similar to functions in the gcc source file profile.c.  In
64    some places we make use of the knowledge of how profile.c works to
65    select particular algorithms here.  */
66 
67 /* The code validates that the profile information read in corresponds
68    to the code currently being compiled.  Rather than checking for
69    identical files, the code below compares a checksum on the CFG
70    (based on the order of basic blocks and the arcs in the CFG).  If
71    the CFG checksum in the gcda file match the CFG checksum in the
72    gcno file, the profile data will be used.  */
73 
74 /* This is the size of the buffer used to read in source file lines.  */
75 
76 struct function_info;
77 struct block_info;
78 struct source_info;
79 
80 /* Describes an arc between two basic blocks.  */
81 
82 struct arc_info
83 {
84   /* source and destination blocks.  */
85   struct block_info *src;
86   struct block_info *dst;
87 
88   /* transition counts.  */
89   gcov_type count;
90   /* used in cycle search, so that we do not clobber original counts.  */
91   gcov_type cs_count;
92 
93   unsigned int count_valid : 1;
94   unsigned int on_tree : 1;
95   unsigned int fake : 1;
96   unsigned int fall_through : 1;
97 
98   /* Arc to a catch handler.  */
99   unsigned int is_throw : 1;
100 
101   /* Arc is for a function that abnormally returns.  */
102   unsigned int is_call_non_return : 1;
103 
104   /* Arc is for catch/setjmp.  */
105   unsigned int is_nonlocal_return : 1;
106 
107   /* Is an unconditional branch.  */
108   unsigned int is_unconditional : 1;
109 
110   /* Loop making arc.  */
111   unsigned int cycle : 1;
112 
113   /* Links to next arc on src and dst lists.  */
114   struct arc_info *succ_next;
115   struct arc_info *pred_next;
116 };
117 
118 /* Describes which locations (lines and files) are associated with
119    a basic block.  */
120 
121 struct block_location_info
122 {
123   block_location_info (unsigned _source_file_idx):
124     source_file_idx (_source_file_idx)
125   {}
126 
127   unsigned source_file_idx;
128   vector<unsigned> lines;
129 };
130 
131 /* Describes a basic block. Contains lists of arcs to successor and
132    predecessor blocks.  */
133 
134 struct block_info
135 {
136   /* Constructor.  */
137   block_info ();
138 
139   /* Chain of exit and entry arcs.  */
140   arc_info *succ;
141   arc_info *pred;
142 
143   /* Number of unprocessed exit and entry arcs.  */
144   gcov_type num_succ;
145   gcov_type num_pred;
146 
147   unsigned id;
148 
149   /* Block execution count.  */
150   gcov_type count;
151   unsigned count_valid : 1;
152   unsigned valid_chain : 1;
153   unsigned invalid_chain : 1;
154   unsigned exceptional : 1;
155 
156   /* Block is a call instrumenting site.  */
157   unsigned is_call_site : 1; /* Does the call.  */
158   unsigned is_call_return : 1; /* Is the return.  */
159 
160   /* Block is a landing pad for longjmp or throw.  */
161   unsigned is_nonlocal_return : 1;
162 
163   vector<block_location_info> locations;
164 
165   struct
166   {
167     /* Single line graph cycle workspace.  Used for all-blocks
168        mode.  */
169     arc_info *arc;
170     unsigned ident;
171   } cycle; /* Used in all-blocks mode, after blocks are linked onto
172 	     lines.  */
173 
174   /* Temporary chain for solving graph, and for chaining blocks on one
175      line.  */
176   struct block_info *chain;
177 
178 };
179 
180 block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred (0),
181   id (0), count (0), count_valid (0), valid_chain (0), invalid_chain (0),
182   exceptional (0), is_call_site (0), is_call_return (0), is_nonlocal_return (0),
183   locations (), chain (NULL)
184 {
185   cycle.arc = NULL;
186 }
187 
188 /* Describes a single line of source.  Contains a chain of basic blocks
189    with code on it.  */
190 
191 struct line_info
192 {
193   /* Default constructor.  */
194   line_info ();
195 
196   /* Return true when NEEDLE is one of basic blocks the line belongs to.  */
197   bool has_block (block_info *needle);
198 
199   /* Execution count.  */
200   gcov_type count;
201 
202   /* Branches from blocks that end on this line.  */
203   vector<arc_info *> branches;
204 
205   /* blocks which start on this line.  Used in all-blocks mode.  */
206   vector<block_info *> blocks;
207 
208   unsigned exists : 1;
209   unsigned unexceptional : 1;
210   unsigned has_unexecuted_block : 1;
211 };
212 
213 line_info::line_info (): count (0), branches (), blocks (), exists (false),
214   unexceptional (0), has_unexecuted_block (0)
215 {
216 }
217 
218 bool
219 line_info::has_block (block_info *needle)
220 {
221   return std::find (blocks.begin (), blocks.end (), needle) != blocks.end ();
222 }
223 
224 /* Describes a single function. Contains an array of basic blocks.  */
225 
226 struct function_info
227 {
228   function_info ();
229   ~function_info ();
230 
231   /* Return true when line N belongs to the function in source file SRC_IDX.
232      The line must be defined in body of the function, can't be inlined.  */
233   bool group_line_p (unsigned n, unsigned src_idx);
234 
235   /* Function filter based on function_info::artificial variable.  */
236 
237   static inline bool
238   is_artificial (function_info *fn)
239   {
240     return fn->artificial;
241   }
242 
243   /* Name of function.  */
244   char *name;
245   char *demangled_name;
246   unsigned ident;
247   unsigned lineno_checksum;
248   unsigned cfg_checksum;
249 
250   /* The graph contains at least one fake incoming edge.  */
251   unsigned has_catch : 1;
252 
253   /* True when the function is artificial and does not exist
254      in a source file.  */
255   unsigned artificial : 1;
256 
257   /* True when multiple functions start at a line in a source file.  */
258   unsigned is_group : 1;
259 
260   /* Array of basic blocks.  Like in GCC, the entry block is
261      at blocks[0] and the exit block is at blocks[1].  */
262 #define ENTRY_BLOCK (0)
263 #define EXIT_BLOCK (1)
264   vector<block_info> blocks;
265   unsigned blocks_executed;
266 
267   /* Raw arc coverage counts.  */
268   vector<gcov_type> counts;
269 
270   /* First line number.  */
271   unsigned start_line;
272 
273   /* First line column.  */
274   unsigned start_column;
275 
276   /* Last line number.  */
277   unsigned end_line;
278 
279   /* Index of source file where the function is defined.  */
280   unsigned src;
281 
282   /* Vector of line information.  */
283   vector<line_info> lines;
284 
285   /* Next function.  */
286   struct function_info *next;
287 };
288 
289 /* Function info comparer that will sort functions according to starting
290    line.  */
291 
292 struct function_line_start_cmp
293 {
294   inline bool operator() (const function_info *lhs,
295 			  const function_info *rhs)
296     {
297       return (lhs->start_line == rhs->start_line
298 	      ? lhs->start_column < rhs->start_column
299 	      : lhs->start_line < rhs->start_line);
300     }
301 };
302 
303 /* Describes coverage of a file or function.  */
304 
305 struct coverage_info
306 {
307   int lines;
308   int lines_executed;
309 
310   int branches;
311   int branches_executed;
312   int branches_taken;
313 
314   int calls;
315   int calls_executed;
316 
317   char *name;
318 };
319 
320 /* Describes a file mentioned in the block graph.  Contains an array
321    of line info.  */
322 
323 struct source_info
324 {
325   /* Default constructor.  */
326   source_info ();
327 
328   vector<function_info *> get_functions_at_location (unsigned line_num) const;
329 
330   /* Index of the source_info in sources vector.  */
331   unsigned index;
332 
333   /* Canonical name of source file.  */
334   char *name;
335   time_t file_time;
336 
337   /* Vector of line information.  */
338   vector<line_info> lines;
339 
340   coverage_info coverage;
341 
342   /* Functions in this source file.  These are in ascending line
343      number order.  */
344   vector <function_info *> functions;
345 };
346 
347 source_info::source_info (): index (0), name (NULL), file_time (),
348   lines (), coverage (), functions ()
349 {
350 }
351 
352 vector<function_info *>
353 source_info::get_functions_at_location (unsigned line_num) const
354 {
355   vector<function_info *> r;
356 
357   for (vector<function_info *>::const_iterator it = functions.begin ();
358        it != functions.end (); it++)
359     {
360       if ((*it)->start_line == line_num && (*it)->src == index)
361 	r.push_back (*it);
362     }
363 
364   std::sort (r.begin (), r.end (), function_line_start_cmp ());
365 
366   return r;
367 }
368 
369 class name_map
370 {
371 public:
372   name_map ()
373   {
374   }
375 
376   name_map (char *_name, unsigned _src): name (_name), src (_src)
377   {
378   }
379 
380   bool operator== (const name_map &rhs) const
381   {
382 #if HAVE_DOS_BASED_FILE_SYSTEM
383     return strcasecmp (this->name, rhs.name) == 0;
384 #else
385     return strcmp (this->name, rhs.name) == 0;
386 #endif
387   }
388 
389   bool operator< (const name_map &rhs) const
390   {
391 #if HAVE_DOS_BASED_FILE_SYSTEM
392     return strcasecmp (this->name, rhs.name) < 0;
393 #else
394     return strcmp (this->name, rhs.name) < 0;
395 #endif
396   }
397 
398   const char *name;  /* Source file name */
399   unsigned src;  /* Source file */
400 };
401 
402 /* Vector of all functions.  */
403 static vector<function_info *> functions;
404 
405 /* Vector of source files.  */
406 static vector<source_info> sources;
407 
408 /* Mapping of file names to sources */
409 static vector<name_map> names;
410 
411 /* This holds data summary information.  */
412 
413 static unsigned object_runs;
414 static unsigned program_count;
415 
416 static unsigned total_lines;
417 static unsigned total_executed;
418 
419 /* Modification time of graph file.  */
420 
421 static time_t bbg_file_time;
422 
423 /* Name of the notes (gcno) output file.  The "bbg" prefix is for
424    historical reasons, when the notes file contained only the
425    basic block graph notes.  */
426 
427 static char *bbg_file_name;
428 
429 /* Stamp of the bbg file */
430 static unsigned bbg_stamp;
431 
432 /* Supports has_unexecuted_blocks functionality.  */
433 static unsigned bbg_supports_has_unexecuted_blocks;
434 
435 /* Name and file pointer of the input file for the count data (gcda).  */
436 
437 static char *da_file_name;
438 
439 /* Data file is missing.  */
440 
441 static int no_data_file;
442 
443 /* If there is several input files, compute and display results after
444    reading all data files.  This way if two or more gcda file refer to
445    the same source file (eg inline subprograms in a .h file), the
446    counts are added.  */
447 
448 static int multiple_files = 0;
449 
450 /* Output branch probabilities.  */
451 
452 static int flag_branches = 0;
453 
454 /* Show unconditional branches too.  */
455 static int flag_unconditional = 0;
456 
457 /* Output a gcov file if this is true.  This is on by default, and can
458    be turned off by the -n option.  */
459 
460 static int flag_gcov_file = 1;
461 
462 /* Output progress indication if this is true.  This is off by default
463    and can be turned on by the -d option.  */
464 
465 static int flag_display_progress = 0;
466 
467 /* Output *.gcov file in intermediate format used by 'lcov'.  */
468 
469 static int flag_intermediate_format = 0;
470 
471 /* Output demangled function names.  */
472 
473 static int flag_demangled_names = 0;
474 
475 /* For included files, make the gcov output file name include the name
476    of the input source file.  For example, if x.h is included in a.c,
477    then the output file name is a.c##x.h.gcov instead of x.h.gcov.  */
478 
479 static int flag_long_names = 0;
480 
481 /* For situations when a long name can potentially hit filesystem path limit,
482    let's calculate md5sum of the path and append it to a file name.  */
483 
484 static int flag_hash_filenames = 0;
485 
486 /* Print verbose informations.  */
487 
488 static int flag_verbose = 0;
489 
490 /* Print colored output.  */
491 
492 static int flag_use_colors = 0;
493 
494 /* Output count information for every basic block, not merely those
495    that contain line number information.  */
496 
497 static int flag_all_blocks = 0;
498 
499 /* Output human readable numbers.  */
500 
501 static int flag_human_readable_numbers = 0;
502 
503 /* Output summary info for each function.  */
504 
505 static int flag_function_summary = 0;
506 
507 /* Object directory file prefix.  This is the directory/file where the
508    graph and data files are looked for, if nonzero.  */
509 
510 static char *object_directory = 0;
511 
512 /* Source directory prefix.  This is removed from source pathnames
513    that match, when generating the output file name.  */
514 
515 static char *source_prefix = 0;
516 static size_t source_length = 0;
517 
518 /* Only show data for sources with relative pathnames.  Absolute ones
519    usually indicate a system header file, which although it may
520    contain inline functions, is usually uninteresting.  */
521 static int flag_relative_only = 0;
522 
523 /* Preserve all pathname components. Needed when object files and
524    source files are in subdirectories. '/' is mangled as '#', '.' is
525    elided and '..' mangled to '^'.  */
526 
527 static int flag_preserve_paths = 0;
528 
529 /* Output the number of times a branch was taken as opposed to the percentage
530    of times it was taken.  */
531 
532 static int flag_counts = 0;
533 
534 /* Forward declarations.  */
535 static int process_args (int, char **);
536 static void print_usage (int) ATTRIBUTE_NORETURN;
537 static void print_version (void) ATTRIBUTE_NORETURN;
538 static void process_file (const char *);
539 static void process_all_functions (void);
540 static void generate_results (const char *);
541 static void create_file_names (const char *);
542 static char *canonicalize_name (const char *);
543 static unsigned find_source (const char *);
544 static void read_graph_file (void);
545 static int read_count_file (void);
546 static void solve_flow_graph (function_info *);
547 static void find_exception_blocks (function_info *);
548 static void add_branch_counts (coverage_info *, const arc_info *);
549 static void add_line_counts (coverage_info *, function_info *);
550 static void executed_summary (unsigned, unsigned);
551 static void function_summary (const coverage_info *, const char *);
552 static const char *format_gcov (gcov_type, gcov_type, int);
553 static void accumulate_line_counts (source_info *);
554 static void output_gcov_file (const char *, source_info *);
555 static int output_branch_count (FILE *, int, const arc_info *);
556 static void output_lines (FILE *, const source_info *);
557 static char *make_gcov_file_name (const char *, const char *);
558 static char *mangle_name (const char *, char *);
559 static void release_structures (void);
560 extern int main (int, char **);
561 
562 function_info::function_info (): name (NULL), demangled_name (NULL),
563   ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0),
564   artificial (0), is_group (0),
565   blocks (), blocks_executed (0), counts (),
566   start_line (0), start_column (), end_line (0), src (0), lines (), next (NULL)
567 {
568 }
569 
570 function_info::~function_info ()
571 {
572   for (int i = blocks.size () - 1; i >= 0; i--)
573     {
574       arc_info *arc, *arc_n;
575 
576       for (arc = blocks[i].succ; arc; arc = arc_n)
577 	{
578 	  arc_n = arc->succ_next;
579 	  free (arc);
580 	}
581     }
582   if (flag_demangled_names && demangled_name != name)
583     free (demangled_name);
584   free (name);
585 }
586 
587 bool function_info::group_line_p (unsigned n, unsigned src_idx)
588 {
589   return is_group && src == src_idx && start_line <= n && n <= end_line;
590 }
591 
592 /* Cycle detection!
593    There are a bajillion algorithms that do this.  Boost's function is named
594    hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in
595    "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs"
596    (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>).
597 
598    The basic algorithm is simple: effectively, we're finding all simple paths
599    in a subgraph (that shrinks every iteration).  Duplicates are filtered by
600    "blocking" a path when a node is added to the path (this also prevents non-
601    simple paths)--the node is unblocked only when it participates in a cycle.
602    */
603 
604 typedef vector<arc_info *> arc_vector_t;
605 typedef vector<const block_info *> block_vector_t;
606 
607 /* Enum with types of loop in CFG.  */
608 
609 enum loop_type
610 {
611   NO_LOOP = 0,
612   LOOP = 1,
613   NEGATIVE_LOOP = 3
614 };
615 
616 /* Loop_type operator that merges two values: A and B.  */
617 
618 inline loop_type& operator |= (loop_type& a, loop_type b)
619 {
620     return a = static_cast<loop_type> (a | b);
621 }
622 
623 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
624    and subtract the value from all counts.  The subtracted value is added
625    to COUNT.  Returns type of loop.  */
626 
627 static loop_type
628 handle_cycle (const arc_vector_t &edges, int64_t &count)
629 {
630   /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
631      that amount.  */
632   int64_t cycle_count = INTTYPE_MAXIMUM (int64_t);
633   for (unsigned i = 0; i < edges.size (); i++)
634     {
635       int64_t ecount = edges[i]->cs_count;
636       if (cycle_count > ecount)
637 	cycle_count = ecount;
638     }
639   count += cycle_count;
640   for (unsigned i = 0; i < edges.size (); i++)
641     edges[i]->cs_count -= cycle_count;
642 
643   return cycle_count < 0 ? NEGATIVE_LOOP : LOOP;
644 }
645 
646 /* Unblock a block U from BLOCKED.  Apart from that, iterate all blocks
647    blocked by U in BLOCK_LISTS.  */
648 
649 static void
650 unblock (const block_info *u, block_vector_t &blocked,
651 	 vector<block_vector_t > &block_lists)
652 {
653   block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u);
654   if (it == blocked.end ())
655     return;
656 
657   unsigned index = it - blocked.begin ();
658   blocked.erase (it);
659 
660   block_vector_t to_unblock (block_lists[index]);
661 
662   block_lists.erase (block_lists.begin () + index);
663 
664   for (block_vector_t::iterator it = to_unblock.begin ();
665        it != to_unblock.end (); it++)
666     unblock (*it, blocked, block_lists);
667 }
668 
669 /* Find circuit going to block V, PATH is provisional seen cycle.
670    BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
671    blocked by a block.  COUNT is accumulated count of the current LINE.
672    Returns what type of loop it contains.  */
673 
674 static loop_type
675 circuit (block_info *v, arc_vector_t &path, block_info *start,
676 	 block_vector_t &blocked, vector<block_vector_t> &block_lists,
677 	 line_info &linfo, int64_t &count)
678 {
679   loop_type result = NO_LOOP;
680 
681   /* Add v to the block list.  */
682   gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
683   blocked.push_back (v);
684   block_lists.push_back (block_vector_t ());
685 
686   for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
687     {
688       block_info *w = arc->dst;
689       if (w < start || !linfo.has_block (w))
690 	continue;
691 
692       path.push_back (arc);
693       if (w == start)
694 	/* Cycle has been found.  */
695 	result |= handle_cycle (path, count);
696       else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
697 	result |= circuit (w, path, start, blocked, block_lists, linfo, count);
698 
699       path.pop_back ();
700     }
701 
702   if (result != NO_LOOP)
703     unblock (v, blocked, block_lists);
704   else
705     for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
706       {
707 	block_info *w = arc->dst;
708 	if (w < start || !linfo.has_block (w))
709 	  continue;
710 
711 	size_t index
712 	  = find (blocked.begin (), blocked.end (), w) - blocked.begin ();
713 	gcc_assert (index < blocked.size ());
714 	block_vector_t &list = block_lists[index];
715 	if (find (list.begin (), list.end (), v) == list.end ())
716 	  list.push_back (v);
717       }
718 
719   return result;
720 }
721 
722 /* Find cycles for a LINFO.  If HANDLE_NEGATIVE_CYCLES is set and the line
723    contains a negative loop, then perform the same function once again.  */
724 
725 static gcov_type
726 get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
727 {
728   /* Note that this algorithm works even if blocks aren't in sorted order.
729      Each iteration of the circuit detection is completely independent
730      (except for reducing counts, but that shouldn't matter anyways).
731      Therefore, operating on a permuted order (i.e., non-sorted) only
732      has the effect of permuting the output cycles.  */
733 
734   loop_type result = NO_LOOP;
735   gcov_type count = 0;
736   for (vector<block_info *>::iterator it = linfo.blocks.begin ();
737        it != linfo.blocks.end (); it++)
738     {
739       arc_vector_t path;
740       block_vector_t blocked;
741       vector<block_vector_t > block_lists;
742       result |= circuit (*it, path, *it, blocked, block_lists, linfo,
743 			 count);
744     }
745 
746   /* If we have a negative cycle, repeat the find_cycles routine.  */
747   if (result == NEGATIVE_LOOP && handle_negative_cycles)
748     count += get_cycles_count (linfo, false);
749 
750   return count;
751 }
752 
753 int
754 main (int argc, char **argv)
755 {
756   int argno;
757   int first_arg;
758   const char *p;
759 
760   p = argv[0] + strlen (argv[0]);
761   while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
762     --p;
763   progname = p;
764 
765   xmalloc_set_program_name (progname);
766 
767   /* Unlock the stdio streams.  */
768   unlock_std_streams ();
769 
770   gcc_init_libintl ();
771 
772   diagnostic_initialize (global_dc, 0);
773 
774   /* Handle response files.  */
775   expandargv (&argc, &argv);
776 
777   argno = process_args (argc, argv);
778   if (optind == argc)
779     print_usage (true);
780 
781   if (argc - argno > 1)
782     multiple_files = 1;
783 
784   first_arg = argno;
785 
786   for (; argno != argc; argno++)
787     {
788       if (flag_display_progress)
789 	printf ("Processing file %d out of %d\n", argno - first_arg + 1,
790 		argc - first_arg);
791       process_file (argv[argno]);
792 
793       if (flag_intermediate_format || argno == argc - 1)
794 	{
795 	  process_all_functions ();
796 	  generate_results (argv[argno]);
797 	  release_structures ();
798 	}
799     }
800 
801   return 0;
802 }
803 
804 /* Print a usage message and exit.  If ERROR_P is nonzero, this is an error,
805    otherwise the output of --help.  */
806 
807 static void
808 print_usage (int error_p)
809 {
810   FILE *file = error_p ? stderr : stdout;
811   int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
812 
813   fnotice (file, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n");
814   fnotice (file, "Print code coverage information.\n\n");
815   fnotice (file, "  -a, --all-blocks                Show information for every basic block\n");
816   fnotice (file, "  -b, --branch-probabilities      Include branch probabilities in output\n");
817   fnotice (file, "  -c, --branch-counts             Output counts of branches taken\n\
818                                     rather than percentages\n");
819   fnotice (file, "  -d, --display-progress          Display progress information\n");
820   fnotice (file, "  -f, --function-summaries        Output summaries for each function\n");
821   fnotice (file, "  -h, --help                      Print this help, then exit\n");
822   fnotice (file, "  -i, --intermediate-format       Output .gcov file in intermediate text format\n");
823   fnotice (file, "  -j, --human-readable            Output human readable numbers\n");
824   fnotice (file, "  -k, --use-colors                Emit colored output\n");
825   fnotice (file, "  -l, --long-file-names           Use long output file names for included\n\
826                                     source files\n");
827   fnotice (file, "  -m, --demangled-names           Output demangled function names\n");
828   fnotice (file, "  -n, --no-output                 Do not create an output file\n");
829   fnotice (file, "  -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
830   fnotice (file, "  -p, --preserve-paths            Preserve all pathname components\n");
831   fnotice (file, "  -r, --relative-only             Only show data for relative sources\n");
832   fnotice (file, "  -s, --source-prefix DIR         Source prefix to elide\n");
833   fnotice (file, "  -u, --unconditional-branches    Show unconditional branch counts too\n");
834   fnotice (file, "  -v, --version                   Print version number, then exit\n");
835   fnotice (file, "  -w, --verbose                   Print verbose informations\n");
836   fnotice (file, "  -x, --hash-filenames            Hash long pathnames\n");
837   fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
838 	   bug_report_url);
839   exit (status);
840 }
841 
842 /* Print version information and exit.  */
843 
844 static void
845 print_version (void)
846 {
847   fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
848   fprintf (stdout, "Copyright %s 2018 Free Software Foundation, Inc.\n",
849 	   _("(C)"));
850   fnotice (stdout,
851 	   _("This is free software; see the source for copying conditions.\n"
852 	     "There is NO warranty; not even for MERCHANTABILITY or \n"
853 	     "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
854   exit (SUCCESS_EXIT_CODE);
855 }
856 
857 static const struct option options[] =
858 {
859   { "help",                 no_argument,       NULL, 'h' },
860   { "version",              no_argument,       NULL, 'v' },
861   { "verbose",              no_argument,       NULL, 'w' },
862   { "all-blocks",           no_argument,       NULL, 'a' },
863   { "branch-probabilities", no_argument,       NULL, 'b' },
864   { "branch-counts",        no_argument,       NULL, 'c' },
865   { "intermediate-format",  no_argument,       NULL, 'i' },
866   { "human-readable",	    no_argument,       NULL, 'j' },
867   { "no-output",            no_argument,       NULL, 'n' },
868   { "long-file-names",      no_argument,       NULL, 'l' },
869   { "function-summaries",   no_argument,       NULL, 'f' },
870   { "demangled-names",      no_argument,       NULL, 'm' },
871   { "preserve-paths",       no_argument,       NULL, 'p' },
872   { "relative-only",        no_argument,       NULL, 'r' },
873   { "object-directory",     required_argument, NULL, 'o' },
874   { "object-file",          required_argument, NULL, 'o' },
875   { "source-prefix",        required_argument, NULL, 's' },
876   { "unconditional-branches", no_argument,     NULL, 'u' },
877   { "display-progress",     no_argument,       NULL, 'd' },
878   { "hash-filenames",	    no_argument,       NULL, 'x' },
879   { "use-colors",	    no_argument,       NULL, 'k' },
880   { 0, 0, 0, 0 }
881 };
882 
883 /* Process args, return index to first non-arg.  */
884 
885 static int
886 process_args (int argc, char **argv)
887 {
888   int opt;
889 
890   const char *opts = "abcdfhijklmno:prs:uvwx";
891   while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
892     {
893       switch (opt)
894 	{
895 	case 'a':
896 	  flag_all_blocks = 1;
897 	  break;
898 	case 'b':
899 	  flag_branches = 1;
900 	  break;
901 	case 'c':
902 	  flag_counts = 1;
903 	  break;
904 	case 'f':
905 	  flag_function_summary = 1;
906 	  break;
907 	case 'h':
908 	  print_usage (false);
909 	  /* print_usage will exit.  */
910 	case 'l':
911 	  flag_long_names = 1;
912 	  break;
913 	case 'j':
914 	  flag_human_readable_numbers = 1;
915 	  break;
916 	case 'k':
917 	  flag_use_colors = 1;
918 	  break;
919 	case 'm':
920 	  flag_demangled_names = 1;
921 	  break;
922 	case 'n':
923 	  flag_gcov_file = 0;
924 	  break;
925 	case 'o':
926 	  object_directory = optarg;
927 	  break;
928 	case 's':
929 	  source_prefix = optarg;
930 	  source_length = strlen (source_prefix);
931 	  break;
932 	case 'r':
933 	  flag_relative_only = 1;
934 	  break;
935 	case 'p':
936 	  flag_preserve_paths = 1;
937 	  break;
938 	case 'u':
939 	  flag_unconditional = 1;
940 	  break;
941 	case 'i':
942           flag_intermediate_format = 1;
943           flag_gcov_file = 1;
944           break;
945         case 'd':
946           flag_display_progress = 1;
947           break;
948 	case 'x':
949 	  flag_hash_filenames = 1;
950 	  break;
951 	case 'w':
952 	  flag_verbose = 1;
953 	  break;
954 	case 'v':
955 	  print_version ();
956 	  /* print_version will exit.  */
957 	default:
958 	  print_usage (true);
959 	  /* print_usage will exit.  */
960 	}
961     }
962 
963   return optind;
964 }
965 
966 /* Output intermediate LINE sitting on LINE_NUM to output file F.  */
967 
968 static void
969 output_intermediate_line (FILE *f, line_info *line, unsigned line_num)
970 {
971   if (!line->exists)
972     return;
973 
974   fprintf (f, "lcount:%u,%s,%d\n", line_num,
975 	   format_gcov (line->count, 0, -1),
976 	   line->has_unexecuted_block);
977 
978   vector<arc_info *>::const_iterator it;
979   if (flag_branches)
980     for (it = line->branches.begin (); it != line->branches.end ();
981 	 it++)
982       {
983 	if (!(*it)->is_unconditional && !(*it)->is_call_non_return)
984 	  {
985 	    const char *branch_type;
986 	    /* branch:<line_num>,<branch_coverage_infoype>
987 	       branch_coverage_infoype
988 	       : notexec (Branch not executed)
989 	       : taken (Branch executed and taken)
990 	       : nottaken (Branch executed, but not taken)
991 	       */
992 	    if ((*it)->src->count)
993 		 branch_type
994 			= ((*it)->count > 0) ? "taken" : "nottaken";
995 	    else
996 	      branch_type = "notexec";
997 	    fprintf (f, "branch:%d,%s\n", line_num, branch_type);
998 	  }
999       }
1000 }
1001 
1002 /* Get the name of the gcov file.  The return value must be free'd.
1003 
1004    It appends the '.gcov' extension to the *basename* of the file.
1005    The resulting file name will be in PWD.
1006 
1007    e.g.,
1008    input: foo.da,       output: foo.da.gcov
1009    input: a/b/foo.cc,   output: foo.cc.gcov  */
1010 
1011 static char *
1012 get_gcov_intermediate_filename (const char *file_name)
1013 {
1014   const char *gcov = ".gcov";
1015   char *result;
1016   const char *cptr;
1017 
1018   /* Find the 'basename'.  */
1019   cptr = lbasename (file_name);
1020 
1021   result = XNEWVEC (char, strlen (cptr) + strlen (gcov) + 1);
1022   sprintf (result, "%s%s", cptr, gcov);
1023 
1024   return result;
1025 }
1026 
1027 /* Output the result in intermediate format used by 'lcov'.
1028 
1029 The intermediate format contains a single file named 'foo.cc.gcov',
1030 with no source code included.
1031 
1032 The default gcov outputs multiple files: 'foo.cc.gcov',
1033 'iostream.gcov', 'ios_base.h.gcov', etc. with source code
1034 included. Instead the intermediate format here outputs only a single
1035 file 'foo.cc.gcov' similar to the above example. */
1036 
1037 static void
1038 output_intermediate_file (FILE *gcov_file, source_info *src)
1039 {
1040   fprintf (gcov_file, "version:%s\n", version_string);
1041   fprintf (gcov_file, "file:%s\n", src->name);    /* source file name */
1042 
1043   std::sort (src->functions.begin (), src->functions.end (),
1044 	     function_line_start_cmp ());
1045   for (vector<function_info *>::iterator it = src->functions.begin ();
1046        it != src->functions.end (); it++)
1047     {
1048       /* function:<name>,<line_number>,<execution_count> */
1049       fprintf (gcov_file, "function:%d,%d,%s,%s\n", (*it)->start_line,
1050 	       (*it)->end_line, format_gcov ((*it)->blocks[0].count, 0, -1),
1051 	       flag_demangled_names ? (*it)->demangled_name : (*it)->name);
1052     }
1053 
1054   for (unsigned line_num = 1; line_num <= src->lines.size (); line_num++)
1055     {
1056       vector<function_info *> fns = src->get_functions_at_location (line_num);
1057 
1058       /* Print first group functions that begin on the line.  */
1059       for (vector<function_info *>::iterator it2 = fns.begin ();
1060 	   it2 != fns.end (); it2++)
1061 	{
1062 	  vector<line_info> &lines = (*it2)->lines;
1063 	  for (unsigned i = 0; i < lines.size (); i++)
1064 	    {
1065 	      line_info *line = &lines[i];
1066 	      output_intermediate_line (gcov_file, line, line_num + i);
1067 	    }
1068 	}
1069 
1070       /* Follow with lines associated with the source file.  */
1071       if (line_num < src->lines.size ())
1072 	output_intermediate_line (gcov_file, &src->lines[line_num], line_num);
1073     }
1074 }
1075 
1076 /* Function start pair.  */
1077 struct function_start
1078 {
1079   unsigned source_file_idx;
1080   unsigned start_line;
1081 };
1082 
1083 /* Traits class for function start hash maps below.  */
1084 
1085 struct function_start_pair_hash : typed_noop_remove <function_start>
1086 {
1087   typedef function_start value_type;
1088   typedef function_start compare_type;
1089 
1090   static hashval_t
1091   hash (const function_start &ref)
1092   {
1093     inchash::hash hstate (0);
1094     hstate.add_int (ref.source_file_idx);
1095     hstate.add_int (ref.start_line);
1096     return hstate.end ();
1097   }
1098 
1099   static bool
1100   equal (const function_start &ref1, const function_start &ref2)
1101   {
1102     return (ref1.source_file_idx == ref2.source_file_idx
1103 	    && ref1.start_line == ref2.start_line);
1104   }
1105 
1106   static void
1107   mark_deleted (function_start &ref)
1108   {
1109     ref.start_line = ~1U;
1110   }
1111 
1112   static void
1113   mark_empty (function_start &ref)
1114   {
1115     ref.start_line = ~2U;
1116   }
1117 
1118   static bool
1119   is_deleted (const function_start &ref)
1120   {
1121     return ref.start_line == ~1U;
1122   }
1123 
1124   static bool
1125   is_empty (const function_start &ref)
1126   {
1127     return ref.start_line == ~2U;
1128   }
1129 };
1130 
1131 /* Process a single input file.  */
1132 
1133 static void
1134 process_file (const char *file_name)
1135 {
1136   create_file_names (file_name);
1137   read_graph_file ();
1138   read_count_file ();
1139 }
1140 
1141 /* Process all functions in all files.  */
1142 
1143 static void
1144 process_all_functions (void)
1145 {
1146   hash_map<function_start_pair_hash, function_info *> fn_map;
1147 
1148   /* Identify group functions.  */
1149   for (vector<function_info *>::iterator it = functions.begin ();
1150        it != functions.end (); it++)
1151     if (!(*it)->artificial)
1152       {
1153 	function_start needle;
1154 	needle.source_file_idx = (*it)->src;
1155 	needle.start_line = (*it)->start_line;
1156 
1157 	function_info **slot = fn_map.get (needle);
1158 	if (slot)
1159 	  {
1160 	    (*slot)->is_group = 1;
1161 	    (*it)->is_group = 1;
1162 	  }
1163 	else
1164 	  fn_map.put (needle, *it);
1165       }
1166 
1167   /* Remove all artificial function.  */
1168   functions.erase (remove_if (functions.begin (), functions.end (),
1169 			      function_info::is_artificial), functions.end ());
1170 
1171   for (vector<function_info *>::iterator it = functions.begin ();
1172        it != functions.end (); it++)
1173     {
1174       function_info *fn = *it;
1175       unsigned src = fn->src;
1176 
1177       if (!fn->counts.empty () || no_data_file)
1178 	{
1179 	  source_info *s = &sources[src];
1180 	  s->functions.push_back (fn);
1181 
1182 	  /* Mark last line in files touched by function.  */
1183 	  for (unsigned block_no = 0; block_no != fn->blocks.size ();
1184 	       block_no++)
1185 	    {
1186 	      block_info *block = &fn->blocks[block_no];
1187 	      for (unsigned i = 0; i < block->locations.size (); i++)
1188 		{
1189 		  /* Sort lines of locations.  */
1190 		  sort (block->locations[i].lines.begin (),
1191 			block->locations[i].lines.end ());
1192 
1193 		  if (!block->locations[i].lines.empty ())
1194 		    {
1195 		      s = &sources[block->locations[i].source_file_idx];
1196 		      unsigned last_line
1197 			= block->locations[i].lines.back ();
1198 
1199 		      /* Record new lines for the function.  */
1200 		      if (last_line >= s->lines.size ())
1201 			{
1202 			  s = &sources[block->locations[i].source_file_idx];
1203 			  unsigned last_line
1204 			    = block->locations[i].lines.back ();
1205 
1206 			  /* Record new lines for the function.  */
1207 			  if (last_line >= s->lines.size ())
1208 			    {
1209 			      /* Record new lines for a source file.  */
1210 			      s->lines.resize (last_line + 1);
1211 			    }
1212 			}
1213 		    }
1214 		}
1215 	    }
1216 
1217 	  /* Allocate lines for group function, following start_line
1218 	     and end_line information of the function.  */
1219 	  if (fn->is_group)
1220 	    fn->lines.resize (fn->end_line - fn->start_line + 1);
1221 
1222 	  solve_flow_graph (fn);
1223 	  if (fn->has_catch)
1224 	    find_exception_blocks (fn);
1225 	}
1226       else
1227 	{
1228 	  /* The function was not in the executable -- some other
1229 	     instance must have been selected.  */
1230 	}
1231     }
1232 }
1233 
1234 static void
1235 output_gcov_file (const char *file_name, source_info *src)
1236 {
1237   char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name);
1238 
1239   if (src->coverage.lines)
1240     {
1241       FILE *gcov_file = fopen (gcov_file_name, "w");
1242       if (gcov_file)
1243 	{
1244 	  fnotice (stdout, "Creating '%s'\n", gcov_file_name);
1245 	  output_lines (gcov_file, src);
1246 	  if (ferror (gcov_file))
1247 	    fnotice (stderr, "Error writing output file '%s'\n",
1248 		     gcov_file_name);
1249 	  fclose (gcov_file);
1250 	}
1251       else
1252 	fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
1253     }
1254   else
1255     {
1256       unlink (gcov_file_name);
1257       fnotice (stdout, "Removing '%s'\n", gcov_file_name);
1258     }
1259   free (gcov_file_name);
1260 }
1261 
1262 static void
1263 generate_results (const char *file_name)
1264 {
1265   FILE *gcov_intermediate_file = NULL;
1266   char *gcov_intermediate_filename = NULL;
1267 
1268   for (vector<function_info *>::iterator it = functions.begin ();
1269        it != functions.end (); it++)
1270     {
1271       function_info *fn = *it;
1272       coverage_info coverage;
1273 
1274       memset (&coverage, 0, sizeof (coverage));
1275       coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
1276       add_line_counts (flag_function_summary ? &coverage : NULL, fn);
1277       if (flag_function_summary)
1278 	{
1279 	  function_summary (&coverage, "Function");
1280 	  fnotice (stdout, "\n");
1281 	}
1282     }
1283 
1284   name_map needle;
1285 
1286   if (file_name)
1287     {
1288       needle.name = file_name;
1289       vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1290 						 needle);
1291       if (it != names.end ())
1292 	file_name = sources[it->src].coverage.name;
1293       else
1294 	file_name = canonicalize_name (file_name);
1295     }
1296 
1297   if (flag_gcov_file && flag_intermediate_format)
1298     {
1299       /* Open the intermediate file.  */
1300       gcov_intermediate_filename = get_gcov_intermediate_filename (file_name);
1301       gcov_intermediate_file = fopen (gcov_intermediate_filename, "w");
1302       if (!gcov_intermediate_file)
1303 	{
1304 	  fnotice (stderr, "Cannot open intermediate output file %s\n",
1305 		   gcov_intermediate_filename);
1306 	  return;
1307 	}
1308     }
1309 
1310   for (vector<source_info>::iterator it = sources.begin ();
1311        it != sources.end (); it++)
1312     {
1313       source_info *src = &(*it);
1314       if (flag_relative_only)
1315 	{
1316 	  /* Ignore this source, if it is an absolute path (after
1317 	     source prefix removal).  */
1318 	  char first = src->coverage.name[0];
1319 
1320 #if HAVE_DOS_BASED_FILE_SYSTEM
1321 	  if (first && src->coverage.name[1] == ':')
1322 	    first = src->coverage.name[2];
1323 #endif
1324 	  if (IS_DIR_SEPARATOR (first))
1325 	    continue;
1326 	}
1327 
1328       accumulate_line_counts (src);
1329       function_summary (&src->coverage, "File");
1330       total_lines += src->coverage.lines;
1331       total_executed += src->coverage.lines_executed;
1332       if (flag_gcov_file)
1333 	{
1334 	  if (flag_intermediate_format)
1335 	    /* Output the intermediate format without requiring source
1336 	       files.  This outputs a section to a *single* file.  */
1337 	    output_intermediate_file (gcov_intermediate_file, src);
1338 	  else
1339 	    output_gcov_file (file_name, src);
1340 	  fnotice (stdout, "\n");
1341 	}
1342     }
1343 
1344   if (flag_gcov_file && flag_intermediate_format)
1345     {
1346       /* Now we've finished writing the intermediate file.  */
1347       fclose (gcov_intermediate_file);
1348       XDELETEVEC (gcov_intermediate_filename);
1349     }
1350 
1351   if (!file_name)
1352     executed_summary (total_lines, total_executed);
1353 }
1354 
1355 /* Release all memory used.  */
1356 
1357 static void
1358 release_structures (void)
1359 {
1360   for (vector<function_info *>::iterator it = functions.begin ();
1361        it != functions.end (); it++)
1362     delete (*it);
1363 
1364   sources.resize (0);
1365   names.resize (0);
1366   functions.resize (0);
1367 }
1368 
1369 /* Generate the names of the graph and data files.  If OBJECT_DIRECTORY
1370    is not specified, these are named from FILE_NAME sans extension.  If
1371    OBJECT_DIRECTORY is specified and is a directory, the files are in that
1372    directory, but named from the basename of the FILE_NAME, sans extension.
1373    Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
1374    and the data files are named from that.  */
1375 
1376 static void
1377 create_file_names (const char *file_name)
1378 {
1379   char *cptr;
1380   char *name;
1381   int length = strlen (file_name);
1382   int base;
1383 
1384   /* Free previous file names.  */
1385   free (bbg_file_name);
1386   free (da_file_name);
1387   da_file_name = bbg_file_name = NULL;
1388   bbg_file_time = 0;
1389   bbg_stamp = 0;
1390 
1391   if (object_directory && object_directory[0])
1392     {
1393       struct stat status;
1394 
1395       length += strlen (object_directory) + 2;
1396       name = XNEWVEC (char, length);
1397       name[0] = 0;
1398 
1399       base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
1400       strcat (name, object_directory);
1401       if (base && (!IS_DIR_SEPARATOR (name[strlen (name) - 1])))
1402 	strcat (name, "/");
1403     }
1404   else
1405     {
1406       name = XNEWVEC (char, length + 1);
1407       strcpy (name, file_name);
1408       base = 0;
1409     }
1410 
1411   if (base)
1412     {
1413       /* Append source file name.  */
1414       const char *cptr = lbasename (file_name);
1415       strcat (name, cptr ? cptr : file_name);
1416     }
1417 
1418   /* Remove the extension.  */
1419   cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
1420   if (cptr)
1421     *cptr = 0;
1422 
1423   length = strlen (name);
1424 
1425   bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
1426   strcpy (bbg_file_name, name);
1427   strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
1428 
1429   da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
1430   strcpy (da_file_name, name);
1431   strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
1432 
1433   free (name);
1434   return;
1435 }
1436 
1437 /* Find or create a source file structure for FILE_NAME. Copies
1438    FILE_NAME on creation */
1439 
1440 static unsigned
1441 find_source (const char *file_name)
1442 {
1443   char *canon;
1444   unsigned idx;
1445   struct stat status;
1446 
1447   if (!file_name)
1448     file_name = "<unknown>";
1449 
1450   name_map needle;
1451   needle.name = file_name;
1452 
1453   vector<name_map>::iterator it = std::find (names.begin (), names.end (),
1454 					     needle);
1455   if (it != names.end ())
1456     {
1457       idx = it->src;
1458       goto check_date;
1459     }
1460 
1461   /* Not found, try the canonical name. */
1462   canon = canonicalize_name (file_name);
1463   needle.name = canon;
1464   it = std::find (names.begin (), names.end (), needle);
1465   if (it == names.end ())
1466     {
1467       /* Not found with canonical name, create a new source.  */
1468       source_info *src;
1469 
1470       idx = sources.size ();
1471       needle = name_map (canon, idx);
1472       names.push_back (needle);
1473 
1474       sources.push_back (source_info ());
1475       src = &sources.back ();
1476       src->name = canon;
1477       src->coverage.name = src->name;
1478       src->index = idx;
1479       if (source_length
1480 #if HAVE_DOS_BASED_FILE_SYSTEM
1481 	  /* You lose if separators don't match exactly in the
1482 	     prefix.  */
1483 	  && !strncasecmp (source_prefix, src->coverage.name, source_length)
1484 #else
1485 	  && !strncmp (source_prefix, src->coverage.name, source_length)
1486 #endif
1487 	  && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
1488 	src->coverage.name += source_length + 1;
1489       if (!stat (src->name, &status))
1490 	src->file_time = status.st_mtime;
1491     }
1492   else
1493     idx = it->src;
1494 
1495   needle.name = file_name;
1496   if (std::find (names.begin (), names.end (), needle) == names.end ())
1497     {
1498       /* Append the non-canonical name.  */
1499       names.push_back (name_map (xstrdup (file_name), idx));
1500     }
1501 
1502   /* Resort the name map.  */
1503   std::sort (names.begin (), names.end ());
1504 
1505  check_date:
1506   if (sources[idx].file_time > bbg_file_time)
1507     {
1508       static int info_emitted;
1509 
1510       fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
1511 	       file_name, bbg_file_name);
1512       if (!info_emitted)
1513 	{
1514 	  fnotice (stderr,
1515 		   "(the message is displayed only once per source file)\n");
1516 	  info_emitted = 1;
1517 	}
1518       sources[idx].file_time = 0;
1519     }
1520 
1521   return idx;
1522 }
1523 
1524 /* Read the notes file.  Save functions to FUNCTIONS global vector.  */
1525 
1526 static void
1527 read_graph_file (void)
1528 {
1529   unsigned version;
1530   unsigned current_tag = 0;
1531   unsigned tag;
1532 
1533   if (!gcov_open (bbg_file_name, 1))
1534     {
1535       fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1536       return;
1537     }
1538   bbg_file_time = gcov_time ();
1539   if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
1540     {
1541       fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
1542       gcov_close ();
1543       return;
1544     }
1545 
1546   version = gcov_read_unsigned ();
1547   if (version != GCOV_VERSION)
1548     {
1549       char v[4], e[4];
1550 
1551       GCOV_UNSIGNED2STRING (v, version);
1552       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1553 
1554       fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
1555 	       bbg_file_name, v, e);
1556     }
1557   bbg_stamp = gcov_read_unsigned ();
1558   bbg_supports_has_unexecuted_blocks = gcov_read_unsigned ();
1559 
1560   function_info *fn = NULL;
1561   while ((tag = gcov_read_unsigned ()))
1562     {
1563       unsigned length = gcov_read_unsigned ();
1564       gcov_position_t base = gcov_position ();
1565 
1566       if (tag == GCOV_TAG_FUNCTION)
1567 	{
1568 	  char *function_name;
1569 	  unsigned ident;
1570 	  unsigned lineno_checksum, cfg_checksum;
1571 
1572 	  ident = gcov_read_unsigned ();
1573 	  lineno_checksum = gcov_read_unsigned ();
1574 	  cfg_checksum = gcov_read_unsigned ();
1575 	  function_name = xstrdup (gcov_read_string ());
1576 	  unsigned artificial = gcov_read_unsigned ();
1577 	  unsigned src_idx = find_source (gcov_read_string ());
1578 	  unsigned start_line = gcov_read_unsigned ();
1579 	  unsigned start_column = gcov_read_unsigned ();
1580 	  unsigned end_line = gcov_read_unsigned ();
1581 
1582 	  fn = new function_info ();
1583 	  functions.push_back (fn);
1584 	  fn->name = function_name;
1585 	  if (flag_demangled_names)
1586 	    {
1587 	      fn->demangled_name = cplus_demangle (fn->name, DMGL_PARAMS);
1588 	      if (!fn->demangled_name)
1589 		fn->demangled_name = fn->name;
1590 	    }
1591 	  fn->ident = ident;
1592 	  fn->lineno_checksum = lineno_checksum;
1593 	  fn->cfg_checksum = cfg_checksum;
1594 	  fn->src = src_idx;
1595 	  fn->start_line = start_line;
1596 	  fn->start_column = start_column;
1597 	  fn->end_line = end_line;
1598 	  fn->artificial = artificial;
1599 
1600 	  current_tag = tag;
1601 	}
1602       else if (fn && tag == GCOV_TAG_BLOCKS)
1603 	{
1604 	  if (!fn->blocks.empty ())
1605 	    fnotice (stderr, "%s:already seen blocks for '%s'\n",
1606 		     bbg_file_name, fn->name);
1607 	  else
1608 	    fn->blocks.resize (gcov_read_unsigned ());
1609 	}
1610       else if (fn && tag == GCOV_TAG_ARCS)
1611 	{
1612 	  unsigned src = gcov_read_unsigned ();
1613 	  fn->blocks[src].id = src;
1614 	  unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
1615 	  block_info *src_blk = &fn->blocks[src];
1616 	  unsigned mark_catches = 0;
1617 	  struct arc_info *arc;
1618 
1619 	  if (src >= fn->blocks.size () || fn->blocks[src].succ)
1620 	    goto corrupt;
1621 
1622 	  while (num_dests--)
1623 	    {
1624 	      unsigned dest = gcov_read_unsigned ();
1625 	      unsigned flags = gcov_read_unsigned ();
1626 
1627 	      if (dest >= fn->blocks.size ())
1628 		goto corrupt;
1629 	      arc = XCNEW (arc_info);
1630 
1631 	      arc->dst = &fn->blocks[dest];
1632 	      arc->src = src_blk;
1633 
1634 	      arc->count = 0;
1635 	      arc->count_valid = 0;
1636 	      arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1637 	      arc->fake = !!(flags & GCOV_ARC_FAKE);
1638 	      arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
1639 
1640 	      arc->succ_next = src_blk->succ;
1641 	      src_blk->succ = arc;
1642 	      src_blk->num_succ++;
1643 
1644 	      arc->pred_next = fn->blocks[dest].pred;
1645 	      fn->blocks[dest].pred = arc;
1646 	      fn->blocks[dest].num_pred++;
1647 
1648 	      if (arc->fake)
1649 		{
1650 		  if (src)
1651 		    {
1652 		      /* Exceptional exit from this function, the
1653 			 source block must be a call.  */
1654 		      fn->blocks[src].is_call_site = 1;
1655 		      arc->is_call_non_return = 1;
1656 		      mark_catches = 1;
1657 		    }
1658 		  else
1659 		    {
1660 		      /* Non-local return from a callee of this
1661 			 function.  The destination block is a setjmp.  */
1662 		      arc->is_nonlocal_return = 1;
1663 		      fn->blocks[dest].is_nonlocal_return = 1;
1664 		    }
1665 		}
1666 
1667 	      if (!arc->on_tree)
1668 		fn->counts.push_back (0);
1669 	    }
1670 
1671 	  if (mark_catches)
1672 	    {
1673 	      /* We have a fake exit from this block.  The other
1674 		 non-fall through exits must be to catch handlers.
1675 		 Mark them as catch arcs.  */
1676 
1677 	      for (arc = src_blk->succ; arc; arc = arc->succ_next)
1678 		if (!arc->fake && !arc->fall_through)
1679 		  {
1680 		    arc->is_throw = 1;
1681 		    fn->has_catch = 1;
1682 		  }
1683 	    }
1684 	}
1685       else if (fn && tag == GCOV_TAG_LINES)
1686 	{
1687 	  unsigned blockno = gcov_read_unsigned ();
1688 	  block_info *block = &fn->blocks[blockno];
1689 
1690 	  if (blockno >= fn->blocks.size ())
1691 	    goto corrupt;
1692 
1693 	  while (true)
1694 	    {
1695 	      unsigned lineno = gcov_read_unsigned ();
1696 
1697 	      if (lineno)
1698 		block->locations.back ().lines.push_back (lineno);
1699 	      else
1700 		{
1701 		  const char *file_name = gcov_read_string ();
1702 
1703 		  if (!file_name)
1704 		    break;
1705 		  block->locations.push_back (block_location_info
1706 					      (find_source (file_name)));
1707 		}
1708 	    }
1709 	}
1710       else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1711 	{
1712 	  fn = NULL;
1713 	  current_tag = 0;
1714 	}
1715       gcov_sync (base, length);
1716       if (gcov_is_error ())
1717 	{
1718 	corrupt:;
1719 	  fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1720 	  break;
1721 	}
1722     }
1723   gcov_close ();
1724 
1725   if (functions.empty ())
1726     fnotice (stderr, "%s:no functions found\n", bbg_file_name);
1727 }
1728 
1729 /* Reads profiles from the count file and attach to each
1730    function. Return nonzero if fatal error.  */
1731 
1732 static int
1733 read_count_file (void)
1734 {
1735   unsigned ix;
1736   unsigned version;
1737   unsigned tag;
1738   function_info *fn = NULL;
1739   int error = 0;
1740 
1741   if (!gcov_open (da_file_name, 1))
1742     {
1743       fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1744 	       da_file_name);
1745       no_data_file = 1;
1746       return 0;
1747     }
1748   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
1749     {
1750       fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1751     cleanup:;
1752       gcov_close ();
1753       return 1;
1754     }
1755   version = gcov_read_unsigned ();
1756   if (version != GCOV_VERSION)
1757     {
1758       char v[4], e[4];
1759 
1760       GCOV_UNSIGNED2STRING (v, version);
1761       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1762 
1763       fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
1764 	       da_file_name, v, e);
1765     }
1766   tag = gcov_read_unsigned ();
1767   if (tag != bbg_stamp)
1768     {
1769       fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
1770       goto cleanup;
1771     }
1772 
1773   while ((tag = gcov_read_unsigned ()))
1774     {
1775       unsigned length = gcov_read_unsigned ();
1776       unsigned long base = gcov_position ();
1777 
1778       if (tag == GCOV_TAG_PROGRAM_SUMMARY)
1779 	{
1780 	  struct gcov_summary summary;
1781 	  gcov_read_summary (&summary);
1782 	  object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1783 	  program_count++;
1784 	}
1785       else if (tag == GCOV_TAG_FUNCTION && !length)
1786 	; /* placeholder  */
1787       else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1788 	{
1789 	  unsigned ident;
1790 
1791 	  /* Try to find the function in the list.  To speed up the
1792 	     search, first start from the last function found.  */
1793 	  ident = gcov_read_unsigned ();
1794 
1795 	  fn = NULL;
1796 	  for (vector<function_info *>::reverse_iterator it
1797 	       = functions.rbegin (); it != functions.rend (); it++)
1798 	    {
1799 	      if ((*it)->ident == ident)
1800 		{
1801 		  fn = *it;
1802 		  break;
1803 		}
1804 	    }
1805 
1806 	  if (!fn)
1807 	    ;
1808 	  else if (gcov_read_unsigned () != fn->lineno_checksum
1809 		   || gcov_read_unsigned () != fn->cfg_checksum)
1810 	    {
1811 	    mismatch:;
1812 	      fnotice (stderr, "%s:profile mismatch for '%s'\n",
1813 		       da_file_name, fn->name);
1814 	      goto cleanup;
1815 	    }
1816 	}
1817       else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
1818 	{
1819 	  if (length != GCOV_TAG_COUNTER_LENGTH (fn->counts.size ()))
1820 	    goto mismatch;
1821 
1822 	  for (ix = 0; ix != fn->counts.size (); ix++)
1823 	    fn->counts[ix] += gcov_read_counter ();
1824 	}
1825       gcov_sync (base, length);
1826       if ((error = gcov_is_error ()))
1827 	{
1828 	  fnotice (stderr,
1829 		   error < 0
1830 		   ? N_("%s:overflowed\n")
1831 		   : N_("%s:corrupted\n"),
1832 		   da_file_name);
1833 	  goto cleanup;
1834 	}
1835     }
1836 
1837   gcov_close ();
1838   return 0;
1839 }
1840 
1841 /* Solve the flow graph. Propagate counts from the instrumented arcs
1842    to the blocks and the uninstrumented arcs.  */
1843 
1844 static void
1845 solve_flow_graph (function_info *fn)
1846 {
1847   unsigned ix;
1848   arc_info *arc;
1849   gcov_type *count_ptr = &fn->counts.front ();
1850   block_info *blk;
1851   block_info *valid_blocks = NULL;    /* valid, but unpropagated blocks.  */
1852   block_info *invalid_blocks = NULL;  /* invalid, but inferable blocks.  */
1853 
1854   /* The arcs were built in reverse order.  Fix that now.  */
1855   for (ix = fn->blocks.size (); ix--;)
1856     {
1857       arc_info *arc_p, *arc_n;
1858 
1859       for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1860 	   arc_p = arc, arc = arc_n)
1861 	{
1862 	  arc_n = arc->succ_next;
1863 	  arc->succ_next = arc_p;
1864 	}
1865       fn->blocks[ix].succ = arc_p;
1866 
1867       for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1868 	   arc_p = arc, arc = arc_n)
1869 	{
1870 	  arc_n = arc->pred_next;
1871 	  arc->pred_next = arc_p;
1872 	}
1873       fn->blocks[ix].pred = arc_p;
1874     }
1875 
1876   if (fn->blocks.size () < 2)
1877     fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
1878 	     bbg_file_name, fn->name);
1879   else
1880     {
1881       if (fn->blocks[ENTRY_BLOCK].num_pred)
1882 	fnotice (stderr, "%s:'%s' has arcs to entry block\n",
1883 		 bbg_file_name, fn->name);
1884       else
1885 	/* We can't deduce the entry block counts from the lack of
1886 	   predecessors.  */
1887 	fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
1888 
1889       if (fn->blocks[EXIT_BLOCK].num_succ)
1890 	fnotice (stderr, "%s:'%s' has arcs from exit block\n",
1891 		 bbg_file_name, fn->name);
1892       else
1893 	/* Likewise, we can't deduce exit block counts from the lack
1894 	   of its successors.  */
1895 	fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
1896     }
1897 
1898   /* Propagate the measured counts, this must be done in the same
1899      order as the code in profile.c  */
1900   for (unsigned i = 0; i < fn->blocks.size (); i++)
1901     {
1902       blk = &fn->blocks[i];
1903       block_info const *prev_dst = NULL;
1904       int out_of_order = 0;
1905       int non_fake_succ = 0;
1906 
1907       for (arc = blk->succ; arc; arc = arc->succ_next)
1908 	{
1909 	  if (!arc->fake)
1910 	    non_fake_succ++;
1911 
1912 	  if (!arc->on_tree)
1913 	    {
1914 	      if (count_ptr)
1915 		arc->count = *count_ptr++;
1916 	      arc->count_valid = 1;
1917 	      blk->num_succ--;
1918 	      arc->dst->num_pred--;
1919 	    }
1920 	  if (prev_dst && prev_dst > arc->dst)
1921 	    out_of_order = 1;
1922 	  prev_dst = arc->dst;
1923 	}
1924       if (non_fake_succ == 1)
1925 	{
1926 	  /* If there is only one non-fake exit, it is an
1927 	     unconditional branch.  */
1928 	  for (arc = blk->succ; arc; arc = arc->succ_next)
1929 	    if (!arc->fake)
1930 	      {
1931 		arc->is_unconditional = 1;
1932 		/* If this block is instrumenting a call, it might be
1933 		   an artificial block. It is not artificial if it has
1934 		   a non-fallthrough exit, or the destination of this
1935 		   arc has more than one entry.  Mark the destination
1936 		   block as a return site, if none of those conditions
1937 		   hold.  */
1938 		if (blk->is_call_site && arc->fall_through
1939 		    && arc->dst->pred == arc && !arc->pred_next)
1940 		  arc->dst->is_call_return = 1;
1941 	      }
1942 	}
1943 
1944       /* Sort the successor arcs into ascending dst order. profile.c
1945 	 normally produces arcs in the right order, but sometimes with
1946 	 one or two out of order.  We're not using a particularly
1947 	 smart sort.  */
1948       if (out_of_order)
1949 	{
1950 	  arc_info *start = blk->succ;
1951 	  unsigned changes = 1;
1952 
1953 	  while (changes)
1954 	    {
1955 	      arc_info *arc, *arc_p, *arc_n;
1956 
1957 	      changes = 0;
1958 	      for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1959 		{
1960 		  if (arc->dst > arc_n->dst)
1961 		    {
1962 		      changes = 1;
1963 		      if (arc_p)
1964 			arc_p->succ_next = arc_n;
1965 		      else
1966 			start = arc_n;
1967 		      arc->succ_next = arc_n->succ_next;
1968 		      arc_n->succ_next = arc;
1969 		      arc_p = arc_n;
1970 		    }
1971 		  else
1972 		    {
1973 		      arc_p = arc;
1974 		      arc = arc_n;
1975 		    }
1976 		}
1977 	    }
1978 	  blk->succ = start;
1979 	}
1980 
1981       /* Place it on the invalid chain, it will be ignored if that's
1982 	 wrong.  */
1983       blk->invalid_chain = 1;
1984       blk->chain = invalid_blocks;
1985       invalid_blocks = blk;
1986     }
1987 
1988   while (invalid_blocks || valid_blocks)
1989     {
1990       while ((blk = invalid_blocks))
1991 	{
1992 	  gcov_type total = 0;
1993 	  const arc_info *arc;
1994 
1995 	  invalid_blocks = blk->chain;
1996 	  blk->invalid_chain = 0;
1997 	  if (!blk->num_succ)
1998 	    for (arc = blk->succ; arc; arc = arc->succ_next)
1999 	      total += arc->count;
2000 	  else if (!blk->num_pred)
2001 	    for (arc = blk->pred; arc; arc = arc->pred_next)
2002 	      total += arc->count;
2003 	  else
2004 	    continue;
2005 
2006 	  blk->count = total;
2007 	  blk->count_valid = 1;
2008 	  blk->chain = valid_blocks;
2009 	  blk->valid_chain = 1;
2010 	  valid_blocks = blk;
2011 	}
2012       while ((blk = valid_blocks))
2013 	{
2014 	  gcov_type total;
2015 	  arc_info *arc, *inv_arc;
2016 
2017 	  valid_blocks = blk->chain;
2018 	  blk->valid_chain = 0;
2019 	  if (blk->num_succ == 1)
2020 	    {
2021 	      block_info *dst;
2022 
2023 	      total = blk->count;
2024 	      inv_arc = NULL;
2025 	      for (arc = blk->succ; arc; arc = arc->succ_next)
2026 		{
2027 		  total -= arc->count;
2028 		  if (!arc->count_valid)
2029 		    inv_arc = arc;
2030 		}
2031 	      dst = inv_arc->dst;
2032 	      inv_arc->count_valid = 1;
2033 	      inv_arc->count = total;
2034 	      blk->num_succ--;
2035 	      dst->num_pred--;
2036 	      if (dst->count_valid)
2037 		{
2038 		  if (dst->num_pred == 1 && !dst->valid_chain)
2039 		    {
2040 		      dst->chain = valid_blocks;
2041 		      dst->valid_chain = 1;
2042 		      valid_blocks = dst;
2043 		    }
2044 		}
2045 	      else
2046 		{
2047 		  if (!dst->num_pred && !dst->invalid_chain)
2048 		    {
2049 		      dst->chain = invalid_blocks;
2050 		      dst->invalid_chain = 1;
2051 		      invalid_blocks = dst;
2052 		    }
2053 		}
2054 	    }
2055 	  if (blk->num_pred == 1)
2056 	    {
2057 	      block_info *src;
2058 
2059 	      total = blk->count;
2060 	      inv_arc = NULL;
2061 	      for (arc = blk->pred; arc; arc = arc->pred_next)
2062 		{
2063 		  total -= arc->count;
2064 		  if (!arc->count_valid)
2065 		    inv_arc = arc;
2066 		}
2067 	      src = inv_arc->src;
2068 	      inv_arc->count_valid = 1;
2069 	      inv_arc->count = total;
2070 	      blk->num_pred--;
2071 	      src->num_succ--;
2072 	      if (src->count_valid)
2073 		{
2074 		  if (src->num_succ == 1 && !src->valid_chain)
2075 		    {
2076 		      src->chain = valid_blocks;
2077 		      src->valid_chain = 1;
2078 		      valid_blocks = src;
2079 		    }
2080 		}
2081 	      else
2082 		{
2083 		  if (!src->num_succ && !src->invalid_chain)
2084 		    {
2085 		      src->chain = invalid_blocks;
2086 		      src->invalid_chain = 1;
2087 		      invalid_blocks = src;
2088 		    }
2089 		}
2090 	    }
2091 	}
2092     }
2093 
2094   /* If the graph has been correctly solved, every block will have a
2095      valid count.  */
2096   for (unsigned i = 0; ix < fn->blocks.size (); i++)
2097     if (!fn->blocks[i].count_valid)
2098       {
2099 	fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
2100 		 bbg_file_name, fn->name);
2101 	break;
2102       }
2103 }
2104 
2105 /* Mark all the blocks only reachable via an incoming catch.  */
2106 
2107 static void
2108 find_exception_blocks (function_info *fn)
2109 {
2110   unsigned ix;
2111   block_info **queue = XALLOCAVEC (block_info *, fn->blocks.size ());
2112 
2113   /* First mark all blocks as exceptional.  */
2114   for (ix = fn->blocks.size (); ix--;)
2115     fn->blocks[ix].exceptional = 1;
2116 
2117   /* Now mark all the blocks reachable via non-fake edges */
2118   queue[0] = &fn->blocks[0];
2119   queue[0]->exceptional = 0;
2120   for (ix = 1; ix;)
2121     {
2122       block_info *block = queue[--ix];
2123       const arc_info *arc;
2124 
2125       for (arc = block->succ; arc; arc = arc->succ_next)
2126 	if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
2127 	  {
2128 	    arc->dst->exceptional = 0;
2129 	    queue[ix++] = arc->dst;
2130 	  }
2131     }
2132 }
2133 
2134 
2135 /* Increment totals in COVERAGE according to arc ARC.  */
2136 
2137 static void
2138 add_branch_counts (coverage_info *coverage, const arc_info *arc)
2139 {
2140   if (arc->is_call_non_return)
2141     {
2142       coverage->calls++;
2143       if (arc->src->count)
2144 	coverage->calls_executed++;
2145     }
2146   else if (!arc->is_unconditional)
2147     {
2148       coverage->branches++;
2149       if (arc->src->count)
2150 	coverage->branches_executed++;
2151       if (arc->count)
2152 	coverage->branches_taken++;
2153     }
2154 }
2155 
2156 /* Format COUNT, if flag_human_readable_numbers is set, return it human
2157    readable format.  */
2158 
2159 static char const *
2160 format_count (gcov_type count)
2161 {
2162   static char buffer[64];
2163   const char *units = " kMGTPEZY";
2164 
2165   if (count < 1000 || !flag_human_readable_numbers)
2166     {
2167       sprintf (buffer, "%" PRId64, count);
2168       return buffer;
2169     }
2170 
2171   unsigned i;
2172   gcov_type divisor = 1;
2173   for (i = 0; units[i+1]; i++, divisor *= 1000)
2174     {
2175       if (count + divisor / 2 < 1000 * divisor)
2176 	break;
2177     }
2178   gcov_type r  = (count + divisor / 2) / divisor;
2179   sprintf (buffer, "%" PRId64 "%c", r, units[i]);
2180   return buffer;
2181 }
2182 
2183 /* Format a GCOV_TYPE integer as either a percent ratio, or absolute
2184    count.  If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
2185    If DP is zero, no decimal point is printed. Only print 100% when
2186    TOP==BOTTOM and only print 0% when TOP=0.  If dp < 0, then simply
2187    format TOP.  Return pointer to a static string.  */
2188 
2189 static char const *
2190 format_gcov (gcov_type top, gcov_type bottom, int dp)
2191 {
2192   static char buffer[20];
2193 
2194   /* Handle invalid values that would result in a misleading value.  */
2195   if (bottom != 0 && top > bottom && dp >= 0)
2196     {
2197       sprintf (buffer, "NAN %%");
2198       return buffer;
2199     }
2200 
2201   if (dp >= 0)
2202     {
2203       float ratio = bottom ? (float)top / bottom : 0;
2204       int ix;
2205       unsigned limit = 100;
2206       unsigned percent;
2207 
2208       for (ix = dp; ix--; )
2209 	limit *= 10;
2210 
2211       percent = (unsigned) (ratio * limit + (float)0.5);
2212       if (percent <= 0 && top)
2213 	percent = 1;
2214       else if (percent >= limit && top != bottom)
2215 	percent = limit - 1;
2216       ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
2217       if (dp)
2218 	{
2219 	  dp++;
2220 	  do
2221 	    {
2222 	      buffer[ix+1] = buffer[ix];
2223 	      ix--;
2224 	    }
2225 	  while (dp--);
2226 	  buffer[ix + 1] = '.';
2227 	}
2228     }
2229   else
2230     return format_count (top);
2231 
2232   return buffer;
2233 }
2234 
2235 /* Summary of execution */
2236 
2237 static void
2238 executed_summary (unsigned lines, unsigned executed)
2239 {
2240   if (lines)
2241     fnotice (stdout, "Lines executed:%s of %d\n",
2242 	     format_gcov (executed, lines, 2), lines);
2243   else
2244     fnotice (stdout, "No executable lines\n");
2245 }
2246 
2247 /* Output summary info for a function or file.  */
2248 
2249 static void
2250 function_summary (const coverage_info *coverage, const char *title)
2251 {
2252   fnotice (stdout, "%s '%s'\n", title, coverage->name);
2253   executed_summary (coverage->lines, coverage->lines_executed);
2254 
2255   if (flag_branches)
2256     {
2257       if (coverage->branches)
2258 	{
2259 	  fnotice (stdout, "Branches executed:%s of %d\n",
2260 		   format_gcov (coverage->branches_executed,
2261 				coverage->branches, 2),
2262 		   coverage->branches);
2263 	  fnotice (stdout, "Taken at least once:%s of %d\n",
2264 		   format_gcov (coverage->branches_taken,
2265 				coverage->branches, 2),
2266 		   coverage->branches);
2267 	}
2268       else
2269 	fnotice (stdout, "No branches\n");
2270       if (coverage->calls)
2271 	fnotice (stdout, "Calls executed:%s of %d\n",
2272 		 format_gcov (coverage->calls_executed, coverage->calls, 2),
2273 		 coverage->calls);
2274       else
2275 	fnotice (stdout, "No calls\n");
2276     }
2277 }
2278 
2279 /* Canonicalize the filename NAME by canonicalizing directory
2280    separators, eliding . components and resolving .. components
2281    appropriately.  Always returns a unique string.  */
2282 
2283 static char *
2284 canonicalize_name (const char *name)
2285 {
2286   /* The canonical name cannot be longer than the incoming name.  */
2287   char *result = XNEWVEC (char, strlen (name) + 1);
2288   const char *base = name, *probe;
2289   char *ptr = result;
2290   char *dd_base;
2291   int slash = 0;
2292 
2293 #if HAVE_DOS_BASED_FILE_SYSTEM
2294   if (base[0] && base[1] == ':')
2295     {
2296       result[0] = base[0];
2297       result[1] = ':';
2298       base += 2;
2299       ptr += 2;
2300     }
2301 #endif
2302   for (dd_base = ptr; *base; base = probe)
2303     {
2304       size_t len;
2305 
2306       for (probe = base; *probe; probe++)
2307 	if (IS_DIR_SEPARATOR (*probe))
2308 	  break;
2309 
2310       len = probe - base;
2311       if (len == 1 && base[0] == '.')
2312 	/* Elide a '.' directory */
2313 	;
2314       else if (len == 2 && base[0] == '.' && base[1] == '.')
2315 	{
2316 	  /* '..', we can only elide it and the previous directory, if
2317 	     we're not a symlink.  */
2318 	  struct stat ATTRIBUTE_UNUSED buf;
2319 
2320 	  *ptr = 0;
2321 	  if (dd_base == ptr
2322 #if defined (S_ISLNK)
2323 	      /* S_ISLNK is not POSIX.1-1996.  */
2324 	      || stat (result, &buf) || S_ISLNK (buf.st_mode)
2325 #endif
2326 		)
2327 	    {
2328 	      /* Cannot elide, or unreadable or a symlink.  */
2329 	      dd_base = ptr + 2 + slash;
2330 	      goto regular;
2331 	    }
2332 	  while (ptr != dd_base && *ptr != '/')
2333 	    ptr--;
2334 	  slash = ptr != result;
2335 	}
2336       else
2337 	{
2338 	regular:
2339 	  /* Regular pathname component.  */
2340 	  if (slash)
2341 	    *ptr++ = '/';
2342 	  memcpy (ptr, base, len);
2343 	  ptr += len;
2344 	  slash = 1;
2345 	}
2346 
2347       for (; IS_DIR_SEPARATOR (*probe); probe++)
2348 	continue;
2349     }
2350   *ptr = 0;
2351 
2352   return result;
2353 }
2354 
2355 /* Print hex representation of 16 bytes from SUM and write it to BUFFER.  */
2356 
2357 static void
2358 md5sum_to_hex (const char *sum, char *buffer)
2359 {
2360   for (unsigned i = 0; i < 16; i++)
2361     sprintf (buffer + (2 * i), "%02x", (unsigned char)sum[i]);
2362 }
2363 
2364 /* Generate an output file name. INPUT_NAME is the canonicalized main
2365    input file and SRC_NAME is the canonicalized file name.
2366    LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation.  With
2367    long_output_names we prepend the processed name of the input file
2368    to each output name (except when the current source file is the
2369    input file, so you don't get a double concatenation). The two
2370    components are separated by '##'.  With preserve_paths we create a
2371    filename from all path components of the source file, replacing '/'
2372    with '#', and .. with '^', without it we simply take the basename
2373    component.  (Remember, the canonicalized name will already have
2374    elided '.' components and converted \\ separators.)  */
2375 
2376 static char *
2377 make_gcov_file_name (const char *input_name, const char *src_name)
2378 {
2379   char *ptr;
2380   char *result;
2381 
2382   if (flag_long_names && input_name && strcmp (src_name, input_name))
2383     {
2384       /* Generate the input filename part.  */
2385       result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
2386 
2387       ptr = result;
2388       ptr = mangle_name (input_name, ptr);
2389       ptr[0] = ptr[1] = '#';
2390       ptr += 2;
2391     }
2392   else
2393     {
2394       result = XNEWVEC (char, strlen (src_name) + 10);
2395       ptr = result;
2396     }
2397 
2398   ptr = mangle_name (src_name, ptr);
2399   strcpy (ptr, ".gcov");
2400 
2401   /* When hashing filenames, we shorten them by only using the filename
2402      component and appending a hash of the full (mangled) pathname.  */
2403   if (flag_hash_filenames)
2404     {
2405       md5_ctx ctx;
2406       char md5sum[16];
2407       char md5sum_hex[33];
2408 
2409       md5_init_ctx (&ctx);
2410       md5_process_bytes (src_name, strlen (src_name), &ctx);
2411       md5_finish_ctx (&ctx, md5sum);
2412       md5sum_to_hex (md5sum, md5sum_hex);
2413       free (result);
2414 
2415       result = XNEWVEC (char, strlen (src_name) + 50);
2416       ptr = result;
2417       ptr = mangle_name (src_name, ptr);
2418       ptr[0] = ptr[1] = '#';
2419       ptr += 2;
2420       memcpy (ptr, md5sum_hex, 32);
2421       ptr += 32;
2422       strcpy (ptr, ".gcov");
2423     }
2424 
2425   return result;
2426 }
2427 
2428 static char *
2429 mangle_name (char const *base, char *ptr)
2430 {
2431   size_t len;
2432 
2433   /* Generate the source filename part.  */
2434   if (!flag_preserve_paths)
2435     {
2436       base = lbasename (base);
2437       len = strlen (base);
2438       memcpy (ptr, base, len);
2439       ptr += len;
2440     }
2441   else
2442     {
2443       /* Convert '/' to '#', convert '..' to '^',
2444 	 convert ':' to '~' on DOS based file system.  */
2445       const char *probe;
2446 
2447 #if HAVE_DOS_BASED_FILE_SYSTEM
2448       if (base[0] && base[1] == ':')
2449 	{
2450 	  ptr[0] = base[0];
2451 	  ptr[1] = '~';
2452 	  ptr += 2;
2453 	  base += 2;
2454 	}
2455 #endif
2456       for (; *base; base = probe)
2457 	{
2458 	  size_t len;
2459 
2460 	  for (probe = base; *probe; probe++)
2461 	    if (*probe == '/')
2462 	      break;
2463 	  len = probe - base;
2464 	  if (len == 2 && base[0] == '.' && base[1] == '.')
2465 	    *ptr++ = '^';
2466 	  else
2467 	    {
2468 	      memcpy (ptr, base, len);
2469 	      ptr += len;
2470 	    }
2471 	  if (*probe)
2472 	    {
2473 	      *ptr++ = '#';
2474 	      probe++;
2475 	    }
2476 	}
2477     }
2478 
2479   return ptr;
2480 }
2481 
2482 /* Scan through the bb_data for each line in the block, increment
2483    the line number execution count indicated by the execution count of
2484    the appropriate basic block.  */
2485 
2486 static void
2487 add_line_counts (coverage_info *coverage, function_info *fn)
2488 {
2489   bool has_any_line = false;
2490   /* Scan each basic block.  */
2491   for (unsigned ix = 0; ix != fn->blocks.size (); ix++)
2492     {
2493       line_info *line = NULL;
2494       block_info *block = &fn->blocks[ix];
2495       if (block->count && ix && ix + 1 != fn->blocks.size ())
2496 	fn->blocks_executed++;
2497       for (unsigned i = 0; i < block->locations.size (); i++)
2498 	{
2499 	  unsigned src_idx = block->locations[i].source_file_idx;
2500 	  vector<unsigned> &lines = block->locations[i].lines;
2501 
2502 	  block->cycle.arc = NULL;
2503 	  block->cycle.ident = ~0U;
2504 
2505 	  for (unsigned j = 0; j < lines.size (); j++)
2506 	    {
2507 	      unsigned ln = lines[j];
2508 
2509 	      /* Line belongs to a function that is in a group.  */
2510 	      if (fn->group_line_p (ln, src_idx))
2511 		{
2512 		  gcc_assert (lines[j] - fn->start_line < fn->lines.size ());
2513 		  line = &(fn->lines[lines[j] - fn->start_line]);
2514 		  line->exists = 1;
2515 		  if (!block->exceptional)
2516 		    {
2517 		      line->unexceptional = 1;
2518 		      if (block->count == 0)
2519 			line->has_unexecuted_block = 1;
2520 		    }
2521 		  line->count += block->count;
2522 		}
2523 	      else
2524 		{
2525 		  gcc_assert (ln < sources[src_idx].lines.size ());
2526 		  line = &(sources[src_idx].lines[ln]);
2527 		  if (coverage)
2528 		    {
2529 		      if (!line->exists)
2530 			coverage->lines++;
2531 		      if (!line->count && block->count)
2532 			coverage->lines_executed++;
2533 		    }
2534 		  line->exists = 1;
2535 		  if (!block->exceptional)
2536 		    {
2537 		      line->unexceptional = 1;
2538 		      if (block->count == 0)
2539 			line->has_unexecuted_block = 1;
2540 		    }
2541 		  line->count += block->count;
2542 		}
2543 	    }
2544 
2545 	  has_any_line = true;
2546 
2547 	  if (!ix || ix + 1 == fn->blocks.size ())
2548 	    /* Entry or exit block.  */;
2549 	  else if (line != NULL)
2550 	    {
2551 	      line->blocks.push_back (block);
2552 
2553 	      if (flag_branches)
2554 		{
2555 		  arc_info *arc;
2556 
2557 		  for (arc = block->succ; arc; arc = arc->succ_next)
2558 		    line->branches.push_back (arc);
2559 		}
2560 	    }
2561 	}
2562     }
2563 
2564   if (!has_any_line)
2565     fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
2566 }
2567 
2568 /* Accumulate info for LINE that belongs to SRC source file.  If ADD_COVERAGE
2569    is set to true, update source file summary.  */
2570 
2571 static void accumulate_line_info (line_info *line, source_info *src,
2572 				  bool add_coverage)
2573 {
2574   if (add_coverage)
2575     for (vector<arc_info *>::iterator it = line->branches.begin ();
2576 	 it != line->branches.end (); it++)
2577       add_branch_counts (&src->coverage, *it);
2578 
2579   if (!line->blocks.empty ())
2580     {
2581       /* The user expects the line count to be the number of times
2582 	 a line has been executed.  Simply summing the block count
2583 	 will give an artificially high number.  The Right Thing
2584 	 is to sum the entry counts to the graph of blocks on this
2585 	 line, then find the elementary cycles of the local graph
2586 	 and add the transition counts of those cycles.  */
2587       gcov_type count = 0;
2588 
2589       /* Cycle detection.  */
2590       for (vector<block_info *>::iterator it = line->blocks.begin ();
2591 	   it != line->blocks.end (); it++)
2592 	{
2593 	  for (arc_info *arc = (*it)->pred; arc; arc = arc->pred_next)
2594 	    if (!line->has_block (arc->src))
2595 	      count += arc->count;
2596 	  for (arc_info *arc = (*it)->succ; arc; arc = arc->succ_next)
2597 	    arc->cs_count = arc->count;
2598 	}
2599 
2600       /* Now, add the count of loops entirely on this line.  */
2601       count += get_cycles_count (*line);
2602       line->count = count;
2603     }
2604 
2605   if (line->exists && add_coverage)
2606     {
2607       src->coverage.lines++;
2608       if (line->count)
2609 	src->coverage.lines_executed++;
2610     }
2611 }
2612 
2613 /* Accumulate the line counts of a file.  */
2614 
2615 static void
2616 accumulate_line_counts (source_info *src)
2617 {
2618   /* First work on group functions.  */
2619   for (vector<function_info *>::iterator it = src->functions.begin ();
2620        it != src->functions.end (); it++)
2621     {
2622       function_info *fn = *it;
2623 
2624       if (fn->src != src->index || !fn->is_group)
2625 	continue;
2626 
2627       for (vector<line_info>::iterator it2 = fn->lines.begin ();
2628 	   it2 != fn->lines.end (); it2++)
2629 	  {
2630 	    line_info *line = &(*it2);
2631 	    accumulate_line_info (line, src, false);
2632 	  }
2633     }
2634 
2635   /* Work on global lines that line in source file SRC.  */
2636   for (vector<line_info>::iterator it = src->lines.begin ();
2637        it != src->lines.end (); it++)
2638     accumulate_line_info (&(*it), src, true);
2639 
2640   /* If not using intermediate mode, sum lines of group functions and
2641      add them to lines that live in a source file.  */
2642   if (!flag_intermediate_format)
2643     for (vector<function_info *>::iterator it = src->functions.begin ();
2644 	 it != src->functions.end (); it++)
2645       {
2646 	function_info *fn = *it;
2647 
2648 	if (fn->src != src->index || !fn->is_group)
2649 	  continue;
2650 
2651 	for (unsigned i = 0; i < fn->lines.size (); i++)
2652 	  {
2653 	    line_info *fn_line = &fn->lines[i];
2654 	    if (fn_line->exists)
2655 	      {
2656 		unsigned ln = fn->start_line + i;
2657 		line_info *src_line = &src->lines[ln];
2658 
2659 		if (!src_line->exists)
2660 		  src->coverage.lines++;
2661 		if (!src_line->count && fn_line->count)
2662 		  src->coverage.lines_executed++;
2663 
2664 		src_line->count += fn_line->count;
2665 		src_line->exists = 1;
2666 
2667 		if (fn_line->has_unexecuted_block)
2668 		  src_line->has_unexecuted_block = 1;
2669 
2670 		if (fn_line->unexceptional)
2671 		  src_line->unexceptional = 1;
2672 	      }
2673 	  }
2674       }
2675 }
2676 
2677 /* Output information about ARC number IX.  Returns nonzero if
2678    anything is output.  */
2679 
2680 static int
2681 output_branch_count (FILE *gcov_file, int ix, const arc_info *arc)
2682 {
2683   if (arc->is_call_non_return)
2684     {
2685       if (arc->src->count)
2686 	{
2687 	  fnotice (gcov_file, "call   %2d returned %s\n", ix,
2688 		   format_gcov (arc->src->count - arc->count,
2689 				arc->src->count, -flag_counts));
2690 	}
2691       else
2692 	fnotice (gcov_file, "call   %2d never executed\n", ix);
2693     }
2694   else if (!arc->is_unconditional)
2695     {
2696       if (arc->src->count)
2697 	fnotice (gcov_file, "branch %2d taken %s%s", ix,
2698 		 format_gcov (arc->count, arc->src->count, -flag_counts),
2699 		 arc->fall_through ? " (fallthrough)"
2700 		 : arc->is_throw ? " (throw)" : "");
2701       else
2702 	fnotice (gcov_file, "branch %2d never executed", ix);
2703 
2704       if (flag_verbose)
2705 	fnotice (gcov_file, " (BB %d)", arc->dst->id);
2706 
2707       fnotice (gcov_file, "\n");
2708     }
2709   else if (flag_unconditional && !arc->dst->is_call_return)
2710     {
2711       if (arc->src->count)
2712 	fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2713 		 format_gcov (arc->count, arc->src->count, -flag_counts));
2714       else
2715 	fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2716     }
2717   else
2718     return 0;
2719   return 1;
2720 }
2721 
2722 static const char *
2723 read_line (FILE *file)
2724 {
2725   static char *string;
2726   static size_t string_len;
2727   size_t pos = 0;
2728   char *ptr;
2729 
2730   if (!string_len)
2731     {
2732       string_len = 200;
2733       string = XNEWVEC (char, string_len);
2734     }
2735 
2736   while ((ptr = fgets (string + pos, string_len - pos, file)))
2737     {
2738       size_t len = strlen (string + pos);
2739 
2740       if (len && string[pos + len - 1] == '\n')
2741 	{
2742 	  string[pos + len - 1] = 0;
2743 	  return string;
2744 	}
2745       pos += len;
2746       /* If the file contains NUL characters or an incomplete
2747 	 last line, which can happen more than once in one run,
2748 	 we have to avoid doubling the STRING_LEN unnecessarily.  */
2749       if (pos > string_len / 2)
2750 	{
2751 	  string_len *= 2;
2752 	  string = XRESIZEVEC (char, string, string_len);
2753 	}
2754     }
2755 
2756   return pos ? string : NULL;
2757 }
2758 
2759 /* Pad string S with spaces from left to have total width equal to 9.  */
2760 
2761 static void
2762 pad_count_string (string &s)
2763 {
2764   if (s.size () < 9)
2765     s.insert (0, 9 - s.size (), ' ');
2766 }
2767 
2768 /* Print GCOV line beginning to F stream.  If EXISTS is set to true, the
2769    line exists in source file.  UNEXCEPTIONAL indicated that it's not in
2770    an exceptional statement.  The output is printed for LINE_NUM of given
2771    COUNT of executions.  EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are
2772    used to indicate non-executed blocks.  */
2773 
2774 static void
2775 output_line_beginning (FILE *f, bool exists, bool unexceptional,
2776 		       bool has_unexecuted_block,
2777 		       gcov_type count, unsigned line_num,
2778 		       const char *exceptional_string,
2779 		       const char *unexceptional_string)
2780 {
2781   string s;
2782   if (exists)
2783     {
2784       if (count > 0)
2785 	{
2786 	  s = format_gcov (count, 0, -1);
2787 	  if (has_unexecuted_block
2788 	      && bbg_supports_has_unexecuted_blocks)
2789 	    {
2790 	      if (flag_use_colors)
2791 		{
2792 		  pad_count_string (s);
2793 		  s.insert (0, SGR_SEQ (COLOR_BG_MAGENTA
2794 					COLOR_SEPARATOR COLOR_FG_WHITE));
2795 		  s += SGR_RESET;
2796 		}
2797 	      else
2798 		s += "*";
2799 	    }
2800 	  pad_count_string (s);
2801 	}
2802       else
2803 	{
2804 	  if (flag_use_colors)
2805 	    {
2806 	      s = "0";
2807 	      pad_count_string (s);
2808 	      if (unexceptional)
2809 		s.insert (0, SGR_SEQ (COLOR_BG_RED
2810 				      COLOR_SEPARATOR COLOR_FG_WHITE));
2811 	      else
2812 		s.insert (0, SGR_SEQ (COLOR_BG_CYAN
2813 				      COLOR_SEPARATOR COLOR_FG_WHITE));
2814 	      s += SGR_RESET;
2815 	    }
2816 	  else
2817 	    {
2818 	      s = unexceptional ? unexceptional_string : exceptional_string;
2819 	      pad_count_string (s);
2820 	    }
2821 	}
2822     }
2823   else
2824     {
2825       s = "-";
2826       pad_count_string (s);
2827     }
2828 
2829   fprintf (f, "%s:%5u", s.c_str (), line_num);
2830 }
2831 
2832 static void
2833 print_source_line (FILE *f, const vector<const char *> &source_lines,
2834 		   unsigned line)
2835 {
2836   gcc_assert (line >= 1);
2837   gcc_assert (line <= source_lines.size ());
2838 
2839   fprintf (f, ":%s\n", source_lines[line - 1]);
2840 }
2841 
2842 /* Output line details for LINE and print it to F file.  LINE lives on
2843    LINE_NUM.  */
2844 
2845 static void
2846 output_line_details (FILE *f, const line_info *line, unsigned line_num)
2847 {
2848   if (flag_all_blocks)
2849     {
2850       arc_info *arc;
2851       int ix, jx;
2852 
2853       ix = jx = 0;
2854       for (vector<block_info *>::const_iterator it = line->blocks.begin ();
2855 	   it != line->blocks.end (); it++)
2856 	{
2857 	  if (!(*it)->is_call_return)
2858 	    {
2859 	      output_line_beginning (f, line->exists,
2860 				     (*it)->exceptional, false,
2861 				     (*it)->count, line_num,
2862 				     "%%%%%", "$$$$$");
2863 	      fprintf (f, "-block %2d", ix++);
2864 	      if (flag_verbose)
2865 		fprintf (f, " (BB %u)", (*it)->id);
2866 	      fprintf (f, "\n");
2867 	    }
2868 	  if (flag_branches)
2869 	    for (arc = (*it)->succ; arc; arc = arc->succ_next)
2870 	      jx += output_branch_count (f, jx, arc);
2871 	}
2872     }
2873   else if (flag_branches)
2874     {
2875       int ix;
2876 
2877       ix = 0;
2878       for (vector<arc_info *>::const_iterator it = line->branches.begin ();
2879 	   it != line->branches.end (); it++)
2880 	ix += output_branch_count (f, ix, (*it));
2881     }
2882 }
2883 
2884 /* Output detail statistics about function FN to file F.  */
2885 
2886 static void
2887 output_function_details (FILE *f, const function_info *fn)
2888 {
2889   if (!flag_branches)
2890     return;
2891 
2892   arc_info *arc = fn->blocks[EXIT_BLOCK].pred;
2893   gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
2894   gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
2895 
2896   for (; arc; arc = arc->pred_next)
2897     if (arc->fake)
2898       return_count -= arc->count;
2899 
2900   fprintf (f, "function %s",
2901 	   flag_demangled_names ? fn->demangled_name : fn->name);
2902   fprintf (f, " called %s",
2903 	   format_gcov (called_count, 0, -1));
2904   fprintf (f, " returned %s",
2905 	   format_gcov (return_count, called_count, 0));
2906   fprintf (f, " blocks executed %s",
2907 	   format_gcov (fn->blocks_executed, fn->blocks.size () - 2,
2908 			0));
2909   fprintf (f, "\n");
2910 }
2911 
2912 /* Read in the source file one line at a time, and output that line to
2913    the gcov file preceded by its execution count and other
2914    information.  */
2915 
2916 static void
2917 output_lines (FILE *gcov_file, const source_info *src)
2918 {
2919 #define  DEFAULT_LINE_START "        -:    0:"
2920 #define FN_SEPARATOR "------------------\n"
2921 
2922   FILE *source_file;
2923   const char *retval;
2924 
2925   fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name);
2926   if (!multiple_files)
2927     {
2928       fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name);
2929       fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n",
2930 	       no_data_file ? "-" : da_file_name);
2931       fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
2932     }
2933   fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count);
2934 
2935   source_file = fopen (src->name, "r");
2936   if (!source_file)
2937     fnotice (stderr, "Cannot open source file %s\n", src->name);
2938   else if (src->file_time == 0)
2939     fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n");
2940 
2941   vector<const char *> source_lines;
2942   if (source_file)
2943     while ((retval = read_line (source_file)) != NULL)
2944       source_lines.push_back (xstrdup (retval));
2945 
2946   unsigned line_start_group = 0;
2947   vector<function_info *> fns;
2948 
2949   for (unsigned line_num = 1; line_num <= source_lines.size (); line_num++)
2950     {
2951       if (line_num >= src->lines.size ())
2952 	{
2953 	  fprintf (gcov_file, "%9s:%5u", "-", line_num);
2954 	  print_source_line (gcov_file, source_lines, line_num);
2955 	  continue;
2956 	}
2957 
2958       const line_info *line = &src->lines[line_num];
2959 
2960       if (line_start_group == 0)
2961 	{
2962 	  fns = src->get_functions_at_location (line_num);
2963 	  if (fns.size () > 1)
2964 	    {
2965 	      /* It's possible to have functions that partially overlap,
2966 		 thus take the maximum end_line of functions starting
2967 		 at LINE_NUM.  */
2968 	      for (unsigned i = 0; i < fns.size (); i++)
2969 		if (fns[i]->end_line > line_start_group)
2970 		  line_start_group = fns[i]->end_line;
2971 	    }
2972 	  else if (fns.size () == 1)
2973 	    {
2974 	      function_info *fn = fns[0];
2975 	      output_function_details (gcov_file, fn);
2976 	    }
2977 	}
2978 
2979       /* For lines which don't exist in the .bb file, print '-' before
2980 	 the source line.  For lines which exist but were never
2981 	 executed, print '#####' or '=====' before the source line.
2982 	 Otherwise, print the execution count before the source line.
2983 	 There are 16 spaces of indentation added before the source
2984 	 line so that tabs won't be messed up.  */
2985       output_line_beginning (gcov_file, line->exists, line->unexceptional,
2986 			     line->has_unexecuted_block, line->count,
2987 			     line_num, "=====", "#####");
2988 
2989       print_source_line (gcov_file, source_lines, line_num);
2990       output_line_details (gcov_file, line, line_num);
2991 
2992       if (line_start_group == line_num)
2993 	{
2994 	  for (vector<function_info *>::iterator it = fns.begin ();
2995 	       it != fns.end (); it++)
2996 	    {
2997 	      function_info *fn = *it;
2998 	      vector<line_info> &lines = fn->lines;
2999 
3000 	      fprintf (gcov_file, FN_SEPARATOR);
3001 
3002 	      string fn_name
3003 		= flag_demangled_names ? fn->demangled_name : fn->name;
3004 
3005 	      if (flag_use_colors)
3006 		{
3007 		  fn_name.insert (0, SGR_SEQ (COLOR_FG_CYAN));
3008 		  fn_name += SGR_RESET;
3009 		}
3010 
3011 	      fprintf (gcov_file, "%s:\n", fn_name.c_str ());
3012 
3013 	      output_function_details (gcov_file, fn);
3014 
3015 	      /* Print all lines covered by the function.  */
3016 	      for (unsigned i = 0; i < lines.size (); i++)
3017 		{
3018 		  line_info *line = &lines[i];
3019 		  unsigned l = fn->start_line + i;
3020 
3021 		  /* For lines which don't exist in the .bb file, print '-'
3022 		     before the source line.  For lines which exist but
3023 		     were never executed, print '#####' or '=====' before
3024 		     the source line.  Otherwise, print the execution count
3025 		     before the source line.
3026 		     There are 16 spaces of indentation added before the source
3027 		     line so that tabs won't be messed up.  */
3028 		  output_line_beginning (gcov_file, line->exists,
3029 					 line->unexceptional,
3030 					 line->has_unexecuted_block,
3031 					 line->count,
3032 					 l, "=====", "#####");
3033 
3034 		  print_source_line (gcov_file, source_lines, l);
3035 		  output_line_details (gcov_file, line, l);
3036 		}
3037 	    }
3038 
3039 	  fprintf (gcov_file, FN_SEPARATOR);
3040 	  line_start_group = 0;
3041 	}
3042     }
3043 
3044   if (source_file)
3045     fclose (source_file);
3046 }
3047