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
signature.asc
Description: OpenPGP digital signature