123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- /* 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"
- #ifdef __DO_UNLOCKED
- static void munge_stream(register FILE *stream, unsigned char *buf)
- {
- stream->__bufend = stream->__bufstart = buf;
- __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
- __STDIO_STREAM_DISABLE_GETC(stream);
- __STDIO_STREAM_DISABLE_PUTC(stream);
- }
- wint_t fgetwc_unlocked(register FILE *stream)
- {
- wint_t wi;
- wchar_t wc[1];
- int n;
- size_t r;
- unsigned char sbuf[1];
- __STDIO_STREAM_VALIDATE(stream);
- wi = WEOF; /* Prepare for failure. */
- if (__STDIO_STREAM_IS_WIDE_READING(stream)
- || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_WIDE)
- ) {
- if (stream->__modeflags & __FLAG_UNGOT) { /* Any ungetwc()s? */
- if (((stream->__modeflags & 1) || stream->__ungot[1])) {
- stream->__ungot_width[0] = 0; /* Application ungot... */
- } else { /* scanf ungot */
- stream->__ungot_width[0] = stream->__ungot_width[1];
- }
- wi = stream->__ungot[(stream->__modeflags--) & 1];
- stream->__ungot[1] = 0;
- goto DONE;
- }
- if (!stream->__bufstart) { /* Ugh... stream isn't buffered! */
- /* Munge the stream temporarily to use a 1-byte buffer. */
- munge_stream(stream, sbuf);
- ++stream->__bufend;
- }
- if (stream->__state.__mask == 0) { /* If last was a complete char */
- stream->__ungot_width[0] = 0; /* then reset the width. */
- }
- LOOP:
- if ((n = __STDIO_STREAM_BUFFER_RAVAIL(stream)) == 0) {
- goto FILL_BUFFER;
- }
- r = mbrtowc(wc, (const char*) stream->__bufpos, n, &stream->__state);
- if (((ssize_t) r) >= 0) { /* Success... */
- if (r == 0) { /* Nul wide char... means 0 byte for us so */
- ++r; /* increment r and handle below as single. */
- }
- stream->__bufpos += r;
- stream->__ungot_width[0] += r;
- wi = *wc;
- goto DONE;
- }
- if (r == ((size_t) -2)) {
- /* Potentially valid but incomplete and no more buffered. */
- stream->__bufpos += n; /* Update bufpos for stream. */
- stream->__ungot_width[0] += n;
- FILL_BUFFER:
- if(__STDIO_FILL_READ_BUFFER(stream)) { /* Refill succeeded? */
- goto LOOP;
- }
- if (!__FERROR_UNLOCKED(stream)) { /* EOF with no error. */
- if (!stream->__state.__mask) { /* No partial wchar. */
- goto DONE;
- }
- /* EOF but partially complete wchar. */
- /* TODO: should EILSEQ be set? */
- __set_errno(EILSEQ);
- }
- }
- /* If we reach here, either r == ((size_t)-1) and mbrtowc set errno
- * to EILSEQ, or r == ((size_t)-2) and stream is in an error state
- * or at EOF with a partially complete wchar. Make sure stream's
- * error indicator is set. */
- stream->__modeflags |= __FLAG_ERROR;
- DONE:
- if (stream->__bufstart == sbuf) { /* Need to un-munge the stream. */
- munge_stream(stream, NULL);
- }
- }
- __STDIO_STREAM_VALIDATE(stream);
- return wi;
- }
- libc_hidden_def(fgetwc_unlocked)
- strong_alias(fgetwc_unlocked,getwc_unlocked)
- #ifndef __UCLIBC_HAS_THREADS__
- strong_alias(fgetwc_unlocked,fgetwc)
- libc_hidden_def(fgetwc)
- strong_alias(fgetwc_unlocked,getwc)
- #endif
- #elif defined __UCLIBC_HAS_THREADS__
- wint_t fgetwc(register FILE *stream)
- {
- wint_t retval;
- __STDIO_AUTO_THREADLOCK_VAR;
- __STDIO_AUTO_THREADLOCK(stream);
- retval = fgetwc_unlocked(stream);
- __STDIO_AUTO_THREADUNLOCK(stream);
- return retval;
- }
- libc_hidden_def(fgetwc)
- strong_alias(fgetwc,getwc)
- #endif
|