blob: d900928b2c1ca2d382499af3c19d4466309e6544 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
/* 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)
|