19a747e4fSDavid du Colombier #include <plan9.h>
29a747e4fSDavid du Colombier
39a747e4fSDavid du Colombier char *argv0;
49a747e4fSDavid du Colombier enum
59a747e4fSDavid du Colombier {
69a747e4fSDavid du Colombier Bit1 = 7,
79a747e4fSDavid du Colombier Bitx = 6,
89a747e4fSDavid du Colombier Bit2 = 5,
99a747e4fSDavid du Colombier Bit3 = 4,
109a747e4fSDavid du Colombier Bit4 = 3,
119a747e4fSDavid du Colombier
129a747e4fSDavid du Colombier T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */
139a747e4fSDavid du Colombier Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
149a747e4fSDavid du Colombier T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
159a747e4fSDavid du Colombier T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
169a747e4fSDavid du Colombier T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
17*82726826SDavid du Colombier T5 = ((1<<(Bit5+1))-1) ^ 0xFF, /* 1111 1000 */
189a747e4fSDavid du Colombier
19*82726826SDavid du Colombier Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0000 0000 0111 1111 */
20*82726826SDavid du Colombier Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0000 0000 0111 1111 1111 */
21*82726826SDavid du Colombier Rune3 = (1<<(Bit3+2*Bitx))-1, /* 0000 0000 1111 1111 1111 1111 */
22*82726826SDavid du Colombier Rune4 = (1<<(Bit4+3*Bitx))-1, /* 0001 1111 1111 1111 1111 1111 */
23*82726826SDavid du Colombier
249a747e4fSDavid du Colombier
259a747e4fSDavid du Colombier Maskx = (1<<Bitx)-1, /* 0011 1111 */
269a747e4fSDavid du Colombier Testx = Maskx ^ 0xFF, /* 1100 0000 */
279a747e4fSDavid du Colombier
28*82726826SDavid du Colombier SurrogateMin = 0xD800,
29*82726826SDavid du Colombier SurrogateMax = 0xDFFF,
30*82726826SDavid du Colombier
319a747e4fSDavid du Colombier Bad = Runeerror
329a747e4fSDavid du Colombier };
339a747e4fSDavid du Colombier
349a747e4fSDavid du Colombier int
chartorune(Rune * rune,char * str)359a747e4fSDavid du Colombier chartorune(Rune *rune, char *str)
369a747e4fSDavid du Colombier {
37*82726826SDavid du Colombier int c, c1, c2, c3;
389a747e4fSDavid du Colombier long l;
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier /*
419a747e4fSDavid du Colombier * one character sequence
429a747e4fSDavid du Colombier * 00000-0007F => T1
439a747e4fSDavid du Colombier */
449a747e4fSDavid du Colombier c = *(uchar*)str;
459a747e4fSDavid du Colombier if(c < Tx) {
469a747e4fSDavid du Colombier *rune = c;
479a747e4fSDavid du Colombier return 1;
489a747e4fSDavid du Colombier }
499a747e4fSDavid du Colombier
509a747e4fSDavid du Colombier /*
519a747e4fSDavid du Colombier * two character sequence
52*82726826SDavid du Colombier * 00080-007FF => T2 Tx
539a747e4fSDavid du Colombier */
549a747e4fSDavid du Colombier c1 = *(uchar*)(str+1) ^ Tx;
559a747e4fSDavid du Colombier if(c1 & Testx)
569a747e4fSDavid du Colombier goto bad;
579a747e4fSDavid du Colombier if(c < T3) {
589a747e4fSDavid du Colombier if(c < T2)
599a747e4fSDavid du Colombier goto bad;
609a747e4fSDavid du Colombier l = ((c << Bitx) | c1) & Rune2;
619a747e4fSDavid du Colombier if(l <= Rune1)
629a747e4fSDavid du Colombier goto bad;
639a747e4fSDavid du Colombier *rune = l;
649a747e4fSDavid du Colombier return 2;
659a747e4fSDavid du Colombier }
669a747e4fSDavid du Colombier
679a747e4fSDavid du Colombier /*
689a747e4fSDavid du Colombier * three character sequence
69*82726826SDavid du Colombier * 00800-0FFFF => T3 Tx Tx
709a747e4fSDavid du Colombier */
719a747e4fSDavid du Colombier c2 = *(uchar*)(str+2) ^ Tx;
72*82726826SDavid du Colombier
739a747e4fSDavid du Colombier if(c2 & Testx)
749a747e4fSDavid du Colombier goto bad;
759a747e4fSDavid du Colombier if(c < T4) {
769a747e4fSDavid du Colombier l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
779a747e4fSDavid du Colombier if(l <= Rune2)
789a747e4fSDavid du Colombier goto bad;
79*82726826SDavid du Colombier if (SurrogateMin <= l && l <= SurrogateMax)
80*82726826SDavid du Colombier goto bad;
819a747e4fSDavid du Colombier *rune = l;
829a747e4fSDavid du Colombier return 3;
839a747e4fSDavid du Colombier }
849a747e4fSDavid du Colombier
859a747e4fSDavid du Colombier /*
86*82726826SDavid du Colombier * four character sequence
87*82726826SDavid du Colombier * 10000-10FFFF => T4 Tx Tx Tx
88*82726826SDavid du Colombier */
89*82726826SDavid du Colombier if(UTFmax >= 4) {
90*82726826SDavid du Colombier c3 = *(uchar*)(str+3) ^ Tx;
91*82726826SDavid du Colombier if(c3 & Testx)
92*82726826SDavid du Colombier goto bad;
93*82726826SDavid du Colombier if(c < T5) {
94*82726826SDavid du Colombier l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
95*82726826SDavid du Colombier if(l <= Rune3)
96*82726826SDavid du Colombier goto bad;
97*82726826SDavid du Colombier if(l > Runemax)
98*82726826SDavid du Colombier goto bad;
99*82726826SDavid du Colombier *rune = l;
100*82726826SDavid du Colombier return 4;
101*82726826SDavid du Colombier }
102*82726826SDavid du Colombier }
103*82726826SDavid du Colombier
104*82726826SDavid du Colombier /*
1059a747e4fSDavid du Colombier * bad decoding
1069a747e4fSDavid du Colombier */
1079a747e4fSDavid du Colombier bad:
1089a747e4fSDavid du Colombier *rune = Bad;
1099a747e4fSDavid du Colombier return 1;
1109a747e4fSDavid du Colombier }
1119a747e4fSDavid du Colombier
1129a747e4fSDavid du Colombier int
runetochar(char * str,Rune * rune)1139a747e4fSDavid du Colombier runetochar(char *str, Rune *rune)
1149a747e4fSDavid du Colombier {
1159a747e4fSDavid du Colombier long c;
1169a747e4fSDavid du Colombier
1179a747e4fSDavid du Colombier /*
1189a747e4fSDavid du Colombier * one character sequence
1199a747e4fSDavid du Colombier * 00000-0007F => 00-7F
1209a747e4fSDavid du Colombier */
1219a747e4fSDavid du Colombier c = *rune;
1229a747e4fSDavid du Colombier if(c <= Rune1) {
1239a747e4fSDavid du Colombier str[0] = c;
1249a747e4fSDavid du Colombier return 1;
1259a747e4fSDavid du Colombier }
1269a747e4fSDavid du Colombier
1279a747e4fSDavid du Colombier /*
1289a747e4fSDavid du Colombier * two character sequence
1299a747e4fSDavid du Colombier * 0080-07FF => T2 Tx
1309a747e4fSDavid du Colombier */
1319a747e4fSDavid du Colombier if(c <= Rune2) {
1329a747e4fSDavid du Colombier str[0] = T2 | (c >> 1*Bitx);
1339a747e4fSDavid du Colombier str[1] = Tx | (c & Maskx);
1349a747e4fSDavid du Colombier return 2;
1359a747e4fSDavid du Colombier }
136*82726826SDavid du Colombier /*
137*82726826SDavid du Colombier * If the Rune is out of range or a surrogate half, convert it to the error rune.
138*82726826SDavid du Colombier * Do this test here because the error rune encodes to three bytes.
139*82726826SDavid du Colombier * Doing it earlier would duplicate work, since an out of range
140*82726826SDavid du Colombier * Rune wouldn't have fit in one or two bytes.
141*82726826SDavid du Colombier */
142*82726826SDavid du Colombier if (c > Runemax)
143*82726826SDavid du Colombier c = Runeerror;
144*82726826SDavid du Colombier if (SurrogateMin <= c && c <= SurrogateMax)
145*82726826SDavid du Colombier c = Runeerror;
1469a747e4fSDavid du Colombier
1479a747e4fSDavid du Colombier /*
1489a747e4fSDavid du Colombier * three character sequence
1499a747e4fSDavid du Colombier * 0800-FFFF => T3 Tx Tx
1509a747e4fSDavid du Colombier */
151*82726826SDavid du Colombier if (c <= Rune3) {
1529a747e4fSDavid du Colombier str[0] = T3 | (c >> 2*Bitx);
1539a747e4fSDavid du Colombier str[1] = Tx | ((c >> 1*Bitx) & Maskx);
1549a747e4fSDavid du Colombier str[2] = Tx | (c & Maskx);
1559a747e4fSDavid du Colombier return 3;
1569a747e4fSDavid du Colombier }
1579a747e4fSDavid du Colombier
158*82726826SDavid du Colombier /*
159*82726826SDavid du Colombier * four character sequence (21-bit value)
160*82726826SDavid du Colombier * 10000-1FFFFF => T4 Tx Tx Tx
161*82726826SDavid du Colombier */
162*82726826SDavid du Colombier str[0] = T4 | (c >> 3*Bitx);
163*82726826SDavid du Colombier str[1] = Tx | ((c >> 2*Bitx) & Maskx);
164*82726826SDavid du Colombier str[2] = Tx | ((c >> 1*Bitx) & Maskx);
165*82726826SDavid du Colombier str[3] = Tx | (c & Maskx);
166*82726826SDavid du Colombier return 4;
167*82726826SDavid du Colombier }
168*82726826SDavid du Colombier
1699a747e4fSDavid du Colombier int
runelen(long c)1709a747e4fSDavid du Colombier runelen(long c)
1719a747e4fSDavid du Colombier {
1729a747e4fSDavid du Colombier Rune rune;
1739a747e4fSDavid du Colombier char str[10];
1749a747e4fSDavid du Colombier
1759a747e4fSDavid du Colombier rune = c;
1769a747e4fSDavid du Colombier return runetochar(str, &rune);
1779a747e4fSDavid du Colombier }
1789a747e4fSDavid du Colombier
1799a747e4fSDavid du Colombier int
utflen(char * s)1809a747e4fSDavid du Colombier utflen(char *s)
1819a747e4fSDavid du Colombier {
1829a747e4fSDavid du Colombier int c;
1839a747e4fSDavid du Colombier long n;
1849a747e4fSDavid du Colombier Rune rune;
1859a747e4fSDavid du Colombier
1869a747e4fSDavid du Colombier n = 0;
1879a747e4fSDavid du Colombier for(;;) {
1889a747e4fSDavid du Colombier c = *(uchar*)s;
1899a747e4fSDavid du Colombier if(c < Runeself) {
1909a747e4fSDavid du Colombier if(c == 0)
1919a747e4fSDavid du Colombier return n;
1929a747e4fSDavid du Colombier s++;
1939a747e4fSDavid du Colombier } else
1949a747e4fSDavid du Colombier s += chartorune(&rune, s);
1959a747e4fSDavid du Colombier n++;
1969a747e4fSDavid du Colombier }
1979a747e4fSDavid du Colombier return 0;
1989a747e4fSDavid du Colombier }
199