Mercurial > hg > CbC > CbC_gcc
annotate gcc/gcov-io.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 1 /* File format for coverage information |
145 | 2 Copyright (C) 1996-2020 Free Software Foundation, Inc. |
0 | 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 3, 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 | |
111 | 18 Under Section 7 of GPL version 3, you are granted additional |
19 permissions described in the GCC Runtime Library Exception, version | |
20 3.1, as published by the Free Software Foundation. | |
21 | |
22 You should have received a copy of the GNU General Public License and | |
23 a copy of the GCC Runtime Library Exception along with this program; | |
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
0 | 25 <http://www.gnu.org/licenses/>. */ |
26 | |
27 /* Routines declared in gcov-io.h. This file should be #included by | |
28 another source file, after having #included gcov-io.h. */ | |
29 | |
30 #if !IN_GCOV | |
31 static void gcov_write_block (unsigned); | |
32 static gcov_unsigned_t *gcov_write_words (unsigned); | |
33 #endif | |
34 static const gcov_unsigned_t *gcov_read_words (unsigned); | |
35 #if !IN_LIBGCOV | |
36 static void gcov_allocate (unsigned); | |
37 #endif | |
38 | |
111 | 39 /* Optimum number of gcov_unsigned_t's read from or written to disk. */ |
40 #define GCOV_BLOCK_SIZE (1 << 10) | |
41 | |
42 struct gcov_var | |
43 { | |
44 FILE *file; | |
45 gcov_position_t start; /* Position of first byte of block */ | |
46 unsigned offset; /* Read/write position within the block. */ | |
47 unsigned length; /* Read limit in the block. */ | |
48 unsigned overread; /* Number of words overread. */ | |
49 int error; /* < 0 overflow, > 0 disk error. */ | |
50 int mode; /* < 0 writing, > 0 reading */ | |
51 #if IN_LIBGCOV | |
52 /* Holds one block plus 4 bytes, thus all coverage reads & writes | |
53 fit within this buffer and we always can transfer GCOV_BLOCK_SIZE | |
54 to and from the disk. libgcov never backtracks and only writes 4 | |
55 or 8 byte objects. */ | |
56 gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1]; | |
57 #else | |
58 int endian; /* Swap endianness. */ | |
59 /* Holds a variable length block, as the compiler can write | |
60 strings and needs to backtrack. */ | |
61 size_t alloc; | |
62 gcov_unsigned_t *buffer; | |
63 #endif | |
64 } gcov_var; | |
65 | |
66 /* Save the current position in the gcov file. */ | |
67 /* We need to expose this function when compiling for gcov-tool. */ | |
68 #ifndef IN_GCOV_TOOL | |
69 static inline | |
70 #endif | |
71 gcov_position_t | |
72 gcov_position (void) | |
73 { | |
74 gcov_nonruntime_assert (gcov_var.mode > 0); | |
75 return gcov_var.start + gcov_var.offset; | |
76 } | |
77 | |
78 /* Return nonzero if the error flag is set. */ | |
79 /* We need to expose this function when compiling for gcov-tool. */ | |
80 #ifndef IN_GCOV_TOOL | |
81 static inline | |
82 #endif | |
83 int | |
84 gcov_is_error (void) | |
85 { | |
86 return gcov_var.file ? gcov_var.error : 1; | |
87 } | |
88 | |
89 #if IN_LIBGCOV | |
90 /* Move to beginning of file and initialize for writing. */ | |
91 GCOV_LINKAGE inline void | |
92 gcov_rewrite (void) | |
93 { | |
94 gcov_var.mode = -1; | |
95 gcov_var.start = 0; | |
96 gcov_var.offset = 0; | |
97 fseek (gcov_var.file, 0L, SEEK_SET); | |
98 } | |
99 #endif | |
100 | |
0 | 101 static inline gcov_unsigned_t from_file (gcov_unsigned_t value) |
102 { | |
103 #if !IN_LIBGCOV | |
104 if (gcov_var.endian) | |
105 { | |
106 value = (value >> 16) | (value << 16); | |
107 value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff); | |
108 } | |
109 #endif | |
110 return value; | |
111 } | |
112 | |
113 /* Open a gcov file. NAME is the name of the file to open and MODE | |
114 indicates whether a new file should be created, or an existing file | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
115 opened. If MODE is >= 0 an existing file will be opened, if |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
116 possible, and if MODE is <= 0, a new file will be created. Use |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
117 MODE=0 to attempt to reopen an existing file and then fall back on |
111 | 118 creating a new one. If MODE > 0, the file will be opened in |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
119 read-only mode. Otherwise it will be opened for modification. |
111 | 120 Return zero on failure, non-zero on success. */ |
0 | 121 |
122 GCOV_LINKAGE int | |
123 #if IN_LIBGCOV | |
124 gcov_open (const char *name) | |
125 #else | |
126 gcov_open (const char *name, int mode) | |
127 #endif | |
128 { | |
129 #if IN_LIBGCOV | |
111 | 130 int mode = 0; |
0 | 131 #endif |
132 #if GCOV_LOCKED | |
133 struct flock s_flock; | |
134 int fd; | |
135 | |
136 s_flock.l_whence = SEEK_SET; | |
137 s_flock.l_start = 0; | |
138 s_flock.l_len = 0; /* Until EOF. */ | |
139 s_flock.l_pid = getpid (); | |
140 #endif | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
141 |
111 | 142 gcov_nonruntime_assert (!gcov_var.file); |
0 | 143 gcov_var.start = 0; |
144 gcov_var.offset = gcov_var.length = 0; | |
145 gcov_var.overread = -1u; | |
146 gcov_var.error = 0; | |
147 #if !IN_LIBGCOV | |
148 gcov_var.endian = 0; | |
149 #endif | |
150 #if GCOV_LOCKED | |
151 if (mode > 0) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
152 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
153 /* Read-only mode - acquire a read-lock. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
154 s_flock.l_type = F_RDLCK; |
111 | 155 /* pass mode (ignored) for compatibility */ |
156 fd = open (name, O_RDONLY, S_IRUSR | S_IWUSR); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
157 } |
0 | 158 else |
111 | 159 { |
160 /* Write mode - acquire a write-lock. */ | |
161 s_flock.l_type = F_WRLCK; | |
162 /* Truncate if force new mode. */ | |
163 fd = open (name, O_RDWR | O_CREAT | (mode < 0 ? O_TRUNC : 0), 0666); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
164 } |
0 | 165 if (fd < 0) |
166 return 0; | |
167 | |
168 while (fcntl (fd, F_SETLKW, &s_flock) && errno == EINTR) | |
169 continue; | |
170 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
171 gcov_var.file = fdopen (fd, (mode > 0) ? "rb" : "r+b"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
172 |
0 | 173 if (!gcov_var.file) |
174 { | |
175 close (fd); | |
176 return 0; | |
177 } | |
178 #else | |
179 if (mode >= 0) | |
111 | 180 /* Open an existing file. */ |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
181 gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
182 |
0 | 183 if (gcov_var.file) |
111 | 184 mode = 1; |
0 | 185 else if (mode <= 0) |
111 | 186 /* Create a new file. */ |
187 gcov_var.file = fopen (name, "w+b"); | |
188 | |
0 | 189 if (!gcov_var.file) |
190 return 0; | |
191 #endif | |
192 | |
111 | 193 gcov_var.mode = mode ? mode : 1; |
194 | |
0 | 195 setbuf (gcov_var.file, (char *)0); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
196 |
0 | 197 return 1; |
198 } | |
199 | |
200 /* Close the current gcov file. Flushes data to disk. Returns nonzero | |
201 on failure or error flag set. */ | |
202 | |
203 GCOV_LINKAGE int | |
204 gcov_close (void) | |
205 { | |
206 if (gcov_var.file) | |
207 { | |
208 #if !IN_GCOV | |
209 if (gcov_var.offset && gcov_var.mode < 0) | |
210 gcov_write_block (gcov_var.offset); | |
211 #endif | |
212 fclose (gcov_var.file); | |
213 gcov_var.file = 0; | |
214 gcov_var.length = 0; | |
215 } | |
216 #if !IN_LIBGCOV | |
217 free (gcov_var.buffer); | |
218 gcov_var.alloc = 0; | |
219 gcov_var.buffer = 0; | |
220 #endif | |
221 gcov_var.mode = 0; | |
222 return gcov_var.error; | |
223 } | |
224 | |
225 #if !IN_LIBGCOV | |
226 /* Check if MAGIC is EXPECTED. Use it to determine endianness of the | |
227 file. Returns +1 for same endian, -1 for other endian and zero for | |
228 not EXPECTED. */ | |
229 | |
230 GCOV_LINKAGE int | |
231 gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected) | |
232 { | |
233 if (magic == expected) | |
234 return 1; | |
235 magic = (magic >> 16) | (magic << 16); | |
236 magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff); | |
237 if (magic == expected) | |
238 { | |
239 gcov_var.endian = 1; | |
240 return -1; | |
241 } | |
242 return 0; | |
243 } | |
244 #endif | |
245 | |
246 #if !IN_LIBGCOV | |
247 static void | |
248 gcov_allocate (unsigned length) | |
249 { | |
250 size_t new_size = gcov_var.alloc; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
251 |
0 | 252 if (!new_size) |
253 new_size = GCOV_BLOCK_SIZE; | |
254 new_size += length; | |
255 new_size *= 2; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
256 |
0 | 257 gcov_var.alloc = new_size; |
258 gcov_var.buffer = XRESIZEVAR (gcov_unsigned_t, gcov_var.buffer, new_size << 2); | |
259 } | |
260 #endif | |
261 | |
262 #if !IN_GCOV | |
263 /* Write out the current block, if needs be. */ | |
264 | |
265 static void | |
266 gcov_write_block (unsigned size) | |
267 { | |
268 if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) | |
269 gcov_var.error = 1; | |
270 gcov_var.start += size; | |
271 gcov_var.offset -= size; | |
272 } | |
273 | |
274 /* Allocate space to write BYTES bytes to the gcov file. Return a | |
275 pointer to those bytes, or NULL on failure. */ | |
276 | |
277 static gcov_unsigned_t * | |
278 gcov_write_words (unsigned words) | |
279 { | |
280 gcov_unsigned_t *result; | |
281 | |
111 | 282 gcov_nonruntime_assert (gcov_var.mode < 0); |
0 | 283 #if IN_LIBGCOV |
284 if (gcov_var.offset >= GCOV_BLOCK_SIZE) | |
285 { | |
286 gcov_write_block (GCOV_BLOCK_SIZE); | |
287 if (gcov_var.offset) | |
288 { | |
289 memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4); | |
290 } | |
291 } | |
292 #else | |
293 if (gcov_var.offset + words > gcov_var.alloc) | |
294 gcov_allocate (gcov_var.offset + words); | |
295 #endif | |
296 result = &gcov_var.buffer[gcov_var.offset]; | |
297 gcov_var.offset += words; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
298 |
0 | 299 return result; |
300 } | |
301 | |
302 /* Write unsigned VALUE to coverage file. Sets error flag | |
303 appropriately. */ | |
304 | |
305 GCOV_LINKAGE void | |
306 gcov_write_unsigned (gcov_unsigned_t value) | |
307 { | |
308 gcov_unsigned_t *buffer = gcov_write_words (1); | |
309 | |
310 buffer[0] = value; | |
311 } | |
312 | |
313 /* Write counter VALUE to coverage file. Sets error flag | |
314 appropriately. */ | |
315 | |
316 #if IN_LIBGCOV | |
317 GCOV_LINKAGE void | |
318 gcov_write_counter (gcov_type value) | |
319 { | |
320 gcov_unsigned_t *buffer = gcov_write_words (2); | |
321 | |
322 buffer[0] = (gcov_unsigned_t) value; | |
323 if (sizeof (value) > sizeof (gcov_unsigned_t)) | |
324 buffer[1] = (gcov_unsigned_t) (value >> 32); | |
325 else | |
326 buffer[1] = 0; | |
327 } | |
328 #endif /* IN_LIBGCOV */ | |
329 | |
330 #if !IN_LIBGCOV | |
331 /* Write STRING to coverage file. Sets error flag on file | |
332 error, overflow flag on overflow */ | |
333 | |
334 GCOV_LINKAGE void | |
335 gcov_write_string (const char *string) | |
336 { | |
337 unsigned length = 0; | |
338 unsigned alloc = 0; | |
339 gcov_unsigned_t *buffer; | |
340 | |
341 if (string) | |
342 { | |
343 length = strlen (string); | |
344 alloc = (length + 4) >> 2; | |
345 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
346 |
0 | 347 buffer = gcov_write_words (1 + alloc); |
348 | |
349 buffer[0] = alloc; | |
111 | 350 |
351 if (alloc > 0) | |
352 { | |
353 buffer[alloc] = 0; /* place nul terminators. */ | |
354 memcpy (&buffer[1], string, length); | |
355 } | |
356 } | |
357 #endif | |
358 | |
359 #if !IN_LIBGCOV | |
360 /* Write FILENAME to coverage file. Sets error flag on file | |
361 error, overflow flag on overflow */ | |
362 | |
363 GCOV_LINKAGE void | |
364 gcov_write_filename (const char *filename) | |
365 { | |
366 if (profile_abs_path_flag && filename && filename[0] | |
367 && !(IS_DIR_SEPARATOR (filename[0]) | |
368 #if HAVE_DOS_BASED_FILE_SYSTEM | |
369 || filename[1] == ':' | |
370 #endif | |
371 )) | |
372 { | |
373 char *buf = getcwd (NULL, 0); | |
374 if (buf != NULL && buf[0]) | |
375 { | |
376 size_t len = strlen (buf); | |
377 buf = (char*)xrealloc (buf, len + strlen (filename) + 2); | |
378 if (!IS_DIR_SEPARATOR (buf[len - 1])) | |
379 strcat (buf, "/"); | |
380 strcat (buf, filename); | |
381 gcov_write_string (buf); | |
382 free (buf); | |
383 return; | |
384 } | |
385 } | |
386 | |
387 gcov_write_string (filename); | |
0 | 388 } |
389 #endif | |
390 | |
391 #if !IN_LIBGCOV | |
392 /* Write a tag TAG and reserve space for the record length. Return a | |
393 value to be used for gcov_write_length. */ | |
394 | |
395 GCOV_LINKAGE gcov_position_t | |
396 gcov_write_tag (gcov_unsigned_t tag) | |
397 { | |
398 gcov_position_t result = gcov_var.start + gcov_var.offset; | |
399 gcov_unsigned_t *buffer = gcov_write_words (2); | |
400 | |
401 buffer[0] = tag; | |
402 buffer[1] = 0; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
403 |
0 | 404 return result; |
405 } | |
406 | |
407 /* Write a record length using POSITION, which was returned by | |
408 gcov_write_tag. The current file position is the end of the | |
409 record, and is restored before returning. Returns nonzero on | |
410 overflow. */ | |
411 | |
412 GCOV_LINKAGE void | |
413 gcov_write_length (gcov_position_t position) | |
414 { | |
415 unsigned offset; | |
416 gcov_unsigned_t length; | |
417 gcov_unsigned_t *buffer; | |
418 | |
111 | 419 gcov_nonruntime_assert (gcov_var.mode < 0); |
420 gcov_nonruntime_assert (position + 2 <= gcov_var.start + gcov_var.offset); | |
421 gcov_nonruntime_assert (position >= gcov_var.start); | |
0 | 422 offset = position - gcov_var.start; |
423 length = gcov_var.offset - offset - 2; | |
424 buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset]; | |
425 buffer[1] = length; | |
426 if (gcov_var.offset >= GCOV_BLOCK_SIZE) | |
427 gcov_write_block (gcov_var.offset); | |
428 } | |
429 | |
430 #else /* IN_LIBGCOV */ | |
431 | |
432 /* Write a tag TAG and length LENGTH. */ | |
433 | |
434 GCOV_LINKAGE void | |
435 gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) | |
436 { | |
437 gcov_unsigned_t *buffer = gcov_write_words (2); | |
438 | |
439 buffer[0] = tag; | |
440 buffer[1] = length; | |
441 } | |
442 | |
443 /* Write a summary structure to the gcov file. Return nonzero on | |
444 overflow. */ | |
445 | |
446 GCOV_LINKAGE void | |
447 gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) | |
448 { | |
131 | 449 gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH); |
450 gcov_write_unsigned (summary->runs); | |
451 gcov_write_unsigned (summary->sum_max); | |
452 } | |
0 | 453 |
454 #endif /* IN_LIBGCOV */ | |
455 | |
456 #endif /*!IN_GCOV */ | |
457 | |
458 /* Return a pointer to read BYTES bytes from the gcov file. Returns | |
459 NULL on failure (read past EOF). */ | |
460 | |
461 static const gcov_unsigned_t * | |
462 gcov_read_words (unsigned words) | |
463 { | |
464 const gcov_unsigned_t *result; | |
465 unsigned excess = gcov_var.length - gcov_var.offset; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
466 |
111 | 467 if (gcov_var.mode <= 0) |
468 return NULL; | |
469 | |
0 | 470 if (excess < words) |
471 { | |
472 gcov_var.start += gcov_var.offset; | |
473 if (excess) | |
474 { | |
111 | 475 #if IN_LIBGCOV |
0 | 476 memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4); |
111 | 477 #else |
478 memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, | |
479 excess * 4); | |
480 #endif | |
0 | 481 } |
482 gcov_var.offset = 0; | |
483 gcov_var.length = excess; | |
484 #if IN_LIBGCOV | |
485 excess = GCOV_BLOCK_SIZE; | |
486 #else | |
487 if (gcov_var.length + words > gcov_var.alloc) | |
488 gcov_allocate (gcov_var.length + words); | |
489 excess = gcov_var.alloc - gcov_var.length; | |
490 #endif | |
491 excess = fread (gcov_var.buffer + gcov_var.length, | |
492 1, excess << 2, gcov_var.file) >> 2; | |
493 gcov_var.length += excess; | |
494 if (gcov_var.length < words) | |
495 { | |
496 gcov_var.overread += words - gcov_var.length; | |
497 gcov_var.length = 0; | |
498 return 0; | |
499 } | |
500 } | |
501 result = &gcov_var.buffer[gcov_var.offset]; | |
502 gcov_var.offset += words; | |
503 return result; | |
504 } | |
505 | |
506 /* Read unsigned value from a coverage file. Sets error flag on file | |
507 error, overflow flag on overflow */ | |
508 | |
509 GCOV_LINKAGE gcov_unsigned_t | |
510 gcov_read_unsigned (void) | |
511 { | |
512 gcov_unsigned_t value; | |
513 const gcov_unsigned_t *buffer = gcov_read_words (1); | |
514 | |
515 if (!buffer) | |
516 return 0; | |
517 value = from_file (buffer[0]); | |
518 return value; | |
519 } | |
520 | |
521 /* Read counter value from a coverage file. Sets error flag on file | |
522 error, overflow flag on overflow */ | |
523 | |
524 GCOV_LINKAGE gcov_type | |
525 gcov_read_counter (void) | |
526 { | |
527 gcov_type value; | |
528 const gcov_unsigned_t *buffer = gcov_read_words (2); | |
529 | |
530 if (!buffer) | |
531 return 0; | |
532 value = from_file (buffer[0]); | |
533 if (sizeof (value) > sizeof (gcov_unsigned_t)) | |
534 value |= ((gcov_type) from_file (buffer[1])) << 32; | |
535 else if (buffer[1]) | |
536 gcov_var.error = -1; | |
537 | |
538 return value; | |
539 } | |
540 | |
131 | 541 /* Mangle filename path of BASE and output new allocated pointer with |
542 mangled path. */ | |
543 | |
544 char * | |
545 mangle_path (char const *base) | |
546 { | |
547 /* Convert '/' to '#', convert '..' to '^', | |
548 convert ':' to '~' on DOS based file system. */ | |
549 const char *probe; | |
145 | 550 char *buffer = (char *)xmalloc (strlen (base) + 1); |
131 | 551 char *ptr = buffer; |
552 | |
553 #if HAVE_DOS_BASED_FILE_SYSTEM | |
554 if (base[0] && base[1] == ':') | |
555 { | |
556 ptr[0] = base[0]; | |
557 ptr[1] = '~'; | |
558 ptr += 2; | |
559 base += 2; | |
560 } | |
561 #endif | |
562 for (; *base; base = probe) | |
563 { | |
564 size_t len; | |
565 | |
566 for (probe = base; *probe; probe++) | |
567 if (*probe == '/') | |
568 break; | |
569 len = probe - base; | |
570 if (len == 2 && base[0] == '.' && base[1] == '.') | |
571 *ptr++ = '^'; | |
572 else | |
573 { | |
574 memcpy (ptr, base, len); | |
575 ptr += len; | |
576 } | |
577 if (*probe) | |
578 { | |
579 *ptr++ = '#'; | |
580 probe++; | |
581 } | |
582 } | |
583 | |
584 /* Terminate the string. */ | |
585 *ptr = '\0'; | |
586 | |
587 return buffer; | |
588 } | |
589 | |
111 | 590 /* We need to expose the below function when compiling for gcov-tool. */ |
591 | |
592 #if !IN_LIBGCOV || defined (IN_GCOV_TOOL) | |
0 | 593 /* Read string from coverage file. Returns a pointer to a static |
594 buffer, or NULL on empty string. You must copy the string before | |
595 calling another gcov function. */ | |
596 | |
597 GCOV_LINKAGE const char * | |
598 gcov_read_string (void) | |
599 { | |
600 unsigned length = gcov_read_unsigned (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
601 |
0 | 602 if (!length) |
603 return 0; | |
604 | |
605 return (const char *) gcov_read_words (length); | |
606 } | |
607 #endif | |
608 | |
609 GCOV_LINKAGE void | |
610 gcov_read_summary (struct gcov_summary *summary) | |
611 { | |
131 | 612 summary->runs = gcov_read_unsigned (); |
613 summary->sum_max = gcov_read_unsigned (); | |
0 | 614 } |
615 | |
111 | 616 /* We need to expose the below function when compiling for gcov-tool. */ |
617 | |
618 #if !IN_LIBGCOV || defined (IN_GCOV_TOOL) | |
0 | 619 /* Reset to a known position. BASE should have been obtained from |
620 gcov_position, LENGTH should be a record length. */ | |
621 | |
622 GCOV_LINKAGE void | |
623 gcov_sync (gcov_position_t base, gcov_unsigned_t length) | |
624 { | |
111 | 625 gcov_nonruntime_assert (gcov_var.mode > 0); |
0 | 626 base += length; |
627 if (base - gcov_var.start <= gcov_var.length) | |
628 gcov_var.offset = base - gcov_var.start; | |
629 else | |
630 { | |
631 gcov_var.offset = gcov_var.length = 0; | |
632 fseek (gcov_var.file, base << 2, SEEK_SET); | |
633 gcov_var.start = ftell (gcov_var.file) >> 2; | |
634 } | |
635 } | |
636 #endif | |
637 | |
638 #if IN_LIBGCOV | |
639 /* Move to a given position in a gcov file. */ | |
640 | |
641 GCOV_LINKAGE void | |
642 gcov_seek (gcov_position_t base) | |
643 { | |
644 if (gcov_var.offset) | |
645 gcov_write_block (gcov_var.offset); | |
646 fseek (gcov_var.file, base << 2, SEEK_SET); | |
647 gcov_var.start = ftell (gcov_var.file) >> 2; | |
648 } | |
649 #endif | |
650 | |
651 #if IN_GCOV > 0 | |
652 /* Return the modification time of the current gcov file. */ | |
653 | |
654 GCOV_LINKAGE time_t | |
655 gcov_time (void) | |
656 { | |
657 struct stat status; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
658 |
0 | 659 if (fstat (fileno (gcov_var.file), &status)) |
660 return 0; | |
661 else | |
662 return status.st_mtime; | |
663 } | |
664 #endif /* IN_GCOV */ |