2003-03-15 Glen Nakamura <glen@imodulo.com>
[official-gcc.git] / gcc / gcov-io.h
blob4fcd7de5d21c8dcb96755e07b63837267c46d5a4
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>.
6 This file is part of GCC.
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.
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.
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. */
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.
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).
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
45 The basic format of the files is
47 file : int32:magic int32:version record*
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.
69 A record has a tag, length and variable amount of data.
71 record: header data
72 header: int32:tag int32:length
73 data: item*
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.
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 basic_block: header int32:flags*
94 arcs: header int32:block_no arc*
95 arc: int32:dest_block int32:flags
96 lines: header int32:block_no line*
97 int32:0 string:NULL
98 line: int32:line_no | int32:0 string:filename
100 The BASIC_BLOCK record holds per-bb flags. The number of blocks
101 can be inferred from its data length. There is one ARCS record per
102 basic block. The number of arcs from a bb is implicit from the
103 data length. It enumerates the destination bb and per-arc flags.
104 There is one LINES record per basic block, it enumerates the source
105 lines which belong to that basic block. Source file names are
106 introduced by a line number of 0, following lines are from the new
107 source file. The initial source file for the function is NULL, but
108 the current source file should be remembered from one LINES record
109 to the next. The end of a block is indicated by an empty filename
110 - this does not reset the current source file. Note there is no
111 ordering of the ARCS and LINES records: they may be in any order,
112 interleaved in any manner. The current filename follows the order
113 the LINES records are stored in the file, *not* the ordering of the
114 blocks they are for.
116 The data file contains the following records.
117 da: {function-data* summary:object summary:program*}*
118 function-data: announce_function arc_counts
119 announce_function: header string:name int32:checksum
120 arc_counts: header int64:count*
121 summary: in32:checksum int32:runs int32:arcs int64:sum int64:max \
122 int64:max_sum int64:sum_max
124 The ANNOUNCE_FUNCTION record is the same as that in the BBG file.
125 The ARC_COUNTS gives the counter values for those arcs that are
126 instrumented. The SUMMARY records give information about the whole
127 object file and about the whole program. The checksum is used for
128 whole program summaries, and disambiguates different programs which
129 include the same instrumented object file. There may be several
130 program summaries, each with a unique checksum. The object
131 summary's checkum is zero. Note that the da file might contain
132 information from several runs concatenated, or the data might be
133 merged.
135 This file is included by both the compiler, gcov tools and the
136 library. The IN_LIBGCC2 define distinguishes these cases. When
137 IN_LIBGCC2 is nonzero, we're building libgcc2 for the target and
138 know the compiler is (the just built) gcc. Otherwise we're
139 generating code for the host, and the compiler may or may not be
140 gcc. In this latter case, you must ensure that 'gcov_type' is
141 typedefed to something suitable (unsigned HOST_WIDEST_INT is
142 usually what you want). */
144 #ifndef GCC_GCOV_IO_H
145 #define GCC_GCOV_IO_H
147 #if IN_LIBGCC2
148 #if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
149 typedef long gcov_type;
150 #else
151 typedef long long gcov_type;
152 #endif
153 #endif /* IN_LIBGCC2 */
155 /* File suffixes. */
156 #define GCOV_DATA_SUFFIX ".da"
157 #define GCOV_GRAPH_SUFFIX ".bbg"
159 /* File magic. */
160 #define GCOV_DATA_MAGIC 0x67636f76 /* "gcov" */
161 #define GCOV_GRAPH_MAGIC 0x67626267 /* "gbbg" */
163 /* gcov-iov.h is automatically generated by the makefile from
164 version.c, it looks like
165 #define GCOV_VERSION ((unsigned)0x89abcdef)
167 #include "gcov-iov.h"
169 /* The record tags. Values [1..3f] are for tags which may be in either
170 file. Values [41..9f] for those in the bbg file and [a1..ff] for
171 the data file. */
173 #define GCOV_TAG_FUNCTION ((unsigned)0x01000000)
174 #define GCOV_TAG_BLOCKS ((unsigned)0x01410000)
175 #define GCOV_TAG_ARCS ((unsigned)0x01430000)
176 #define GCOV_TAG_LINES ((unsigned)0x01450000)
177 #define GCOV_TAG_ARC_COUNTS ((unsigned)0x01a10000)
178 #define GCOV_TAG_OBJECT_SUMMARY ((unsigned)0xa1000000)
179 #define GCOV_TAG_PROGRAM_SUMMARY ((unsigned)0xa3000000)
180 #define GCOV_TAG_PLACEHOLDER_SUMMARY ((unsigned)0xa5000000)
181 #define GCOV_TAG_INCORRECT_SUMMARY ((unsigned)0xa7000000)
183 /* The tag level mask has 1's in the position of the inner levels, &
184 the lsb of the current level, and zero on the current and outer
185 levels. */
186 #define GCOV_TAG_MASK(TAG) (((TAG) - 1) ^ (TAG))
188 /* Return nonzero if SUB is an immediate subtag of TAG. */
189 #define GCOV_TAG_IS_SUBTAG(TAG,SUB) \
190 (GCOV_TAG_MASK (TAG) >> 8 == GCOV_TAG_MASK (SUB) \
191 && !(((SUB) ^ (TAG)) & ~GCOV_TAG_MASK(TAG)))
193 /* Return nonzero if SUB is at a sublevel to TAG. */
194 #define GCOV_TAG_IS_SUBLEVEL(TAG,SUB) \
195 (GCOV_TAG_MASK (TAG) > GCOV_TAG_MASK (SUB))
197 /* Basic block flags. */
198 #define GCOV_BLOCK_UNEXPECTED (1 << 0)
200 /* Arc flags. */
201 #define GCOV_ARC_ON_TREE (1 << 0)
202 #define GCOV_ARC_FAKE (1 << 1)
203 #define GCOV_ARC_FALLTHROUGH (1 << 2)
205 /* Structured records. */
207 /* Object & program summary record. */
208 struct gcov_summary
210 unsigned checksum; /* checksum of program */
211 unsigned runs; /* number of program runs */
212 unsigned arcs; /* number of instrumented arcs */
213 gcov_type arc_sum; /* sum of all arc counters */
214 gcov_type arc_max_one; /* max counter on any one run */
215 gcov_type arc_max_sum; /* maximum arc_sum */
216 gcov_type arc_sum_max; /* sum of max_one */
219 /* Structures embedded in coveraged program. The structures generated
220 by write_profile must match these. */
222 /* Information about section of counters for a function. */
223 struct counter_section
225 unsigned tag; /* Tag of the section. */
226 unsigned n_counters; /* Number of counters in the section. */
229 #if IN_LIBGCC2
230 /* Information about section of counters for an object file. */
231 struct counter_section_data
233 unsigned tag; /* Tag of the section. */
234 unsigned n_counters; /* Number of counters in the section. */
235 gcov_type *counters; /* The data. */
238 /* Information about a single function. */
239 struct function_info
241 const char *name; /* (mangled) name of function */
242 unsigned checksum; /* function checksum */
243 unsigned n_counter_sections; /* Number of types of counters */
244 const struct counter_section *counter_sections;
245 /* The section descriptions */
248 /* Information about a single object file. */
249 struct gcov_info
251 unsigned long version; /* expected version number */
252 struct gcov_info *next; /* link to next, used by libgcc */
254 const char *filename; /* output file name */
255 long wkspc; /* libgcc workspace */
257 unsigned n_functions; /* number of functions */
258 const struct function_info *functions; /* table of functions */
260 unsigned n_counter_sections; /* Number of types of counters */
261 const struct counter_section_data *counter_sections;
262 /* The data to be put into the sections. */
265 /* Register a new object file module. */
266 extern void __gcov_init (struct gcov_info *);
268 /* Called before fork, to avoid double counting. */
269 extern void __gcov_flush (void);
271 /* Since this file is used in both host and target files, and we don't
272 include ansidecl.h in target files, provide some necessary macros. */
273 #ifndef PARAMS
274 # define PARAMS(X) X
275 #endif
276 #ifndef ATTRIBUTE_UNUSED
277 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
278 #endif
280 #endif /* IN_LIBGCC2 */
282 /* Functions for reading and writing gcov files. */
283 static int gcov_write_unsigned PARAMS((FILE *, unsigned))
284 ATTRIBUTE_UNUSED;
285 static int gcov_write_counter PARAMS((FILE *, gcov_type))
286 ATTRIBUTE_UNUSED;
287 static int gcov_write_string PARAMS((FILE *, const char *, unsigned))
288 ATTRIBUTE_UNUSED;
289 static int gcov_read_unsigned PARAMS((FILE *, unsigned *))
290 ATTRIBUTE_UNUSED;
291 static int gcov_read_counter PARAMS((FILE *, gcov_type *))
292 ATTRIBUTE_UNUSED;
293 #if !IN_LIBGCC2
294 static int gcov_read_string PARAMS((FILE *, char **, unsigned *))
295 ATTRIBUTE_UNUSED;
296 #endif
297 static int gcov_read_summary PARAMS ((FILE *, struct gcov_summary *))
298 ATTRIBUTE_UNUSED;
299 #if IN_LIBGCC2
300 static int gcov_write_summary PARAMS ((FILE *, unsigned,
301 const struct gcov_summary *))
302 ATTRIBUTE_UNUSED;
303 #endif
304 #define gcov_save_position(STREAM) \
305 da_file_position (STREAM)
306 #define gcov_reserve_length(STREAM) \
307 (gcov_write_unsigned (STREAM, 0) ? 0 : da_file_position (STREAM) - 4)
308 static int gcov_write_length PARAMS((FILE *, long))
309 ATTRIBUTE_UNUSED;
310 #define gcov_resync(STREAM, BASE, LENGTH) \
311 da_file_seek (STREAM, BASE + (long)LENGTH, SEEK_SET)
312 #define gcov_skip(STREAM, LENGTH) \
313 da_file_seek (STREAM, LENGTH, SEEK_CUR)
314 #define gcov_skip_string(STREAM, LENGTH) \
315 da_file_seek (STREAM, (LENGTH) + 4 - ((LENGTH) & 3), SEEK_CUR)
316 #if IN_LIBGCC2
317 static FILE *da_file_open PARAMS ((const char *, int *));
318 static int da_file_close PARAMS ((void));
319 static int da_file_eof PARAMS ((void));
320 static int da_file_error PARAMS ((void));
321 #endif
322 static unsigned long da_file_position PARAMS ((FILE *));
323 static int da_file_seek PARAMS ((FILE *, long, int));
324 static size_t da_file_write PARAMS ((const void *, size_t, size_t, FILE *));
325 static size_t da_file_read PARAMS ((void *, size_t, size_t, FILE *));
327 /* Write VALUE to coverage file FILE. Return nonzero if failed due to
328 file i/o error, or value error. */
330 static int
331 gcov_write_unsigned (file, value)
332 FILE *file;
333 unsigned value;
335 char buffer[4];
336 unsigned ix;
338 for (ix = sizeof (buffer); ix--; )
340 buffer[ix] = value;
341 value >>= 8;
343 return ((sizeof (value) > sizeof (buffer) && value)
344 || da_file_write (buffer, 1, sizeof (buffer), file) != sizeof (buffer));
347 /* Write VALUE to coverage file FILE. Return nonzero if failed due to
348 file i/o error, or value error. Negative values are not checked
349 here -- they are checked in gcov_read_counter. */
351 static int
352 gcov_write_counter (file, value)
353 FILE *file;
354 gcov_type value;
356 char buffer[8];
357 unsigned ix;
359 for (ix = sizeof (buffer); ix--; )
361 buffer[ix] = value;
362 value >>= 8;
364 return ((sizeof (value) > sizeof (buffer) && value != 0 && value != -1)
365 || da_file_write (buffer, 1, sizeof (buffer), file) != sizeof (buffer));
368 /* Write VALUE to coverage file FILE. Return nonzero if failed due to
369 file i/o error, or value error. */
371 static int
372 gcov_write_string (file, string, length)
373 FILE *file;
374 unsigned length;
375 const char *string;
377 unsigned pad = 0;
378 unsigned rem = 4 - (length & 3);
380 if (string)
381 return (gcov_write_unsigned (file, length)
382 || da_file_write (string, 1, length, file) != length
383 || da_file_write (&pad, 1, rem, file) != rem);
384 else
385 return gcov_write_unsigned (file, 0);
388 /* Read *VALUE_P from coverage file FILE. Return nonzero if failed
389 due to file i/o error, or range error. */
391 static int
392 gcov_read_unsigned (file, value_p)
393 FILE *file;
394 unsigned *value_p;
396 unsigned value = 0;
397 unsigned ix;
398 unsigned char buffer[4];
400 if (da_file_read (buffer, 1, sizeof (buffer), file) != sizeof (buffer))
401 return 1;
402 for (ix = sizeof (value); ix < sizeof (buffer); ix++)
403 if (buffer[ix])
404 return 1;
405 for (ix = 0; ix != sizeof (buffer); ix++)
407 value <<= 8;
408 value |= buffer[ix];
410 *value_p = value;
411 return 0;
414 /* Read *VALUE_P from coverage file FILE. Return nonzero if failed
415 due to file i/o error, or range error. */
417 static int
418 gcov_read_counter (file, value_p)
419 FILE *file;
420 gcov_type *value_p;
422 gcov_type value = 0;
423 unsigned ix;
424 unsigned char buffer[8];
426 if (da_file_read (buffer, 1, sizeof (buffer), file) != sizeof (buffer))
427 return 1;
428 for (ix = sizeof (value); ix < sizeof (buffer); ix++)
429 if (buffer[ix])
430 return 1;
431 for (ix = 0; ix != sizeof (buffer); ix++)
433 value <<= 8;
434 value |= buffer[ix];
437 *value_p = value;
438 return value < 0;
441 #if !IN_LIBGCC2
443 /* Read string from coverage file FILE. Length is stored in *LENGTH_P
444 (if non-null), a buffer is allocated and returned in *STRING_P.
445 Return nonzero if failed due to file i/o error, or range
446 error. Uses xmalloc to allocate the string buffer. */
448 static int
449 gcov_read_string (file, string_p, length_p)
450 FILE *file;
451 char **string_p;
452 unsigned *length_p;
454 unsigned length;
456 if (gcov_read_unsigned (file, &length))
457 return 1;
459 if (length_p)
460 *length_p = length;
461 free (*string_p);
463 *string_p = NULL;
464 if (!length)
465 return 0;
467 length += 4 - (length & 3);
468 *string_p = (char *) xmalloc (length);
470 return da_file_read (*string_p, 1, length, file) != length;
474 #endif /* !IN_LIBGCC2 */
476 /* Write a record length at PLACE. The current file position is the
477 end of the record, and is restored before returning. Returns
478 nonzero on failure. */
480 static int
481 gcov_write_length (file, place)
482 FILE *file;
483 long place;
485 long here = da_file_position (file);
486 int result = (!place || da_file_seek (file, place, SEEK_SET)
487 || gcov_write_unsigned (file, here - place - 4));
488 if (da_file_seek (file, here, SEEK_SET))
489 result = 1;
490 return result;
493 #define GCOV_SUMMARY_LENGTH 44
494 static int
495 gcov_read_summary (da_file, summary)
496 FILE *da_file;
497 struct gcov_summary *summary;
499 return (gcov_read_unsigned (da_file, &summary->checksum)
500 || gcov_read_unsigned (da_file, &summary->runs)
501 || gcov_read_unsigned (da_file, &summary->arcs)
502 || gcov_read_counter (da_file, &summary->arc_sum)
503 || gcov_read_counter (da_file, &summary->arc_max_one)
504 || gcov_read_counter (da_file, &summary->arc_max_sum)
505 || gcov_read_counter (da_file, &summary->arc_sum_max));
508 #if IN_LIBGCC2
509 static int
510 gcov_write_summary (da_file, tag, summary)
511 FILE *da_file;
512 unsigned tag;
513 const struct gcov_summary *summary;
515 long base;
517 return (gcov_write_unsigned (da_file, tag)
518 || !(base = gcov_reserve_length (da_file))
519 || gcov_write_unsigned (da_file, summary->checksum)
520 || gcov_write_unsigned (da_file, summary->runs)
521 || gcov_write_unsigned (da_file, summary->arcs)
522 || gcov_write_counter (da_file, summary->arc_sum)
523 || gcov_write_counter (da_file, summary->arc_max_one)
524 || gcov_write_counter (da_file, summary->arc_max_sum)
525 || gcov_write_counter (da_file, summary->arc_sum_max)
526 || gcov_write_length (da_file, base));
528 #endif
530 #if IN_LIBGCC2
531 /* The kernel had problems with managing a lot of small reads/writes we use;
532 the functions below are used to buffer whole file in memory, thus reading and
533 writing it only once. This should be feasible, as we have this amount
534 of memory for counters allocated anyway. */
536 static FILE *actual_da_file;
537 static unsigned long actual_da_file_position;
538 static unsigned long actual_da_file_length;
539 static char *actual_da_file_buffer;
540 static unsigned long actual_da_file_buffer_size;
542 /* Open the file NAME and return it; in EXISTED return 1 if it existed
543 already. */
544 static FILE *
545 da_file_open (name, existed)
546 const char *name;
547 int *existed;
549 #if defined (TARGET_HAS_F_SETLKW)
550 struct flock s_flock;
552 s_flock.l_type = F_WRLCK;
553 s_flock.l_whence = SEEK_SET;
554 s_flock.l_start = 0;
555 s_flock.l_len = 0; /* Until EOF. */
556 s_flock.l_pid = getpid ();
557 #endif
559 if (actual_da_file)
560 return 0;
561 actual_da_file_position = 0;
562 if (!actual_da_file_buffer)
564 actual_da_file_buffer = malloc (1);
565 actual_da_file_buffer_size = 1;
568 actual_da_file = fopen (name, "r+t");
569 if (actual_da_file)
570 *existed = 1;
571 else
573 actual_da_file = fopen (name, "w+t");
574 if (actual_da_file)
575 *existed = 0;
576 else
577 return 0;
580 #if defined (TARGET_HAS_F_SETLKW)
581 /* After a fork, another process might try to read and/or write
582 the same file simultaneously. So if we can, lock the file to
583 avoid race conditions. */
584 while (fcntl (fileno (actual_da_file), F_SETLKW, &s_flock)
585 && errno == EINTR)
586 continue;
587 #endif
589 if (*existed)
591 if (fseek (actual_da_file, 0, SEEK_END))
593 fclose (actual_da_file);
594 actual_da_file = 0;
595 return 0;
597 actual_da_file_length = ftell (actual_da_file);
598 rewind (actual_da_file);
600 else
601 actual_da_file_length = 0;
603 if (actual_da_file_length > actual_da_file_buffer_size)
605 actual_da_file_buffer_size = actual_da_file_length;
606 actual_da_file_buffer = realloc (actual_da_file_buffer,
607 actual_da_file_buffer_size);
608 if (!actual_da_file_buffer)
610 fclose (actual_da_file);
611 actual_da_file = 0;
612 return 0;
616 if (*existed)
618 if (fread (actual_da_file_buffer, actual_da_file_length,
619 1, actual_da_file) != 1)
621 fclose (actual_da_file);
622 actual_da_file = 0;
623 return 0;
625 rewind (actual_da_file);
628 return actual_da_file;
631 /* Write changes to the .da file and close it. */
632 static int da_file_close ()
634 if (!actual_da_file)
635 return -1;
637 if (fwrite (actual_da_file_buffer, actual_da_file_length,
638 1, actual_da_file) != 1)
639 return da_file_error ();
641 if (fclose (actual_da_file))
643 actual_da_file = 0;
644 return -1;
647 actual_da_file = 0;
648 return 0;
651 /* Returns current position in .da file. */
652 static unsigned long
653 da_file_position (file)
654 FILE *file;
656 if (file)
657 return ftell (file);
658 return actual_da_file_position;
661 /* Tests whether we have reached end of .da file. */
662 static int
663 da_file_eof ()
665 return actual_da_file_position == actual_da_file_length;
668 /* Change position in the .da file. */
669 static int
670 da_file_seek (file, pos, whence)
671 FILE *file;
672 long pos;
673 int whence;
675 if (file)
676 return fseek (file, pos, whence);
678 if (!actual_da_file)
679 return -1;
681 switch (whence)
683 case SEEK_CUR:
684 if (pos < 0 && (unsigned long) -pos > actual_da_file_position)
685 return da_file_error ();
687 actual_da_file_position += pos;
688 break;
689 case SEEK_SET:
690 actual_da_file_position = pos;
691 break;
692 case SEEK_END:
693 if ((unsigned long) -pos > actual_da_file_length)
694 return da_file_error ();
695 actual_da_file_position = actual_da_file_length + pos;
697 if (actual_da_file_position > actual_da_file_length)
698 return da_file_error ();
699 return 0;
702 /* Write LEN chars of DATA to actual .da file; ELTS is expected to be 1,
703 FILE 0. */
704 static size_t
705 da_file_write (data, elts, len, file)
706 const void *data;
707 size_t elts;
708 size_t len;
709 FILE *file;
711 size_t l = len;
712 const char *dat = data;
714 if (file)
715 return fwrite (data, elts, len, file);
717 if (elts != 1)
718 abort ();
720 if (!actual_da_file)
721 return -1;
722 if (actual_da_file_position + len > actual_da_file_buffer_size)
724 actual_da_file_buffer_size = 2 * (actual_da_file_position + len);
725 actual_da_file_buffer = realloc (actual_da_file_buffer,
726 actual_da_file_buffer_size);
727 if (!actual_da_file_buffer)
728 return da_file_error ();
730 while (len--)
731 actual_da_file_buffer[actual_da_file_position++] = *dat++;
732 if (actual_da_file_position > actual_da_file_length)
733 actual_da_file_length = actual_da_file_position;
735 return l;
738 /* Read LEN chars of DATA from actual .da file; ELTS is expected to be 1,
739 FILE 0. */
740 static size_t
741 da_file_read (data, elts, len, file)
742 void *data;
743 size_t elts;
744 size_t len;
745 FILE *file;
747 size_t l;
748 char *dat = data;
750 if (file)
751 return fread (data, elts, len, file);
753 if (elts != 1)
754 abort ();
756 if (!actual_da_file)
757 return -1;
758 if (actual_da_file_position + len > actual_da_file_length)
759 len = actual_da_file_length - actual_da_file_position;
760 l = len;
762 while (len--)
763 *dat++ = actual_da_file_buffer[actual_da_file_position++];
764 return l;
767 /* Close the current .da file and report error. */
768 static int
769 da_file_error ()
771 if (actual_da_file)
772 fclose (actual_da_file);
773 actual_da_file = 0;
774 return -1;
776 #else /* !IN_LIBGCC2 */
777 static size_t
778 da_file_write (data, elts, len, file)
779 const void *data;
780 size_t elts;
781 size_t len;
782 FILE *file;
784 return fwrite (data, elts, len, file);
787 static size_t
788 da_file_read (data, elts, len, file)
789 void *data;
790 size_t elts;
791 size_t len;
792 FILE *file;
794 return fread (data, elts, len, file);
797 static unsigned long
798 da_file_position (file)
799 FILE *file;
801 return ftell (file);
804 static int
805 da_file_seek (file, pos, whence)
806 FILE *file;
807 long pos;
808 int whence;
810 return fseek (file, pos, whence);
812 #endif
814 #endif /* GCC_GCOV_IO_H */