1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
3 * GNU Library General Public License (LGPL) version 2 or later.
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
10 /* Having ungotten characters implies the stream is reading.
11 * The scheme used here treats the least significant 2 bits of
12 * the stream's modeflags member as follows:
13 * 0 0 Not currently reading.
14 * 0 1 Reading, but no ungetc() or scanf() push back chars.
15 * 1 0 Reading with one ungetc() char (ungot[1] is 1)
16 * or one scanf() pushed back char (ungot[1] is 0).
17 * 1 1 Reading with both an ungetc() char and a scanf()
18 * pushed back char. Note that this must be the result
19 * of a scanf() push back (in ungot[0]) _followed_ by
20 * an ungetc() call (in ungot[1]).
23 * scanf() can NOT use ungetc() to push back characters.
24 * (See section 7.19.6.2 of the C9X rationale -- WG14/N897.)
27 int ungetc(int c
, register FILE *stream
)
29 __STDIO_AUTO_THREADLOCK_VAR
;
31 __STDIO_AUTO_THREADLOCK(stream
);
32 __STDIO_STREAM_VALIDATE(stream
);
34 #ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
35 /* If buffered narrow reading with no ungot slots filled, and if not
36 * ungetting a different char than the one last read from the buffer,
37 * we can simply decrement the position and not worry about disabling
38 * the getc macros. This will cut down on overhead in applications
39 * that use getc/ungetc extensively (like gcc). */
40 /* NOTE: If we can use getc, then we are buffered narrow reading with
41 * no ungot slots filled. */
42 if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream
)
44 && (stream
->__bufpos
> stream
->__bufstart
)
45 && (stream
->__bufpos
[-1] == ((unsigned char)c
))
48 __STDIO_STREAM_CLEAR_EOF(stream
); /* Must clear end-of-file flag. */
51 /* Note: Even if c == EOF, we need to initialize/verify the
52 * stream's orientation and ensure the stream is in reading
53 * mode (if readable and properly oriented). */
54 if ((!__STDIO_STREAM_IS_NARROW_READING(stream
)
55 && __STDIO_STREAM_TRANS_TO_READ(stream
, __FLAG_NARROW
))
56 || ((stream
->__modeflags
& __FLAG_UNGOT
)
57 && ((stream
->__modeflags
& 1) || stream
->__ungot
[1]))
60 } else if (c
!= EOF
) {
61 __STDIO_STREAM_DISABLE_GETC(stream
);
63 /* Flag this as a user ungot, as scanf does the necessary fixup. */
64 stream
->__ungot
[1] = 1;
65 stream
->__ungot
[(++stream
->__modeflags
) & 1] = c
;
67 __STDIO_STREAM_CLEAR_EOF(stream
); /* Must clear end-of-file flag. */
70 __STDIO_STREAM_VALIDATE(stream
);
71 __STDIO_AUTO_THREADUNLOCK(stream
);
75 libc_hidden_def(ungetc
)