OSDN Git Service

* gcc.c-torture/compile/20021120-1.c: New test.
[pf3gnuchains/gcc-fork.git] / gcc / gcov.c
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2    source file.
3    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
4    1999, 2000, 2001, 2002 Free Software Foundation, Inc.
5    Contributed by James E. Wilson of Cygnus Support.
6    Mangled by Bob Manson of Cygnus Support.
7
8 Gcov is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 Gcov is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Gcov; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* ??? The code in final.c that produces the struct bb assumes that there is
24    no padding between the fields.  This is not necessary true.  The current
25    code can only be trusted if longs and pointers are the same size.  */
26
27 /* ??? No need to print an execution count on every line, could just print
28    it on the first line of each block, and only print it on a subsequent
29    line in the same block if the count changes.  */
30
31 /* ??? Print a list of the ten blocks with the highest execution counts,
32    and list the line numbers corresponding to those blocks.  Also, perhaps
33    list the line numbers with the highest execution counts, only printing
34    the first if there are several which are all listed in the same block.  */
35
36 /* ??? Should have an option to print the number of basic blocks, and the
37    percent of them that are covered.  */
38
39 /* ??? Does not correctly handle the case where two .bb files refer to the
40    same included source file.  For example, if one has a short file containing
41    only inline functions, which is then included in two other files, then
42    there will be two .bb files which refer to the include file, but there
43    is no way to get the total execution counts for the included file, can
44    only get execution counts for one or the other of the including files.  */
45
46 #include "config.h"
47 #include "system.h"
48 #include "intl.h"
49 #include "version.h"
50 #undef abort
51
52 #include <getopt.h>
53
54 typedef HOST_WIDEST_INT gcov_type;
55 #include "gcov-io.h"
56
57 /* The .bb file format consists of several lists of 4-byte integers
58    which are the line numbers of each basic block in the file.  Each
59    list is terminated by a zero.  These lists correspond to the basic
60    blocks in the reconstructed program flow graph.
61
62    A line number of -1 indicates that a source file name (padded to a
63    long boundary) follows.  The padded file name is followed by
64    another -1 to make it easy to scan past file names.  A -2 indicates
65    that a function name (padded to a long boundary) follows; the name
66    is followed by another -2 to make it easy to scan past the function
67    name.
68
69    The .bbg file contains enough info to enable gcov to reconstruct the
70    program flow graph.  The first word is the number of basic blocks,
71    the second word is the number of arcs, followed by the list of arcs
72    (source bb, dest bb pairs), then a -1, then the number of instrumented
73    arcs followed by the instrumented arcs, followed by another -1.  This
74    is repeated for each function.
75
76    The .da file contains the execution count for each instrumented branch.
77
78    The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
79    and the .da files are created when an executable compiled with
80    -fprofile-arcs is run.  */
81
82 /* The functions in this file for creating and solution program flow graphs
83    are very similar to functions in the gcc source file profile.c.  */
84
85 /* This is the size of the buffer used to read in source file lines.  */
86
87 #define STRING_SIZE 200
88
89 /* One copy of this structure is created for each source file mentioned in the
90    .bb file.  */
91
92 struct sourcefile
93 {
94   char *name;
95   int maxlineno;
96   struct sourcefile *next;
97 };
98
99 /* This points to the head of the sourcefile structure list.  */
100
101 struct sourcefile *sources;
102
103 /* One of these is dynamically created whenever we identify an arc in the
104    function.  */
105
106 struct adj_list
107 {
108   int source;
109   int target;
110   gcov_type arc_count;
111   unsigned int count_valid : 1;
112   unsigned int on_tree : 1;
113   unsigned int fake : 1;
114   unsigned int fall_through : 1;
115 #if 0
116   /* Not needed for gcov, but defined in profile.c.  */
117   rtx branch_insn;
118 #endif
119   struct adj_list *pred_next;
120   struct adj_list *succ_next;
121 };
122
123 /* Count the number of basic blocks, and create an array of these structures,
124    one for each bb in the function.  */
125
126 struct bb_info
127 {
128   struct adj_list *succ;
129   struct adj_list *pred;
130   gcov_type succ_count;
131   gcov_type pred_count;
132   gcov_type exec_count;
133   unsigned int count_valid : 1;
134   unsigned int on_tree : 1;
135 #if 0
136   /* Not needed for gcov, but defined in profile.c.  */
137   rtx first_insn;
138 #endif
139 };
140
141 /* When outputting branch probabilities, one of these structures is created
142    for each branch/call.  */
143
144 struct arcdata
145 {
146   gcov_type hits;
147   gcov_type total;
148   int call_insn;
149   struct arcdata *next;
150 };
151
152 /* Used to save the list of bb_graphs, one per function.  */
153
154 struct bb_info_list
155 {
156   /* Indexed by block number, holds the basic block graph for one function.  */
157   struct bb_info *bb_graph;
158   int num_blocks;
159   struct bb_info_list *next;
160 };
161
162 /* Used to hold information about each line.  */
163 struct line_info
164 {
165   gcov_type count;            /* execution count */
166   struct arcdata *branches;   /* list of branch probabilities for line.  */
167   unsigned exists : 1;        /* has code associated with it.  */
168 };
169   
170 struct coverage
171 {
172   int lines;
173   int lines_executed;
174   
175   int branches;
176   int branches_executed;
177   int branches_taken;
178   
179   int calls;
180   int calls_executed;
181   
182   char *name;
183 };
184
185 /* Holds a list of function basic block graphs.  */
186
187 static struct bb_info_list *bb_graph_list = 0;
188
189 /* Modification time of data files.  */
190
191 static time_t bb_file_time;
192
193 /* Name and file pointer of the input file for the basic block graph.  */
194
195 static char *bbg_file_name;
196 static FILE *bbg_file;
197
198 /* Name and file pointer of the input file for the arc count data.  */
199
200 static char *da_file_name;
201 static FILE *da_file;
202
203 /* Name and file pointer of the input file for the basic block line counts.  */
204
205 static char *bb_file_name;
206 static FILE *bb_file;
207
208 /* Holds the entire contents of the bb_file read into memory.  */
209
210 static char *bb_data;
211
212 /* Size of bb_data array in longs.  */
213
214 static long bb_data_size;
215
216 /* Name of the file mentioned on the command line.  */
217
218 static char *input_file_name = 0;
219
220 /* Output branch probabilities if true.  */
221
222 static int output_branch_probs = 0;
223
224 /* Output a gcov file if this is true.  This is on by default, and can
225    be turned off by the -n option.  */
226
227 static int output_gcov_file = 1;
228
229 /* For included files, make the gcov output file name include the name of
230    the input source file.  For example, if x.h is included in a.c, then the
231    output file name is a.c.x.h.gcov instead of x.h.gcov.  This works only
232    when a single source file is specified.  */
233
234 static int output_long_names = 0;
235
236 /* Output summary info for each function.  */
237
238 static int output_function_summary = 0;
239
240 /* Object directory file prefix.  This is the directory/file
241    where .bb and .bbg files are looked for, if nonzero.  */
242
243 static char *object_directory = 0;
244
245 /* Preserve all pathname components. Needed when object files and
246    source files are in subdirectories.  */
247 static int preserve_paths = 0;
248
249 /* Output the number of times a branch was taken as opposed to the percentage
250    of times it was taken.  Turned on by the -c option */
251
252 static int output_branch_counts = 0;
253
254 /* Forward declarations.  */
255 static void process_args PARAMS ((int, char **));
256 static void open_files PARAMS ((void));
257 static void read_files PARAMS ((void));
258 static void scan_for_source_files PARAMS ((void));
259 static void output_data PARAMS ((struct sourcefile *));
260 static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
261 static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
262 static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
263 static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
264 static gcov_type *read_profile PARAMS ((char *, long, int));
265 static void create_program_flow_graph PARAMS ((struct bb_info_list *));
266 static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
267 static void accumulate_branch_counts PARAMS ((struct coverage *,
268                                               struct arcdata *));
269 static void calculate_branch_probs PARAMS ((struct bb_info *,
270                                             struct line_info *,
271                                             struct coverage *));
272 static void function_summary PARAMS ((struct coverage *, const char *));
273 static void init_line_info PARAMS ((struct line_info *,
274                                     struct coverage *, long));
275 static void output_line_info PARAMS ((FILE *, const struct line_info *,
276                                       const struct coverage *, long));
277 static char *make_gcov_file_name PARAMS ((char *));
278 static const char *format_hwint PARAMS ((HOST_WIDEST_INT, HOST_WIDEST_INT,
279                                          int));
280
281 extern int main PARAMS ((int, char **));
282
283 int
284 main (argc, argv)
285      int argc;
286      char **argv;
287 {
288   struct sourcefile *s_ptr;
289   
290   gcc_init_libintl ();
291
292   process_args (argc, argv);
293
294   open_files ();
295
296   read_files ();
297
298   scan_for_source_files ();
299
300   for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
301     output_data (s_ptr);
302
303   return 0;
304 }
305
306 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
307 static void
308 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
309 {
310   VA_OPEN (ap, msgid);
311   VA_FIXEDARG (ap, FILE *, file);
312   VA_FIXEDARG (ap, const char *, msgid);
313
314   vfprintf (file, _(msgid), ap);
315   VA_CLOSE (ap);
316 }
317
318 /* More 'friendly' abort that prints the line and file.
319    config.h can #define abort fancy_abort if you like that sort of thing.  */
320 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
321
322 void
323 fancy_abort ()
324 {
325   fnotice (stderr, "Internal gcov abort.\n");
326   exit (FATAL_EXIT_CODE);
327 }
328 \f
329 /* Print a usage message and exit.  If ERROR_P is nonzero, this is an error,
330    otherwise the output of --help.  */
331
332 static void
333 print_usage (error_p)
334      int error_p;
335 {
336   FILE *file = error_p ? stderr : stdout;
337   int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
338   fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
339   fnotice (file, "Print code coverage information.\n\n");
340   fnotice (file, "  -h, --help                      Print this help, then exit\n");
341   fnotice (file, "  -v, --version                   Print version number, then exit\n");
342   fnotice (file, "  -b, --branch-probabilities      Include branch probabilities in output\n");
343   fnotice (file, "  -c, --branch-counts             Given counts of branches taken\n\
344                                     rather than percentages\n");
345   fnotice (file, "  -n, --no-output                 Do not create an output file\n");
346   fnotice (file, "  -l, --long-file-names           Use long output file names for included\n\
347                                     source files\n");
348   fnotice (file, "  -f, --function-summaries        Output summaries for each function\n");
349   fnotice (file, "  -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
350   fnotice (file, "  -p, --preserve-paths            Preserve all pathname components\n");
351   fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
352            bug_report_url);
353   exit (status);
354 }
355
356 /* Print version information and exit.  */
357
358 static void
359 print_version ()
360 {
361   fnotice (stdout, "gcov (GCC) %s\n", version_string);
362   fnotice (stdout, "Copyright (C) 2001 Free Software Foundation, Inc.\n");
363   fnotice (stdout,
364            "This is free software; see the source for copying conditions.  There is NO\n\
365 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
366   exit (SUCCESS_EXIT_CODE);
367 }
368
369 static const struct option options[] =
370 {
371   { "help",                 no_argument,       NULL, 'h' },
372   { "version",              no_argument,       NULL, 'v' },
373   { "branch-probabilities", no_argument,       NULL, 'b' },
374   { "branch-counts",        no_argument,       NULL, 'c' },
375   { "no-output",            no_argument,       NULL, 'n' },
376   { "long-file-names",      no_argument,       NULL, 'l' },
377   { "function-summaries",   no_argument,       NULL, 'f' },
378   { "preserve-paths",       no_argument,       NULL, 'p' },
379   { "object-directory",     required_argument, NULL, 'o' },
380   { "object-file",          required_argument, NULL, 'o' },
381 };
382
383 /* Parse the command line.  */
384
385 static void
386 process_args (argc, argv)
387      int argc;
388      char **argv;
389 {
390   int opt;
391
392   while ((opt = getopt_long (argc, argv, "hvbclnfo:p", options, NULL)) != -1)
393     {
394       switch (opt)
395         {
396         case 'h':
397           print_usage (false);
398           /* print_usage will exit.  */
399         case 'v':
400           print_version ();
401           /* print_version will exit.  */
402         case 'b':
403           output_branch_probs = 1;
404           break;
405         case 'c':
406           output_branch_counts = 1;
407           break;
408         case 'n':
409           output_gcov_file = 0;
410           break;
411         case 'l':
412           output_long_names = 1;
413           break;
414         case 'f':
415           output_function_summary = 1;
416           break;
417         case 'o':
418           object_directory = optarg;
419           break;
420         case 'p':
421           preserve_paths = 1;
422           break;
423         default:
424           print_usage (true);
425           /* print_usage will exit.  */
426         }
427     }
428
429   if (optind != argc - 1)
430     print_usage (true);
431
432   input_file_name = argv[optind];
433 }
434
435
436 /* Find and open the .bb, .da, and .bbg files. If OBJECT_DIRECTORY is
437    not specified, these are looked for in the current directory, and
438    named from the basename of the input_file_name sans extension. If
439    OBJECT_DIRECTORY is specified and is a directory, the files are in
440    that directory, but named from the basename of the input_file_name,
441    sans extension. Otherwise OBJECT_DIRECTORY is taken to be the name
442    of the object *file*, and the data files are named from that.  */
443
444 static void
445 open_files ()
446 {
447   char *cptr;
448   char *name;
449   int length = strlen (input_file_name);
450   int base;
451   
452   if (object_directory && object_directory[0])
453     {
454       struct stat status;
455
456       length += strlen (object_directory) + 2;
457       name = xmalloc (length);
458       name[0] = 0;
459       
460       base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
461       strcat (name, object_directory);
462       if (base && name[strlen (name) - 1] != '/')
463         strcat (name, "/");
464     }
465   else
466     {
467       name = xmalloc (length + 1);
468       name[0] = 0;
469       base = 1;
470     }
471   
472   if (base)
473     {
474       /* Append source file name */
475       cptr = strrchr (input_file_name, '/');
476       cptr = cptr ? cptr + 1 : input_file_name;
477
478       strcat (name, cptr);
479     }
480   /* Remove the extension.  */
481   cptr = strrchr (name, '.');
482   if (cptr)
483     *cptr = 0;
484   
485   length = strlen (name);
486   da_file_name = xmalloc (length + 4);
487   bb_file_name = xmalloc (length + 4);
488   bbg_file_name = xmalloc (length + 5);
489
490   strcpy (da_file_name, name);
491   strcpy (bb_file_name, name);
492   strcpy (bbg_file_name, name);
493   strcpy (da_file_name + length, ".da");
494   strcpy (bb_file_name + length, ".bb");
495   strcpy (bbg_file_name + length, ".bbg");
496
497   bb_file = fopen (bb_file_name, "rb");
498   if (bb_file == NULL)
499     {
500       fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
501       exit (FATAL_EXIT_CODE);
502     }
503
504   bbg_file = fopen (bbg_file_name, "rb");
505   if (bbg_file == NULL)
506     {
507       fnotice (stderr, "Could not open program flow graph file %s.\n",
508                bbg_file_name);
509       exit (FATAL_EXIT_CODE);
510     }
511   
512   {
513     struct stat status;
514
515     if (!fstat (fileno (bb_file), &status))
516       bb_file_time = status.st_mtime;
517   }
518   
519   /* If none of the functions in the file were executed, then there won't
520      be a .da file.  Just assume that all counts are zero in this case.  */
521   da_file = fopen (da_file_name, "rb");
522   if (da_file == NULL)
523     {
524       fnotice (stderr, "Could not open data file %s.\n", da_file_name);
525       fnotice (stderr, "Assuming that all execution counts are zero.\n");
526     }
527
528   /* Check for empty .bbg file.  This indicates that there is no executable
529      code in this source file.  */
530   /* Set the EOF condition if at the end of file.  */
531   ungetc (getc (bbg_file), bbg_file);
532   if (feof (bbg_file))
533     {
534       fnotice (stderr, "No executable code associated with file %s.\n",
535                input_file_name);
536       exit (FATAL_EXIT_CODE);
537     }
538 }
539 \f
540 /* Initialize a new arc.  */
541
542 static void
543 init_arc (arcptr, source, target, bb_graph)
544      struct adj_list *arcptr;
545      int source, target;
546      struct bb_info *bb_graph;
547 {
548   arcptr->target = target;
549   arcptr->source = source;
550
551   arcptr->arc_count = 0;
552   arcptr->count_valid = 0;
553   arcptr->on_tree = 0;
554   arcptr->fake = 0;
555   arcptr->fall_through = 0;
556
557   arcptr->succ_next = bb_graph[source].succ;
558   bb_graph[source].succ = arcptr;
559   bb_graph[source].succ_count++;
560
561   arcptr->pred_next = bb_graph[target].pred;
562   bb_graph[target].pred = arcptr;
563   bb_graph[target].pred_count++;
564 }
565
566 /* Reverse the arcs on an arc list.  */
567
568 static struct adj_list *
569 reverse_arcs (arcptr)
570      struct adj_list *arcptr;
571 {
572   struct adj_list *prev = 0;
573   struct adj_list *next;
574
575   for ( ; arcptr; arcptr = next)
576     {
577       next = arcptr->succ_next;
578       arcptr->succ_next = prev;
579       prev = arcptr;
580     }
581
582   return prev;
583 }
584
585 /* Reads profiles from the .da file and compute a hybrid profile.  */
586
587 static gcov_type *
588 read_profile (function_name, cfg_checksum, instr_arcs)
589      char *function_name;
590      long cfg_checksum;
591      int instr_arcs;
592 {
593   int i;
594   int okay = 1;
595   gcov_type *profile;
596   char *function_name_buffer;
597   int function_name_buffer_len;
598
599   profile = xmalloc (sizeof (gcov_type) * instr_arcs);
600   function_name_buffer_len = strlen (function_name) + 1;
601   function_name_buffer = xmalloc (function_name_buffer_len + 1);
602
603   for (i = 0; i < instr_arcs; i++)
604     profile[i] = 0;
605
606   if (!da_file)
607     return profile;
608
609   rewind (da_file);
610   while (1)
611     {
612       long magic, extra_bytes;
613       long func_count;
614       int i;
615
616       if (__read_long (&magic, da_file, 4) != 0)
617         break;
618
619       if (magic != -123)
620         {
621           okay = 0;
622           break;
623         }
624
625       if (__read_long (&func_count, da_file, 4) != 0)
626         {
627           okay = 0;
628           break;
629         }
630
631       if (__read_long (&extra_bytes, da_file, 4) != 0)
632         {
633           okay = 0;
634           break;
635         }
636
637       /* skip extra data emited by __bb_exit_func.  */
638       fseek (da_file, extra_bytes, SEEK_CUR);
639
640       for (i = 0; i < func_count; i++)
641         {
642           long arc_count;
643           long chksum;
644           int j;
645
646           if (__read_gcov_string
647               (function_name_buffer, function_name_buffer_len, da_file,
648                -1) != 0)
649             {
650               okay = 0;
651               break;
652             }
653
654           if (__read_long (&chksum, da_file, 4) != 0)
655             {
656               okay = 0;
657               break;
658             }
659
660           if (__read_long (&arc_count, da_file, 4) != 0)
661             {
662               okay = 0;
663               break;
664             }
665
666           if (strcmp (function_name_buffer, function_name) != 0
667               || arc_count != instr_arcs || chksum != cfg_checksum)
668             {
669               /* skip */
670               if (fseek (da_file, arc_count * 8, SEEK_CUR) < 0)
671                 {
672                   okay = 0;
673                   break;
674                 }
675             }
676           else
677             {
678               gcov_type tmp;
679
680               for (j = 0; j < arc_count; j++)
681                 if (__read_gcov_type (&tmp, da_file, 8) != 0)
682                   {
683                     okay = 0;
684                     break;
685                   }
686                 else
687                   {
688                     profile[j] += tmp;
689                   }
690             }
691         }
692
693       if (!okay)
694         break;
695
696     }
697
698   free (function_name_buffer);
699
700   if (!okay)
701     {
702       fprintf (stderr, ".da file corrupted!\n");
703       free (profile);
704       abort ();
705     }
706
707   return profile;
708 }
709
710 /* Construct the program flow graph from the .bbg file, and read in the data
711    in the .da file.  */
712
713 static void
714 create_program_flow_graph (bptr)
715      struct bb_info_list *bptr;
716 {
717   long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
718   int i;
719   struct adj_list *arcptr;
720   struct bb_info *bb_graph;
721   long cfg_checksum;
722   long instr_arcs = 0;
723   gcov_type *profile;
724   int profile_pos = 0;
725   char *function_name;
726   long function_name_len, tmp;
727
728   /* Read function name.  */
729   __read_long (&tmp, bbg_file, 4);   /* ignore -1.  */
730   __read_long (&function_name_len, bbg_file, 4);
731   function_name = xmalloc (function_name_len + 1);
732   fread (function_name, 1, function_name_len + 1, bbg_file);
733
734   /* Skip padding.  */
735   tmp = (function_name_len + 1) % 4;
736
737   if (tmp)
738     fseek (bbg_file, 4 - tmp, SEEK_CUR);
739
740   __read_long (&tmp, bbg_file, 4);   /* ignore -1.  */
741
742   /* Read the cfg checksum.  */
743   __read_long (&cfg_checksum, bbg_file, 4);
744
745   /* Read the number of blocks.  */
746   __read_long (&num_blocks, bbg_file, 4);
747
748   /* Create an array of size bb number of bb_info structs.  */
749   bb_graph = (struct bb_info *) xcalloc (num_blocks, sizeof (struct bb_info));
750
751   bptr->bb_graph = bb_graph;
752   bptr->num_blocks = num_blocks;
753
754   /* Read and create each arc from the .bbg file.  */
755   __read_long (&number_arcs, bbg_file, 4);
756   for (i = 0; i < num_blocks; i++)
757     {
758       int j;
759
760       __read_long (&num_arcs_per_block, bbg_file, 4);
761       for (j = 0; j < num_arcs_per_block; j++)
762         {
763           if (number_arcs-- < 0)
764             abort ();
765
766           src = i;
767           __read_long (&dest, bbg_file, 4);
768
769           arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
770           init_arc (arcptr, src, dest, bb_graph);
771
772           __read_long (&flag_bits, bbg_file, 4);
773           if (flag_bits & 0x1)
774             arcptr->on_tree++;
775           else
776             instr_arcs++;
777           arcptr->fake = !! (flag_bits & 0x2);
778           arcptr->fall_through = !! (flag_bits & 0x4);
779         }
780     }
781
782   if (number_arcs)
783     abort ();
784
785   /* Read and ignore the -1 separating the arc list from the arc list of the
786      next function.  */
787   __read_long (&src, bbg_file, 4);
788   if (src != -1)
789     abort ();
790
791   /* Must reverse the order of all succ arcs, to ensure that they match
792      the order of the data in the .da file.  */
793
794   for (i = 0; i < num_blocks; i++)
795     if (bb_graph[i].succ)
796       bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
797
798   /* Read profile from the .da file.  */
799
800   profile = read_profile (function_name, cfg_checksum, instr_arcs);
801
802   /* For each arc not on the spanning tree, set its execution count from
803      the .da file.  */
804
805   /* The first count in the .da file is the number of times that the function
806      was entered.  This is the exec_count for block zero.  */
807
808   /* This duplicates code in branch_prob in profile.c.  */
809
810   for (i = 0; i < num_blocks; i++)
811     for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
812       if (! arcptr->on_tree)
813         {
814           arcptr->arc_count = profile[profile_pos++];
815           arcptr->count_valid = 1;
816           bb_graph[i].succ_count--;
817           bb_graph[arcptr->target].pred_count--;
818         }
819   free (profile);
820   free (function_name);
821 }
822
823 static void
824 solve_program_flow_graph (bptr)
825      struct bb_info_list *bptr;
826 {
827   int passes, changes;
828   gcov_type total;
829   int i;
830   struct adj_list *arcptr;
831   struct bb_info *bb_graph;
832   int num_blocks;
833
834   num_blocks = bptr->num_blocks;
835   bb_graph = bptr->bb_graph;
836
837   /* For every block in the file,
838      - if every exit/entrance arc has a known count, then set the block count
839      - if the block count is known, and every exit/entrance arc but one has
840        a known execution count, then set the count of the remaining arc
841
842      As arc counts are set, decrement the succ/pred count, but don't delete
843      the arc, that way we can easily tell when all arcs are known, or only
844      one arc is unknown.  */
845
846   /* The order that the basic blocks are iterated through is important.
847      Since the code that finds spanning trees starts with block 0, low numbered
848      arcs are put on the spanning tree in preference to high numbered arcs.
849      Hence, most instrumented arcs are at the end.  Graph solving works much
850      faster if we propagate numbers from the end to the start.
851
852      This takes an average of slightly more than 3 passes.  */
853
854   changes = 1;
855   passes = 0;
856   while (changes)
857     {
858       passes++;
859       changes = 0;
860
861       for (i = num_blocks - 1; i >= 0; i--)
862         {
863           if (! bb_graph[i].count_valid)
864             {
865               if (bb_graph[i].succ_count == 0)
866                 {
867                   total = 0;
868                   for (arcptr = bb_graph[i].succ; arcptr;
869                        arcptr = arcptr->succ_next)
870                     total += arcptr->arc_count;
871                   bb_graph[i].exec_count = total;
872                   bb_graph[i].count_valid = 1;
873                   changes = 1;
874                 }
875               else if (bb_graph[i].pred_count == 0)
876                 {
877                   total = 0;
878                   for (arcptr = bb_graph[i].pred; arcptr;
879                        arcptr = arcptr->pred_next)
880                     total += arcptr->arc_count;
881                   bb_graph[i].exec_count = total;
882                   bb_graph[i].count_valid = 1;
883                   changes = 1;
884                 }
885             }
886           if (bb_graph[i].count_valid)
887             {
888               if (bb_graph[i].succ_count == 1)
889                 {
890                   total = 0;
891                   /* One of the counts will be invalid, but it is zero,
892                      so adding it in also doesn't hurt.  */
893                   for (arcptr = bb_graph[i].succ; arcptr;
894                        arcptr = arcptr->succ_next)
895                     total += arcptr->arc_count;
896                   /* Calculate count for remaining arc by conservation.  */
897                   total = bb_graph[i].exec_count - total;
898                   /* Search for the invalid arc, and set its count.  */
899                   for (arcptr = bb_graph[i].succ; arcptr;
900                        arcptr = arcptr->succ_next)
901                     if (! arcptr->count_valid)
902                       break;
903                   if (! arcptr)
904                     abort ();
905                   arcptr->count_valid = 1;
906                   arcptr->arc_count = total;
907                   bb_graph[i].succ_count--;
908
909                   bb_graph[arcptr->target].pred_count--;
910                   changes = 1;
911                 }
912               if (bb_graph[i].pred_count == 1)
913                 {
914                   total = 0;
915                   /* One of the counts will be invalid, but it is zero,
916                      so adding it in also doesn't hurt.  */
917                   for (arcptr = bb_graph[i].pred; arcptr;
918                        arcptr = arcptr->pred_next)
919                     total += arcptr->arc_count;
920                   /* Calculate count for remaining arc by conservation.  */
921                   total = bb_graph[i].exec_count - total;
922                   /* Search for the invalid arc, and set its count.  */
923                   for (arcptr = bb_graph[i].pred; arcptr;
924                        arcptr = arcptr->pred_next)
925                     if (! arcptr->count_valid)
926                       break;
927                   if (! arcptr)
928                     abort ();
929                   arcptr->count_valid = 1;
930                   arcptr->arc_count = total;
931                   bb_graph[i].pred_count--;
932
933                   bb_graph[arcptr->source].succ_count--;
934                   changes = 1;
935                 }
936             }
937         }
938     }
939
940   /* If the graph has been correctly solved, every block will have a
941      succ and pred count of zero.  */
942   for (i = 0; i < num_blocks; i++)
943     if (bb_graph[i].succ_count || bb_graph[i].pred_count)
944       abort ();
945 }
946
947
948 static void
949 read_files ()
950 {
951   struct stat buf;
952   struct bb_info_list *list_end = 0;
953   struct bb_info_list *b_ptr;
954
955   while (! feof (bbg_file))
956     {
957       b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
958
959       b_ptr->next = 0;
960       if (list_end)
961         list_end->next = b_ptr;
962       else
963         bb_graph_list = b_ptr;
964       list_end = b_ptr;
965
966       /* Read in the data in the .bbg file and reconstruct the program flow
967          graph for one function.  */
968       create_program_flow_graph (b_ptr);
969
970       /* Set the EOF condition if at the end of file.  */
971       ungetc (getc (bbg_file), bbg_file);
972     }
973
974   /* Calculate all of the basic block execution counts and branch
975      taken probabilities.  */
976
977   for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
978     solve_program_flow_graph (b_ptr);
979
980   /* Read in all of the data from the .bb file.   This info will be accessed
981      sequentially twice.  */
982   stat (bb_file_name, &buf);
983   bb_data_size = buf.st_size / 4;
984
985   bb_data = (char *) xmalloc ((unsigned) buf.st_size);
986   fread (bb_data, sizeof (char), buf.st_size, bb_file);
987
988   fclose (bb_file);
989   if (da_file)
990     fclose (da_file);
991   fclose (bbg_file);
992 }
993
994
995 /* Scan the data in the .bb file to find all source files referenced,
996    and the largest line number mentioned in each one.  */
997
998 static void
999 scan_for_source_files ()
1000 {
1001   struct sourcefile *s_ptr = NULL;
1002   char *ptr;
1003   long count;
1004   long line_num;
1005
1006   /* Search the bb_data to find:
1007      1) The number of sources files contained herein, and
1008      2) The largest line number for each source file.  */
1009
1010   ptr = bb_data;
1011   sources = 0;
1012   for (count = 0; count < bb_data_size; count++)
1013     {
1014       __fetch_long (&line_num, ptr, 4);
1015       ptr += 4;
1016       if (line_num == -1)
1017         {
1018           /* A source file name follows.  Check to see if we already have
1019            a sourcefile structure for this file.  */
1020           s_ptr = sources;
1021           while (s_ptr && strcmp (s_ptr->name, ptr))
1022             s_ptr = s_ptr->next;
1023
1024           if (s_ptr == 0)
1025             {
1026               /* No sourcefile structure for this file name exists, create
1027                  a new one, and append it to the front of the sources list.  */
1028               s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
1029               s_ptr->name = xstrdup (ptr);
1030               s_ptr->maxlineno = 0;
1031               s_ptr->next = sources;
1032               sources = s_ptr;
1033             }
1034
1035           /* Scan past the file name.  */
1036           {
1037             long delim;
1038             do {
1039               count++;
1040               __fetch_long (&delim, ptr, 4);
1041               ptr += 4;
1042             } while (delim != line_num);
1043           }
1044         }
1045       else if (line_num == -2)
1046         {
1047           long delim;
1048
1049           /* A function name follows.  Ignore it.  */
1050           do {
1051             count++;
1052             __fetch_long (&delim, ptr, 4);
1053             ptr += 4;
1054           } while (delim != line_num);
1055         }
1056       /* There will be a zero before the first file name, in which case s_ptr
1057          will still be uninitialized.  So, only try to set the maxlineno
1058          field if line_num is nonzero.  */
1059       else if (line_num > 0)
1060         {
1061           if (s_ptr->maxlineno <= line_num)
1062             s_ptr->maxlineno = line_num + 1;
1063         }
1064       else if (line_num < 0)
1065         {
1066           /* Don't know what this is, but it's garbage.  */
1067           abort ();
1068         }
1069     }
1070 }
1071 \f
1072
1073 /* Increment totals in FUNCTION according to arc A_PTR.  */
1074
1075 static void
1076 accumulate_branch_counts (function, a_ptr)
1077      struct coverage *function;
1078      struct arcdata *a_ptr;
1079 {
1080   if (a_ptr->call_insn)
1081     {
1082       function->calls++;
1083       if (a_ptr->total)
1084         function->calls_executed++;
1085     }
1086   else
1087     {
1088       function->branches++;
1089       if (a_ptr->total)
1090         function->branches_executed++;
1091       if (a_ptr->hits)
1092         function->branches_taken++;
1093     }
1094 }
1095
1096 /* Calculate the branch taken probabilities for all arcs branches at the
1097    end of this block.  */
1098
1099 static void
1100 calculate_branch_probs (block_ptr, line_info, function)
1101      struct bb_info *block_ptr;
1102      struct line_info *line_info;
1103      struct coverage *function;
1104 {
1105   gcov_type total;
1106   struct adj_list *arcptr;
1107
1108   total = block_ptr->exec_count;
1109   for (arcptr = block_ptr->succ; arcptr; arcptr = arcptr->succ_next)
1110     {
1111       struct arcdata *a_ptr;
1112       
1113       /* Ignore fall through arcs as they aren't really branches.  */
1114       if (arcptr->fall_through)
1115         continue;
1116
1117       a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
1118       a_ptr->total = total;
1119       a_ptr->hits = total ? arcptr->arc_count : 0;
1120       a_ptr->call_insn = arcptr->fake;
1121
1122       if (function)
1123         accumulate_branch_counts (function, a_ptr);
1124       /* Prepend the new branch to the list.  */
1125       a_ptr->next = line_info->branches;
1126       line_info->branches = a_ptr;
1127     }
1128 }
1129
1130 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1131    count.  If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1132    If DP is zero, no decimal point is printed. Only print 100% when
1133    TOP==BOTTOM and only print 0% when TOP=0.  If dp < 0, then simply
1134    format TOP.  Return pointer to a static string.  */
1135
1136 static char const *
1137 format_hwint (top, bottom, dp)
1138      HOST_WIDEST_INT top, bottom;
1139      int dp;
1140 {
1141   static char buffer[20];
1142   
1143   if (dp >= 0)
1144     {
1145       float ratio = bottom ? (float)top / bottom : 0;
1146       int ix;
1147       unsigned limit = 100;
1148       unsigned percent;
1149   
1150       for (ix = dp; ix--; )
1151         limit *= 10;
1152       
1153       percent = (unsigned) (ratio * limit + (float)0.5);
1154       if (percent <= 0 && top)
1155         percent = 1;
1156       else if (percent >= limit && top != bottom)
1157         percent = limit - 1;
1158       ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1159       if (dp)
1160         {
1161           dp++;
1162           do
1163             {
1164               buffer[ix+1] = buffer[ix];
1165               ix--;
1166             }
1167           while (dp--);
1168           buffer[ix + 1] = '.';
1169         }
1170     }
1171   else
1172     sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, top);
1173   
1174   return buffer;
1175 }
1176
1177
1178 /* Output summary info for a function.  */
1179
1180 static void
1181 function_summary (function, title)
1182      struct coverage *function;
1183      const char *title;
1184 {
1185   if (function->lines)
1186     fnotice (stdout, "%s of %d lines executed in %s %s\n",
1187              format_hwint (function->lines_executed,
1188                            function->lines, 2),
1189              function->lines, title, function->name);
1190   else
1191     fnotice (stdout, "No executable lines in %s %s\n",
1192              title, function->name);
1193
1194   if (output_branch_probs)
1195     {
1196       if (function->branches)
1197         {
1198           fnotice (stdout, "%s of %d branches executed in %s %s\n",
1199                    format_hwint (function->branches_executed,
1200                                  function->branches, 2),
1201                    function->branches, title, function->name);
1202           fnotice (stdout,
1203                 "%s of %d branches taken at least once in %s %s\n",
1204                    format_hwint (function->branches_taken,
1205                                  function->branches, 2),
1206                    function->branches, title, function->name);
1207         }
1208       else
1209         fnotice (stdout, "No branches in %s %s\n", title, function->name);
1210       if (function->calls)
1211         fnotice (stdout, "%s of %d calls executed in %s %s\n",
1212                  format_hwint (function->calls_executed,
1213                                function->calls, 2),
1214                  function->calls, title, function->name);
1215       else
1216         fnotice (stdout, "No calls in %s %s\n", title, function->name);
1217     }
1218 }
1219
1220 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1221    affect name generation. With preserve_paths we create a filename
1222    from all path components of the source file, replacing '/' with
1223    '#', without it we simply take the basename component. With
1224    long_output_names we prepend the processed name of the input file
1225    to each output name (except when the current source file is the
1226    input file, so you don't get a double concatenation). The two
1227    components are separated by '##'. Also '.' filename components are
1228    removed and '..'  components are renamed to '^'.  */
1229
1230 static char *
1231 make_gcov_file_name (src_name)
1232      char *src_name;
1233 {
1234   char *cptr;
1235   char *name = xmalloc (strlen (src_name) + strlen (input_file_name) + 10);
1236   
1237   name[0] = 0;
1238   if (output_long_names && strcmp (src_name, input_file_name))
1239     {
1240       /* Generate the input filename part.  */
1241       cptr = preserve_paths ? NULL : strrchr (input_file_name, '/');
1242       cptr = cptr ? cptr + 1 : input_file_name;
1243       strcat (name, cptr);
1244       strcat (name, "##");
1245     }
1246    
1247   /* Generate the source filename part.  */
1248   cptr = preserve_paths ? NULL : strrchr (src_name, '/');
1249   cptr = cptr ? cptr + 1 : src_name;
1250   strcat (name, cptr);
1251   
1252   if (preserve_paths)
1253     {
1254       /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1255       char *prev;
1256       
1257       for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1258         {
1259           unsigned shift = 0;
1260           
1261           if (prev + 1 == cptr && prev[0] == '.')
1262             {
1263               /* Remove '.' */
1264               shift = 2;
1265             }
1266           else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1267             {
1268               /* Convert '..' */
1269               shift = 1;
1270               prev[1] = '^';
1271             }
1272           else
1273             *cptr++ = '#';
1274           if (shift)
1275             {
1276               cptr = prev;
1277               do
1278                 prev[0] = prev[shift];
1279               while (*prev++);
1280             }
1281         }
1282     }
1283   
1284   /* Don't strip off the ending for compatibility with tcov, since
1285      this results in confusion if there is more than one file with the
1286      same basename, e.g. tmp.c and tmp.h.  */
1287   strcat (name, ".gcov");
1288   return name;
1289 }
1290
1291 /* Scan through the bb_data, and when the file name matches the
1292    source file name, then for each following line number, increment
1293    the line number execution count indicated by the execution count of
1294    the appropriate basic block.  */
1295
1296 static void
1297 init_line_info (line_info, total, maxlineno)
1298      struct line_info *line_info;
1299      struct coverage *total;
1300      long maxlineno;
1301 {
1302   long block_num = 0;           /* current block number */
1303   struct bb_info *block_ptr = NULL;     /* current block ptr */
1304   struct coverage function;
1305   struct coverage *func_ptr = NULL;
1306   struct bb_info_list *current_graph = NULL; /* Graph for current function.  */
1307   int is_this_file = 0; /* We're scanning a block from the desired file.  */
1308   char *ptr = bb_data;
1309   long count;
1310   long line_num;
1311   struct line_info *line_ptr = 0; /* line info ptr.  */
1312    
1313   memset (&function, 0, sizeof (function));
1314   if (output_function_summary)
1315     func_ptr = &function;
1316   
1317   for (count = 0; count < bb_data_size; count++)
1318     {
1319       __fetch_long (&line_num, ptr, 4);
1320       ptr += 4;
1321       if (line_num < 0)
1322         {
1323           long delim;
1324           
1325           if (line_num == -1)
1326             {
1327               /* Marks the beginning of a file name.  Check to see
1328                  whether this is the filename we are currently
1329                  collecting data for.  */
1330               is_this_file = !strcmp (total->name, ptr);
1331             }
1332           else if (line_num == -2)
1333             {
1334               /* Marks the start of a new function.  Advance to the
1335                  next program flow graph.  */
1336               if (!current_graph)
1337                 current_graph = bb_graph_list;
1338               else
1339                 {
1340                   if (block_num == current_graph->num_blocks - 1)
1341                     /* Last block falls through to exit.  */
1342                     ;
1343                   else if (block_num == current_graph->num_blocks - 2)
1344                     {
1345                       if (output_branch_probs && is_this_file)
1346                         calculate_branch_probs (block_ptr, line_ptr, func_ptr);
1347                     }
1348                   else
1349                     {
1350                       fnotice (stderr,
1351                                "didn't use all bb entries of graph, function %s\n",
1352                                function.name);
1353                       fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1354                                block_num, current_graph->num_blocks);
1355                     }
1356                   if (func_ptr && is_this_file)
1357                     function_summary (func_ptr, "function");
1358                   current_graph = current_graph->next;
1359                 }
1360               block_num = 0;
1361               block_ptr = current_graph->bb_graph;
1362               memset (&function, 0, sizeof (function));
1363               function.name = ptr;
1364             }
1365           else
1366             {
1367               fnotice (stderr, "ERROR: unexpected line number %ld\n", line_num);
1368               abort ();
1369             }
1370
1371           /* Scan past the string.  */
1372           for (delim = 0; delim != line_num; count++)
1373             {
1374               __fetch_long (&delim, ptr, 4);
1375               ptr += 4;
1376             }
1377         }
1378       else if (!line_num)
1379         {
1380           /* Marks the end of a block.  */
1381           if (block_num >= current_graph->num_blocks)
1382             {
1383               fnotice (stderr, "ERROR: too many basic blocks in function %s\n",
1384                        function.name);
1385               abort ();
1386             }
1387           
1388           if (output_branch_probs && is_this_file)
1389             calculate_branch_probs (block_ptr, line_ptr, func_ptr);
1390           
1391           block_num++;
1392           block_ptr++;
1393         }
1394       else if (is_this_file)
1395         {
1396           if (line_num >= maxlineno)
1397             {
1398               fnotice (stderr, "ERROR: out of range line number in function %s\n",
1399                        function.name);
1400               abort ();
1401             }
1402
1403           line_ptr = &line_info[line_num];
1404           if (func_ptr)
1405             {
1406               if (!line_ptr->exists)
1407                 func_ptr->lines++;
1408               if (!line_ptr->count && block_ptr->exec_count)
1409                 func_ptr->lines_executed++;
1410             }
1411           
1412           /* Accumulate execution data for this line number.  */
1413           line_ptr->count += block_ptr->exec_count;
1414           line_ptr->exists = 1;
1415         }
1416     }
1417   
1418   if (func_ptr && is_this_file)
1419     function_summary (func_ptr, "function");
1420   
1421   /* Calculate summary test coverage statistics.  */
1422   for (line_num = 1, line_ptr = &line_info[line_num];
1423        line_num < maxlineno; line_num++, line_ptr++)
1424     {
1425       struct arcdata *a_ptr, *prev, *next;
1426       
1427       if (line_ptr->exists)
1428         {
1429           total->lines++;
1430           if (line_ptr->count)
1431             total->lines_executed++;
1432         }
1433
1434       /* Total and reverse the branch information.  */
1435       for (a_ptr = line_ptr->branches, prev = NULL; a_ptr; a_ptr = next)
1436         {
1437           next = a_ptr->next;
1438           a_ptr->next = prev;
1439           prev = a_ptr;
1440
1441           accumulate_branch_counts (total, a_ptr);
1442         }
1443       line_ptr->branches = prev;
1444     }
1445 }
1446
1447 /* Read in the source file one line at a time, and output that line to
1448    the gcov file preceded by its execution count and other
1449    information.  */
1450
1451 static void
1452 output_line_info (gcov_file, line_info, total, maxlineno)
1453      FILE *gcov_file;
1454      const struct line_info *line_info;
1455      const struct coverage *total;
1456      long maxlineno;
1457 {
1458   FILE *source_file;
1459   long line_num;                    /* current line number */
1460   const struct line_info *line_ptr; /* current line info ptr.  */
1461   char string[STRING_SIZE];         /* line buffer.  */
1462   char const *retval = "";          /* status of source file reading.  */
1463
1464   fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, total->name);
1465   fprintf (gcov_file, "%9s:%5d:Object:%s\n", "-", 0, bb_file_name);
1466   
1467   source_file = fopen (total->name, "r");
1468   if (!source_file)
1469     {
1470       fnotice (stderr, "Could not open source file %s.\n", total->name);
1471       retval = NULL;
1472     }
1473   else
1474     {
1475       struct stat status;
1476       
1477       if (!fstat (fileno (source_file), &status)
1478           && status.st_mtime > bb_file_time)
1479         {
1480           fnotice (stderr, "Warning: source file %s is newer than %s\n",
1481                    total->name, bb_file_name);
1482           fprintf (gcov_file, "%9s:%5d:Source is newer than compiler output\n",
1483                    "-", 0);
1484         }
1485     }
1486
1487   for (line_num = 1, line_ptr = &line_info[line_num];
1488        line_num < maxlineno; line_num++, line_ptr++)
1489     {
1490       /* For lines which don't exist in the .bb file, print '-' before
1491          the source line.  For lines which exist but were never
1492          executed, print '#####' before the source line.  Otherwise,
1493          print the execution count before the source line.  There are
1494          16 spaces of indentation added before the source line so that
1495          tabs won't be messed up.  */
1496       fprintf (gcov_file, "%9s:%5ld:",
1497                !line_ptr->exists ? "-"
1498                : !line_ptr->count ? "#####"
1499                : format_hwint (line_ptr->count, 0, -1), line_num);
1500       
1501       if (retval)
1502         {
1503           /* Copy source line.  */
1504           do
1505             {
1506               retval = fgets (string, STRING_SIZE, source_file);
1507               if (!retval)
1508                 {
1509                   fnotice (stderr,
1510                            "Unexpected EOF while reading source file %s.\n",
1511                            total->name);
1512                   break;
1513                 }
1514               fputs (retval, gcov_file);
1515             }
1516           while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1517         }
1518       if (!retval)
1519         fputs ("??\n", gcov_file);
1520       
1521       if (output_branch_probs)
1522         {
1523           int i;
1524           struct arcdata *a_ptr;
1525           
1526           for (i = 0, a_ptr = line_ptr->branches; a_ptr;
1527                a_ptr = a_ptr->next, i++)
1528             {
1529               if (a_ptr->call_insn)
1530                 {
1531                   if (a_ptr->total == 0)
1532                     fnotice (gcov_file, "call   %2d never executed\n", i);
1533                   else
1534                     fnotice
1535                       (gcov_file, "call   %2d returns %s\n", i,
1536                        format_hwint (a_ptr->total - a_ptr->hits,
1537                                      a_ptr->total,
1538                                      -output_branch_counts));
1539                 }
1540               else
1541                 {
1542                   if (a_ptr->total == 0)
1543                     fnotice (gcov_file, "branch %2d never executed\n", i);
1544                   else
1545                     fnotice
1546                       (gcov_file, "branch %2d taken %s\n", i,
1547                        format_hwint (a_ptr->hits, a_ptr->total,
1548                                      -output_branch_counts));
1549                 }
1550             }
1551         }
1552     }
1553   
1554   /* Handle all remaining source lines.  There may be lines after the
1555      last line of code.  */
1556   if (retval)
1557     {
1558       for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1559         {
1560           fprintf (gcov_file, "%9s:%5ld:%s", "-", line_num, retval);
1561           
1562           while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1563             {
1564               retval = fgets (string, STRING_SIZE, source_file);
1565               if (!retval)
1566                 break;
1567               fputs (retval, gcov_file);
1568             }
1569         }
1570     }
1571   
1572   if (source_file)
1573     fclose (source_file);
1574 }
1575
1576 /* Calculate line execution counts, and output a .gcov file for source
1577    file S_PTR. Allocate an array big enough to hold a count for each
1578    line.  Scan through the bb_data, and when the file name matches the
1579    current file name, then for each following line number, increment
1580    the line number execution count indicated by the execution count of
1581    the appropriate basic block.  */
1582
1583 static void
1584 output_data (s_ptr)
1585              struct sourcefile *s_ptr;
1586 {
1587   struct line_info *line_info   /* line info data */
1588     = (struct line_info *) xcalloc (s_ptr->maxlineno,
1589                                     sizeof (struct line_info));
1590   long line_num;
1591   struct coverage total;
1592   
1593   memset (&total, 0, sizeof (total));
1594   total.name = s_ptr->name;
1595   
1596   init_line_info (line_info, &total, s_ptr->maxlineno);
1597   function_summary (&total, "file");
1598
1599   if (output_gcov_file)
1600     {
1601       /* Now the statistics are ready.  Read in the source file one
1602          line at a time, and output that line to the gcov file
1603          preceded by its execution information.  */
1604       
1605       char *gcov_file_name = make_gcov_file_name (total.name);
1606       FILE *gcov_file = fopen (gcov_file_name, "w");
1607       
1608       if (gcov_file)
1609         {
1610           fnotice (stdout, "Creating %s.\n", gcov_file_name);
1611           output_line_info (gcov_file, line_info, &total, s_ptr->maxlineno);
1612           if (ferror (gcov_file))
1613             fnotice (stderr, "Error writing output file %s.\n",
1614                      gcov_file_name);
1615           fclose (gcov_file);
1616         }
1617       else
1618         fnotice (stderr, "Could not open output file %s.\n", gcov_file_name);
1619       free (gcov_file_name);
1620     }
1621
1622   /* Free data.  */
1623   for (line_num = 1; line_num != s_ptr->maxlineno; line_num++)
1624     {
1625       struct arcdata *branch, *next;
1626
1627       for (branch = line_info[line_num].branches; branch; branch = next)
1628         {
1629           next = branch->next;
1630           free (branch);
1631         }
1632     }
1633   free (line_info);
1634 }