fgetwc.c revision 103539
160107Sobrien/*- 225689Sjkh * Copyright (c) 2002 Tim J. Robbins. 325689Sjkh * All rights reserved. 425689Sjkh * 5111698Sluigi * Redistribution and use in source and binary forms, with or without 6111698Sluigi * modification, are permitted provided that the following conditions 7270310Sse * are met: 8111698Sluigi * 1. Redistributions of source code must retain the above copyright 9111698Sluigi * notice, this list of conditions and the following disclaimer. 10270310Sse * 2. Redistributions in binary form must reproduce the above copyright 11270310Sse * notice, this list of conditions and the following disclaimer in the 12270310Sse * documentation and/or other materials provided with the distribution. 13111698Sluigi * 1425689Sjkh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15270310Sse * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16270310Sse * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17111698Sluigi * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18111698Sluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19111698Sluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20111698Sluigi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21111698Sluigi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22111698Sluigi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23111698Sluigi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24111698Sluigi * SUCH DAMAGE. 25111698Sluigi */ 26111698Sluigi 27270310Sse#include <sys/cdefs.h> 2814408Sjkh__FBSDID("$FreeBSD: head/lib/libc/stdio/fgetwc.c 103539 2002-09-18 12:17:28Z tjr $"); 2914408Sjkh 3014408Sjkh#include "namespace.h" 3114408Sjkh#include <errno.h> 3214408Sjkh#include <stdio.h> 3314408Sjkh#include <stdlib.h> 34270310Sse#include <wchar.h> 35270310Sse#include "un-namespace.h" 36270310Sse#include "libc_private.h" 37270310Sse#include "local.h" 38270310Sse 39270310Ssestatic __inline wint_t __fgetwc_nbf(FILE *); 40111698Sluigi 41111698Sluigiwint_t 42270310Ssefgetwc(FILE *fp) 43270310Sse{ 44270310Sse wint_t wc; 45270310Sse 4614408Sjkh FLOCKFILE(fp); 4714408Sjkh ORIENT(fp, 1); 48111698Sluigi if (MB_CUR_MAX == 1) { 49111698Sluigi /* 50270310Sse * Assume we're using a single-byte locale. A safer test 51270310Sse * might be to check _CurrentRuneLocale->encoding. 52111698Sluigi */ 53270310Sse wc = (wint_t)__sgetc(fp); 54111698Sluigi } else 55111698Sluigi wc = __fgetwc_nbf(fp); 56270310Sse FUNLOCKFILE(fp); 57270310Sse 58270310Sse return (wc); 5914408Sjkh} 6014408Sjkh 6114408Sjkhstatic __inline wint_t 62270310Sse__fgetwc_nbf(FILE *fp) 63270310Sse{ 64270310Sse char buf[MB_LEN_MAX]; 65270310Sse mbstate_t mbs; 66111698Sluigi size_t n, nconv; 67111698Sluigi int c; 6814408Sjkh wchar_t wc; 69111698Sluigi 7014408Sjkh n = 0; 71270310Sse while (n < MB_CUR_MAX) { 72270310Sse if ((c = __sgetc(fp)) == EOF) { 73270310Sse if (n == 0) 7414408Sjkh return (WEOF); 75270310Sse break; 76270310Sse } 77270310Sse buf[n++] = (char)c; 78270310Sse memset(&mbs, 0, sizeof(mbs)); 79270310Sse nconv = mbrtowc(&wc, buf, n, &mbs); 80270310Sse if (nconv == n) 8114408Sjkh return (wc); 82270310Sse else if (nconv == 0) 83270310Sse return (L'\0'); 84270310Sse else if (nconv == (size_t)-1) 85111698Sluigi break; 8614408Sjkh } 8743334Syokota 8814408Sjkh FUNLOCKFILE(fp); 8932822Syokota while (n-- != 0) 9014408Sjkh ungetc((unsigned char)buf[n], fp); 9114408Sjkh FLOCKFILE(fp); 9214408Sjkh errno = EILSEQ; 9314408Sjkh return (WEOF); 9414408Sjkh} 9514408Sjkh