| 1 | #include <stdlib.h> |
| 2 | #include <wchar.h> |
| 3 | #include <errno.h> |
| 4 | #include "internal.h" |
| 5 | |
| 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 size_t 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 | } |