#include #include #include #include "fileutil.h" int ungetc(int c, FILE *fp) { if(c == EOF) return c; if(!fp->readable) { errno = EINVAL; return EOF; } /* If there is no buffer, create a temporary one */ if(!fp->buf) __fp_set_buffer(fp, NULL, 16); __fp_buffer_mode_read(fp); /* If there is a spot available in the buffer, use it */ if(fp->bufpos > 0) { fp->buf[--fp->bufpos] = c; fp->bufungetc++; fp->eof = 0; return c; } /* Otherwise, make some room. If the buffer is full of ungetc() characters then we can't preserve the semantics, so we fail. */ if(fp->bufungetc >= (int)fp->bufsize) return EOF; /* If the buffer is full, discard read data that isn't ungetc()'d. */ if(fp->bufread >= fp->bufsize) { int discarded = fp->bufread - fp->bufungetc; if(fseek(fp, -discarded, SEEK_CUR)) return EOF; fp->bufread -= discarded; } /* Then move whichever type of read data remains to the very end of the buffer, so we have as much space as possible for more ungetc(). */ memmove(fp->buf + fp->bufsize - fp->bufread, fp->buf, fp->bufread); fp->bufpos = fp->bufsize - fp->bufread; fp->bufread = fp->bufsize; /* Because we've made space, conclude like the first case */ fp->buf[--fp->bufpos] = c; fp->bufungetc++; fp->eof = 0; return c; }