1 #include <stdlib.h>
2 #include <wchar.h>
3 #include <errno.h>
4 #include "internal.h"
5 
mbrtowc(wchar_t * restrict wc,const char * restrict src,size_t n,mbstate_t * restrict st)6 size_t mbrtowc(wchar_t *restrict wc, const char *restrict src, size_t n, mbstate_t *restrict st)
7 {
8 	static unsigned internal_state;
9 	unsigned c;
10 	const unsigned char *s = (const void *)src;
11 	const unsigned N = n;
12 	wchar_t dummy;
13 
14 	if (!st) st = (void *)&internal_state;
15 	c = *(unsigned *)st;
16 
17 	if (!s) {
18 		if (c) goto ilseq;
19 		return 0;
20 	} else if (!wc) wc = &dummy;
21 
22 	if (!n) return -2;
23 	if (!c) {
24 		if (*s < 0x80) return !!(*wc = *s);
25 		if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1;
26 		if (*s-SA > SB-SA) goto ilseq;
27 		c = bittab[*s++-SA]; n--;
28 	}
29 
30 	if (n) {
31 		if (OOB(c,*s)) goto ilseq;
32 loop:
33 		c = c<<6 | *s++-0x80; n--;
34 		if (!(c&(1U<<31))) {
35 			*(unsigned *)st = 0;
36 			*wc = c;
37 			return N-n;
38 		}
39 		if (n) {
40 			if (*s-0x80u >= 0x40) goto ilseq;
41 			goto loop;
42 		}
43 	}
44 
45 	*(unsigned *)st = c;
46 	return -2;
47 ilseq:
48 	*(unsigned *)st = 0;
49 	errno = EILSEQ;
50 	return -1;
51 }
52