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