bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: fflush after ungetc


From: Eric Blake
Subject: Re: fflush after ungetc
Date: Fri, 7 Mar 2008 03:41:16 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Bruno Haible <bruno <at> clisp.org> writes:

> 
> Eric Blake wrote:
> > Newlib has two bugs - first, fflush is failing to discard ungetc data when
> > changing the underlying fd offset.
> 
> This bug is common to all BSD and AT&T Unix derived implementations. For BSD
> systems, I'm committing this fix. For AT&T Unix derived implementations, I
> don't see an easy fix.

I'm not sure I agree with your patch - I'm starting to waffle on what POSIX 
requires.  Maybe it's worth asking the Austin Group after all?

But even if we keep your patch unchanged in semantics, it has some nits:

> +   /* 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>
> +           "The file-position indicator is decremented by each successful
> +            call to ungetc()..."
> +         <http://www.opengroup.org/susv3/functions/ungetc.html>
> +           "... the fgetc() function shall ... advance the associated file
> +         position indicator for the stream ..."

Swapped comments.

>   @code{fflush} on an input stream changes the position of the stream to the
>   end of the previous buffer, on some platforms: mingw.
> + @item
> + @code{fflush} on an input stream right after @code{ungetc} does not discard
> + the @code{ungetc} buffer, on some platforms:
> + MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, Cygwin.
> + Cygwin.
>   @end itemize

Cygwin listed twice.  But be aware that there was a change in cygwin behavior 
from 1.5.25-10 to 1.5.25-11, due to this thread.



Now, on to my waffling:

>   /* Check that fflush after a non-backup ungetc() call discards the ungetc
>      buffer.  This is mandated by POSIX
>      <http://www.opengroup.org/susv3/functions/ungetc.html>:
>        "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."  */

fflush neither reads nor discards pushed-back bytes (ungetc states that only 
fseek, fsetpos, and rewind discard bytes).

>   /* Here the file-position indicator must be 2.  */
> 
>   c = ungetc ('@', stdin);
>   ASSERT (c == '@');
> 
>   fflush (stdin);
> 
>   /* Here the file-position indicator must be 2 again.  */

I'm not sure I like these semantics.  I would almost rather have the file-
position indicator be 1 at this point, but with fseek(stdin,0,SEEK_CUR) 
resetting it to 2 (since fseek discards the ungetc data).


> 
>   c = fgetc (stdin);
>   ASSERT (c == '/');

But then I'm not sure whether this means that this read would result in '!' 
(the original byte at position 1 - HP-UX 11 and cygwin 1.5.25-11 behavior), '@' 
(the pushed back byte - MacOS X and glibc pipe behavior), or '/' (the byte at 
position 2 - glibc seek behavior).

I guess the reason that I want position 1, not 2, is that when you ungetc with 
what you just read (rather than with arbitrary data), you are stating that you 
want the next process in the pipeline that uses the underlying file description 
to consume that byte because you didn't want it after all.  But since ungetc is 
not allowed to change the underlying file contents, if you push back something 
other than what you read before going on to the next process, the next process 
cannot read the modified byte (MacOS).   I guess it boils down to whether the 
next process should reread the original byte (HP-UX) or assume that you 
consumed it after all by pushing random data (glibc seek).

ungetc is just a portability pitfall - maybe we're just better off documenting 
that portable programs never call more than one ungetc on a stream, and never 
with a byte different than what was read (even though this is more restrictive 
than what C99 guarantees); although this still doesn't fix the HP-UX pipe bug 
for not even allowing one byte of ungetc.

-- 
Eric Blake






reply via email to

[Prev in Thread] Current Thread [Next in Thread]