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 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING. If not, write to the Free 19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2002111-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 35static int __fetch_long PARAMS ((long *, char *, size_t)) 36 ATTRIBUTE_UNUSED; 37static int __read_long PARAMS ((long *, FILE *, size_t)) 38 ATTRIBUTE_UNUSED; 39static int __write_long PARAMS ((long, FILE *, size_t)) 40 ATTRIBUTE_UNUSED; 41static int __fetch_gcov_type PARAMS ((gcov_type *, char *, size_t)) 42 ATTRIBUTE_UNUSED; 43static int __store_gcov_type PARAMS ((gcov_type, char *, size_t)) 44 ATTRIBUTE_UNUSED; 45static int __read_gcov_type PARAMS ((gcov_type *, FILE *, size_t)) 46 ATTRIBUTE_UNUSED; 47static int __write_gcov_type PARAMS ((gcov_type, FILE *, size_t)) 48 ATTRIBUTE_UNUSED; 49static int __write_gcov_string PARAMS ((const char *, size_t, FILE*, long)) 50 ATTRIBUTE_UNUSED; 51static 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 60static int 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 95static int 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 118static int 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 150static int 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 164static int 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 187static int 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 201static int 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 218static int 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 258static int 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