1 /* fpurge - Flushing buffers of a FILE stream. */
3 /* Copyright (C) 2007-2010 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
27 /* Specification. Same as in ../../externs.h. */
28 #define NEED_FPURGE_DECL
30 # define fpurge _bash_fpurge
32 extern int fpurge __P((FILE *stream));
34 #if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
35 # include <stdio_ext.h>
39 /* Inline contents of gnulib:stdio-impl.h */
41 /* Many stdio implementations have the same logic and therefore can share
42 the same implementation of stdio extension API, except that some fields
43 have different naming conventions, or their access requires some casts. */
45 /* BSD stdio derived implementations. */
47 #if defined __NetBSD__ /* NetBSD */
48 /* Get __NetBSD_Version__. */
49 # include <sys/param.h>
52 #if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
54 # if defined __DragonFly__ /* DragonFly */
55 /* See <http://www.dragonflybsd.org/cvsweb/src/lib/libc/stdio/priv_stdio.h?rev=HEAD&content-type=text/x-cvsweb-markup>. */
56 # define fp_ ((struct { struct __FILE_public pub; \
57 struct { unsigned char *_base; int _size; } _bf; \
63 struct { unsigned char *_base; int _size; } _ub; \
65 unsigned char _ubuf[3]; \
66 unsigned char _nbuf[1]; \
67 struct { unsigned char *_base; int _size; } _lb; \
70 /* More fields, not relevant here. */ \
72 /* See <http://www.dragonflybsd.org/cvsweb/src/include/stdio.h?rev=HEAD&content-type=text/x-cvsweb-markup>. */
74 # define _flags pub._flags
81 # if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ /* NetBSD >= 1.5ZA, OpenBSD */
82 /* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
83 and <http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup> */
86 struct __sbuf _ub; /* ungetc buffer */
87 /* More fields, not relevant here. */
89 # define fp_ub ((struct __sfileext *) fp->_ext._base)->_ub
90 # else /* FreeBSD, NetBSD <= 1.5Z, DragonFly, MacOS X, Cygwin */
91 # define fp_ub fp_->_ub
94 # define HASUB(fp) (fp_ub._base != NULL)
98 /* SystemV derived implementations. */
102 # if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */
103 # define fp_ ((struct { unsigned char *_ptr; \
104 unsigned char *_base; \
105 unsigned char *_end; \
108 unsigned int _flag; \
114 # if defined _SCO_DS /* OpenServer */
117 # define _base __base
118 # define _flag __flag
126 #if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
129 /* The __fpurge function does not have a return value. */
132 #elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin 1.7 */
134 /* Call the system's fpurge function. */
136 # if !HAVE_DECL_FPURGE
137 extern int fpurge (FILE *);
139 int result = fpurge (fp);
140 # if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
142 /* Correct the invariants that fpurge broke.
143 <stdio.h> on BSD systems says:
144 "The following always hold: if _flags & __SRD, _w is 0."
145 If this invariant is not fulfilled and the stream is read-write but
146 currently reading, subsequent putc or fputc calls will write directly
147 into the buffer, although they shouldn't be allowed to. */
148 if ((fp_->_flags & __SRD) != 0)
155 /* Most systems provide FILE as a struct and the necessary bitmask in
156 <stdio.h>, because they need it for implementing getc() and putc() as
158 # if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
159 fp->_IO_read_end = fp->_IO_read_ptr;
160 fp->_IO_write_ptr = fp->_IO_write_base;
161 /* Avoid memory leak when there is an active ungetc buffer. */
162 if (fp->_IO_save_base != NULL)
164 free (fp->_IO_save_base);
165 fp->_IO_save_base = NULL;
168 # elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
169 fp_->_p = fp_->_bf._base;
171 fp_->_w = ((fp_->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
174 /* Avoid memory leak when there is an active ungetc buffer. */
175 if (fp_ub._base != NULL)
177 if (fp_ub._base != fp_->_ubuf)
182 # elif defined __EMX__ /* emx+gcc */
183 fp->_ptr = fp->_buffer;
186 fp->_ungetc_count = 0;
188 # elif defined _IOERR || defined __TANDEM /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */
189 fp->_ptr = fp->_base;
190 if (fp->_ptr != NULL)
193 # elif defined __UCLIBC__ /* uClibc */
194 # ifdef __STDIO_BUFFERS
195 if (fp->__modeflags & __FLAG_WRITING)
196 fp->__bufpos = fp->__bufstart;
197 else if (fp->__modeflags & (__FLAG_READONLY | __FLAG_READING))
198 fp->__bufpos = fp->__bufread;
201 # elif defined __QNX__ /* QNX */
202 fp->_Rback = fp->_Back + sizeof (fp->_Back);
204 if (fp->_Mode & 0x2000 /* _MWRITE */)
205 /* fp->_Buf <= fp->_Next <= fp->_Wend */
206 fp->_Next = fp->_Buf;
208 /* fp->_Buf <= fp->_Next <= fp->_Rend */
209 fp->_Rend = fp->_Next;
211 # elif defined __MINT__ /* Atari FreeMiNT */
212 if (fp->__pushed_back)
214 fp->__bufp = fp->__pushback_bufp;
215 fp->__pushed_back = 0;
217 /* Preserve the current file position. */
218 if (fp->__target != -1)
219 fp->__target += fp->__bufp - fp->__buffer;
220 fp->__bufp = fp->__buffer;
221 /* Nothing in the buffer, next getc is nontrivial. */
222 fp->__get_limit = fp->__bufp;
223 /* Nothing in the buffer, next putc is nontrivial. */
224 fp->__put_limit = fp->__buffer;
227 # warning "Please port gnulib fpurge.c to your platform! Look at the definitions of fflush, setvbuf and ungetc on your system, then report this to bug-gnulib."