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