annotate lib/freadseek.c @ 17605:23cb5b2fd95b

relocatable-perl: like relocatable-script, but for Perl scripts * build-aux/relocatable.pl.in: Add. * doc/relocatable-maint.texi: Add documentation. * modules/relocatable-perl: Add.
author Reuben Thomas <rrt@sc3d.org>
date Thu, 09 Jan 2014 22:31:42 +0000
parents 344018b6e5d7
children ab58d4870664
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1 /* Skipping input from a FILE stream.
17587
344018b6e5d7 maint: update copyright
Eric Blake <eblake@redhat.com>
parents: 17249
diff changeset
2 Copyright (C) 2007-2014 Free Software Foundation, Inc.
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
4 This program is free software: you can redistribute it and/or modify
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
5 it under the terms of the GNU General Public License as published by
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
6 the Free Software Foundation; either version 3 of the License, or
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
7 (at your option) any later version.
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
8
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
9 This program is distributed in the hope that it will be useful,
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
12 GNU General Public License for more details.
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
13
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
14 You should have received a copy of the GNU General Public License
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
16
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
17 #include <config.h>
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
18
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
19 /* Specification. */
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
20 #include "freadseek.h"
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
21
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
22 #include <stdlib.h>
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
23 #include <unistd.h>
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
24
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
25 #include "freadahead.h"
9819
9ccce8a9bf52 Pass test-freadseek on cygwin.
Eric Blake <ebb9@byu.net>
parents: 9738
diff changeset
26 #include "freadptr.h"
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
27
9980
2c1ba629f5d5 New private include file lib/stdio-impl.h.
Bruno Haible <bruno@clisp.org>
parents: 9928
diff changeset
28 #include "stdio-impl.h"
2c1ba629f5d5 New private include file lib/stdio-impl.h.
Bruno Haible <bruno@clisp.org>
parents: 9928
diff changeset
29
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
30 /* Increment the in-memory pointer. INCREMENT must be at most the buffer size
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
31 returned by freadptr().
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
32 This is very cheap (no system calls). */
17185
dd46d4e6beea dup, execute, fatal-signal, etc.: no 'static inline'
Paul Eggert <eggert@cs.ucla.edu>
parents: 16935
diff changeset
33 static void
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
34 freadptrinc (FILE *fp, size_t increment)
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
35 {
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
36 /* Keep this code in sync with freadptr! */
16916
3d02d25fa13d stdioext: Add support for musl libc.
Bruno Haible <bruno@clisp.org>
parents: 16344
diff changeset
37 #if HAVE___FREADPTRINC /* musl libc */
3d02d25fa13d stdioext: Add support for musl libc.
Bruno Haible <bruno@clisp.org>
parents: 16344
diff changeset
38 __freadptrinc (fp, increment);
3d02d25fa13d stdioext: Add support for musl libc.
Bruno Haible <bruno@clisp.org>
parents: 16344
diff changeset
39 #elif defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
40 fp->_IO_read_ptr += increment;
16935
498a2211d839 Write "Mac OS X" instead of "MacOS X".
Bruno Haible <bruno@clisp.org>
parents: 16916
diff changeset
41 #elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin */
9981
e3d6988a9347 Add tentative support for DragonFly BSD.
Bruno Haible <bruno@clisp.org>
parents: 9980
diff changeset
42 fp_->_p += increment;
e3d6988a9347 Add tentative support for DragonFly BSD.
Bruno Haible <bruno@clisp.org>
parents: 9980
diff changeset
43 fp_->_r -= increment;
9881
e21211210418 Port the extended stdio functions to emx+gcc.
Bruno Haible <bruno@clisp.org>
parents: 9876
diff changeset
44 #elif defined __EMX__ /* emx+gcc */
e21211210418 Port the extended stdio functions to emx+gcc.
Bruno Haible <bruno@clisp.org>
parents: 9876
diff changeset
45 fp->_ptr += increment;
e21211210418 Port the extended stdio functions to emx+gcc.
Bruno Haible <bruno@clisp.org>
parents: 9876
diff changeset
46 fp->_rcount -= increment;
15485
20a2699b8a90 stdioext: Add support for Minix.
Bruno Haible <bruno@clisp.org>
parents: 14079
diff changeset
47 #elif defined __minix /* Minix */
20a2699b8a90 stdioext: Add support for Minix.
Bruno Haible <bruno@clisp.org>
parents: 14079
diff changeset
48 fp_->_ptr += increment;
20a2699b8a90 stdioext: Add support for Minix.
Bruno Haible <bruno@clisp.org>
parents: 14079
diff changeset
49 fp_->_count -= increment;
13997
6fa9f46e6153 Port extended stdio modules to HP NonStop Kernel.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
50 #elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, NonStop Kernel */
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
51 fp_->_ptr += increment;
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
52 fp_->_cnt -= increment;
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
53 #elif defined __UCLIBC__ /* uClibc */
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
54 # ifdef __STDIO_BUFFERS
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
55 fp->__bufpos += increment;
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
56 # else
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
57 abort ();
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
58 # endif
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
59 #elif defined __QNX__ /* QNX */
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
60 fp->_Next += increment;
11236
d4475bf2a2bf Add tentative support for FreeMiNT.
Bruno Haible <bruno@clisp.org>
parents: 10780
diff changeset
61 #elif defined __MINT__ /* Atari FreeMiNT */
d4475bf2a2bf Add tentative support for FreeMiNT.
Bruno Haible <bruno@clisp.org>
parents: 10780
diff changeset
62 fp->__bufp += increment;
16344
ecfc57537d99 stdioext: Add tentative support for Plan9.
Bruno Haible <bruno@clisp.org>
parents: 16201
diff changeset
63 #elif defined EPLAN9 /* Plan9 */
ecfc57537d99 stdioext: Add tentative support for Plan9.
Bruno Haible <bruno@clisp.org>
parents: 16201
diff changeset
64 fp->rp += increment;
10404
4611578c5669 Add conditional code for SLOW_BUT_NO_HACKS.
Bruno Haible <bruno@clisp.org>
parents: 9981
diff changeset
65 #elif defined SLOW_BUT_NO_HACKS /* users can define this */
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
66 #else
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
67 #error "Please port gnulib freadseek.c to your platform! Look at the definition of getc, getc_unlocked on your system, then report this to bug-gnulib."
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
68 #endif
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
69 }
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
70
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
71 int
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
72 freadseek (FILE *fp, size_t offset)
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
73 {
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
74 size_t total_buffered;
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
75 int fd;
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
76
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
77 if (offset == 0)
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
78 return 0;
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
79
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
80 /* Seek over the already read and buffered input as quickly as possible,
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
81 without doing any system calls. */
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
82 total_buffered = freadahead (fp);
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
83 /* This loop is usually executed at most twice: once for ungetc buffer (if
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
84 present) and once for the main buffer. */
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
85 while (total_buffered > 0)
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
86 {
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
87 size_t buffered;
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
88
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
89 if (freadptr (fp, &buffered) != NULL && buffered > 0)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
90 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
91 size_t increment = (buffered < offset ? buffered : offset);
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
92
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
93 freadptrinc (fp, increment);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
94 offset -= increment;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
95 if (offset == 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
96 return 0;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
97 total_buffered -= increment;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
98 if (total_buffered == 0)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
99 break;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
100 }
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
101 /* Read one byte. If we were reading from the ungetc buffer, this
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
102 switches the stream back to the main buffer. */
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
103 if (fgetc (fp) == EOF)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
104 goto eof;
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
105 offset--;
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
106 if (offset == 0)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
107 return 0;
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
108 total_buffered--;
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
109 }
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
110
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
111 /* Test whether the stream is seekable or not. */
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
112 fd = fileno (fp);
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
113 if (fd >= 0 && lseek (fd, 0, SEEK_CUR) >= 0)
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
114 {
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
115 /* FP refers to a regular file. fseek is most efficient in this case. */
12255
83ddd76ac091 fflush, freadseek: use fseeko, not fseek
Eric Blake <ebb9@byu.net>
parents: 11236
diff changeset
116 return fseeko (fp, offset, SEEK_CUR);
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
117 }
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
118 else
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
119 {
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
120 /* FP is a non-seekable stream, possibly not even referring to a file
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
121 descriptor. Read OFFSET bytes explicitly and discard them. */
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
122 char buf[4096];
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
123
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
124 do
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
125 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
126 size_t count = (sizeof (buf) < offset ? sizeof (buf) : offset);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
127 if (fread (buf, 1, count, fp) < count)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
128 goto eof;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
129 offset -= count;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12255
diff changeset
130 }
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
131 while (offset > 0);
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
132
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
133 return 0;
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
134 }
9826
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
135
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
136 eof:
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
137 /* EOF, or error before or while reading. */
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
138 if (ferror (fp))
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
139 return EOF;
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
140 else
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
141 /* Encountered EOF. */
c421fead68d3 Improve freadseek's efficiency after ungetc.
Bruno Haible <bruno@clisp.org>
parents: 9825
diff changeset
142 return 0;
9738
923434ebe936 New module 'freadseek'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
143 }