OSDN Git Service

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