1101776Stjr/*- 2129583Stjr * Copyright (c) 2002-2004 Tim J. Robbins. 3101776Stjr * All rights reserved. 4101776Stjr * 5227753Stheraven * Copyright (c) 2011 The FreeBSD Foundation 6227753Stheraven * All rights reserved. 7227753Stheraven * Portions of this software were developed by David Chisnall 8227753Stheraven * under sponsorship from the FreeBSD Foundation. 9227753Stheraven * 10101776Stjr * Redistribution and use in source and binary forms, with or without 11101776Stjr * modification, are permitted provided that the following conditions 12101776Stjr * are met: 13101776Stjr * 1. Redistributions of source code must retain the above copyright 14101776Stjr * notice, this list of conditions and the following disclaimer. 15101776Stjr * 2. Redistributions in binary form must reproduce the above copyright 16101776Stjr * notice, this list of conditions and the following disclaimer in the 17101776Stjr * documentation and/or other materials provided with the distribution. 18101776Stjr * 19101776Stjr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20101776Stjr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21101776Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22101776Stjr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23101776Stjr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24101776Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25101776Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26101776Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27101776Stjr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28101776Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29101776Stjr * SUCH DAMAGE. 30101776Stjr */ 31101776Stjr 32101776Stjr#include <sys/cdefs.h> 33101776Stjr__FBSDID("$FreeBSD$"); 34101776Stjr 35101776Stjr#include "namespace.h" 36101776Stjr#include <errno.h> 37101776Stjr#include <stdio.h> 38103523Stjr#include <stdlib.h> 39101776Stjr#include <wchar.h> 40101776Stjr#include "un-namespace.h" 41101776Stjr#include "libc_private.h" 42101776Stjr#include "local.h" 43132442Stjr#include "mblocal.h" 44227753Stheraven#include "xlocale_private.h" 45101776Stjr 46103676Stjr/* 47103676Stjr * MT-safe version. 48103676Stjr */ 49103676Stjrwint_t 50227753Stheravenfgetwc_l(FILE *fp, locale_t locale) 51103676Stjr{ 52103676Stjr wint_t r; 53227753Stheraven FIX_LOCALE(locale); 54103676Stjr 55103676Stjr FLOCKFILE(fp); 56103676Stjr ORIENT(fp, 1); 57227753Stheraven r = __fgetwc(fp, locale); 58103676Stjr FUNLOCKFILE(fp); 59103676Stjr 60103676Stjr return (r); 61103676Stjr} 62234799Sdas 63227753Stheravenwint_t 64227753Stheravenfgetwc(FILE *fp) 65227753Stheraven{ 66227753Stheraven return fgetwc_l(fp, __get_locale()); 67227753Stheraven} 68103676Stjr 69131880Stjr/* 70234799Sdas * Internal (non-MPSAFE) version of fgetwc(). This version takes an 71234799Sdas * mbstate_t argument specifying the initial conversion state. For 72234799Sdas * wide streams, this should always be fp->_mbstate. On return, *nread 73234799Sdas * is set to the number of bytes read. 74131880Stjr */ 75234799Sdaswint_t 76234799Sdas__fgetwc_mbs(FILE *fp, mbstate_t *mbs, int *nread, locale_t locale) 77103539Stjr{ 78103523Stjr wchar_t wc; 79129584Stjr size_t nconv; 80227753Stheraven struct xlocale_ctype *l = XLOCALE_CTYPE(locale); 81101776Stjr 82234799Sdas if (fp->_r <= 0 && __srefill(fp)) { 83234799Sdas *nread = 0; 84129584Stjr return (WEOF); 85234799Sdas } 86131880Stjr if (MB_CUR_MAX == 1) { 87131880Stjr /* Fast path for single-byte encodings. */ 88131880Stjr wc = *fp->_p++; 89131880Stjr fp->_r--; 90234799Sdas *nread = 1; 91131880Stjr return (wc); 92131880Stjr } 93234799Sdas *nread = 0; 94129584Stjr do { 95234799Sdas nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, mbs); 96129584Stjr if (nconv == (size_t)-1) 97103523Stjr break; 98129584Stjr else if (nconv == (size_t)-2) 99129583Stjr continue; 100129584Stjr else if (nconv == 0) { 101129584Stjr fp->_p++; 102129584Stjr fp->_r--; 103234799Sdas (*nread)++; 104103523Stjr return (L'\0'); 105129584Stjr } else { 106129584Stjr fp->_p += nconv; 107129584Stjr fp->_r -= nconv; 108234799Sdas *nread += nconv; 109129583Stjr return (wc); 110129584Stjr } 111129584Stjr } while (__srefill(fp) == 0); 112129583Stjr fp->_flags |= __SERR; 113103523Stjr errno = EILSEQ; 114103523Stjr return (WEOF); 115101776Stjr} 116