OSDN Git Service

14dc5842ad10f56aeae37c1ced8cb912d392222e
[pf3gnuchains/gcc-fork.git] / gcc / gcov-io.h
1 /* File format for coverage information
2    Copyright (C) 1996, 1997, 1998, 2000, 2002 Free Software Foundation, Inc.
3    Contributed by Bob Manson <manson@cygnus.com>.
4    Completely remangled by Nathan Sidwell <nathan@codesourcery.com>.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.  */
22
23 /* Coverage information is held in two files.  A basic block graph
24    file, which is generated by the compiler, and a counter file, which
25    is generated by the program under test.  Both files use a similar
26    structure.  We do not attempt to make these files backwards
27    compatible with previous versions, as you only need coverage
28    information when developing a program.  We do hold version
29    information, so that mismatches can be detected, and we use a
30    format that allows tools to skip information they do not understand
31    or are not interested in.
32
33    Numbers are recorded in big endian unsigned binary form.  Either in
34    32 or 64 bits.  Strings are stored with a length count and NUL
35    terminator, and 0 to 3 bytes of zero padding up to the next 4 byte
36    boundary.  Zero length and NULL strings are simply stored as a
37    length of zero (they have no trailing NUL or padding).
38
39         int32:  byte3 byte2 byte1 byte0
40         int64:  byte7 byte6 byte5 byte4 byte3 byte2 byte1 byte0
41         string: int32:0 | int32:length char* char:0 padding
42         padding: | char:0 | char:0 char:0 | char:0 char:0 char:0
43         item: int32 | int64 | string
44
45    The basic format of the files is
46
47         file : int32:magic int32:version record*
48
49    The magic ident is different for the bbg and the counter files.
50    The version is the same for both files and is derived from gcc's
51    version number.  Although the ident and version are formally 32 bit
52    numbers, they are derived from 4 character ASCII strings.  The
53    version number consists of the single character major version
54    number, a two character minor version number (leading zero for
55    versions less than 10), and a single character indicating the
56    status of the release.  That will be 'e' experimental, 'p'
57    prerelease and 'r' for release.  Because, by good fortune, these are
58    in alphabetical order, string collating can be used to compare
59    version strings, and because numbers are stored big endian, numeric
60    comparison can be used when it is read as a 32 bit value.  Be aware
61    that the 'e' designation will (naturally) be unstable and might be
62    incompatible with itself.  For gcc 3.4 experimental, it would be
63    '304e' (0x33303465).  When the major version reaches 10, the letters
64    A-Z will be used.  Assuming minor increments releases every 6
65    months, we have to make a major increment every 50 years.  Assuming
66    major increments releases every 5 years, we're ok for the next 155
67    years -- good enough for me.
68
69    A record has a tag, length and variable amount of data.
70
71         record: header data
72         header: int32:tag int32:length
73         data: item*
74
75    Records are not nested, but there is a record hierarchy.  Tag
76    numbers reflect this hierarchy.  Tags are unique across bbg and da
77    files.  Some record types have a varying amount of data.  The LENGTH
78    is usually used to determine how much data.  The tag value is split
79    into 4 8-bit fields, one for each of four possible levels.  The
80    most significant is allocated first.  Unused levels are zero.
81    Active levels are odd-valued, so that the LSB of the level is one.
82    A sub-level incorporates the values of its superlevels.  This
83    formatting allows you to determine the tag heirarchy, without
84    understanding the tags themselves, and is similar to the standard
85    section numbering used in technical documents.  Level values
86    [1..3f] are used for common tags, values [41..9f] for the graph
87    file and [a1..ff] for the counter file.
88
89    The basic block graph file contains the following records
90         bbg:  function-graph*
91         function-graph: announce_function basic_blocks {arcs | lines}*
92         announce_function: header string:name int32:checksum
93                 string:source int32:lineno
94         basic_block: header int32:flags*
95         arcs: header int32:block_no arc*
96         arc:  int32:dest_block int32:flags
97         lines: header int32:block_no line*
98                int32:0 string:NULL
99         line:  int32:line_no | int32:0 string:filename
100
101    The BASIC_BLOCK record holds per-bb flags.  The number of blocks
102    can be inferred from its data length.  There is one ARCS record per
103    basic block.  The number of arcs from a bb is implicit from the
104    data length.  It enumerates the destination bb and per-arc flags.
105    There is one LINES record per basic block, it enumerates the source
106    lines which belong to that basic block.  Source file names are
107    introduced by a line number of 0, following lines are from the new
108    source file.  The initial source file for the function is NULL, but
109    the current source file should be remembered from one LINES record
110    to the next.  The end of a block is indicated by an empty filename
111    - this does not reset the current source file.  Note there is no
112    ordering of the ARCS and LINES records: they may be in any order,
113    interleaved in any manner.  The current filename follows the order
114    the LINES records are stored in the file, *not* the ordering of the
115    blocks they are for.
116
117    The data file contains the following records.
118         da:   {function-data* summary:object summary:program*}*
119         function-data:  announce_function arc_counts
120         announce_function: header string:name int32:checksum
121         arc_counts: header int64:count*
122         summary: in32:checksum int32:runs int32:arcs int64:sum int64:max \
123                 int64:max_sum int64:sum_max
124
125    The ANNOUNCE_FUNCTION record is the same as that in the BBG file,
126    but without the source location.
127    The ARC_COUNTS gives the counter values for those arcs that are
128    instrumented.  The SUMMARY records give information about the whole
129    object file and about the whole program.  The checksum is used for
130    whole program summaries, and disambiguates different programs which
131    include the same instrumented object file.  There may be several
132    program summaries, each with a unique checksum.  The object
133    summary's checkum is zero.  Note that the da file might contain
134    information from several runs concatenated, or the data might be
135    merged.
136
137    This file is included by both the compiler, gcov tools and the
138    library.  The IN_LIBGCC2 define distinguishes these cases.  When
139    IN_LIBGCC2 is nonzero, we're building libgcc2 for the target and
140    know the compiler is (the just built) gcc.  Otherwise we're
141    generating code for the host, and the compiler may or may not be
142    gcc.  In this latter case, you must ensure that 'gcov_type' is
143    typedefed to something suitable (unsigned HOST_WIDEST_INT is
144    usually what you want).  */
145
146 #ifndef GCC_GCOV_IO_H
147 #define GCC_GCOV_IO_H
148
149 #if IN_LIBGCC2
150 #if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
151 typedef long gcov_type;
152 #else
153 typedef long long gcov_type;
154 #endif
155 #endif /* IN_LIBGCC2 */
156
157 /* File suffixes.  */
158 #define GCOV_DATA_SUFFIX ".da"
159 #define GCOV_GRAPH_SUFFIX ".bbg"
160
161 /* File magic.  */
162 #define GCOV_DATA_MAGIC  0x67636f76 /* "gcov" */
163 #define GCOV_GRAPH_MAGIC 0x67626267 /* "gbbg" */
164
165 /* gcov-iov.h is automatically generated by the makefile from
166    version.c, it looks like
167         #define GCOV_VERSION ((unsigned)0x89abcdef)
168 */
169 #include "gcov-iov.h"
170
171 /* The record tags.  Values [1..3f] are for tags which may be in either
172    file.  Values [41..9f] for those in the bbg file and [a1..ff] for
173    the data file.  */
174
175 #define GCOV_TAG_FUNCTION        ((unsigned)0x01000000)
176 #define GCOV_TAG_BLOCKS          ((unsigned)0x01410000)
177 #define GCOV_TAG_ARCS            ((unsigned)0x01430000)
178 #define GCOV_TAG_LINES           ((unsigned)0x01450000)
179 #define GCOV_TAG_ARC_COUNTS      ((unsigned)0x01a10000)
180 #define GCOV_TAG_OBJECT_SUMMARY  ((unsigned)0xa1000000)
181 #define GCOV_TAG_PROGRAM_SUMMARY ((unsigned)0xa3000000)
182 #define GCOV_TAG_PLACEHOLDER_SUMMARY ((unsigned)0xa5000000)
183 #define GCOV_TAG_INCORRECT_SUMMARY ((unsigned)0xa7000000)
184
185 /* The tag level mask has 1's in the position of the inner levels, &
186    the lsb of the current level, and zero on the current and outer
187    levels.  */
188 #define GCOV_TAG_MASK(TAG) (((TAG) - 1) ^ (TAG))
189
190 /* Return nonzero if SUB is an immediate subtag of TAG.  */
191 #define GCOV_TAG_IS_SUBTAG(TAG,SUB)                             \
192         (GCOV_TAG_MASK (TAG) >> 8 == GCOV_TAG_MASK (SUB)        \
193          && !(((SUB) ^ (TAG)) & ~GCOV_TAG_MASK(TAG)))
194
195 /* Return nonzero if SUB is at a sublevel to TAG.  */
196 #define GCOV_TAG_IS_SUBLEVEL(TAG,SUB)                           \
197         (GCOV_TAG_MASK (TAG) > GCOV_TAG_MASK (SUB))
198
199 /* Basic block flags.  */
200 #define GCOV_BLOCK_UNEXPECTED   (1 << 1)
201
202 /* Arc flags.  */
203 #define GCOV_ARC_ON_TREE        (1 << 0)
204 #define GCOV_ARC_FAKE           (1 << 1)
205 #define GCOV_ARC_FALLTHROUGH    (1 << 2)
206
207 /* Structured records.  */
208
209 /* Object & program summary record.  */
210 struct gcov_summary
211 {
212   unsigned checksum;      /* checksum of program */
213   unsigned runs;          /* number of program runs */
214   unsigned arcs;          /* number of instrumented arcs */
215   gcov_type arc_sum;      /* sum of all arc counters */
216   gcov_type arc_max_one;  /* max counter on any one run */
217   gcov_type arc_max_sum;  /* maximum arc_sum */
218   gcov_type arc_sum_max;  /* sum of max_one */
219 };
220
221 /* Structures embedded in coveraged program.  The structures generated
222    by write_profile must match these.  */
223
224 /* Information about section of counters for a function.  */
225 struct counter_section
226 {
227   unsigned tag;         /* Tag of the section.  */
228   unsigned n_counters;  /* Number of counters in the section.  */
229 };
230
231 #if IN_LIBGCC2
232 /* Information about section of counters for an object file.  */
233 struct counter_section_data
234 {
235   unsigned tag;         /* Tag of the section.  */
236   unsigned n_counters;  /* Number of counters in the section.  */
237   gcov_type *counters;  /* The data.  */
238 };
239
240 /* Information about a single function.  */
241 struct function_info
242 {
243   const char *name;             /* (mangled) name of function */
244   unsigned checksum;            /* function checksum */
245   unsigned n_counter_sections;  /* Number of types of counters */
246   const struct counter_section *counter_sections;
247                                 /* The section descriptions */
248 };
249
250 /* Information about a single object file.  */
251 struct gcov_info
252 {
253   unsigned long version;        /* expected version number */
254   struct gcov_info *next;       /* link to next, used by libgcc */
255
256   const char *filename;         /* output file name */
257   long wkspc;                   /* libgcc workspace */
258
259   unsigned n_functions;             /* number of functions */
260   const struct function_info *functions; /* table of functions */
261
262   unsigned n_counter_sections;  /* Number of types of counters */
263   const struct counter_section_data *counter_sections;
264                                 /* The data to be put into the sections.  */
265 };
266
267 /* Register a new object file module.  */
268 extern void __gcov_init (struct gcov_info *);
269
270 /* Called before fork, to avoid double counting.  */
271 extern void __gcov_flush (void);
272
273 /* Since this file is used in both host and target files, and we don't
274    include ansidecl.h in target files, provide some necessary macros.  */
275 #ifndef PARAMS
276 # define PARAMS(X) X
277 #endif
278 #ifndef ATTRIBUTE_UNUSED
279 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
280 #endif
281
282 #endif /* IN_LIBGCC2 */
283
284 /* Functions for reading and writing gcov files.  */
285 static int gcov_write_unsigned PARAMS((FILE *, unsigned))
286      ATTRIBUTE_UNUSED;
287 static int gcov_write_counter PARAMS((FILE *, gcov_type))
288      ATTRIBUTE_UNUSED;
289 static int gcov_write_string PARAMS((FILE *, const char *, unsigned))
290      ATTRIBUTE_UNUSED;
291 static int gcov_read_unsigned PARAMS((FILE *, unsigned *))
292      ATTRIBUTE_UNUSED;
293 static int gcov_read_counter PARAMS((FILE *, gcov_type *))
294      ATTRIBUTE_UNUSED;
295 #if !IN_LIBGCC2
296 static int gcov_read_string PARAMS((FILE *, char **, unsigned *))
297      ATTRIBUTE_UNUSED;
298 #endif
299 static int gcov_read_summary PARAMS ((FILE *, struct gcov_summary *))
300      ATTRIBUTE_UNUSED;
301 #if IN_LIBGCC2
302 static int gcov_write_summary PARAMS ((FILE *, unsigned,
303                                        const struct gcov_summary *))
304      ATTRIBUTE_UNUSED;
305 #endif
306 #define gcov_save_position(STREAM) \
307         da_file_position (STREAM)
308 #define gcov_reserve_length(STREAM) \
309         (gcov_write_unsigned (STREAM, 0) ? 0 : da_file_position (STREAM) - 4)
310 static int gcov_write_length PARAMS((FILE *, long))
311      ATTRIBUTE_UNUSED;
312 #define gcov_resync(STREAM, BASE, LENGTH) \
313         da_file_seek (STREAM, BASE + (long)LENGTH, SEEK_SET)
314 #define gcov_skip(STREAM, LENGTH) \
315         da_file_seek (STREAM, LENGTH, SEEK_CUR)
316 #define gcov_skip_string(STREAM, LENGTH) \
317         da_file_seek (STREAM, (LENGTH) + 4 - ((LENGTH) & 3), SEEK_CUR)
318 #if IN_LIBGCC2
319 static FILE *da_file_open PARAMS ((const char *, int *));
320 static int da_file_close PARAMS ((void));
321 static int da_file_eof PARAMS ((void));
322 static int da_file_error PARAMS ((void));
323 #endif
324 static unsigned long da_file_position PARAMS ((FILE *));
325 static int da_file_seek PARAMS ((FILE *, long, int));
326 static size_t da_file_write PARAMS ((const void *, size_t, size_t, FILE *));
327 static size_t da_file_read PARAMS ((void *, size_t, size_t, FILE *));
328
329 /* Write VALUE to coverage file FILE.  Return nonzero if failed due to
330    file i/o error, or value error.  */
331
332 static int
333 gcov_write_unsigned (file, value)
334      FILE *file;
335      unsigned value;
336 {
337   char buffer[4];
338   unsigned ix;
339
340   for (ix = sizeof (buffer); ix--; )
341     {
342       buffer[ix] = value;
343       value >>= 8;
344     }
345   return ((sizeof (value) > sizeof (buffer) && value)
346           || da_file_write (buffer, 1, sizeof (buffer), file) != sizeof (buffer));
347 }
348
349 /* Write VALUE to coverage file FILE.  Return nonzero if failed due to
350    file i/o error, or value error.  Negative values are not checked
351    here -- they are checked in gcov_read_counter.  */
352
353 static int
354 gcov_write_counter (file, value)
355      FILE *file;
356      gcov_type value;
357 {
358   char buffer[8];
359   unsigned ix;
360
361   for (ix = sizeof (buffer); ix--; )
362     {
363       buffer[ix] = value;
364       value >>= 8;
365     }
366   return ((sizeof (value) > sizeof (buffer) && value != 0 && value != -1)
367           || da_file_write (buffer, 1, sizeof (buffer), file) != sizeof (buffer));
368 }
369
370 /* Write VALUE to coverage file FILE.  Return nonzero if failed due to
371    file i/o error, or value error.  */
372
373 static int
374 gcov_write_string (file, string, length)
375      FILE *file;
376      unsigned length;
377      const char *string;
378 {
379   unsigned pad = 0;
380   unsigned rem = 4 - (length & 3);
381
382   if (string)
383     return (gcov_write_unsigned (file, length)
384             || da_file_write (string, 1, length, file) != length
385             || da_file_write (&pad, 1, rem, file) != rem);
386   else
387     return gcov_write_unsigned (file, 0);
388 }
389
390 /* Read *VALUE_P from coverage file FILE.  Return nonzero if failed
391    due to file i/o error, or range error.  */
392
393 static int
394 gcov_read_unsigned (file, value_p)
395      FILE *file;
396      unsigned *value_p;
397 {
398   unsigned value = 0;
399   unsigned ix;
400   unsigned char buffer[4];
401
402   if (da_file_read (buffer, 1, sizeof (buffer), file) != sizeof (buffer))
403     return 1;
404   for (ix = sizeof (value); ix < sizeof (buffer); ix++)
405     if (buffer[ix])
406       return 1;
407   for (ix = 0; ix != sizeof (buffer); ix++)
408     {
409       value <<= 8;
410       value |= buffer[ix];
411     }
412   *value_p = value;
413   return 0;
414 }
415
416 /* Read *VALUE_P from coverage file FILE.  Return nonzero if failed
417    due to file i/o error, or range error.  */
418
419 static int
420 gcov_read_counter (file, value_p)
421      FILE *file;
422      gcov_type *value_p;
423 {
424   gcov_type value = 0;
425   unsigned ix;
426   unsigned char buffer[8];
427
428   if (da_file_read (buffer, 1, sizeof (buffer), file) != sizeof (buffer))
429     return 1;
430   for (ix = sizeof (value); ix < sizeof (buffer); ix++)
431     if (buffer[ix])
432       return 1;
433   for (ix = 0; ix != sizeof (buffer); ix++)
434     {
435       value <<= 8;
436       value |= buffer[ix];
437     }
438
439   *value_p = value;
440   return value < 0;
441 }
442
443 #if !IN_LIBGCC2
444
445 /* Read string from coverage file FILE.  Length is stored in *LENGTH_P
446    (if non-null), a buffer is allocated and returned in *STRING_P.
447    Return nonzero if failed due to file i/o error, or range
448    error.  Uses xmalloc to allocate the string buffer.  */
449
450 static int
451 gcov_read_string (file, string_p, length_p)
452      FILE *file;
453      char **string_p;
454      unsigned *length_p;
455 {
456   unsigned length;
457
458   if (gcov_read_unsigned (file, &length))
459     return 1;
460
461   if (length_p)
462     *length_p = length;
463   free (*string_p);
464
465   *string_p = NULL;
466   if (!length)
467     return 0;
468
469   length += 4 - (length & 3);
470   *string_p = (char *) xmalloc (length);
471
472   return da_file_read (*string_p, 1, length, file) != length;
473
474 }
475
476 #endif /* !IN_LIBGCC2 */
477
478 /* Write a record length at PLACE.  The current file position is the
479    end of the record, and is restored before returning.  Returns
480    nonzero on failure.  */
481
482 static int
483 gcov_write_length (file, place)
484      FILE *file;
485      long place;
486 {
487   long here = da_file_position (file);
488   int result = (!place || da_file_seek (file, place, SEEK_SET)
489                 || gcov_write_unsigned (file, here - place - 4));
490   if (da_file_seek (file, here, SEEK_SET))
491     result = 1;
492   return result;
493 }
494
495 #define GCOV_SUMMARY_LENGTH 44
496 static int
497 gcov_read_summary (da_file, summary)
498      FILE *da_file;
499      struct gcov_summary *summary;
500 {
501   return (gcov_read_unsigned (da_file, &summary->checksum)
502           || gcov_read_unsigned (da_file, &summary->runs)
503           || gcov_read_unsigned (da_file, &summary->arcs)
504           || gcov_read_counter (da_file, &summary->arc_sum)
505           || gcov_read_counter (da_file, &summary->arc_max_one)
506           || gcov_read_counter (da_file, &summary->arc_max_sum)
507           || gcov_read_counter (da_file, &summary->arc_sum_max));
508 }
509
510 #if IN_LIBGCC2
511 static int
512 gcov_write_summary (da_file, tag, summary)
513      FILE *da_file;
514      unsigned tag;
515      const struct gcov_summary *summary;
516 {
517   long base;
518
519   return (gcov_write_unsigned (da_file, tag)
520           || !(base = gcov_reserve_length (da_file))
521           || gcov_write_unsigned (da_file, summary->checksum)
522           || gcov_write_unsigned (da_file, summary->runs)
523           || gcov_write_unsigned (da_file, summary->arcs)
524           || gcov_write_counter (da_file, summary->arc_sum)
525           || gcov_write_counter (da_file, summary->arc_max_one)
526           || gcov_write_counter (da_file, summary->arc_max_sum)
527           || gcov_write_counter (da_file, summary->arc_sum_max)
528           || gcov_write_length (da_file, base));
529 }
530 #endif
531
532 #if IN_LIBGCC2
533 /* The kernel had problems with managing a lot of small reads/writes we use;
534    the functions below are used to buffer whole file in memory, thus reading and
535    writing it only once.  This should be feasible, as we have this amount
536    of memory for counters allocated anyway.  */
537
538 static FILE *actual_da_file;
539 static unsigned long actual_da_file_position;
540 static unsigned long actual_da_file_length;
541 static char *actual_da_file_buffer;
542 static unsigned long actual_da_file_buffer_size;
543
544 /* Open the file NAME and return it; in EXISTED return 1 if it existed
545    already.  */
546 static FILE *
547 da_file_open (name, existed)
548      const char *name;
549      int *existed;
550 {
551 #if defined (TARGET_HAS_F_SETLKW)
552   struct flock s_flock;
553
554   s_flock.l_type = F_WRLCK;
555   s_flock.l_whence = SEEK_SET;
556   s_flock.l_start = 0;
557   s_flock.l_len = 0; /* Until EOF.  */
558   s_flock.l_pid = getpid ();
559 #endif
560
561   if (actual_da_file)
562     return 0;
563   actual_da_file_position = 0;
564   if (!actual_da_file_buffer)
565     {
566       actual_da_file_buffer = malloc (1);
567       actual_da_file_buffer_size = 1;
568     }
569
570   actual_da_file = fopen (name, "r+t");
571   if (actual_da_file)
572     *existed = 1;
573   else
574     {
575       actual_da_file = fopen (name, "w+t");
576       if (actual_da_file)
577         *existed = 0;
578       else
579         return 0;
580     }
581
582 #if defined (TARGET_HAS_F_SETLKW)
583   /* After a fork, another process might try to read and/or write
584      the same file simultaneously.  So if we can, lock the file to
585      avoid race conditions.  */
586   while (fcntl (fileno (actual_da_file), F_SETLKW, &s_flock)
587          && errno == EINTR)
588     continue;
589 #endif
590
591   if (*existed)
592     {
593       if (fseek (actual_da_file, 0, SEEK_END))
594         {
595           fclose (actual_da_file);
596           actual_da_file = 0;
597           return 0;
598         }
599       actual_da_file_length = ftell (actual_da_file);
600       rewind (actual_da_file);
601     }
602   else
603     actual_da_file_length = 0;
604
605   if (actual_da_file_length > actual_da_file_buffer_size)
606     {
607       actual_da_file_buffer_size = actual_da_file_length;
608       actual_da_file_buffer = realloc (actual_da_file_buffer,
609                                        actual_da_file_buffer_size);
610       if (!actual_da_file_buffer)
611         {
612           fclose (actual_da_file);
613           actual_da_file = 0;
614           return 0;
615         }
616     }
617
618   if (*existed)
619     {
620       if (fread (actual_da_file_buffer, actual_da_file_length,
621                  1, actual_da_file) != 1)
622         {
623           fclose (actual_da_file);
624           actual_da_file = 0;
625           return 0;
626         }
627       rewind (actual_da_file);
628     }
629
630   return actual_da_file;
631 }
632
633 /* Write changes to the .da file and close it.  */
634 static int da_file_close ()
635 {
636   if (!actual_da_file)
637     return -1;
638   
639   if (fwrite (actual_da_file_buffer, actual_da_file_length,
640               1, actual_da_file) != 1)
641     return da_file_error ();
642
643   if (fclose (actual_da_file))
644     {
645       actual_da_file = 0;
646       return -1;
647     }
648
649   actual_da_file = 0;
650   return 0;
651 }
652
653 /* Returns current position in .da file.  */
654 static unsigned long
655 da_file_position (file)
656      FILE *file;
657 {
658   if (file)
659     return ftell (file);
660   return actual_da_file_position;
661 }
662
663 /* Tests whether we have reached end of .da file.  */
664 static int
665 da_file_eof ()
666 {
667   return actual_da_file_position == actual_da_file_length;
668 }
669
670 /* Change position in the .da file.  */
671 static int
672 da_file_seek (file, pos, whence)
673      FILE *file;
674      long pos;
675      int whence;
676 {
677   if (file)
678     return fseek (file, pos, whence);
679
680   if (!actual_da_file)
681     return -1;
682
683   switch (whence)
684     {
685     case SEEK_CUR:
686       if (pos < 0 && (unsigned long) -pos > actual_da_file_position)
687         return da_file_error ();
688
689       actual_da_file_position += pos;
690       break;
691     case SEEK_SET:
692       actual_da_file_position = pos;
693       break;
694     case SEEK_END:
695       if ((unsigned long) -pos > actual_da_file_length)
696         return da_file_error ();
697       actual_da_file_position = actual_da_file_length + pos;
698     }
699   if (actual_da_file_position > actual_da_file_length)
700     return da_file_error ();
701   return 0;
702 }
703
704 /* Write LEN chars of DATA to actual .da file; ELTS is expected to be 1,
705    FILE 0.  */
706 static size_t
707 da_file_write (data, elts, len, file)
708      const void *data;
709      size_t elts;
710      size_t len;
711      FILE *file;
712 {
713   size_t l = len;
714   const char *dat = data;
715
716   if (file)
717     return fwrite (data, elts, len, file);
718
719   if (elts != 1)
720     abort ();
721
722   if (!actual_da_file)
723     return -1;
724   if (actual_da_file_position + len > actual_da_file_buffer_size)
725     {
726       actual_da_file_buffer_size = 2 * (actual_da_file_position + len);
727       actual_da_file_buffer = realloc (actual_da_file_buffer,
728                                        actual_da_file_buffer_size);
729       if (!actual_da_file_buffer)
730         return da_file_error ();
731     }
732   while (len--)
733     actual_da_file_buffer[actual_da_file_position++] = *dat++;
734   if (actual_da_file_position > actual_da_file_length)
735     actual_da_file_length = actual_da_file_position;
736
737   return l;
738 }
739
740 /* Read LEN chars of DATA from actual .da file; ELTS is expected to be 1,
741    FILE 0.  */
742 static size_t
743 da_file_read (data, elts, len, file)
744      void *data;
745      size_t elts;
746      size_t len;
747      FILE *file;
748 {
749   size_t l;
750   char *dat = data;
751
752   if (file)
753     return fread (data, elts, len, file);
754
755   if (elts != 1)
756     abort ();
757
758   if (!actual_da_file)
759     return -1;
760   if (actual_da_file_position + len > actual_da_file_length)
761     len = actual_da_file_length - actual_da_file_position;
762   l = len;
763   
764   while (len--)
765     *dat++ = actual_da_file_buffer[actual_da_file_position++];
766   return l;
767 }
768
769 /* Close the current .da file and report error.  */
770 static int
771 da_file_error ()
772 {
773   if (actual_da_file)
774     fclose (actual_da_file);
775   actual_da_file = 0;
776   return -1;
777 }
778 #else /* !IN_LIBGCC2 */
779 static size_t
780 da_file_write (data, elts, len, file)
781      const void *data;
782      size_t elts;
783      size_t len;
784      FILE *file;
785 {
786   return fwrite (data, elts, len, file);
787 }
788
789 static size_t
790 da_file_read (data, elts, len, file)
791      void *data;
792      size_t elts;
793      size_t len;
794      FILE *file;
795 {
796   return fread (data, elts, len, file);
797 }
798
799 static unsigned long
800 da_file_position (file)
801      FILE *file;
802 {
803   return ftell (file);
804 }
805
806 static int
807 da_file_seek (file, pos, whence)
808      FILE *file;
809      long pos;
810      int whence;
811 {
812   return fseek (file, pos, whence);
813 }
814 #endif
815
816 #endif /* GCC_GCOV_IO_H */