xref: /plan9/sys/src/cmd/tcs/html.c (revision 4ac975e2e38b792d24bc60de7fce5e6173f046ea)
18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
38ccd4a63SDavid du Colombier #include <bio.h>
48ccd4a63SDavid du Colombier #include "hdr.h"
58ccd4a63SDavid du Colombier #include "conv.h"
68ccd4a63SDavid du Colombier 
78ccd4a63SDavid du Colombier typedef struct Hchar Hchar;
88ccd4a63SDavid du Colombier struct Hchar
98ccd4a63SDavid du Colombier {
108ccd4a63SDavid du Colombier 	char *s;
118ccd4a63SDavid du Colombier 	Rune r;
128ccd4a63SDavid du Colombier };
138ccd4a63SDavid du Colombier 
148ccd4a63SDavid du Colombier /* &lt;, &gt;, &quot;, &amp; intentionally omitted */
158ccd4a63SDavid du Colombier 
168ccd4a63SDavid du Colombier static Hchar byname[] =
178ccd4a63SDavid du Colombier {
188ccd4a63SDavid du Colombier 	{"AElig", 198},
198ccd4a63SDavid du Colombier 	{"Aacute", 193},
208ccd4a63SDavid du Colombier 	{"Acirc", 194},
218ccd4a63SDavid du Colombier 	{"Agrave", 192},
22*4ac975e2SDavid du Colombier 	{"Alpha", 913},
238ccd4a63SDavid du Colombier 	{"Aring", 197},
248ccd4a63SDavid du Colombier 	{"Atilde", 195},
258ccd4a63SDavid du Colombier 	{"Auml", 196},
26*4ac975e2SDavid du Colombier 	{"Beta", 914},
278ccd4a63SDavid du Colombier 	{"Ccedil", 199},
28*4ac975e2SDavid du Colombier 	{"Chi", 935},
29*4ac975e2SDavid du Colombier 	{"Dagger", 8225},
30*4ac975e2SDavid du Colombier 	{"Delta", 916},
318ccd4a63SDavid du Colombier 	{"ETH", 208},
328ccd4a63SDavid du Colombier 	{"Eacute", 201},
338ccd4a63SDavid du Colombier 	{"Ecirc", 202},
348ccd4a63SDavid du Colombier 	{"Egrave", 200},
35*4ac975e2SDavid du Colombier 	{"Epsilon", 917},
36*4ac975e2SDavid du Colombier 	{"Eta", 919},
378ccd4a63SDavid du Colombier 	{"Euml", 203},
38*4ac975e2SDavid du Colombier 	{"Gamma", 915},
398ccd4a63SDavid du Colombier 	{"Iacute", 205},
408ccd4a63SDavid du Colombier 	{"Icirc", 206},
418ccd4a63SDavid du Colombier 	{"Igrave", 204},
42*4ac975e2SDavid du Colombier 	{"Iota", 921},
438ccd4a63SDavid du Colombier 	{"Iuml", 207},
44*4ac975e2SDavid du Colombier 	{"Kappa", 922},
45*4ac975e2SDavid du Colombier 	{"Lambda", 923},
46*4ac975e2SDavid du Colombier 	{"Mu", 924},
478ccd4a63SDavid du Colombier 	{"Ntilde", 209},
48*4ac975e2SDavid du Colombier 	{"Nu", 925},
49*4ac975e2SDavid du Colombier 	{"OElig", 338},
508ccd4a63SDavid du Colombier 	{"Oacute", 211},
518ccd4a63SDavid du Colombier 	{"Ocirc", 212},
528ccd4a63SDavid du Colombier 	{"Ograve", 210},
53*4ac975e2SDavid du Colombier 	{"Omega", 937},
54*4ac975e2SDavid du Colombier 	{"Omicron", 927},
558ccd4a63SDavid du Colombier 	{"Oslash", 216},
568ccd4a63SDavid du Colombier 	{"Otilde", 213},
578ccd4a63SDavid du Colombier 	{"Ouml", 214},
58*4ac975e2SDavid du Colombier 	{"Phi", 934},
59*4ac975e2SDavid du Colombier 	{"Pi", 928},
60*4ac975e2SDavid du Colombier 	{"Prime", 8243},
61*4ac975e2SDavid du Colombier 	{"Psi", 936},
62*4ac975e2SDavid du Colombier 	{"Rho", 929},
63*4ac975e2SDavid du Colombier 	{"Scaron", 352},
64*4ac975e2SDavid du Colombier 	{"Sigma", 931},
658ccd4a63SDavid du Colombier 	{"THORN", 222},
66*4ac975e2SDavid du Colombier 	{"Tau", 932},
67*4ac975e2SDavid du Colombier 	{"Theta", 920},
688ccd4a63SDavid du Colombier 	{"Uacute", 218},
698ccd4a63SDavid du Colombier 	{"Ucirc", 219},
708ccd4a63SDavid du Colombier 	{"Ugrave", 217},
71*4ac975e2SDavid du Colombier 	{"Upsilon", 933},
728ccd4a63SDavid du Colombier 	{"Uuml", 220},
73*4ac975e2SDavid du Colombier 	{"Xi", 926},
748ccd4a63SDavid du Colombier 	{"Yacute", 221},
75*4ac975e2SDavid du Colombier 	{"Yuml", 376},
76*4ac975e2SDavid du Colombier 	{"Zeta", 918},
778ccd4a63SDavid du Colombier 	{"aacute", 225},
788ccd4a63SDavid du Colombier 	{"acirc", 226},
798ccd4a63SDavid du Colombier 	{"acute", 180},
808ccd4a63SDavid du Colombier 	{"aelig", 230},
818ccd4a63SDavid du Colombier 	{"agrave", 224},
82*4ac975e2SDavid du Colombier 	{"alefsym", 8501},
838ccd4a63SDavid du Colombier 	{"alpha", 945},
84*4ac975e2SDavid du Colombier 	{"amp", 38},
85*4ac975e2SDavid du Colombier 	{"and", 8743},
86*4ac975e2SDavid du Colombier 	{"ang", 8736},
878ccd4a63SDavid du Colombier 	{"aring", 229},
88*4ac975e2SDavid du Colombier 	{"asymp", 8776},
898ccd4a63SDavid du Colombier 	{"atilde", 227},
908ccd4a63SDavid du Colombier 	{"auml", 228},
91*4ac975e2SDavid du Colombier 	{"bdquo", 8222},
928ccd4a63SDavid du Colombier 	{"beta", 946},
938ccd4a63SDavid du Colombier 	{"brvbar", 166},
94*4ac975e2SDavid du Colombier 	{"bull", 8226},
95*4ac975e2SDavid du Colombier 	{"cap", 8745},
968ccd4a63SDavid du Colombier 	{"ccedil", 231},
978ccd4a63SDavid du Colombier 	{"cdots", 8943},
988ccd4a63SDavid du Colombier 	{"cedil", 184},
998ccd4a63SDavid du Colombier 	{"cent", 162},
1008ccd4a63SDavid du Colombier 	{"chi", 967},
101*4ac975e2SDavid du Colombier 	{"circ", 710},
102*4ac975e2SDavid du Colombier 	{"clubs", 9827},
103*4ac975e2SDavid du Colombier 	{"cong", 8773},
1048ccd4a63SDavid du Colombier 	{"copy", 169},
105*4ac975e2SDavid du Colombier 	{"crarr", 8629},
106*4ac975e2SDavid du Colombier 	{"cup", 8746},
1078ccd4a63SDavid du Colombier 	{"curren", 164},
108*4ac975e2SDavid du Colombier 	{"dArr", 8659},
109*4ac975e2SDavid du Colombier 	{"dagger", 8224},
110*4ac975e2SDavid du Colombier 	{"darr", 8595},
1118ccd4a63SDavid du Colombier 	{"ddots", 8945},
1128ccd4a63SDavid du Colombier 	{"deg", 176},
1138ccd4a63SDavid du Colombier 	{"delta", 948},
114*4ac975e2SDavid du Colombier 	{"diams", 9830},
1158ccd4a63SDavid du Colombier 	{"divide", 247},
1168ccd4a63SDavid du Colombier 	{"eacute", 233},
1178ccd4a63SDavid du Colombier 	{"ecirc", 234},
1188ccd4a63SDavid du Colombier 	{"egrave", 232},
1198ccd4a63SDavid du Colombier 	{"emdash", 8212},	/* non-standard but commonly used */
120*4ac975e2SDavid du Colombier 	{"empty", 8709},
1218ccd4a63SDavid du Colombier 	{"emsp", 8195},
1228ccd4a63SDavid du Colombier 	{"endash", 8211},	/* non-standard but commonly used */
1238ccd4a63SDavid du Colombier 	{"ensp", 8194},
1248ccd4a63SDavid du Colombier 	{"epsilon", 949},
125*4ac975e2SDavid du Colombier 	{"equiv", 8801},
1268ccd4a63SDavid du Colombier 	{"eta", 951},
1278ccd4a63SDavid du Colombier 	{"eth", 240},
1288ccd4a63SDavid du Colombier 	{"euml", 235},
129*4ac975e2SDavid du Colombier 	{"euro", 8364},
130*4ac975e2SDavid du Colombier 	{"exist", 8707},
131*4ac975e2SDavid du Colombier 	{"fnof", 402},
132*4ac975e2SDavid du Colombier 	{"forall", 8704},
1338ccd4a63SDavid du Colombier 	{"frac12", 189},
1348ccd4a63SDavid du Colombier 	{"frac14", 188},
1358ccd4a63SDavid du Colombier 	{"frac34", 190},
136*4ac975e2SDavid du Colombier 	{"frasl", 8260},
1378ccd4a63SDavid du Colombier 	{"gamma", 947},
138*4ac975e2SDavid du Colombier 	{"ge", 8805},
139*4ac975e2SDavid du Colombier 	{"gt", 62},
140*4ac975e2SDavid du Colombier 	{"hArr", 8660},
141*4ac975e2SDavid du Colombier 	{"harr", 8596},
142*4ac975e2SDavid du Colombier 	{"hearts", 9829},
143*4ac975e2SDavid du Colombier 	{"hellip", 8230},
1448ccd4a63SDavid du Colombier 	{"iacute", 237},
1458ccd4a63SDavid du Colombier 	{"icirc", 238},
1468ccd4a63SDavid du Colombier 	{"iexcl", 161},
1478ccd4a63SDavid du Colombier 	{"igrave", 236},
148*4ac975e2SDavid du Colombier 	{"image", 8465},
149*4ac975e2SDavid du Colombier 	{"infin", 8734},
150*4ac975e2SDavid du Colombier 	{"int", 8747},
1518ccd4a63SDavid du Colombier 	{"iota", 953},
1528ccd4a63SDavid du Colombier 	{"iquest", 191},
153*4ac975e2SDavid du Colombier 	{"isin", 8712},
1548ccd4a63SDavid du Colombier 	{"iuml", 239},
1558ccd4a63SDavid du Colombier 	{"kappa", 954},
156*4ac975e2SDavid du Colombier 	{"lArr", 8656},
1578ccd4a63SDavid du Colombier 	{"lambda", 955},
158*4ac975e2SDavid du Colombier 	{"lang", 9001},
1598ccd4a63SDavid du Colombier 	{"laquo", 171},
160*4ac975e2SDavid du Colombier 	{"larr", 8592},
161*4ac975e2SDavid du Colombier 	{"lceil", 8968},
1628ccd4a63SDavid du Colombier 	{"ldots", 8230},
163*4ac975e2SDavid du Colombier 	{"ldquo", 8220},
164*4ac975e2SDavid du Colombier 	{"le", 8804},
165*4ac975e2SDavid du Colombier 	{"lfloor", 8970},
166*4ac975e2SDavid du Colombier 	{"lowast", 8727},
167*4ac975e2SDavid du Colombier 	{"loz", 9674},
168*4ac975e2SDavid du Colombier 	{"lrm", 8206},
169*4ac975e2SDavid du Colombier 	{"lsaquo", 8249},
1708ccd4a63SDavid du Colombier 	{"lsquo", 8216},
171*4ac975e2SDavid du Colombier 	{"lt", 60},
1728ccd4a63SDavid du Colombier 	{"macr", 175},
1738ccd4a63SDavid du Colombier 	{"mdash", 8212},
1748ccd4a63SDavid du Colombier 	{"micro", 181},
1758ccd4a63SDavid du Colombier 	{"middot", 183},
176*4ac975e2SDavid du Colombier 	{"minus", 8722},
1778ccd4a63SDavid du Colombier 	{"mu", 956},
178*4ac975e2SDavid du Colombier 	{"nabla", 8711},
1798ccd4a63SDavid du Colombier 	{"nbsp", 160},
1808ccd4a63SDavid du Colombier 	{"ndash", 8211},
181*4ac975e2SDavid du Colombier 	{"ne", 8800},
182*4ac975e2SDavid du Colombier 	{"ni", 8715},
1838ccd4a63SDavid du Colombier 	{"not", 172},
184*4ac975e2SDavid du Colombier 	{"notin", 8713},
185*4ac975e2SDavid du Colombier 	{"nsub", 8836},
1868ccd4a63SDavid du Colombier 	{"ntilde", 241},
1878ccd4a63SDavid du Colombier 	{"nu", 957},
1888ccd4a63SDavid du Colombier 	{"oacute", 243},
1898ccd4a63SDavid du Colombier 	{"ocirc", 244},
190*4ac975e2SDavid du Colombier 	{"oelig", 339},
1918ccd4a63SDavid du Colombier 	{"ograve", 242},
192*4ac975e2SDavid du Colombier 	{"oline", 8254},
1938ccd4a63SDavid du Colombier 	{"omega", 969},
1948ccd4a63SDavid du Colombier 	{"omicron", 959},
195*4ac975e2SDavid du Colombier 	{"oplus", 8853},
196*4ac975e2SDavid du Colombier 	{"or", 8744},
1978ccd4a63SDavid du Colombier 	{"ordf", 170},
1988ccd4a63SDavid du Colombier 	{"ordm", 186},
1998ccd4a63SDavid du Colombier 	{"oslash", 248},
2008ccd4a63SDavid du Colombier 	{"otilde", 245},
201*4ac975e2SDavid du Colombier 	{"otimes", 8855},
2028ccd4a63SDavid du Colombier 	{"ouml", 246},
2038ccd4a63SDavid du Colombier 	{"para", 182},
204*4ac975e2SDavid du Colombier 	{"part", 8706},
205*4ac975e2SDavid du Colombier 	{"permil", 8240},
206*4ac975e2SDavid du Colombier 	{"perp", 8869},
2078ccd4a63SDavid du Colombier 	{"phi", 966},
2088ccd4a63SDavid du Colombier 	{"pi", 960},
209*4ac975e2SDavid du Colombier 	{"piv", 982},
2108ccd4a63SDavid du Colombier 	{"plusmn", 177},
2118ccd4a63SDavid du Colombier 	{"pound", 163},
212*4ac975e2SDavid du Colombier 	{"prime", 8242},
213*4ac975e2SDavid du Colombier 	{"prod", 8719},
214*4ac975e2SDavid du Colombier 	{"prop", 8733},
2158ccd4a63SDavid du Colombier 	{"psi", 968},
2168ccd4a63SDavid du Colombier 	{"quad", 8193},
217*4ac975e2SDavid du Colombier 	{"quot", 34},
218*4ac975e2SDavid du Colombier 	{"rArr", 8658},
219*4ac975e2SDavid du Colombier 	{"radic", 8730},
220*4ac975e2SDavid du Colombier 	{"rang", 9002},
2218ccd4a63SDavid du Colombier 	{"raquo", 187},
222*4ac975e2SDavid du Colombier 	{"rarr", 8594},
223*4ac975e2SDavid du Colombier 	{"rceil", 8969},
2248ccd4a63SDavid du Colombier 	{"rdquo", 8221},
225*4ac975e2SDavid du Colombier 	{"real", 8476},
2268ccd4a63SDavid du Colombier 	{"reg", 174},
227*4ac975e2SDavid du Colombier 	{"rfloor", 8971},
2288ccd4a63SDavid du Colombier 	{"rho", 961},
229*4ac975e2SDavid du Colombier 	{"rlm", 8207},
230*4ac975e2SDavid du Colombier 	{"rsaquo", 8250},
2318ccd4a63SDavid du Colombier 	{"rsquo", 8217},
232*4ac975e2SDavid du Colombier 	{"sbquo", 8218},
233*4ac975e2SDavid du Colombier 	{"scaron", 353},
234*4ac975e2SDavid du Colombier 	{"sdot", 8901},
2358ccd4a63SDavid du Colombier 	{"sect", 167},
2368ccd4a63SDavid du Colombier 	{"shy", 173},
2378ccd4a63SDavid du Colombier 	{"sigma", 963},
238*4ac975e2SDavid du Colombier 	{"sigmaf", 962},
239*4ac975e2SDavid du Colombier 	{"sim", 8764},
2408ccd4a63SDavid du Colombier 	{"sp", 8194},
241*4ac975e2SDavid du Colombier 	{"spades", 9824},
242*4ac975e2SDavid du Colombier 	{"sub", 8834},
243*4ac975e2SDavid du Colombier 	{"sube", 8838},
244*4ac975e2SDavid du Colombier 	{"sum", 8721},
245*4ac975e2SDavid du Colombier 	{"sup", 8835},
2468ccd4a63SDavid du Colombier 	{"sup1", 185},
2478ccd4a63SDavid du Colombier 	{"sup2", 178},
2488ccd4a63SDavid du Colombier 	{"sup3", 179},
249*4ac975e2SDavid du Colombier 	{"supe", 8839},
2508ccd4a63SDavid du Colombier 	{"szlig", 223},
2518ccd4a63SDavid du Colombier 	{"tau", 964},
252*4ac975e2SDavid du Colombier 	{"there4", 8756},
2538ccd4a63SDavid du Colombier 	{"theta", 952},
254*4ac975e2SDavid du Colombier 	{"thetasym", 977},
2558ccd4a63SDavid du Colombier 	{"thinsp", 8201},
2568ccd4a63SDavid du Colombier 	{"thorn", 254},
257*4ac975e2SDavid du Colombier 	{"tilde", 732},
2588ccd4a63SDavid du Colombier 	{"times", 215},
2598ccd4a63SDavid du Colombier 	{"trade", 8482},
260*4ac975e2SDavid du Colombier 	{"uArr", 8657},
2618ccd4a63SDavid du Colombier 	{"uacute", 250},
262*4ac975e2SDavid du Colombier 	{"uarr", 8593},
2638ccd4a63SDavid du Colombier 	{"ucirc", 251},
2648ccd4a63SDavid du Colombier 	{"ugrave", 249},
2658ccd4a63SDavid du Colombier 	{"uml", 168},
266*4ac975e2SDavid du Colombier 	{"upsih", 978},
2678ccd4a63SDavid du Colombier 	{"upsilon", 965},
2688ccd4a63SDavid du Colombier 	{"uuml", 252},
2698ccd4a63SDavid du Colombier 	{"varepsilon", 8712},
2708ccd4a63SDavid du Colombier 	{"varphi", 981},
2718ccd4a63SDavid du Colombier 	{"varpi", 982},
2728ccd4a63SDavid du Colombier 	{"varrho", 1009},
2738ccd4a63SDavid du Colombier 	{"vdots", 8942},
2748ccd4a63SDavid du Colombier 	{"vsigma", 962},
2758ccd4a63SDavid du Colombier 	{"vtheta", 977},
276*4ac975e2SDavid du Colombier 	{"weierp", 8472},
2778ccd4a63SDavid du Colombier 	{"xi", 958},
2788ccd4a63SDavid du Colombier 	{"yacute", 253},
2798ccd4a63SDavid du Colombier 	{"yen", 165},
2808ccd4a63SDavid du Colombier 	{"yuml", 255},
281*4ac975e2SDavid du Colombier 	{"zeta", 950},
282*4ac975e2SDavid du Colombier 	{"zwj", 8205},
283*4ac975e2SDavid du Colombier 	{"zwnj", 8204}
2848ccd4a63SDavid du Colombier };
2858ccd4a63SDavid du Colombier 
2868ccd4a63SDavid du Colombier static Hchar byrune[nelem(byname)];
2878ccd4a63SDavid du Colombier 
2888ccd4a63SDavid du Colombier static int
2898ccd4a63SDavid du Colombier hnamecmp(const void *va, const void *vb)
2908ccd4a63SDavid du Colombier {
2918ccd4a63SDavid du Colombier 	Hchar *a, *b;
2928ccd4a63SDavid du Colombier 
2938ccd4a63SDavid du Colombier 	a = (Hchar*)va;
2948ccd4a63SDavid du Colombier 	b = (Hchar*)vb;
2958ccd4a63SDavid du Colombier 	return strcmp(a->s, b->s);
2968ccd4a63SDavid du Colombier }
2978ccd4a63SDavid du Colombier 
2988ccd4a63SDavid du Colombier static int
2998ccd4a63SDavid du Colombier hrunecmp(const void *va, const void *vb)
3008ccd4a63SDavid du Colombier {
3018ccd4a63SDavid du Colombier 	Hchar *a, *b;
3028ccd4a63SDavid du Colombier 
3038ccd4a63SDavid du Colombier 	a = (Hchar*)va;
3048ccd4a63SDavid du Colombier 	b = (Hchar*)vb;
3058ccd4a63SDavid du Colombier 	return a->r - b->r;
3068ccd4a63SDavid du Colombier }
3078ccd4a63SDavid du Colombier 
3088ccd4a63SDavid du Colombier static void
3098ccd4a63SDavid du Colombier html_init(void)
3108ccd4a63SDavid du Colombier {
3118ccd4a63SDavid du Colombier 	static int init;
3128ccd4a63SDavid du Colombier 
3138ccd4a63SDavid du Colombier 	if(init)
3148ccd4a63SDavid du Colombier 		return;
3158ccd4a63SDavid du Colombier 	init = 1;
3168ccd4a63SDavid du Colombier 	memmove(byrune, byname, sizeof byrune);
3178ccd4a63SDavid du Colombier 	qsort(byname, nelem(byname), sizeof byname[0], hnamecmp);
3188ccd4a63SDavid du Colombier 	qsort(byrune, nelem(byrune), sizeof byrune[0], hrunecmp);
3198ccd4a63SDavid du Colombier }
3208ccd4a63SDavid du Colombier 
3218ccd4a63SDavid du Colombier static Rune
3228ccd4a63SDavid du Colombier findbyname(char *s)
3238ccd4a63SDavid du Colombier {
3248ccd4a63SDavid du Colombier 	Hchar *h;
3258ccd4a63SDavid du Colombier 	int n, m, x;
3268ccd4a63SDavid du Colombier 
3278ccd4a63SDavid du Colombier 	h = byname;
3288ccd4a63SDavid du Colombier 	n = nelem(byname);
3298ccd4a63SDavid du Colombier 	while(n > 0){
3308ccd4a63SDavid du Colombier 		m = n/2;
3318ccd4a63SDavid du Colombier 		x = strcmp(h[m].s, s);
3328ccd4a63SDavid du Colombier 		if(x == 0)
3338ccd4a63SDavid du Colombier 			return h[m].r;
3348ccd4a63SDavid du Colombier 		if(x < 0){
3358ccd4a63SDavid du Colombier 			h += m+1;
3368ccd4a63SDavid du Colombier 			n -= m+1;
3378ccd4a63SDavid du Colombier 		}else
3388ccd4a63SDavid du Colombier 			n = m;
3398ccd4a63SDavid du Colombier 	}
3408ccd4a63SDavid du Colombier 	return Runeerror;
3418ccd4a63SDavid du Colombier }
3428ccd4a63SDavid du Colombier 
3438ccd4a63SDavid du Colombier static char*
3448ccd4a63SDavid du Colombier findbyrune(Rune r)
3458ccd4a63SDavid du Colombier {
3468ccd4a63SDavid du Colombier 	Hchar *h;
3478ccd4a63SDavid du Colombier 	int n, m;
3488ccd4a63SDavid du Colombier 
3498ccd4a63SDavid du Colombier 	h = byrune;
3508ccd4a63SDavid du Colombier 	n = nelem(byrune);
3518ccd4a63SDavid du Colombier 	while(n > 0){
3528ccd4a63SDavid du Colombier 		m = n/2;
3538ccd4a63SDavid du Colombier 		if(h[m].r == r)
3548ccd4a63SDavid du Colombier 			return h[m].s;
3558ccd4a63SDavid du Colombier 		if(h[m].r < r){
3568ccd4a63SDavid du Colombier 			h += m+1;
3578ccd4a63SDavid du Colombier 			n -= m+1;
3588ccd4a63SDavid du Colombier 		}else
3598ccd4a63SDavid du Colombier 			n = m;
3608ccd4a63SDavid du Colombier 	}
3618ccd4a63SDavid du Colombier 	return nil;
3628ccd4a63SDavid du Colombier }
3638ccd4a63SDavid du Colombier 
3648ccd4a63SDavid du Colombier void
3658ccd4a63SDavid du Colombier html_in(int fd, long *x, struct convert *out)
3668ccd4a63SDavid du Colombier {
3678ccd4a63SDavid du Colombier 	char buf[100], *p;
3688ccd4a63SDavid du Colombier 	Biobuf b;
3698ccd4a63SDavid du Colombier 	Rune rbuf[N];
3708ccd4a63SDavid du Colombier 	Rune *r, *er;
3718ccd4a63SDavid du Colombier 	int c, i;
3728ccd4a63SDavid du Colombier 
3738ccd4a63SDavid du Colombier 	USED(x);
3748ccd4a63SDavid du Colombier 
3758ccd4a63SDavid du Colombier 	html_init();
3768ccd4a63SDavid du Colombier 	r = rbuf;
3778ccd4a63SDavid du Colombier 	er = rbuf+N;
3788ccd4a63SDavid du Colombier 	Binit(&b, fd, OREAD);
3798ccd4a63SDavid du Colombier 	while((c = Bgetrune(&b)) != Beof){
3808ccd4a63SDavid du Colombier 		if(r >= er){
3818ccd4a63SDavid du Colombier 			OUT(out, rbuf, r-rbuf);
3828ccd4a63SDavid du Colombier 			r = rbuf;
3838ccd4a63SDavid du Colombier 		}
3848ccd4a63SDavid du Colombier 		if(c == '&'){
3858ccd4a63SDavid du Colombier 			buf[0] = c;
3868ccd4a63SDavid du Colombier 			for(i=1; i<nelem(buf)-1;){
3878ccd4a63SDavid du Colombier 				c = Bgetc(&b);
3888ccd4a63SDavid du Colombier 				if(c == Beof)
3898ccd4a63SDavid du Colombier 					break;
3908ccd4a63SDavid du Colombier 				buf[i++] = c;
3918ccd4a63SDavid du Colombier 				if(strchr("; \t\r\n", c))
3928ccd4a63SDavid du Colombier 					break;
3938ccd4a63SDavid du Colombier 			}
3948ccd4a63SDavid du Colombier 			buf[i] = 0;
3958ccd4a63SDavid du Colombier 			if(buf[i-1] == ';'){
3968ccd4a63SDavid du Colombier 				buf[i-1] = 0;
3978ccd4a63SDavid du Colombier 				if((c = findbyname(buf+1)) != Runeerror){
3988ccd4a63SDavid du Colombier 					*r++ = c;
3998ccd4a63SDavid du Colombier 					continue;
4008ccd4a63SDavid du Colombier 				}
4018ccd4a63SDavid du Colombier 				buf[i-1] = ';';
4028ccd4a63SDavid du Colombier 				if(buf[1] == '#'){
4038ccd4a63SDavid du Colombier 					if(buf[2] == 'x')
4048ccd4a63SDavid du Colombier 						c = strtol(buf+3, &p, 16);
4058ccd4a63SDavid du Colombier 					else
4068ccd4a63SDavid du Colombier 						c = strtol(buf+2, &p, 10);
4078ccd4a63SDavid du Colombier 					if(*p != ';' || c >= NRUNE || c < 0)
4088ccd4a63SDavid du Colombier 						goto bad;
4098ccd4a63SDavid du Colombier 					*r++ = c;
4108ccd4a63SDavid du Colombier 					continue;
4118ccd4a63SDavid du Colombier 				}
4128ccd4a63SDavid du Colombier 			}
4138ccd4a63SDavid du Colombier 		bad:
4148ccd4a63SDavid du Colombier 			for(p=buf; p<buf+i; ){
4158ccd4a63SDavid du Colombier 				p += chartorune(r++, p);
4168ccd4a63SDavid du Colombier 				if(r >= er){
4178ccd4a63SDavid du Colombier 					OUT(out, rbuf, r-rbuf);
4188ccd4a63SDavid du Colombier 					r = rbuf;
4198ccd4a63SDavid du Colombier 				}
4208ccd4a63SDavid du Colombier 			}
4218ccd4a63SDavid du Colombier 			continue;
4228ccd4a63SDavid du Colombier 		}
4238ccd4a63SDavid du Colombier 		*r++ = c;
4248ccd4a63SDavid du Colombier 	}
4258ccd4a63SDavid du Colombier 	if(r > rbuf)
4268ccd4a63SDavid du Colombier 		OUT(out, rbuf, r-rbuf);
4278ccd4a63SDavid du Colombier }
4288ccd4a63SDavid du Colombier 
4298ccd4a63SDavid du Colombier /*
4308ccd4a63SDavid du Colombier  * use biobuf because can use more than UTFmax bytes per rune
4318ccd4a63SDavid du Colombier  */
4328ccd4a63SDavid du Colombier void
4338ccd4a63SDavid du Colombier html_out(Rune *r, int n, long *x)
4348ccd4a63SDavid du Colombier {
4358ccd4a63SDavid du Colombier 	char *s;
4368ccd4a63SDavid du Colombier 	Biobuf b;
4378ccd4a63SDavid du Colombier 	Rune *er;
4388ccd4a63SDavid du Colombier 
4391fa40b8eSDavid du Colombier 	USED(x);
4408ccd4a63SDavid du Colombier 	html_init();
4418ccd4a63SDavid du Colombier 	Binit(&b, 1, OWRITE);
4428ccd4a63SDavid du Colombier 	er = r+n;
4438ccd4a63SDavid du Colombier 	for(; r<er; r++){
4448ccd4a63SDavid du Colombier 		if(*r < Runeself)
4458ccd4a63SDavid du Colombier 			Bputrune(&b, *r);
4468ccd4a63SDavid du Colombier 		else if((s = findbyrune(*r)) != nil)
4478ccd4a63SDavid du Colombier 			Bprint(&b, "&%s;", s);
4488ccd4a63SDavid du Colombier 		else
449426d2b71SDavid du Colombier 			Bprint(&b, "&#%d;", *r);
4508ccd4a63SDavid du Colombier 	}
4518ccd4a63SDavid du Colombier 	Bflush(&b);
4528ccd4a63SDavid du Colombier }
4538ccd4a63SDavid du Colombier 
454