1570af302Sopenharmony_ci#include <stdlib.h> 2570af302Sopenharmony_ci#include <wchar.h> 3570af302Sopenharmony_ci#include <errno.h> 4570af302Sopenharmony_ci#include "internal.h" 5570af302Sopenharmony_ci 6570af302Sopenharmony_cisize_t mbrtowc(wchar_t *restrict wc, const char *restrict src, size_t n, mbstate_t *restrict st) 7570af302Sopenharmony_ci{ 8570af302Sopenharmony_ci static unsigned internal_state; 9570af302Sopenharmony_ci unsigned c; 10570af302Sopenharmony_ci const unsigned char *s = (const void *)src; 11570af302Sopenharmony_ci const size_t N = n; 12570af302Sopenharmony_ci wchar_t dummy; 13570af302Sopenharmony_ci 14570af302Sopenharmony_ci if (!st) st = (void *)&internal_state; 15570af302Sopenharmony_ci c = *(unsigned *)st; 16570af302Sopenharmony_ci 17570af302Sopenharmony_ci if (!s) { 18570af302Sopenharmony_ci if (c) goto ilseq; 19570af302Sopenharmony_ci return 0; 20570af302Sopenharmony_ci } else if (!wc) wc = &dummy; 21570af302Sopenharmony_ci 22570af302Sopenharmony_ci if (!n) return -2; 23570af302Sopenharmony_ci if (!c) { 24570af302Sopenharmony_ci if (*s < 0x80) return !!(*wc = *s); 25570af302Sopenharmony_ci if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1; 26570af302Sopenharmony_ci if (*s-SA > SB-SA) goto ilseq; 27570af302Sopenharmony_ci c = bittab[*s++-SA]; n--; 28570af302Sopenharmony_ci } 29570af302Sopenharmony_ci 30570af302Sopenharmony_ci if (n) { 31570af302Sopenharmony_ci if (OOB(c,*s)) goto ilseq; 32570af302Sopenharmony_ciloop: 33570af302Sopenharmony_ci c = c<<6 | *s++-0x80; n--; 34570af302Sopenharmony_ci if (!(c&(1U<<31))) { 35570af302Sopenharmony_ci *(unsigned *)st = 0; 36570af302Sopenharmony_ci *wc = c; 37570af302Sopenharmony_ci return N-n; 38570af302Sopenharmony_ci } 39570af302Sopenharmony_ci if (n) { 40570af302Sopenharmony_ci if (*s-0x80u >= 0x40) goto ilseq; 41570af302Sopenharmony_ci goto loop; 42570af302Sopenharmony_ci } 43570af302Sopenharmony_ci } 44570af302Sopenharmony_ci 45570af302Sopenharmony_ci *(unsigned *)st = c; 46570af302Sopenharmony_ci return -2; 47570af302Sopenharmony_ciilseq: 48570af302Sopenharmony_ci *(unsigned *)st = 0; 49570af302Sopenharmony_ci errno = EILSEQ; 50570af302Sopenharmony_ci return -1; 51570af302Sopenharmony_ci} 52