Mercurial > hg > octave-lyh > gnulib-hg
changeset 11018:8a3de59b56aa
Make fflush-after-ungetc POSIX compliant on BSD systems.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Fri, 16 Jan 2009 02:07:53 +0100 |
parents | 95eb3a6eb21d |
children | 7b796798b7bb |
files | ChangeLog lib/fflush.c |
diffstat | 2 files changed, 55 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-01-15 Bruno Haible <bruno@clisp.org> + + Make fflush-after-ungetc POSIX compliant on BSD systems. + * lib/fflush.c (clear_ungetc_buffer_preserving_position): New function. + (clear_ungetc_buffer): Implement also for other systems. + (rpl_fflush): On glibc systems, invoke + clear_ungetc_buffer_preserving_position. Otherwise, invoke + clear_ungetc_buffer after fetching the stream's position, not before. + 2009-01-15 Bruno Haible <bruno@clisp.org> Make fflush-after-ungetc POSIX compliant on glibc systems.
--- a/lib/fflush.c +++ b/lib/fflush.c @@ -31,21 +31,44 @@ #undef fflush + +#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */ + +/* Clear the stream's ungetc buffer, preserving the value of ftello (fp). */ +static inline void +clear_ungetc_buffer_preserving_position (FILE *fp) +{ + if (fp->_flags & _IO_IN_BACKUP) + /* _IO_free_backup_area is a bit complicated. Simply call fseek. */ + fseek (fp, 0, SEEK_CUR); +} + +#else + +/* Clear the stream's ungetc buffer. May modify the value of ftello (fp). */ static inline void clear_ungetc_buffer (FILE *fp) { -#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */ - if (fp->_flags & _IO_IN_BACKUP) - /* _IO_free_backup_area is a bit complicated. Simply call fseek. */ - fseek (fp, 0, SEEK_CUR); -#elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */ +# if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */ if (HASUB (fp)) { fp_->_p += fp_->_r; fp_->_r = 0; } +# elif defined __EMX__ /* emx+gcc */ + if (fp->_ungetc_count > 0) + { + fp->_ungetc_count = 0; + fp->_rcount = - fp->_rcount; + } +# elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */ + /* Nothing to do. */ +# else /* other implementations */ + fseek (fp, 0, SEEK_CUR); +# endif +} + #endif -} #if (defined __sferror || defined __DragonFly__) && defined __SNPT /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */ @@ -104,9 +127,15 @@ if (stream == NULL || ! freading (stream)) return fflush (stream); - /* Clear the ungetc buffer. +#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */ + + clear_ungetc_buffer_preserving_position (stream); - This is needed before fetching the file-position indicator, because + return fflush (stream); + +#else + + /* Notes about the file-position indicator: 1) The file position indicator is incremented by fgetc() and decremented by ungetc(): <http://www.opengroup.org/susv3/functions/fgetc.html> @@ -119,19 +148,12 @@ "The value of the file-position indicator for the stream after reading or discarding all pushed-back bytes shall be the same as it was before the bytes were pushed back." - 3) Here we are discarding all pushed-back bytes. - - Unfortunately it is impossible to implement this on platforms with - _IOERR, because an ungetc() on this platform prepends the pushed-back - bytes to the buffer without an indication of the limit between the - pushed-back bytes and the read-ahead bytes. */ - clear_ungetc_buffer (stream); - -#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */ - - return fflush (stream); - -#else + Here we are discarding all pushed-back bytes. But more specifically, + 3) <http://www.opengroup.org/austin/aardvark/latest/xshbug3.txt> says: + "[After fflush(),] the file offset of the underlying open file + description shall be set to the file position of the stream, and + any characters pushed back onto the stream by ungetc() ... shall + be discarded." */ /* POSIX does not specify fflush behavior for non-seekable input streams. Some implementations purge unread data, some return @@ -143,6 +165,9 @@ return EOF; } + /* Clear the ungetc buffer. */ + clear_ungetc_buffer (stream); + /* To get here, we must be flushing a seekable input stream, so the semantics of fpurge are now appropriate to clear the buffer. To avoid losing data, the lseek is also necessary. */