xref: /openbsd-src/gnu/usr.bin/gcc/gcc/gcov-io.h (revision c87b03e512fc05ed6e0222f6fb0ae86264b1d05b)
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