bug-gnulib
[Top][All Lists]
Advanced

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

Re: gnulib portability issues


From: Eric Blake
Subject: Re: gnulib portability issues
Date: Tue, 12 Jun 2012 06:12:39 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20120430 Thunderbird/12.0.1

On 06/12/2012 01:04 AM, Ben Pfaff wrote:
> Eric Blake <address@hidden> 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   address@hidden    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

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