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
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 /* For included files, make the gcov output file name include the name
301 of the input source file. For example, if x.h is included in a.c,
302 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
304 static int flag_long_names
= 0;
306 /* Output count information for every basic block, not merely those
307 that contain line number information. */
309 static int flag_all_blocks
= 0;
311 /* Output summary info for each function. */
313 static int flag_function_summary
= 0;
315 /* Object directory file prefix. This is the directory/file where the
316 graph and data files are looked for, if nonzero. */
318 static char *object_directory
= 0;
320 /* Preserve all pathname components. Needed when object files and
321 source files are in subdirectories. '/' is mangled as '#', '.' is
322 elided and '..' mangled to '^'. */
324 static int flag_preserve_paths
= 0;
326 /* Output the number of times a branch was taken as opposed to the percentage
327 of times it was taken. */
329 static int flag_counts
= 0;
331 /* Forward declarations. */
332 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2
;
333 static int process_args (int, char **);
334 static void print_usage (int) ATTRIBUTE_NORETURN
;
335 static void print_version (void) ATTRIBUTE_NORETURN
;
336 static void process_file (const char *);
337 static void generate_results (const char *);
338 static void create_file_names (const char *);
339 static source_t
*find_source (const char *);
340 static int read_graph_file (void);
341 static int read_count_file (void);
342 static void solve_flow_graph (function_t
*);
343 static void add_branch_counts (coverage_t
*, const arc_t
*);
344 static void add_line_counts (coverage_t
*, function_t
*);
345 static void function_summary (const coverage_t
*, const char *);
346 static const char *format_gcov (gcov_type
, gcov_type
, int);
347 static void accumulate_line_counts (source_t
*);
348 static int output_branch_count (FILE *, int, const arc_t
*);
349 static void output_lines (FILE *, const source_t
*);
350 static char *make_gcov_file_name (const char *, const char *);
351 static void release_structures (void);
352 extern int main (int, char **);
355 main (int argc
, char **argv
)
359 /* Unlock the stdio streams. */
360 unlock_std_streams ();
364 argno
= process_args (argc
, argv
);
368 if (argc
- argno
> 1)
371 for (; argno
!= argc
; argno
++)
372 process_file (argv
[argno
]);
374 generate_results (multiple_files
? NULL
: argv
[argc
- 1]);
376 release_structures ();
382 fnotice (FILE *file
, const char *cmsgid
, ...)
386 va_start (ap
, cmsgid
);
387 vfprintf (file
, _(cmsgid
), ap
);
391 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
392 otherwise the output of --help. */
395 print_usage (int error_p
)
397 FILE *file
= error_p
? stderr
: stdout
;
398 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
400 fnotice (file
, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
401 fnotice (file
, "Print code coverage information.\n\n");
402 fnotice (file
, " -h, --help Print this help, then exit\n");
403 fnotice (file
, " -v, --version Print version number, then exit\n");
404 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
405 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
406 fnotice (file
, " -c, --branch-counts Given counts of branches taken\n\
407 rather than percentages\n");
408 fnotice (file
, " -n, --no-output Do not create an output file\n");
409 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
411 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
412 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
413 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
414 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
415 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
420 /* Print version information and exit. */
425 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
426 fprintf (stdout
, "Copyright %s 2008 Free Software Foundation, Inc.\n",
429 _("This is free software; see the source for copying conditions.\n"
430 "There is NO warranty; not even for MERCHANTABILITY or \n"
431 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
432 exit (SUCCESS_EXIT_CODE
);
435 static const struct option options
[] =
437 { "help", no_argument
, NULL
, 'h' },
438 { "version", no_argument
, NULL
, 'v' },
439 { "all-blocks", no_argument
, NULL
, 'a' },
440 { "branch-probabilities", no_argument
, NULL
, 'b' },
441 { "branch-counts", no_argument
, NULL
, 'c' },
442 { "no-output", no_argument
, NULL
, 'n' },
443 { "long-file-names", no_argument
, NULL
, 'l' },
444 { "function-summaries", no_argument
, NULL
, 'f' },
445 { "preserve-paths", no_argument
, NULL
, 'p' },
446 { "object-directory", required_argument
, NULL
, 'o' },
447 { "object-file", required_argument
, NULL
, 'o' },
448 { "unconditional-branches", no_argument
, NULL
, 'u' },
452 /* Process args, return index to first non-arg. */
455 process_args (int argc
, char **argv
)
459 while ((opt
= getopt_long (argc
, argv
, "abcfhlno:puv", options
, NULL
)) != -1)
473 flag_function_summary
= 1;
477 /* print_usage will exit. */
485 object_directory
= optarg
;
488 flag_preserve_paths
= 1;
491 flag_unconditional
= 1;
495 /* print_version will exit. */
498 /* print_usage will exit. */
505 /* Process a single source file. */
508 process_file (const char *file_name
)
512 function_t
*old_functions
;
514 /* Save and clear the list of current functions. They will be appended
516 old_functions
= functions
;
519 create_file_names (file_name
);
520 if (read_graph_file ())
525 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
529 if (read_count_file ())
532 for (fn_p
= NULL
, fn
= functions
; fn
; fn_p
= fn
, fn
= fn
->next
)
533 solve_flow_graph (fn
);
536 fn_p
->next
= old_functions
;
540 generate_results (const char *file_name
)
545 for (src
= sources
; src
; src
= src
->next
)
546 src
->lines
= XCNEWVEC (line_t
, src
->num_lines
);
547 for (fn
= functions
; fn
; fn
= fn
->next
)
551 memset (&coverage
, 0, sizeof (coverage
));
552 coverage
.name
= fn
->name
;
553 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
554 if (flag_function_summary
)
556 function_summary (&coverage
, "Function");
557 fnotice (stdout
, "\n");
561 for (src
= sources
; src
; src
= src
->next
)
563 accumulate_line_counts (src
);
564 function_summary (&src
->coverage
, "File");
567 char *gcov_file_name
= make_gcov_file_name (file_name
, src
->name
);
568 FILE *gcov_file
= fopen (gcov_file_name
, "w");
572 fnotice (stdout
, "%s:creating '%s'\n",
573 src
->name
, gcov_file_name
);
574 output_lines (gcov_file
, src
);
575 if (ferror (gcov_file
))
576 fnotice (stderr
, "%s:error writing output file '%s'\n",
577 src
->name
, gcov_file_name
);
581 fnotice (stderr
, "%s:could not open output file '%s'\n",
582 src
->name
, gcov_file_name
);
583 free (gcov_file_name
);
585 fnotice (stdout
, "\n");
589 /* Release all memory used. */
592 release_structures (void)
597 while ((src
= sources
))
605 while ((fn
= functions
))
610 functions
= fn
->next
;
611 for (ix
= fn
->num_blocks
, block
= fn
->blocks
; ix
--; block
++)
615 for (arc
= block
->succ
; arc
; arc
= arc_n
)
617 arc_n
= arc
->succ_next
;
626 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
627 is not specified, these are looked for in the current directory,
628 and named from the basename of the FILE_NAME sans extension. If
629 OBJECT_DIRECTORY is specified and is a directory, the files are in
630 that directory, but named from the basename of the FILE_NAME, sans
631 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
632 the object *file*, and the data files are named from that. */
635 create_file_names (const char *file_name
)
639 int length
= strlen (file_name
);
642 /* Free previous file names. */
644 free (bbg_file_name
);
647 da_file_name
= bbg_file_name
= NULL
;
651 if (object_directory
&& object_directory
[0])
655 length
+= strlen (object_directory
) + 2;
656 name
= XNEWVEC (char, length
);
659 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
660 strcat (name
, object_directory
);
661 if (base
&& name
[strlen (name
) - 1] != '/')
666 name
= XNEWVEC (char, length
+ 1);
673 /* Append source file name. */
674 cptr
= strrchr (file_name
, '/');
675 strcat (name
, cptr
? cptr
+ 1 : file_name
);
678 /* Remove the extension. */
679 cptr
= strrchr (name
, '.');
683 length
= strlen (name
);
685 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
686 strcpy (bbg_file_name
, name
);
687 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
689 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
690 strcpy (da_file_name
, name
);
691 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
697 /* Find or create a source file structure for FILE_NAME. Copies
698 FILE_NAME on creation */
701 find_source (const char *file_name
)
707 file_name
= "<unknown>";
709 for (src
= sources
; src
; src
= src
->next
)
710 if (!strcmp (file_name
, src
->name
))
715 src
= XCNEW (source_t
);
716 src
->name
= xstrdup (file_name
);
717 src
->coverage
.name
= src
->name
;
718 src
->index
= source_index
++;
722 if (!stat (file_name
, &status
))
723 src
->file_time
= status
.st_mtime
;
726 if (src
->file_time
> bbg_file_time
)
728 static int info_emitted
;
730 fnotice (stderr
, "%s:source file is newer than graph file '%s'\n",
731 src
->name
, bbg_file_name
);
735 "(the message is only displayed one per source file)\n");
744 /* Read the graph file. Return nonzero on fatal error. */
747 read_graph_file (void)
750 unsigned current_tag
= 0;
751 struct function_info
*fn
= NULL
;
752 function_t
*old_functions_head
= functions
;
753 source_t
*src
= NULL
;
757 if (!gcov_open (bbg_file_name
, 1))
759 fnotice (stderr
, "%s:cannot open graph file\n", bbg_file_name
);
762 bbg_file_time
= gcov_time ();
763 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
765 fnotice (stderr
, "%s:not a gcov graph file\n", bbg_file_name
);
770 version
= gcov_read_unsigned ();
771 if (version
!= GCOV_VERSION
)
775 GCOV_UNSIGNED2STRING (v
, version
);
776 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
778 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
779 bbg_file_name
, v
, e
);
781 bbg_stamp
= gcov_read_unsigned ();
783 while ((tag
= gcov_read_unsigned ()))
785 unsigned length
= gcov_read_unsigned ();
786 gcov_position_t base
= gcov_position ();
788 if (tag
== GCOV_TAG_FUNCTION
)
791 unsigned ident
, checksum
, lineno
;
793 function_t
*probe
, *prev
;
795 ident
= gcov_read_unsigned ();
796 checksum
= gcov_read_unsigned ();
797 function_name
= xstrdup (gcov_read_string ());
798 src
= find_source (gcov_read_string ());
799 lineno
= gcov_read_unsigned ();
801 fn
= XCNEW (function_t
);
802 fn
->name
= function_name
;
804 fn
->checksum
= checksum
;
808 fn
->next
= functions
;
812 if (lineno
>= src
->num_lines
)
813 src
->num_lines
= lineno
+ 1;
814 /* Now insert it into the source file's list of
815 functions. Normally functions will be encountered in
816 ascending order, so a simple scan is quick. */
817 for (probe
= src
->functions
, prev
= NULL
;
818 probe
&& probe
->line
> lineno
;
819 prev
= probe
, probe
= probe
->line_next
)
821 fn
->line_next
= probe
;
823 prev
->line_next
= fn
;
827 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
830 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
831 bbg_file_name
, fn
->name
);
834 unsigned ix
, num_blocks
= GCOV_TAG_BLOCKS_NUM (length
);
835 fn
->num_blocks
= num_blocks
;
837 fn
->blocks
= XCNEWVEC (block_t
, fn
->num_blocks
);
838 for (ix
= 0; ix
!= num_blocks
; ix
++)
839 fn
->blocks
[ix
].flags
= gcov_read_unsigned ();
842 else if (fn
&& tag
== GCOV_TAG_ARCS
)
844 unsigned src
= gcov_read_unsigned ();
845 unsigned num_dests
= GCOV_TAG_ARCS_NUM (length
);
847 if (src
>= fn
->num_blocks
|| fn
->blocks
[src
].succ
)
852 struct arc_info
*arc
;
853 unsigned dest
= gcov_read_unsigned ();
854 unsigned flags
= gcov_read_unsigned ();
856 if (dest
>= fn
->num_blocks
)
860 arc
->dst
= &fn
->blocks
[dest
];
861 arc
->src
= &fn
->blocks
[src
];
864 arc
->count_valid
= 0;
865 arc
->on_tree
= !!(flags
& GCOV_ARC_ON_TREE
);
866 arc
->fake
= !!(flags
& GCOV_ARC_FAKE
);
867 arc
->fall_through
= !!(flags
& GCOV_ARC_FALLTHROUGH
);
869 arc
->succ_next
= fn
->blocks
[src
].succ
;
870 fn
->blocks
[src
].succ
= arc
;
871 fn
->blocks
[src
].num_succ
++;
873 arc
->pred_next
= fn
->blocks
[dest
].pred
;
874 fn
->blocks
[dest
].pred
= arc
;
875 fn
->blocks
[dest
].num_pred
++;
881 /* Exceptional exit from this function, the
882 source block must be a call. */
883 fn
->blocks
[src
].is_call_site
= 1;
884 arc
->is_call_non_return
= 1;
888 /* Non-local return from a callee of this
889 function. The destination block is a catch or
891 arc
->is_nonlocal_return
= 1;
892 fn
->blocks
[dest
].is_nonlocal_return
= 1;
900 else if (fn
&& tag
== GCOV_TAG_LINES
)
902 unsigned blockno
= gcov_read_unsigned ();
903 unsigned *line_nos
= XCNEWVEC (unsigned, length
- 1);
905 if (blockno
>= fn
->num_blocks
|| fn
->blocks
[blockno
].u
.line
.encoding
)
910 unsigned lineno
= gcov_read_unsigned ();
917 line_nos
[ix
++] = src
->index
;
919 line_nos
[ix
++] = lineno
;
920 if (lineno
>= src
->num_lines
)
921 src
->num_lines
= lineno
+ 1;
925 const char *file_name
= gcov_read_string ();
929 src
= find_source (file_name
);
932 line_nos
[ix
++] = src
->index
;
936 fn
->blocks
[blockno
].u
.line
.encoding
= line_nos
;
937 fn
->blocks
[blockno
].u
.line
.num
= ix
;
939 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
944 gcov_sync (base
, length
);
945 if (gcov_is_error ())
948 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
955 /* We built everything backwards, so nreverse them all. */
957 /* Reverse sources. Not strictly necessary, but we'll then process
958 them in the 'expected' order. */
960 source_t
*src
, *src_p
, *src_n
;
962 for (src_p
= NULL
, src
= sources
; src
; src_p
= src
, src
= src_n
)
970 /* Reverse functions. */
972 function_t
*fn
, *fn_p
, *fn_n
;
974 for (fn_p
= old_functions_head
, fn
= functions
;
975 fn
!= old_functions_head
;
976 fn_p
= fn
, fn
= fn_n
)
983 /* Reverse the arcs. */
984 for (ix
= fn
->num_blocks
; ix
--;)
986 arc_t
*arc
, *arc_p
, *arc_n
;
988 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
989 arc_p
= arc
, arc
= arc_n
)
991 arc_n
= arc
->succ_next
;
992 arc
->succ_next
= arc_p
;
994 fn
->blocks
[ix
].succ
= arc_p
;
996 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
997 arc_p
= arc
, arc
= arc_n
)
999 arc_n
= arc
->pred_next
;
1000 arc
->pred_next
= arc_p
;
1002 fn
->blocks
[ix
].pred
= arc_p
;
1010 /* Reads profiles from the count file and attach to each
1011 function. Return nonzero if fatal error. */
1014 read_count_file (void)
1019 function_t
*fn
= NULL
;
1022 if (!gcov_open (da_file_name
, 1))
1024 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1029 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1031 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1036 version
= gcov_read_unsigned ();
1037 if (version
!= GCOV_VERSION
)
1041 GCOV_UNSIGNED2STRING (v
, version
);
1042 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1044 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1045 da_file_name
, v
, e
);
1047 tag
= gcov_read_unsigned ();
1048 if (tag
!= bbg_stamp
)
1050 fnotice (stderr
, "%s:stamp mismatch with graph file\n", da_file_name
);
1054 while ((tag
= gcov_read_unsigned ()))
1056 unsigned length
= gcov_read_unsigned ();
1057 unsigned long base
= gcov_position ();
1059 if (tag
== GCOV_TAG_OBJECT_SUMMARY
)
1060 gcov_read_summary (&object_summary
);
1061 else if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1063 else if (tag
== GCOV_TAG_FUNCTION
)
1065 unsigned ident
= gcov_read_unsigned ();
1066 struct function_info
*fn_n
= functions
;
1068 /* Try to find the function in the list.
1069 To speed up the search, first start from the last function
1071 for (fn
= fn
? fn
->next
: NULL
; ; fn
= fn
->next
)
1075 else if ((fn
= fn_n
))
1079 fnotice (stderr
, "%s:unknown function '%u'\n",
1080 da_file_name
, ident
);
1083 if (fn
->ident
== ident
)
1089 else if (gcov_read_unsigned () != fn
->checksum
)
1092 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1093 da_file_name
, fn
->name
);
1097 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1099 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->num_counts
))
1103 fn
->counts
= XCNEWVEC (gcov_type
, fn
->num_counts
);
1105 for (ix
= 0; ix
!= fn
->num_counts
; ix
++)
1106 fn
->counts
[ix
] += gcov_read_counter ();
1108 gcov_sync (base
, length
);
1109 if ((error
= gcov_is_error ()))
1111 fnotice (stderr
, error
< 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1121 /* Solve the flow graph. Propagate counts from the instrumented arcs
1122 to the blocks and the uninstrumented arcs. */
1125 solve_flow_graph (function_t
*fn
)
1129 gcov_type
*count_ptr
= fn
->counts
;
1131 block_t
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1132 block_t
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1134 if (fn
->num_blocks
< 2)
1135 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1136 bbg_file_name
, fn
->name
);
1139 if (fn
->blocks
[0].num_pred
)
1140 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1141 bbg_file_name
, fn
->name
);
1143 /* We can't deduce the entry block counts from the lack of
1145 fn
->blocks
[0].num_pred
= ~(unsigned)0;
1147 if (fn
->blocks
[fn
->num_blocks
- 1].num_succ
)
1148 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1149 bbg_file_name
, fn
->name
);
1151 /* Likewise, we can't deduce exit block counts from the lack
1152 of its successors. */
1153 fn
->blocks
[fn
->num_blocks
- 1].num_succ
= ~(unsigned)0;
1156 /* Propagate the measured counts, this must be done in the same
1157 order as the code in profile.c */
1158 for (ix
= 0, blk
= fn
->blocks
; ix
!= fn
->num_blocks
; ix
++, blk
++)
1160 block_t
const *prev_dst
= NULL
;
1161 int out_of_order
= 0;
1162 int non_fake_succ
= 0;
1164 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1172 arc
->count
= *count_ptr
++;
1173 arc
->count_valid
= 1;
1175 arc
->dst
->num_pred
--;
1177 if (prev_dst
&& prev_dst
> arc
->dst
)
1179 prev_dst
= arc
->dst
;
1181 if (non_fake_succ
== 1)
1183 /* If there is only one non-fake exit, it is an
1184 unconditional branch. */
1185 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1188 arc
->is_unconditional
= 1;
1189 /* If this block is instrumenting a call, it might be
1190 an artificial block. It is not artificial if it has
1191 a non-fallthrough exit, or the destination of this
1192 arc has more than one entry. Mark the destination
1193 block as a return site, if none of those conditions
1195 if (blk
->is_call_site
&& arc
->fall_through
1196 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1197 arc
->dst
->is_call_return
= 1;
1201 /* Sort the successor arcs into ascending dst order. profile.c
1202 normally produces arcs in the right order, but sometimes with
1203 one or two out of order. We're not using a particularly
1207 arc_t
*start
= blk
->succ
;
1208 unsigned changes
= 1;
1212 arc_t
*arc
, *arc_p
, *arc_n
;
1215 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1217 if (arc
->dst
> arc_n
->dst
)
1221 arc_p
->succ_next
= arc_n
;
1224 arc
->succ_next
= arc_n
->succ_next
;
1225 arc_n
->succ_next
= arc
;
1238 /* Place it on the invalid chain, it will be ignored if that's
1240 blk
->invalid_chain
= 1;
1241 blk
->chain
= invalid_blocks
;
1242 invalid_blocks
= blk
;
1245 while (invalid_blocks
|| valid_blocks
)
1247 while ((blk
= invalid_blocks
))
1249 gcov_type total
= 0;
1252 invalid_blocks
= blk
->chain
;
1253 blk
->invalid_chain
= 0;
1255 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1256 total
+= arc
->count
;
1257 else if (!blk
->num_pred
)
1258 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1259 total
+= arc
->count
;
1264 blk
->count_valid
= 1;
1265 blk
->chain
= valid_blocks
;
1266 blk
->valid_chain
= 1;
1269 while ((blk
= valid_blocks
))
1272 arc_t
*arc
, *inv_arc
;
1274 valid_blocks
= blk
->chain
;
1275 blk
->valid_chain
= 0;
1276 if (blk
->num_succ
== 1)
1282 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1284 total
-= arc
->count
;
1285 if (!arc
->count_valid
)
1289 inv_arc
->count_valid
= 1;
1290 inv_arc
->count
= total
;
1293 if (dst
->count_valid
)
1295 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
1297 dst
->chain
= valid_blocks
;
1298 dst
->valid_chain
= 1;
1304 if (!dst
->num_pred
&& !dst
->invalid_chain
)
1306 dst
->chain
= invalid_blocks
;
1307 dst
->invalid_chain
= 1;
1308 invalid_blocks
= dst
;
1312 if (blk
->num_pred
== 1)
1318 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1320 total
-= arc
->count
;
1321 if (!arc
->count_valid
)
1325 inv_arc
->count_valid
= 1;
1326 inv_arc
->count
= total
;
1329 if (src
->count_valid
)
1331 if (src
->num_succ
== 1 && !src
->valid_chain
)
1333 src
->chain
= valid_blocks
;
1334 src
->valid_chain
= 1;
1340 if (!src
->num_succ
&& !src
->invalid_chain
)
1342 src
->chain
= invalid_blocks
;
1343 src
->invalid_chain
= 1;
1344 invalid_blocks
= src
;
1351 /* If the graph has been correctly solved, every block will have a
1353 for (ix
= 0; ix
< fn
->num_blocks
; ix
++)
1354 if (!fn
->blocks
[ix
].count_valid
)
1356 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
1357 bbg_file_name
, fn
->name
);
1364 /* Increment totals in COVERAGE according to arc ARC. */
1367 add_branch_counts (coverage_t
*coverage
, const arc_t
*arc
)
1369 if (arc
->is_call_non_return
)
1372 if (arc
->src
->count
)
1373 coverage
->calls_executed
++;
1375 else if (!arc
->is_unconditional
)
1377 coverage
->branches
++;
1378 if (arc
->src
->count
)
1379 coverage
->branches_executed
++;
1381 coverage
->branches_taken
++;
1385 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1386 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1387 If DP is zero, no decimal point is printed. Only print 100% when
1388 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1389 format TOP. Return pointer to a static string. */
1392 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
1394 static char buffer
[20];
1398 float ratio
= bottom
? (float)top
/ bottom
: 0;
1400 unsigned limit
= 100;
1403 for (ix
= dp
; ix
--; )
1406 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1407 if (percent
<= 0 && top
)
1409 else if (percent
>= limit
&& top
!= bottom
)
1410 percent
= limit
- 1;
1411 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
1417 buffer
[ix
+1] = buffer
[ix
];
1421 buffer
[ix
+ 1] = '.';
1425 sprintf (buffer
, HOST_WIDEST_INT_PRINT_DEC
, (HOST_WIDEST_INT
)top
);
1431 /* Output summary info for a function. */
1434 function_summary (const coverage_t
*coverage
, const char *title
)
1436 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
1438 if (coverage
->lines
)
1439 fnotice (stdout
, "Lines executed:%s of %d\n",
1440 format_gcov (coverage
->lines_executed
, coverage
->lines
, 2),
1443 fnotice (stdout
, "No executable lines\n");
1447 if (coverage
->branches
)
1449 fnotice (stdout
, "Branches executed:%s of %d\n",
1450 format_gcov (coverage
->branches_executed
,
1451 coverage
->branches
, 2),
1452 coverage
->branches
);
1453 fnotice (stdout
, "Taken at least once:%s of %d\n",
1454 format_gcov (coverage
->branches_taken
,
1455 coverage
->branches
, 2),
1456 coverage
->branches
);
1459 fnotice (stdout
, "No branches\n");
1460 if (coverage
->calls
)
1461 fnotice (stdout
, "Calls executed:%s of %d\n",
1462 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
1465 fnotice (stdout
, "No calls\n");
1469 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1470 affect name generation. With preserve_paths we create a filename
1471 from all path components of the source file, replacing '/' with
1472 '#', without it we simply take the basename component. With
1473 long_output_names we prepend the processed name of the input file
1474 to each output name (except when the current source file is the
1475 input file, so you don't get a double concatenation). The two
1476 components are separated by '##'. Also '.' filename components are
1477 removed and '..' components are renamed to '^'. */
1480 make_gcov_file_name (const char *input_name
, const char *src_name
)
1485 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
1487 name
= XNEWVEC (char, strlen (src_name
) + strlen (input_name
) + 10);
1489 /* Generate the input filename part. */
1490 cptr
= flag_preserve_paths
? NULL
: strrchr (input_name
, '/');
1491 strcat (name
, cptr
? cptr
+ 1 : input_name
);
1492 strcat (name
, "##");
1496 name
= XNEWVEC (char, strlen (src_name
) + 10);
1500 /* Generate the source filename part. */
1501 cptr
= flag_preserve_paths
? NULL
: strrchr (src_name
, '/');
1502 strcat (name
, cptr
? cptr
+ 1 : src_name
);
1504 if (flag_preserve_paths
)
1506 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1509 for (cptr
= name
; (cptr
= strchr ((prev
= cptr
), '/'));)
1513 if (prev
+ 1 == cptr
&& prev
[0] == '.')
1518 else if (prev
+ 2 == cptr
&& prev
[0] == '.' && prev
[1] == '.')
1530 prev
[0] = prev
[shift
];
1536 strcat (name
, ".gcov");
1540 /* Scan through the bb_data for each line in the block, increment
1541 the line number execution count indicated by the execution count of
1542 the appropriate basic block. */
1545 add_line_counts (coverage_t
*coverage
, function_t
*fn
)
1548 line_t
*line
= NULL
; /* This is propagated from one iteration to the
1551 /* Scan each basic block. */
1552 for (ix
= 0; ix
!= fn
->num_blocks
; ix
++)
1554 block_t
*block
= &fn
->blocks
[ix
];
1556 const source_t
*src
= NULL
;
1559 if (block
->count
&& ix
&& ix
+ 1 != fn
->num_blocks
)
1560 fn
->blocks_executed
++;
1561 for (jx
= 0, encoding
= block
->u
.line
.encoding
;
1562 jx
!= block
->u
.line
.num
; jx
++, encoding
++)
1565 unsigned src_n
= *++encoding
;
1567 for (src
= sources
; src
->index
!= src_n
; src
= src
->next
)
1573 line
= &src
->lines
[*encoding
];
1579 if (!line
->count
&& block
->count
)
1580 coverage
->lines_executed
++;
1583 line
->count
+= block
->count
;
1585 free (block
->u
.line
.encoding
);
1586 block
->u
.cycle
.arc
= NULL
;
1587 block
->u
.cycle
.ident
= ~0U;
1589 if (!ix
|| ix
+ 1 == fn
->num_blocks
)
1590 /* Entry or exit block */;
1591 else if (flag_all_blocks
)
1593 line_t
*block_line
= line
? line
: &fn
->src
->lines
[fn
->line
];
1595 block
->chain
= block_line
->u
.blocks
;
1596 block_line
->u
.blocks
= block
;
1598 else if (flag_branches
)
1602 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1604 arc
->line_next
= line
->u
.branches
;
1605 line
->u
.branches
= arc
;
1606 if (coverage
&& !arc
->is_unconditional
)
1607 add_branch_counts (coverage
, arc
);
1612 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
1615 /* Accumulate the line counts of a file. */
1618 accumulate_line_counts (source_t
*src
)
1621 function_t
*fn
, *fn_p
, *fn_n
;
1624 /* Reverse the function order. */
1625 for (fn
= src
->functions
, fn_p
= NULL
; fn
;
1626 fn_p
= fn
, fn
= fn_n
)
1628 fn_n
= fn
->line_next
;
1629 fn
->line_next
= fn_p
;
1631 src
->functions
= fn_p
;
1633 for (ix
= src
->num_lines
, line
= src
->lines
; ix
--; line
++)
1635 if (!flag_all_blocks
)
1637 arc_t
*arc
, *arc_p
, *arc_n
;
1639 /* Total and reverse the branch information. */
1640 for (arc
= line
->u
.branches
, arc_p
= NULL
; arc
;
1641 arc_p
= arc
, arc
= arc_n
)
1643 arc_n
= arc
->line_next
;
1644 arc
->line_next
= arc_p
;
1646 add_branch_counts (&src
->coverage
, arc
);
1648 line
->u
.branches
= arc_p
;
1650 else if (line
->u
.blocks
)
1652 /* The user expects the line count to be the number of times
1653 a line has been executed. Simply summing the block count
1654 will give an artificially high number. The Right Thing
1655 is to sum the entry counts to the graph of blocks on this
1656 line, then find the elementary cycles of the local graph
1657 and add the transition counts of those cycles. */
1658 block_t
*block
, *block_p
, *block_n
;
1659 gcov_type count
= 0;
1661 /* Reverse the block information. */
1662 for (block
= line
->u
.blocks
, block_p
= NULL
; block
;
1663 block_p
= block
, block
= block_n
)
1665 block_n
= block
->chain
;
1666 block
->chain
= block_p
;
1667 block
->u
.cycle
.ident
= ix
;
1669 line
->u
.blocks
= block_p
;
1671 /* Sum the entry arcs. */
1672 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1676 for (arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
1678 if (arc
->src
->u
.cycle
.ident
!= ix
)
1679 count
+= arc
->count
;
1681 add_branch_counts (&src
->coverage
, arc
);
1684 /* Initialize the cs_count. */
1685 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1686 arc
->cs_count
= arc
->count
;
1689 /* Find the loops. This uses the algorithm described in
1690 Tiernan 'An Efficient Search Algorithm to Find the
1691 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1692 the P array by having each block point to the arc that
1693 connects to the previous block. The H array is implicitly
1694 held because of the arc ordering, and the block's
1695 previous arc pointer.
1697 Although the algorithm is O(N^3) for highly connected
1698 graphs, at worst we'll have O(N^2), as most blocks have
1699 only one or two exits. Most graphs will be small.
1701 For each loop we find, locate the arc with the smallest
1702 transition count, and add that to the cumulative
1703 count. Decrease flow over the cycle and remove the arc
1704 from consideration. */
1705 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1707 block_t
*head
= block
;
1715 block_t
*dst
= arc
->dst
;
1716 if (/* Already used that arc. */
1718 /* Not to same graph, or before first vertex. */
1719 || dst
->u
.cycle
.ident
!= ix
1720 /* Already in path. */
1721 || dst
->u
.cycle
.arc
)
1723 arc
= arc
->succ_next
;
1729 /* Found a closing arc. */
1730 gcov_type cycle_count
= arc
->cs_count
;
1731 arc_t
*cycle_arc
= arc
;
1734 /* Locate the smallest arc count of the loop. */
1735 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1736 dst
= probe_arc
->src
)
1737 if (cycle_count
> probe_arc
->cs_count
)
1739 cycle_count
= probe_arc
->cs_count
;
1740 cycle_arc
= probe_arc
;
1743 count
+= cycle_count
;
1744 cycle_arc
->cycle
= 1;
1746 /* Remove the flow from the cycle. */
1747 arc
->cs_count
-= cycle_count
;
1748 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1749 dst
= probe_arc
->src
)
1750 probe_arc
->cs_count
-= cycle_count
;
1752 /* Unwind to the cyclic arc. */
1753 while (head
!= cycle_arc
->src
)
1755 arc
= head
->u
.cycle
.arc
;
1756 head
->u
.cycle
.arc
= NULL
;
1760 arc
= arc
->succ_next
;
1764 /* Add new block to chain. */
1765 dst
->u
.cycle
.arc
= arc
;
1769 /* We could not add another vertex to the path. Remove
1770 the last vertex from the list. */
1771 arc
= head
->u
.cycle
.arc
;
1774 /* It was not the first vertex. Move onto next arc. */
1775 head
->u
.cycle
.arc
= NULL
;
1777 arc
= arc
->succ_next
;
1778 goto current_vertex
;
1780 /* Mark this block as unusable. */
1781 block
->u
.cycle
.ident
= ~0U;
1784 line
->count
= count
;
1789 src
->coverage
.lines
++;
1791 src
->coverage
.lines_executed
++;
1796 /* Output information about ARC number IX. Returns nonzero if
1797 anything is output. */
1800 output_branch_count (FILE *gcov_file
, int ix
, const arc_t
*arc
)
1803 if (arc
->is_call_non_return
)
1805 if (arc
->src
->count
)
1807 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
1808 format_gcov (arc
->src
->count
- arc
->count
,
1809 arc
->src
->count
, -flag_counts
));
1812 fnotice (gcov_file
, "call %2d never executed\n", ix
);
1814 else if (!arc
->is_unconditional
)
1816 if (arc
->src
->count
)
1817 fnotice (gcov_file
, "branch %2d taken %s%s\n", ix
,
1818 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
1819 arc
->fall_through
? " (fallthrough)" : "");
1821 fnotice (gcov_file
, "branch %2d never executed\n", ix
);
1823 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
1825 if (arc
->src
->count
)
1826 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
1827 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
1829 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
1837 /* Read in the source file one line at a time, and output that line to
1838 the gcov file preceded by its execution count and other
1842 output_lines (FILE *gcov_file
, const source_t
*src
)
1845 unsigned line_num
; /* current line number. */
1846 const line_t
*line
; /* current line info ptr. */
1847 char string
[STRING_SIZE
]; /* line buffer. */
1848 char const *retval
= ""; /* status of source file reading. */
1849 function_t
*fn
= NULL
;
1851 fprintf (gcov_file
, "%9s:%5d:Source:%s\n", "-", 0, src
->name
);
1852 if (!multiple_files
)
1854 fprintf (gcov_file
, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name
);
1855 fprintf (gcov_file
, "%9s:%5d:Data:%s\n", "-", 0,
1856 no_data_file
? "-" : da_file_name
);
1857 fprintf (gcov_file
, "%9s:%5d:Runs:%u\n", "-", 0,
1858 object_summary
.ctrs
[GCOV_COUNTER_ARCS
].runs
);
1860 fprintf (gcov_file
, "%9s:%5d:Programs:%u\n", "-", 0, program_count
);
1862 source_file
= fopen (src
->name
, "r");
1865 fnotice (stderr
, "%s:cannot open source file\n", src
->name
);
1868 else if (src
->file_time
== 0)
1869 fprintf (gcov_file
, "%9s:%5d:Source is newer than graph\n", "-", 0);
1872 fn
= src
->functions
;
1874 for (line_num
= 1, line
= &src
->lines
[line_num
];
1875 line_num
< src
->num_lines
; line_num
++, line
++)
1877 for (; fn
&& fn
->line
== line_num
; fn
= fn
->line_next
)
1879 arc_t
*arc
= fn
->blocks
[fn
->num_blocks
- 1].pred
;
1880 gcov_type return_count
= fn
->blocks
[fn
->num_blocks
- 1].count
;
1882 for (; arc
; arc
= arc
->pred_next
)
1884 return_count
-= arc
->count
;
1886 fprintf (gcov_file
, "function %s", fn
->name
);
1887 fprintf (gcov_file
, " called %s",
1888 format_gcov (fn
->blocks
[0].count
, 0, -1));
1889 fprintf (gcov_file
, " returned %s",
1890 format_gcov (return_count
, fn
->blocks
[0].count
, 0));
1891 fprintf (gcov_file
, " blocks executed %s",
1892 format_gcov (fn
->blocks_executed
, fn
->num_blocks
- 2, 0));
1893 fprintf (gcov_file
, "\n");
1896 /* For lines which don't exist in the .bb file, print '-' before
1897 the source line. For lines which exist but were never
1898 executed, print '#####' before the source line. Otherwise,
1899 print the execution count before the source line. There are
1900 16 spaces of indentation added before the source line so that
1901 tabs won't be messed up. */
1902 fprintf (gcov_file
, "%9s:%5u:",
1903 !line
->exists
? "-" : !line
->count
? "#####"
1904 : format_gcov (line
->count
, 0, -1), line_num
);
1908 /* Copy source line. */
1911 retval
= fgets (string
, STRING_SIZE
, source_file
);
1914 fputs (retval
, gcov_file
);
1916 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n');
1919 fputs ("/*EOF*/\n", gcov_file
);
1921 if (flag_all_blocks
)
1927 for (ix
= jx
= 0, block
= line
->u
.blocks
; block
;
1928 block
= block
->chain
)
1930 if (!block
->is_call_return
)
1931 fprintf (gcov_file
, "%9s:%5u-block %2d\n",
1932 !line
->exists
? "-" : !block
->count
? "$$$$$"
1933 : format_gcov (block
->count
, 0, -1),
1936 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1937 jx
+= output_branch_count (gcov_file
, jx
, arc
);
1940 else if (flag_branches
)
1945 for (ix
= 0, arc
= line
->u
.branches
; arc
; arc
= arc
->line_next
)
1946 ix
+= output_branch_count (gcov_file
, ix
, arc
);
1950 /* Handle all remaining source lines. There may be lines after the
1951 last line of code. */
1954 for (; (retval
= fgets (string
, STRING_SIZE
, source_file
)); line_num
++)
1956 fprintf (gcov_file
, "%9s:%5u:%s", "-", line_num
, retval
);
1958 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n')
1960 retval
= fgets (string
, STRING_SIZE
, source_file
);
1963 fputs (retval
, gcov_file
);
1969 fclose (source_file
);