1 /* $MirOS: src/lib/libc/stdio/fgetwc.c,v 1.7 2008/08/01 23:50:01 tg Exp $ */
2 /* $OpenBSD: fgetwc.c,v 1.1 2005/06/17 20:40:32 espie Exp $	*/
3 /* $NetBSD: fgetwc.c,v 1.3 2003/03/07 07:11:36 tshiozak Exp $ */
4 
5 /*-
6  * Copyright (c) 2007, 2008 Thorsten Glaser
7  * Copyright (c)2001 Citrus Project,
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $Citrus$
32  */
33 
34 #include <errno.h>
35 #include <stdbool.h>
36 #include <stdio.h>
37 #include <wchar.h>
38 #include "local.h"
39 
40 __RCSID("$MirOS: src/lib/libc/stdio/fgetwc.c,v 1.7 2008/08/01 23:50:01 tg Exp $");
41 
42 wint_t __fgetwc_unlock(FILE *);
43 
44 wint_t
__fgetwc_unlock(FILE * fp)45 __fgetwc_unlock(FILE *fp)
46 {
47 	struct wchar_io_data *wcio;
48 	mbstate_t *st;
49 	wchar_t wc;
50 	size_t size;
51 
52 	_SET_ORIENTATION(fp, 1);
53 	wcio = WCIO_GET(fp);
54 	if (wcio == 0) {
55 		errno = ENOMEM;
56 		return WEOF;
57 	}
58 
59 	/* if there're ungetwc'ed wchars, use them */
60 	if (wcio->wcio_ungetwc_inbuf) {
61 		wc = wcio->wcio_ungetwc_buf[--wcio->wcio_ungetwc_inbuf];
62 
63 		return wc;
64 	}
65 
66 	st = &wcio->wcio_mbstate_in;
67 
68 	do {
69 		char c;
70 		int ch = __sgetc(fp);
71 
72 		if (ch == EOF) {
73 			if (optu8to16(&wc, NULL, 0, st) == 0)
74 				return (wc);
75 			return WEOF;
76 		}
77 
78 		c = ch;
79 		size = optu8to16(&wc, &c, 1, st);
80 		if (size == 0) {
81 			ungetc(ch, fp);
82 			return (wc);
83 		}
84 	} while (size == (size_t)-2);
85 
86 	return wc;
87 }
88 
89 wint_t
fgetwc(FILE * fp)90 fgetwc(FILE *fp)
91 {
92 	wint_t r;
93 
94 	flockfile(fp);
95 	r = __fgetwc_unlock(fp);
96 	funlockfile(fp);
97 
98 	return (r);
99 }
100