diff options
Diffstat (limited to 'libc/stdio/fgetc.c')
-rw-r--r-- | libc/stdio/fgetc.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/libc/stdio/fgetc.c b/libc/stdio/fgetc.c new file mode 100644 index 000000000..c672d9fe9 --- /dev/null +++ b/libc/stdio/fgetc.c @@ -0,0 +1,98 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org> + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef fgetc +#undef fgetc_unlocked +#undef getc +#undef getc_unlocked + +extern int __fgetc_unlocked(FILE *stream); + +#ifdef __DO_UNLOCKED + +weak_alias(__fgetc_unlocked,fgetc_unlocked); +weak_alias(__fgetc_unlocked,getc_unlocked); +#ifndef __UCLIBC_HAS_THREADS__ +weak_alias(__fgetc_unlocked,fgetc); +weak_alias(__fgetc_unlocked,getc); +#endif + +int __fgetc_unlocked(FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + /* First the fast path. We're good to go if getc macro enabled. */ + if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream)) { + return __STDIO_STREAM_BUFFER_GET(stream); + } + + /* Next quickest... reading and narrow oriented, but macro + * disabled and/or buffer is exhausted. */ + if (__STDIO_STREAM_IS_NARROW_READING(stream) + || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW) + ) { + if (stream->__modeflags & __FLAG_UNGOT) { /* Use ungots first. */ + unsigned char uc = stream->__ungot[(stream->__modeflags--) & 1]; + stream->__ungot[1] = 0; + __STDIO_STREAM_VALIDATE(stream); + return uc; + } + + if (__STDIO_STREAM_BUFFER_RAVAIL(stream)) { /* Have buffered? */ + return __STDIO_STREAM_BUFFER_GET(stream); + } + + /* Is this a fake stream for *sscanf? */ + if (__STDIO_STREAM_IS_FAKE_VSSCANF(stream)) { + __STDIO_STREAM_SET_EOF(stream); + return EOF; + } + + /* We need to read from the host environment, so we must + * flush all line buffered streams if the stream is not + * fully buffered. */ + if (!__STDIO_STREAM_IS_FBF(stream)) { + __STDIO_FLUSH_LBF_STREAMS; + } + + if (__STDIO_STREAM_BUFFER_SIZE(stream)) { /* Do we have a buffer? */ + __STDIO_STREAM_DISABLE_GETC(stream); + if(__STDIO_FILL_READ_BUFFER(stream)) { /* Refill succeeded? */ + __STDIO_STREAM_ENABLE_GETC(stream); /* FBF or LBF */ + return __STDIO_STREAM_BUFFER_GET(stream); + } + } else { + unsigned char uc; + if (__stdio_READ(stream, &uc, 1)) { + return uc; + } + } + } + + return EOF; +} + +#elif defined __UCLIBC_HAS_THREADS__ + +weak_alias(fgetc,getc); + +int fgetc(register FILE *stream) +{ + if (stream->__user_locking != 0) { + return __GETC_UNLOCKED_MACRO(stream); + } else { + int retval; + __STDIO_ALWAYS_THREADLOCK(stream); + retval = __GETC_UNLOCKED_MACRO(stream); + __STDIO_ALWAYS_THREADUNLOCK(stream); + return retval; + } +} + +#endif |