On Fri, Apr 28, 2017 at 12:44:52PM +0200, Johannes Schindelin wrote: > > Also, what is the behavior of ungetc when we pass it EOF? > > According to the documentation, it would cast EOF to an unsigned char and > push that back. Definitely incorrect. > > > It looks like POSIX does what we want (pushing EOF is a noop, and the > > stream retains its feof() status), but I don't know if there are other > > implementations to worry about. > > That's not what my man page here says: > > 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. POSIX covers this this case explicitly: If the value of c equals that of the macro EOF, the operation shall fail and the input stream shall be left unchanged. That comes straight from C99, which says: If the value of c equals that of the macro EOF, the operation fails and the input stream is unchanged. I don't have a copy of C89 handy, but I didn't see any mention of the behavior in the "changes from the previous edition" section of C99. So it's possible that there's an implementation that is unhappy with ungetc(EOF), but unless we know of one specifically, it seems pretty safe. Given that and the similar explicit rule for EOF via isspace(), I think the original code actually behaves fine. Of course, we do not use the standard isspace() anyway. Our implementation will cast the EOF to an unsigned char. If it's "-1", that ends up as 255, which matches no classes. But if the platform has an oddball EOF like 288, that would confuse our isspace(). -Peff