| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 | /* 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"libc_hidden_proto(fgetwc_unlocked)libc_hidden_proto(mbrtowc)#ifdef __DO_UNLOCKEDstatic 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, 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__libc_hidden_proto(fgetwc)strong_alias(fgetwc_unlocked,fgetwc)libc_hidden_def(fgetwc)strong_alias(fgetwc_unlocked,getwc)#endif#elif defined __UCLIBC_HAS_THREADS__libc_hidden_proto(fgetwc)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
 |