]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gcov.c
expr.h (extract_bit_field): Remove packedp parameter.
[thirdparty/gcc.git] / gcc / gcov.c
CommitLineData
86144b75
DE
1/* Gcov.c: prepend line execution counts and branch probabilities to a
2 source file.
d1e082c2 3 Copyright (C) 1990-2013 Free Software Foundation, Inc.
86144b75 4 Contributed by James E. Wilson of Cygnus Support.
1d300e19 5 Mangled by Bob Manson of Cygnus Support.
4977bab6 6 Mangled further by Nathan Sidwell <nathan@codesourcery.com>
86144b75
DE
7
8Gcov is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
9dcd6f09 10the Free Software Foundation; either version 3, or (at your option)
86144b75
DE
11any later version.
12
13Gcov is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
9dcd6f09
NC
19along with Gcov; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
86144b75 21
86144b75
DE
22/* ??? Print a list of the ten blocks with the highest execution counts,
23 and list the line numbers corresponding to those blocks. Also, perhaps
24 list the line numbers with the highest execution counts, only printing
25 the first if there are several which are all listed in the same block. */
26
27/* ??? Should have an option to print the number of basic blocks, and the
28 percent of them that are covered. */
29
4977bab6
ZW
30/* Need an option to show individual block counts, and show
31 probabilities of fall through arcs. */
86144b75 32
1d300e19 33#include "config.h"
b04cd507 34#include "system.h"
4977bab6
ZW
35#include "coretypes.h"
36#include "tm.h"
ab87f8c8 37#include "intl.h"
2691e6d7 38#include "diagnostic.h"
5735c3ea 39#include "version.h"
fc8a650e 40#include "demangle.h"
86144b75 41
5735c3ea
JM
42#include <getopt.h>
43
546d2adb 44#define IN_GCOV 1
86144b75 45#include "gcov-io.h"
d79f9ec9 46#include "gcov-io.c"
86144b75 47
1a9075e2 48/* The gcno file is generated by -ftest-coverage option. The gcda file is
4977bab6
ZW
49 generated by a program compiled with -fprofile-arcs. Their formats
50 are documented in gcov-io.h. */
86144b75
DE
51
52/* The functions in this file for creating and solution program flow graphs
4977bab6
ZW
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. */
86144b75 56
10adac51
XDL
57/* The code validates that the profile information read in corresponds
58 to the code currently being compiled. Rather than checking for
9696c529 59 identical files, the code below compares a checksum on the CFG
10adac51 60 (based on the order of basic blocks and the arcs in the CFG). If
9696c529
SB
61 the CFG checksum in the gcda file match the CFG checksum in the
62 gcno file, the profile data will be used. */
10adac51 63
86144b75
DE
64/* This is the size of the buffer used to read in source file lines. */
65
4977bab6
ZW
66struct function_info;
67struct block_info;
27283c73 68struct source_info;
86144b75 69
4977bab6 70/* Describes an arc between two basic blocks. */
86144b75 71
4977bab6
ZW
72typedef struct arc_info
73{
32dd366d 74 /* source and destination blocks. */
4977bab6
ZW
75 struct block_info *src;
76 struct block_info *dst;
86144b75 77
4977bab6
ZW
78 /* transition counts. */
79 gcov_type count;
3d7ca167
ZD
80 /* used in cycle search, so that we do not clobber original counts. */
81 gcov_type cs_count;
86144b75 82
86144b75
DE
83 unsigned int count_valid : 1;
84 unsigned int on_tree : 1;
85 unsigned int fake : 1;
86 unsigned int fall_through : 1;
86144b75 87
8919c0d9
NS
88 /* Arc to a catch handler. */
89 unsigned int is_throw : 1;
90
27283c73
NS
91 /* Arc is for a function that abnormally returns. */
92 unsigned int is_call_non_return : 1;
93
fa10beec 94 /* Arc is for catch/setjmp. */
27283c73
NS
95 unsigned int is_nonlocal_return : 1;
96
97 /* Is an unconditional branch. */
98 unsigned int is_unconditional : 1;
99
10b7602f
NS
100 /* Loop making arc. */
101 unsigned int cycle : 1;
102
4977bab6
ZW
103 /* Next branch on line. */
104 struct arc_info *line_next;
f55ade6e 105
4977bab6
ZW
106 /* Links to next arc on src and dst lists. */
107 struct arc_info *succ_next;
108 struct arc_info *pred_next;
109} arc_t;
86144b75 110
4977bab6
ZW
111/* Describes a basic block. Contains lists of arcs to successor and
112 predecessor blocks. */
86144b75 113
4977bab6 114typedef struct block_info
86144b75 115{
4977bab6
ZW
116 /* Chain of exit and entry arcs. */
117 arc_t *succ;
118 arc_t *pred;
119
32dd366d 120 /* Number of unprocessed exit and entry arcs. */
4977bab6
ZW
121 gcov_type num_succ;
122 gcov_type num_pred;
123
32dd366d 124 /* Block execution count. */
4977bab6 125 gcov_type count;
8919c0d9 126 unsigned flags : 12;
4977bab6
ZW
127 unsigned count_valid : 1;
128 unsigned valid_chain : 1;
129 unsigned invalid_chain : 1;
8919c0d9 130 unsigned exceptional : 1;
4977bab6 131
27283c73 132 /* Block is a call instrumenting site. */
10b7602f
NS
133 unsigned is_call_site : 1; /* Does the call. */
134 unsigned is_call_return : 1; /* Is the return. */
4977bab6 135
27283c73
NS
136 /* Block is a landing pad for longjmp or throw. */
137 unsigned is_nonlocal_return : 1;
138
139 union
140 {
141 struct
142 {
143 /* Array of line numbers and source files. source files are
144 introduced by a linenumber of zero, the next 'line number' is
145 the number of the source file. Always starts with a source
146 file. */
147 unsigned *encoding;
148 unsigned num;
149 } line; /* Valid until blocks are linked onto lines */
150 struct
151 {
10b7602f 152 /* Single line graph cycle workspace. Used for all-blocks
71c0e7fc 153 mode. */
10b7602f
NS
154 arc_t *arc;
155 unsigned ident;
156 } cycle; /* Used in all-blocks mode, after blocks are linked onto
71c0e7fc 157 lines. */
27283c73
NS
158 } u;
159
160 /* Temporary chain for solving graph, and for chaining blocks on one
161 line. */
4977bab6 162 struct block_info *chain;
f55ade6e 163
4977bab6 164} block_t;
86144b75 165
4977bab6 166/* Describes a single function. Contains an array of basic blocks. */
86144b75 167
4977bab6 168typedef struct function_info
8b219a76 169{
4977bab6
ZW
170 /* Name of function. */
171 char *name;
fc8a650e 172 char *demangled_name;
796621e8 173 unsigned ident;
10adac51
XDL
174 unsigned lineno_checksum;
175 unsigned cfg_checksum;
86144b75 176
8919c0d9
NS
177 /* The graph contains at least one fake incoming edge. */
178 unsigned has_catch : 1;
179
9696c529
SB
180 /* Array of basic blocks. Like in GCC, the entry block is
181 at blocks[0] and the exit block is at blocks[1]. */
182#define ENTRY_BLOCK (0)
183#define EXIT_BLOCK (1)
4977bab6
ZW
184 block_t *blocks;
185 unsigned num_blocks;
27283c73 186 unsigned blocks_executed;
4977bab6
ZW
187
188 /* Raw arc coverage counts. */
189 gcov_type *counts;
190 unsigned num_counts;
27283c73 191
1ce1b792 192 /* First line number & file. */
27283c73 193 unsigned line;
1ce1b792 194 unsigned src;
27283c73
NS
195
196 /* Next function in same source file. */
197 struct function_info *line_next;
f55ade6e 198
4977bab6
ZW
199 /* Next function. */
200 struct function_info *next;
201} function_t;
202
203/* Describes coverage of a file or function. */
204
205typedef struct coverage_info
8b219a76
NS
206{
207 int lines;
208 int lines_executed;
f55ade6e 209
8b219a76
NS
210 int branches;
211 int branches_executed;
212 int branches_taken;
f55ade6e 213
8b219a76
NS
214 int calls;
215 int calls_executed;
f55ade6e 216
8b219a76 217 char *name;
4977bab6 218} coverage_t;
8b219a76 219
4977bab6
ZW
220/* Describes a single line of source. Contains a chain of basic blocks
221 with code on it. */
86144b75 222
4977bab6
ZW
223typedef struct line_info
224{
225 gcov_type count; /* execution count */
27283c73
NS
226 union
227 {
f55ade6e 228 arc_t *branches; /* branches from blocks that end on this
27283c73 229 line. Used for branch-counts when not
71c0e7fc 230 all-blocks mode. */
27283c73 231 block_t *blocks; /* blocks which start on this line. Used
71c0e7fc 232 in all-blocks mode. */
27283c73 233 } u;
4977bab6 234 unsigned exists : 1;
8919c0d9 235 unsigned unexceptional : 1;
4977bab6 236} line_t;
86144b75 237
4977bab6
ZW
238/* Describes a file mentioned in the block graph. Contains an array
239 of line info. */
37b8715b 240
4977bab6
ZW
241typedef struct source_info
242{
eeabee0a 243 /* Canonical name of source file. */
4977bab6 244 char *name;
1a9075e2 245 time_t file_time;
37b8715b 246
32dd366d 247 /* Array of line information. */
4977bab6
ZW
248 line_t *lines;
249 unsigned num_lines;
86144b75 250
4977bab6 251 coverage_t coverage;
27283c73
NS
252
253 /* Functions in this source file. These are in ascending line
254 number order. */
255 function_t *functions;
4977bab6 256} source_t;
86144b75 257
eeabee0a
NS
258typedef struct name_map
259{
260 char *name; /* Source file name */
261 unsigned src; /* Source file */
262} name_map_t;
263
4977bab6 264/* Holds a list of function basic block graphs. */
86144b75 265
4977bab6 266static function_t *functions;
1ce1b792 267static function_t **fn_end = &functions;
86144b75 268
1ce1b792
NS
269static source_t *sources; /* Array of source files */
270static unsigned n_sources; /* Number of sources */
271static unsigned a_sources; /* Allocated sources */
1a9075e2 272
eeabee0a
NS
273static name_map_t *names; /* Mapping of file names to sources */
274static unsigned n_names; /* Number of names */
275static unsigned a_names; /* Allocated names */
276
27283c73
NS
277/* This holds data summary information. */
278
5366b186 279static unsigned object_runs;
27283c73
NS
280static unsigned program_count;
281
bdbdc4e1
NS
282static unsigned total_lines;
283static unsigned total_executed;
284
32dd366d 285/* Modification time of graph file. */
86144b75 286
4977bab6 287static time_t bbg_file_time;
86144b75 288
efbb59b2
SB
289/* Name of the notes (gcno) output file. The "bbg" prefix is for
290 historical reasons, when the notes file contained only the
291 basic block graph notes. */
86144b75 292
4977bab6 293static char *bbg_file_name;
86144b75 294
dd486eb2
NS
295/* Stamp of the bbg file */
296static unsigned bbg_stamp;
297
efbb59b2 298/* Name and file pointer of the input file for the count data (gcda). */
86144b75 299
4977bab6 300static char *da_file_name;
86144b75 301
80b3502b
NS
302/* Data file is missing. */
303
304static int no_data_file;
305
1a9075e2
TG
306/* If there is several input files, compute and display results after
307 reading all data files. This way if two or more gcda file refer to
308 the same source file (eg inline subprograms in a .h file), the
309 counts are added. */
310
311static int multiple_files = 0;
312
4977bab6 313/* Output branch probabilities. */
86144b75 314
4977bab6 315static int flag_branches = 0;
86144b75 316
f55ade6e 317/* Show unconditional branches too. */
27283c73
NS
318static int flag_unconditional = 0;
319
86144b75
DE
320/* Output a gcov file if this is true. This is on by default, and can
321 be turned off by the -n option. */
322
4977bab6 323static int flag_gcov_file = 1;
86144b75 324
acdb4da7
NS
325/* Output progress indication if this is true. This is off by default
326 and can be turned on by the -d option. */
327
328static int flag_display_progress = 0;
329
fc8a650e
SS
330/* Output *.gcov file in intermediate format used by 'lcov'. */
331
332static int flag_intermediate_format = 0;
333
334/* Output demangled function names. */
335
336static int flag_demangled_names = 0;
337
4977bab6
ZW
338/* For included files, make the gcov output file name include the name
339 of the input source file. For example, if x.h is included in a.c,
340 then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
86144b75 341
4977bab6 342static int flag_long_names = 0;
86144b75 343
27283c73
NS
344/* Output count information for every basic block, not merely those
345 that contain line number information. */
346
347static int flag_all_blocks = 0;
348
86144b75
DE
349/* Output summary info for each function. */
350
4977bab6 351static int flag_function_summary = 0;
86144b75 352
4977bab6
ZW
353/* Object directory file prefix. This is the directory/file where the
354 graph and data files are looked for, if nonzero. */
86144b75
DE
355
356static char *object_directory = 0;
357
1bec9caa
NS
358/* Source directory prefix. This is removed from source pathnames
359 that match, when generating the output file name. */
360
361static char *source_prefix = 0;
362static size_t source_length = 0;
363
364/* Only show data for sources with relative pathnames. Absolute ones
365 usually indicate a system header file, which although it may
366 contain inline functions, is usually uninteresting. */
367static int flag_relative_only = 0;
368
37b8715b 369/* Preserve all pathname components. Needed when object files and
4977bab6
ZW
370 source files are in subdirectories. '/' is mangled as '#', '.' is
371 elided and '..' mangled to '^'. */
372
373static int flag_preserve_paths = 0;
37b8715b 374
8bfa6fc5 375/* Output the number of times a branch was taken as opposed to the percentage
32dd366d 376 of times it was taken. */
23190837 377
4977bab6 378static int flag_counts = 0;
8bfa6fc5 379
86144b75 380/* Forward declarations. */
f55ade6e
AJ
381static int process_args (int, char **);
382static void print_usage (int) ATTRIBUTE_NORETURN;
383static void print_version (void) ATTRIBUTE_NORETURN;
384static void process_file (const char *);
1a9075e2 385static void generate_results (const char *);
f55ade6e 386static void create_file_names (const char *);
eeabee0a
NS
387static int name_search (const void *, const void *);
388static int name_sort (const void *, const void *);
389static char *canonicalize_name (const char *);
1ce1b792
NS
390static unsigned find_source (const char *);
391static function_t *read_graph_file (void);
392static int read_count_file (function_t *);
f55ade6e 393static void solve_flow_graph (function_t *);
8919c0d9 394static void find_exception_blocks (function_t *);
f55ade6e
AJ
395static void add_branch_counts (coverage_t *, const arc_t *);
396static void add_line_counts (coverage_t *, function_t *);
bdbdc4e1 397static void executed_summary (unsigned, unsigned);
f55ade6e
AJ
398static void function_summary (const coverage_t *, const char *);
399static const char *format_gcov (gcov_type, gcov_type, int);
400static void accumulate_line_counts (source_t *);
fc8a650e 401static void output_gcov_file(const char *, source_t *);
f55ade6e
AJ
402static int output_branch_count (FILE *, int, const arc_t *);
403static void output_lines (FILE *, const source_t *);
404static char *make_gcov_file_name (const char *, const char *);
eeabee0a 405static char *mangle_name (const char *, char *);
f55ade6e 406static void release_structures (void);
5366b186 407static void release_function (function_t *);
f55ade6e 408extern int main (int, char **);
86144b75
DE
409
410int
f55ade6e 411main (int argc, char **argv)
86144b75 412{
4977bab6 413 int argno;
acdb4da7 414 int first_arg;
2691e6d7
JM
415 const char *p;
416
417 p = argv[0] + strlen (argv[0]);
418 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
419 --p;
420 progname = p;
421
422 xmalloc_set_program_name (progname);
f55ade6e 423
98a3dad4 424 /* Unlock the stdio streams. */
2653bb0c 425 unlock_std_streams ();
98a3dad4 426
191bf464 427 gcc_init_libintl ();
ab87f8c8 428
2691e6d7
JM
429 diagnostic_initialize (global_dc, 0);
430
e3536b82
TG
431 /* Handle response files. */
432 expandargv (&argc, &argv);
433
84ec53b6
NS
434 a_names = 10;
435 names = XNEWVEC (name_map_t, a_names);
436 a_sources = 10;
437 sources = XNEWVEC (source_t, a_sources);
438
4977bab6
ZW
439 argno = process_args (argc, argv);
440 if (optind == argc)
441 print_usage (true);
86144b75 442
1a9075e2
TG
443 if (argc - argno > 1)
444 multiple_files = 1;
445
acdb4da7
NS
446 first_arg = argno;
447
4977bab6 448 for (; argno != argc; argno++)
acdb4da7
NS
449 {
450 if (flag_display_progress)
451 printf("Processing file %d out of %d\n",
452 argno - first_arg + 1, argc - first_arg);
453 process_file (argv[argno]);
454 }
f55ade6e 455
1a9075e2
TG
456 generate_results (multiple_files ? NULL : argv[argc - 1]);
457
458 release_structures ();
f55ade6e 459
86144b75
DE
460 return 0;
461}
86144b75 462\f
5735c3ea
JM
463/* Print a usage message and exit. If ERROR_P is nonzero, this is an error,
464 otherwise the output of --help. */
86144b75
DE
465
466static void
f55ade6e 467print_usage (int error_p)
86144b75 468{
5735c3ea
JM
469 FILE *file = error_p ? stderr : stdout;
470 int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
f55ade6e 471
eeabee0a 472 fnotice (file, "Usage: gcov [OPTION]... SOURCE|OBJ...\n\n");
5735c3ea
JM
473 fnotice (file, "Print code coverage information.\n\n");
474 fnotice (file, " -h, --help Print this help, then exit\n");
27283c73 475 fnotice (file, " -a, --all-blocks Show information for every basic block\n");
5735c3ea 476 fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n");
fc8a650e 477 fnotice (file, " -c, --branch-counts Output counts of branches taken\n\
5735c3ea 478 rather than percentages\n");
fc8a650e
SS
479 fnotice (file, " -d, --display-progress Display progress information\n");
480 fnotice (file, " -f, --function-summaries Output summaries for each function\n");
481 fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n");
5735c3ea
JM
482 fnotice (file, " -l, --long-file-names Use long output file names for included\n\
483 source files\n");
fc8a650e
SS
484 fnotice (file, " -m, --demangled-names Output demangled function names\n");
485 fnotice (file, " -n, --no-output Do not create an output file\n");
37b8715b
NS
486 fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
487 fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
fc8a650e
SS
488 fnotice (file, " -r, --relative-only Only show data for relative sources\n");
489 fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
27283c73 490 fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n");
fc8a650e 491 fnotice (file, " -v, --version Print version number, then exit\n");
5735c3ea 492 fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
a976603e 493 bug_report_url);
5735c3ea
JM
494 exit (status);
495}
496
497/* Print version information and exit. */
498
499static void
f55ade6e 500print_version (void)
5735c3ea 501{
2f41c1d6 502 fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
df8e2b4f 503 fprintf (stdout, "Copyright %s 2013 Free Software Foundation, Inc.\n",
9f76f909 504 _("(C)"));
5735c3ea 505 fnotice (stdout,
9f76f909
KH
506 _("This is free software; see the source for copying conditions.\n"
507 "There is NO warranty; not even for MERCHANTABILITY or \n"
508 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
5735c3ea 509 exit (SUCCESS_EXIT_CODE);
86144b75
DE
510}
511
5735c3ea
JM
512static const struct option options[] =
513{
514 { "help", no_argument, NULL, 'h' },
515 { "version", no_argument, NULL, 'v' },
27283c73 516 { "all-blocks", no_argument, NULL, 'a' },
5735c3ea
JM
517 { "branch-probabilities", no_argument, NULL, 'b' },
518 { "branch-counts", no_argument, NULL, 'c' },
fc8a650e 519 { "intermediate-format", no_argument, NULL, 'i' },
5735c3ea
JM
520 { "no-output", no_argument, NULL, 'n' },
521 { "long-file-names", no_argument, NULL, 'l' },
522 { "function-summaries", no_argument, NULL, 'f' },
fc8a650e 523 { "demangled-names", no_argument, NULL, 'm' },
37b8715b 524 { "preserve-paths", no_argument, NULL, 'p' },
1bec9caa 525 { "relative-only", no_argument, NULL, 'r' },
37b8715b
NS
526 { "object-directory", required_argument, NULL, 'o' },
527 { "object-file", required_argument, NULL, 'o' },
1bec9caa 528 { "source-prefix", required_argument, NULL, 's' },
27283c73 529 { "unconditional-branches", no_argument, NULL, 'u' },
acdb4da7 530 { "display-progress", no_argument, NULL, 'd' },
d90f9882 531 { 0, 0, 0, 0 }
5735c3ea
JM
532};
533
4977bab6 534/* Process args, return index to first non-arg. */
86144b75 535
4977bab6 536static int
f55ade6e 537process_args (int argc, char **argv)
86144b75 538{
5735c3ea 539 int opt;
86144b75 540
fc8a650e
SS
541 while ((opt = getopt_long (argc, argv, "abcdfhilmno:s:pruv", options, NULL)) !=
542 -1)
86144b75 543 {
5735c3ea 544 switch (opt)
86144b75 545 {
27283c73
NS
546 case 'a':
547 flag_all_blocks = 1;
548 break;
5735c3ea 549 case 'b':
4977bab6 550 flag_branches = 1;
5735c3ea
JM
551 break;
552 case 'c':
4977bab6 553 flag_counts = 1;
5735c3ea 554 break;
27283c73
NS
555 case 'f':
556 flag_function_summary = 1;
5735c3ea 557 break;
27283c73
NS
558 case 'h':
559 print_usage (false);
560 /* print_usage will exit. */
5735c3ea 561 case 'l':
4977bab6 562 flag_long_names = 1;
5735c3ea 563 break;
fc8a650e
SS
564 case 'm':
565 flag_demangled_names = 1;
566 break;
27283c73
NS
567 case 'n':
568 flag_gcov_file = 0;
5735c3ea
JM
569 break;
570 case 'o':
571 object_directory = optarg;
572 break;
1bec9caa
NS
573 case 's':
574 source_prefix = optarg;
575 source_length = strlen (source_prefix);
576 break;
577 case 'r':
578 flag_relative_only = 1;
579 break;
37b8715b 580 case 'p':
4977bab6 581 flag_preserve_paths = 1;
37b8715b 582 break;
27283c73
NS
583 case 'u':
584 flag_unconditional = 1;
585 break;
fc8a650e
SS
586 case 'i':
587 flag_intermediate_format = 1;
588 flag_gcov_file = 1;
589 break;
acdb4da7
NS
590 case 'd':
591 flag_display_progress = 1;
592 break;
27283c73
NS
593 case 'v':
594 print_version ();
595 /* print_version will exit. */
5735c3ea
JM
596 default:
597 print_usage (true);
598 /* print_usage will exit. */
86144b75 599 }
86144b75
DE
600 }
601
4977bab6
ZW
602 return optind;
603}
604
fc8a650e
SS
605/* Get the name of the gcov file. The return value must be free'd.
606
607 It appends the '.gcov' extension to the *basename* of the file.
608 The resulting file name will be in PWD.
609
610 e.g.,
611 input: foo.da, output: foo.da.gcov
612 input: a/b/foo.cc, output: foo.cc.gcov */
613
614static char *
615get_gcov_intermediate_filename (const char *file_name)
616{
617 const char *gcov = ".gcov";
618 char *result;
619 const char *cptr;
620
621 /* Find the 'basename'. */
622 cptr = lbasename (file_name);
623
624 result = XNEWVEC(char, strlen (cptr) + strlen (gcov) + 1);
625 sprintf (result, "%s%s", cptr, gcov);
626
627 return result;
628}
629
630/* Output the result in intermediate format used by 'lcov'.
631
632The intermediate format contains a single file named 'foo.cc.gcov',
633with no source code included. A sample output is
634
635file:foo.cc
636function:5,1,_Z3foov
637function:13,1,main
638function:19,1,_GLOBAL__sub_I__Z3foov
639function:19,1,_Z41__static_initialization_and_destruction_0ii
640lcount:5,1
641lcount:7,9
642lcount:9,8
643lcount:11,1
644file:/.../iostream
645lcount:74,1
646file:/.../basic_ios.h
647file:/.../ostream
648file:/.../ios_base.h
649function:157,0,_ZStorSt12_Ios_IostateS_
650lcount:157,0
651file:/.../char_traits.h
652function:258,0,_ZNSt11char_traitsIcE6lengthEPKc
653lcount:258,0
654...
655
656The default gcov outputs multiple files: 'foo.cc.gcov',
657'iostream.gcov', 'ios_base.h.gcov', etc. with source code
658included. Instead the intermediate format here outputs only a single
659file 'foo.cc.gcov' similar to the above example. */
660
661static void
662output_intermediate_file (FILE *gcov_file, source_t *src)
663{
664 unsigned line_num; /* current line number. */
665 const line_t *line; /* current line info ptr. */
666 function_t *fn; /* current function info ptr. */
667
668 fprintf (gcov_file, "file:%s\n", src->name); /* source file name */
669
670 for (fn = src->functions; fn; fn = fn->line_next)
671 {
672 /* function:<name>,<line_number>,<execution_count> */
673 fprintf (gcov_file, "function:%d,%s,%s\n", fn->line,
674 format_gcov (fn->blocks[0].count, 0, -1),
675 flag_demangled_names ? fn->demangled_name : fn->name);
676 }
677
678 for (line_num = 1, line = &src->lines[line_num];
679 line_num < src->num_lines;
680 line_num++, line++)
681 {
682 arc_t *arc;
683 if (line->exists)
684 fprintf (gcov_file, "lcount:%u,%s\n", line_num,
685 format_gcov (line->count, 0, -1));
686 if (flag_branches)
687 for (arc = line->u.branches; arc; arc = arc->line_next)
688 {
689 if (!arc->is_unconditional && !arc->is_call_non_return)
690 {
691 const char *branch_type;
692 /* branch:<line_num>,<branch_coverage_type>
693 branch_coverage_type
694 : notexec (Branch not executed)
695 : taken (Branch executed and taken)
696 : nottaken (Branch executed, but not taken)
697 */
698 if (arc->src->count)
699 branch_type = (arc->count > 0) ? "taken" : "nottaken";
700 else
701 branch_type = "notexec";
702 fprintf(gcov_file, "branch:%d,%s\n", line_num, branch_type);
703 }
704 }
705 }
706}
707
708
eeabee0a 709/* Process a single input file. */
5735c3ea 710
4977bab6 711static void
f55ade6e 712process_file (const char *file_name)
4977bab6 713{
1ce1b792 714 function_t *fns;
f55ade6e 715
4977bab6 716 create_file_names (file_name);
1ce1b792
NS
717 fns = read_graph_file ();
718 if (!fns)
4977bab6 719 return;
1ce1b792
NS
720
721 read_count_file (fns);
722 while (fns)
4977bab6 723 {
1ce1b792 724 function_t *fn = fns;
f55ade6e 725
1ce1b792
NS
726 fns = fn->next;
727 fn->next = NULL;
5366b186
NS
728 if (fn->counts)
729 {
1ce1b792
NS
730 unsigned src = fn->src;
731 unsigned line = fn->line;
732 unsigned block_no;
733 function_t *probe, **prev;
734
735 /* Now insert it into the source file's list of
736 functions. Normally functions will be encountered in
737 ascending order, so a simple scan is quick. Note we're
738 building this list in reverse order. */
739 for (prev = &sources[src].functions;
740 (probe = *prev); prev = &probe->line_next)
741 if (probe->line <= line)
742 break;
743 fn->line_next = probe;
744 *prev = fn;
745
746 /* Mark last line in files touched by function. */
747 for (block_no = 0; block_no != fn->num_blocks; block_no++)
748 {
749 unsigned *enc = fn->blocks[block_no].u.line.encoding;
750 unsigned num = fn->blocks[block_no].u.line.num;
751
752 for (; num--; enc++)
753 if (!*enc)
754 {
755 if (enc[1] != src)
756 {
757 if (line >= sources[src].num_lines)
758 sources[src].num_lines = line + 1;
759 line = 0;
760 src = enc[1];
761 }
762 enc++;
763 num--;
764 }
765 else if (*enc > line)
766 line = *enc;
767 }
768 if (line >= sources[src].num_lines)
769 sources[src].num_lines = line + 1;
770
5366b186 771 solve_flow_graph (fn);
8919c0d9
NS
772 if (fn->has_catch)
773 find_exception_blocks (fn);
1ce1b792
NS
774 *fn_end = fn;
775 fn_end = &fn->next;
5366b186
NS
776 }
777 else
1ce1b792
NS
778 /* The function was not in the executable -- some other
779 instance must have been selected. */
780 release_function (fn);
5366b186 781 }
1a9075e2
TG
782}
783
fc8a650e
SS
784static void
785output_gcov_file(const char *file_name, source_t *src)
786{
787 char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name);
788
789 if (src->coverage.lines)
790 {
791 FILE *gcov_file = fopen (gcov_file_name, "w");
792 if (gcov_file)
793 {
794 fnotice (stdout, "Creating '%s'\n", gcov_file_name);
795 output_lines (gcov_file, src);
796 if (ferror (gcov_file))
797 fnotice (stderr, "Error writing output file '%s'\n", gcov_file_name);
798 fclose (gcov_file);
799 }
800 else
801 fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
802 }
803 else
804 {
805 unlink (gcov_file_name);
806 fnotice (stdout, "Removing '%s'\n", gcov_file_name);
807 }
808 free (gcov_file_name);
809}
810
1a9075e2
TG
811static void
812generate_results (const char *file_name)
813{
1ce1b792 814 unsigned ix;
1a9075e2
TG
815 source_t *src;
816 function_t *fn;
fc8a650e
SS
817 FILE *gcov_intermediate_file = NULL;
818 char *gcov_intermediate_filename = NULL;
1a9075e2 819
1ce1b792
NS
820 for (ix = n_sources, src = sources; ix--; src++)
821 if (src->num_lines)
822 src->lines = XCNEWVEC (line_t, src->num_lines);
823
4977bab6
ZW
824 for (fn = functions; fn; fn = fn->next)
825 {
826 coverage_t coverage;
f55ade6e 827
4977bab6 828 memset (&coverage, 0, sizeof (coverage));
fc8a650e 829 coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
4977bab6
ZW
830 add_line_counts (flag_function_summary ? &coverage : NULL, fn);
831 if (flag_function_summary)
832 {
833 function_summary (&coverage, "Function");
834 fnotice (stdout, "\n");
835 }
836 }
f55ade6e 837
eeabee0a
NS
838 if (file_name)
839 {
840 name_map_t *name_map = (name_map_t *)bsearch
841 (file_name, names, n_names, sizeof (*names), name_search);
842 if (name_map)
1bec9caa 843 file_name = sources[name_map->src].coverage.name;
eeabee0a
NS
844 else
845 file_name = canonicalize_name (file_name);
846 }
fc8a650e
SS
847
848 if (flag_gcov_file && flag_intermediate_format)
849 {
850 /* Open the intermediate file. */
851 gcov_intermediate_filename =
852 get_gcov_intermediate_filename (file_name);
853 gcov_intermediate_file = fopen (gcov_intermediate_filename, "w");
854 if (!gcov_intermediate_file)
855 {
856 fnotice (stderr, "Cannot open intermediate output file %s\n",
857 gcov_intermediate_filename);
858 return;
859 }
860 }
861
1ce1b792 862 for (ix = n_sources, src = sources; ix--; src++)
4977bab6 863 {
1bec9caa
NS
864 if (flag_relative_only)
865 {
866 /* Ignore this source, if it is an absolute path (after
867 source prefix removal). */
868 char first = src->coverage.name[0];
869
870#if HAVE_DOS_BASED_FILE_SYSTEM
871 if (first && src->coverage.name[1] == ':')
fe860eb5 872 first = src->coverage.name[2];
1bec9caa 873#endif
fe860eb5
KT
874 if (IS_DIR_SEPARATOR (first))
875 continue;
1bec9caa
NS
876 }
877
4977bab6
ZW
878 accumulate_line_counts (src);
879 function_summary (&src->coverage, "File");
bdbdc4e1
NS
880 total_lines += src->coverage.lines;
881 total_executed += src->coverage.lines_executed;
8f961b22 882 if (flag_gcov_file)
4977bab6 883 {
fc8a650e
SS
884 if (flag_intermediate_format)
885 /* Output the intermediate format without requiring source
886 files. This outputs a section to a *single* file. */
887 output_intermediate_file (gcov_intermediate_file, src);
888 else
889 output_gcov_file (file_name, src);
890 fnotice (stdout, "\n");
891 }
892 }
8f961b22 893
fc8a650e
SS
894 if (flag_gcov_file && flag_intermediate_format)
895 {
896 /* Now we've finished writing the intermediate file. */
897 fclose (gcov_intermediate_file);
898 XDELETEVEC (gcov_intermediate_filename);
4977bab6 899 }
bdbdc4e1
NS
900
901 if (!file_name)
902 executed_summary (total_lines, total_executed);
86144b75
DE
903}
904
5366b186
NS
905/* Release a function structure */
906
907static void
908release_function (function_t *fn)
909{
910 unsigned ix;
911 block_t *block;
912
913 for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
914 {
915 arc_t *arc, *arc_n;
916
917 for (arc = block->succ; arc; arc = arc_n)
918 {
919 arc_n = arc->succ_next;
920 free (arc);
921 }
922 }
923 free (fn->blocks);
924 free (fn->counts);
fc8a650e
SS
925 if (flag_demangled_names && fn->demangled_name != fn->name)
926 free (fn->demangled_name);
927 free (fn->name);
5366b186
NS
928}
929
4977bab6 930/* Release all memory used. */
86144b75 931
4977bab6 932static void
f55ade6e 933release_structures (void)
4977bab6 934{
1ce1b792 935 unsigned ix;
4977bab6 936 function_t *fn;
f55ade6e 937
1ce1b792 938 for (ix = n_sources; ix--;)
eeabee0a
NS
939 free (sources[ix].lines);
940 free (sources);
941
942 for (ix = n_names; ix--;)
943 free (names[ix].name);
944 free (names);
f55ade6e 945
4977bab6
ZW
946 while ((fn = functions))
947 {
4977bab6 948 functions = fn->next;
5366b186 949 release_function (fn);
4977bab6
ZW
950 }
951}
952
15882fe9
TG
953/* Generate the names of the graph and data files. If OBJECT_DIRECTORY
954 is not specified, these are named from FILE_NAME sans extension. If
955 OBJECT_DIRECTORY is specified and is a directory, the files are in that
956 directory, but named from the basename of the FILE_NAME, sans extension.
957 Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
958 and the data files are named from that. */
86144b75
DE
959
960static void
f55ade6e 961create_file_names (const char *file_name)
86144b75 962{
86144b75 963 char *cptr;
37b8715b 964 char *name;
4977bab6 965 int length = strlen (file_name);
37b8715b 966 int base;
f55ade6e 967
1a9075e2 968 /* Free previous file names. */
04695783
JM
969 free (bbg_file_name);
970 free (da_file_name);
1a9075e2
TG
971 da_file_name = bbg_file_name = NULL;
972 bbg_file_time = 0;
973 bbg_stamp = 0;
974
37b8715b 975 if (object_directory && object_directory[0])
86144b75 976 {
37b8715b
NS
977 struct stat status;
978
979 length += strlen (object_directory) + 2;
5ed6ace5 980 name = XNEWVEC (char, length);
37b8715b 981 name[0] = 0;
f55ade6e 982
37b8715b
NS
983 base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
984 strcat (name, object_directory);
2f07423c 985 if (base && (! IS_DIR_SEPARATOR (name[strlen (name) - 1])))
37b8715b 986 strcat (name, "/");
86144b75
DE
987 }
988 else
989 {
5ed6ace5 990 name = XNEWVEC (char, length + 1);
15882fe9
TG
991 strcpy (name, file_name);
992 base = 0;
86144b75 993 }
f55ade6e 994
37b8715b
NS
995 if (base)
996 {
f9da5064 997 /* Append source file name. */
2f07423c
PO
998 const char *cptr = lbasename (file_name);
999 strcat (name, cptr ? cptr : file_name);
37b8715b 1000 }
f55ade6e 1001
4b7e68e7 1002 /* Remove the extension. */
258ef007 1003 cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.');
86144b75 1004 if (cptr)
37b8715b 1005 *cptr = 0;
f55ade6e 1006
37b8715b 1007 length = strlen (name);
b8698a0f 1008
5ed6ace5 1009 bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1);
4977bab6 1010 strcpy (bbg_file_name, name);
160e2e4f 1011 strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
37b8715b 1012
5ed6ace5 1013 da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1);
4977bab6
ZW
1014 strcpy (da_file_name, name);
1015 strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
f55ade6e 1016
a14df7da 1017 free (name);
4977bab6 1018 return;
86144b75 1019}
86144b75 1020
eeabee0a
NS
1021/* A is a string and B is a pointer to name_map_t. Compare for file
1022 name orderability. */
1023
1024static int
1025name_search (const void *a_, const void *b_)
1026{
1027 const char *a = (const char *)a_;
1028 const name_map_t *b = (const name_map_t *)b_;
1029
1030#if HAVE_DOS_BASED_FILE_SYSTEM
1031 return strcasecmp (a, b->name);
1032#else
1033 return strcmp (a, b->name);
1034#endif
1035}
1036
1037/* A and B are a pointer to name_map_t. Compare for file name
1038 orderability. */
1039
1040static int
1041name_sort (const void *a_, const void *b_)
1042{
1043 const name_map_t *a = (const name_map_t *)a_;
1044 return name_search (a->name, b_);
1045}
1046
94de45d9
NS
1047/* Find or create a source file structure for FILE_NAME. Copies
1048 FILE_NAME on creation */
27283c73 1049
1ce1b792 1050static unsigned
f55ade6e 1051find_source (const char *file_name)
27283c73 1052{
eeabee0a
NS
1053 name_map_t *name_map;
1054 char *canon;
1055 unsigned idx;
1a9075e2 1056 struct stat status;
94de45d9
NS
1057
1058 if (!file_name)
1059 file_name = "<unknown>";
eeabee0a
NS
1060 name_map = (name_map_t *)bsearch
1061 (file_name, names, n_names, sizeof (*names), name_search);
1062 if (name_map)
1063 {
1064 idx = name_map->src;
1065 goto check_date;
1066 }
f55ade6e 1067
eeabee0a 1068 if (n_names + 2 > a_names)
1a9075e2 1069 {
eeabee0a
NS
1070 /* Extend the name map array -- we'll be inserting one or two
1071 entries. */
eeabee0a
NS
1072 a_names *= 2;
1073 name_map = XNEWVEC (name_map_t, a_names);
1074 memcpy (name_map, names, n_names * sizeof (*names));
1075 free (names);
1076 names = name_map;
1077 }
1078
1079 /* Not found, try the canonical name. */
1080 canon = canonicalize_name (file_name);
1081 name_map = (name_map_t *)bsearch
1082 (canon, names, n_names, sizeof (*names), name_search);
1083 if (!name_map)
1084 {
1085 /* Not found with canonical name, create a new source. */
1086 source_t *src;
1087
1ce1b792
NS
1088 if (n_sources == a_sources)
1089 {
1ce1b792
NS
1090 a_sources *= 2;
1091 src = XNEWVEC (source_t, a_sources);
1092 memcpy (src, sources, n_sources * sizeof (*sources));
1093 free (sources);
1094 sources = src;
1095 }
eeabee0a
NS
1096
1097 idx = n_sources;
1098
1099 name_map = &names[n_names++];
1100 name_map->name = canon;
1101 name_map->src = idx;
1102
1103 src = &sources[n_sources++];
1104 memset (src, 0, sizeof (*src));
1105 src->name = canon;
1a9075e2 1106 src->coverage.name = src->name;
1bec9caa
NS
1107 if (source_length
1108#if HAVE_DOS_BASED_FILE_SYSTEM
1109 /* You lose if separators don't match exactly in the
1110 prefix. */
1111 && !strncasecmp (source_prefix, src->coverage.name, source_length)
1112#else
1113 && !strncmp (source_prefix, src->coverage.name, source_length)
1114#endif
1115 && IS_DIR_SEPARATOR (src->coverage.name[source_length]))
1116 src->coverage.name += source_length + 1;
eeabee0a 1117 if (!stat (src->name, &status))
1a9075e2
TG
1118 src->file_time = status.st_mtime;
1119 }
eeabee0a
NS
1120 else
1121 idx = name_map->src;
1122
1123 if (name_search (file_name, name_map))
1124 {
1125 /* Append the non-canonical name. */
1126 name_map = &names[n_names++];
1127 name_map->name = xstrdup (file_name);
1128 name_map->src = idx;
1129 }
1a9075e2 1130
eeabee0a
NS
1131 /* Resort the name map. */
1132 qsort (names, n_names, sizeof (*names), name_sort);
1133
1134 check_date:
1135 if (sources[idx].file_time > bbg_file_time)
1a9075e2
TG
1136 {
1137 static int info_emitted;
1138
efbb59b2 1139 fnotice (stderr, "%s:source file is newer than notes file '%s'\n",
eeabee0a 1140 file_name, bbg_file_name);
1a9075e2
TG
1141 if (!info_emitted)
1142 {
1143 fnotice (stderr,
1144 "(the message is only displayed one per source file)\n");
1145 info_emitted = 1;
1146 }
eeabee0a 1147 sources[idx].file_time = 0;
1a9075e2 1148 }
94de45d9 1149
eeabee0a 1150 return idx;
27283c73
NS
1151}
1152
efbb59b2 1153/* Read the notes file. Return list of functions read -- in reverse order. */
86144b75 1154
1ce1b792 1155static function_t *
f55ade6e 1156read_graph_file (void)
86144b75 1157{
94de45d9 1158 unsigned version;
4977bab6 1159 unsigned current_tag = 0;
1ce1b792
NS
1160 function_t *fn = NULL;
1161 function_t *fns = NULL;
1162 function_t **fns_end = &fns;
1163 unsigned src_idx = 0;
4977bab6 1164 unsigned ix;
7d63a2fa 1165 unsigned tag;
f55ade6e 1166
546d2adb 1167 if (!gcov_open (bbg_file_name, 1))
86144b75 1168 {
efbb59b2 1169 fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name);
1ce1b792 1170 return fns;
86144b75 1171 }
546d2adb 1172 bbg_file_time = gcov_time ();
160e2e4f 1173 if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
b7c9bf28 1174 {
efbb59b2 1175 fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name);
546d2adb 1176 gcov_close ();
1ce1b792 1177 return fns;
4977bab6 1178 }
b7c9bf28 1179
94de45d9
NS
1180 version = gcov_read_unsigned ();
1181 if (version != GCOV_VERSION)
4977bab6
ZW
1182 {
1183 char v[4], e[4];
f55ade6e 1184
330d2e2a
NS
1185 GCOV_UNSIGNED2STRING (v, version);
1186 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
1187
9e637a26 1188 fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n",
4977bab6
ZW
1189 bbg_file_name, v, e);
1190 }
dd486eb2
NS
1191 bbg_stamp = gcov_read_unsigned ();
1192
7d63a2fa 1193 while ((tag = gcov_read_unsigned ()))
4977bab6 1194 {
94de45d9 1195 unsigned length = gcov_read_unsigned ();
7d63a2fa 1196 gcov_position_t base = gcov_position ();
796621e8 1197
4977bab6 1198 if (tag == GCOV_TAG_FUNCTION)
b7c9bf28 1199 {
94de45d9 1200 char *function_name;
10adac51
XDL
1201 unsigned ident, lineno;
1202 unsigned lineno_checksum, cfg_checksum;
4977bab6 1203
796621e8 1204 ident = gcov_read_unsigned ();
10adac51
XDL
1205 lineno_checksum = gcov_read_unsigned ();
1206 cfg_checksum = gcov_read_unsigned ();
796621e8 1207 function_name = xstrdup (gcov_read_string ());
1ce1b792 1208 src_idx = find_source (gcov_read_string ());
94de45d9 1209 lineno = gcov_read_unsigned ();
f55ade6e 1210
5ed6ace5 1211 fn = XCNEW (function_t);
4977bab6 1212 fn->name = function_name;
fc8a650e
SS
1213 if (flag_demangled_names)
1214 {
1215 fn->demangled_name = cplus_demangle (fn->name, DMGL_PARAMS);
1216 if (!fn->demangled_name)
1217 fn->demangled_name = fn->name;
1218 }
796621e8 1219 fn->ident = ident;
10adac51
XDL
1220 fn->lineno_checksum = lineno_checksum;
1221 fn->cfg_checksum = cfg_checksum;
1ce1b792 1222 fn->src = src_idx;
27283c73 1223 fn->line = lineno;
4977bab6 1224
1ce1b792
NS
1225 fn->line_next = NULL;
1226 fn->next = NULL;
1227 *fns_end = fn;
1228 fns_end = &fn->next;
4977bab6 1229 current_tag = tag;
b7c9bf28 1230 }
4977bab6 1231 else if (fn && tag == GCOV_TAG_BLOCKS)
b7c9bf28 1232 {
4977bab6 1233 if (fn->blocks)
9e637a26 1234 fnotice (stderr, "%s:already seen blocks for '%s'\n",
4977bab6
ZW
1235 bbg_file_name, fn->name);
1236 else
b7c9bf28 1237 {
330d2e2a 1238 unsigned ix, num_blocks = GCOV_TAG_BLOCKS_NUM (length);
27283c73 1239 fn->num_blocks = num_blocks;
f55ade6e 1240
5ed6ace5 1241 fn->blocks = XCNEWVEC (block_t, fn->num_blocks);
27283c73 1242 for (ix = 0; ix != num_blocks; ix++)
94de45d9 1243 fn->blocks[ix].flags = gcov_read_unsigned ();
b7c9bf28 1244 }
4977bab6
ZW
1245 }
1246 else if (fn && tag == GCOV_TAG_ARCS)
1247 {
94de45d9 1248 unsigned src = gcov_read_unsigned ();
330d2e2a 1249 unsigned num_dests = GCOV_TAG_ARCS_NUM (length);
8919c0d9
NS
1250 block_t *src_blk = &fn->blocks[src];
1251 unsigned mark_catches = 0;
1252 struct arc_info *arc;
4977bab6 1253
94de45d9 1254 if (src >= fn->num_blocks || fn->blocks[src].succ)
4977bab6 1255 goto corrupt;
f55ade6e 1256
4977bab6 1257 while (num_dests--)
b7c9bf28 1258 {
94de45d9
NS
1259 unsigned dest = gcov_read_unsigned ();
1260 unsigned flags = gcov_read_unsigned ();
f55ade6e 1261
94de45d9 1262 if (dest >= fn->num_blocks)
4977bab6 1263 goto corrupt;
5ed6ace5 1264 arc = XCNEW (arc_t);
f55ade6e 1265
4977bab6 1266 arc->dst = &fn->blocks[dest];
8919c0d9 1267 arc->src = src_blk;
f55ade6e 1268
4977bab6
ZW
1269 arc->count = 0;
1270 arc->count_valid = 0;
1271 arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
1272 arc->fake = !!(flags & GCOV_ARC_FAKE);
1273 arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
f55ade6e 1274
8919c0d9
NS
1275 arc->succ_next = src_blk->succ;
1276 src_blk->succ = arc;
1277 src_blk->num_succ++;
f55ade6e 1278
4977bab6
ZW
1279 arc->pred_next = fn->blocks[dest].pred;
1280 fn->blocks[dest].pred = arc;
1281 fn->blocks[dest].num_pred++;
1282
27283c73
NS
1283 if (arc->fake)
1284 {
1285 if (src)
1286 {
1287 /* Exceptional exit from this function, the
1288 source block must be a call. */
1289 fn->blocks[src].is_call_site = 1;
1290 arc->is_call_non_return = 1;
8919c0d9 1291 mark_catches = 1;
27283c73
NS
1292 }
1293 else
1294 {
1295 /* Non-local return from a callee of this
8919c0d9 1296 function. The destination block is a setjmp. */
27283c73
NS
1297 arc->is_nonlocal_return = 1;
1298 fn->blocks[dest].is_nonlocal_return = 1;
1299 }
1300 }
f55ade6e 1301
4977bab6
ZW
1302 if (!arc->on_tree)
1303 fn->num_counts++;
b7c9bf28 1304 }
8919c0d9
NS
1305
1306 if (mark_catches)
1307 {
1308 /* We have a fake exit from this block. The other
1309 non-fall through exits must be to catch handlers.
1310 Mark them as catch arcs. */
1311
1312 for (arc = src_blk->succ; arc; arc = arc->succ_next)
1313 if (!arc->fake && !arc->fall_through)
1314 {
1315 arc->is_throw = 1;
1316 fn->has_catch = 1;
1317 }
1318 }
4977bab6
ZW
1319 }
1320 else if (fn && tag == GCOV_TAG_LINES)
1321 {
94de45d9 1322 unsigned blockno = gcov_read_unsigned ();
5ed6ace5 1323 unsigned *line_nos = XCNEWVEC (unsigned, length - 1);
4977bab6 1324
94de45d9 1325 if (blockno >= fn->num_blocks || fn->blocks[blockno].u.line.encoding)
4977bab6 1326 goto corrupt;
f55ade6e 1327
4977bab6 1328 for (ix = 0; ; )
b7c9bf28 1329 {
94de45d9 1330 unsigned lineno = gcov_read_unsigned ();
f55ade6e 1331
4977bab6 1332 if (lineno)
b7c9bf28 1333 {
4977bab6
ZW
1334 if (!ix)
1335 {
1336 line_nos[ix++] = 0;
1ce1b792 1337 line_nos[ix++] = src_idx;
4977bab6
ZW
1338 }
1339 line_nos[ix++] = lineno;
b7c9bf28 1340 }
4977bab6
ZW
1341 else
1342 {
94de45d9 1343 const char *file_name = gcov_read_string ();
f55ade6e 1344
4977bab6 1345 if (!file_name)
b7c9bf28 1346 break;
1ce1b792 1347 src_idx = find_source (file_name);
4977bab6 1348 line_nos[ix++] = 0;
1ce1b792 1349 line_nos[ix++] = src_idx;
4977bab6 1350 }
b7c9bf28 1351 }
f55ade6e 1352
27283c73
NS
1353 fn->blocks[blockno].u.line.encoding = line_nos;
1354 fn->blocks[blockno].u.line.num = ix;
4977bab6
ZW
1355 }
1356 else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
1357 {
1358 fn = NULL;
1359 current_tag = 0;
1360 }
474f141e 1361 gcov_sync (base, length);
94de45d9 1362 if (gcov_is_error ())
00cf2913
NS
1363 {
1364 corrupt:;
1365 fnotice (stderr, "%s:corrupted\n", bbg_file_name);
1ce1b792 1366 break;
00cf2913 1367 }
b7c9bf28 1368 }
546d2adb 1369 gcov_close ();
f55ade6e 1370
1ce1b792
NS
1371 if (!fns)
1372 fnotice (stderr, "%s:no functions found\n", bbg_file_name);
b7c9bf28 1373
1ce1b792 1374 return fns;
b7c9bf28 1375}
86144b75 1376
4977bab6 1377/* Reads profiles from the count file and attach to each
272d0bee 1378 function. Return nonzero if fatal error. */
86144b75 1379
4977bab6 1380static int
1ce1b792 1381read_count_file (function_t *fns)
86144b75 1382{
4977bab6 1383 unsigned ix;
94de45d9 1384 unsigned version;
7d63a2fa 1385 unsigned tag;
4977bab6 1386 function_t *fn = NULL;
7d63a2fa 1387 int error = 0;
4977bab6 1388
546d2adb 1389 if (!gcov_open (da_file_name, 1))
86144b75 1390 {
80b3502b
NS
1391 fnotice (stderr, "%s:cannot open data file, assuming not executed\n",
1392 da_file_name);
1393 no_data_file = 1;
1394 return 0;
4977bab6 1395 }
160e2e4f 1396 if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
4977bab6
ZW
1397 {
1398 fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
1399 cleanup:;
546d2adb 1400 gcov_close ();
4977bab6
ZW
1401 return 1;
1402 }
94de45d9
NS
1403 version = gcov_read_unsigned ();
1404 if (version != GCOV_VERSION)
4977bab6 1405 {
330d2e2a
NS
1406 char v[4], e[4];
1407
1408 GCOV_UNSIGNED2STRING (v, version);
1409 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
b8698a0f 1410
9e637a26 1411 fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n",
330d2e2a 1412 da_file_name, v, e);
86144b75 1413 }
dd486eb2
NS
1414 tag = gcov_read_unsigned ();
1415 if (tag != bbg_stamp)
1416 {
efbb59b2 1417 fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name);
dd486eb2
NS
1418 goto cleanup;
1419 }
f55ade6e 1420
7d63a2fa 1421 while ((tag = gcov_read_unsigned ()))
4977bab6 1422 {
94de45d9
NS
1423 unsigned length = gcov_read_unsigned ();
1424 unsigned long base = gcov_position ();
94de45d9 1425
5366b186 1426 if (tag == GCOV_TAG_PROGRAM_SUMMARY)
86144b75 1427 {
5366b186
NS
1428 struct gcov_summary summary;
1429 gcov_read_summary (&summary);
1430 object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs;
1431 program_count++;
1432 }
1433 else if (tag == GCOV_TAG_FUNCTION && !length)
1434 ; /* placeholder */
1435 else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH)
1436 {
1437 unsigned ident;
1438 struct function_info *fn_n;
4977bab6 1439
5366b186
NS
1440 /* Try to find the function in the list. To speed up the
1441 search, first start from the last function found. */
1442 ident = gcov_read_unsigned ();
1ce1b792 1443 fn_n = fns;
5366b186
NS
1444 for (fn = fn ? fn->next : NULL; ; fn = fn->next)
1445 {
1446 if (fn)
1447 ;
1448 else if ((fn = fn_n))
1449 fn_n = NULL;
1450 else
1451 {
1452 fnotice (stderr, "%s:unknown function '%u'\n",
1453 da_file_name, ident);
4977bab6 1454 break;
5366b186
NS
1455 }
1456 if (fn->ident == ident)
1457 break;
1458 }
4977bab6
ZW
1459
1460 if (!fn)
1461 ;
10adac51
XDL
1462 else if (gcov_read_unsigned () != fn->lineno_checksum
1463 || gcov_read_unsigned () != fn->cfg_checksum)
86144b75 1464 {
4977bab6 1465 mismatch:;
9e637a26 1466 fnotice (stderr, "%s:profile mismatch for '%s'\n",
94de45d9 1467 da_file_name, fn->name);
4977bab6
ZW
1468 goto cleanup;
1469 }
1470 }
cdb23767 1471 else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
4977bab6 1472 {
330d2e2a 1473 if (length != GCOV_TAG_COUNTER_LENGTH (fn->num_counts))
4977bab6 1474 goto mismatch;
f55ade6e 1475
4977bab6 1476 if (!fn->counts)
5ed6ace5 1477 fn->counts = XCNEWVEC (gcov_type, fn->num_counts);
f55ade6e 1478
4977bab6 1479 for (ix = 0; ix != fn->num_counts; ix++)
94de45d9
NS
1480 fn->counts[ix] += gcov_read_counter ();
1481 }
474f141e 1482 gcov_sync (base, length);
94de45d9 1483 if ((error = gcov_is_error ()))
00cf2913
NS
1484 {
1485 fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
1486 da_file_name);
1487 goto cleanup;
1488 }
7d63a2fa 1489 }
f55ade6e 1490
546d2adb 1491 gcov_close ();
4977bab6 1492 return 0;
86144b75
DE
1493}
1494
4977bab6
ZW
1495/* Solve the flow graph. Propagate counts from the instrumented arcs
1496 to the blocks and the uninstrumented arcs. */
86144b75
DE
1497
1498static void
f55ade6e 1499solve_flow_graph (function_t *fn)
86144b75 1500{
4977bab6
ZW
1501 unsigned ix;
1502 arc_t *arc;
1503 gcov_type *count_ptr = fn->counts;
27283c73 1504 block_t *blk;
32dd366d
KH
1505 block_t *valid_blocks = NULL; /* valid, but unpropagated blocks. */
1506 block_t *invalid_blocks = NULL; /* invalid, but inferable blocks. */
f55ade6e 1507
1ce1b792
NS
1508 /* The arcs were built in reverse order. Fix that now. */
1509 for (ix = fn->num_blocks; ix--;)
1510 {
1511 arc_t *arc_p, *arc_n;
1512
1513 for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
1514 arc_p = arc, arc = arc_n)
1515 {
1516 arc_n = arc->succ_next;
1517 arc->succ_next = arc_p;
1518 }
1519 fn->blocks[ix].succ = arc_p;
1520
1521 for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
1522 arc_p = arc, arc = arc_n)
1523 {
1524 arc_n = arc->pred_next;
1525 arc->pred_next = arc_p;
1526 }
1527 fn->blocks[ix].pred = arc_p;
1528 }
1529
4977bab6 1530 if (fn->num_blocks < 2)
9e637a26 1531 fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n",
4977bab6
ZW
1532 bbg_file_name, fn->name);
1533 else
86144b75 1534 {
9696c529 1535 if (fn->blocks[ENTRY_BLOCK].num_pred)
9e637a26 1536 fnotice (stderr, "%s:'%s' has arcs to entry block\n",
4977bab6 1537 bbg_file_name, fn->name);
86144b75 1538 else
4977bab6
ZW
1539 /* We can't deduce the entry block counts from the lack of
1540 predecessors. */
9696c529 1541 fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
f55ade6e 1542
9696c529 1543 if (fn->blocks[EXIT_BLOCK].num_succ)
9e637a26 1544 fnotice (stderr, "%s:'%s' has arcs from exit block\n",
4977bab6
ZW
1545 bbg_file_name, fn->name);
1546 else
1547 /* Likewise, we can't deduce exit block counts from the lack
1548 of its successors. */
9696c529 1549 fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
86144b75
DE
1550 }
1551
4977bab6
ZW
1552 /* Propagate the measured counts, this must be done in the same
1553 order as the code in profile.c */
27283c73 1554 for (ix = 0, blk = fn->blocks; ix != fn->num_blocks; ix++, blk++)
86144b75 1555 {
4977bab6
ZW
1556 block_t const *prev_dst = NULL;
1557 int out_of_order = 0;
27283c73 1558 int non_fake_succ = 0;
f55ade6e 1559
27283c73 1560 for (arc = blk->succ; arc; arc = arc->succ_next)
86144b75 1561 {
27283c73
NS
1562 if (!arc->fake)
1563 non_fake_succ++;
f55ade6e 1564
4977bab6 1565 if (!arc->on_tree)
86144b75 1566 {
4977bab6
ZW
1567 if (count_ptr)
1568 arc->count = *count_ptr++;
1569 arc->count_valid = 1;
27283c73 1570 blk->num_succ--;
4977bab6 1571 arc->dst->num_pred--;
86144b75 1572 }
4977bab6
ZW
1573 if (prev_dst && prev_dst > arc->dst)
1574 out_of_order = 1;
1575 prev_dst = arc->dst;
86144b75 1576 }
27283c73
NS
1577 if (non_fake_succ == 1)
1578 {
1579 /* If there is only one non-fake exit, it is an
1580 unconditional branch. */
1581 for (arc = blk->succ; arc; arc = arc->succ_next)
1582 if (!arc->fake)
1583 {
1584 arc->is_unconditional = 1;
1585 /* If this block is instrumenting a call, it might be
e0bb17a8 1586 an artificial block. It is not artificial if it has
10b7602f
NS
1587 a non-fallthrough exit, or the destination of this
1588 arc has more than one entry. Mark the destination
1589 block as a return site, if none of those conditions
1590 hold. */
1591 if (blk->is_call_site && arc->fall_through
1592 && arc->dst->pred == arc && !arc->pred_next)
1593 arc->dst->is_call_return = 1;
27283c73
NS
1594 }
1595 }
f55ade6e 1596
4977bab6
ZW
1597 /* Sort the successor arcs into ascending dst order. profile.c
1598 normally produces arcs in the right order, but sometimes with
1599 one or two out of order. We're not using a particularly
32dd366d 1600 smart sort. */
4977bab6 1601 if (out_of_order)
86144b75 1602 {
27283c73 1603 arc_t *start = blk->succ;
4977bab6 1604 unsigned changes = 1;
f55ade6e 1605
4977bab6
ZW
1606 while (changes)
1607 {
1608 arc_t *arc, *arc_p, *arc_n;
f55ade6e 1609
4977bab6
ZW
1610 changes = 0;
1611 for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1612 {
1613 if (arc->dst > arc_n->dst)
1614 {
1615 changes = 1;
1616 if (arc_p)
1617 arc_p->succ_next = arc_n;
1618 else
1619 start = arc_n;
1620 arc->succ_next = arc_n->succ_next;
1621 arc_n->succ_next = arc;
1622 arc_p = arc_n;
1623 }
1624 else
1625 {
1626 arc_p = arc;
1627 arc = arc_n;
1628 }
1629 }
1630 }
27283c73 1631 blk->succ = start;
86144b75 1632 }
f55ade6e 1633
4977bab6
ZW
1634 /* Place it on the invalid chain, it will be ignored if that's
1635 wrong. */
27283c73
NS
1636 blk->invalid_chain = 1;
1637 blk->chain = invalid_blocks;
1638 invalid_blocks = blk;
4977bab6
ZW
1639 }
1640
1641 while (invalid_blocks || valid_blocks)
1642 {
4977bab6 1643 while ((blk = invalid_blocks))
86144b75 1644 {
4977bab6
ZW
1645 gcov_type total = 0;
1646 const arc_t *arc;
f55ade6e 1647
4977bab6
ZW
1648 invalid_blocks = blk->chain;
1649 blk->invalid_chain = 0;
1650 if (!blk->num_succ)
1651 for (arc = blk->succ; arc; arc = arc->succ_next)
1652 total += arc->count;
1653 else if (!blk->num_pred)
1654 for (arc = blk->pred; arc; arc = arc->pred_next)
1655 total += arc->count;
1656 else
1657 continue;
f55ade6e 1658
4977bab6
ZW
1659 blk->count = total;
1660 blk->count_valid = 1;
1661 blk->chain = valid_blocks;
1662 blk->valid_chain = 1;
1663 valid_blocks = blk;
86144b75 1664 }
4977bab6 1665 while ((blk = valid_blocks))
86144b75 1666 {
4977bab6
ZW
1667 gcov_type total;
1668 arc_t *arc, *inv_arc;
1669
1670 valid_blocks = blk->chain;
1671 blk->valid_chain = 0;
1672 if (blk->num_succ == 1)
1673 {
1674 block_t *dst;
f55ade6e 1675
4977bab6
ZW
1676 total = blk->count;
1677 inv_arc = NULL;
1678 for (arc = blk->succ; arc; arc = arc->succ_next)
1679 {
1680 total -= arc->count;
1681 if (!arc->count_valid)
1682 inv_arc = arc;
1683 }
1684 dst = inv_arc->dst;
1685 inv_arc->count_valid = 1;
1686 inv_arc->count = total;
1687 blk->num_succ--;
1688 dst->num_pred--;
1689 if (dst->count_valid)
1690 {
1691 if (dst->num_pred == 1 && !dst->valid_chain)
1692 {
1693 dst->chain = valid_blocks;
1694 dst->valid_chain = 1;
1695 valid_blocks = dst;
1696 }
1697 }
1698 else
1699 {
1700 if (!dst->num_pred && !dst->invalid_chain)
1701 {
1702 dst->chain = invalid_blocks;
1703 dst->invalid_chain = 1;
1704 invalid_blocks = dst;
1705 }
1706 }
1707 }
1708 if (blk->num_pred == 1)
1709 {
1710 block_t *src;
f55ade6e 1711
4977bab6
ZW
1712 total = blk->count;
1713 inv_arc = NULL;
1714 for (arc = blk->pred; arc; arc = arc->pred_next)
1715 {
1716 total -= arc->count;
1717 if (!arc->count_valid)
1718 inv_arc = arc;
1719 }
1720 src = inv_arc->src;
1721 inv_arc->count_valid = 1;
1722 inv_arc->count = total;
1723 blk->num_pred--;
1724 src->num_succ--;
1725 if (src->count_valid)
1726 {
1727 if (src->num_succ == 1 && !src->valid_chain)
1728 {
1729 src->chain = valid_blocks;
1730 src->valid_chain = 1;
1731 valid_blocks = src;
1732 }
1733 }
1734 else
1735 {
1736 if (!src->num_succ && !src->invalid_chain)
1737 {
1738 src->chain = invalid_blocks;
1739 src->invalid_chain = 1;
1740 invalid_blocks = src;
1741 }
1742 }
1743 }
86144b75
DE
1744 }
1745 }
f55ade6e 1746
4977bab6
ZW
1747 /* If the graph has been correctly solved, every block will have a
1748 valid count. */
1749 for (ix = 0; ix < fn->num_blocks; ix++)
1750 if (!fn->blocks[ix].count_valid)
1751 {
9e637a26 1752 fnotice (stderr, "%s:graph is unsolvable for '%s'\n",
4977bab6
ZW
1753 bbg_file_name, fn->name);
1754 break;
1755 }
86144b75 1756}
4977bab6 1757
8919c0d9
NS
1758/* Mark all the blocks only reachable via an incoming catch. */
1759
1760static void
1761find_exception_blocks (function_t *fn)
1762{
1763 unsigned ix;
1764 block_t **queue = XALLOCAVEC (block_t *, fn->num_blocks);
1765
1766 /* First mark all blocks as exceptional. */
1767 for (ix = fn->num_blocks; ix--;)
1768 fn->blocks[ix].exceptional = 1;
1769
1770 /* Now mark all the blocks reachable via non-fake edges */
1771 queue[0] = fn->blocks;
1772 queue[0]->exceptional = 0;
1773 for (ix = 1; ix;)
1774 {
1775 block_t *block = queue[--ix];
1776 const arc_t *arc;
1777
1778 for (arc = block->succ; arc; arc = arc->succ_next)
1779 if (!arc->fake && !arc->is_throw && arc->dst->exceptional)
1780 {
1781 arc->dst->exceptional = 0;
1782 queue[ix++] = arc->dst;
1783 }
1784 }
1785}
86144b75 1786\f
86144b75 1787
4977bab6 1788/* Increment totals in COVERAGE according to arc ARC. */
8b219a76
NS
1789
1790static void
f55ade6e 1791add_branch_counts (coverage_t *coverage, const arc_t *arc)
8b219a76 1792{
27283c73 1793 if (arc->is_call_non_return)
8b219a76 1794 {
4977bab6
ZW
1795 coverage->calls++;
1796 if (arc->src->count)
1797 coverage->calls_executed++;
8b219a76 1798 }
27283c73 1799 else if (!arc->is_unconditional)
8b219a76 1800 {
4977bab6
ZW
1801 coverage->branches++;
1802 if (arc->src->count)
1803 coverage->branches_executed++;
1804 if (arc->count)
1805 coverage->branches_taken++;
86144b75
DE
1806 }
1807}
1808
9696c529 1809/* Format a GCOV_TYPE integer as either a percent ratio, or absolute
37b8715b
NS
1810 count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1811 If DP is zero, no decimal point is printed. Only print 100% when
1812 TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
1813 format TOP. Return pointer to a static string. */
1814
1815static char const *
f55ade6e 1816format_gcov (gcov_type top, gcov_type bottom, int dp)
37b8715b
NS
1817{
1818 static char buffer[20];
f55ade6e 1819
37b8715b
NS
1820 if (dp >= 0)
1821 {
1822 float ratio = bottom ? (float)top / bottom : 0;
1823 int ix;
1824 unsigned limit = 100;
1825 unsigned percent;
f55ade6e 1826
37b8715b
NS
1827 for (ix = dp; ix--; )
1828 limit *= 10;
f55ade6e 1829
d19202ba
NS
1830 percent = (unsigned) (ratio * limit + (float)0.5);
1831 if (percent <= 0 && top)
37b8715b 1832 percent = 1;
d19202ba 1833 else if (percent >= limit && top != bottom)
37b8715b
NS
1834 percent = limit - 1;
1835 ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1836 if (dp)
1837 {
1838 dp++;
1839 do
1840 {
1841 buffer[ix+1] = buffer[ix];
1842 ix--;
1843 }
1844 while (dp--);
1845 buffer[ix + 1] = '.';
1846 }
1847 }
1848 else
4977bab6 1849 sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
f55ade6e 1850
37b8715b
NS
1851 return buffer;
1852}
1853
bdbdc4e1 1854/* Summary of execution */
86144b75
DE
1855
1856static void
bdbdc4e1 1857executed_summary (unsigned lines, unsigned executed)
86144b75 1858{
bdbdc4e1 1859 if (lines)
4977bab6 1860 fnotice (stdout, "Lines executed:%s of %d\n",
bdbdc4e1 1861 format_gcov (executed, lines, 2), lines);
86144b75 1862 else
1457ebf9 1863 fnotice (stdout, "No executable lines\n");
bdbdc4e1
NS
1864}
1865
1866/* Output summary info for a function or file. */
1867
1868static void
1869function_summary (const coverage_t *coverage, const char *title)
1870{
1871 fnotice (stdout, "%s '%s'\n", title, coverage->name);
1872 executed_summary (coverage->lines, coverage->lines_executed);
86144b75 1873
4977bab6 1874 if (flag_branches)
86144b75 1875 {
4977bab6 1876 if (coverage->branches)
86144b75 1877 {
4977bab6
ZW
1878 fnotice (stdout, "Branches executed:%s of %d\n",
1879 format_gcov (coverage->branches_executed,
1880 coverage->branches, 2),
1881 coverage->branches);
1882 fnotice (stdout, "Taken at least once:%s of %d\n",
1883 format_gcov (coverage->branches_taken,
1884 coverage->branches, 2),
1885 coverage->branches);
86144b75
DE
1886 }
1887 else
4977bab6
ZW
1888 fnotice (stdout, "No branches\n");
1889 if (coverage->calls)
1890 fnotice (stdout, "Calls executed:%s of %d\n",
1891 format_gcov (coverage->calls_executed, coverage->calls, 2),
1892 coverage->calls);
86144b75 1893 else
4977bab6 1894 fnotice (stdout, "No calls\n");
8b219a76
NS
1895 }
1896}
1897
eeabee0a
NS
1898/* Canonicalize the filename NAME by canonicalizing directory
1899 separators, eliding . components and resolving .. components
1900 appropriately. Always returns a unique string. */
1901
1902static char *
1903canonicalize_name (const char *name)
1904{
1905 /* The canonical name cannot be longer than the incoming name. */
1906 char *result = XNEWVEC (char, strlen (name) + 1);
1907 const char *base = name, *probe;
1908 char *ptr = result;
1909 char *dd_base;
1910 int slash = 0;
1911
1912#if HAVE_DOS_BASED_FILE_SYSTEM
1913 if (base[0] && base[1] == ':')
1914 {
1915 result[0] = base[0];
1916 result[1] = ':';
1917 base += 2;
1918 ptr += 2;
1919 }
1920#endif
1921 for (dd_base = ptr; *base; base = probe)
1922 {
1923 size_t len;
1924
1925 for (probe = base; *probe; probe++)
1926 if (IS_DIR_SEPARATOR (*probe))
1927 break;
1928
1929 len = probe - base;
1930 if (len == 1 && base[0] == '.')
1931 /* Elide a '.' directory */
1932 ;
1933 else if (len == 2 && base[0] == '.' && base[1] == '.')
1934 {
1935 /* '..', we can only elide it and the previous directory, if
1936 we're not a symlink. */
8c121ccb
NS
1937 struct stat ATTRIBUTE_UNUSED buf;
1938
eeabee0a 1939 *ptr = 0;
8c121ccb
NS
1940 if (dd_base == ptr
1941#if defined (S_ISLNK)
1942 /* S_ISLNK is not POSIX.1-1996. */
1943 || stat (result, &buf) || S_ISLNK (buf.st_mode)
1944#endif
1945 )
eeabee0a
NS
1946 {
1947 /* Cannot elide, or unreadable or a symlink. */
1948 dd_base = ptr + 2 + slash;
1949 goto regular;
1950 }
1951 while (ptr != dd_base && *ptr != '/')
1952 ptr--;
1953 slash = ptr != result;
1954 }
1955 else
1956 {
1957 regular:
1958 /* Regular pathname component. */
1959 if (slash)
1960 *ptr++ = '/';
1961 memcpy (ptr, base, len);
1962 ptr += len;
1963 slash = 1;
1964 }
1965
1966 for (; IS_DIR_SEPARATOR (*probe); probe++)
1967 continue;
1968 }
1969 *ptr = 0;
1970
1971 return result;
1972}
1973
1974/* Generate an output file name. INPUT_NAME is the canonicalized main
1975 input file and SRC_NAME is the canonicalized file name.
1976 LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With
8b219a76
NS
1977 long_output_names we prepend the processed name of the input file
1978 to each output name (except when the current source file is the
1979 input file, so you don't get a double concatenation). The two
eeabee0a
NS
1980 components are separated by '##'. With preserve_paths we create a
1981 filename from all path components of the source file, replacing '/'
1982 with '#', and .. with '^', without it we simply take the basename
1983 component. (Remember, the canonicalized name will already have
1984 elided '.' components and converted \\ separators.) */
8b219a76
NS
1985
1986static char *
f55ade6e 1987make_gcov_file_name (const char *input_name, const char *src_name)
8b219a76 1988{
eeabee0a
NS
1989 char *ptr;
1990 char *result;
f55ade6e 1991
1a9075e2 1992 if (flag_long_names && input_name && strcmp (src_name, input_name))
8b219a76
NS
1993 {
1994 /* Generate the input filename part. */
eeabee0a
NS
1995 result = XNEWVEC (char, strlen (input_name) + strlen (src_name) + 10);
1996
1997 ptr = result;
1998 ptr = mangle_name (input_name, ptr);
1999 ptr[0] = ptr[1] = '#';
2000 ptr += 2;
8b219a76 2001 }
1a9075e2
TG
2002 else
2003 {
eeabee0a
NS
2004 result = XNEWVEC (char, strlen (src_name) + 10);
2005 ptr = result;
1a9075e2 2006 }
f55ade6e 2007
eeabee0a
NS
2008 ptr = mangle_name (src_name, ptr);
2009 strcpy (ptr, ".gcov");
2010
2011 return result;
2012}
f55ade6e 2013
eeabee0a
NS
2014static char *
2015mangle_name (char const *base, char *ptr)
2016{
2017 size_t len;
2018
2019 /* Generate the source filename part. */
2020 if (!flag_preserve_paths)
2021 {
2022 base = lbasename (base);
2023 len = strlen (base);
2024 memcpy (ptr, base, len);
2025 ptr += len;
2026 }
2027 else
8b219a76 2028 {
eeabee0a 2029 /* Convert '/' to '#', convert '..' to '^',
2f07423c 2030 convert ':' to '~' on DOS based file system. */
eeabee0a 2031 const char *probe;
f55ade6e 2032
eeabee0a
NS
2033#if HAVE_DOS_BASED_FILE_SYSTEM
2034 if (base[0] && base[1] == ':')
2f07423c 2035 {
eeabee0a
NS
2036 ptr[0] = base[0];
2037 ptr[1] = '~';
2038 ptr += 2;
2039 base += 2;
2040 }
2f07423c 2041#endif
eeabee0a
NS
2042 for (; *base; base = probe)
2043 {
2044 size_t len;
2045
2046 for (probe = base; *probe; probe++)
2047 if (*probe == '/')
2048 break;
2049 len = probe - base;
2050 if (len == 2 && base[0] == '.' && base[1] == '.')
2051 *ptr++ = '^';
2052 else
2f07423c 2053 {
eeabee0a
NS
2054 memcpy (ptr, base, len);
2055 ptr += len;
2f07423c 2056 }
eeabee0a 2057 if (*probe)
ba78087b 2058 {
eeabee0a
NS
2059 *ptr++ = '#';
2060 probe++;
ba78087b 2061 }
f55ade6e 2062 }
86144b75 2063 }
eeabee0a
NS
2064
2065 return ptr;
86144b75
DE
2066}
2067
4977bab6 2068/* Scan through the bb_data for each line in the block, increment
8b219a76
NS
2069 the line number execution count indicated by the execution count of
2070 the appropriate basic block. */
86144b75
DE
2071
2072static void
f55ade6e 2073add_line_counts (coverage_t *coverage, function_t *fn)
86144b75 2074{
4977bab6 2075 unsigned ix;
beb235f8 2076 line_t *line = NULL; /* This is propagated from one iteration to the
4977bab6
ZW
2077 next. */
2078
32dd366d 2079 /* Scan each basic block. */
4977bab6 2080 for (ix = 0; ix != fn->num_blocks; ix++)
86144b75 2081 {
27283c73 2082 block_t *block = &fn->blocks[ix];
4977bab6
ZW
2083 unsigned *encoding;
2084 const source_t *src = NULL;
2085 unsigned jx;
2086
27283c73
NS
2087 if (block->count && ix && ix + 1 != fn->num_blocks)
2088 fn->blocks_executed++;
2089 for (jx = 0, encoding = block->u.line.encoding;
2090 jx != block->u.line.num; jx++, encoding++)
4977bab6
ZW
2091 if (!*encoding)
2092 {
1ce1b792 2093 src = &sources[*++encoding];
4977bab6
ZW
2094 jx++;
2095 }
2096 else
2097 {
2098 line = &src->lines[*encoding];
2099
2100 if (coverage)
2101 {
2102 if (!line->exists)
2103 coverage->lines++;
27283c73 2104 if (!line->count && block->count)
4977bab6
ZW
2105 coverage->lines_executed++;
2106 }
2107 line->exists = 1;
8919c0d9
NS
2108 if (!block->exceptional)
2109 line->unexceptional = 1;
4977bab6
ZW
2110 line->count += block->count;
2111 }
27283c73 2112 free (block->u.line.encoding);
10b7602f
NS
2113 block->u.cycle.arc = NULL;
2114 block->u.cycle.ident = ~0U;
f55ade6e 2115
27283c73
NS
2116 if (!ix || ix + 1 == fn->num_blocks)
2117 /* Entry or exit block */;
2118 else if (flag_all_blocks)
86144b75 2119 {
1ce1b792
NS
2120 line_t *block_line = line;
2121
2122 if (!block_line)
2123 block_line = &sources[fn->src].lines[fn->line];
f55ade6e 2124
10b7602f
NS
2125 block->chain = block_line->u.blocks;
2126 block_line->u.blocks = block;
27283c73
NS
2127 }
2128 else if (flag_branches)
2129 {
2130 arc_t *arc;
2131
4977bab6 2132 for (arc = block->succ; arc; arc = arc->succ_next)
86144b75 2133 {
27283c73
NS
2134 arc->line_next = line->u.branches;
2135 line->u.branches = arc;
2136 if (coverage && !arc->is_unconditional)
4977bab6 2137 add_branch_counts (coverage, arc);
86144b75 2138 }
8b219a76
NS
2139 }
2140 }
4977bab6 2141 if (!line)
9e637a26 2142 fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name);
4977bab6
ZW
2143}
2144
32dd366d 2145/* Accumulate the line counts of a file. */
4977bab6
ZW
2146
2147static void
f55ade6e 2148accumulate_line_counts (source_t *src)
4977bab6
ZW
2149{
2150 line_t *line;
27283c73 2151 function_t *fn, *fn_p, *fn_n;
4977bab6 2152 unsigned ix;
27283c73
NS
2153
2154 /* Reverse the function order. */
2155 for (fn = src->functions, fn_p = NULL; fn;
2156 fn_p = fn, fn = fn_n)
2157 {
2158 fn_n = fn->line_next;
2159 fn->line_next = fn_p;
2160 }
2161 src->functions = fn_p;
f55ade6e 2162
4977bab6 2163 for (ix = src->num_lines, line = src->lines; ix--; line++)
8b219a76 2164 {
27283c73 2165 if (!flag_all_blocks)
8b219a76 2166 {
27283c73 2167 arc_t *arc, *arc_p, *arc_n;
f55ade6e 2168
27283c73
NS
2169 /* Total and reverse the branch information. */
2170 for (arc = line->u.branches, arc_p = NULL; arc;
2171 arc_p = arc, arc = arc_n)
2172 {
2173 arc_n = arc->line_next;
2174 arc->line_next = arc_p;
f55ade6e 2175
27283c73
NS
2176 add_branch_counts (&src->coverage, arc);
2177 }
2178 line->u.branches = arc_p;
8b219a76 2179 }
27283c73
NS
2180 else if (line->u.blocks)
2181 {
2182 /* The user expects the line count to be the number of times
2183 a line has been executed. Simply summing the block count
2184 will give an artificially high number. The Right Thing
10b7602f
NS
2185 is to sum the entry counts to the graph of blocks on this
2186 line, then find the elementary cycles of the local graph
2187 and add the transition counts of those cycles. */
27283c73 2188 block_t *block, *block_p, *block_n;
27283c73 2189 gcov_type count = 0;
f55ade6e 2190
f9da5064 2191 /* Reverse the block information. */
27283c73
NS
2192 for (block = line->u.blocks, block_p = NULL; block;
2193 block_p = block, block = block_n)
2194 {
2195 block_n = block->chain;
2196 block->chain = block_p;
10b7602f 2197 block->u.cycle.ident = ix;
27283c73
NS
2198 }
2199 line->u.blocks = block_p;
f55ade6e 2200
10b7602f
NS
2201 /* Sum the entry arcs. */
2202 for (block = line->u.blocks; block; block = block->chain)
2203 {
2204 arc_t *arc;
86144b75 2205
10b7602f
NS
2206 for (arc = block->pred; arc; arc = arc->pred_next)
2207 {
2208 if (arc->src->u.cycle.ident != ix)
2209 count += arc->count;
2210 if (flag_branches)
2211 add_branch_counts (&src->coverage, arc);
2212 }
3d7ca167
ZD
2213
2214 /* Initialize the cs_count. */
2215 for (arc = block->succ; arc; arc = arc->succ_next)
2216 arc->cs_count = arc->count;
10b7602f
NS
2217 }
2218
2219 /* Find the loops. This uses the algorithm described in
2220 Tiernan 'An Efficient Search Algorithm to Find the
2221 Elementary Circuits of a Graph', CACM Dec 1970. We hold
2222 the P array by having each block point to the arc that
2223 connects to the previous block. The H array is implicitly
2224 held because of the arc ordering, and the block's
2225 previous arc pointer.
2226
2227 Although the algorithm is O(N^3) for highly connected
2228 graphs, at worst we'll have O(N^2), as most blocks have
2229 only one or two exits. Most graphs will be small.
2230
2231 For each loop we find, locate the arc with the smallest
2232 transition count, and add that to the cumulative
3d7ca167
ZD
2233 count. Decrease flow over the cycle and remove the arc
2234 from consideration. */
10b7602f 2235 for (block = line->u.blocks; block; block = block->chain)
27283c73 2236 {
10b7602f
NS
2237 block_t *head = block;
2238 arc_t *arc;
f55ade6e 2239
10b7602f
NS
2240 next_vertex:;
2241 arc = head->succ;
2242 current_vertex:;
2243 while (arc)
27283c73 2244 {
10b7602f
NS
2245 block_t *dst = arc->dst;
2246 if (/* Already used that arc. */
2247 arc->cycle
2248 /* Not to same graph, or before first vertex. */
2249 || dst->u.cycle.ident != ix
2250 /* Already in path. */
2251 || dst->u.cycle.arc)
2252 {
2253 arc = arc->succ_next;
2254 continue;
2255 }
f55ade6e 2256
10b7602f 2257 if (dst == block)
27283c73 2258 {
10b7602f 2259 /* Found a closing arc. */
3d7ca167 2260 gcov_type cycle_count = arc->cs_count;
10b7602f
NS
2261 arc_t *cycle_arc = arc;
2262 arc_t *probe_arc;
f55ade6e 2263
71c0e7fc 2264 /* Locate the smallest arc count of the loop. */
10b7602f
NS
2265 for (dst = head; (probe_arc = dst->u.cycle.arc);
2266 dst = probe_arc->src)
3d7ca167 2267 if (cycle_count > probe_arc->cs_count)
10b7602f 2268 {
3d7ca167 2269 cycle_count = probe_arc->cs_count;
10b7602f
NS
2270 cycle_arc = probe_arc;
2271 }
f55ade6e 2272
10b7602f
NS
2273 count += cycle_count;
2274 cycle_arc->cycle = 1;
3d7ca167
ZD
2275
2276 /* Remove the flow from the cycle. */
2277 arc->cs_count -= cycle_count;
2278 for (dst = head; (probe_arc = dst->u.cycle.arc);
2279 dst = probe_arc->src)
2280 probe_arc->cs_count -= cycle_count;
2281
10b7602f
NS
2282 /* Unwind to the cyclic arc. */
2283 while (head != cycle_arc->src)
27283c73 2284 {
10b7602f 2285 arc = head->u.cycle.arc;
3d7ca167 2286 head->u.cycle.arc = NULL;
10b7602f 2287 head = arc->src;
27283c73 2288 }
10b7602f
NS
2289 /* Move on. */
2290 arc = arc->succ_next;
2291 continue;
27283c73 2292 }
f55ade6e 2293
10b7602f
NS
2294 /* Add new block to chain. */
2295 dst->u.cycle.arc = arc;
2296 head = dst;
2297 goto next_vertex;
27283c73 2298 }
10b7602f
NS
2299 /* We could not add another vertex to the path. Remove
2300 the last vertex from the list. */
2301 arc = head->u.cycle.arc;
2302 if (arc)
27283c73 2303 {
71c0e7fc 2304 /* It was not the first vertex. Move onto next arc. */
10b7602f
NS
2305 head->u.cycle.arc = NULL;
2306 head = arc->src;
2307 arc = arc->succ_next;
2308 goto current_vertex;
27283c73 2309 }
10b7602f
NS
2310 /* Mark this block as unusable. */
2311 block->u.cycle.ident = ~0U;
27283c73 2312 }
10b7602f 2313
27283c73
NS
2314 line->count = count;
2315 }
f55ade6e 2316
4977bab6 2317 if (line->exists)
8b219a76 2318 {
4977bab6
ZW
2319 src->coverage.lines++;
2320 if (line->count)
2321 src->coverage.lines_executed++;
8b219a76 2322 }
8b219a76
NS
2323 }
2324}
86144b75 2325
61ada8ae 2326/* Output information about ARC number IX. Returns nonzero if
27283c73
NS
2327 anything is output. */
2328
2329static int
f55ade6e 2330output_branch_count (FILE *gcov_file, int ix, const arc_t *arc)
27283c73 2331{
27283c73
NS
2332 if (arc->is_call_non_return)
2333 {
2334 if (arc->src->count)
2335 {
2336 fnotice (gcov_file, "call %2d returned %s\n", ix,
2337 format_gcov (arc->src->count - arc->count,
2338 arc->src->count, -flag_counts));
2339 }
2340 else
2341 fnotice (gcov_file, "call %2d never executed\n", ix);
2342 }
2343 else if (!arc->is_unconditional)
2344 {
2345 if (arc->src->count)
2346 fnotice (gcov_file, "branch %2d taken %s%s\n", ix,
2347 format_gcov (arc->count, arc->src->count, -flag_counts),
8919c0d9
NS
2348 arc->fall_through ? " (fallthrough)"
2349 : arc->is_throw ? " (throw)" : "");
27283c73
NS
2350 else
2351 fnotice (gcov_file, "branch %2d never executed\n", ix);
2352 }
10b7602f 2353 else if (flag_unconditional && !arc->dst->is_call_return)
27283c73
NS
2354 {
2355 if (arc->src->count)
2356 fnotice (gcov_file, "unconditional %2d taken %s\n", ix,
2357 format_gcov (arc->count, arc->src->count, -flag_counts));
2358 else
2359 fnotice (gcov_file, "unconditional %2d never executed\n", ix);
2360 }
2361 else
2362 return 0;
2363 return 1;
f55ade6e 2364
27283c73
NS
2365}
2366
8f961b22
NS
2367static const char *
2368read_line (FILE *file)
2369{
2370 static char *string;
2371 static size_t string_len;
2372 size_t pos = 0;
2373 char *ptr;
2374
2375 if (!string_len)
2376 {
2377 string_len = 200;
2378 string = XNEWVEC (char, string_len);
2379 }
2380
2381 while ((ptr = fgets (string + pos, string_len - pos, file)))
2382 {
2383 size_t len = strlen (string + pos);
2384
2385 if (string[pos + len - 1] == '\n')
2386 {
2387 string[pos + len - 1] = 0;
2388 return string;
2389 }
2390 pos += len;
92b05e72
JJ
2391 string = XRESIZEVEC (char, string, string_len * 2);
2392 string_len *= 2;
8f961b22
NS
2393 }
2394
2395 return pos ? string : NULL;
2396}
2397
8b219a76
NS
2398/* Read in the source file one line at a time, and output that line to
2399 the gcov file preceded by its execution count and other
2400 information. */
86144b75 2401
8b219a76 2402static void
f55ade6e 2403output_lines (FILE *gcov_file, const source_t *src)
8b219a76
NS
2404{
2405 FILE *source_file;
f55ade6e 2406 unsigned line_num; /* current line number. */
4977bab6 2407 const line_t *line; /* current line info ptr. */
8f961b22 2408 const char *retval = ""; /* status of source file reading. */
f5d39c3d 2409 function_t *fn = NULL;
4977bab6 2410
1bec9caa 2411 fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->coverage.name);
1a9075e2
TG
2412 if (!multiple_files)
2413 {
2414 fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
2415 fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0,
2416 no_data_file ? "-" : da_file_name);
5366b186 2417 fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_runs);
1a9075e2 2418 }
27283c73 2419 fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
f55ade6e 2420
4977bab6 2421 source_file = fopen (src->name, "r");
8b219a76
NS
2422 if (!source_file)
2423 {
1bec9caa 2424 fnotice (stderr, "Cannot open source file %s\n", src->name);
8b219a76
NS
2425 retval = NULL;
2426 }
1a9075e2
TG
2427 else if (src->file_time == 0)
2428 fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0);
8b219a76 2429
f5d39c3d
NS
2430 if (flag_branches)
2431 fn = src->functions;
2432
4977bab6
ZW
2433 for (line_num = 1, line = &src->lines[line_num];
2434 line_num < src->num_lines; line_num++, line++)
8b219a76 2435 {
27283c73
NS
2436 for (; fn && fn->line == line_num; fn = fn->line_next)
2437 {
9696c529
SB
2438 arc_t *arc = fn->blocks[EXIT_BLOCK].pred;
2439 gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
2440 gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
b8698a0f 2441
27283c73
NS
2442 for (; arc; arc = arc->pred_next)
2443 if (arc->fake)
2444 return_count -= arc->count;
b8698a0f 2445
fc8a650e
SS
2446 fprintf (gcov_file, "function %s", flag_demangled_names ?
2447 fn->demangled_name : fn->name);
27283c73 2448 fprintf (gcov_file, " called %s",
9696c529 2449 format_gcov (called_count, 0, -1));
27283c73 2450 fprintf (gcov_file, " returned %s",
9696c529 2451 format_gcov (return_count, called_count, 0));
27283c73
NS
2452 fprintf (gcov_file, " blocks executed %s",
2453 format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
2454 fprintf (gcov_file, "\n");
2455 }
f55ade6e 2456
8f961b22
NS
2457 if (retval)
2458 retval = read_line (source_file);
2459
8b219a76 2460 /* For lines which don't exist in the .bb file, print '-' before
f55ade6e 2461 the source line. For lines which exist but were never
8f961b22
NS
2462 executed, print '#####' or '=====' before the source line.
2463 Otherwise, print the execution count before the source line.
2464 There are 16 spaces of indentation added before the source
2465 line so that tabs won't be messed up. */
2466 fprintf (gcov_file, "%9s:%5u:%s\n",
8919c0d9
NS
2467 !line->exists ? "-" : line->count
2468 ? format_gcov (line->count, 0, -1)
8f961b22
NS
2469 : line->unexceptional ? "#####" : "=====", line_num,
2470 retval ? retval : "/*EOF*/");
27283c73
NS
2471
2472 if (flag_all_blocks)
8b219a76 2473 {
27283c73 2474 block_t *block;
10b7602f 2475 arc_t *arc;
27283c73 2476 int ix, jx;
f55ade6e 2477
27283c73
NS
2478 for (ix = jx = 0, block = line->u.blocks; block;
2479 block = block->chain)
37b8715b 2480 {
10b7602f 2481 if (!block->is_call_return)
27283c73 2482 fprintf (gcov_file, "%9s:%5u-block %2d\n",
8919c0d9
NS
2483 !line->exists ? "-" : block->count
2484 ? format_gcov (block->count, 0, -1)
2485 : block->exceptional ? "%%%%%" : "$$$$$",
10b7602f 2486 line_num, ix++);
27283c73
NS
2487 if (flag_branches)
2488 for (arc = block->succ; arc; arc = arc->succ_next)
2489 jx += output_branch_count (gcov_file, jx, arc);
86144b75 2490 }
8b219a76 2491 }
27283c73
NS
2492 else if (flag_branches)
2493 {
2494 int ix;
2495 arc_t *arc;
f55ade6e 2496
27283c73
NS
2497 for (ix = 0, arc = line->u.branches; arc; arc = arc->line_next)
2498 ix += output_branch_count (gcov_file, ix, arc);
2499 }
8b219a76 2500 }
f55ade6e 2501
8b219a76
NS
2502 /* Handle all remaining source lines. There may be lines after the
2503 last line of code. */
2504 if (retval)
2505 {
8f961b22
NS
2506 for (; (retval = read_line (source_file)); line_num++)
2507 fprintf (gcov_file, "%9s:%5u:%s\n", "-", line_num, retval);
8b219a76 2508 }
f55ade6e 2509
8b219a76
NS
2510 if (source_file)
2511 fclose (source_file);
2512}