Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / gcc / gcov.c
1 /* Gcov.c: prepend line execution counts and branch probabilities to a
2    source file.
3    Copyright (C) 1990, 91-94, 96, 97, 98, 1999 Free Software Foundation, Inc.
4    Contributed by James E. Wilson of Cygnus Support.
5    Mangled by Bob Manson of Cygnus Support.
6
7 Gcov is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 Gcov is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Gcov; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* ??? The code in final.c that produces the struct bb assumes that there is
23    no padding between the fields.  This is not necessary true.  The current
24    code can only be trusted if longs and pointers are the same size.  */
25
26 /* ??? No need to print an execution count on every line, could just print
27    it on the first line of each block, and only print it on a subsequent
28    line in the same block if the count changes.  */
29
30 /* ??? Print a list of the ten blocks with the highest execution counts,
31    and list the line numbers corresponding to those blocks.  Also, perhaps
32    list the line numbers with the highest execution counts, only printing
33    the first if there are several which are all listed in the same block.  */
34
35 /* ??? Should have an option to print the number of basic blocks, and the
36    percent of them that are covered.  */
37
38 /* ??? Does not correctly handle the case where two .bb files refer to the
39    same included source file.  For example, if one has a short file containing
40    only inline functions, which is then included in two other files, then
41    there will be two .bb files which refer to the include file, but there
42    is no way to get the total execution counts for the included file, can
43    only get execution counts for one or the other of the including files.  */
44
45 #include "config.h"
46 #include "system.h"
47 #include "intl.h"
48 #undef abort
49
50 #include "gcov-io.h"
51
52 /* The .bb file format consists of several lists of 4-byte integers
53    which are the line numbers of each basic block in the file.  Each
54    list is terminated by a zero.  These lists correspond to the basic
55    blocks in the reconstructed program flow graph.
56
57    A line number of -1 indicates that a source file name (padded to a
58    long boundary) follows.  The padded file name is followed by
59    another -1 to make it easy to scan past file names.  A -2 indicates
60    that a function name (padded to a long boundary) follows; the name
61    is followed by another -2 to make it easy to scan past the function
62    name.
63
64    The .bbg file contains enough info to enable gcov to reconstruct the
65    program flow graph.  The first word is the number of basic blocks,
66    the second word is the number of arcs, followed by the list of arcs
67    (source bb, dest bb pairs), then a -1, then the number of instrumented
68    arcs followed by the instrumented arcs, followed by another -1.  This
69    is repeated for each function.
70
71    The .da file contains the execution count for each instrumented branch.
72
73    The .bb and .bbg files are created by giving GCC the -ftest-coverage option,
74    and the .da files are created when an executable compiled with
75    -fprofile-arcs is run.  */
76
77 /* The functions in this file for creating and solution program flow graphs
78    are very similar to functions in the gcc source file profile.c.  */
79
80 char gcov_version_string[] = "GNU gcov version 1.5\n";
81
82 /* This is the size of the buffer used to read in source file lines.  */
83
84 #define STRING_SIZE 200
85
86 /* One copy of this structure is created for each source file mentioned in the
87    .bb file.  */
88
89 struct sourcefile
90 {
91   char *name;
92   int maxlineno;
93   struct sourcefile *next;
94 };
95
96 /* This points to the head of the sourcefile structure list.  */
97
98 struct sourcefile *sources;
99
100 /* One of these is dynamically created whenever we identify an arc in the
101    function.  */
102
103 struct adj_list {
104   int source;
105   int target;
106   int arc_count;
107   unsigned int count_valid : 1;
108   unsigned int on_tree : 1;
109   unsigned int fake : 1;
110   unsigned int fall_through : 1;
111 #if 0
112   /* Not needed for gcov, but defined in profile.c.  */
113   rtx branch_insn;
114 #endif
115   struct adj_list *pred_next;
116   struct adj_list *succ_next;
117 };
118
119 /* Count the number of basic blocks, and create an array of these structures,
120    one for each bb in the function.  */
121
122 struct bb_info {
123   struct adj_list *succ;
124   struct adj_list *pred;
125   int succ_count;
126   int pred_count;
127   int exec_count;
128   unsigned int count_valid : 1;
129   unsigned int on_tree : 1;
130 #if 0
131   /* Not needed for gcov, but defined in profile.c.  */
132   rtx first_insn;
133 #endif
134 };
135
136 /* When outputting branch probabilities, one of these structures is created
137    for each branch/call.  */
138
139 struct arcdata
140 {
141   int prob;
142   int call_insn;
143   struct arcdata *next;
144 };
145
146 /* Used to save the list of bb_graphs, one per function.  */
147
148 struct bb_info_list {
149   /* Indexed by block number, holds the basic block graph for one function.  */
150   struct bb_info *bb_graph;
151   int num_blocks;
152   struct bb_info_list *next;
153 };
154
155 /* Holds a list of function basic block graphs.  */
156
157 static struct bb_info_list *bb_graph_list = 0;
158
159 /* Name and file pointer of the input file for the basic block graph.  */
160
161 static char *bbg_file_name;
162 static FILE *bbg_file;
163
164 /* Name and file pointer of the input file for the arc count data.  */
165
166 static char *da_file_name;
167 static FILE *da_file;
168
169 /* Name and file pointer of the input file for the basic block line counts.  */
170
171 static char *bb_file_name;
172 static FILE *bb_file;
173
174 /* Holds the entire contents of the bb_file read into memory.  */
175
176 static char *bb_data;
177
178 /* Size of bb_data array in longs.  */
179
180 static long bb_data_size;
181
182 /* Name and file pointer of the output file.  */
183
184 static char *gcov_file_name;
185 static FILE *gcov_file;
186
187 /* Name of the file mentioned on the command line.  */
188
189 static char *input_file_name = 0;
190
191 /* Output branch probabilities if true.  */
192
193 static int output_branch_probs = 0;
194
195 /* Output a gcov file if this is true.  This is on by default, and can
196    be turned off by the -n option.  */
197
198 static int output_gcov_file = 1;
199
200 /* For included files, make the gcov output file name include the name of
201    the input source file.  For example, if x.h is included in a.c, then the
202    output file name is a.c.x.h.gcov instead of x.h.gcov.  This works only
203    when a single source file is specified.  */
204
205 static int output_long_names = 0;
206
207 /* Output summary info for each function.  */
208
209 static int output_function_summary = 0;
210
211 /* Object directory file prefix.  This is the directory where .bb and .bbg
212    files are looked for, if non-zero.  */
213
214 static char *object_directory = 0;
215
216 /* Forward declarations.  */
217 static void process_args PROTO ((int, char **));
218 static void open_files PROTO ((void));
219 static void read_files PROTO ((void));
220 static void scan_for_source_files PROTO ((void));
221 static void output_data PROTO ((void));
222 static void print_usage PROTO ((void)) ATTRIBUTE_NORETURN;
223
224 int
225 main (argc, argv)
226      int argc;
227      char **argv;
228 {
229 #ifdef HAVE_LC_MESSAGES
230   setlocale (LC_MESSAGES, "");
231 #endif
232   (void) bindtextdomain (PACKAGE, localedir);
233   (void) textdomain (PACKAGE);
234
235   process_args (argc, argv);
236
237   open_files ();
238
239   read_files ();
240
241   scan_for_source_files ();
242
243   output_data ();
244
245   return 0;
246 }
247
248 static void fnotice PVPROTO ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
249 static void
250 fnotice VPROTO ((FILE *file, const char *msgid, ...))
251 {
252 #ifndef ANSI_PROTOTYPES
253   FILE *file;
254   const char *msgid;
255 #endif
256   va_list ap;
257
258   VA_START (ap, msgid);
259
260 #ifndef ANSI_PROTOTYPES
261   file = va_arg (ap, FILE *);
262   msgid = va_arg (ap, const char *);
263 #endif
264
265   vfprintf (file, _(msgid), ap);
266   va_end (ap);
267 }
268
269
270 PTR
271 xmalloc (size)
272   size_t size;
273 {
274   register PTR value = (PTR) malloc (size);
275   if (value == 0)
276     {
277       fnotice (stderr, "error: virtual memory exhausted");
278       exit (FATAL_EXIT_CODE);
279     }
280   return value;
281 }
282
283 /* More 'friendly' abort that prints the line and file.
284    config.h can #define abort fancy_abort if you like that sort of thing.  */
285
286 void
287 fancy_abort ()
288 {
289   fnotice (stderr, "Internal gcc abort.\n");
290   exit (FATAL_EXIT_CODE);
291 }
292 \f
293 /* Print a usage message and exit.  */
294
295 static void
296 print_usage ()
297 {
298   fnotice (stderr, "gcov [-b] [-v] [-n] [-l] [-f] [-o OBJDIR] file\n");
299   exit (FATAL_EXIT_CODE);
300 }
301
302 /* Parse the command line.  */
303
304 static void
305 process_args (argc, argv)
306      int argc;
307      char **argv;
308 {
309   int i;
310
311   for (i = 1; i < argc; i++)
312     {
313       if (argv[i][0] == '-')
314         {
315           if (argv[i][1] == 'b')
316             output_branch_probs = 1;
317           else if (argv[i][1] == 'v')
318             fputs (gcov_version_string, stderr);
319           else if (argv[i][1] == 'n')
320             output_gcov_file = 0;
321           else if (argv[i][1] == 'l')
322             output_long_names = 1;
323           else if (argv[i][1] == 'f')
324             output_function_summary = 1;
325           else if (argv[i][1] == 'o' && argv[i][2] == '\0')
326             object_directory = argv[++i];
327           else
328             print_usage ();
329         }
330       else if (! input_file_name)
331         input_file_name = argv[i];
332       else
333         print_usage ();
334     }
335
336   if (! input_file_name)
337     print_usage ();
338 }
339
340
341 /* Find and open the .bb, .da, and .bbg files.  */
342
343 static void
344 open_files ()
345 {
346   int count, objdir_count;
347   char *cptr;
348
349   /* Determine the names of the .bb, .bbg, and .da files.  Strip off the
350      extension, if any, and append the new extensions.  */
351   count = strlen (input_file_name);
352   if (object_directory)
353     objdir_count = strlen (object_directory);
354   else
355     objdir_count = 0;
356
357   da_file_name = xmalloc (count + objdir_count + 4);
358   bb_file_name = xmalloc (count + objdir_count + 4);
359   bbg_file_name = xmalloc (count + objdir_count + 5);
360
361   if (object_directory)
362     {
363       strcpy (da_file_name, object_directory);
364       strcpy (bb_file_name, object_directory);
365       strcpy (bbg_file_name, object_directory);
366
367       if (object_directory[objdir_count - 1] != '/')
368         {
369           strcat (da_file_name, "/");
370           strcat (bb_file_name, "/");
371           strcat (bbg_file_name, "/");
372         }
373
374       cptr = rindex (input_file_name, '/');
375       if (cptr)
376         {
377           strcat (da_file_name, cptr + 1);
378           strcat (bb_file_name, cptr + 1);
379           strcat (bbg_file_name, cptr + 1);
380         }
381       else
382         {
383           strcat (da_file_name, input_file_name);
384           strcat (bb_file_name, input_file_name);
385           strcat (bbg_file_name, input_file_name);
386         }
387     }
388   else
389     {
390       strcpy (da_file_name, input_file_name);
391       strcpy (bb_file_name, input_file_name);
392       strcpy (bbg_file_name, input_file_name);
393     }
394
395   cptr = rindex (bb_file_name, '.');
396   if (cptr)
397     strcpy (cptr, ".bb");
398   else
399     strcat (bb_file_name, ".bb");
400
401   cptr = rindex (da_file_name, '.');
402   if (cptr)
403     strcpy (cptr, ".da");
404   else
405     strcat (da_file_name, ".da");
406
407   cptr = rindex (bbg_file_name, '.');
408   if (cptr)
409     strcpy (cptr, ".bbg");
410   else
411     strcat (bbg_file_name, ".bbg");
412
413   bb_file = fopen (bb_file_name, "r");
414   if (bb_file == NULL)
415     {
416       fnotice (stderr, "Could not open basic block file %s.\n", bb_file_name);
417       exit (FATAL_EXIT_CODE);
418     }
419
420   /* If none of the functions in the file were executed, then there won't
421      be a .da file.  Just assume that all counts are zero in this case.  */
422   da_file = fopen (da_file_name, "r");
423   if (da_file == NULL)
424     {
425       fnotice (stderr, "Could not open data file %s.\n", da_file_name);
426       fnotice (stderr, "Assuming that all execution counts are zero.\n");
427     }
428     
429   bbg_file = fopen (bbg_file_name, "r");
430   if (bbg_file == NULL)
431     {
432       fnotice (stderr, "Could not open program flow graph file %s.\n",
433                bbg_file_name);
434       exit (FATAL_EXIT_CODE);
435     }
436
437   /* Check for empty .bbg file.  This indicates that there is no executable
438      code in this source file.  */
439   /* Set the EOF condition if at the end of file.  */
440   ungetc (getc (bbg_file), bbg_file);
441   if (feof (bbg_file))
442     {
443       fnotice (stderr, "No executable code associated with file %s.\n",
444                input_file_name);
445       exit (FATAL_EXIT_CODE);
446     }
447 }
448 \f
449 /* Initialize a new arc.  */
450
451 static void
452 init_arc (arcptr, source, target, bb_graph)
453      struct adj_list *arcptr;
454      int source, target;
455      struct bb_info *bb_graph;
456 {
457   arcptr->target = target;
458   arcptr->source = source;
459
460   arcptr->arc_count = 0;
461   arcptr->count_valid = 0;
462   arcptr->on_tree = 0;
463   arcptr->fake = 0;
464   arcptr->fall_through = 0;
465
466   arcptr->succ_next = bb_graph[source].succ;
467   bb_graph[source].succ = arcptr;
468   bb_graph[source].succ_count++;
469
470   arcptr->pred_next = bb_graph[target].pred;
471   bb_graph[target].pred = arcptr;
472   bb_graph[target].pred_count++;
473 }
474
475
476 /* Reverse the arcs on a arc list.  */
477
478 static struct adj_list *
479 reverse_arcs (arcptr)
480      struct adj_list *arcptr;
481 {
482   struct adj_list *prev = 0;
483   struct adj_list *next;
484
485   for ( ; arcptr; arcptr = next)
486     {
487       next = arcptr->succ_next;
488       arcptr->succ_next = prev;
489       prev = arcptr;
490     }
491
492   return prev;
493 }
494
495
496 /* Construct the program flow graph from the .bbg file, and read in the data
497    in the .da file.  */
498
499 static void
500 create_program_flow_graph (bptr)
501      struct bb_info_list *bptr;
502 {
503   long num_blocks, number_arcs, src, dest, flag_bits, num_arcs_per_block;
504   int i;
505   struct adj_list *arcptr;
506   struct bb_info *bb_graph;
507
508   /* Read the number of blocks.  */
509   __read_long (&num_blocks, bbg_file, 4);
510
511   /* Create an array of size bb number of bb_info structs.  Bzero it.  */
512   bb_graph = (struct bb_info *) xmalloc (num_blocks
513                                          * sizeof (struct bb_info));
514   bzero ((char *) bb_graph, sizeof (struct bb_info) * num_blocks);
515
516   bptr->bb_graph = bb_graph;
517   bptr->num_blocks = num_blocks;
518
519   /* Read and create each arc from the .bbg file.  */
520   __read_long (&number_arcs, bbg_file, 4);
521   for (i = 0; i < num_blocks; i++)
522     {
523       int j;
524
525       __read_long (&num_arcs_per_block, bbg_file, 4);
526       for (j = 0; j < num_arcs_per_block; j++)
527         {
528           if (number_arcs-- < 0)
529             abort ();
530
531           src = i;
532           __read_long (&dest, bbg_file, 4);
533
534           arcptr = (struct adj_list *) xmalloc (sizeof (struct adj_list));
535           init_arc (arcptr, src, dest, bb_graph);
536
537           __read_long (&flag_bits, bbg_file, 4);
538           arcptr->on_tree = flag_bits & 0x1;
539           arcptr->fake = !! (flag_bits & 0x2);
540           arcptr->fall_through = !! (flag_bits & 0x4);
541         }
542     }
543
544   if (number_arcs)
545     abort ();
546
547   /* Read and ignore the -1 separating the arc list from the arc list of the
548      next function.  */
549   __read_long (&src, bbg_file, 4);
550   if (src != -1)
551     abort ();
552
553   /* Must reverse the order of all succ arcs, to ensure that they match
554      the order of the data in the .da file.  */
555
556   for (i = 0; i < num_blocks; i++)
557     if (bb_graph[i].succ)
558       bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
559
560   /* For each arc not on the spanning tree, set its execution count from
561      the .da file.  */
562
563   /* The first count in the .da file is the number of times that the function
564      was entered.  This is the exec_count for block zero.  */
565
566   /* This duplicates code in branch_prob in profile.c.  */
567
568   for (i = 0; i < num_blocks; i++)
569     for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
570       if (! arcptr->on_tree)
571         {
572           long tmp_count = 0;;
573           if (da_file && __read_long (&tmp_count, da_file, 8))
574             abort();
575
576           arcptr->arc_count = tmp_count;
577           arcptr->count_valid = 1;
578           bb_graph[i].succ_count--;
579           bb_graph[arcptr->target].pred_count--;
580         }
581 }
582   
583 static void
584 solve_program_flow_graph (bptr)
585      struct bb_info_list *bptr;
586 {
587   int passes, changes, total;
588   int i;
589   struct adj_list *arcptr;
590   struct bb_info *bb_graph;
591   int num_blocks;
592
593   num_blocks = bptr->num_blocks;
594   bb_graph = bptr->bb_graph;
595
596   /* For every block in the file,
597      - if every exit/entrance arc has a known count, then set the block count
598      - if the block count is known, and every exit/entrance arc but one has
599        a known execution count, then set the count of the remaining arc
600
601      As arc counts are set, decrement the succ/pred count, but don't delete
602      the arc, that way we can easily tell when all arcs are known, or only
603      one arc is unknown.  */
604
605   /* The order that the basic blocks are iterated through is important.
606      Since the code that finds spanning trees starts with block 0, low numbered
607      arcs are put on the spanning tree in preference to high numbered arcs.
608      Hence, most instrumented arcs are at the end.  Graph solving works much
609      faster if we propagate numbers from the end to the start.
610
611      This takes an average of slightly more than 3 passes.  */
612
613   changes = 1;
614   passes = 0;
615   while (changes)
616     {
617       passes++;
618       changes = 0;
619
620       for (i = num_blocks - 1; i >= 0; i--)
621         {
622           if (! bb_graph[i].count_valid)
623             {
624               if (bb_graph[i].succ_count == 0)
625                 {
626                   total = 0;
627                   for (arcptr = bb_graph[i].succ; arcptr;
628                        arcptr = arcptr->succ_next)
629                     total += arcptr->arc_count;
630                   bb_graph[i].exec_count = total;
631                   bb_graph[i].count_valid = 1;
632                   changes = 1;
633                 }
634               else if (bb_graph[i].pred_count == 0)
635                 {
636                   total = 0;
637                   for (arcptr = bb_graph[i].pred; arcptr;
638                        arcptr = arcptr->pred_next)
639                     total += arcptr->arc_count;
640                   bb_graph[i].exec_count = total;
641                   bb_graph[i].count_valid = 1;
642                   changes = 1;
643                 }
644             }
645           if (bb_graph[i].count_valid)
646             {
647               if (bb_graph[i].succ_count == 1)
648                 {
649                   total = 0;
650                   /* One of the counts will be invalid, but it is zero,
651                      so adding it in also doesn't hurt.  */
652                   for (arcptr = bb_graph[i].succ; arcptr;
653                        arcptr = arcptr->succ_next)
654                     total += arcptr->arc_count;
655                   /* Calculate count for remaining arc by conservation.  */
656                   total = bb_graph[i].exec_count - total;
657                   /* Search for the invalid arc, and set its count.  */
658                   for (arcptr = bb_graph[i].succ; arcptr;
659                        arcptr = arcptr->succ_next)
660                     if (! arcptr->count_valid)
661                       break;
662                   if (! arcptr)
663                     abort ();
664                   arcptr->count_valid = 1;
665                   arcptr->arc_count = total;
666                   bb_graph[i].succ_count--;
667
668                   bb_graph[arcptr->target].pred_count--;
669                   changes = 1;
670                 }
671               if (bb_graph[i].pred_count == 1)
672                 {
673                   total = 0;
674                   /* One of the counts will be invalid, but it is zero,
675                      so adding it in also doesn't hurt.  */
676                   for (arcptr = bb_graph[i].pred; arcptr;
677                        arcptr = arcptr->pred_next)
678                     total += arcptr->arc_count;
679                   /* Calculate count for remaining arc by conservation.  */
680                   total = bb_graph[i].exec_count - total;
681                   /* Search for the invalid arc, and set its count.  */
682                   for (arcptr = bb_graph[i].pred; arcptr;
683                        arcptr = arcptr->pred_next)
684                     if (! arcptr->count_valid)
685                       break;
686                   if (! arcptr)
687                     abort ();
688                   arcptr->count_valid = 1;
689                   arcptr->arc_count = total;
690                   bb_graph[i].pred_count--;
691
692                   bb_graph[arcptr->source].succ_count--;
693                   changes = 1;
694                 }
695             }
696         }
697     }
698               
699   /* If the graph has been correctly solved, every block will have a
700      succ and pred count of zero.  */
701   for (i = 0; i < num_blocks; i++)
702     if (bb_graph[i].succ_count || bb_graph[i].pred_count)
703       abort ();
704 }
705
706
707 static void
708 read_files ()
709 {
710   struct stat buf;
711   struct bb_info_list *list_end = 0;
712   struct bb_info_list *b_ptr;
713   long total;
714
715   /* Read and ignore the first word of the .da file, which is the count of
716      how many numbers follow.  */
717   if (da_file && __read_long (&total, da_file, 8))
718     abort();
719
720   while (! feof (bbg_file))
721     {
722       b_ptr = (struct bb_info_list *) xmalloc (sizeof (struct bb_info_list));
723
724       b_ptr->next = 0;
725       if (list_end)
726         list_end->next = b_ptr;
727       else
728         bb_graph_list = b_ptr;
729       list_end = b_ptr;
730
731       /* Read in the data in the .bbg file and reconstruct the program flow
732          graph for one function.  */
733       create_program_flow_graph (b_ptr);
734
735       /* Set the EOF condition if at the end of file.  */
736       ungetc (getc (bbg_file), bbg_file);
737     }
738
739   /* Check to make sure the .da file data is valid.  */
740
741   if (da_file)
742     {
743       if (feof (da_file))
744         fnotice (stderr, ".da file contents exhausted too early\n");
745       /* Should be at end of file now.  */
746       if (__read_long (&total, da_file, 8) == 0)
747         fnotice (stderr, ".da file contents not exhausted\n");
748     }
749
750   /* Calculate all of the basic block execution counts and branch
751      taken probabilities.  */
752
753   for (b_ptr = bb_graph_list; b_ptr; b_ptr = b_ptr->next)
754     solve_program_flow_graph (b_ptr);
755
756   /* Read in all of the data from the .bb file.   This info will be accessed
757      sequentially twice.  */
758   stat (bb_file_name, &buf);
759   bb_data_size = buf.st_size / 4;
760
761   bb_data = (char *) xmalloc ((unsigned) buf.st_size);
762   fread (bb_data, sizeof (char), buf.st_size, bb_file);
763   
764   fclose (bb_file);
765   if (da_file)
766     fclose (da_file);
767   fclose (bbg_file);
768 }
769
770
771 /* Scan the data in the .bb file to find all source files referenced,
772    and the largest line number mentioned in each one.  */
773
774 static void
775 scan_for_source_files ()
776 {
777   struct sourcefile *s_ptr = NULL;
778   char *ptr;
779   int count;
780   long line_num;
781
782   /* Search the bb_data to find:
783      1) The number of sources files contained herein, and
784      2) The largest line number for each source file.  */
785
786   ptr = bb_data;
787   sources = 0;
788   for (count = 0; count < bb_data_size; count++)
789     {
790       __fetch_long (&line_num, ptr, 4);
791       ptr += 4;
792       if (line_num == -1)
793         {
794           /* A source file name follows.  Check to see if we already have
795            a sourcefile structure for this file.  */
796           s_ptr = sources;
797           while (s_ptr && strcmp (s_ptr->name, ptr))
798             s_ptr = s_ptr->next;
799
800           if (s_ptr == 0)
801             {
802               /* No sourcefile structure for this file name exists, create
803                  a new one, and append it to the front of the sources list.  */
804               s_ptr = (struct sourcefile *) xmalloc (sizeof(struct sourcefile));
805               s_ptr->name = xmalloc (strlen ((char *) ptr) + 1);
806               strcpy (s_ptr->name, (char *) ptr);
807               s_ptr->maxlineno = 0;
808               s_ptr->next = sources;
809               sources = s_ptr;
810             }
811
812           /* Scan past the file name.  */
813           {
814             long delim;
815             do {
816               count++;
817               __fetch_long (&delim, ptr, 4);
818               ptr += 4;
819             } while (delim != line_num);
820           }
821         }
822       else if (line_num == -2)
823         {
824           long delim;
825
826           /* A function name follows.  Ignore it.  */
827           do {
828             count++;
829             __fetch_long (&delim, ptr, 4);
830             ptr += 4;
831           } while (delim != line_num);
832         }
833       /* There will be a zero before the first file name, in which case s_ptr
834          will still be uninitialized.  So, only try to set the maxlineno
835          field if line_num is non-zero.  */
836       else if (line_num > 0)
837         {
838           if (s_ptr->maxlineno <= line_num)
839             s_ptr->maxlineno = line_num + 1;
840         }
841       else if (line_num < 0)
842         {
843           /* Don't know what this is, but it's garbage. */
844           abort();
845         }
846     }
847 }
848 \f
849 /* For calculating coverage at the function level.  */
850
851 static int function_source_lines;
852 static int function_source_lines_executed;
853 static int function_branches;
854 static int function_branches_executed;
855 static int function_branches_taken;
856 static int function_calls;
857 static int function_calls_executed;
858 static char *function_name;
859
860 /* Calculate the branch taken probabilities for all arcs branches at the
861    end of this block.  */
862
863 static void
864 calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
865      struct bb_info_list *current_graph;
866      int block_num;
867      struct arcdata **branch_probs;
868      int last_line_num;
869 {
870   int total;
871   struct adj_list *arcptr;
872   struct arcdata *end_ptr, *a_ptr;
873
874   total = current_graph->bb_graph[block_num].exec_count;
875   for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
876        arcptr = arcptr->succ_next)
877     {
878       /* Ignore fall through arcs as they aren't really branches.  */
879
880       if (arcptr->fall_through)
881         continue;
882                       
883       a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
884       if (total == 0)
885         a_ptr->prob = -1;
886       else
887         a_ptr->prob = ((arcptr->arc_count * 100) + (total >> 1)) / total;
888       a_ptr->call_insn = arcptr->fake;
889
890       if (output_function_summary)
891         {
892           if (a_ptr->call_insn)
893             {
894               function_calls++;
895               if (a_ptr->prob != -1)
896                 function_calls_executed++;
897             }
898           else
899             {
900               function_branches++;
901               if (a_ptr->prob != -1)
902                 function_branches_executed++;
903               if (a_ptr->prob > 0)
904                 function_branches_taken++;
905             }
906         }
907
908       /* Append the new branch to the end of the list.  */
909       a_ptr->next = 0;
910       if (! branch_probs[last_line_num])
911         branch_probs[last_line_num] = a_ptr;
912       else
913         {
914           end_ptr = branch_probs[last_line_num];
915           while (end_ptr->next != 0)
916             end_ptr = end_ptr->next;
917           end_ptr->next = a_ptr;
918         }
919     }
920 }
921
922 /* Output summary info for a function.  */
923
924 static void
925 function_summary ()
926 {
927   if (function_source_lines)
928     fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
929              (((double) function_source_lines_executed / function_source_lines)
930               * 100), function_source_lines, function_name);
931   else
932     fnotice (stdout, "No executable source lines in function %s\n",
933              function_name);
934
935   if (output_branch_probs)
936     {
937       if (function_branches)
938         {
939           fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
940                    (((double) function_branches_executed / function_branches)
941                     * 100), function_branches, function_name);
942           fnotice (stdout,
943                 "%6.2f%% of %d branches taken at least once in function %s\n",
944                    (((double) function_branches_taken / function_branches)
945                     * 100), function_branches, function_name);
946         }
947       else
948         fnotice (stdout, "No branches in function %s\n", function_name);
949       if (function_calls)
950         fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
951                  (((double) function_calls_executed / function_calls)
952                   * 100), function_calls, function_name);
953       else
954         fnotice (stdout, "No calls in function %s\n", function_name);
955     }
956 }
957
958 /* Calculate line execution counts, and output the data to a .tcov file.  */
959
960 static void
961 output_data ()
962 {
963   /* When scanning data, this is true only if the data applies to the
964      current source file.  */
965   int this_file;
966   /* An array indexed by line number which indicates how many times that line
967      was executed.  */
968   long *line_counts;
969   /* An array indexed by line number which indicates whether the line was
970      present in the bb file (i.e. whether it had code associate with it).
971      Lines never executed are those which both exist, and have zero execution
972      counts.  */
973   char *line_exists;
974   /* An array indexed by line number, which contains a list of branch
975      probabilities, one for each branch on that line.  */
976   struct arcdata **branch_probs = NULL;
977   struct sourcefile *s_ptr;
978   char *source_file_name;
979   FILE *source_file;
980   struct bb_info_list *current_graph;
981   int count;
982   char *cptr;
983   long block_num;
984   long line_num;
985   long last_line_num = 0;
986   int i;
987   struct arcdata *a_ptr;
988   /* Buffer used for reading in lines from the source file.  */
989   char string[STRING_SIZE];
990   /* For calculating coverage at the file level.  */
991   int total_source_lines;
992   int total_source_lines_executed;
993   int total_branches;
994   int total_branches_executed;
995   int total_branches_taken;
996   int total_calls;
997   int total_calls_executed;
998
999   /* Now, for each source file, allocate an array big enough to hold a count
1000      for each line.  Scan through the bb_data, and when the file name matches
1001      the current file name, then for each following line number, increment
1002      the line number execution count indicated by the execution count of
1003      the appropriate basic block.  */
1004
1005   for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
1006     {
1007       /* If this is a relative file name, and an object directory has been
1008          specified, then make it relative to the object directory name.  */
1009       if (*s_ptr->name != '/' && object_directory != 0
1010           && *object_directory != '\0')
1011         {
1012           int objdir_count = strlen (object_directory);
1013           source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
1014           strcpy (source_file_name, object_directory);
1015           if (object_directory[objdir_count - 1] != '/')
1016             source_file_name[objdir_count++] = '/';
1017           strcpy (source_file_name + objdir_count, s_ptr->name);
1018         }
1019       else
1020         source_file_name = s_ptr->name;
1021
1022       line_counts = (long *) xmalloc (sizeof (long) * s_ptr->maxlineno);
1023       bzero ((char *) line_counts, sizeof (long) * s_ptr->maxlineno);
1024       line_exists = xmalloc (s_ptr->maxlineno);
1025       bzero (line_exists, s_ptr->maxlineno);
1026       if (output_branch_probs)
1027         {
1028           branch_probs = (struct arcdata **) xmalloc (sizeof (struct arcdata *)
1029                                                       * s_ptr->maxlineno);
1030           bzero ((char *) branch_probs, 
1031                  sizeof (struct arcdata *) * s_ptr->maxlineno);
1032         }
1033       
1034       /* There will be a zero at the beginning of the bb info, before the
1035          first list of line numbers, so must initialize block_num to 0.  */
1036       block_num = 0;
1037       this_file = 0;
1038       current_graph = 0;
1039       {
1040         /* Pointer into the bb_data, incremented while scanning the data.  */
1041         char *ptr = bb_data;
1042         for (count = 0; count < bb_data_size; count++)
1043           {
1044             long delim;
1045
1046             __fetch_long (&line_num, ptr, 4);
1047             ptr += 4;
1048             if (line_num == -1)
1049               {
1050                 /* Marks the beginning of a file name.  Check to see whether
1051                    this is the filename we are currently collecting data for.  */
1052
1053                 if (strcmp (s_ptr->name, ptr))
1054                   this_file = 0;
1055                 else
1056                   this_file = 1;
1057               
1058                 /* Scan past the file name.  */
1059                 do {
1060                   count++;
1061                   __fetch_long (&delim, ptr, 4);
1062                   ptr += 4;
1063                 } while (delim != line_num);
1064               }
1065             else if (line_num == -2)
1066               {
1067                 /* Marks the start of a new function.  Advance to the next
1068                    program flow graph.  */
1069
1070                 if (! current_graph)
1071                   current_graph = bb_graph_list;
1072                 else
1073                   {
1074                     if (block_num == current_graph->num_blocks - 1)
1075                       /* Last block falls through to exit.  */
1076                       ;
1077                     else if (block_num == current_graph->num_blocks - 2)
1078                       {
1079                         if (output_branch_probs && this_file)
1080                           calculate_branch_probs (current_graph, block_num,
1081                                                   branch_probs, last_line_num);
1082                       }
1083                     else
1084                       {
1085                         fnotice (stderr,
1086                                  "didn't use all bb entries of graph, function %s\n",
1087                                  function_name);
1088                         fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
1089                                  block_num, current_graph->num_blocks);
1090                       }
1091
1092                     current_graph = current_graph->next;
1093                     block_num = 0;
1094
1095                     if (output_function_summary && this_file)
1096                       function_summary ();
1097                   }
1098
1099                 if (output_function_summary)
1100                   {
1101                     function_source_lines = 0;
1102                     function_source_lines_executed = 0;
1103                     function_branches = 0;
1104                     function_branches_executed = 0;
1105                     function_branches_taken = 0;
1106                     function_calls = 0;
1107                     function_calls_executed = 0;
1108                   }
1109
1110                 /* Save the function name for later use.  */
1111                 function_name = ptr;
1112
1113                 /* Scan past the file name.  */
1114                 do {
1115                   count++;
1116                   __fetch_long (&delim, ptr, 4);
1117                   ptr += 4;
1118                 } while (delim != line_num);
1119               }
1120             else if (line_num == 0)
1121               {
1122                 /* Marks the end of a block.  */
1123
1124                 if (block_num >= current_graph->num_blocks)
1125                   {
1126                     fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
1127                              function_name);
1128                     abort ();
1129                   }
1130                   
1131                 if (output_branch_probs && this_file)
1132                   calculate_branch_probs (current_graph, block_num,
1133                                           branch_probs, last_line_num);
1134
1135                 block_num++;
1136               }
1137             else if (this_file)
1138               {
1139                 if (output_function_summary)
1140                   {
1141                     if (line_exists[line_num] == 0)
1142                       function_source_lines++;
1143                     if (line_counts[line_num] == 0
1144                         && current_graph->bb_graph[block_num].exec_count != 0)
1145                       function_source_lines_executed++;
1146                   }
1147
1148                 /* Accumulate execution data for this line number.  */
1149
1150                 line_counts[line_num]
1151                   += current_graph->bb_graph[block_num].exec_count;
1152                 line_exists[line_num] = 1;
1153                 last_line_num = line_num;
1154               }
1155           }
1156       }
1157
1158       if (output_function_summary && this_file)
1159         function_summary ();
1160
1161       /* Calculate summary test coverage statistics.  */
1162
1163       total_source_lines = 0;
1164       total_source_lines_executed = 0;
1165       total_branches = 0;
1166       total_branches_executed = 0;
1167       total_branches_taken = 0;
1168       total_calls = 0;
1169       total_calls_executed = 0;
1170
1171       for (count = 1; count < s_ptr->maxlineno; count++)
1172         {
1173           if (line_exists[count])
1174             {
1175               total_source_lines++;
1176               if (line_counts[count])
1177                 total_source_lines_executed++;
1178             }
1179           if (output_branch_probs)
1180             {
1181               for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
1182                 {
1183                   if (a_ptr->call_insn)
1184                     {
1185                       total_calls++;
1186                       if (a_ptr->prob != -1)
1187                         total_calls_executed++;
1188                     }
1189                   else
1190                     {
1191                       total_branches++;
1192                       if (a_ptr->prob != -1)
1193                         total_branches_executed++;
1194                       if (a_ptr->prob > 0)
1195                         total_branches_taken++;
1196                     }
1197                 }
1198             }
1199         }
1200
1201       if (total_source_lines)
1202         fnotice (stdout,
1203                  "%6.2f%% of %d source lines executed in file %s\n",
1204                  (((double) total_source_lines_executed / total_source_lines)
1205                   * 100), total_source_lines, source_file_name);
1206       else
1207         fnotice (stdout, "No executable source lines in file %s\n",
1208                  source_file_name);
1209
1210       if (output_branch_probs)
1211         {
1212           if (total_branches)
1213             {
1214               fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
1215                        (((double) total_branches_executed / total_branches)
1216                         * 100), total_branches, source_file_name);
1217               fnotice (stdout,
1218                     "%6.2f%% of %d branches taken at least once in file %s\n",
1219                        (((double) total_branches_taken / total_branches)
1220                         * 100), total_branches, source_file_name);
1221             }
1222           else
1223             fnotice (stdout, "No branches in file %s\n", source_file_name);
1224           if (total_calls)
1225             fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
1226                      (((double) total_calls_executed / total_calls)
1227                       * 100), total_calls, source_file_name);
1228           else
1229             fnotice (stdout, "No calls in file %s\n", source_file_name);
1230         }
1231
1232       if (output_gcov_file)
1233         {
1234           /* Now the statistics are ready.  Read in the source file one line
1235              at a time, and output that line to the gcov file preceded by
1236              its execution count if non zero.  */
1237       
1238           source_file = fopen (source_file_name, "r");
1239           if (source_file == NULL)
1240             {
1241               fnotice (stderr, "Could not open source file %s.\n",
1242                        source_file_name);
1243               free (line_counts);
1244               free (line_exists);
1245               continue;
1246             }
1247
1248           count = strlen (source_file_name);
1249           cptr = rindex (s_ptr->name, '/');
1250           if (cptr)
1251             cptr = cptr + 1;
1252           else
1253             cptr = s_ptr->name;
1254           if (output_long_names && strcmp (cptr, input_file_name))
1255             {
1256               gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
1257               
1258               cptr = rindex (input_file_name, '/');
1259               if (cptr)
1260                 strcpy (gcov_file_name, cptr + 1);
1261               else
1262                 strcpy (gcov_file_name, input_file_name);
1263
1264               strcat (gcov_file_name, ".");
1265
1266               cptr = rindex (source_file_name, '/');
1267               if (cptr)
1268                 strcat (gcov_file_name, cptr + 1);
1269               else
1270                 strcat (gcov_file_name, source_file_name);
1271             }
1272           else
1273             {
1274               gcov_file_name = xmalloc (count + 6);
1275               cptr = rindex (source_file_name, '/');
1276               if (cptr)
1277                 strcpy (gcov_file_name, cptr + 1);
1278               else
1279                 strcpy (gcov_file_name, source_file_name);
1280             }
1281
1282           /* Don't strip off the ending for compatibility with tcov, since
1283              this results in confusion if there is more than one file with
1284              the same basename, e.g. tmp.c and tmp.h.  */
1285           strcat (gcov_file_name, ".gcov");
1286
1287           gcov_file = fopen (gcov_file_name, "w");
1288
1289           if (gcov_file == NULL)
1290             {
1291               fnotice (stderr, "Could not open output file %s.\n",
1292                        gcov_file_name);
1293               fclose (source_file);
1294               free (line_counts);
1295               free (line_exists);
1296               continue;
1297             }
1298
1299           fnotice (stdout, "Creating %s.\n", gcov_file_name);
1300
1301           for (count = 1; count < s_ptr->maxlineno; count++)
1302             {
1303               char *retval;
1304               int len;
1305
1306               retval = fgets (string, STRING_SIZE, source_file);
1307
1308               /* For lines which don't exist in the .bb file, print nothing
1309                  before the source line.  For lines which exist but were never
1310                  executed, print ###### before the source line.  Otherwise,
1311                  print the execution count before the source line.  */
1312               /* There are 16 spaces of indentation added before the source
1313                  line so that tabs won't be messed up.  */
1314               if (line_exists[count])
1315                 {
1316                   if (line_counts[count])
1317                     fprintf (gcov_file, "%12ld    %s", line_counts[count],
1318                              string);
1319                   else
1320                     fprintf (gcov_file, "      ######    %s", string);
1321                 }
1322               else
1323                 fprintf (gcov_file, "\t\t%s", string);
1324
1325               /* In case the source file line is larger than our buffer, keep
1326                  reading and outputting lines until we get a newline.  */
1327               len = strlen (string);
1328               while ((len == 0 || string[strlen (string) - 1] != '\n')
1329                      && retval != NULL)
1330                 {
1331                   retval = fgets (string, STRING_SIZE, source_file);
1332                   fputs (string, gcov_file);
1333                 }
1334
1335               if (output_branch_probs)
1336                 {
1337                   for (i = 0, a_ptr = branch_probs[count]; a_ptr;
1338                        a_ptr = a_ptr->next, i++)
1339                     {
1340                       if (a_ptr->call_insn)
1341                         {
1342                           if (a_ptr->prob == -1)
1343                             fnotice (gcov_file, "call %d never executed\n", i);
1344                           else
1345                             fnotice (gcov_file,
1346                                      "call %d returns = %d%%\n",
1347                                      i, 100 - a_ptr->prob);
1348                         }
1349                       else
1350                         {
1351                           if (a_ptr->prob == -1)
1352                             fnotice (gcov_file, "branch %d never executed\n",
1353                                      i);
1354                           else
1355                             fnotice (gcov_file, "branch %d taken = %d%%\n", i,
1356                                      a_ptr->prob);
1357                         }
1358                     }
1359                 }
1360
1361               /* Gracefully handle errors while reading the source file.  */
1362               if (retval == NULL)
1363                 {
1364                   fnotice (stderr,
1365                            "Unexpected EOF while reading source file %s.\n",
1366                            source_file_name);
1367                   break;
1368                 }
1369             }
1370
1371           /* Handle all remaining source lines.  There may be lines
1372              after the last line of code.  */
1373
1374           {
1375             char *retval = fgets (string, STRING_SIZE, source_file);
1376             while (retval != NULL)
1377               {
1378                 int len;
1379
1380                 fprintf (gcov_file, "\t\t%s", string);
1381
1382                 /* In case the source file line is larger than our buffer, keep
1383                    reading and outputting lines until we get a newline.  */
1384                 len = strlen (string);
1385                 while ((len == 0 || string[strlen (string) - 1] != '\n')
1386                        && retval != NULL)
1387                   {
1388                     retval = fgets (string, STRING_SIZE, source_file);
1389                     fputs (string, gcov_file);
1390                   }
1391
1392                 retval = fgets (string, STRING_SIZE, source_file);
1393               }
1394           }
1395
1396           fclose (source_file);
1397           fclose (gcov_file);
1398         }
1399
1400       free (line_counts);
1401       free (line_exists);
1402     }
1403 }