fgetwc.c revision 103676
1133819Stjr/*- 2133819Stjr * Copyright (c) 2002 Tim J. Robbins. 3133819Stjr * All rights reserved. 4133819Stjr * 5133819Stjr * Redistribution and use in source and binary forms, with or without 6210432Skib * modification, are permitted provided that the following conditions 7133819Stjr * are met: 8133819Stjr * 1. Redistributions of source code must retain the above copyright 9133819Stjr * notice, this list of conditions and the following disclaimer. 10133819Stjr * 2. Redistributions in binary form must reproduce the above copyright 11133819Stjr * notice, this list of conditions and the following disclaimer in the 12133819Stjr * documentation and/or other materials provided with the distribution. 13133819Stjr * 14177999Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15164199Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16133819Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17133819Stjr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18161330Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19161330Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20133819Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21133819Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22133819Stjr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23133819Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24133819Stjr * SUCH DAMAGE. 25133819Stjr */ 26133819Stjr 27133819Stjr#include <sys/cdefs.h> 28133819Stjr__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetwc.c 103676 2002-09-20 13:20:41Z tjr $"); 29133819Stjr 30133819Stjr#include "namespace.h" 31133819Stjr#include <errno.h> 32133819Stjr#include <stdio.h> 33133819Stjr#include <stdlib.h> 34133819Stjr#include <wchar.h> 35143198Ssobomax#include "un-namespace.h" 36133819Stjr#include "libc_private.h" 37133819Stjr#include "local.h" 38133819Stjr 39133819Stjrstatic __inline wint_t __fgetwc_nbf(FILE *); 40133819Stjr 41133819Stjr/* 42133819Stjr * Non-MT-safe version. 43133819Stjr */ 44133819Stjrwint_t 45133819Stjr__fgetwc(FILE *fp) 46133819Stjr{ 47133819Stjr wint_t wc; 48133819Stjr 49133819Stjr if (MB_CUR_MAX == 1) { 50133819Stjr /* 51133819Stjr * Assume we're using a single-byte locale. A safer test 52133819Stjr * might be to check _CurrentRuneLocale->encoding. 53133819Stjr */ 54133819Stjr wc = (wint_t)__sgetc(fp); 55133819Stjr } else 56133819Stjr wc = __fgetwc_nbf(fp); 57133819Stjr 58133819Stjr return (wc); 59133819Stjr} 60133819Stjr 61133819Stjr/* 62210432Skib * MT-safe version. 63210432Skib */ 64133819Stjrwint_t 65133819Stjrfgetwc(FILE *fp) 66133819Stjr{ 67133819Stjr wint_t r; 68133819Stjr 69133819Stjr FLOCKFILE(fp); 70133819Stjr ORIENT(fp, 1); 71133819Stjr r = __fgetwc(fp); 72133819Stjr FUNLOCKFILE(fp); 73133819Stjr 74133819Stjr return (r); 75133819Stjr} 76133819Stjr 77133819Stjrstatic __inline wint_t 78133819Stjr__fgetwc_nbf(FILE *fp) 79133819Stjr{ 80133819Stjr char buf[MB_LEN_MAX]; 81133819Stjr mbstate_t mbs; 82133819Stjr size_t n, nconv; 83133819Stjr int c; 84133819Stjr wchar_t wc; 85156919Snetchild 86156919Snetchild n = 0; 87156919Snetchild while (n < MB_CUR_MAX) { 88156919Snetchild if ((c = __sgetc(fp)) == EOF) { 89133819Stjr if (n == 0) 90133819Stjr return (WEOF); 91133819Stjr break; 92133819Stjr } 93133819Stjr buf[n++] = (char)c; 94133819Stjr memset(&mbs, 0, sizeof(mbs)); 95133819Stjr nconv = mbrtowc(&wc, buf, n, &mbs); 96133819Stjr if (nconv == n) 97133819Stjr return (wc); 98133819Stjr else if (nconv == 0) 99133819Stjr return (L'\0'); 100133819Stjr else if (nconv == (size_t)-1) 101133819Stjr break; 102133819Stjr } 103133819Stjr 104133819Stjr while (n-- != 0) 105133819Stjr __ungetc((unsigned char)buf[n], fp); 106133819Stjr errno = EILSEQ; 107133819Stjr return (WEOF); 108133819Stjr} 109133819Stjr