[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Austin group ruling on ungetc vs. fflush
From: |
Bruno Haible |
Subject: |
Re: Austin group ruling on ungetc vs. fflush |
Date: |
Fri, 16 Jan 2009 02:09:06 +0100 |
User-agent: |
KMail/1.9.9 |
This makes fflush after ungetc work on BSD systems.
2009-01-15 Bruno Haible <address@hidden>
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.
*** lib/fflush.c.orig 2009-01-16 02:05:12.000000000 +0100
--- lib/fflush.c 2009-01-16 01:39:32.000000000 +0100
***************
*** 31,52 ****
#undef fflush
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 (HASUB (fp))
{
fp_->_p += fp_->_r;
fp_->_r = 0;
}
! #endif
}
#if (defined __sferror || defined __DragonFly__) && defined __SNPT /*
FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
static inline int
--- 31,75 ----
#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 __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 */
static inline int
***************
*** 104,112 ****
if (stream == NULL || ! freading (stream))
return fflush (stream);
! /* Clear the ungetc buffer.
! This is needed before fetching the file-position indicator, because
1) The file position indicator is incremented by fgetc() and decremented
by ungetc():
<http://www.opengroup.org/susv3/functions/fgetc.html>
--- 127,141 ----
if (stream == NULL || ! freading (stream))
return fflush (stream);
! #if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS,
Haiku, Linux libc5 */
!
! clear_ungetc_buffer_preserving_position (stream);
!
! 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,137 ****
"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
/* POSIX does not specify fflush behavior for non-seekable input
streams. Some implementations purge unread data, some return
--- 148,159 ----
"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."
! 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,148 ****
--- 165,173 ----
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. */
- Austin group ruling on ungetc vs. fflush, Eric Blake, 2009/01/09
- Re: Austin group ruling on ungetc vs. fflush, Bruno Haible, 2009/01/15
- Re: Austin group ruling on ungetc vs. fflush, Eric Blake, 2009/01/15
- Re: Austin group ruling on ungetc vs. fflush, Bruno Haible, 2009/01/17
- Re: Austin group ruling on ungetc vs. fflush, Eric Blake, 2009/01/17
- Re: Austin group ruling on ungetc vs. fflush, Bruno Haible, 2009/01/17
Re: Austin group ruling on ungetc vs. fflush, Bruno Haible, 2009/01/15