1570af302Sopenharmony_ci#include <stdlib.h> 2570af302Sopenharmony_ci#include <wchar.h> 3570af302Sopenharmony_ci#include <errno.h> 4570af302Sopenharmony_ci#include "internal.h" 5570af302Sopenharmony_ci 6570af302Sopenharmony_ciint mbtowc(wchar_t *restrict wc, const char *restrict src, size_t n) 7570af302Sopenharmony_ci{ 8570af302Sopenharmony_ci unsigned c; 9570af302Sopenharmony_ci const unsigned char *s = (const void *)src; 10570af302Sopenharmony_ci wchar_t dummy; 11570af302Sopenharmony_ci 12570af302Sopenharmony_ci if (!s) return 0; 13570af302Sopenharmony_ci if (!n) goto ilseq; 14570af302Sopenharmony_ci if (!wc) wc = &dummy; 15570af302Sopenharmony_ci 16570af302Sopenharmony_ci if (*s < 0x80) return !!(*wc = *s); 17570af302Sopenharmony_ci if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1; 18570af302Sopenharmony_ci if (*s-SA > SB-SA) goto ilseq; 19570af302Sopenharmony_ci c = bittab[*s++-SA]; 20570af302Sopenharmony_ci 21570af302Sopenharmony_ci /* Avoid excessive checks against n: If shifting the state n-1 22570af302Sopenharmony_ci * times does not clear the high bit, then the value of n is 23570af302Sopenharmony_ci * insufficient to read a character */ 24570af302Sopenharmony_ci if (n<4 && ((c<<(6*n-6)) & (1U<<31))) goto ilseq; 25570af302Sopenharmony_ci 26570af302Sopenharmony_ci if (OOB(c,*s)) goto ilseq; 27570af302Sopenharmony_ci c = (c<<6) | (*s++-0x80); 28570af302Sopenharmony_ci if (!(c&(1U<<31))) { 29570af302Sopenharmony_ci *wc = c; 30570af302Sopenharmony_ci return 2; 31570af302Sopenharmony_ci } 32570af302Sopenharmony_ci 33570af302Sopenharmony_ci if (*s-0x80u >= 0x40) goto ilseq; 34570af302Sopenharmony_ci c = (c<<6) | (*s++-0x80); 35570af302Sopenharmony_ci if (!(c&(1U<<31))) { 36570af302Sopenharmony_ci *wc = c; 37570af302Sopenharmony_ci return 3; 38570af302Sopenharmony_ci } 39570af302Sopenharmony_ci 40570af302Sopenharmony_ci if (*s-0x80u >= 0x40) goto ilseq; 41570af302Sopenharmony_ci *wc = (c<<6) | (*s++-0x80); 42570af302Sopenharmony_ci return 4; 43570af302Sopenharmony_ci 44570af302Sopenharmony_ciilseq: 45570af302Sopenharmony_ci errno = EILSEQ; 46570af302Sopenharmony_ci return -1; 47570af302Sopenharmony_ci} 48