1#include <errno.h>2#include <stdlib.h>3#include <string.h>4#include <wchar.h>56#include "../libc.h"78#undef mbrtowc910size_t11mbrtowc(wchar_t *restrict pwc, const char *restrict s, size_t n,12 mbstate_t *restrict ps)13{14 static mbstate_t state;15 const unsigned char *t = (const unsigned char *) s;16 wchar_t dummy;17 unsigned long wc;18 unsigned c, oc;19 int sh, max;2021 if (!ps)22 ps = &state;2324 if (t == NULL) {25 if (ps->sh != 0)26 goto return_error;27 pwc = &dummy;28 goto return_code_set;29 }30 if (n == 0)31 return -2;3233 oc = ps->oc;34 wc = ps->wc;35 sh = ps->sh;3637 /* initial state? */38 if (sh == 0) {39 /* NUL character? */40 if ((c = wc = *t) == 0)41 goto return_code;42 t++;43 n--;4445 /* fast track for ascii? */46 if (c < 0x80)47 goto return_code;4849 /* out of sequence multibyte? */50 if ((c & 0xc0) != 0xc0)51 goto return_error;5253 /* in sequence multibyte! */54 oc = c << 1;55 wc = 0;56 sh = 1;57 }5859 for ( ; n > 0; --n) {60 if (sh > MB_CUR_MAX)61 goto return_error;6263 c = *t++;64 if ((c & 0xc0) != 0x80)65 goto return_error;6667 wc <<= 6;68 wc |= c & 0x3f;69 oc <<= 1;70 sh++;7172 if ((oc & 0x80) == 0) {73 oc = (oc & 0xff) >> sh;74 wc |= oc << (sh-1) * 6;7576 if (!_validutf8(wc, &max) || sh != max)77 goto return_error;78 goto return_code_set;79 }80 }8182 ps->sh = sh;83 ps->oc = oc;84 ps->wc = wc;85 return -2;8687return_code_set:88 memset(ps, 0, sizeof(*ps));89return_code:90 if (pwc)91 *pwc = wc;92 return t - (unsigned char *) s;9394return_error:95 memset(ps, 0, sizeof(*ps));96 errno = EILSEQ;97 return -1;98}