OSDN Git Service

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