scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

 1#include <errno.h>
 2#include <stdlib.h>
 3#include <string.h>
 4#include <wchar.h>
 5
 6#include "../libc.h"
 7
 8#undef mbrtowc
 9
10size_t
11mbrtowc(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;
20
21	if (!ps)
22		ps  = &state;
23
24	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;
32
33	oc = ps->oc;
34	wc = ps->wc;
35	sh = ps->sh;
36
37	/* initial state? */
38	if (sh == 0) {
39		/* NUL character? */
40		if ((c = wc = *t) == 0)
41			goto return_code;
42		t++;
43		n--;
44
45		/* fast track for ascii? */
46		if (c < 0x80)
47			goto return_code;
48
49		/* out of sequence multibyte? */
50		if ((c & 0xc0) != 0xc0)
51			goto return_error;
52
53		/* in sequence multibyte! */
54		oc = c << 1;
55		wc = 0;
56		sh = 1;
57	}
58
59	for ( ; n > 0; --n) {
60		if (sh > MB_CUR_MAX)
61			goto return_error;
62
63		c = *t++;
64		if ((c & 0xc0) != 0x80)
65			goto return_error;
66
67		wc <<= 6;
68		wc |= c & 0x3f;
69		oc <<= 1;
70		sh++;
71
72		if ((oc & 0x80) == 0) {
73			oc = (oc & 0xff) >> sh;
74			wc |= oc << (sh-1) * 6;
75	
76			if (!_validutf8(wc, &max) || sh != max)
77				goto return_error;
78			goto return_code_set;
79		}
80	}
81
82	ps->sh = sh;
83	ps->oc = oc;
84	ps->wc = wc;
85	return -2;
86
87return_code_set:
88	memset(ps, 0, sizeof(*ps));
89return_code:
90	if (pwc)
91		*pwc = wc;
92	return t - (unsigned char *) s;
93
94return_error:
95	memset(ps, 0, sizeof(*ps));
96	errno = EILSEQ;
97	return -1;
98}