On Tue, Jun 12, 2012 at 06:12:39AM -0600, Eric Blake wrote: > 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().
This is where we (musl vs glibc and perhaps you) have very different design philosophies. Using a single non-switchable buffer simplifies all the stdio code paths a lot, and reduces the cost of unget/get cycles. I wouldn't look fondly on changing this for the sake of supporting something that the standard says applications can't rely upon. Moreover, our stdio, aside from functions like fopen/fclose that affect the open file list, are intentionally async-signal-safe provided that the same FILE is not used in the signal handler and the interrupted code. Of course the standard doesn't require this, but I think this non-mandated behavior is a lot more useful certain developers (possibly embedded/realtime folks targetting exactly one OS/libc/piece of hardware) than arbitrary-length ungetc. The reason I mention all this is to point out that "implementations could just all do X and conform to our expectations" is often not as simple as it sounds. Some implementations are just bad, but others have very conscious decisions to do things differently, some of which may be incompatible with the changes you would expect to be easy. Rich