commit two parts of my last patch that escaped, somehow
[official-gcc.git] / gcc / gcov.c
blob8a413677993c7986fd808dbf1a2605429d79d016
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>
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.
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.
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. */
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. */
29 /* ??? Should have an option to print the number of basic blocks, and the
30 percent of them that are covered. */
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. */
41 /* Need an option to show individual block counts, and show
42 probabilities of fall through arcs. */
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
52 #include <getopt.h>
54 #define IN_GCOV 1
55 #include "gcov-io.h"
56 #include "gcov-io.c"
58 /* The bbg file is generated by -ftest-coverage option. The da file is
59 generated by a program compiled with -fprofile-arcs. Their formats
60 are documented in gcov-io.h. */
62 /* The functions in this file for creating and solution program flow graphs
63 are very similar to functions in the gcc source file profile.c. In
64 some places we make use of the knowledge of how profile.c works to
65 select particular algorithms here. */
67 /* This is the size of the buffer used to read in source file lines. */
69 #define STRING_SIZE 200
71 struct function_info;
72 struct block_info;
73 struct source_info;
75 /* Describes an arc between two basic blocks. */
77 typedef struct arc_info
79 /* source and destination blocks. */
80 struct block_info *src;
81 struct block_info *dst;
83 /* transition counts. */
84 gcov_type count;
86 unsigned int count_valid : 1;
87 unsigned int on_tree : 1;
88 unsigned int fake : 1;
89 unsigned int fall_through : 1;
91 /* Arc is for a function that abnormally returns. */
92 unsigned int is_call_non_return : 1;
94 /* Arc is for catch/setjump. */
95 unsigned int is_nonlocal_return : 1;
97 /* Is an unconditional branch. */
98 unsigned int is_unconditional : 1;
100 /* Loop making arc. */
101 unsigned int cycle : 1;
103 /* Next branch on line. */
104 struct arc_info *line_next;
106 /* Links to next arc on src and dst lists. */
107 struct arc_info *succ_next;
108 struct arc_info *pred_next;
109 } arc_t;
111 /* Describes a basic block. Contains lists of arcs to successor and
112 predecessor blocks. */
114 typedef struct block_info
116 /* Chain of exit and entry arcs. */
117 arc_t *succ;
118 arc_t *pred;
120 /* Number of unprocessed exit and entry arcs. */
121 gcov_type num_succ;
122 gcov_type num_pred;
124 /* Block execution count. */
125 gcov_type count;
126 unsigned flags : 13;
127 unsigned count_valid : 1;
128 unsigned valid_chain : 1;
129 unsigned invalid_chain : 1;
131 /* Block is a call instrumenting site. */
132 unsigned is_call_site : 1; /* Does the call. */
133 unsigned is_call_return : 1; /* Is the return. */
135 /* Block is a landing pad for longjmp or throw. */
136 unsigned is_nonlocal_return : 1;
138 union
140 struct
142 /* Array of line numbers and source files. source files are
143 introduced by a linenumber of zero, the next 'line number' is
144 the number of the source file. Always starts with a source
145 file. */
146 unsigned *encoding;
147 unsigned num;
148 } line; /* Valid until blocks are linked onto lines */
149 struct
151 /* Single line graph cycle workspace. Used for all-blocks
152 mode. */
153 arc_t *arc;
154 unsigned ident;
155 } cycle; /* Used in all-blocks mode, after blocks are linked onto
156 lines. */
157 } u;
159 /* Temporary chain for solving graph, and for chaining blocks on one
160 line. */
161 struct block_info *chain;
163 } block_t;
165 /* Describes a single function. Contains an array of basic blocks. */
167 typedef struct function_info
169 /* Name of function. */
170 char *name;
171 unsigned checksum;
173 /* Array of basic blocks. */
174 block_t *blocks;
175 unsigned num_blocks;
176 unsigned blocks_executed;
178 /* Raw arc coverage counts. */
179 gcov_type *counts;
180 unsigned num_counts;
182 /* First line number. */
183 unsigned line;
184 struct source_info *src;
186 /* Next function in same source file. */
187 struct function_info *line_next;
189 /* Next function. */
190 struct function_info *next;
191 } function_t;
193 /* Describes coverage of a file or function. */
195 typedef struct coverage_info
197 int lines;
198 int lines_executed;
200 int branches;
201 int branches_executed;
202 int branches_taken;
204 int calls;
205 int calls_executed;
207 char *name;
208 } coverage_t;
210 /* Describes a single line of source. Contains a chain of basic blocks
211 with code on it. */
213 typedef struct line_info
215 gcov_type count; /* execution count */
216 union
218 arc_t *branches; /* branches from blocks that end on this
219 line. Used for branch-counts when not
220 all-blocks mode. */
221 block_t *blocks; /* blocks which start on this line. Used
222 in all-blocks mode. */
223 } u;
224 unsigned exists : 1;
225 } line_t;
227 /* Describes a file mentioned in the block graph. Contains an array
228 of line info. */
230 typedef struct source_info
232 /* Name of source file. */
233 char *name;
234 unsigned index;
236 /* Array of line information. */
237 line_t *lines;
238 unsigned num_lines;
240 coverage_t coverage;
242 /* Functions in this source file. These are in ascending line
243 number order. */
244 function_t *functions;
246 /* Next source file. */
247 struct source_info *next;
248 } source_t;
250 /* Holds a list of function basic block graphs. */
252 static function_t *functions;
254 /* This points to the head of the sourcefile structure list. */
256 static source_t *sources;
258 /* This holds data summary information. */
260 static struct gcov_summary object_summary;
261 static unsigned program_count;
263 /* Modification time of graph file. */
265 static time_t bbg_file_time;
267 /* Name and file pointer of the input file for the basic block graph. */
269 static char *bbg_file_name;
271 /* Name and file pointer of the input file for the arc count data. */
273 static char *da_file_name;
275 /* Output branch probabilities. */
277 static int flag_branches = 0;
279 /* Show unconditional branches too. */
280 static int flag_unconditional = 0;
282 /* Output a gcov file if this is true. This is on by default, and can
283 be turned off by the -n option. */
285 static int flag_gcov_file = 1;
287 /* For included files, make the gcov output file name include the name
288 of the input source file. For example, if x.h is included in a.c,
289 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
291 static int flag_long_names = 0;
293 /* Output count information for every basic block, not merely those
294 that contain line number information. */
296 static int flag_all_blocks = 0;
298 /* Output summary info for each function. */
300 static int flag_function_summary = 0;
302 /* Object directory file prefix. This is the directory/file where the
303 graph and data files are looked for, if nonzero. */
305 static char *object_directory = 0;
307 /* Preserve all pathname components. Needed when object files and
308 source files are in subdirectories. '/' is mangled as '#', '.' is
309 elided and '..' mangled to '^'. */
311 static int flag_preserve_paths = 0;
313 /* Output the number of times a branch was taken as opposed to the percentage
314 of times it was taken. */
316 static int flag_counts = 0;
318 /* Forward declarations. */
319 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
320 static int process_args PARAMS ((int, char **));
321 static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
322 static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
323 static void process_file PARAMS ((const char *));
324 static void create_file_names PARAMS ((const char *));
325 static source_t *find_source PARAMS ((const char *));
326 static int read_graph_file PARAMS ((void));
327 static int read_count_file PARAMS ((void));
328 static void solve_flow_graph PARAMS ((function_t *));
329 static void add_branch_counts PARAMS ((coverage_t *, const arc_t *));
330 static void add_line_counts PARAMS ((coverage_t *, function_t *));
331 static void function_summary PARAMS ((const coverage_t *, const char *));
332 static const char *format_gcov PARAMS ((gcov_type, gcov_type, int));
333 static void accumulate_line_counts PARAMS ((source_t *));
334 static int output_branch_count PARAMS ((FILE *, int, const arc_t *));
335 static void output_lines PARAMS ((FILE *, const source_t *));
336 static char *make_gcov_file_name PARAMS ((const char *, const char *));
337 static void release_structures PARAMS ((void));
338 extern int main PARAMS ((int, char **));
341 main (argc, argv)
342 int argc;
343 char **argv;
345 int argno;
347 gcc_init_libintl ();
349 argno = process_args (argc, argv);
350 if (optind == argc)
351 print_usage (true);
353 for (; argno != argc; argno++)
355 release_structures ();
357 process_file (argv[argno]);
360 return 0;
363 static void
364 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
366 VA_OPEN (ap, msgid);
367 VA_FIXEDARG (ap, FILE *, file);
368 VA_FIXEDARG (ap, const char *, msgid);
370 vfprintf (file, _(msgid), ap);
371 VA_CLOSE (ap);
374 /* More 'friendly' abort that prints the line and file.
375 config.h can #define abort fancy_abort if you like that sort of thing. */
376 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
378 void
379 fancy_abort ()
381 fnotice (stderr, "Internal gcov abort.\n");
382 exit (FATAL_EXIT_CODE);
385 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
386 otherwise the output of --help. */
388 static void
389 print_usage (error_p)
390 int error_p;
392 FILE *file = error_p ? stderr : stdout;
393 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
395 fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
396 fnotice (file, "Print code coverage information.\n\n");
397 fnotice (file, " -h, --help Print this help, then exit\n");
398 fnotice (file, " -v, --version Print version number, then exit\n");
399 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
400 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
401 fnotice (file, " -c, --branch-counts Given counts of branches taken\n\
402 rather than percentages\n");
403 fnotice (file, " -n, --no-output Do not create an output file\n");
404 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
405 source files\n");
406 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
407 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
408 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
409 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
410 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
411 bug_report_url);
412 exit (status);
415 /* Print version information and exit. */
417 static void
418 print_version ()
420 char v[4];
421 unsigned version = GCOV_VERSION;
422 unsigned ix;
424 for (ix = 4; ix--; version >>= 8)
425 v[ix] = version;
426 fnotice (stdout, "gcov %.4s (GCC %s)\n", v, version_string);
427 fnotice (stdout, "Copyright (C) 2002 Free Software Foundation, Inc.\n");
428 fnotice (stdout,
429 "This is free software; see the source for copying conditions. There is NO\n\
430 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
431 exit (SUCCESS_EXIT_CODE);
434 static const struct option options[] =
436 { "help", no_argument, NULL, 'h' },
437 { "version", no_argument, NULL, 'v' },
438 { "all-blocks", no_argument, NULL, 'a' },
439 { "branch-probabilities", no_argument, NULL, 'b' },
440 { "branch-counts", no_argument, NULL, 'c' },
441 { "no-output", no_argument, NULL, 'n' },
442 { "long-file-names", no_argument, NULL, 'l' },
443 { "function-summaries", no_argument, NULL, 'f' },
444 { "preserve-paths", no_argument, NULL, 'p' },
445 { "object-directory", required_argument, NULL, 'o' },
446 { "object-file", required_argument, NULL, 'o' },
447 { "unconditional-branches", no_argument, NULL, 'u' },
450 /* Process args, return index to first non-arg. */
452 static int
453 process_args (argc, argv)
454 int argc;
455 char **argv;
457 int opt;
459 while ((opt = getopt_long (argc, argv, "abcfhlno:puv", options, NULL)) != -1)
461 switch (opt)
463 case 'a':
464 flag_all_blocks = 1;
465 break;
466 case 'b':
467 flag_branches = 1;
468 break;
469 case 'c':
470 flag_counts = 1;
471 break;
472 case 'f':
473 flag_function_summary = 1;
474 break;
475 case 'h':
476 print_usage (false);
477 /* print_usage will exit. */
478 case 'l':
479 flag_long_names = 1;
480 break;
481 case 'n':
482 flag_gcov_file = 0;
483 break;
484 case 'o':
485 object_directory = optarg;
486 break;
487 case 'p':
488 flag_preserve_paths = 1;
489 break;
490 case 'u':
491 flag_unconditional = 1;
492 break;
493 case 'v':
494 print_version ();
495 /* print_version will exit. */
496 default:
497 print_usage (true);
498 /* print_usage will exit. */
502 return optind;
505 /* Process a single source file. */
507 static void
508 process_file (file_name)
509 const char *file_name;
511 source_t *src;
512 function_t *fn;
514 create_file_names (file_name);
515 if (read_graph_file ())
516 return;
518 if (!functions)
520 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
521 return;
524 if (read_count_file ())
525 return;
527 for (fn = functions; fn; fn = fn->next)
528 solve_flow_graph (fn);
529 for (src = sources; src; src = src->next)
530 src->lines = (line_t *) xcalloc (src->num_lines, sizeof (line_t));
531 for (fn = functions; fn; fn = fn->next)
533 coverage_t coverage;
535 memset (&coverage, 0, sizeof (coverage));
536 coverage.name = fn->name;
537 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
538 if (flag_function_summary)
540 function_summary (&coverage, "Function");
541 fnotice (stdout, "\n");
545 for (src = sources; src; src = src->next)
547 accumulate_line_counts (src);
548 function_summary (&src->coverage, "File");
549 if (flag_gcov_file)
551 char *gcov_file_name = make_gcov_file_name (file_name, src->name);
552 FILE *gcov_file = fopen (gcov_file_name, "w");
554 if (gcov_file)
556 fnotice (stdout, "%s:creating `%s'\n",
557 src->name, gcov_file_name);
558 output_lines (gcov_file, src);
559 if (ferror (gcov_file))
560 fnotice (stderr, "%s:error writing output file `%s'\n",
561 src->name, gcov_file_name);
562 fclose (gcov_file);
564 else
565 fnotice (stderr, "%s:could not open output file `%s'\n",
566 src->name, gcov_file_name);
567 free (gcov_file_name);
569 fnotice (stdout, "\n");
573 /* Release all memory used. */
575 static void
576 release_structures ()
578 function_t *fn;
579 source_t *src;
581 free (bbg_file_name);
582 free (da_file_name);
583 da_file_name = bbg_file_name = NULL;
584 bbg_file_time = 0;
586 while ((src = sources))
588 sources = src->next;
590 free (src->name);
591 free (src->lines);
594 while ((fn = functions))
596 unsigned ix;
597 block_t *block;
599 functions = fn->next;
600 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
602 arc_t *arc, *arc_n;
604 for (arc = block->succ; arc; arc = arc_n)
606 arc_n = arc->succ_next;
607 free (arc);
610 free (fn->blocks);
611 free (fn->counts);
615 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
616 is not specified, these are looked for in the current directory,
617 and named from the basename of the FILE_NAME sans extension. If
618 OBJECT_DIRECTORY is specified and is a directory, the files are in
619 that directory, but named from the basename of the FILE_NAME, sans
620 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
621 the object *file*, and the data files are named from that. */
623 static void
624 create_file_names (file_name)
625 const char *file_name;
627 char *cptr;
628 char *name;
629 int length = strlen (file_name);
630 int base;
632 if (object_directory && object_directory[0])
634 struct stat status;
636 length += strlen (object_directory) + 2;
637 name = xmalloc (length);
638 name[0] = 0;
640 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
641 strcat (name, object_directory);
642 if (base && name[strlen (name) - 1] != '/')
643 strcat (name, "/");
645 else
647 name = xmalloc (length + 1);
648 name[0] = 0;
649 base = 1;
652 if (base)
654 /* Append source file name */
655 cptr = strrchr (file_name, '/');
656 strcat (name, cptr ? cptr + 1 : file_name);
659 /* Remove the extension. */
660 cptr = strrchr (name, '.');
661 if (cptr)
662 *cptr = 0;
664 length = strlen (name);
666 bbg_file_name = xmalloc (length + strlen (GCOV_GRAPH_SUFFIX) + 1);
667 strcpy (bbg_file_name, name);
668 strcpy (bbg_file_name + length, GCOV_GRAPH_SUFFIX);
670 da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
671 strcpy (da_file_name, name);
672 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
674 return;
677 /* Find or create a source file structure for FILE_NAME. Copies
678 FILE_NAME on creation */
680 static source_t *
681 find_source (file_name)
682 const char *file_name;
684 source_t *src;
686 if (!file_name)
687 file_name = "<unknown>";
689 for (src = sources; src; src = src->next)
690 if (!strcmp (file_name, src->name))
691 return src;
693 src = (source_t *)xcalloc (1, sizeof (source_t));
694 src->name = xstrdup (file_name);
695 src->coverage.name = src->name;
696 src->index = sources ? sources->index + 1 : 1;
697 src->next = sources;
698 sources = src;
700 return src;
703 /* Read the graph file. Return nonzero on fatal error. */
705 static int
706 read_graph_file ()
708 unsigned version;
709 unsigned current_tag = 0;
710 struct function_info *fn = NULL;
711 source_t *src = NULL;
712 unsigned ix;
714 if (!gcov_open (bbg_file_name, 1))
716 fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
717 return 1;
719 bbg_file_time = gcov_time ();
720 if (gcov_read_unsigned () != GCOV_GRAPH_MAGIC)
722 fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
723 gcov_close ();
724 return 1;
727 version = gcov_read_unsigned ();
728 if (version != GCOV_VERSION)
730 char v[4], e[4];
731 unsigned required = GCOV_VERSION;
733 for (ix = 4; ix--; required >>= 8, version >>= 8)
735 v[ix] = version;
736 e[ix] = required;
738 fnotice (stderr, "%s:version `%.4s', prefer `%.4s'\n",
739 bbg_file_name, v, e);
742 while (!gcov_is_eof ())
744 unsigned tag = gcov_read_unsigned ();
745 unsigned length = gcov_read_unsigned ();
746 unsigned long base = gcov_position ();
748 if (tag == GCOV_TAG_FUNCTION)
750 char *function_name;
751 unsigned checksum, lineno;
752 source_t *src;
753 function_t *probe, *prev;
755 function_name = xstrdup (gcov_read_string ());
756 checksum = gcov_read_unsigned ();
757 src = find_source (gcov_read_string ());
758 lineno = gcov_read_unsigned ();
760 fn = (function_t *)xcalloc (1, sizeof (function_t));
761 fn->name = function_name;
762 fn->checksum = checksum;
763 fn->src = src;
764 fn->line = lineno;
766 fn->next = functions;
767 functions = fn;
768 current_tag = tag;
770 if (lineno >= src->num_lines)
771 src->num_lines = lineno + 1;
772 /* Now insert it into the source file's list of
773 functions. Normally functions will be encountered in
774 ascending order, so a simple scan is quick. */
775 for (probe = src->functions, prev = NULL;
776 probe && probe->line > lineno;
777 prev = probe, probe = probe->line_next)
778 continue;
779 fn->line_next = probe;
780 if (prev)
781 prev->line_next = fn;
782 else
783 src->functions = fn;
785 else if (fn && tag == GCOV_TAG_BLOCKS)
787 if (fn->blocks)
788 fnotice (stderr, "%s:already seen blocks for `%s'\n",
789 bbg_file_name, fn->name);
790 else
792 unsigned ix, num_blocks = length / 4;
793 fn->num_blocks = num_blocks;
795 fn->blocks
796 = (block_t *)xcalloc (fn->num_blocks, sizeof (block_t));
797 for (ix = 0; ix != num_blocks; ix++)
798 fn->blocks[ix].flags = gcov_read_unsigned ();
801 else if (fn && tag == GCOV_TAG_ARCS)
803 unsigned src = gcov_read_unsigned ();
804 unsigned num_dests = (length - 4) / 8;
806 if (src >= fn->num_blocks || fn->blocks[src].succ)
807 goto corrupt;
809 while (num_dests--)
811 struct arc_info *arc;
812 unsigned dest = gcov_read_unsigned ();
813 unsigned flags = gcov_read_unsigned ();
815 if (dest >= fn->num_blocks)
816 goto corrupt;
817 arc = (arc_t *) xcalloc (1, sizeof (arc_t));
819 arc->dst = &fn->blocks[dest];
820 arc->src = &fn->blocks[src];
822 arc->count = 0;
823 arc->count_valid = 0;
824 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
825 arc->fake = !!(flags & GCOV_ARC_FAKE);
826 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
828 arc->succ_next = fn->blocks[src].succ;
829 fn->blocks[src].succ = arc;
830 fn->blocks[src].num_succ++;
832 arc->pred_next = fn->blocks[dest].pred;
833 fn->blocks[dest].pred = arc;
834 fn->blocks[dest].num_pred++;
836 if (arc->fake)
838 if (src)
840 /* Exceptional exit from this function, the
841 source block must be a call. */
842 fn->blocks[src].is_call_site = 1;
843 arc->is_call_non_return = 1;
845 else
847 /* Non-local return from a callee of this
848 function. The destination block is a catch or
849 setjmp. */
850 arc->is_nonlocal_return = 1;
851 fn->blocks[dest].is_nonlocal_return = 1;
855 if (!arc->on_tree)
856 fn->num_counts++;
859 else if (fn && tag == GCOV_TAG_LINES)
861 unsigned blockno = gcov_read_unsigned ();
862 unsigned *line_nos
863 = (unsigned *)xcalloc ((length - 4) / 4, sizeof (unsigned));
865 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
866 goto corrupt;
868 for (ix = 0; ; )
870 unsigned lineno = gcov_read_unsigned ();
872 if (lineno)
874 if (!ix)
876 line_nos[ix++] = 0;
877 line_nos[ix++] = src->index;
879 line_nos[ix++] = lineno;
880 if (lineno >= src->num_lines)
881 src->num_lines = lineno + 1;
883 else
885 const char *file_name = gcov_read_string ();
887 if (!file_name)
888 break;
889 src = find_source (file_name);
891 line_nos[ix++] = 0;
892 line_nos[ix++] = src->index;
896 fn->blocks[blockno].u.line.encoding = line_nos;
897 fn->blocks[blockno].u.line.num = ix;
899 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
901 fn = NULL;
902 current_tag = 0;
904 gcov_seek (base, length);
905 if (gcov_is_error ())
907 corrupt:;
908 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
909 gcov_close ();
910 return 1;
913 gcov_close ();
915 /* We built everything backwards, so nreverse them all */
917 /* Reverse sources. Not strictly necessary, but we'll then process
918 them in the 'expected' order. */
920 source_t *src, *src_p, *src_n;
922 for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
924 src_n = src->next;
925 src->next = src_p;
927 sources = src_p;
930 /* Reverse functions. */
932 function_t *fn, *fn_p, *fn_n;
934 for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
936 unsigned ix;
938 fn_n = fn->next;
939 fn->next = fn_p;
941 /* Reverse the arcs */
942 for (ix = fn->num_blocks; ix--;)
944 arc_t *arc, *arc_p, *arc_n;
946 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
947 arc_p = arc, arc = arc_n)
949 arc_n = arc->succ_next;
950 arc->succ_next = arc_p;
952 fn->blocks[ix].succ = arc_p;
954 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
955 arc_p = arc, arc = arc_n)
957 arc_n = arc->pred_next;
958 arc->pred_next = arc_p;
960 fn->blocks[ix].pred = arc_p;
963 functions = fn_p;
965 return 0;
968 /* Reads profiles from the count file and attach to each
969 function. Return nonzero if fatal error. */
971 static int
972 read_count_file ()
974 unsigned ix;
975 unsigned version;
976 function_t *fn = NULL;
978 if (!gcov_open (da_file_name, 1))
980 fnotice (stderr, "%s:cannot open data file\n", da_file_name);
981 return 1;
983 if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
985 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
986 cleanup:;
987 gcov_close ();
988 return 1;
990 version = gcov_read_unsigned ();
991 if (version != GCOV_VERSION)
993 char v[4], e[4];
994 unsigned desired = GCOV_VERSION;
996 for (ix = 4; ix--; desired >>= 8, version >>= 8)
998 v[ix] = version;
999 e[ix] = desired;
1001 fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
1002 da_file_name, v, e);
1005 while (!gcov_is_eof ())
1007 unsigned tag = gcov_read_unsigned ();
1008 unsigned length = gcov_read_unsigned ();
1009 unsigned long base = gcov_position ();
1010 int error;
1012 if (tag == GCOV_TAG_OBJECT_SUMMARY)
1013 gcov_read_summary (&object_summary);
1014 else if (tag == GCOV_TAG_PROGRAM_SUMMARY
1015 || tag == GCOV_TAG_INCORRECT_SUMMARY)
1016 program_count++;
1017 else if (tag == GCOV_TAG_FUNCTION)
1019 const char *function_name = gcov_read_string ();
1020 struct function_info *fn_n = functions;
1022 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1024 if (fn)
1026 else if ((fn = fn_n))
1027 fn_n = NULL;
1028 else
1030 fnotice (stderr, "%s:unknown function `%s'\n",
1031 da_file_name, function_name);
1032 break;
1034 if (!strcmp (fn->name, function_name))
1035 break;
1038 if (!fn)
1040 else if (gcov_read_unsigned () != fn->checksum)
1042 mismatch:;
1043 fnotice (stderr, "%s:profile mismatch for `%s'\n",
1044 da_file_name, fn->name);
1045 goto cleanup;
1048 else if (tag == GCOV_TAG_ARC_COUNTS && fn)
1050 if (length != 8 * fn->num_counts)
1051 goto mismatch;
1053 if (!fn->counts)
1054 fn->counts
1055 = (gcov_type *)xcalloc (fn->num_counts, sizeof (gcov_type));
1057 for (ix = 0; ix != fn->num_counts; ix++)
1058 fn->counts[ix] += gcov_read_counter ();
1060 gcov_seek (base, length);
1061 if ((error = gcov_is_error ()))
1063 fnotice (stderr, error < 0
1064 ? "%s:overflowed\n" : "%s:corrupted\n", da_file_name);
1065 goto cleanup;
1069 gcov_close ();
1070 return 0;
1073 /* Solve the flow graph. Propagate counts from the instrumented arcs
1074 to the blocks and the uninstrumented arcs. */
1076 static void
1077 solve_flow_graph (fn)
1078 function_t *fn;
1080 unsigned ix;
1081 arc_t *arc;
1082 gcov_type *count_ptr = fn->counts;
1083 block_t *blk;
1084 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1085 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
1087 if (fn->num_blocks < 2)
1088 fnotice (stderr, "%s:`%s' lacks entry and/or exit blocks\n",
1089 bbg_file_name, fn->name);
1090 else
1092 if (fn->blocks[0].num_pred)
1093 fnotice (stderr, "%s:`%s' has arcs to entry block\n",
1094 bbg_file_name, fn->name);
1095 else
1096 /* We can't deduce the entry block counts from the lack of
1097 predecessors. */
1098 fn->blocks[0].num_pred = ~(unsigned)0;
1100 if (fn->blocks[fn->num_blocks - 1].num_succ)
1101 fnotice (stderr, "%s:`%s' has arcs from exit block\n",
1102 bbg_file_name, fn->name);
1103 else
1104 /* Likewise, we can't deduce exit block counts from the lack
1105 of its successors. */
1106 fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1109 /* Propagate the measured counts, this must be done in the same
1110 order as the code in profile.c */
1111 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
1113 block_t const *prev_dst = NULL;
1114 int out_of_order = 0;
1115 int non_fake_succ = 0;
1117 for (arc = blk->succ; arc; arc = arc->succ_next)
1119 if (!arc->fake)
1120 non_fake_succ++;
1122 if (!arc->on_tree)
1124 if (count_ptr)
1125 arc->count = *count_ptr++;
1126 arc->count_valid = 1;
1127 blk->num_succ--;
1128 arc->dst->num_pred--;
1130 if (prev_dst && prev_dst > arc->dst)
1131 out_of_order = 1;
1132 prev_dst = arc->dst;
1134 if (non_fake_succ == 1)
1136 /* If there is only one non-fake exit, it is an
1137 unconditional branch. */
1138 for (arc = blk->succ; arc; arc = arc->succ_next)
1139 if (!arc->fake)
1141 arc->is_unconditional = 1;
1142 /* If this block is instrumenting a call, it might be
1143 an artifical block. It is not artificial if it has
1144 a non-fallthrough exit, or the destination of this
1145 arc has more than one entry. Mark the destination
1146 block as a return site, if none of those conditions
1147 hold. */
1148 if (blk->is_call_site && arc->fall_through
1149 && arc->dst->pred == arc && !arc->pred_next)
1150 arc->dst->is_call_return = 1;
1154 /* Sort the successor arcs into ascending dst order. profile.c
1155 normally produces arcs in the right order, but sometimes with
1156 one or two out of order. We're not using a particularly
1157 smart sort. */
1158 if (out_of_order)
1160 arc_t *start = blk->succ;
1161 unsigned changes = 1;
1163 while (changes)
1165 arc_t *arc, *arc_p, *arc_n;
1167 changes = 0;
1168 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1170 if (arc->dst > arc_n->dst)
1172 changes = 1;
1173 if (arc_p)
1174 arc_p->succ_next = arc_n;
1175 else
1176 start = arc_n;
1177 arc->succ_next = arc_n->succ_next;
1178 arc_n->succ_next = arc;
1179 arc_p = arc_n;
1181 else
1183 arc_p = arc;
1184 arc = arc_n;
1188 blk->succ = start;
1191 /* Place it on the invalid chain, it will be ignored if that's
1192 wrong. */
1193 blk->invalid_chain = 1;
1194 blk->chain = invalid_blocks;
1195 invalid_blocks = blk;
1198 while (invalid_blocks || valid_blocks)
1200 while ((blk = invalid_blocks))
1202 gcov_type total = 0;
1203 const arc_t *arc;
1205 invalid_blocks = blk->chain;
1206 blk->invalid_chain = 0;
1207 if (!blk->num_succ)
1208 for (arc = blk->succ; arc; arc = arc->succ_next)
1209 total += arc->count;
1210 else if (!blk->num_pred)
1211 for (arc = blk->pred; arc; arc = arc->pred_next)
1212 total += arc->count;
1213 else
1214 continue;
1216 blk->count = total;
1217 blk->count_valid = 1;
1218 blk->chain = valid_blocks;
1219 blk->valid_chain = 1;
1220 valid_blocks = blk;
1222 while ((blk = valid_blocks))
1224 gcov_type total;
1225 arc_t *arc, *inv_arc;
1227 valid_blocks = blk->chain;
1228 blk->valid_chain = 0;
1229 if (blk->num_succ == 1)
1231 block_t *dst;
1233 total = blk->count;
1234 inv_arc = NULL;
1235 for (arc = blk->succ; arc; arc = arc->succ_next)
1237 total -= arc->count;
1238 if (!arc->count_valid)
1239 inv_arc = arc;
1241 dst = inv_arc->dst;
1242 inv_arc->count_valid = 1;
1243 inv_arc->count = total;
1244 blk->num_succ--;
1245 dst->num_pred--;
1246 if (dst->count_valid)
1248 if (dst->num_pred == 1 && !dst->valid_chain)
1250 dst->chain = valid_blocks;
1251 dst->valid_chain = 1;
1252 valid_blocks = dst;
1255 else
1257 if (!dst->num_pred && !dst->invalid_chain)
1259 dst->chain = invalid_blocks;
1260 dst->invalid_chain = 1;
1261 invalid_blocks = dst;
1265 if (blk->num_pred == 1)
1267 block_t *src;
1269 total = blk->count;
1270 inv_arc = NULL;
1271 for (arc = blk->pred; arc; arc = arc->pred_next)
1273 total -= arc->count;
1274 if (!arc->count_valid)
1275 inv_arc = arc;
1277 src = inv_arc->src;
1278 inv_arc->count_valid = 1;
1279 inv_arc->count = total;
1280 blk->num_pred--;
1281 src->num_succ--;
1282 if (src->count_valid)
1284 if (src->num_succ == 1 && !src->valid_chain)
1286 src->chain = valid_blocks;
1287 src->valid_chain = 1;
1288 valid_blocks = src;
1291 else
1293 if (!src->num_succ && !src->invalid_chain)
1295 src->chain = invalid_blocks;
1296 src->invalid_chain = 1;
1297 invalid_blocks = src;
1304 /* If the graph has been correctly solved, every block will have a
1305 valid count. */
1306 for (ix = 0; ix < fn->num_blocks; ix++)
1307 if (!fn->blocks[ix].count_valid)
1309 fnotice (stderr, "%s:graph is unsolvable for `%s'\n",
1310 bbg_file_name, fn->name);
1311 break;
1317 /* Increment totals in COVERAGE according to arc ARC. */
1319 static void
1320 add_branch_counts (coverage, arc)
1321 coverage_t *coverage;
1322 const arc_t *arc;
1324 if (arc->is_call_non_return)
1326 coverage->calls++;
1327 if (arc->src->count)
1328 coverage->calls_executed++;
1330 else if (!arc->is_unconditional)
1332 coverage->branches++;
1333 if (arc->src->count)
1334 coverage->branches_executed++;
1335 if (arc->count)
1336 coverage->branches_taken++;
1340 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1341 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1342 If DP is zero, no decimal point is printed. Only print 100% when
1343 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1344 format TOP. Return pointer to a static string. */
1346 static char const *
1347 format_gcov (top, bottom, dp)
1348 gcov_type top, bottom;
1349 int dp;
1351 static char buffer[20];
1353 if (dp >= 0)
1355 float ratio = bottom ? (float)top / bottom : 0;
1356 int ix;
1357 unsigned limit = 100;
1358 unsigned percent;
1360 for (ix = dp; ix--; )
1361 limit *= 10;
1363 percent = (unsigned) (ratio * limit + (float)0.5);
1364 if (percent <= 0 && top)
1365 percent = 1;
1366 else if (percent >= limit && top != bottom)
1367 percent = limit - 1;
1368 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1369 if (dp)
1371 dp++;
1374 buffer[ix+1] = buffer[ix];
1375 ix--;
1377 while (dp--);
1378 buffer[ix + 1] = '.';
1381 else
1382 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1384 return buffer;
1388 /* Output summary info for a function. */
1390 static void
1391 function_summary (coverage, title)
1392 const coverage_t *coverage;
1393 const char *title;
1395 fnotice (stdout, "%s `%s'\n", title, coverage->name);
1397 if (coverage->lines)
1398 fnotice (stdout, "Lines executed:%s of %d\n",
1399 format_gcov (coverage->lines_executed, coverage->lines, 2),
1400 coverage->lines);
1401 else
1402 fnotice (stdout, "No executable lines");
1404 if (flag_branches)
1406 if (coverage->branches)
1408 fnotice (stdout, "Branches executed:%s of %d\n",
1409 format_gcov (coverage->branches_executed,
1410 coverage->branches, 2),
1411 coverage->branches);
1412 fnotice (stdout, "Taken at least once:%s of %d\n",
1413 format_gcov (coverage->branches_taken,
1414 coverage->branches, 2),
1415 coverage->branches);
1417 else
1418 fnotice (stdout, "No branches\n");
1419 if (coverage->calls)
1420 fnotice (stdout, "Calls executed:%s of %d\n",
1421 format_gcov (coverage->calls_executed, coverage->calls, 2),
1422 coverage->calls);
1423 else
1424 fnotice (stdout, "No calls\n");
1428 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1429 affect name generation. With preserve_paths we create a filename
1430 from all path components of the source file, replacing '/' with
1431 '#', without it we simply take the basename component. With
1432 long_output_names we prepend the processed name of the input file
1433 to each output name (except when the current source file is the
1434 input file, so you don't get a double concatenation). The two
1435 components are separated by '##'. Also '.' filename components are
1436 removed and '..' components are renamed to '^'. */
1438 static char *
1439 make_gcov_file_name (input_name, src_name)
1440 const char *input_name;
1441 const char *src_name;
1443 char *cptr;
1444 char *name = xmalloc (strlen (src_name) + strlen (input_name) + 10);
1446 name[0] = 0;
1447 if (flag_long_names && strcmp (src_name, input_name))
1449 /* Generate the input filename part. */
1450 cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1451 strcat (name, cptr ? cptr + 1 : input_name);
1452 strcat (name, "##");
1455 /* Generate the source filename part. */
1456 cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1457 strcat (name, cptr ? cptr + 1 : src_name);
1459 if (flag_preserve_paths)
1461 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1462 char *prev;
1464 for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1466 unsigned shift = 0;
1468 if (prev + 1 == cptr && prev[0] == '.')
1470 /* Remove '.' */
1471 shift = 2;
1473 else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1475 /* Convert '..' */
1476 shift = 1;
1477 prev[1] = '^';
1479 else
1480 *cptr++ = '#';
1481 if (shift)
1483 cptr = prev;
1485 prev[0] = prev[shift];
1486 while (*prev++);
1491 strcat (name, ".gcov");
1492 return name;
1495 /* Scan through the bb_data for each line in the block, increment
1496 the line number execution count indicated by the execution count of
1497 the appropriate basic block. */
1499 static void
1500 add_line_counts (coverage, fn)
1501 coverage_t *coverage;
1502 function_t *fn;
1504 unsigned ix;
1505 line_t *line = NULL; /* this is propagated from one iteration to the
1506 next. */
1508 /* Scan each basic block. */
1509 for (ix = 0; ix != fn->num_blocks; ix++)
1511 block_t *block = &fn->blocks[ix];
1512 unsigned *encoding;
1513 const source_t *src = NULL;
1514 unsigned jx;
1516 if (block->count && ix && ix + 1 != fn->num_blocks)
1517 fn->blocks_executed++;
1518 for (jx = 0, encoding = block->u.line.encoding;
1519 jx != block->u.line.num; jx++, encoding++)
1520 if (!*encoding)
1522 unsigned src_n = *++encoding;
1524 for (src = sources; src->index != src_n; src = src->next)
1525 continue;
1526 jx++;
1528 else
1530 line = &src->lines[*encoding];
1532 if (coverage)
1534 if (!line->exists)
1535 coverage->lines++;
1536 if (!line->count && block->count)
1537 coverage->lines_executed++;
1539 line->exists = 1;
1540 line->count += block->count;
1542 free (block->u.line.encoding);
1543 block->u.cycle.arc = NULL;
1544 block->u.cycle.ident = ~0U;
1546 if (!ix || ix + 1 == fn->num_blocks)
1547 /* Entry or exit block */;
1548 else if (flag_all_blocks)
1550 line_t *block_line = line ? line : &fn->src->lines[fn->line];
1552 block->chain = block_line->u.blocks;
1553 block_line->u.blocks = block;
1555 else if (flag_branches)
1557 arc_t *arc;
1559 for (arc = block->succ; arc; arc = arc->succ_next)
1561 arc->line_next = line->u.branches;
1562 line->u.branches = arc;
1563 if (coverage && !arc->is_unconditional)
1564 add_branch_counts (coverage, arc);
1568 if (!line)
1569 fnotice (stderr, "%s:no lines for `%s'\n", bbg_file_name, fn->name);
1572 /* Accumulate the line counts of a file. */
1574 static void
1575 accumulate_line_counts (src)
1576 source_t *src;
1578 line_t *line;
1579 function_t *fn, *fn_p, *fn_n;
1580 unsigned ix;
1582 /* Reverse the function order. */
1583 for (fn = src->functions, fn_p = NULL; fn;
1584 fn_p = fn, fn = fn_n)
1586 fn_n = fn->line_next;
1587 fn->line_next = fn_p;
1589 src->functions = fn_p;
1591 for (ix = src->num_lines, line = src->lines; ix--; line++)
1593 if (!flag_all_blocks)
1595 arc_t *arc, *arc_p, *arc_n;
1597 /* Total and reverse the branch information. */
1598 for (arc = line->u.branches, arc_p = NULL; arc;
1599 arc_p = arc, arc = arc_n)
1601 arc_n = arc->line_next;
1602 arc->line_next = arc_p;
1604 add_branch_counts (&src->coverage, arc);
1606 line->u.branches = arc_p;
1608 else if (line->u.blocks)
1610 /* The user expects the line count to be the number of times
1611 a line has been executed. Simply summing the block count
1612 will give an artificially high number. The Right Thing
1613 is to sum the entry counts to the graph of blocks on this
1614 line, then find the elementary cycles of the local graph
1615 and add the transition counts of those cycles. */
1616 block_t *block, *block_p, *block_n;
1617 gcov_type count = 0;
1619 /* Reverse the block information */
1620 for (block = line->u.blocks, block_p = NULL; block;
1621 block_p = block, block = block_n)
1623 block_n = block->chain;
1624 block->chain = block_p;
1625 block->u.cycle.ident = ix;
1627 line->u.blocks = block_p;
1629 /* Sum the entry arcs. */
1630 for (block = line->u.blocks; block; block = block->chain)
1632 arc_t *arc;
1634 for (arc = block->pred; arc; arc = arc->pred_next)
1636 if (arc->src->u.cycle.ident != ix)
1637 count += arc->count;
1638 if (flag_branches)
1639 add_branch_counts (&src->coverage, arc);
1643 /* Find the loops. This uses the algorithm described in
1644 Tiernan 'An Efficient Search Algorithm to Find the
1645 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1646 the P array by having each block point to the arc that
1647 connects to the previous block. The H array is implicitly
1648 held because of the arc ordering, and the block's
1649 previous arc pointer.
1651 Although the algorithm is O(N^3) for highly connected
1652 graphs, at worst we'll have O(N^2), as most blocks have
1653 only one or two exits. Most graphs will be small.
1655 For each loop we find, locate the arc with the smallest
1656 transition count, and add that to the cumulative
1657 count. Remove the arc from consideration. */
1658 for (block = line->u.blocks; block; block = block->chain)
1660 block_t *head = block;
1661 arc_t *arc;
1663 next_vertex:;
1664 arc = head->succ;
1665 current_vertex:;
1666 while (arc)
1668 block_t *dst = arc->dst;
1669 if (/* Already used that arc. */
1670 arc->cycle
1671 /* Not to same graph, or before first vertex. */
1672 || dst->u.cycle.ident != ix
1673 /* Already in path. */
1674 || dst->u.cycle.arc)
1676 arc = arc->succ_next;
1677 continue;
1680 if (dst == block)
1682 /* Found a closing arc. */
1683 gcov_type cycle_count = arc->count;
1684 arc_t *cycle_arc = arc;
1685 arc_t *probe_arc;
1687 /* Locate the smallest arc count of the loop. */
1688 for (dst = head; (probe_arc = dst->u.cycle.arc);
1689 dst = probe_arc->src)
1690 if (cycle_count > probe_arc->count)
1692 cycle_count = probe_arc->count;
1693 cycle_arc = probe_arc;
1696 count += cycle_count;
1697 cycle_arc->cycle = 1;
1698 /* Unwind to the cyclic arc. */
1699 while (head != cycle_arc->src)
1701 arc = head->u.cycle.arc;
1702 head = arc->src;
1704 /* Move on. */
1705 arc = arc->succ_next;
1706 continue;
1709 /* Add new block to chain. */
1710 dst->u.cycle.arc = arc;
1711 head = dst;
1712 goto next_vertex;
1714 /* We could not add another vertex to the path. Remove
1715 the last vertex from the list. */
1716 arc = head->u.cycle.arc;
1717 if (arc)
1719 /* It was not the first vertex. Move onto next arc. */
1720 head->u.cycle.arc = NULL;
1721 head = arc->src;
1722 arc = arc->succ_next;
1723 goto current_vertex;
1725 /* Mark this block as unusable. */
1726 block->u.cycle.ident = ~0U;
1729 line->count = count;
1732 if (line->exists)
1734 src->coverage.lines++;
1735 if (line->count)
1736 src->coverage.lines_executed++;
1741 /* Ouput information about ARC number IX. Returns non-zero if
1742 anything is output. */
1744 static int
1745 output_branch_count (gcov_file, ix, arc)
1746 FILE *gcov_file;
1747 int ix;
1748 const arc_t *arc;
1751 if (arc->is_call_non_return)
1753 if (arc->src->count)
1755 fnotice (gcov_file, "call %2d returned %s\n", ix,
1756 format_gcov (arc->src->count - arc->count,
1757 arc->src->count, -flag_counts));
1759 else
1760 fnotice (gcov_file, "call %2d never executed\n", ix);
1762 else if (!arc->is_unconditional)
1764 if (arc->src->count)
1765 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
1766 format_gcov (arc->count, arc->src->count, -flag_counts),
1767 arc->fall_through ? " (fallthrough)" : "");
1768 else
1769 fnotice (gcov_file, "branch %2d never executed\n", ix);
1771 else if (flag_unconditional && !arc->dst->is_call_return)
1773 if (arc->src->count)
1774 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
1775 format_gcov (arc->count, arc->src->count, -flag_counts));
1776 else
1777 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
1779 else
1780 return 0;
1781 return 1;
1785 /* Read in the source file one line at a time, and output that line to
1786 the gcov file preceded by its execution count and other
1787 information. */
1789 static void
1790 output_lines (gcov_file, src)
1791 FILE *gcov_file;
1792 const source_t *src;
1794 FILE *source_file;
1795 unsigned line_num; /* current line number. */
1796 const line_t *line; /* current line info ptr. */
1797 char string[STRING_SIZE]; /* line buffer. */
1798 char const *retval = ""; /* status of source file reading. */
1799 function_t *fn = src->functions;
1801 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1802 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1803 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
1804 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_summary.runs);
1805 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
1807 source_file = fopen (src->name, "r");
1808 if (!source_file)
1810 fnotice (stderr, "%s:cannot open source file\n", src->name);
1811 retval = NULL;
1813 else
1815 struct stat status;
1817 if (!fstat (fileno (source_file), &status)
1818 && status.st_mtime > bbg_file_time)
1820 fnotice (stderr, "%s:source file is newer than graph file `%s'\n",
1821 src->name, bbg_file_name);
1822 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1823 "-", 0);
1827 for (line_num = 1, line = &src->lines[line_num];
1828 line_num < src->num_lines; line_num++, line++)
1830 for (; fn && fn->line == line_num; fn = fn->line_next)
1832 arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
1833 gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
1835 for (; arc; arc = arc->pred_next)
1836 if (arc->fake)
1837 return_count -= arc->count;
1839 fprintf (gcov_file, "function %s", fn->name);
1840 fprintf (gcov_file, " called %s",
1841 format_gcov (fn->blocks[0].count, 0, -1));
1842 fprintf (gcov_file, " returned %s",
1843 format_gcov (return_count, fn->blocks[0].count, 0));
1844 fprintf (gcov_file, " blocks executed %s",
1845 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
1846 fprintf (gcov_file, "\n");
1849 /* For lines which don't exist in the .bb file, print '-' before
1850 the source line. For lines which exist but were never
1851 executed, print '#####' before the source line. Otherwise,
1852 print the execution count before the source line. There are
1853 16 spaces of indentation added before the source line so that
1854 tabs won't be messed up. */
1855 fprintf (gcov_file, "%9s:%5u:",
1856 !line->exists ? "-" : !line->count ? "#####"
1857 : format_gcov (line->count, 0, -1), line_num);
1859 if (retval)
1861 /* Copy source line. */
1864 retval = fgets (string, STRING_SIZE, source_file);
1865 if (!retval)
1866 break;
1867 fputs (retval, gcov_file);
1869 while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1871 if (!retval)
1872 fputs ("/*EOF*/\n", gcov_file);
1874 if (flag_all_blocks)
1876 block_t *block;
1877 arc_t *arc;
1878 int ix, jx;
1880 for (ix = jx = 0, block = line->u.blocks; block;
1881 block = block->chain)
1883 if (!block->is_call_return)
1884 fprintf (gcov_file, "%9s:%5u-block %2d\n",
1885 !line->exists ? "-" : !block->count ? "$$$$$"
1886 : format_gcov (block->count, 0, -1),
1887 line_num, ix++);
1888 if (flag_branches)
1889 for (arc = block->succ; arc; arc = arc->succ_next)
1890 jx += output_branch_count (gcov_file, jx, arc);
1893 else if (flag_branches)
1895 int ix;
1896 arc_t *arc;
1898 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
1899 ix += output_branch_count (gcov_file, ix, arc);
1903 /* Handle all remaining source lines. There may be lines after the
1904 last line of code. */
1905 if (retval)
1907 for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1909 fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1911 while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1913 retval = fgets (string, STRING_SIZE, source_file);
1914 if (!retval)
1915 break;
1916 fputs (retval, gcov_file);
1921 if (source_file)
1922 fclose (source_file);