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