1 /* Machine-independent I/O routines for gcov.
2 Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
3 Contributed by Bob Manson <manson@cygnus.com>.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21
22 /* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public
28 License. */
29
30 #ifndef GCC_GCOV_IO_H
31 #define GCC_GCOV_IO_H
32 #include <stdio.h>
33 #include <sys/types.h>
34
35 static int __fetch_long PARAMS ((long *, char *, size_t))
36 ATTRIBUTE_UNUSED;
37 static int __read_long PARAMS ((long *, FILE *, size_t))
38 ATTRIBUTE_UNUSED;
39 static int __write_long PARAMS ((long, FILE *, size_t))
40 ATTRIBUTE_UNUSED;
41 static int __fetch_gcov_type PARAMS ((gcov_type *, char *, size_t))
42 ATTRIBUTE_UNUSED;
43 static int __store_gcov_type PARAMS ((gcov_type, char *, size_t))
44 ATTRIBUTE_UNUSED;
45 static int __read_gcov_type PARAMS ((gcov_type *, FILE *, size_t))
46 ATTRIBUTE_UNUSED;
47 static int __write_gcov_type PARAMS ((gcov_type, FILE *, size_t))
48 ATTRIBUTE_UNUSED;
49 static int __write_gcov_string PARAMS ((const char *, size_t, FILE*, long))
50 ATTRIBUTE_UNUSED;
51 static int __read_gcov_string PARAMS ((char *, size_t, FILE*, long))
52 ATTRIBUTE_UNUSED;
53
54 /* These routines only work for signed values. */
55
56 /* Store a portable representation of VALUE in DEST using BYTES*8-1 bits.
57 Return a nonzero value if VALUE requires more than BYTES*8-1 bits
58 to store. */
59
60 static int
__store_gcov_type(value,dest,bytes)61 __store_gcov_type (value, dest, bytes)
62 gcov_type value;
63 char *dest;
64 size_t bytes;
65 {
66 int upper_bit = (value < 0 ? 128 : 0);
67 size_t i;
68
69 if (value < 0)
70 {
71 gcov_type oldvalue = value;
72 value = -value;
73 if (oldvalue != -value)
74 return 1;
75 }
76
77 for(i = 0 ; i < (sizeof (value) < bytes ? sizeof (value) : bytes) ; i++) {
78 dest[i] = value & (i == (bytes - 1) ? 127 : 255);
79 value = value / 256;
80 }
81
82 if (value && value != -1)
83 return 1;
84
85 for(; i < bytes ; i++)
86 dest[i] = 0;
87 dest[bytes - 1] |= upper_bit;
88 return 0;
89 }
90
91 /* Retrieve a quantity containing BYTES*8-1 bits from SOURCE and store
92 the result in DEST. Returns a nonzero value if the value in SOURCE
93 will not fit in DEST. */
94
95 static int
__fetch_gcov_type(dest,source,bytes)96 __fetch_gcov_type (dest, source, bytes)
97 gcov_type *dest;
98 char *source;
99 size_t bytes;
100 {
101 gcov_type value = 0;
102 int i;
103
104 for (i = bytes - 1; (size_t) i > (sizeof (*dest) - 1); i--)
105 if (source[i] & ((size_t) i == (bytes - 1) ? 127 : 255 ))
106 return 1;
107
108 for (; i >= 0; i--)
109 value = value * 256 + (source[i] & ((size_t)i == (bytes - 1) ? 127 : 255));
110
111 if ((source[bytes - 1] & 128) && (value > 0))
112 value = - value;
113
114 *dest = value;
115 return 0;
116 }
117
118 static int
__fetch_long(dest,source,bytes)119 __fetch_long (dest, source, bytes)
120 long *dest;
121 char *source;
122 size_t bytes;
123 {
124 long value = 0;
125 int i;
126
127 for (i = bytes - 1; (size_t) i > (sizeof (*dest) - 1); i--)
128 if (source[i] & ((size_t) i == (bytes - 1) ? 127 : 255 ))
129 return 1;
130
131 for (; i >= 0; i--)
132 value = value * 256 + (source[i] & ((size_t)i == (bytes - 1) ? 127 : 255));
133
134 if ((source[bytes - 1] & 128) && (value > 0))
135 value = - value;
136
137 *dest = value;
138 return 0;
139 }
140
141 /* Write a BYTES*8-bit quantity to FILE, portably. Returns a nonzero
142 value if the write fails, or if VALUE can't be stored in BYTES*8
143 bits.
144
145 Note that VALUE may not actually be large enough to hold BYTES*8
146 bits, but BYTES characters will be written anyway.
147
148 BYTES may be a maximum of 10. */
149
150 static int
__write_gcov_type(value,file,bytes)151 __write_gcov_type (value, file, bytes)
152 gcov_type value;
153 FILE *file;
154 size_t bytes;
155 {
156 char c[10];
157
158 if (bytes > 10 || __store_gcov_type (value, c, bytes))
159 return 1;
160 else
161 return fwrite(c, 1, bytes, file) != bytes;
162 }
163
164 static int
__write_long(value,file,bytes)165 __write_long (value, file, bytes)
166 long value;
167 FILE *file;
168 size_t bytes;
169 {
170 char c[10];
171
172 if (bytes > 10 || __store_gcov_type ((gcov_type)value, c, bytes))
173 return 1;
174 else
175 return fwrite(c, 1, bytes, file) != bytes;
176 }
177
178 /* Read a quantity containing BYTES bytes from FILE, portably. Return
179 a nonzero value if the read fails or if the value will not fit
180 in DEST.
181
182 Note that DEST may not be large enough to hold all of the requested
183 data, but the function will read BYTES characters anyway.
184
185 BYTES may be a maximum of 10. */
186
187 static int
__read_gcov_type(dest,file,bytes)188 __read_gcov_type (dest, file, bytes)
189 gcov_type *dest;
190 FILE *file;
191 size_t bytes;
192 {
193 char c[10];
194
195 if (bytes > 10 || fread(c, 1, bytes, file) != bytes)
196 return 1;
197 else
198 return __fetch_gcov_type (dest, c, bytes);
199 }
200
201 static int
__read_long(dest,file,bytes)202 __read_long (dest, file, bytes)
203 long *dest;
204 FILE *file;
205 size_t bytes;
206 {
207 char c[10];
208
209 if (bytes > 10 || fread(c, 1, bytes, file) != bytes)
210 return 1;
211 else
212 return __fetch_long (dest, c, bytes);
213 }
214
215
216 /* Writes string in gcov format. */
217
218 static int
__write_gcov_string(string,length,file,delim)219 __write_gcov_string (string, length, file, delim)
220 const char *string;
221 size_t length;
222 FILE *file;
223 long delim;
224 {
225 size_t temp = length + 1;
226
227 /* delimiter */
228 if (__write_long (delim, file, 4) != 0)
229 return 1;
230
231 if (__write_long (length, file, 4) != 0)
232 return 1;
233
234 if (fwrite (string, temp, 1, file) != 1)
235 return 1;
236
237 temp &= 3;
238
239 if (temp)
240 {
241 char c[4];
242
243 c[0] = c[1] = c[2] = c[3] = 0;
244
245 if (fwrite (c, sizeof (char), 4 - temp, file) != 4 - temp)
246 return 1;
247 }
248
249 if (__write_long (delim, file, 4) != 0)
250 return 1;
251
252 return 0;
253 }
254
255 /* Reads string in gcov format. */
256
257
258 static int
__read_gcov_string(string,max_length,file,delim)259 __read_gcov_string (string, max_length, file, delim)
260 char *string;
261 size_t max_length;
262 FILE *file;
263 long delim;
264 {
265 long delim_from_file;
266 long length;
267 long read_length;
268 long tmp;
269
270 if (__read_long (&delim_from_file, file, 4) != 0)
271 return 1;
272
273 if (delim_from_file != delim)
274 return 1;
275
276 if (__read_long (&length, file, 4) != 0)
277 return 1;
278
279 if (length > (long) max_length)
280 read_length = max_length;
281 else
282 read_length = length;
283
284 tmp = (((length + 1) - 1) / 4 + 1) * 4;
285 /* This is the size occupied by the string in the file */
286
287 if (fread (string, read_length, 1, file) != 1)
288 return 1;
289
290 string[read_length] = 0;
291
292 if (fseek (file, tmp - read_length, SEEK_CUR) < 0)
293 return 1;
294
295 if (__read_long (&delim_from_file, file, 4) != 0)
296 return 1;
297
298 if (delim_from_file != delim)
299 return 1;
300
301 return 0;
302 }
303
304
305 #endif /* ! GCC_GCOV_IO_H */
306