12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- /* 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"
- /* Having ungotten characters implies the stream is reading.
- * The scheme used here treats the least significant 2 bits of
- * the stream's modeflags member as follows:
- * 0 0 Not currently reading.
- * 0 1 Reading, but no ungetc() or scanf() push back chars.
- * 1 0 Reading with one ungetc() char (ungot[1] is 1)
- * or one scanf() pushed back char (ungot[1] is 0).
- * 1 1 Reading with both an ungetc() char and a scanf()
- * pushed back char. Note that this must be the result
- * of a scanf() push back (in ungot[0]) _followed_ by
- * an ungetc() call (in ungot[1]).
- *
- * Notes:
- * scanf() can NOT use ungetc() to push back characters.
- * (See section 7.19.6.2 of the C9X rationale -- WG14/N897.)
- */
- /* libc_hidden_proto(ungetc) */
- int ungetc(int c, register FILE *stream)
- {
- __STDIO_AUTO_THREADLOCK_VAR;
- __STDIO_AUTO_THREADLOCK(stream);
- __STDIO_STREAM_VALIDATE(stream);
- #ifdef __UCLIBC_MJN3_ONLY__
- #warning CONSIDER: Make fast ungetc an option?
- #endif
- #ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
- /* If buffered narrow reading with no ungot slots filled, and if not
- * ungetting a different char than the one last read from the buffer,
- * we can simply decrement the position and not worry about disabling
- * the getc macros. This will cut down on overhead in applications
- * that use getc/ungetc extensively (like gcc). */
- /* NOTE: If we can use getc, then we are buffered narrow reading with
- * no ungot slots filled. */
- if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream)
- && (c != EOF)
- && (stream->__bufpos > stream->__bufstart)
- && (stream->__bufpos[-1] == ((unsigned char)c))
- ) {
- --stream->__bufpos;
- __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */
- } else
- #endif
- /* Note: Even if c == EOF, we need to initialize/verify the
- * stream's orientation and ensure the stream is in reading
- * mode (if readable and properly oriented). */
- if ((!__STDIO_STREAM_IS_NARROW_READING(stream)
- && __STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW))
- || ((stream->__modeflags & __FLAG_UNGOT)
- && ((stream->__modeflags & 1) || stream->__ungot[1]))
- ) {
- c = EOF;
- } else if (c != EOF) {
- __STDIO_STREAM_DISABLE_GETC(stream);
- /* Flag this as a user ungot, as scanf does the necessary fixup. */
- stream->__ungot[1] = 1;
- stream->__ungot[(++stream->__modeflags) & 1] = c;
- __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */
- }
- __STDIO_STREAM_VALIDATE(stream);
- __STDIO_AUTO_THREADUNLOCK(stream);
- return c;
- }
- libc_hidden_def(ungetc)
|