rewrite popen to use posix_spawn instead of fragile vfork hacks
[musl] / src / stdio / fgetwc.c
1 #include "stdio_impl.h"
2 #include <wchar.h>
3 #include <errno.h>
4
5 wint_t __fgetwc_unlocked(FILE *f)
6 {
7         mbstate_t st = { 0 };
8         wchar_t wc;
9         int c;
10         unsigned char b;
11         size_t l;
12
13         f->mode |= f->mode+1;
14
15         /* Convert character from buffer if possible */
16         if (f->rpos < f->rend) {
17                 l = mbrtowc(&wc, (void *)f->rpos, f->rend - f->rpos, &st);
18                 if (l+2 >= 2) {
19                         f->rpos += l + !l; /* l==0 means 1 byte, null */
20                         return wc;
21                 }
22                 if (l == -1) {
23                         f->rpos++;
24                         return WEOF;
25                 }
26         } else l = -2;
27
28         /* Convert character byte-by-byte */
29         while (l == -2) {
30                 b = c = getc_unlocked(f);
31                 if (c < 0) {
32                         if (!mbsinit(&st)) errno = EILSEQ;
33                         return WEOF;
34                 }
35                 l = mbrtowc(&wc, (void *)&b, 1, &st);
36                 if (l == -1) return WEOF;
37         }
38
39         return wc;
40 }
41
42 wint_t fgetwc(FILE *f)
43 {
44         wint_t c;
45         FLOCK(f);
46         c = __fgetwc_unlocked(f);
47         FUNLOCK(f);
48         return c;
49 }
50
51 weak_alias(__fgetwc_unlocked, fgetwc_unlocked);
52 weak_alias(__fgetwc_unlocked, getwc_unlocked);