fxlibc/src/libc/stdio/ungetc.c

54 lines
1.3 KiB
C

#include <stdio.h>
#include <errno.h>
#include <string.h>
#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;
}