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