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 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 3, or (at your option)
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 COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* ??? Print a list of the ten blocks with the highest execution counts,
24 and list the line numbers corresponding to those blocks. Also, perhaps
25 list the line numbers with the highest execution counts, only printing
26 the first if there are several which are all listed in the same block. */
28 /* ??? Should have an option to print the number of basic blocks, and the
29 percent of them that are covered. */
31 /* Need an option to show individual block counts, and show
32 probabilities of fall through arcs. */
36 #include "coretypes.h"
47 /* The gcno file is generated by -ftest-coverage option. The gcda file is
48 generated by a program compiled with -fprofile-arcs. Their formats
49 are documented in gcov-io.h. */
51 /* The functions in this file for creating and solution program flow graphs
52 are very similar to functions in the gcc source file profile.c. In
53 some places we make use of the knowledge of how profile.c works to
54 select particular algorithms here. */
56 /* This is the size of the buffer used to read in source file lines. */
58 #define STRING_SIZE 200
64 /* Describes an arc between two basic blocks. */
66 typedef struct arc_info
68 /* source and destination blocks. */
69 struct block_info
*src
;
70 struct block_info
*dst
;
72 /* transition counts. */
74 /* used in cycle search, so that we do not clobber original counts. */
77 unsigned int count_valid
: 1;
78 unsigned int on_tree
: 1;
79 unsigned int fake
: 1;
80 unsigned int fall_through
: 1;
82 /* Arc is for a function that abnormally returns. */
83 unsigned int is_call_non_return
: 1;
85 /* Arc is for catch/setjump. */
86 unsigned int is_nonlocal_return
: 1;
88 /* Is an unconditional branch. */
89 unsigned int is_unconditional
: 1;
91 /* Loop making arc. */
92 unsigned int cycle
: 1;
94 /* Next branch on line. */
95 struct arc_info
*line_next
;
97 /* Links to next arc on src and dst lists. */
98 struct arc_info
*succ_next
;
99 struct arc_info
*pred_next
;
102 /* Describes a basic block. Contains lists of arcs to successor and
103 predecessor blocks. */
105 typedef struct block_info
107 /* Chain of exit and entry arcs. */
111 /* Number of unprocessed exit and entry arcs. */
115 /* Block execution count. */
118 unsigned count_valid
: 1;
119 unsigned valid_chain
: 1;
120 unsigned invalid_chain
: 1;
122 /* Block is a call instrumenting site. */
123 unsigned is_call_site
: 1; /* Does the call. */
124 unsigned is_call_return
: 1; /* Is the return. */
126 /* Block is a landing pad for longjmp or throw. */
127 unsigned is_nonlocal_return
: 1;
133 /* Array of line numbers and source files. source files are
134 introduced by a linenumber of zero, the next 'line number' is
135 the number of the source file. Always starts with a source
139 } line
; /* Valid until blocks are linked onto lines */
142 /* Single line graph cycle workspace. Used for all-blocks
146 } cycle
; /* Used in all-blocks mode, after blocks are linked onto
150 /* Temporary chain for solving graph, and for chaining blocks on one
152 struct block_info
*chain
;
156 /* Describes a single function. Contains an array of basic blocks. */
158 typedef struct function_info
160 /* Name of function. */
165 /* Array of basic blocks. */
168 unsigned blocks_executed
;
170 /* Raw arc coverage counts. */
174 /* First line number. */
176 struct source_info
*src
;
178 /* Next function in same source file. */
179 struct function_info
*line_next
;
182 struct function_info
*next
;
185 /* Describes coverage of a file or function. */
187 typedef struct coverage_info
193 int branches_executed
;
202 /* Describes a single line of source. Contains a chain of basic blocks
205 typedef struct line_info
207 gcov_type count
; /* execution count */
210 arc_t
*branches
; /* branches from blocks that end on this
211 line. Used for branch-counts when not
213 block_t
*blocks
; /* blocks which start on this line. Used
214 in all-blocks mode. */
219 /* Describes a file mentioned in the block graph. Contains an array
222 typedef struct source_info
224 /* Name of source file. */
229 /* Array of line information. */
235 /* Functions in this source file. These are in ascending line
237 function_t
*functions
;
239 /* Next source file. */
240 struct source_info
*next
;
243 /* Holds a list of function basic block graphs. */
245 static function_t
*functions
;
247 /* This points to the head of the sourcefile structure list. New elements
248 are always prepended. */
250 static source_t
*sources
;
252 /* Next index for a source file. */
254 static unsigned source_index
;
256 /* This holds data summary information. */
258 static struct gcov_summary object_summary
;
259 static unsigned program_count
;
261 /* Modification time of graph file. */
263 static time_t bbg_file_time
;
265 /* Name and file pointer of the input file for the basic block graph. */
267 static char *bbg_file_name
;
269 /* Stamp of the bbg file */
270 static unsigned bbg_stamp
;
272 /* Name and file pointer of the input file for the arc count data. */
274 static char *da_file_name
;
276 /* Data file is missing. */
278 static int no_data_file
;
280 /* If there is several input files, compute and display results after
281 reading all data files. This way if two or more gcda file refer to
282 the same source file (eg inline subprograms in a .h file), the
285 static int multiple_files
= 0;
287 /* Output branch probabilities. */
289 static int flag_branches
= 0;
291 /* Show unconditional branches too. */
292 static int flag_unconditional
= 0;
294 /* Output a gcov file if this is true. This is on by default, and can
295 be turned off by the -n option. */
297 static int flag_gcov_file
= 1;
299 /* For included files, make the gcov output file name include the name
300 of the input source file. For example, if x.h is included in a.c,
301 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
303 static int flag_long_names
= 0;
305 /* Output count information for every basic block, not merely those
306 that contain line number information. */
308 static int flag_all_blocks
= 0;
310 /* Output summary info for each function. */
312 static int flag_function_summary
= 0;
314 /* Object directory file prefix. This is the directory/file where the
315 graph and data files are looked for, if nonzero. */
317 static char *object_directory
= 0;
319 /* Preserve all pathname components. Needed when object files and
320 source files are in subdirectories. '/' is mangled as '#', '.' is
321 elided and '..' mangled to '^'. */
323 static int flag_preserve_paths
= 0;
325 /* Output the number of times a branch was taken as opposed to the percentage
326 of times it was taken. */
328 static int flag_counts
= 0;
330 /* Forward declarations. */
331 static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2
;
332 static int process_args (int, char **);
333 static void print_usage (int) ATTRIBUTE_NORETURN
;
334 static void print_version (void) ATTRIBUTE_NORETURN
;
335 static void process_file (const char *);
336 static void generate_results (const char *);
337 static void create_file_names (const char *);
338 static source_t
*find_source (const char *);
339 static int read_graph_file (void);
340 static int read_count_file (void);
341 static void solve_flow_graph (function_t
*);
342 static void add_branch_counts (coverage_t
*, const arc_t
*);
343 static void add_line_counts (coverage_t
*, function_t
*);
344 static void function_summary (const coverage_t
*, const char *);
345 static const char *format_gcov (gcov_type
, gcov_type
, int);
346 static void accumulate_line_counts (source_t
*);
347 static int output_branch_count (FILE *, int, const arc_t
*);
348 static void output_lines (FILE *, const source_t
*);
349 static char *make_gcov_file_name (const char *, const char *);
350 static void release_structures (void);
351 extern int main (int, char **);
354 main (int argc
, char **argv
)
358 /* Unlock the stdio streams. */
359 unlock_std_streams ();
363 argno
= process_args (argc
, argv
);
367 if (argc
- argno
> 1)
370 for (; argno
!= argc
; argno
++)
371 process_file (argv
[argno
]);
373 generate_results (multiple_files
? NULL
: argv
[argc
- 1]);
375 release_structures ();
381 fnotice (FILE *file
, const char *cmsgid
, ...)
385 va_start (ap
, cmsgid
);
386 vfprintf (file
, _(cmsgid
), ap
);
390 /* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
391 otherwise the output of --help. */
394 print_usage (int error_p
)
396 FILE *file
= error_p
? stderr
: stdout
;
397 int status
= error_p
? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
;
399 fnotice (file
, "Usage: gcov [OPTION]... SOURCEFILE...\n\n");
400 fnotice (file
, "Print code coverage information.\n\n");
401 fnotice (file
, " -h, --help Print this help, then exit\n");
402 fnotice (file
, " -v, --version Print version number, then exit\n");
403 fnotice (file
, " -a, --all-blocks Show information for every basic block\n");
404 fnotice (file
, " -b, --branch-probabilities Include branch probabilities in output\n");
405 fnotice (file
, " -c, --branch-counts Given counts of branches taken\n\
406 rather than percentages\n");
407 fnotice (file
, " -n, --no-output Do not create an output file\n");
408 fnotice (file
, " -l, --long-file-names Use long output file names for included\n\
410 fnotice (file
, " -f, --function-summaries Output summaries for each function\n");
411 fnotice (file
, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
412 fnotice (file
, " -p, --preserve-paths Preserve all pathname components\n");
413 fnotice (file
, " -u, --unconditional-branches Show unconditional branch counts too\n");
414 fnotice (file
, "\nFor bug reporting instructions, please see:\n%s.\n",
419 /* Print version information and exit. */
424 fnotice (stdout
, "gcov %s%s\n", pkgversion_string
, version_string
);
425 fprintf (stdout
, "Copyright %s 2007 Free Software Foundation, Inc.\n",
428 _("This is free software; see the source for copying conditions.\n"
429 "There is NO warranty; not even for MERCHANTABILITY or \n"
430 "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' },
451 /* Process args, return index to first non-arg. */
454 process_args (int argc
, char **argv
)
458 while ((opt
= getopt_long (argc
, argv
, "abcfhlno:puv", options
, NULL
)) != -1)
472 flag_function_summary
= 1;
476 /* print_usage will exit. */
484 object_directory
= optarg
;
487 flag_preserve_paths
= 1;
490 flag_unconditional
= 1;
494 /* print_version will exit. */
497 /* print_usage will exit. */
504 /* Process a single source file. */
507 process_file (const char *file_name
)
511 function_t
*old_functions
;
513 /* Save and clear the list of current functions. They will be appended
515 old_functions
= functions
;
518 create_file_names (file_name
);
519 if (read_graph_file ())
524 fnotice (stderr
, "%s:no functions found\n", bbg_file_name
);
528 if (read_count_file ())
531 for (fn_p
= NULL
, fn
= functions
; fn
; fn_p
= fn
, fn
= fn
->next
)
532 solve_flow_graph (fn
);
535 fn_p
->next
= old_functions
;
539 generate_results (const char *file_name
)
544 for (src
= sources
; src
; src
= src
->next
)
545 src
->lines
= XCNEWVEC (line_t
, src
->num_lines
);
546 for (fn
= functions
; fn
; fn
= fn
->next
)
550 memset (&coverage
, 0, sizeof (coverage
));
551 coverage
.name
= fn
->name
;
552 add_line_counts (flag_function_summary
? &coverage
: NULL
, fn
);
553 if (flag_function_summary
)
555 function_summary (&coverage
, "Function");
556 fnotice (stdout
, "\n");
560 for (src
= sources
; src
; src
= src
->next
)
562 accumulate_line_counts (src
);
563 function_summary (&src
->coverage
, "File");
566 char *gcov_file_name
= make_gcov_file_name (file_name
, src
->name
);
567 FILE *gcov_file
= fopen (gcov_file_name
, "w");
571 fnotice (stdout
, "%s:creating '%s'\n",
572 src
->name
, gcov_file_name
);
573 output_lines (gcov_file
, src
);
574 if (ferror (gcov_file
))
575 fnotice (stderr
, "%s:error writing output file '%s'\n",
576 src
->name
, gcov_file_name
);
580 fnotice (stderr
, "%s:could not open output file '%s'\n",
581 src
->name
, gcov_file_name
);
582 free (gcov_file_name
);
584 fnotice (stdout
, "\n");
588 /* Release all memory used. */
591 release_structures (void)
596 while ((src
= sources
))
604 while ((fn
= functions
))
609 functions
= fn
->next
;
610 for (ix
= fn
->num_blocks
, block
= fn
->blocks
; ix
--; block
++)
614 for (arc
= block
->succ
; arc
; arc
= arc_n
)
616 arc_n
= arc
->succ_next
;
625 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
626 is not specified, these are looked for in the current directory,
627 and named from the basename of the FILE_NAME sans extension. If
628 OBJECT_DIRECTORY is specified and is a directory, the files are in
629 that directory, but named from the basename of the FILE_NAME, sans
630 extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
631 the object *file*, and the data files are named from that. */
634 create_file_names (const char *file_name
)
638 int length
= strlen (file_name
);
641 /* Free previous file names. */
643 free (bbg_file_name
);
646 da_file_name
= bbg_file_name
= NULL
;
650 if (object_directory
&& object_directory
[0])
654 length
+= strlen (object_directory
) + 2;
655 name
= XNEWVEC (char, length
);
658 base
= !stat (object_directory
, &status
) && S_ISDIR (status
.st_mode
);
659 strcat (name
, object_directory
);
660 if (base
&& name
[strlen (name
) - 1] != '/')
665 name
= XNEWVEC (char, length
+ 1);
672 /* Append source file name. */
673 cptr
= strrchr (file_name
, '/');
674 strcat (name
, cptr
? cptr
+ 1 : file_name
);
677 /* Remove the extension. */
678 cptr
= strrchr (name
, '.');
682 length
= strlen (name
);
684 bbg_file_name
= XNEWVEC (char, length
+ strlen (GCOV_NOTE_SUFFIX
) + 1);
685 strcpy (bbg_file_name
, name
);
686 strcpy (bbg_file_name
+ length
, GCOV_NOTE_SUFFIX
);
688 da_file_name
= XNEWVEC (char, length
+ strlen (GCOV_DATA_SUFFIX
) + 1);
689 strcpy (da_file_name
, name
);
690 strcpy (da_file_name
+ length
, GCOV_DATA_SUFFIX
);
696 /* Find or create a source file structure for FILE_NAME. Copies
697 FILE_NAME on creation */
700 find_source (const char *file_name
)
706 file_name
= "<unknown>";
708 for (src
= sources
; src
; src
= src
->next
)
709 if (!strcmp (file_name
, src
->name
))
714 src
= XCNEW (source_t
);
715 src
->name
= xstrdup (file_name
);
716 src
->coverage
.name
= src
->name
;
717 src
->index
= source_index
++;
721 if (!stat (file_name
, &status
))
722 src
->file_time
= status
.st_mtime
;
725 if (src
->file_time
> bbg_file_time
)
727 static int info_emitted
;
729 fnotice (stderr
, "%s:source file is newer than graph file '%s'\n",
730 src
->name
, bbg_file_name
);
734 "(the message is only displayed one per source file)\n");
743 /* Read the graph file. Return nonzero on fatal error. */
746 read_graph_file (void)
749 unsigned current_tag
= 0;
750 struct function_info
*fn
= NULL
;
751 function_t
*old_functions_head
= functions
;
752 source_t
*src
= NULL
;
756 if (!gcov_open (bbg_file_name
, 1))
758 fnotice (stderr
, "%s:cannot open graph file\n", bbg_file_name
);
761 bbg_file_time
= gcov_time ();
762 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC
))
764 fnotice (stderr
, "%s:not a gcov graph file\n", bbg_file_name
);
769 version
= gcov_read_unsigned ();
770 if (version
!= GCOV_VERSION
)
774 GCOV_UNSIGNED2STRING (v
, version
);
775 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
777 fnotice (stderr
, "%s:version '%.4s', prefer '%.4s'\n",
778 bbg_file_name
, v
, e
);
780 bbg_stamp
= gcov_read_unsigned ();
782 while ((tag
= gcov_read_unsigned ()))
784 unsigned length
= gcov_read_unsigned ();
785 gcov_position_t base
= gcov_position ();
787 if (tag
== GCOV_TAG_FUNCTION
)
790 unsigned ident
, checksum
, lineno
;
792 function_t
*probe
, *prev
;
794 ident
= gcov_read_unsigned ();
795 checksum
= gcov_read_unsigned ();
796 function_name
= xstrdup (gcov_read_string ());
797 src
= find_source (gcov_read_string ());
798 lineno
= gcov_read_unsigned ();
800 fn
= XCNEW (function_t
);
801 fn
->name
= function_name
;
803 fn
->checksum
= checksum
;
807 fn
->next
= functions
;
811 if (lineno
>= src
->num_lines
)
812 src
->num_lines
= lineno
+ 1;
813 /* Now insert it into the source file's list of
814 functions. Normally functions will be encountered in
815 ascending order, so a simple scan is quick. */
816 for (probe
= src
->functions
, prev
= NULL
;
817 probe
&& probe
->line
> lineno
;
818 prev
= probe
, probe
= probe
->line_next
)
820 fn
->line_next
= probe
;
822 prev
->line_next
= fn
;
826 else if (fn
&& tag
== GCOV_TAG_BLOCKS
)
829 fnotice (stderr
, "%s:already seen blocks for '%s'\n",
830 bbg_file_name
, fn
->name
);
833 unsigned ix
, num_blocks
= GCOV_TAG_BLOCKS_NUM (length
);
834 fn
->num_blocks
= num_blocks
;
836 fn
->blocks
= XCNEWVEC (block_t
, fn
->num_blocks
);
837 for (ix
= 0; ix
!= num_blocks
; ix
++)
838 fn
->blocks
[ix
].flags
= gcov_read_unsigned ();
841 else if (fn
&& tag
== GCOV_TAG_ARCS
)
843 unsigned src
= gcov_read_unsigned ();
844 unsigned num_dests
= GCOV_TAG_ARCS_NUM (length
);
846 if (src
>= fn
->num_blocks
|| fn
->blocks
[src
].succ
)
851 struct arc_info
*arc
;
852 unsigned dest
= gcov_read_unsigned ();
853 unsigned flags
= gcov_read_unsigned ();
855 if (dest
>= fn
->num_blocks
)
859 arc
->dst
= &fn
->blocks
[dest
];
860 arc
->src
= &fn
->blocks
[src
];
863 arc
->count_valid
= 0;
864 arc
->on_tree
= !!(flags
& GCOV_ARC_ON_TREE
);
865 arc
->fake
= !!(flags
& GCOV_ARC_FAKE
);
866 arc
->fall_through
= !!(flags
& GCOV_ARC_FALLTHROUGH
);
868 arc
->succ_next
= fn
->blocks
[src
].succ
;
869 fn
->blocks
[src
].succ
= arc
;
870 fn
->blocks
[src
].num_succ
++;
872 arc
->pred_next
= fn
->blocks
[dest
].pred
;
873 fn
->blocks
[dest
].pred
= arc
;
874 fn
->blocks
[dest
].num_pred
++;
880 /* Exceptional exit from this function, the
881 source block must be a call. */
882 fn
->blocks
[src
].is_call_site
= 1;
883 arc
->is_call_non_return
= 1;
887 /* Non-local return from a callee of this
888 function. The destination block is a catch or
890 arc
->is_nonlocal_return
= 1;
891 fn
->blocks
[dest
].is_nonlocal_return
= 1;
899 else if (fn
&& tag
== GCOV_TAG_LINES
)
901 unsigned blockno
= gcov_read_unsigned ();
902 unsigned *line_nos
= XCNEWVEC (unsigned, length
- 1);
904 if (blockno
>= fn
->num_blocks
|| fn
->blocks
[blockno
].u
.line
.encoding
)
909 unsigned lineno
= gcov_read_unsigned ();
916 line_nos
[ix
++] = src
->index
;
918 line_nos
[ix
++] = lineno
;
919 if (lineno
>= src
->num_lines
)
920 src
->num_lines
= lineno
+ 1;
924 const char *file_name
= gcov_read_string ();
928 src
= find_source (file_name
);
931 line_nos
[ix
++] = src
->index
;
935 fn
->blocks
[blockno
].u
.line
.encoding
= line_nos
;
936 fn
->blocks
[blockno
].u
.line
.num
= ix
;
938 else if (current_tag
&& !GCOV_TAG_IS_SUBTAG (current_tag
, tag
))
943 gcov_sync (base
, length
);
944 if (gcov_is_error ())
947 fnotice (stderr
, "%s:corrupted\n", bbg_file_name
);
954 /* We built everything backwards, so nreverse them all. */
956 /* Reverse sources. Not strictly necessary, but we'll then process
957 them in the 'expected' order. */
959 source_t
*src
, *src_p
, *src_n
;
961 for (src_p
= NULL
, src
= sources
; src
; src_p
= src
, src
= src_n
)
969 /* Reverse functions. */
971 function_t
*fn
, *fn_p
, *fn_n
;
973 for (fn_p
= old_functions_head
, fn
= functions
;
974 fn
!= old_functions_head
;
975 fn_p
= fn
, fn
= fn_n
)
982 /* Reverse the arcs. */
983 for (ix
= fn
->num_blocks
; ix
--;)
985 arc_t
*arc
, *arc_p
, *arc_n
;
987 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].succ
; arc
;
988 arc_p
= arc
, arc
= arc_n
)
990 arc_n
= arc
->succ_next
;
991 arc
->succ_next
= arc_p
;
993 fn
->blocks
[ix
].succ
= arc_p
;
995 for (arc_p
= NULL
, arc
= fn
->blocks
[ix
].pred
; arc
;
996 arc_p
= arc
, arc
= arc_n
)
998 arc_n
= arc
->pred_next
;
999 arc
->pred_next
= arc_p
;
1001 fn
->blocks
[ix
].pred
= arc_p
;
1009 /* Reads profiles from the count file and attach to each
1010 function. Return nonzero if fatal error. */
1013 read_count_file (void)
1018 function_t
*fn
= NULL
;
1021 if (!gcov_open (da_file_name
, 1))
1023 fnotice (stderr
, "%s:cannot open data file, assuming not executed\n",
1028 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC
))
1030 fnotice (stderr
, "%s:not a gcov data file\n", da_file_name
);
1035 version
= gcov_read_unsigned ();
1036 if (version
!= GCOV_VERSION
)
1040 GCOV_UNSIGNED2STRING (v
, version
);
1041 GCOV_UNSIGNED2STRING (e
, GCOV_VERSION
);
1043 fnotice (stderr
, "%s:version '%.4s', prefer version '%.4s'\n",
1044 da_file_name
, v
, e
);
1046 tag
= gcov_read_unsigned ();
1047 if (tag
!= bbg_stamp
)
1049 fnotice (stderr
, "%s:stamp mismatch with graph file\n", da_file_name
);
1053 while ((tag
= gcov_read_unsigned ()))
1055 unsigned length
= gcov_read_unsigned ();
1056 unsigned long base
= gcov_position ();
1058 if (tag
== GCOV_TAG_OBJECT_SUMMARY
)
1059 gcov_read_summary (&object_summary
);
1060 else if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
1062 else if (tag
== GCOV_TAG_FUNCTION
)
1064 unsigned ident
= gcov_read_unsigned ();
1065 struct function_info
*fn_n
= functions
;
1067 /* Try to find the function in the list.
1068 To speed up the search, first start from the last function
1070 for (fn
= fn
? fn
->next
: NULL
; ; fn
= fn
->next
)
1074 else if ((fn
= fn_n
))
1078 fnotice (stderr
, "%s:unknown function '%u'\n",
1079 da_file_name
, ident
);
1082 if (fn
->ident
== ident
)
1088 else if (gcov_read_unsigned () != fn
->checksum
)
1091 fnotice (stderr
, "%s:profile mismatch for '%s'\n",
1092 da_file_name
, fn
->name
);
1096 else if (tag
== GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS
) && fn
)
1098 if (length
!= GCOV_TAG_COUNTER_LENGTH (fn
->num_counts
))
1102 fn
->counts
= XCNEWVEC (gcov_type
, fn
->num_counts
);
1104 for (ix
= 0; ix
!= fn
->num_counts
; ix
++)
1105 fn
->counts
[ix
] += gcov_read_counter ();
1107 gcov_sync (base
, length
);
1108 if ((error
= gcov_is_error ()))
1110 fnotice (stderr
, error
< 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1120 /* Solve the flow graph. Propagate counts from the instrumented arcs
1121 to the blocks and the uninstrumented arcs. */
1124 solve_flow_graph (function_t
*fn
)
1128 gcov_type
*count_ptr
= fn
->counts
;
1130 block_t
*valid_blocks
= NULL
; /* valid, but unpropagated blocks. */
1131 block_t
*invalid_blocks
= NULL
; /* invalid, but inferable blocks. */
1133 if (fn
->num_blocks
< 2)
1134 fnotice (stderr
, "%s:'%s' lacks entry and/or exit blocks\n",
1135 bbg_file_name
, fn
->name
);
1138 if (fn
->blocks
[0].num_pred
)
1139 fnotice (stderr
, "%s:'%s' has arcs to entry block\n",
1140 bbg_file_name
, fn
->name
);
1142 /* We can't deduce the entry block counts from the lack of
1144 fn
->blocks
[0].num_pred
= ~(unsigned)0;
1146 if (fn
->blocks
[fn
->num_blocks
- 1].num_succ
)
1147 fnotice (stderr
, "%s:'%s' has arcs from exit block\n",
1148 bbg_file_name
, fn
->name
);
1150 /* Likewise, we can't deduce exit block counts from the lack
1151 of its successors. */
1152 fn
->blocks
[fn
->num_blocks
- 1].num_succ
= ~(unsigned)0;
1155 /* Propagate the measured counts, this must be done in the same
1156 order as the code in profile.c */
1157 for (ix
= 0, blk
= fn
->blocks
; ix
!= fn
->num_blocks
; ix
++, blk
++)
1159 block_t
const *prev_dst
= NULL
;
1160 int out_of_order
= 0;
1161 int non_fake_succ
= 0;
1163 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1171 arc
->count
= *count_ptr
++;
1172 arc
->count_valid
= 1;
1174 arc
->dst
->num_pred
--;
1176 if (prev_dst
&& prev_dst
> arc
->dst
)
1178 prev_dst
= arc
->dst
;
1180 if (non_fake_succ
== 1)
1182 /* If there is only one non-fake exit, it is an
1183 unconditional branch. */
1184 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1187 arc
->is_unconditional
= 1;
1188 /* If this block is instrumenting a call, it might be
1189 an artificial block. It is not artificial if it has
1190 a non-fallthrough exit, or the destination of this
1191 arc has more than one entry. Mark the destination
1192 block as a return site, if none of those conditions
1194 if (blk
->is_call_site
&& arc
->fall_through
1195 && arc
->dst
->pred
== arc
&& !arc
->pred_next
)
1196 arc
->dst
->is_call_return
= 1;
1200 /* Sort the successor arcs into ascending dst order. profile.c
1201 normally produces arcs in the right order, but sometimes with
1202 one or two out of order. We're not using a particularly
1206 arc_t
*start
= blk
->succ
;
1207 unsigned changes
= 1;
1211 arc_t
*arc
, *arc_p
, *arc_n
;
1214 for (arc_p
= NULL
, arc
= start
; (arc_n
= arc
->succ_next
);)
1216 if (arc
->dst
> arc_n
->dst
)
1220 arc_p
->succ_next
= arc_n
;
1223 arc
->succ_next
= arc_n
->succ_next
;
1224 arc_n
->succ_next
= arc
;
1237 /* Place it on the invalid chain, it will be ignored if that's
1239 blk
->invalid_chain
= 1;
1240 blk
->chain
= invalid_blocks
;
1241 invalid_blocks
= blk
;
1244 while (invalid_blocks
|| valid_blocks
)
1246 while ((blk
= invalid_blocks
))
1248 gcov_type total
= 0;
1251 invalid_blocks
= blk
->chain
;
1252 blk
->invalid_chain
= 0;
1254 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1255 total
+= arc
->count
;
1256 else if (!blk
->num_pred
)
1257 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1258 total
+= arc
->count
;
1263 blk
->count_valid
= 1;
1264 blk
->chain
= valid_blocks
;
1265 blk
->valid_chain
= 1;
1268 while ((blk
= valid_blocks
))
1271 arc_t
*arc
, *inv_arc
;
1273 valid_blocks
= blk
->chain
;
1274 blk
->valid_chain
= 0;
1275 if (blk
->num_succ
== 1)
1281 for (arc
= blk
->succ
; arc
; arc
= arc
->succ_next
)
1283 total
-= arc
->count
;
1284 if (!arc
->count_valid
)
1288 inv_arc
->count_valid
= 1;
1289 inv_arc
->count
= total
;
1292 if (dst
->count_valid
)
1294 if (dst
->num_pred
== 1 && !dst
->valid_chain
)
1296 dst
->chain
= valid_blocks
;
1297 dst
->valid_chain
= 1;
1303 if (!dst
->num_pred
&& !dst
->invalid_chain
)
1305 dst
->chain
= invalid_blocks
;
1306 dst
->invalid_chain
= 1;
1307 invalid_blocks
= dst
;
1311 if (blk
->num_pred
== 1)
1317 for (arc
= blk
->pred
; arc
; arc
= arc
->pred_next
)
1319 total
-= arc
->count
;
1320 if (!arc
->count_valid
)
1324 inv_arc
->count_valid
= 1;
1325 inv_arc
->count
= total
;
1328 if (src
->count_valid
)
1330 if (src
->num_succ
== 1 && !src
->valid_chain
)
1332 src
->chain
= valid_blocks
;
1333 src
->valid_chain
= 1;
1339 if (!src
->num_succ
&& !src
->invalid_chain
)
1341 src
->chain
= invalid_blocks
;
1342 src
->invalid_chain
= 1;
1343 invalid_blocks
= src
;
1350 /* If the graph has been correctly solved, every block will have a
1352 for (ix
= 0; ix
< fn
->num_blocks
; ix
++)
1353 if (!fn
->blocks
[ix
].count_valid
)
1355 fnotice (stderr
, "%s:graph is unsolvable for '%s'\n",
1356 bbg_file_name
, fn
->name
);
1363 /* Increment totals in COVERAGE according to arc ARC. */
1366 add_branch_counts (coverage_t
*coverage
, const arc_t
*arc
)
1368 if (arc
->is_call_non_return
)
1371 if (arc
->src
->count
)
1372 coverage
->calls_executed
++;
1374 else if (!arc
->is_unconditional
)
1376 coverage
->branches
++;
1377 if (arc
->src
->count
)
1378 coverage
->branches_executed
++;
1380 coverage
->branches_taken
++;
1384 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1385 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1386 If DP is zero, no decimal point is printed. Only print 100% when
1387 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1388 format TOP. Return pointer to a static string. */
1391 format_gcov (gcov_type top
, gcov_type bottom
, int dp
)
1393 static char buffer
[20];
1397 float ratio
= bottom
? (float)top
/ bottom
: 0;
1399 unsigned limit
= 100;
1402 for (ix
= dp
; ix
--; )
1405 percent
= (unsigned) (ratio
* limit
+ (float)0.5);
1406 if (percent
<= 0 && top
)
1408 else if (percent
>= limit
&& top
!= bottom
)
1409 percent
= limit
- 1;
1410 ix
= sprintf (buffer
, "%.*u%%", dp
+ 1, percent
);
1416 buffer
[ix
+1] = buffer
[ix
];
1420 buffer
[ix
+ 1] = '.';
1424 sprintf (buffer
, HOST_WIDEST_INT_PRINT_DEC
, (HOST_WIDEST_INT
)top
);
1430 /* Output summary info for a function. */
1433 function_summary (const coverage_t
*coverage
, const char *title
)
1435 fnotice (stdout
, "%s '%s'\n", title
, coverage
->name
);
1437 if (coverage
->lines
)
1438 fnotice (stdout
, "Lines executed:%s of %d\n",
1439 format_gcov (coverage
->lines_executed
, coverage
->lines
, 2),
1442 fnotice (stdout
, "No executable lines\n");
1446 if (coverage
->branches
)
1448 fnotice (stdout
, "Branches executed:%s of %d\n",
1449 format_gcov (coverage
->branches_executed
,
1450 coverage
->branches
, 2),
1451 coverage
->branches
);
1452 fnotice (stdout
, "Taken at least once:%s of %d\n",
1453 format_gcov (coverage
->branches_taken
,
1454 coverage
->branches
, 2),
1455 coverage
->branches
);
1458 fnotice (stdout
, "No branches\n");
1459 if (coverage
->calls
)
1460 fnotice (stdout
, "Calls executed:%s of %d\n",
1461 format_gcov (coverage
->calls_executed
, coverage
->calls
, 2),
1464 fnotice (stdout
, "No calls\n");
1468 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1469 affect name generation. With preserve_paths we create a filename
1470 from all path components of the source file, replacing '/' with
1471 '#', without it we simply take the basename component. With
1472 long_output_names we prepend the processed name of the input file
1473 to each output name (except when the current source file is the
1474 input file, so you don't get a double concatenation). The two
1475 components are separated by '##'. Also '.' filename components are
1476 removed and '..' components are renamed to '^'. */
1479 make_gcov_file_name (const char *input_name
, const char *src_name
)
1484 if (flag_long_names
&& input_name
&& strcmp (src_name
, input_name
))
1486 name
= XNEWVEC (char, strlen (src_name
) + strlen (input_name
) + 10);
1488 /* Generate the input filename part. */
1489 cptr
= flag_preserve_paths
? NULL
: strrchr (input_name
, '/');
1490 strcat (name
, cptr
? cptr
+ 1 : input_name
);
1491 strcat (name
, "##");
1495 name
= XNEWVEC (char, strlen (src_name
) + 10);
1499 /* Generate the source filename part. */
1500 cptr
= flag_preserve_paths
? NULL
: strrchr (src_name
, '/');
1501 strcat (name
, cptr
? cptr
+ 1 : src_name
);
1503 if (flag_preserve_paths
)
1505 /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1508 for (cptr
= name
; (cptr
= strchr ((prev
= cptr
), '/'));)
1512 if (prev
+ 1 == cptr
&& prev
[0] == '.')
1517 else if (prev
+ 2 == cptr
&& prev
[0] == '.' && prev
[1] == '.')
1529 prev
[0] = prev
[shift
];
1535 strcat (name
, ".gcov");
1539 /* Scan through the bb_data for each line in the block, increment
1540 the line number execution count indicated by the execution count of
1541 the appropriate basic block. */
1544 add_line_counts (coverage_t
*coverage
, function_t
*fn
)
1547 line_t
*line
= NULL
; /* This is propagated from one iteration to the
1550 /* Scan each basic block. */
1551 for (ix
= 0; ix
!= fn
->num_blocks
; ix
++)
1553 block_t
*block
= &fn
->blocks
[ix
];
1555 const source_t
*src
= NULL
;
1558 if (block
->count
&& ix
&& ix
+ 1 != fn
->num_blocks
)
1559 fn
->blocks_executed
++;
1560 for (jx
= 0, encoding
= block
->u
.line
.encoding
;
1561 jx
!= block
->u
.line
.num
; jx
++, encoding
++)
1564 unsigned src_n
= *++encoding
;
1566 for (src
= sources
; src
->index
!= src_n
; src
= src
->next
)
1572 line
= &src
->lines
[*encoding
];
1578 if (!line
->count
&& block
->count
)
1579 coverage
->lines_executed
++;
1582 line
->count
+= block
->count
;
1584 free (block
->u
.line
.encoding
);
1585 block
->u
.cycle
.arc
= NULL
;
1586 block
->u
.cycle
.ident
= ~0U;
1588 if (!ix
|| ix
+ 1 == fn
->num_blocks
)
1589 /* Entry or exit block */;
1590 else if (flag_all_blocks
)
1592 line_t
*block_line
= line
? line
: &fn
->src
->lines
[fn
->line
];
1594 block
->chain
= block_line
->u
.blocks
;
1595 block_line
->u
.blocks
= block
;
1597 else if (flag_branches
)
1601 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1603 arc
->line_next
= line
->u
.branches
;
1604 line
->u
.branches
= arc
;
1605 if (coverage
&& !arc
->is_unconditional
)
1606 add_branch_counts (coverage
, arc
);
1611 fnotice (stderr
, "%s:no lines for '%s'\n", bbg_file_name
, fn
->name
);
1614 /* Accumulate the line counts of a file. */
1617 accumulate_line_counts (source_t
*src
)
1620 function_t
*fn
, *fn_p
, *fn_n
;
1623 /* Reverse the function order. */
1624 for (fn
= src
->functions
, fn_p
= NULL
; fn
;
1625 fn_p
= fn
, fn
= fn_n
)
1627 fn_n
= fn
->line_next
;
1628 fn
->line_next
= fn_p
;
1630 src
->functions
= fn_p
;
1632 for (ix
= src
->num_lines
, line
= src
->lines
; ix
--; line
++)
1634 if (!flag_all_blocks
)
1636 arc_t
*arc
, *arc_p
, *arc_n
;
1638 /* Total and reverse the branch information. */
1639 for (arc
= line
->u
.branches
, arc_p
= NULL
; arc
;
1640 arc_p
= arc
, arc
= arc_n
)
1642 arc_n
= arc
->line_next
;
1643 arc
->line_next
= arc_p
;
1645 add_branch_counts (&src
->coverage
, arc
);
1647 line
->u
.branches
= arc_p
;
1649 else if (line
->u
.blocks
)
1651 /* The user expects the line count to be the number of times
1652 a line has been executed. Simply summing the block count
1653 will give an artificially high number. The Right Thing
1654 is to sum the entry counts to the graph of blocks on this
1655 line, then find the elementary cycles of the local graph
1656 and add the transition counts of those cycles. */
1657 block_t
*block
, *block_p
, *block_n
;
1658 gcov_type count
= 0;
1660 /* Reverse the block information. */
1661 for (block
= line
->u
.blocks
, block_p
= NULL
; block
;
1662 block_p
= block
, block
= block_n
)
1664 block_n
= block
->chain
;
1665 block
->chain
= block_p
;
1666 block
->u
.cycle
.ident
= ix
;
1668 line
->u
.blocks
= block_p
;
1670 /* Sum the entry arcs. */
1671 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1675 for (arc
= block
->pred
; arc
; arc
= arc
->pred_next
)
1677 if (arc
->src
->u
.cycle
.ident
!= ix
)
1678 count
+= arc
->count
;
1680 add_branch_counts (&src
->coverage
, arc
);
1683 /* Initialize the cs_count. */
1684 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1685 arc
->cs_count
= arc
->count
;
1688 /* Find the loops. This uses the algorithm described in
1689 Tiernan 'An Efficient Search Algorithm to Find the
1690 Elementary Circuits of a Graph', CACM Dec 1970. We hold
1691 the P array by having each block point to the arc that
1692 connects to the previous block. The H array is implicitly
1693 held because of the arc ordering, and the block's
1694 previous arc pointer.
1696 Although the algorithm is O(N^3) for highly connected
1697 graphs, at worst we'll have O(N^2), as most blocks have
1698 only one or two exits. Most graphs will be small.
1700 For each loop we find, locate the arc with the smallest
1701 transition count, and add that to the cumulative
1702 count. Decrease flow over the cycle and remove the arc
1703 from consideration. */
1704 for (block
= line
->u
.blocks
; block
; block
= block
->chain
)
1706 block_t
*head
= block
;
1714 block_t
*dst
= arc
->dst
;
1715 if (/* Already used that arc. */
1717 /* Not to same graph, or before first vertex. */
1718 || dst
->u
.cycle
.ident
!= ix
1719 /* Already in path. */
1720 || dst
->u
.cycle
.arc
)
1722 arc
= arc
->succ_next
;
1728 /* Found a closing arc. */
1729 gcov_type cycle_count
= arc
->cs_count
;
1730 arc_t
*cycle_arc
= arc
;
1733 /* Locate the smallest arc count of the loop. */
1734 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1735 dst
= probe_arc
->src
)
1736 if (cycle_count
> probe_arc
->cs_count
)
1738 cycle_count
= probe_arc
->cs_count
;
1739 cycle_arc
= probe_arc
;
1742 count
+= cycle_count
;
1743 cycle_arc
->cycle
= 1;
1745 /* Remove the flow from the cycle. */
1746 arc
->cs_count
-= cycle_count
;
1747 for (dst
= head
; (probe_arc
= dst
->u
.cycle
.arc
);
1748 dst
= probe_arc
->src
)
1749 probe_arc
->cs_count
-= cycle_count
;
1751 /* Unwind to the cyclic arc. */
1752 while (head
!= cycle_arc
->src
)
1754 arc
= head
->u
.cycle
.arc
;
1755 head
->u
.cycle
.arc
= NULL
;
1759 arc
= arc
->succ_next
;
1763 /* Add new block to chain. */
1764 dst
->u
.cycle
.arc
= arc
;
1768 /* We could not add another vertex to the path. Remove
1769 the last vertex from the list. */
1770 arc
= head
->u
.cycle
.arc
;
1773 /* It was not the first vertex. Move onto next arc. */
1774 head
->u
.cycle
.arc
= NULL
;
1776 arc
= arc
->succ_next
;
1777 goto current_vertex
;
1779 /* Mark this block as unusable. */
1780 block
->u
.cycle
.ident
= ~0U;
1783 line
->count
= count
;
1788 src
->coverage
.lines
++;
1790 src
->coverage
.lines_executed
++;
1795 /* Output information about ARC number IX. Returns nonzero if
1796 anything is output. */
1799 output_branch_count (FILE *gcov_file
, int ix
, const arc_t
*arc
)
1802 if (arc
->is_call_non_return
)
1804 if (arc
->src
->count
)
1806 fnotice (gcov_file
, "call %2d returned %s\n", ix
,
1807 format_gcov (arc
->src
->count
- arc
->count
,
1808 arc
->src
->count
, -flag_counts
));
1811 fnotice (gcov_file
, "call %2d never executed\n", ix
);
1813 else if (!arc
->is_unconditional
)
1815 if (arc
->src
->count
)
1816 fnotice (gcov_file
, "branch %2d taken %s%s\n", ix
,
1817 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
),
1818 arc
->fall_through
? " (fallthrough)" : "");
1820 fnotice (gcov_file
, "branch %2d never executed\n", ix
);
1822 else if (flag_unconditional
&& !arc
->dst
->is_call_return
)
1824 if (arc
->src
->count
)
1825 fnotice (gcov_file
, "unconditional %2d taken %s\n", ix
,
1826 format_gcov (arc
->count
, arc
->src
->count
, -flag_counts
));
1828 fnotice (gcov_file
, "unconditional %2d never executed\n", ix
);
1836 /* Read in the source file one line at a time, and output that line to
1837 the gcov file preceded by its execution count and other
1841 output_lines (FILE *gcov_file
, const source_t
*src
)
1844 unsigned line_num
; /* current line number. */
1845 const line_t
*line
; /* current line info ptr. */
1846 char string
[STRING_SIZE
]; /* line buffer. */
1847 char const *retval
= ""; /* status of source file reading. */
1848 function_t
*fn
= NULL
;
1850 fprintf (gcov_file
, "%9s:%5d:Source:%s\n", "-", 0, src
->name
);
1851 if (!multiple_files
)
1853 fprintf (gcov_file
, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name
);
1854 fprintf (gcov_file
, "%9s:%5d:Data:%s\n", "-", 0,
1855 no_data_file
? "-" : da_file_name
);
1856 fprintf (gcov_file
, "%9s:%5d:Runs:%u\n", "-", 0,
1857 object_summary
.ctrs
[GCOV_COUNTER_ARCS
].runs
);
1859 fprintf (gcov_file
, "%9s:%5d:Programs:%u\n", "-", 0, program_count
);
1861 source_file
= fopen (src
->name
, "r");
1864 fnotice (stderr
, "%s:cannot open source file\n", src
->name
);
1867 else if (src
->file_time
== 0)
1868 fprintf (gcov_file
, "%9s:%5d:Source is newer than graph\n", "-", 0);
1871 fn
= src
->functions
;
1873 for (line_num
= 1, line
= &src
->lines
[line_num
];
1874 line_num
< src
->num_lines
; line_num
++, line
++)
1876 for (; fn
&& fn
->line
== line_num
; fn
= fn
->line_next
)
1878 arc_t
*arc
= fn
->blocks
[fn
->num_blocks
- 1].pred
;
1879 gcov_type return_count
= fn
->blocks
[fn
->num_blocks
- 1].count
;
1881 for (; arc
; arc
= arc
->pred_next
)
1883 return_count
-= arc
->count
;
1885 fprintf (gcov_file
, "function %s", fn
->name
);
1886 fprintf (gcov_file
, " called %s",
1887 format_gcov (fn
->blocks
[0].count
, 0, -1));
1888 fprintf (gcov_file
, " returned %s",
1889 format_gcov (return_count
, fn
->blocks
[0].count
, 0));
1890 fprintf (gcov_file
, " blocks executed %s",
1891 format_gcov (fn
->blocks_executed
, fn
->num_blocks
- 2, 0));
1892 fprintf (gcov_file
, "\n");
1895 /* For lines which don't exist in the .bb file, print '-' before
1896 the source line. For lines which exist but were never
1897 executed, print '#####' before the source line. Otherwise,
1898 print the execution count before the source line. There are
1899 16 spaces of indentation added before the source line so that
1900 tabs won't be messed up. */
1901 fprintf (gcov_file
, "%9s:%5u:",
1902 !line
->exists
? "-" : !line
->count
? "#####"
1903 : format_gcov (line
->count
, 0, -1), line_num
);
1907 /* Copy source line. */
1910 retval
= fgets (string
, STRING_SIZE
, source_file
);
1913 fputs (retval
, gcov_file
);
1915 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n');
1918 fputs ("/*EOF*/\n", gcov_file
);
1920 if (flag_all_blocks
)
1926 for (ix
= jx
= 0, block
= line
->u
.blocks
; block
;
1927 block
= block
->chain
)
1929 if (!block
->is_call_return
)
1930 fprintf (gcov_file
, "%9s:%5u-block %2d\n",
1931 !line
->exists
? "-" : !block
->count
? "$$$$$"
1932 : format_gcov (block
->count
, 0, -1),
1935 for (arc
= block
->succ
; arc
; arc
= arc
->succ_next
)
1936 jx
+= output_branch_count (gcov_file
, jx
, arc
);
1939 else if (flag_branches
)
1944 for (ix
= 0, arc
= line
->u
.branches
; arc
; arc
= arc
->line_next
)
1945 ix
+= output_branch_count (gcov_file
, ix
, arc
);
1949 /* Handle all remaining source lines. There may be lines after the
1950 last line of code. */
1953 for (; (retval
= fgets (string
, STRING_SIZE
, source_file
)); line_num
++)
1955 fprintf (gcov_file
, "%9s:%5u:%s", "-", line_num
, retval
);
1957 while (!retval
[0] || retval
[strlen (retval
) - 1] != '\n')
1959 retval
= fgets (string
, STRING_SIZE
, source_file
);
1962 fputs (retval
, gcov_file
);
1968 fclose (source_file
);