On 06/12/2012 01:04 AM, Ben Pfaff wrote:
> Eric Blake <ebl...@redhat.com> writes:
> 
>> Wrong.  Pretty much every libc out there lets you ungetc() more than one
>> byte.
> 
> Does that include glibc?  Then there is a bug in the manual,
> which says:
> 
>         The GNU C library only supports one character of
>         pushback—in other words, it does not work to call ungetc
>         twice without doing input in between.
> 
> in the description of ungetc().

That's the glibc documentation and I agree it is inaccurate; the Linux
man-pages project is better:

       ungetc() pushes c back to stream, cast to unsigned char,  where
it  is
       available  for subsequent read operations.  Pushed-back
characters will
       be returned in reverse order; only one pushback is guaranteed.

And this simple program proves that most libc know how to push back more
than one byte, whether or not they differ from the original contents,
and especially in the common case where the byte still fits in the
buffer.  It's the corner case where the bytes being pushed back differ
from the backing store, and where they don't fit in the normal buffer
(perhaps because you have used setvbuf or friends), and therefore libc
has to malloc() some pushback storage, and if the malloc fails then so
does the ungetc().

$ cat foo.c
#include <stdio.h>
int main(void)
{
    char buf[10];
    if (fseek(stdin, 0, SEEK_CUR))
        return 1;
    if (fread(buf, 1, sizeof(buf), stdin) != 10)
        return 2;
    if (ungetc(buf[9], stdin) != buf[9])
        return 3;
    if (ungetc(buf[8], stdin) != buf[8])
        return 4;
    if (getchar() != buf[8])
        return 5;
    if (getchar() != buf[9])
        return 6;
    if (ungetc(buf[9] + 1, stdin) != buf[9] + 1)
        return 7;
    if (ungetc(buf[8] + 1, stdin) != buf[8] + 1)
        return 8;
    if (getchar() != buf[8] + 1)
        return 9;
    if (getchar() != buf[9] + 1)
        return 10;
    return 0;
}
$ ./foo < foo.c; echo $?
0

-- 
Eric Blake   ebl...@redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to