OSDN Git Service

* basic-block.h: Fix comment formatting.
[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    Mangled further by Nathan Sidwell <nathan@codesourcery.com>
8
9 Gcov is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 Gcov is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Gcov; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24 /* ??? Print a list of the ten blocks with the highest execution counts,
25    and list the line numbers corresponding to those blocks.  Also, perhaps
26    list the line numbers with the highest execution counts, only printing
27    the first if there are several which are all listed in the same block.  */
28
29 /* ??? Should have an option to print the number of basic blocks, and the
30    percent of them that are covered.  */
31
32 /* ??? Does not correctly handle the case where two .bb files refer to
33    the same included source file.  For example, if one has a short
34    file containing only inline functions, which is then included in
35    two other files, then there will be two .bb files which refer to
36    the include file, but there is no way to get the total execution
37    counts for the included file, can only get execution counts for one
38    or the other of the including files. this can be fixed by --ratios
39    --long-file-names --preserve-paths and perl.  */
40
41 /* Need an option to show individual block counts, and show
42    probabilities of fall through arcs.  */
43
44 #include "config.h"
45 #include "system.h"
46 #include "coretypes.h"
47 #include "tm.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 bbg file is generated by -ftest-coverage option. The da file is
58    generated by a program compiled with -fprofile-arcs. Their formats
59    are documented in gcov-io.h.  */
60
61 /* The functions in this file for creating and solution program flow graphs
62    are very similar to functions in the gcc source file profile.c.  In
63    some places we make use of the knowledge of how profile.c works to
64    select particular algorithms here.  */
65
66 /* This is the size of the buffer used to read in source file lines.  */
67
68 #define STRING_SIZE 200
69
70 struct function_info;
71 struct block_info;
72
73 /* Describes an arc between two basic blocks.  */
74
75 typedef struct arc_info
76 {
77   /* source and destination blocks.  */
78   struct block_info *src;
79   struct block_info *dst;
80
81   /* transition counts.  */
82   gcov_type count;
83
84   unsigned int count_valid : 1;
85   unsigned int on_tree : 1;
86   unsigned int fake : 1;
87   unsigned int fall_through : 1;
88
89   /* Arc to a call.  */
90   unsigned int is_call : 1;
91   
92   /* Next branch on line.  */
93   struct arc_info *line_next;
94   
95   /* Links to next arc on src and dst lists.  */
96   struct arc_info *succ_next;
97   struct arc_info *pred_next;
98 } arc_t;
99
100 /* Describes a basic block. Contains lists of arcs to successor and
101    predecessor blocks.  */
102
103 typedef struct block_info
104 {
105   /* Chain of exit and entry arcs.  */
106   arc_t *succ;
107   arc_t *pred;
108
109   /* Number of unprocessed exit and entry arcs.  */
110   gcov_type num_succ;
111   gcov_type num_pred;
112
113   /* Block execution count.  */
114   gcov_type count;
115   unsigned count_valid : 1;
116   unsigned valid_chain : 1;
117   unsigned invalid_chain : 1;
118
119   /* Array of line numbers and source files. source files are
120      introduced by a linenumber of zero, the next 'line number' is the
121      number of the source file.  Always starts with a source file.  */
122   unsigned *encoding;
123   unsigned num_encodings;
124
125   /* Temporary chain for solving graph.  */
126   struct block_info *chain;
127   
128 } block_t;
129
130 /* Describes a single function. Contains an array of basic blocks.  */
131
132 typedef struct function_info
133 {
134   /* Name of function.  */
135   char *name;
136   unsigned checksum;
137
138   /* Array of basic blocks.  */
139   block_t *blocks;
140   unsigned num_blocks;
141
142   /* Raw arc coverage counts.  */
143   gcov_type *counts;
144   unsigned num_counts;
145   
146   /* Next function.  */
147   struct function_info *next;
148 } function_t;
149
150 /* Describes coverage of a file or function.  */
151
152 typedef struct coverage_info
153 {
154   int lines;
155   int lines_executed;
156   
157   int branches;
158   int branches_executed;
159   int branches_taken;
160   
161   int calls;
162   int calls_executed;
163   
164   char *name;
165 } coverage_t;
166
167 /* Describes a single line of source. Contains a chain of basic blocks
168    with code on it.  */
169
170 typedef struct line_info
171 {
172   gcov_type count;         /* execution count */
173   arc_t *branches;         /* branches from blocks that end on this
174                               line.  */
175   unsigned exists : 1;
176 } line_t;
177
178 /* Describes a file mentioned in the block graph.  Contains an array
179    of line info.  */
180
181 typedef struct source_info
182 {
183   /* Name of source file.  */
184   char *name;
185   unsigned index;
186
187   /* Array of line information.  */
188   line_t *lines;
189   unsigned num_lines;
190
191   coverage_t coverage;
192   
193   /* Next source file.  */
194   struct source_info *next;
195 } source_t;
196
197 /* Holds a list of function basic block graphs.  */
198
199 static function_t *functions;
200
201 /* This points to the head of the sourcefile structure list.  */
202
203 static source_t *sources;
204
205 /* Modification time of graph file.  */
206
207 static time_t bbg_file_time;
208
209 /* Name and file pointer of the input file for the basic block graph.  */
210
211 static char *bbg_file_name;
212
213 /* Name and file pointer of the input file for the arc count data.  */
214
215 static char *da_file_name;
216
217 /* Output branch probabilities.  */
218
219 static int flag_branches = 0;
220
221 /* Output a gcov file if this is true.  This is on by default, and can
222    be turned off by the -n option.  */
223
224 static int flag_gcov_file = 1;
225
226 /* For included files, make the gcov output file name include the name
227    of the input source file.  For example, if x.h is included in a.c,
228    then the output file name is a.c##x.h.gcov instead of x.h.gcov.  */
229
230 static int flag_long_names = 0;
231
232 /* Output summary info for each function.  */
233
234 static int flag_function_summary = 0;
235
236 /* Object directory file prefix.  This is the directory/file where the
237    graph and data files are looked for, if nonzero.  */
238
239 static char *object_directory = 0;
240
241 /* Preserve all pathname components. Needed when object files and
242    source files are in subdirectories. '/' is mangled as '#', '.' is
243    elided and '..' mangled to '^'.  */
244
245 static int flag_preserve_paths = 0;
246
247 /* Output the number of times a branch was taken as opposed to the percentage
248    of times it was taken.  */
249
250 static int flag_counts = 0;
251
252 /* Forward declarations.  */
253 static void fnotice PARAMS ((FILE *, const char *, ...)) ATTRIBUTE_PRINTF_2;
254 static int process_args PARAMS ((int, char **));
255 static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
256 static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
257 static void process_file PARAMS ((const char *));
258 static void create_file_names PARAMS ((const char *));
259 static int read_graph_file PARAMS ((void));
260 static int read_count_file PARAMS ((void));
261 static void solve_flow_graph PARAMS ((function_t *));
262 static void add_branch_counts PARAMS ((coverage_t *, const arc_t *));
263 static void add_line_counts PARAMS ((coverage_t *, const function_t *));
264 static void function_summary PARAMS ((const coverage_t *, const char *));
265 static const char *format_gcov PARAMS ((gcov_type, gcov_type, int));
266 static void accumulate_line_counts PARAMS ((source_t *));
267 static void output_lines PARAMS ((FILE *, const source_t *));
268 static char *make_gcov_file_name PARAMS ((const char *, const char *));
269 static void release_structures PARAMS ((void));
270 extern int main PARAMS ((int, char **));
271
272 int
273 main (argc, argv)
274      int argc;
275      char **argv;
276 {
277   int argno;
278   
279   gcc_init_libintl ();
280
281   argno = process_args (argc, argv);
282   if (optind == argc)
283     print_usage (true);
284
285   for (; argno != argc; argno++)
286     {
287       release_structures ();
288       
289       process_file (argv[argno]);
290     }
291   
292   return 0;
293 }
294
295 static void
296 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
297 {
298   VA_OPEN (ap, msgid);
299   VA_FIXEDARG (ap, FILE *, file);
300   VA_FIXEDARG (ap, const char *, msgid);
301
302   vfprintf (file, _(msgid), ap);
303   VA_CLOSE (ap);
304 }
305
306 /* More 'friendly' abort that prints the line and file.
307    config.h can #define abort fancy_abort if you like that sort of thing.  */
308 extern void fancy_abort PARAMS ((void)) ATTRIBUTE_NORETURN;
309
310 void
311 fancy_abort ()
312 {
313   fnotice (stderr, "Internal gcov abort.\n");
314   exit (FATAL_EXIT_CODE);
315 }
316 \f
317 /* Print a usage message and exit.  If ERROR_P is nonzero, this is an error,
318    otherwise the output of --help.  */
319
320 static void
321 print_usage (error_p)
322      int error_p;
323 {
324   FILE *file = error_p ? stderr : stdout;
325   int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
326   
327   fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n");
328   fnotice (file, "Print code coverage information.\n\n");
329   fnotice (file, "  -h, --help                      Print this help, then exit\n");
330   fnotice (file, "  -v, --version                   Print version number, then exit\n");
331   fnotice (file, "  -b, --branch-probabilities      Include branch probabilities in output\n");
332   fnotice (file, "  -c, --branch-counts             Given counts of branches taken\n\
333                                     rather than percentages\n");
334   fnotice (file, "  -n, --no-output                 Do not create an output file\n");
335   fnotice (file, "  -l, --long-file-names           Use long output file names for included\n\
336                                     source files\n");
337   fnotice (file, "  -f, --function-summaries        Output summaries for each function\n");
338   fnotice (file, "  -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
339   fnotice (file, "  -p, --preserve-paths            Preserve all pathname components\n");
340   fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
341            bug_report_url);
342   exit (status);
343 }
344
345 /* Print version information and exit.  */
346
347 static void
348 print_version ()
349 {
350   char v[4];
351   unsigned version = GCOV_VERSION;
352   unsigned ix;
353
354   for (ix = 4; ix--; version >>= 8)
355     v[ix] = version;
356   fnotice (stdout, "gcov %.4s (GCC %s)\n", v, version_string);
357   fnotice (stdout, "Copyright (C) 2002 Free Software Foundation, Inc.\n");
358   fnotice (stdout,
359            "This is free software; see the source for copying conditions.  There is NO\n\
360 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
361   exit (SUCCESS_EXIT_CODE);
362 }
363
364 static const struct option options[] =
365 {
366   { "help",                 no_argument,       NULL, 'h' },
367   { "version",              no_argument,       NULL, 'v' },
368   { "branch-probabilities", no_argument,       NULL, 'b' },
369   { "branch-counts",        no_argument,       NULL, 'c' },
370   { "no-output",            no_argument,       NULL, 'n' },
371   { "long-file-names",      no_argument,       NULL, 'l' },
372   { "function-summaries",   no_argument,       NULL, 'f' },
373   { "preserve-paths",       no_argument,       NULL, 'p' },
374   { "object-directory",     required_argument, NULL, 'o' },
375   { "object-file",          required_argument, NULL, 'o' },
376 };
377
378 /* Process args, return index to first non-arg.  */
379
380 static int
381 process_args (argc, argv)
382      int argc;
383      char **argv;
384 {
385   int opt;
386
387   while ((opt = getopt_long (argc, argv, "hvbclnfo:p", options, NULL)) != -1)
388     {
389       switch (opt)
390         {
391         case 'h':
392           print_usage (false);
393           /* print_usage will exit.  */
394         case 'v':
395           print_version ();
396           /* print_version will exit.  */
397         case 'b':
398           flag_branches = 1;
399           break;
400         case 'c':
401           flag_counts = 1;
402           break;
403         case 'n':
404           flag_gcov_file = 0;
405           break;
406         case 'l':
407           flag_long_names = 1;
408           break;
409         case 'f':
410           flag_function_summary = 1;
411           break;
412         case 'o':
413           object_directory = optarg;
414           break;
415         case 'p':
416           flag_preserve_paths = 1;
417           break;
418         default:
419           print_usage (true);
420           /* print_usage will exit.  */
421         }
422     }
423
424   return optind;
425 }
426
427 /* Process a single source file.  */
428
429 static void
430 process_file (file_name)
431      const char *file_name;
432 {
433   source_t *src;
434   function_t *fn;
435   
436   create_file_names (file_name);
437   if (read_graph_file ())
438     return;
439   
440   if (!functions)
441     {
442       fnotice (stderr, "%s:no functions found\n", bbg_file_name);
443       return;
444     }
445   
446   if (read_count_file ())
447     return;
448   
449   for (fn = functions; fn; fn = fn->next)
450     solve_flow_graph (fn);
451   for (src = sources; src; src = src->next)
452     src->lines = (line_t *) xcalloc (src->num_lines, sizeof (line_t));
453   for (fn = functions; fn; fn = fn->next)
454     {
455       coverage_t coverage;
456       
457       memset (&coverage, 0, sizeof (coverage));
458       coverage.name = fn->name;
459       add_line_counts (flag_function_summary ? &coverage : NULL, fn);
460       if (flag_function_summary)
461         {
462           function_summary (&coverage, "Function");
463           fnotice (stdout, "\n");
464         }
465     }
466   
467   for (src = sources; src; src = src->next)
468     {
469       accumulate_line_counts (src);
470       function_summary (&src->coverage, "File");
471       if (flag_gcov_file)
472         {
473           char *gcov_file_name = make_gcov_file_name (file_name, src->name);
474           FILE *gcov_file = fopen (gcov_file_name, "w");
475           
476           if (gcov_file)
477             {
478               fnotice (stdout, "%s:creating `%s'\n",
479                        src->name, gcov_file_name);
480               output_lines (gcov_file, src);
481               if (ferror (gcov_file))
482                     fnotice (stderr, "%s:error writing output file `%s'\n",
483                              src->name, gcov_file_name);
484               fclose (gcov_file);
485             }
486           else
487             fnotice (stderr, "%s:could not open output file `%s'\n",
488                      src->name, gcov_file_name);
489           free (gcov_file_name);
490         }
491       fnotice (stdout, "\n");
492     }
493 }
494
495 /* Release all memory used.  */
496
497 static void
498 release_structures ()
499 {
500   function_t *fn;
501   source_t *src;
502   
503   free (bbg_file_name);
504   free (da_file_name);
505   da_file_name = bbg_file_name = NULL;
506   bbg_file_time = 0;
507   
508   while ((src = sources))
509     {
510       sources = src->next;
511
512       free (src->name);
513       free (src->lines);
514     }
515   
516   while ((fn = functions))
517     {
518       unsigned ix;
519       block_t *block;
520       
521       functions = fn->next;
522       for (ix = fn->num_blocks, block = fn->blocks; ix--; block++)
523         {
524           arc_t *arc, *arc_n;
525
526           for (arc = block->succ; arc; arc = arc_n)
527             {
528               arc_n = arc->succ_next;
529               free (arc);
530             }
531           free (block->encoding);
532         }
533       free (fn->blocks);
534       free (fn->counts);
535     }
536 }
537
538 /* Generate the names of the graph and data files. If OBJECT_DIRECTORY
539    is not specified, these are looked for in the current directory,
540    and named from the basename of the FILE_NAME sans extension. If
541    OBJECT_DIRECTORY is specified and is a directory, the files are in
542    that directory, but named from the basename of the FILE_NAME, sans
543    extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
544    the object *file*, and the data files are named from that.  */
545
546 static void
547 create_file_names (file_name)
548      const char *file_name;
549 {
550   char *cptr;
551   char *name;
552   int length = strlen (file_name);
553   int base;
554   
555   if (object_directory && object_directory[0])
556     {
557       struct stat status;
558
559       length += strlen (object_directory) + 2;
560       name = xmalloc (length);
561       name[0] = 0;
562       
563       base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
564       strcat (name, object_directory);
565       if (base && name[strlen (name) - 1] != '/')
566         strcat (name, "/");
567     }
568   else
569     {
570       name = xmalloc (length + 1);
571       name[0] = 0;
572       base = 1;
573     }
574   
575   if (base)
576     {
577       /* Append source file name */
578       cptr = strrchr (file_name, '/');
579       strcat (name, cptr ? cptr + 1 : file_name);
580     }
581   
582   /* Remove the extension.  */
583   cptr = strrchr (name, '.');
584   if (cptr)
585     *cptr = 0;
586   
587   length = strlen (name);
588   
589   bbg_file_name = xmalloc (length + strlen (GCOV_GRAPH_SUFFIX) + 1);
590   strcpy (bbg_file_name, name);
591   strcpy (bbg_file_name + length, GCOV_GRAPH_SUFFIX);
592
593   da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
594   strcpy (da_file_name, name);
595   strcpy (da_file_name + length, GCOV_DATA_SUFFIX);
596   
597   return;
598 }
599
600 /* Read the graph file. Return nonzero on fatal error.  */
601
602 static int
603 read_graph_file ()
604 {
605   FILE *file;
606   struct stat status;
607   unsigned magic, version;
608   unsigned current_tag = 0;
609   unsigned tag;
610   struct function_info *fn = NULL;
611   source_t *src = NULL;
612   unsigned ix;
613
614   file = fopen (bbg_file_name, "rb");
615   if (!file)
616     {
617       fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
618       return 1;
619     }
620   if (!fstat (fileno (file), &status))
621     bbg_file_time = status.st_mtime;
622   if (gcov_read_unsigned (file, &magic) || magic != GCOV_GRAPH_MAGIC)
623     {
624       fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
625       fclose (file);
626       return 1;
627     }
628
629   if (gcov_read_unsigned (file, &version) || version != GCOV_VERSION)
630     {
631       char v[4], e[4];
632
633       magic = GCOV_VERSION;
634       
635       for (ix = 4; ix--; magic >>= 8, version >>= 8)
636         {
637           v[ix] = version;
638           e[ix] = magic;
639         }
640       fnotice (stderr, "%s:version `%.4s', prefer `%.4s'\n",
641                bbg_file_name, v, e);
642     }
643   
644   while (!gcov_read_unsigned (file, &tag))
645     {
646       unsigned length;
647       long base;
648
649       if (gcov_read_unsigned (file, &length))
650         goto corrupt;
651
652       base = gcov_save_position (file);
653       
654       if (tag == GCOV_TAG_FUNCTION)
655         {
656           char *function_name = NULL;
657           unsigned checksum;
658
659           if (gcov_read_string (file, &function_name, NULL)
660               || gcov_read_unsigned (file, &checksum))
661             goto corrupt;
662           fn = (function_t *)xcalloc (1, sizeof (function_t));
663           fn->name = function_name;
664           fn->checksum = checksum;
665
666           fn->next = functions;
667           functions = fn;
668           current_tag = tag;
669         }
670       else if (fn && tag == GCOV_TAG_BLOCKS)
671         {
672           if (fn->blocks)
673             fnotice (stderr, "%s:already seen blocks for `%s'\n",
674                      bbg_file_name, fn->name);
675           else
676             {
677               fn->num_blocks = length / 4;
678               fn->blocks
679                 = (block_t *)xcalloc (fn->num_blocks, sizeof (block_t));
680             }
681         }
682       else if (fn && tag == GCOV_TAG_ARCS)
683         {
684           unsigned src;
685           unsigned num_dests = (length - 4) / 8;
686           unsigned dest, flags;
687
688           if (gcov_read_unsigned (file, &src)
689               || src >= fn->num_blocks
690               || fn->blocks[src].succ)
691             goto corrupt;
692           
693           while (num_dests--)
694             {
695               struct arc_info *arc;
696               
697               if (gcov_read_unsigned (file, &dest)
698                   || gcov_read_unsigned (file, &flags)
699                   || dest >= fn->num_blocks)
700                 goto corrupt;
701               arc = (arc_t *) xcalloc (1, sizeof (arc_t));
702               
703               arc->dst = &fn->blocks[dest];
704               arc->src = &fn->blocks[src];
705               
706               arc->count = 0;
707               arc->count_valid = 0;
708               arc->on_tree = !!(flags & GCOV_ARC_ON_TREE);
709               arc->fake = !!(flags & GCOV_ARC_FAKE);
710               arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH);
711               
712               arc->succ_next = fn->blocks[src].succ;
713               fn->blocks[src].succ = arc;
714               fn->blocks[src].num_succ++;
715               
716               arc->pred_next = fn->blocks[dest].pred;
717               fn->blocks[dest].pred = arc;
718               fn->blocks[dest].num_pred++;
719
720               arc->is_call = arc->fake;
721               
722               if (!arc->on_tree)
723                 fn->num_counts++;
724             }
725         }
726       else if (fn && tag == GCOV_TAG_LINES)
727         {
728           unsigned blockno;
729           unsigned *line_nos
730             = (unsigned *)xcalloc ((length - 4) / 4, sizeof (unsigned));
731
732           if (gcov_read_unsigned (file, &blockno)
733               || blockno >= fn->num_blocks
734               || fn->blocks[blockno].encoding)
735             goto corrupt;
736           
737           for (ix = 0; ;  )
738             {
739               unsigned lineno;
740               
741               if (gcov_read_unsigned (file, &lineno))
742                 goto corrupt;
743               if (lineno)
744                 {
745                   if (!ix)
746                     {
747                       line_nos[ix++] = 0;
748                       line_nos[ix++] = src->index;
749                     }
750                   line_nos[ix++] = lineno;
751                   if (lineno >= src->num_lines)
752                     src->num_lines = lineno + 1;
753                 }
754               else
755                 {
756                   char *file_name = NULL;
757                   
758                   if (gcov_read_string (file, &file_name, NULL))
759                     goto corrupt;
760                   if (!file_name)
761                     break;
762                   for (src = sources; src; src = src->next)
763                     if (!strcmp (file_name, src->name))
764                       {
765                         free (file_name);
766                         break;
767                       }
768                   if (!src)
769                     {
770                       src = (source_t *)xcalloc (1, sizeof (source_t));
771                       src->name = file_name;
772                       src->coverage.name = file_name;
773                       src->index = sources ? sources->index + 1 : 1;
774                       src->next = sources;
775                       sources = src;
776                     }
777                   line_nos[ix++] = 0;
778                   line_nos[ix++] = src->index;
779                 }
780             }
781           
782           fn->blocks[blockno].encoding = line_nos;
783           fn->blocks[blockno].num_encodings = ix;
784         }
785       else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag))
786         {
787           fn = NULL;
788           current_tag = 0;
789         }
790       if (gcov_resync (file, base, length))
791         {
792         corrupt:;
793           fnotice (stderr, "%s:corrupted\n", bbg_file_name);
794           fclose (file);
795           return 1;
796         }
797     }
798   fclose (file);
799   
800   /* We built everything backwards, so nreverse them all */
801   
802   /* Reverse sources. Not strictly necessary, but we'll then process
803      them in the 'expected' order.  */
804   {
805     source_t *src, *src_p, *src_n;
806
807     for (src_p = NULL, src = sources; src; src_p = src, src = src_n)
808       {
809         src_n = src->next;
810         src->next = src_p;
811       }
812     sources =  src_p;
813   }
814
815   /* Reverse functions.  */
816   {
817     function_t *fn, *fn_p, *fn_n;
818
819     for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n)
820       {
821         unsigned ix;
822         
823         fn_n = fn->next;
824         fn->next = fn_p;
825
826         /* Reverse the arcs */
827         for (ix = fn->num_blocks; ix--;)
828           {
829             arc_t *arc, *arc_p, *arc_n;
830             
831             for (arc_p = NULL, arc = fn->blocks[ix].succ; arc;
832                  arc_p = arc, arc = arc_n)
833               {
834                 arc_n = arc->succ_next;
835                 arc->succ_next = arc_p;
836               }
837             fn->blocks[ix].succ = arc_p;
838
839             for (arc_p = NULL, arc = fn->blocks[ix].pred; arc;
840                  arc_p = arc, arc = arc_n)
841               {
842                 arc_n = arc->pred_next;
843                 arc->pred_next = arc_p;
844               }
845             fn->blocks[ix].pred = arc_p;
846           }
847       }
848     functions = fn_p;
849   }
850   return 0;
851 }
852
853 /* Reads profiles from the count file and attach to each
854    function. Return nonzero if fatal error.  */
855
856 static int
857 read_count_file ()
858 {
859   FILE *file;
860   unsigned ix;
861   char *function_name_buffer = NULL;
862   unsigned magic, version;
863   function_t *fn = NULL;
864
865   file = fopen (da_file_name, "rb");
866   if (!file)
867     {
868       fnotice (stderr, "%s:cannot open data file\n", da_file_name);
869       return 1;
870     }
871   if (gcov_read_unsigned (file, &magic) || magic != GCOV_DATA_MAGIC)
872     {
873       fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
874     cleanup:;
875       free (function_name_buffer);
876       fclose (file);
877       return 1;
878     }
879   if (gcov_read_unsigned (file, &version) || version != GCOV_VERSION)
880     {
881       char v[4], e[4];
882       
883       magic = GCOV_VERSION;
884       for (ix = 4; ix--; magic >>= 8, version >>= 8)
885         {
886           v[ix] = version;
887           e[ix] = magic;
888         }
889       fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
890                da_file_name, v, e);
891     }
892   
893   while (1)
894     {
895       unsigned tag, length;
896       long base;
897       
898       if (gcov_read_unsigned (file, &tag)
899           || gcov_read_unsigned (file, &length))
900         {
901           if (feof (file))
902             break;
903           
904         corrupt:;
905           fnotice (stderr, "%s:corrupted\n", da_file_name);
906           goto cleanup;
907         }
908       base = gcov_save_position (file);
909       if (tag == GCOV_TAG_FUNCTION)
910         {
911           unsigned checksum;
912           struct function_info *fn_n = functions;
913           
914           if (gcov_read_string (file, &function_name_buffer, NULL)
915               || gcov_read_unsigned (file, &checksum))
916             goto corrupt;
917
918           for (fn = fn ? fn->next : NULL; ; fn = fn->next)
919             {
920               if (fn)
921                 ;
922               else if ((fn = fn_n))
923                 fn_n = NULL;
924               else
925                 {
926                   fnotice (stderr, "%s:unknown function `%s'\n",
927                            da_file_name, function_name_buffer);
928                   break;
929                 }
930               if (!strcmp (fn->name, function_name_buffer))
931                 break;
932             }
933
934           if (!fn)
935             ;
936           else if (checksum != fn->checksum)
937             {
938             mismatch:;
939               fnotice (stderr, "%s:profile mismatch for `%s'\n",
940                        da_file_name, function_name_buffer);
941               goto cleanup;
942             }
943         }
944       else if (tag == GCOV_TAG_ARC_COUNTS && fn)
945         {
946           if (length != 8 * fn->num_counts)
947             goto mismatch;
948           
949           if (!fn->counts)
950             fn->counts
951               = (gcov_type *)xcalloc (fn->num_counts, sizeof (gcov_type));
952           
953           for (ix = 0; ix != fn->num_counts; ix++)
954             {
955               gcov_type count;
956               
957               if (gcov_read_counter (file, &count))
958                 goto corrupt;
959               fn->counts[ix] += count;
960             }
961         }
962       gcov_resync (file, base, length);
963     }
964
965   fclose (file);
966   free (function_name_buffer);
967   return 0;
968 }
969
970 /* Solve the flow graph. Propagate counts from the instrumented arcs
971    to the blocks and the uninstrumented arcs.  */
972
973 static void
974 solve_flow_graph (fn)
975      function_t *fn;
976 {
977   unsigned ix;
978   arc_t *arc;
979   gcov_type *count_ptr = fn->counts;
980   block_t *valid_blocks = NULL;    /* valid, but unpropagated blocks.  */
981   block_t *invalid_blocks = NULL;  /* invalid, but inferable blocks.  */
982   
983   if (fn->num_blocks < 2)
984     fnotice (stderr, "%s:`%s' lacks entry and/or exit blocks\n",
985              bbg_file_name, fn->name);
986   else
987     {
988       if (fn->blocks[0].num_pred)
989         fnotice (stderr, "%s:`%s' has arcs to entry block\n",
990                  bbg_file_name, fn->name);
991       else
992         /* We can't deduce the entry block counts from the lack of
993            predecessors.  */
994         fn->blocks[0].num_pred = ~(unsigned)0;
995       
996       if (fn->blocks[fn->num_blocks - 1].num_succ)
997         fnotice (stderr, "%s:`%s' has arcs from exit block\n",
998                  bbg_file_name, fn->name);
999       else
1000         /* Likewise, we can't deduce exit block counts from the lack
1001            of its successors.  */
1002         fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
1003     }
1004
1005   /* Propagate the measured counts, this must be done in the same
1006      order as the code in profile.c  */
1007   for (ix = 0; ix != fn->num_blocks; ix++)
1008     {
1009       block_t const *prev_dst = NULL;
1010       int out_of_order = 0;
1011       
1012       for (arc = fn->blocks[ix].succ; arc; arc = arc->succ_next)
1013         {
1014           if (!arc->on_tree)
1015             {
1016               if (count_ptr)
1017                 arc->count = *count_ptr++;
1018               arc->count_valid = 1;
1019               fn->blocks[ix].num_succ--;
1020               arc->dst->num_pred--;
1021             }
1022           if (prev_dst && prev_dst > arc->dst)
1023             out_of_order = 1;
1024           prev_dst = arc->dst;
1025         }
1026       
1027       /* Sort the successor arcs into ascending dst order. profile.c
1028          normally produces arcs in the right order, but sometimes with
1029          one or two out of order.  We're not using a particularly
1030          smart sort.  */
1031       if (out_of_order)
1032         {
1033           arc_t *start = fn->blocks[ix].succ;
1034           unsigned changes = 1;
1035           
1036           while (changes)
1037             {
1038               arc_t *arc, *arc_p, *arc_n;
1039               
1040               changes = 0;
1041               for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);)
1042                 {
1043                   if (arc->dst > arc_n->dst)
1044                     {
1045                       changes = 1;
1046                       if (arc_p)
1047                         arc_p->succ_next = arc_n;
1048                       else
1049                         start = arc_n;
1050                       arc->succ_next = arc_n->succ_next;
1051                       arc_n->succ_next = arc;
1052                       arc_p = arc_n;
1053                     }
1054                   else
1055                     {
1056                       arc_p = arc;
1057                       arc = arc_n;
1058                     }
1059                 }
1060             }
1061           fn->blocks[ix].succ = start;
1062         }
1063       
1064       /* Place it on the invalid chain, it will be ignored if that's
1065          wrong.  */
1066       fn->blocks[ix].invalid_chain = 1;
1067       fn->blocks[ix].chain = invalid_blocks;
1068       invalid_blocks = &fn->blocks[ix];
1069     }
1070
1071   while (invalid_blocks || valid_blocks)
1072     {
1073       block_t *blk;
1074       
1075       while ((blk = invalid_blocks))
1076         {
1077           gcov_type total = 0;
1078           const arc_t *arc;
1079           
1080           invalid_blocks = blk->chain;
1081           blk->invalid_chain = 0;
1082           if (!blk->num_succ)
1083             for (arc = blk->succ; arc; arc = arc->succ_next)
1084               total += arc->count;
1085           else if (!blk->num_pred)
1086             for (arc = blk->pred; arc; arc = arc->pred_next)
1087               total += arc->count;
1088           else
1089             continue;
1090           
1091           blk->count = total;
1092           blk->count_valid = 1;
1093           blk->chain = valid_blocks;
1094           blk->valid_chain = 1;
1095           valid_blocks = blk;
1096         }
1097       while ((blk = valid_blocks))
1098         {
1099           gcov_type total;
1100           arc_t *arc, *inv_arc;
1101
1102           valid_blocks = blk->chain;
1103           blk->valid_chain = 0;
1104           if (blk->num_succ == 1)
1105             {
1106               block_t *dst;
1107               
1108               total = blk->count;
1109               inv_arc = NULL;
1110               for (arc = blk->succ; arc; arc = arc->succ_next)
1111                 {
1112                   total -= arc->count;
1113                   if (!arc->count_valid)
1114                     inv_arc = arc;
1115                 }
1116               dst = inv_arc->dst;
1117               inv_arc->count_valid = 1;
1118               inv_arc->count = total;
1119               blk->num_succ--;
1120               dst->num_pred--;
1121               if (dst->count_valid)
1122                 {
1123                   if (dst->num_pred == 1 && !dst->valid_chain)
1124                     {
1125                       dst->chain = valid_blocks;
1126                       dst->valid_chain = 1;
1127                       valid_blocks = dst;
1128                     }
1129                 }
1130               else
1131                 {
1132                   if (!dst->num_pred && !dst->invalid_chain)
1133                     {
1134                       dst->chain = invalid_blocks;
1135                       dst->invalid_chain = 1;
1136                       invalid_blocks = dst;
1137                     }
1138                 }
1139             }
1140           if (blk->num_pred == 1)
1141             {
1142               block_t *src;
1143               
1144               total = blk->count;
1145               inv_arc = NULL;
1146               for (arc = blk->pred; arc; arc = arc->pred_next)
1147                 {
1148                   total -= arc->count;
1149                   if (!arc->count_valid)
1150                     inv_arc = arc;
1151                 }
1152               src = inv_arc->src;
1153               inv_arc->count_valid = 1;
1154               inv_arc->count = total;
1155               blk->num_pred--;
1156               src->num_succ--;
1157               if (src->count_valid)
1158                 {
1159                   if (src->num_succ == 1 && !src->valid_chain)
1160                     {
1161                       src->chain = valid_blocks;
1162                       src->valid_chain = 1;
1163                       valid_blocks = src;
1164                     }
1165                 }
1166               else
1167                 {
1168                   if (!src->num_succ && !src->invalid_chain)
1169                     {
1170                       src->chain = invalid_blocks;
1171                       src->invalid_chain = 1;
1172                       invalid_blocks = src;
1173                     }
1174                 }
1175             }
1176         }
1177     }
1178   
1179   /* If the graph has been correctly solved, every block will have a
1180      valid count.  */
1181   for (ix = 0; ix < fn->num_blocks; ix++)
1182     if (!fn->blocks[ix].count_valid)
1183       {
1184         fnotice (stderr, "%s:graph is unsolvable for `%s'\n",
1185                  bbg_file_name, fn->name);
1186         break;
1187       }
1188 }
1189
1190 \f
1191
1192 /* Increment totals in COVERAGE according to arc ARC.  */
1193
1194 static void
1195 add_branch_counts (coverage, arc)
1196      coverage_t *coverage;
1197      const arc_t *arc;
1198 {
1199   if (arc->is_call)
1200     {
1201       coverage->calls++;
1202       if (arc->src->count)
1203         coverage->calls_executed++;
1204     }
1205   else
1206     {
1207       coverage->branches++;
1208       if (arc->src->count)
1209         coverage->branches_executed++;
1210       if (arc->count)
1211         coverage->branches_taken++;
1212     }
1213 }
1214
1215 /* Format a HOST_WIDE_INT as either a percent ratio, or absolute
1216    count.  If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
1217    If DP is zero, no decimal point is printed. Only print 100% when
1218    TOP==BOTTOM and only print 0% when TOP=0.  If dp < 0, then simply
1219    format TOP.  Return pointer to a static string.  */
1220
1221 static char const *
1222 format_gcov (top, bottom, dp)
1223      gcov_type top, bottom;
1224      int dp;
1225 {
1226   static char buffer[20];
1227   
1228   if (dp >= 0)
1229     {
1230       float ratio = bottom ? (float)top / bottom : 0;
1231       int ix;
1232       unsigned limit = 100;
1233       unsigned percent;
1234   
1235       for (ix = dp; ix--; )
1236         limit *= 10;
1237       
1238       percent = (unsigned) (ratio * limit + (float)0.5);
1239       if (percent <= 0 && top)
1240         percent = 1;
1241       else if (percent >= limit && top != bottom)
1242         percent = limit - 1;
1243       ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
1244       if (dp)
1245         {
1246           dp++;
1247           do
1248             {
1249               buffer[ix+1] = buffer[ix];
1250               ix--;
1251             }
1252           while (dp--);
1253           buffer[ix + 1] = '.';
1254         }
1255     }
1256   else
1257     sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)top);
1258   
1259   return buffer;
1260 }
1261
1262
1263 /* Output summary info for a function.  */
1264
1265 static void
1266 function_summary (coverage, title)
1267      const coverage_t *coverage;
1268      const char *title;
1269 {
1270   fnotice (stdout, "%s `%s'\n", title, coverage->name);
1271
1272   if (coverage->lines)
1273     fnotice (stdout, "Lines executed:%s of %d\n",
1274              format_gcov (coverage->lines_executed, coverage->lines, 2),
1275              coverage->lines);
1276   else
1277     fnotice (stdout, "No executable lines");
1278
1279   if (flag_branches)
1280     {
1281       if (coverage->branches)
1282         {
1283           fnotice (stdout, "Branches executed:%s of %d\n",
1284                    format_gcov (coverage->branches_executed,
1285                                 coverage->branches, 2),
1286                    coverage->branches);
1287           fnotice (stdout, "Taken at least once:%s of %d\n",
1288                    format_gcov (coverage->branches_taken,
1289                                 coverage->branches, 2),
1290                    coverage->branches);
1291         }
1292       else
1293         fnotice (stdout, "No branches\n");
1294       if (coverage->calls)
1295         fnotice (stdout, "Calls executed:%s of %d\n",
1296                  format_gcov (coverage->calls_executed, coverage->calls, 2),
1297                  coverage->calls);
1298       else
1299         fnotice (stdout, "No calls\n");
1300     }
1301 }
1302
1303 /* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
1304    affect name generation. With preserve_paths we create a filename
1305    from all path components of the source file, replacing '/' with
1306    '#', without it we simply take the basename component. With
1307    long_output_names we prepend the processed name of the input file
1308    to each output name (except when the current source file is the
1309    input file, so you don't get a double concatenation). The two
1310    components are separated by '##'. Also '.' filename components are
1311    removed and '..'  components are renamed to '^'.  */
1312
1313 static char *
1314 make_gcov_file_name (input_name, src_name)
1315      const char *input_name;
1316      const char *src_name;
1317 {
1318   char *cptr;
1319   char *name = xmalloc (strlen (src_name) + strlen (input_name) + 10);
1320   
1321   name[0] = 0;
1322   if (flag_long_names && strcmp (src_name, input_name))
1323     {
1324       /* Generate the input filename part.  */
1325       cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/');
1326       strcat (name, cptr ? cptr + 1 : input_name);
1327       strcat (name, "##");
1328     }
1329    
1330   /* Generate the source filename part.  */
1331   cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/');
1332   strcat (name, cptr ? cptr + 1 : src_name);
1333   
1334   if (flag_preserve_paths)
1335     {
1336       /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
1337       char *prev;
1338       
1339       for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
1340         {
1341           unsigned shift = 0;
1342           
1343           if (prev + 1 == cptr && prev[0] == '.')
1344             {
1345               /* Remove '.' */
1346               shift = 2;
1347             }
1348           else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
1349             {
1350               /* Convert '..' */
1351               shift = 1;
1352               prev[1] = '^';
1353             }
1354           else
1355             *cptr++ = '#';
1356           if (shift)
1357             {
1358               cptr = prev;
1359               do
1360                 prev[0] = prev[shift];
1361               while (*prev++);
1362             }
1363         }
1364     }
1365   
1366   strcat (name, ".gcov");
1367   return name;
1368 }
1369
1370 /* Scan through the bb_data for each line in the block, increment
1371    the line number execution count indicated by the execution count of
1372    the appropriate basic block.  */
1373
1374 static void
1375 add_line_counts (coverage, fn)
1376      coverage_t *coverage;
1377      const function_t *fn;
1378 {
1379   unsigned ix;
1380   line_t *line = NULL; /* this is propagated from one iteration to the
1381                           next.  */
1382
1383   /* Scan each basic block.  */
1384   for (ix = 0; ix != fn->num_blocks; ix++)
1385     {
1386       const block_t *block = &fn->blocks[ix];
1387       unsigned *encoding;
1388       const source_t *src = NULL;
1389       unsigned jx;
1390
1391       for (jx = 0, encoding = block->encoding;
1392            jx != block->num_encodings; jx++, encoding++)
1393         if (!*encoding)
1394           {
1395             unsigned src_n = *++encoding;
1396
1397             for (src = sources; src->index != src_n; src = src->next)
1398               continue;
1399             jx++;
1400           }
1401         else
1402           {
1403             line = &src->lines[*encoding];
1404
1405             if (coverage)
1406               {
1407                 if (!line->exists)
1408                   coverage->lines++;
1409                 if  (!line->count && block->count)
1410                   coverage->lines_executed++;
1411               }
1412             line->exists = 1;
1413             line->count += block->count;
1414           }
1415       
1416       if (line && flag_branches)
1417         {
1418           arc_t *arc;
1419           
1420           for (arc = block->succ; arc; arc = arc->succ_next)
1421             {
1422               /* Ignore fall through arcs as they aren't really branches.  */
1423               if (arc->fall_through)
1424                 continue;
1425               
1426               arc->line_next = line->branches;
1427               line->branches = arc;
1428               if (coverage)
1429                 add_branch_counts (coverage, arc);
1430             }
1431         }
1432     }
1433   if (!line)
1434     fnotice (stderr, "%s:no lines for `%s'\n", bbg_file_name, fn->name);
1435 }
1436
1437 /* Accumulate the line counts of a file.  */
1438
1439 static void
1440 accumulate_line_counts (src)
1441      source_t *src;
1442 {
1443   line_t *line;
1444   unsigned ix;
1445   
1446   for (ix = src->num_lines, line = src->lines; ix--; line++)
1447     {
1448       arc_t *arc, *arc_p, *arc_n;
1449       
1450       /* Total and reverse the branch information.  */
1451       for (arc = line->branches, arc_p = NULL; arc; arc_p = arc, arc = arc_n)
1452         {
1453           arc_n = arc->line_next;
1454           arc->line_next = arc_p;
1455
1456           add_branch_counts (&src->coverage, arc);
1457         }
1458       line->branches = arc_p;
1459
1460       if (line->exists)
1461         {
1462           src->coverage.lines++;
1463           if (line->count)
1464             src->coverage.lines_executed++;
1465         }
1466     }
1467 }
1468
1469 /* Read in the source file one line at a time, and output that line to
1470    the gcov file preceded by its execution count and other
1471    information.  */
1472
1473 static void
1474 output_lines (gcov_file, src)
1475      FILE *gcov_file;
1476      const source_t *src;
1477 {
1478   FILE *source_file;
1479   unsigned line_num;            /* current line number.  */
1480   const line_t *line;           /* current line info ptr.  */
1481   char string[STRING_SIZE];     /* line buffer.  */
1482   char const *retval = "";      /* status of source file reading.  */
1483
1484   fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
1485   fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
1486   fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
1487   
1488   source_file = fopen (src->name, "r");
1489   if (!source_file)
1490     {
1491       fnotice (stderr, "%s:cannot open source file\n", src->name);
1492       retval = NULL;
1493     }
1494   else
1495     {
1496       struct stat status;
1497       
1498       if (!fstat (fileno (source_file), &status)
1499           && status.st_mtime > bbg_file_time)
1500         {
1501           fnotice (stderr, "%s:source file is newer than graph file `%s'\n",
1502                    src->name, bbg_file_name);
1503           fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n",
1504                    "-", 0);
1505         }
1506     }
1507
1508   for (line_num = 1, line = &src->lines[line_num];
1509        line_num < src->num_lines; line_num++, line++)
1510     {
1511       /* For lines which don't exist in the .bb file, print '-' before
1512          the source line.  For lines which exist but were never
1513          executed, print '#####' before the source line.  Otherwise,
1514          print the execution count before the source line.  There are
1515          16 spaces of indentation added before the source line so that
1516          tabs won't be messed up.  */
1517       fprintf (gcov_file, "%9s:%5u:",
1518                !line->exists ? "-" : !line->count ? "#####"
1519                : format_gcov (line->count, 0, -1), line_num);
1520       
1521       if (retval)
1522         {
1523           /* Copy source line.  */
1524           do
1525             {
1526               retval = fgets (string, STRING_SIZE, source_file);
1527               if (!retval)
1528                 {
1529                   fnotice (stderr, "%s:unexpected EOF\n", src->name);
1530                   break;
1531                 }
1532               fputs (retval, gcov_file);
1533             }
1534           while (!retval[0] || retval[strlen (retval) - 1] != '\n');
1535         }
1536       if (!retval)
1537         fputs ("??\n", gcov_file);
1538       
1539       if (flag_branches)
1540         {
1541           int ix;
1542           arc_t *arc;
1543           
1544           for (ix = 0, arc = line->branches; arc; arc = arc->line_next, ix++)
1545             {
1546               if (arc->is_call)
1547                 {
1548                   if (arc->src->count)
1549                     fnotice
1550                       (gcov_file, "call   %2d returns %s\n", ix,
1551                        format_gcov (arc->src->count - arc->count,
1552                                     arc->src->count,
1553                                     -flag_counts));
1554                   else
1555                     fnotice (gcov_file, "call   %2d never executed\n", ix);
1556                 }
1557               else
1558                 {
1559                   if (arc->src->count)
1560                     fnotice
1561                       (gcov_file, "branch %2d taken %s\n", ix,
1562                        format_gcov (arc->count, arc->src->count,
1563                                     -flag_counts));
1564                   else
1565                     fnotice (gcov_file, "branch %2d never executed\n", ix);
1566                 }
1567             }
1568         }
1569     }
1570   
1571   /* Handle all remaining source lines.  There may be lines after the
1572      last line of code.  */
1573   if (retval)
1574     {
1575       for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
1576         {
1577           fprintf (gcov_file, "%9s:%5u:%s", "-", line_num, retval);
1578           
1579           while (!retval[0] || retval[strlen (retval) - 1] != '\n')
1580             {
1581               retval = fgets (string, STRING_SIZE, source_file);
1582               if (!retval)
1583                 break;
1584               fputs (retval, gcov_file);
1585             }
1586         }
1587     }
1588   
1589   if (source_file)
1590     fclose (source_file);
1591 }