1 /* Gcov.c: prepend line execution counts and branch probabilities to a
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
4 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
5 Free Software Foundation, Inc.
6 Contributed by James E. Wilson of Cygnus Support.
7 Mangled by Bob Manson of Cygnus Support.
8 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
10 Gcov is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
15 Gcov is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with Gcov; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
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 /* Need an option to show individual block counts, and show
33 probabilities of fall through arcs. */
37 #include "coretypes.h"
48 /* The gcno file is generated by -ftest-coverage option. The gcda file is
49 generated by a program compiled with -fprofile-arcs. Their formats
50 are documented in gcov-io.h. */
52 /* The functions in this file for creating and solution program flow graphs
53 are very similar to functions in the gcc source file profile.c. In
54 some places we make use of the knowledge of how profile.c works to
55 select particular algorithms here. */
57 /* This is the size of the buffer used to read in source file lines. */
59 #define STRING_SIZE 200
65 /* Describes an arc between two basic blocks. */
67 typedef struct arc_info
69 /* source and destination blocks. */
70 struct block_info
*src
;
71 struct block_info
*dst
;
73 /* transition counts. */
75 /* used in cycle search, so that we do not clobber original counts. */
78 unsigned int count_valid
: 1;
79 unsigned int on_tree
: 1;
80 unsigned int fake
: 1;
81 unsigned int fall_through
: 1;
83 /* Arc is for a function that abnormally returns. */
84 unsigned int is_call_non_return
: 1;
86 /* Arc is for catch/setjmp. */
87 unsigned int is_nonlocal_return
: 1;
89 /* Is an unconditional branch. */
90 unsigned int is_unconditional
: 1;
92 /* Loop making arc. */
93 unsigned int cycle
: 1;
95 /* Next branch on line. */
96 struct arc_info
*line_next
;
98 /* Links to next arc on src and dst lists. */
99 struct arc_info
*succ_next
;
100 struct arc_info
*pred_next
;
103 /* Describes a basic block. Contains lists of arcs to successor and
104 predecessor blocks. */
106 typedef struct block_info
108 /* Chain of exit and entry arcs. */
112 /* Number of unprocessed exit and entry arcs. */
116 /* Block execution count. */
119 unsigned count_valid
: 1;
120 unsigned valid_chain
: 1;
121 unsigned invalid_chain
: 1;
123 /* Block is a call instrumenting site. */
124 unsigned is_call_site
: 1; /* Does the call. */
125 unsigned is_call_return
: 1; /* Is the return. */
127 /* Block is a landing pad for longjmp or throw. */
128 unsigned is_nonlocal_return
: 1;
134 /* Array of line numbers and source files. source files are
135 introduced by a linenumber of zero, the next 'line number' is
136 the number of the source file. Always starts with a source
140 } line
; /* Valid until blocks are linked onto lines */
143 /* Single line graph cycle workspace. Used for all-blocks
147 } cycle
; /* Used in all-blocks mode, after blocks are linked onto
151 /* Temporary chain for solving graph, and for chaining blocks on one
153 struct block_info
*chain
;
157 /* Describes a single function. Contains an array of basic blocks. */
159 typedef struct function_info
161 /* Name of function. */
166 /* Array of basic blocks. */
169 unsigned blocks_executed
;
171 /* Raw arc coverage counts. */
175 /* First line number. */
177 struct source_info
*src
;
179 /* Next function in same source file. */
180 struct function_info
*line_next
;
183 struct function_info
*next
;
186 /* Describes coverage of a file or function. */
188 typedef struct coverage_info
194 int branches_executed
;
203 /* Describes a single line of source. Contains a chain of basic blocks
206 typedef struct line_info
208 gcov_type count
; /* execution count */
211 arc_t
*branches
; /* branches from blocks that end on this
212 line. Used for branch-counts when not
214 block_t
*blocks
; /* blocks which start on this line. Used
215 in all-blocks mode. */
220 /* Describes a file mentioned in the block graph. Contains an array
223 typedef struct source_info
225 /* Name of source file. */
230 /* Array of line information. */
236 /* Functions in this source file. These are in ascending line
238 function_t
*functions
;
240 /* Next source file. */
241 struct source_info
*next
;
244 /* Holds a list of function basic block graphs. */
246 static function_t
*functions
;
248 /* This points to the head of the sourcefile structure list. New elements
249 are always prepended. */
251 static source_t
*sources
;
253 /* Next index for a source file. */
255 static unsigned source_index
;
257 /* This holds data summary information. */
259 static struct gcov_summary object_summary
;
260 static unsigned program_count
;
262 /* Modification time of graph file. */
264 static time_t bbg_file_time
;
266 /* Name and file pointer of the input file for the basic block graph. */
268 static char *bbg_file_name
;
270 /* Stamp of the bbg file */
271 static unsigned bbg_stamp
;
273 /* Name and file pointer of the input file for the arc count data. */
275 static char *da_file_name
;
277 /* Data file is missing. */
279 static int no_data_file
;
281 /* If there is several input files, compute and display results after
282 reading all data files. This way if two or more gcda file refer to
283 the same source file (eg inline subprograms in a .h file), the
286 static int multiple_files
= 0;
288 /* Output branch probabilities. */
290 static int flag_branches
= 0;
292 /* Show unconditional branches too. */
293 static int flag_unconditional
= 0;
295 /* Output a gcov file if this is true. This is on by default, and can
296 be turned off by the -n option. */
298 static int flag_gcov_file
= 1;
300 /* Output progress indication if this is true. This is off by default
301 and can be turned on by the -d option. */
303 static int flag_display_progress
= 0;
305 /* For included files, make the gcov output file name include the name
306 of the input source file. For example, if x.h is included in a.c,
307 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
309 static int flag_long_names
= 0;
311 /* Output count information for every basic block, not merely those
312 that contain line number information. */
314 static int flag_all_blocks
= 0;
316 /* Output summary info for each function. */
318 static int flag_function_summary
= 0;
320 /* Object directory file prefix. This is the directory/file where the
321 graph and data files are looked for, if nonzero. */
323 static char *object_directory
= 0;
325 /* Preserve all pathname components. Needed when object files and
326 source files are in subdirectories. '/' is mangled as '#', '.' is
327 elided and '..' mangled to '^'. */
329 static int flag_preserve_paths
= 0;
331 /* Output the number of times a branch was taken as opposed to the percentage
332 of times it was taken. */
334 static int flag_counts
= 0;
336 /* Forward declarations. */
337 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2
;
338 static int process_args (int, char **);
339 static void print_usage (int) ATTRIBUTE_NORETURN
;
340 static void print_version (void) ATTRIBUTE_NORETURN
;
341 static void process_file (const char *);
342 static void generate_results (const char *);
343 static void create_file_names (const char *);
344 static source_t
*find_source (const char *);
345 static int read_graph_file (void);
346 static int read_count_file (void);
347 static void solve_flow_graph (function_t
*);
348 static void add_branch_counts (coverage_t
*, const arc_t
*);
349 static void add_line_counts (coverage_t
*, function_t
*);
350 static void function_summary (const coverage_t
*, const char *);
351 static const char *format_gcov (gcov_type
, gcov_type
, int);
352 static void accumulate_line_counts (source_t
*);
353 static int output_branch_count (FILE *, int, const arc_t
*);
354 static void output_lines (FILE *, const source_t
*);
355 static char *make_gcov_file_name (const char *, const char *);
356 static void release_structures (void);
357 extern int main (int, char **);
360 main (int argc
, char **argv
)
365 /* Unlock the stdio streams. */
366 unlock_std_streams ();
370 /* Handle response files. */
371 expandargv (&argc
, &argv
);
373 argno
= process_args (argc
, argv
);
377 if (argc
- argno
> 1)
382 for (; argno
!= argc
; argno
++)
384 if (flag_display_progress
)
385 printf("Processing file %d out of %d\n",
386 argno
- first_arg
+ 1, argc
- first_arg
);
387 process_file (argv
[argno
]);
390 generate_results (multiple_files
? NULL
: argv
[argc
- 1]);
392 release_structures ();
398 fnotice (FILE *file
, const char *cmsgid
, ...)
402 va_start (ap
, cmsgid
);
403 vfprintf (file
, _(cmsgid
), ap
);
407 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
408 otherwise the output of --help. */
411 print_usage (int error_p
)
413 FILE *file
= error_p
? stderr
: stdout
;
414 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
416 fnotice (file
, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
417 fnotice (file
, "Print code coverage information.\n\n");
418 fnotice (file
, " -h, --help Print this help, then exit\n");
419 fnotice (file
, " -v, --version Print version number, then exit\n");
420 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
421 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
422 fnotice (file
, " -c, --branch-counts Given counts of branches taken\n\
423 rather than percentages\n");
424 fnotice (file
, " -n, --no-output Do not create an output file\n");
425 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
427 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
428 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
429 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
430 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
431 fnotice (file
, " -d, --display-progress Display progress information\n");
432 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
437 /* Print version information and exit. */
442 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
443 fprintf (stdout
, "Copyright %s 2011 Free Software Foundation, Inc.\n",
446 _("This is free software; see the source for copying conditions.\n"
447 "There is NO warranty; not even for MERCHANTABILITY or \n"
448 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
449 exit (SUCCESS_EXIT_CODE
);
452 static const struct option options
[] =
454 { "help", no_argument
, NULL
, 'h' },
455 { "version", no_argument
, NULL
, 'v' },
456 { "all-blocks", no_argument
, NULL
, 'a' },
457 { "branch-probabilities", no_argument
, NULL
, 'b' },
458 { "branch-counts", no_argument
, NULL
, 'c' },
459 { "no-output", no_argument
, NULL
, 'n' },
460 { "long-file-names", no_argument
, NULL
, 'l' },
461 { "function-summaries", no_argument
, NULL
, 'f' },
462 { "preserve-paths", no_argument
, NULL
, 'p' },
463 { "object-directory", required_argument
, NULL
, 'o' },
464 { "object-file", required_argument
, NULL
, 'o' },
465 { "unconditional-branches", no_argument
, NULL
, 'u' },
466 { "display-progress", no_argument
, NULL
, 'd' },
470 /* Process args, return index to first non-arg. */
473 process_args (int argc
, char **argv
)
477 while ((opt
= getopt_long (argc
, argv
, "abcdfhlno:puv", options
, NULL
)) != -1)
491 flag_function_summary
= 1;
495 /* print_usage will exit. */
503 object_directory
= optarg
;
506 flag_preserve_paths
= 1;
509 flag_unconditional
= 1;
512 flag_display_progress
= 1;
516 /* print_version will exit. */
519 /* print_usage will exit. */
526 /* Process a single source file. */
529 process_file (const char *file_name
)
533 function_t
*old_functions
;
535 /* Save and clear the list of current functions. They will be appended
537 old_functions
= functions
;
540 create_file_names (file_name
);
541 if (read_graph_file ())
546 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
550 if (read_count_file ())
553 for (fn_p
= NULL
, fn
= functions
; fn
; fn_p
= fn
, fn
= fn
->next
)
554 solve_flow_graph (fn
);
557 fn_p
->next
= old_functions
;
561 generate_results (const char *file_name
)
566 for (src
= sources
; src
; src
= src
->next
)
567 src
->lines
= XCNEWVEC (line_t
, src
->num_lines
);
568 for (fn
= functions
; fn
; fn
= fn
->next
)
572 memset (&coverage
, 0, sizeof (coverage
));
573 coverage
.name
= fn
->name
;
574 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
575 if (flag_function_summary
)
577 function_summary (&coverage
, "Function");
578 fnotice (stdout
, "\n");
582 for (src
= sources
; src
; src
= src
->next
)
584 accumulate_line_counts (src
);
585 function_summary (&src
->coverage
, "File");
588 char *gcov_file_name
= make_gcov_file_name (file_name
, src
->name
);
589 FILE *gcov_file
= fopen (gcov_file_name
, "w");
593 fnotice (stdout
, "%s:creating '%s'\n",
594 src
->name
, gcov_file_name
);
595 output_lines (gcov_file
, src
);
596 if (ferror (gcov_file
))
597 fnotice (stderr
, "%s:error writing output file '%s'\n",
598 src
->name
, gcov_file_name
);
602 fnotice (stderr
, "%s:could not open output file '%s'\n",
603 src
->name
, gcov_file_name
);
604 free (gcov_file_name
);
606 fnotice (stdout
, "\n");
610 /* Release all memory used. */
613 release_structures (void)
618 while ((src
= sources
))
626 while ((fn
= functions
))
631 functions
= fn
->next
;
632 for (ix
= fn
->num_blocks
, block
= fn
->blocks
; ix
--; block
++)
636 for (arc
= block
->succ
; arc
; arc
= arc_n
)
638 arc_n
= arc
->succ_next
;
647 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
648 is not specified, these are looked for in the current directory,
649 and named from the basename of the FILE_NAME sans extension. If
650 OBJECT_DIRECTORY is specified and is a directory, the files are in
651 that directory, but named from the basename of the FILE_NAME, sans
652 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
653 the object *file*, and the data files are named from that. */
656 create_file_names (const char *file_name
)
660 int length
= strlen (file_name
);
663 /* Free previous file names. */
665 free (bbg_file_name
);
668 da_file_name
= bbg_file_name
= NULL
;
672 if (object_directory
&& object_directory
[0])
676 length
+= strlen (object_directory
) + 2;
677 name
= XNEWVEC (char, length
);
680 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
681 strcat (name
, object_directory
);
682 if (base
&& (! IS_DIR_SEPARATOR (name
[strlen (name
) - 1])))
687 name
= XNEWVEC (char, length
+ 1);
694 /* Append source file name. */
695 const char *cptr
= lbasename (file_name
);
696 strcat (name
, cptr
? cptr
: file_name
);
699 /* Remove the extension. */
700 cptr
= strrchr (name
, '.');
704 length
= strlen (name
);
706 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
707 strcpy (bbg_file_name
, name
);
708 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
710 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
711 strcpy (da_file_name
, name
);
712 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
718 /* Find or create a source file structure for FILE_NAME. Copies
719 FILE_NAME on creation */
722 find_source (const char *file_name
)
728 file_name
= "<unknown>";
730 for (src
= sources
; src
; src
= src
->next
)
731 if (!filename_cmp (file_name
, src
->name
))
736 src
= XCNEW (source_t
);
737 src
->name
= xstrdup (file_name
);
738 src
->coverage
.name
= src
->name
;
739 src
->index
= source_index
++;
743 if (!stat (file_name
, &status
))
744 src
->file_time
= status
.st_mtime
;
747 if (src
->file_time
> bbg_file_time
)
749 static int info_emitted
;
751 fnotice (stderr
, "%s:source file is newer than graph file '%s'\n",
752 src
->name
, bbg_file_name
);
756 "(the message is only displayed one per source file)\n");
765 /* Read the graph file. Return nonzero on fatal error. */
768 read_graph_file (void)
771 unsigned current_tag
= 0;
772 struct function_info
*fn
= NULL
;
773 function_t
*old_functions_head
= functions
;
774 source_t
*src
= NULL
;
778 if (!gcov_open (bbg_file_name
, 1))
780 fnotice (stderr
, "%s:cannot open graph file\n", bbg_file_name
);
783 bbg_file_time
= gcov_time ();
784 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
786 fnotice (stderr
, "%s:not a gcov graph file\n", bbg_file_name
);
791 version
= gcov_read_unsigned ();
792 if (version
!= GCOV_VERSION
)
796 GCOV_UNSIGNED2STRING (v
, version
);
797 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
799 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
800 bbg_file_name
, v
, e
);
802 bbg_stamp
= gcov_read_unsigned ();
804 while ((tag
= gcov_read_unsigned ()))
806 unsigned length
= gcov_read_unsigned ();
807 gcov_position_t base
= gcov_position ();
809 if (tag
== GCOV_TAG_FUNCTION
)
812 unsigned ident
, checksum
, lineno
;
814 function_t
*probe
, *prev
;
816 ident
= gcov_read_unsigned ();
817 checksum
= gcov_read_unsigned ();
818 function_name
= xstrdup (gcov_read_string ());
819 src
= find_source (gcov_read_string ());
820 lineno
= gcov_read_unsigned ();
822 fn
= XCNEW (function_t
);
823 fn
->name
= function_name
;
825 fn
->checksum
= checksum
;
829 fn
->next
= functions
;
833 if (lineno
>= src
->num_lines
)
834 src
->num_lines
= lineno
+ 1;
835 /* Now insert it into the source file's list of
836 functions. Normally functions will be encountered in
837 ascending order, so a simple scan is quick. */
838 for (probe
= src
->functions
, prev
= NULL
;
839 probe
&& probe
->line
> lineno
;
840 prev
= probe
, probe
= probe
->line_next
)
842 fn
->line_next
= probe
;
844 prev
->line_next
= fn
;
848 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
851 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
852 bbg_file_name
, fn
->name
);
855 unsigned ix
, num_blocks
= GCOV_TAG_BLOCKS_NUM (length
);
856 fn
->num_blocks
= num_blocks
;
858 fn
->blocks
= XCNEWVEC (block_t
, fn
->num_blocks
);
859 for (ix
= 0; ix
!= num_blocks
; ix
++)
860 fn
->blocks
[ix
].flags
= gcov_read_unsigned ();
863 else if (fn
&& tag
== GCOV_TAG_ARCS
)
865 unsigned src
= gcov_read_unsigned ();
866 unsigned num_dests
= GCOV_TAG_ARCS_NUM (length
);
868 if (src
>= fn
->num_blocks
|| fn
->blocks
[src
].succ
)
873 struct arc_info
*arc
;
874 unsigned dest
= gcov_read_unsigned ();
875 unsigned flags
= gcov_read_unsigned ();
877 if (dest
>= fn
->num_blocks
)
881 arc
->dst
= &fn
->blocks
[dest
];
882 arc
->src
= &fn
->blocks
[src
];
885 arc
->count_valid
= 0;
886 arc
->on_tree
= !!(flags
& GCOV_ARC_ON_TREE
);
887 arc
->fake
= !!(flags
& GCOV_ARC_FAKE
);
888 arc
->fall_through
= !!(flags
& GCOV_ARC_FALLTHROUGH
);
890 arc
->succ_next
= fn
->blocks
[src
].succ
;
891 fn
->blocks
[src
].succ
= arc
;
892 fn
->blocks
[src
].num_succ
++;
894 arc
->pred_next
= fn
->blocks
[dest
].pred
;
895 fn
->blocks
[dest
].pred
= arc
;
896 fn
->blocks
[dest
].num_pred
++;
902 /* Exceptional exit from this function, the
903 source block must be a call. */
904 fn
->blocks
[src
].is_call_site
= 1;
905 arc
->is_call_non_return
= 1;
909 /* Non-local return from a callee of this
910 function. The destination block is a catch or
912 arc
->is_nonlocal_return
= 1;
913 fn
->blocks
[dest
].is_nonlocal_return
= 1;
921 else if (fn
&& tag
== GCOV_TAG_LINES
)
923 unsigned blockno
= gcov_read_unsigned ();
924 unsigned *line_nos
= XCNEWVEC (unsigned, length
- 1);
926 if (blockno
>= fn
->num_blocks
|| fn
->blocks
[blockno
].u
.line
.encoding
)
931 unsigned lineno
= gcov_read_unsigned ();
938 line_nos
[ix
++] = src
->index
;
940 line_nos
[ix
++] = lineno
;
941 if (lineno
>= src
->num_lines
)
942 src
->num_lines
= lineno
+ 1;
946 const char *file_name
= gcov_read_string ();
950 src
= find_source (file_name
);
953 line_nos
[ix
++] = src
->index
;
957 fn
->blocks
[blockno
].u
.line
.encoding
= line_nos
;
958 fn
->blocks
[blockno
].u
.line
.num
= ix
;
960 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
965 gcov_sync (base
, length
);
966 if (gcov_is_error ())
969 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
976 /* We built everything backwards, so nreverse them all. */
978 /* Reverse sources. Not strictly necessary, but we'll then process
979 them in the 'expected' order. */
981 source_t
*src
, *src_p
, *src_n
;
983 for (src_p
= NULL
, src
= sources
; src
; src_p
= src
, src
= src_n
)
991 /* Reverse functions. */
993 function_t
*fn
, *fn_p
, *fn_n
;
995 for (fn_p
= old_functions_head
, fn
= functions
;
996 fn
!= old_functions_head
;
997 fn_p
= fn
, fn
= fn_n
)
1004 /* Reverse the arcs. */
1005 for (ix
= fn
->num_blocks
; ix
--;)
1007 arc_t
*arc
, *arc_p
, *arc_n
;
1009 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
1010 arc_p
= arc
, arc
= arc_n
)
1012 arc_n
= arc
->succ_next
;
1013 arc
->succ_next
= arc_p
;
1015 fn
->blocks
[ix
].succ
= arc_p
;
1017 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
1018 arc_p
= arc
, arc
= arc_n
)
1020 arc_n
= arc
->pred_next
;
1021 arc
->pred_next
= arc_p
;
1023 fn
->blocks
[ix
].pred
= arc_p
;
1031 /* Reads profiles from the count file and attach to each
1032 function. Return nonzero if fatal error. */
1035 read_count_file (void)
1040 function_t
*fn
= NULL
;
1043 if (!gcov_open (da_file_name
, 1))
1045 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1050 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1052 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1057 version
= gcov_read_unsigned ();
1058 if (version
!= GCOV_VERSION
)
1062 GCOV_UNSIGNED2STRING (v
, version
);
1063 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1065 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1066 da_file_name
, v
, e
);
1068 tag
= gcov_read_unsigned ();
1069 if (tag
!= bbg_stamp
)
1071 fnotice (stderr
, "%s:stamp mismatch with graph file\n", da_file_name
);
1075 while ((tag
= gcov_read_unsigned ()))
1077 unsigned length
= gcov_read_unsigned ();
1078 unsigned long base
= gcov_position ();
1080 if (tag
== GCOV_TAG_OBJECT_SUMMARY
)
1081 gcov_read_summary (&object_summary
);
1082 else if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1084 else if (tag
== GCOV_TAG_FUNCTION
)
1087 unsigned ident
= gcov_read_unsigned ();
1088 struct function_info
*fn_n
= functions
;
1090 /* Try to find the function in the list.
1091 To speed up the search, first start from the last function
1093 for (fn
= fn
? fn
->next
: NULL
; ; fn
= fn
->next
)
1097 else if ((fn
= fn_n
))
1101 fnotice (stderr
, "%s:unknown function '%u'\n",
1102 da_file_name
, ident
);
1105 if (fn
->ident
== ident
)
1112 else if (gcov_read_unsigned () != fn
->checksum
)
1115 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1116 da_file_name
, fn
->name
);
1120 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1122 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->num_counts
))
1126 fn
->counts
= XCNEWVEC (gcov_type
, fn
->num_counts
);
1128 for (ix
= 0; ix
!= fn
->num_counts
; ix
++)
1129 fn
->counts
[ix
] += gcov_read_counter ();
1131 gcov_sync (base
, length
);
1132 if ((error
= gcov_is_error ()))
1134 fnotice (stderr
, error
< 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1144 /* Solve the flow graph. Propagate counts from the instrumented arcs
1145 to the blocks and the uninstrumented arcs. */
1148 solve_flow_graph (function_t
*fn
)
1152 gcov_type
*count_ptr
= fn
->counts
;
1154 block_t
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1155 block_t
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1157 if (fn
->num_blocks
< 2)
1158 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1159 bbg_file_name
, fn
->name
);
1162 if (fn
->blocks
[0].num_pred
)
1163 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1164 bbg_file_name
, fn
->name
);
1166 /* We can't deduce the entry block counts from the lack of
1168 fn
->blocks
[0].num_pred
= ~(unsigned)0;
1170 if (fn
->blocks
[fn
->num_blocks
- 1].num_succ
)
1171 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1172 bbg_file_name
, fn
->name
);
1174 /* Likewise, we can't deduce exit block counts from the lack
1175 of its successors. */
1176 fn
->blocks
[fn
->num_blocks
- 1].num_succ
= ~(unsigned)0;
1179 /* Propagate the measured counts, this must be done in the same
1180 order as the code in profile.c */
1181 for (ix
= 0, blk
= fn
->blocks
; ix
!= fn
->num_blocks
; ix
++, blk
++)
1183 block_t
const *prev_dst
= NULL
;
1184 int out_of_order
= 0;
1185 int non_fake_succ
= 0;
1187 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1195 arc
->count
= *count_ptr
++;
1196 arc
->count_valid
= 1;
1198 arc
->dst
->num_pred
--;
1200 if (prev_dst
&& prev_dst
> arc
->dst
)
1202 prev_dst
= arc
->dst
;
1204 if (non_fake_succ
== 1)
1206 /* If there is only one non-fake exit, it is an
1207 unconditional branch. */
1208 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1211 arc
->is_unconditional
= 1;
1212 /* If this block is instrumenting a call, it might be
1213 an artificial block. It is not artificial if it has
1214 a non-fallthrough exit, or the destination of this
1215 arc has more than one entry. Mark the destination
1216 block as a return site, if none of those conditions
1218 if (blk
->is_call_site
&& arc
->fall_through
1219 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1220 arc
->dst
->is_call_return
= 1;
1224 /* Sort the successor arcs into ascending dst order. profile.c
1225 normally produces arcs in the right order, but sometimes with
1226 one or two out of order. We're not using a particularly
1230 arc_t
*start
= blk
->succ
;
1231 unsigned changes
= 1;
1235 arc_t
*arc
, *arc_p
, *arc_n
;
1238 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1240 if (arc
->dst
> arc_n
->dst
)
1244 arc_p
->succ_next
= arc_n
;
1247 arc
->succ_next
= arc_n
->succ_next
;
1248 arc_n
->succ_next
= arc
;
1261 /* Place it on the invalid chain, it will be ignored if that's
1263 blk
->invalid_chain
= 1;
1264 blk
->chain
= invalid_blocks
;
1265 invalid_blocks
= blk
;
1268 while (invalid_blocks
|| valid_blocks
)
1270 while ((blk
= invalid_blocks
))
1272 gcov_type total
= 0;
1275 invalid_blocks
= blk
->chain
;
1276 blk
->invalid_chain
= 0;
1278 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1279 total
+= arc
->count
;
1280 else if (!blk
->num_pred
)
1281 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1282 total
+= arc
->count
;
1287 blk
->count_valid
= 1;
1288 blk
->chain
= valid_blocks
;
1289 blk
->valid_chain
= 1;
1292 while ((blk
= valid_blocks
))
1295 arc_t
*arc
, *inv_arc
;
1297 valid_blocks
= blk
->chain
;
1298 blk
->valid_chain
= 0;
1299 if (blk
->num_succ
== 1)
1305 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1307 total
-= arc
->count
;
1308 if (!arc
->count_valid
)
1312 inv_arc
->count_valid
= 1;
1313 inv_arc
->count
= total
;
1316 if (dst
->count_valid
)
1318 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
1320 dst
->chain
= valid_blocks
;
1321 dst
->valid_chain
= 1;
1327 if (!dst
->num_pred
&& !dst
->invalid_chain
)
1329 dst
->chain
= invalid_blocks
;
1330 dst
->invalid_chain
= 1;
1331 invalid_blocks
= dst
;
1335 if (blk
->num_pred
== 1)
1341 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1343 total
-= arc
->count
;
1344 if (!arc
->count_valid
)
1348 inv_arc
->count_valid
= 1;
1349 inv_arc
->count
= total
;
1352 if (src
->count_valid
)
1354 if (src
->num_succ
== 1 && !src
->valid_chain
)
1356 src
->chain
= valid_blocks
;
1357 src
->valid_chain
= 1;
1363 if (!src
->num_succ
&& !src
->invalid_chain
)
1365 src
->chain
= invalid_blocks
;
1366 src
->invalid_chain
= 1;
1367 invalid_blocks
= src
;
1374 /* If the graph has been correctly solved, every block will have a
1376 for (ix
= 0; ix
< fn
->num_blocks
; ix
++)
1377 if (!fn
->blocks
[ix
].count_valid
)
1379 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
1380 bbg_file_name
, fn
->name
);
1387 /* Increment totals in COVERAGE according to arc ARC. */
1390 add_branch_counts (coverage_t
*coverage
, const arc_t
*arc
)
1392 if (arc
->is_call_non_return
)
1395 if (arc
->src
->count
)
1396 coverage
->calls_executed
++;
1398 else if (!arc
->is_unconditional
)
1400 coverage
->branches
++;
1401 if (arc
->src
->count
)
1402 coverage
->branches_executed
++;
1404 coverage
->branches_taken
++;
1408 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1409 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1410 If DP is zero, no decimal point is printed. Only print 100% when
1411 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1412 format TOP. Return pointer to a static string. */
1415 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
1417 static char buffer
[20];
1421 float ratio
= bottom
? (float)top
/ bottom
: 0;
1423 unsigned limit
= 100;
1426 for (ix
= dp
; ix
--; )
1429 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1430 if (percent
<= 0 && top
)
1432 else if (percent
>= limit
&& top
!= bottom
)
1433 percent
= limit
- 1;
1434 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
1440 buffer
[ix
+1] = buffer
[ix
];
1444 buffer
[ix
+ 1] = '.';
1448 sprintf (buffer
, HOST_WIDEST_INT_PRINT_DEC
, (HOST_WIDEST_INT
)top
);
1454 /* Output summary info for a function. */
1457 function_summary (const coverage_t
*coverage
, const char *title
)
1459 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
1461 if (coverage
->lines
)
1462 fnotice (stdout
, "Lines executed:%s of %d\n",
1463 format_gcov (coverage
->lines_executed
, coverage
->lines
, 2),
1466 fnotice (stdout
, "No executable lines\n");
1470 if (coverage
->branches
)
1472 fnotice (stdout
, "Branches executed:%s of %d\n",
1473 format_gcov (coverage
->branches_executed
,
1474 coverage
->branches
, 2),
1475 coverage
->branches
);
1476 fnotice (stdout
, "Taken at least once:%s of %d\n",
1477 format_gcov (coverage
->branches_taken
,
1478 coverage
->branches
, 2),
1479 coverage
->branches
);
1482 fnotice (stdout
, "No branches\n");
1483 if (coverage
->calls
)
1484 fnotice (stdout
, "Calls executed:%s of %d\n",
1485 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
1488 fnotice (stdout
, "No calls\n");
1492 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1493 affect name generation. With preserve_paths we create a filename
1494 from all path components of the source file, replacing '/' with
1495 '#', without it we simply take the basename component. With
1496 long_output_names we prepend the processed name of the input file
1497 to each output name (except when the current source file is the
1498 input file, so you don't get a double concatenation). The two
1499 components are separated by '##'. Also '.' filename components are
1500 removed and '..' components are renamed to '^'. */
1503 make_gcov_file_name (const char *input_name
, const char *src_name
)
1508 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
1510 name
= XNEWVEC (char, strlen (src_name
) + strlen (input_name
) + 10);
1512 /* Generate the input filename part. */
1513 cptr
= flag_preserve_paths
? NULL
: lbasename (input_name
);
1514 strcat (name
, cptr
? cptr
: input_name
);
1515 strcat (name
, "##");
1519 name
= XNEWVEC (char, strlen (src_name
) + 10);
1523 /* Generate the source filename part. */
1525 cptr
= flag_preserve_paths
? NULL
: lbasename (src_name
);
1526 strcat (name
, cptr
? cptr
: src_name
);
1528 if (flag_preserve_paths
)
1530 /* Convert '/' and '\' to '#', remove '/./', convert '/../' to '#^#',
1531 convert ':' to '~' on DOS based file system. */
1532 char *pnew
= name
, *pold
= name
;
1534 /* First check for leading drive separator. */
1536 while (*pold
!= '\0')
1538 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
1547 && (strstr (pold
, "/./") == pold
1548 || strstr (pold
, "/.\\") == pold
))
1550 && (strstr (pold
, "\\.\\") == pold
1551 || strstr (pold
, "\\./") == pold
)))
1553 else if (*pold
== '/'
1554 && (strstr (pold
, "/../") == pold
1555 || strstr (pold
, "/..\\") == pold
))
1557 strcpy (pnew
, "#^#");
1561 else if (*pold
== '\\'
1562 && (strstr (pold
, "\\..\\") == pold
1563 || strstr (pold
, "\\../") == pold
))
1565 strcpy (pnew
, "#^#");
1569 else if (*pold
== '/' || *pold
== '\\')
1581 strcat (name
, ".gcov");
1585 /* Scan through the bb_data for each line in the block, increment
1586 the line number execution count indicated by the execution count of
1587 the appropriate basic block. */
1590 add_line_counts (coverage_t
*coverage
, function_t
*fn
)
1593 line_t
*line
= NULL
; /* This is propagated from one iteration to the
1596 /* Scan each basic block. */
1597 for (ix
= 0; ix
!= fn
->num_blocks
; ix
++)
1599 block_t
*block
= &fn
->blocks
[ix
];
1601 const source_t
*src
= NULL
;
1604 if (block
->count
&& ix
&& ix
+ 1 != fn
->num_blocks
)
1605 fn
->blocks_executed
++;
1606 for (jx
= 0, encoding
= block
->u
.line
.encoding
;
1607 jx
!= block
->u
.line
.num
; jx
++, encoding
++)
1610 unsigned src_n
= *++encoding
;
1612 for (src
= sources
; src
->index
!= src_n
; src
= src
->next
)
1618 line
= &src
->lines
[*encoding
];
1624 if (!line
->count
&& block
->count
)
1625 coverage
->lines_executed
++;
1628 line
->count
+= block
->count
;
1630 free (block
->u
.line
.encoding
);
1631 block
->u
.cycle
.arc
= NULL
;
1632 block
->u
.cycle
.ident
= ~0U;
1634 if (!ix
|| ix
+ 1 == fn
->num_blocks
)
1635 /* Entry or exit block */;
1636 else if (flag_all_blocks
)
1638 line_t
*block_line
= line
? line
: &fn
->src
->lines
[fn
->line
];
1640 block
->chain
= block_line
->u
.blocks
;
1641 block_line
->u
.blocks
= block
;
1643 else if (flag_branches
)
1647 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1649 arc
->line_next
= line
->u
.branches
;
1650 line
->u
.branches
= arc
;
1651 if (coverage
&& !arc
->is_unconditional
)
1652 add_branch_counts (coverage
, arc
);
1657 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
1660 /* Accumulate the line counts of a file. */
1663 accumulate_line_counts (source_t
*src
)
1666 function_t
*fn
, *fn_p
, *fn_n
;
1669 /* Reverse the function order. */
1670 for (fn
= src
->functions
, fn_p
= NULL
; fn
;
1671 fn_p
= fn
, fn
= fn_n
)
1673 fn_n
= fn
->line_next
;
1674 fn
->line_next
= fn_p
;
1676 src
->functions
= fn_p
;
1678 for (ix
= src
->num_lines
, line
= src
->lines
; ix
--; line
++)
1680 if (!flag_all_blocks
)
1682 arc_t
*arc
, *arc_p
, *arc_n
;
1684 /* Total and reverse the branch information. */
1685 for (arc
= line
->u
.branches
, arc_p
= NULL
; arc
;
1686 arc_p
= arc
, arc
= arc_n
)
1688 arc_n
= arc
->line_next
;
1689 arc
->line_next
= arc_p
;
1691 add_branch_counts (&src
->coverage
, arc
);
1693 line
->u
.branches
= arc_p
;
1695 else if (line
->u
.blocks
)
1697 /* The user expects the line count to be the number of times
1698 a line has been executed. Simply summing the block count
1699 will give an artificially high number. The Right Thing
1700 is to sum the entry counts to the graph of blocks on this
1701 line, then find the elementary cycles of the local graph
1702 and add the transition counts of those cycles. */
1703 block_t
*block
, *block_p
, *block_n
;
1704 gcov_type count
= 0;
1706 /* Reverse the block information. */
1707 for (block
= line
->u
.blocks
, block_p
= NULL
; block
;
1708 block_p
= block
, block
= block_n
)
1710 block_n
= block
->chain
;
1711 block
->chain
= block_p
;
1712 block
->u
.cycle
.ident
= ix
;
1714 line
->u
.blocks
= block_p
;
1716 /* Sum the entry arcs. */
1717 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1721 for (arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
1723 if (arc
->src
->u
.cycle
.ident
!= ix
)
1724 count
+= arc
->count
;
1726 add_branch_counts (&src
->coverage
, arc
);
1729 /* Initialize the cs_count. */
1730 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1731 arc
->cs_count
= arc
->count
;
1734 /* Find the loops. This uses the algorithm described in
1735 Tiernan 'An Efficient Search Algorithm to Find the
1736 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1737 the P array by having each block point to the arc that
1738 connects to the previous block. The H array is implicitly
1739 held because of the arc ordering, and the block's
1740 previous arc pointer.
1742 Although the algorithm is O(N^3) for highly connected
1743 graphs, at worst we'll have O(N^2), as most blocks have
1744 only one or two exits. Most graphs will be small.
1746 For each loop we find, locate the arc with the smallest
1747 transition count, and add that to the cumulative
1748 count. Decrease flow over the cycle and remove the arc
1749 from consideration. */
1750 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1752 block_t
*head
= block
;
1760 block_t
*dst
= arc
->dst
;
1761 if (/* Already used that arc. */
1763 /* Not to same graph, or before first vertex. */
1764 || dst
->u
.cycle
.ident
!= ix
1765 /* Already in path. */
1766 || dst
->u
.cycle
.arc
)
1768 arc
= arc
->succ_next
;
1774 /* Found a closing arc. */
1775 gcov_type cycle_count
= arc
->cs_count
;
1776 arc_t
*cycle_arc
= arc
;
1779 /* Locate the smallest arc count of the loop. */
1780 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1781 dst
= probe_arc
->src
)
1782 if (cycle_count
> probe_arc
->cs_count
)
1784 cycle_count
= probe_arc
->cs_count
;
1785 cycle_arc
= probe_arc
;
1788 count
+= cycle_count
;
1789 cycle_arc
->cycle
= 1;
1791 /* Remove the flow from the cycle. */
1792 arc
->cs_count
-= cycle_count
;
1793 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1794 dst
= probe_arc
->src
)
1795 probe_arc
->cs_count
-= cycle_count
;
1797 /* Unwind to the cyclic arc. */
1798 while (head
!= cycle_arc
->src
)
1800 arc
= head
->u
.cycle
.arc
;
1801 head
->u
.cycle
.arc
= NULL
;
1805 arc
= arc
->succ_next
;
1809 /* Add new block to chain. */
1810 dst
->u
.cycle
.arc
= arc
;
1814 /* We could not add another vertex to the path. Remove
1815 the last vertex from the list. */
1816 arc
= head
->u
.cycle
.arc
;
1819 /* It was not the first vertex. Move onto next arc. */
1820 head
->u
.cycle
.arc
= NULL
;
1822 arc
= arc
->succ_next
;
1823 goto current_vertex
;
1825 /* Mark this block as unusable. */
1826 block
->u
.cycle
.ident
= ~0U;
1829 line
->count
= count
;
1834 src
->coverage
.lines
++;
1836 src
->coverage
.lines_executed
++;
1841 /* Output information about ARC number IX. Returns nonzero if
1842 anything is output. */
1845 output_branch_count (FILE *gcov_file
, int ix
, const arc_t
*arc
)
1848 if (arc
->is_call_non_return
)
1850 if (arc
->src
->count
)
1852 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
1853 format_gcov (arc
->src
->count
- arc
->count
,
1854 arc
->src
->count
, -flag_counts
));
1857 fnotice (gcov_file
, "call %2d never executed\n", ix
);
1859 else if (!arc
->is_unconditional
)
1861 if (arc
->src
->count
)
1862 fnotice (gcov_file
, "branch %2d taken %s%s\n", ix
,
1863 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
1864 arc
->fall_through
? " (fallthrough)" : "");
1866 fnotice (gcov_file
, "branch %2d never executed\n", ix
);
1868 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
1870 if (arc
->src
->count
)
1871 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
1872 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
1874 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
1882 /* Read in the source file one line at a time, and output that line to
1883 the gcov file preceded by its execution count and other
1887 output_lines (FILE *gcov_file
, const source_t
*src
)
1890 unsigned line_num
; /* current line number. */
1891 const line_t
*line
; /* current line info ptr. */
1892 char string
[STRING_SIZE
]; /* line buffer. */
1893 char const *retval
= ""; /* status of source file reading. */
1894 function_t
*fn
= NULL
;
1896 fprintf (gcov_file
, "%9s:%5d:Source:%s\n", "-", 0, src
->name
);
1897 if (!multiple_files
)
1899 fprintf (gcov_file
, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name
);
1900 fprintf (gcov_file
, "%9s:%5d:Data:%s\n", "-", 0,
1901 no_data_file
? "-" : da_file_name
);
1902 fprintf (gcov_file
, "%9s:%5d:Runs:%u\n", "-", 0,
1903 object_summary
.ctrs
[GCOV_COUNTER_ARCS
].runs
);
1905 fprintf (gcov_file
, "%9s:%5d:Programs:%u\n", "-", 0, program_count
);
1907 source_file
= fopen (src
->name
, "r");
1910 fnotice (stderr
, "%s:cannot open source file\n", src
->name
);
1913 else if (src
->file_time
== 0)
1914 fprintf (gcov_file
, "%9s:%5d:Source is newer than graph\n", "-", 0);
1917 fn
= src
->functions
;
1919 for (line_num
= 1, line
= &src
->lines
[line_num
];
1920 line_num
< src
->num_lines
; line_num
++, line
++)
1922 for (; fn
&& fn
->line
== line_num
; fn
= fn
->line_next
)
1924 arc_t
*arc
= fn
->blocks
[fn
->num_blocks
- 1].pred
;
1925 gcov_type return_count
= fn
->blocks
[fn
->num_blocks
- 1].count
;
1927 for (; arc
; arc
= arc
->pred_next
)
1929 return_count
-= arc
->count
;
1931 fprintf (gcov_file
, "function %s", fn
->name
);
1932 fprintf (gcov_file
, " called %s",
1933 format_gcov (fn
->blocks
[0].count
, 0, -1));
1934 fprintf (gcov_file
, " returned %s",
1935 format_gcov (return_count
, fn
->blocks
[0].count
, 0));
1936 fprintf (gcov_file
, " blocks executed %s",
1937 format_gcov (fn
->blocks_executed
, fn
->num_blocks
- 2, 0));
1938 fprintf (gcov_file
, "\n");
1941 /* For lines which don't exist in the .bb file, print '-' before
1942 the source line. For lines which exist but were never
1943 executed, print '#####' before the source line. Otherwise,
1944 print the execution count before the source line. There are
1945 16 spaces of indentation added before the source line so that
1946 tabs won't be messed up. */
1947 fprintf (gcov_file
, "%9s:%5u:",
1948 !line
->exists
? "-" : !line
->count
? "#####"
1949 : format_gcov (line
->count
, 0, -1), line_num
);
1953 /* Copy source line. */
1956 retval
= fgets (string
, STRING_SIZE
, source_file
);
1959 fputs (retval
, gcov_file
);
1961 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n');
1964 fputs ("/*EOF*/\n", gcov_file
);
1966 if (flag_all_blocks
)
1972 for (ix
= jx
= 0, block
= line
->u
.blocks
; block
;
1973 block
= block
->chain
)
1975 if (!block
->is_call_return
)
1976 fprintf (gcov_file
, "%9s:%5u-block %2d\n",
1977 !line
->exists
? "-" : !block
->count
? "$$$$$"
1978 : format_gcov (block
->count
, 0, -1),
1981 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1982 jx
+= output_branch_count (gcov_file
, jx
, arc
);
1985 else if (flag_branches
)
1990 for (ix
= 0, arc
= line
->u
.branches
; arc
; arc
= arc
->line_next
)
1991 ix
+= output_branch_count (gcov_file
, ix
, arc
);
1995 /* Handle all remaining source lines. There may be lines after the
1996 last line of code. */
1999 for (; (retval
= fgets (string
, STRING_SIZE
, source_file
)); line_num
++)
2001 fprintf (gcov_file
, "%9s:%5u:%s", "-", line_num
, retval
);
2003 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n')
2005 retval
= fgets (string
, STRING_SIZE
, source_file
);
2008 fputs (retval
, gcov_file
);
2014 fclose (source_file
);