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.
14 static void munge_stream(register FILE *stream
, unsigned char *buf
)
16 stream
->__bufend
= stream
->__bufstart
= buf
;
17 __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream
);
18 __STDIO_STREAM_DISABLE_GETC(stream
);
19 __STDIO_STREAM_DISABLE_PUTC(stream
);
22 wint_t fgetwc_unlocked(register FILE *stream
)
28 unsigned char sbuf
[1];
30 __STDIO_STREAM_VALIDATE(stream
);
32 wi
= WEOF
; /* Prepare for failure. */
34 if (__STDIO_STREAM_IS_WIDE_READING(stream
)
35 || !__STDIO_STREAM_TRANS_TO_READ(stream
, __FLAG_WIDE
)
37 if (stream
->__modeflags
& __FLAG_UNGOT
) { /* Any ungetwc()s? */
38 if (((stream
->__modeflags
& 1) || stream
->__ungot
[1])) {
39 stream
->__ungot_width
[0] = 0; /* Application ungot... */
40 } else { /* scanf ungot */
41 stream
->__ungot_width
[0] = stream
->__ungot_width
[1];
44 wi
= stream
->__ungot
[(stream
->__modeflags
--) & 1];
45 stream
->__ungot
[1] = 0;
49 if (!stream
->__bufstart
) { /* Ugh... stream isn't buffered! */
50 /* Munge the stream temporarily to use a 1-byte buffer. */
51 munge_stream(stream
, sbuf
);
55 if (stream
->__state
.__mask
== 0) { /* If last was a complete char */
56 stream
->__ungot_width
[0] = 0; /* then reset the width. */
60 if ((n
= __STDIO_STREAM_BUFFER_RAVAIL(stream
)) == 0) {
64 r
= mbrtowc(wc
, (const char*) stream
->__bufpos
, n
, &stream
->__state
);
65 if (((ssize_t
) r
) >= 0) { /* Success... */
66 if (r
== 0) { /* Nul wide char... means 0 byte for us so */
67 ++r
; /* increment r and handle below as single. */
69 stream
->__bufpos
+= r
;
70 stream
->__ungot_width
[0] += r
;
75 if (r
== ((size_t) -2)) {
76 /* Potentially valid but incomplete and no more buffered. */
77 stream
->__bufpos
+= n
; /* Update bufpos for stream. */
78 stream
->__ungot_width
[0] += n
;
80 if(__STDIO_FILL_READ_BUFFER(stream
)) { /* Refill succeeded? */
83 if (!__FERROR_UNLOCKED(stream
)) { /* EOF with no error. */
84 if (!stream
->__state
.__mask
) { /* No partial wchar. */
87 /* EOF but partially complete wchar. */
88 /* TODO: should EILSEQ be set? */
93 /* If we reach here, either r == ((size_t)-1) and mbrtowc set errno
94 * to EILSEQ, or r == ((size_t)-2) and stream is in an error state
95 * or at EOF with a partially complete wchar. Make sure stream's
96 * error indicator is set. */
97 stream
->__modeflags
|= __FLAG_ERROR
;
100 if (stream
->__bufstart
== sbuf
) { /* Need to un-munge the stream. */
101 munge_stream(stream
, NULL
);
106 __STDIO_STREAM_VALIDATE(stream
);
110 libc_hidden_def(fgetwc_unlocked
)
112 strong_alias(fgetwc_unlocked
,getwc_unlocked
)
113 #ifndef __UCLIBC_HAS_THREADS__
114 strong_alias(fgetwc_unlocked
,fgetwc
)
115 libc_hidden_def(fgetwc
)
117 strong_alias(fgetwc_unlocked
,getwc
)
120 #elif defined __UCLIBC_HAS_THREADS__
122 wint_t fgetwc(register FILE *stream
)
125 __STDIO_AUTO_THREADLOCK_VAR
;
127 __STDIO_AUTO_THREADLOCK(stream
);
129 retval
= fgetwc_unlocked(stream
);
131 __STDIO_AUTO_THREADUNLOCK(stream
);
135 libc_hidden_def(fgetwc
)
137 strong_alias(fgetwc
,getwc
)