xref: /plan9/sys/src/cmd/tcs/html.c (revision 2cba34c722cc5343f414835ed47b457dd3b026ca)
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 
16*2cba34c7SDavid du Colombier /*
17*2cba34c7SDavid du Colombier  * Names beginning with _ are names we recognize
18*2cba34c7SDavid du Colombier  * (without the underscore) but will not generate,
19*2cba34c7SDavid du Colombier  * because they are nonstandard.
20*2cba34c7SDavid du Colombier  */
218ccd4a63SDavid du Colombier static Hchar byname[] =
228ccd4a63SDavid du Colombier {
238ccd4a63SDavid du Colombier 	{"AElig", 198},
248ccd4a63SDavid du Colombier 	{"Aacute", 193},
258ccd4a63SDavid du Colombier 	{"Acirc", 194},
268ccd4a63SDavid du Colombier 	{"Agrave", 192},
274ac975e2SDavid du Colombier 	{"Alpha", 913},
288ccd4a63SDavid du Colombier 	{"Aring", 197},
298ccd4a63SDavid du Colombier 	{"Atilde", 195},
308ccd4a63SDavid du Colombier 	{"Auml", 196},
314ac975e2SDavid du Colombier 	{"Beta", 914},
328ccd4a63SDavid du Colombier 	{"Ccedil", 199},
334ac975e2SDavid du Colombier 	{"Chi", 935},
344ac975e2SDavid du Colombier 	{"Dagger", 8225},
354ac975e2SDavid du Colombier 	{"Delta", 916},
368ccd4a63SDavid du Colombier 	{"ETH", 208},
378ccd4a63SDavid du Colombier 	{"Eacute", 201},
388ccd4a63SDavid du Colombier 	{"Ecirc", 202},
398ccd4a63SDavid du Colombier 	{"Egrave", 200},
404ac975e2SDavid du Colombier 	{"Epsilon", 917},
414ac975e2SDavid du Colombier 	{"Eta", 919},
428ccd4a63SDavid du Colombier 	{"Euml", 203},
434ac975e2SDavid du Colombier 	{"Gamma", 915},
448ccd4a63SDavid du Colombier 	{"Iacute", 205},
458ccd4a63SDavid du Colombier 	{"Icirc", 206},
468ccd4a63SDavid du Colombier 	{"Igrave", 204},
474ac975e2SDavid du Colombier 	{"Iota", 921},
488ccd4a63SDavid du Colombier 	{"Iuml", 207},
494ac975e2SDavid du Colombier 	{"Kappa", 922},
504ac975e2SDavid du Colombier 	{"Lambda", 923},
514ac975e2SDavid du Colombier 	{"Mu", 924},
528ccd4a63SDavid du Colombier 	{"Ntilde", 209},
534ac975e2SDavid du Colombier 	{"Nu", 925},
544ac975e2SDavid du Colombier 	{"OElig", 338},
558ccd4a63SDavid du Colombier 	{"Oacute", 211},
568ccd4a63SDavid du Colombier 	{"Ocirc", 212},
578ccd4a63SDavid du Colombier 	{"Ograve", 210},
584ac975e2SDavid du Colombier 	{"Omega", 937},
594ac975e2SDavid du Colombier 	{"Omicron", 927},
608ccd4a63SDavid du Colombier 	{"Oslash", 216},
618ccd4a63SDavid du Colombier 	{"Otilde", 213},
628ccd4a63SDavid du Colombier 	{"Ouml", 214},
634ac975e2SDavid du Colombier 	{"Phi", 934},
644ac975e2SDavid du Colombier 	{"Pi", 928},
654ac975e2SDavid du Colombier 	{"Prime", 8243},
664ac975e2SDavid du Colombier 	{"Psi", 936},
674ac975e2SDavid du Colombier 	{"Rho", 929},
684ac975e2SDavid du Colombier 	{"Scaron", 352},
694ac975e2SDavid du Colombier 	{"Sigma", 931},
708ccd4a63SDavid du Colombier 	{"THORN", 222},
714ac975e2SDavid du Colombier 	{"Tau", 932},
724ac975e2SDavid du Colombier 	{"Theta", 920},
738ccd4a63SDavid du Colombier 	{"Uacute", 218},
748ccd4a63SDavid du Colombier 	{"Ucirc", 219},
758ccd4a63SDavid du Colombier 	{"Ugrave", 217},
764ac975e2SDavid du Colombier 	{"Upsilon", 933},
778ccd4a63SDavid du Colombier 	{"Uuml", 220},
784ac975e2SDavid du Colombier 	{"Xi", 926},
798ccd4a63SDavid du Colombier 	{"Yacute", 221},
804ac975e2SDavid du Colombier 	{"Yuml", 376},
814ac975e2SDavid du Colombier 	{"Zeta", 918},
828ccd4a63SDavid du Colombier 	{"aacute", 225},
838ccd4a63SDavid du Colombier 	{"acirc", 226},
848ccd4a63SDavid du Colombier 	{"acute", 180},
858ccd4a63SDavid du Colombier 	{"aelig", 230},
868ccd4a63SDavid du Colombier 	{"agrave", 224},
874ac975e2SDavid du Colombier 	{"alefsym", 8501},
888ccd4a63SDavid du Colombier 	{"alpha", 945},
894ac975e2SDavid du Colombier 	{"amp", 38},
904ac975e2SDavid du Colombier 	{"and", 8743},
914ac975e2SDavid du Colombier 	{"ang", 8736},
928ccd4a63SDavid du Colombier 	{"aring", 229},
934ac975e2SDavid du Colombier 	{"asymp", 8776},
948ccd4a63SDavid du Colombier 	{"atilde", 227},
958ccd4a63SDavid du Colombier 	{"auml", 228},
964ac975e2SDavid du Colombier 	{"bdquo", 8222},
978ccd4a63SDavid du Colombier 	{"beta", 946},
988ccd4a63SDavid du Colombier 	{"brvbar", 166},
994ac975e2SDavid du Colombier 	{"bull", 8226},
1004ac975e2SDavid du Colombier 	{"cap", 8745},
1018ccd4a63SDavid du Colombier 	{"ccedil", 231},
1028ccd4a63SDavid du Colombier 	{"cdots", 8943},
1038ccd4a63SDavid du Colombier 	{"cedil", 184},
1048ccd4a63SDavid du Colombier 	{"cent", 162},
1058ccd4a63SDavid du Colombier 	{"chi", 967},
1064ac975e2SDavid du Colombier 	{"circ", 710},
1074ac975e2SDavid du Colombier 	{"clubs", 9827},
1084ac975e2SDavid du Colombier 	{"cong", 8773},
1098ccd4a63SDavid du Colombier 	{"copy", 169},
1104ac975e2SDavid du Colombier 	{"crarr", 8629},
1114ac975e2SDavid du Colombier 	{"cup", 8746},
1128ccd4a63SDavid du Colombier 	{"curren", 164},
1134ac975e2SDavid du Colombier 	{"dArr", 8659},
1144ac975e2SDavid du Colombier 	{"dagger", 8224},
1154ac975e2SDavid du Colombier 	{"darr", 8595},
1168ccd4a63SDavid du Colombier 	{"ddots", 8945},
1178ccd4a63SDavid du Colombier 	{"deg", 176},
1188ccd4a63SDavid du Colombier 	{"delta", 948},
1194ac975e2SDavid du Colombier 	{"diams", 9830},
1208ccd4a63SDavid du Colombier 	{"divide", 247},
1218ccd4a63SDavid du Colombier 	{"eacute", 233},
1228ccd4a63SDavid du Colombier 	{"ecirc", 234},
1238ccd4a63SDavid du Colombier 	{"egrave", 232},
124*2cba34c7SDavid du Colombier 	{"_emdash", 8212},	/* non-standard but commonly used */
1254ac975e2SDavid du Colombier 	{"empty", 8709},
1268ccd4a63SDavid du Colombier 	{"emsp", 8195},
127*2cba34c7SDavid du Colombier 	{"_endash", 8211},	/* non-standard but commonly used */
1288ccd4a63SDavid du Colombier 	{"ensp", 8194},
1298ccd4a63SDavid du Colombier 	{"epsilon", 949},
1304ac975e2SDavid du Colombier 	{"equiv", 8801},
1318ccd4a63SDavid du Colombier 	{"eta", 951},
1328ccd4a63SDavid du Colombier 	{"eth", 240},
1338ccd4a63SDavid du Colombier 	{"euml", 235},
1344ac975e2SDavid du Colombier 	{"euro", 8364},
1354ac975e2SDavid du Colombier 	{"exist", 8707},
1364ac975e2SDavid du Colombier 	{"fnof", 402},
1374ac975e2SDavid du Colombier 	{"forall", 8704},
1388ccd4a63SDavid du Colombier 	{"frac12", 189},
1398ccd4a63SDavid du Colombier 	{"frac14", 188},
1408ccd4a63SDavid du Colombier 	{"frac34", 190},
1414ac975e2SDavid du Colombier 	{"frasl", 8260},
1428ccd4a63SDavid du Colombier 	{"gamma", 947},
1434ac975e2SDavid du Colombier 	{"ge", 8805},
1444ac975e2SDavid du Colombier 	{"gt", 62},
1454ac975e2SDavid du Colombier 	{"hArr", 8660},
1464ac975e2SDavid du Colombier 	{"harr", 8596},
1474ac975e2SDavid du Colombier 	{"hearts", 9829},
1484ac975e2SDavid du Colombier 	{"hellip", 8230},
1498ccd4a63SDavid du Colombier 	{"iacute", 237},
1508ccd4a63SDavid du Colombier 	{"icirc", 238},
1518ccd4a63SDavid du Colombier 	{"iexcl", 161},
1528ccd4a63SDavid du Colombier 	{"igrave", 236},
1534ac975e2SDavid du Colombier 	{"image", 8465},
1544ac975e2SDavid du Colombier 	{"infin", 8734},
1554ac975e2SDavid du Colombier 	{"int", 8747},
1568ccd4a63SDavid du Colombier 	{"iota", 953},
1578ccd4a63SDavid du Colombier 	{"iquest", 191},
1584ac975e2SDavid du Colombier 	{"isin", 8712},
1598ccd4a63SDavid du Colombier 	{"iuml", 239},
1608ccd4a63SDavid du Colombier 	{"kappa", 954},
1614ac975e2SDavid du Colombier 	{"lArr", 8656},
1628ccd4a63SDavid du Colombier 	{"lambda", 955},
1634ac975e2SDavid du Colombier 	{"lang", 9001},
1648ccd4a63SDavid du Colombier 	{"laquo", 171},
1654ac975e2SDavid du Colombier 	{"larr", 8592},
1664ac975e2SDavid du Colombier 	{"lceil", 8968},
167*2cba34c7SDavid du Colombier 	{"_ldots", 8230},
1684ac975e2SDavid du Colombier 	{"ldquo", 8220},
1694ac975e2SDavid du Colombier 	{"le", 8804},
1704ac975e2SDavid du Colombier 	{"lfloor", 8970},
1714ac975e2SDavid du Colombier 	{"lowast", 8727},
1724ac975e2SDavid du Colombier 	{"loz", 9674},
1734ac975e2SDavid du Colombier 	{"lrm", 8206},
1744ac975e2SDavid du Colombier 	{"lsaquo", 8249},
1758ccd4a63SDavid du Colombier 	{"lsquo", 8216},
1764ac975e2SDavid du Colombier 	{"lt", 60},
1778ccd4a63SDavid du Colombier 	{"macr", 175},
1788ccd4a63SDavid du Colombier 	{"mdash", 8212},
1798ccd4a63SDavid du Colombier 	{"micro", 181},
1808ccd4a63SDavid du Colombier 	{"middot", 183},
1814ac975e2SDavid du Colombier 	{"minus", 8722},
1828ccd4a63SDavid du Colombier 	{"mu", 956},
1834ac975e2SDavid du Colombier 	{"nabla", 8711},
1848ccd4a63SDavid du Colombier 	{"nbsp", 160},
1858ccd4a63SDavid du Colombier 	{"ndash", 8211},
1864ac975e2SDavid du Colombier 	{"ne", 8800},
1874ac975e2SDavid du Colombier 	{"ni", 8715},
1888ccd4a63SDavid du Colombier 	{"not", 172},
1894ac975e2SDavid du Colombier 	{"notin", 8713},
1904ac975e2SDavid du Colombier 	{"nsub", 8836},
1918ccd4a63SDavid du Colombier 	{"ntilde", 241},
1928ccd4a63SDavid du Colombier 	{"nu", 957},
1938ccd4a63SDavid du Colombier 	{"oacute", 243},
1948ccd4a63SDavid du Colombier 	{"ocirc", 244},
1954ac975e2SDavid du Colombier 	{"oelig", 339},
1968ccd4a63SDavid du Colombier 	{"ograve", 242},
1974ac975e2SDavid du Colombier 	{"oline", 8254},
1988ccd4a63SDavid du Colombier 	{"omega", 969},
1998ccd4a63SDavid du Colombier 	{"omicron", 959},
2004ac975e2SDavid du Colombier 	{"oplus", 8853},
2014ac975e2SDavid du Colombier 	{"or", 8744},
2028ccd4a63SDavid du Colombier 	{"ordf", 170},
2038ccd4a63SDavid du Colombier 	{"ordm", 186},
2048ccd4a63SDavid du Colombier 	{"oslash", 248},
2058ccd4a63SDavid du Colombier 	{"otilde", 245},
2064ac975e2SDavid du Colombier 	{"otimes", 8855},
2078ccd4a63SDavid du Colombier 	{"ouml", 246},
2088ccd4a63SDavid du Colombier 	{"para", 182},
2094ac975e2SDavid du Colombier 	{"part", 8706},
2104ac975e2SDavid du Colombier 	{"permil", 8240},
2114ac975e2SDavid du Colombier 	{"perp", 8869},
2128ccd4a63SDavid du Colombier 	{"phi", 966},
2138ccd4a63SDavid du Colombier 	{"pi", 960},
2144ac975e2SDavid du Colombier 	{"piv", 982},
2158ccd4a63SDavid du Colombier 	{"plusmn", 177},
2168ccd4a63SDavid du Colombier 	{"pound", 163},
2174ac975e2SDavid du Colombier 	{"prime", 8242},
2184ac975e2SDavid du Colombier 	{"prod", 8719},
2194ac975e2SDavid du Colombier 	{"prop", 8733},
2208ccd4a63SDavid du Colombier 	{"psi", 968},
2218ccd4a63SDavid du Colombier 	{"quad", 8193},
2224ac975e2SDavid du Colombier 	{"quot", 34},
2234ac975e2SDavid du Colombier 	{"rArr", 8658},
2244ac975e2SDavid du Colombier 	{"radic", 8730},
2254ac975e2SDavid du Colombier 	{"rang", 9002},
2268ccd4a63SDavid du Colombier 	{"raquo", 187},
2274ac975e2SDavid du Colombier 	{"rarr", 8594},
2284ac975e2SDavid du Colombier 	{"rceil", 8969},
2298ccd4a63SDavid du Colombier 	{"rdquo", 8221},
2304ac975e2SDavid du Colombier 	{"real", 8476},
2318ccd4a63SDavid du Colombier 	{"reg", 174},
2324ac975e2SDavid du Colombier 	{"rfloor", 8971},
2338ccd4a63SDavid du Colombier 	{"rho", 961},
2344ac975e2SDavid du Colombier 	{"rlm", 8207},
2354ac975e2SDavid du Colombier 	{"rsaquo", 8250},
2368ccd4a63SDavid du Colombier 	{"rsquo", 8217},
2374ac975e2SDavid du Colombier 	{"sbquo", 8218},
2384ac975e2SDavid du Colombier 	{"scaron", 353},
2394ac975e2SDavid du Colombier 	{"sdot", 8901},
2408ccd4a63SDavid du Colombier 	{"sect", 167},
2418ccd4a63SDavid du Colombier 	{"shy", 173},
2428ccd4a63SDavid du Colombier 	{"sigma", 963},
2434ac975e2SDavid du Colombier 	{"sigmaf", 962},
2444ac975e2SDavid du Colombier 	{"sim", 8764},
245*2cba34c7SDavid du Colombier 	{"_sp", 8194},
2464ac975e2SDavid du Colombier 	{"spades", 9824},
2474ac975e2SDavid du Colombier 	{"sub", 8834},
2484ac975e2SDavid du Colombier 	{"sube", 8838},
2494ac975e2SDavid du Colombier 	{"sum", 8721},
2504ac975e2SDavid du Colombier 	{"sup", 8835},
2518ccd4a63SDavid du Colombier 	{"sup1", 185},
2528ccd4a63SDavid du Colombier 	{"sup2", 178},
2538ccd4a63SDavid du Colombier 	{"sup3", 179},
2544ac975e2SDavid du Colombier 	{"supe", 8839},
2558ccd4a63SDavid du Colombier 	{"szlig", 223},
2568ccd4a63SDavid du Colombier 	{"tau", 964},
2574ac975e2SDavid du Colombier 	{"there4", 8756},
2588ccd4a63SDavid du Colombier 	{"theta", 952},
2594ac975e2SDavid du Colombier 	{"thetasym", 977},
2608ccd4a63SDavid du Colombier 	{"thinsp", 8201},
2618ccd4a63SDavid du Colombier 	{"thorn", 254},
2624ac975e2SDavid du Colombier 	{"tilde", 732},
2638ccd4a63SDavid du Colombier 	{"times", 215},
2648ccd4a63SDavid du Colombier 	{"trade", 8482},
2654ac975e2SDavid du Colombier 	{"uArr", 8657},
2668ccd4a63SDavid du Colombier 	{"uacute", 250},
2674ac975e2SDavid du Colombier 	{"uarr", 8593},
2688ccd4a63SDavid du Colombier 	{"ucirc", 251},
2698ccd4a63SDavid du Colombier 	{"ugrave", 249},
2708ccd4a63SDavid du Colombier 	{"uml", 168},
2714ac975e2SDavid du Colombier 	{"upsih", 978},
2728ccd4a63SDavid du Colombier 	{"upsilon", 965},
2738ccd4a63SDavid du Colombier 	{"uuml", 252},
274*2cba34c7SDavid du Colombier 	{"_varepsilon", 8712},
2758ccd4a63SDavid du Colombier 	{"varphi", 981},
276*2cba34c7SDavid du Colombier 	{"_varpi", 982},
2778ccd4a63SDavid du Colombier 	{"varrho", 1009},
2788ccd4a63SDavid du Colombier 	{"vdots", 8942},
279*2cba34c7SDavid du Colombier 	{"_vsigma", 962},
280*2cba34c7SDavid du Colombier 	{"_vtheta", 977},
2814ac975e2SDavid du Colombier 	{"weierp", 8472},
2828ccd4a63SDavid du Colombier 	{"xi", 958},
2838ccd4a63SDavid du Colombier 	{"yacute", 253},
2848ccd4a63SDavid du Colombier 	{"yen", 165},
2858ccd4a63SDavid du Colombier 	{"yuml", 255},
2864ac975e2SDavid du Colombier 	{"zeta", 950},
2874ac975e2SDavid du Colombier 	{"zwj", 8205},
2884ac975e2SDavid du Colombier 	{"zwnj", 8204}
2898ccd4a63SDavid du Colombier };
2908ccd4a63SDavid du Colombier 
2918ccd4a63SDavid du Colombier static Hchar byrune[nelem(byname)];
2928ccd4a63SDavid du Colombier 
2938ccd4a63SDavid du Colombier static int
hnamecmp(const void * va,const void * vb)2948ccd4a63SDavid du Colombier hnamecmp(const void *va, const void *vb)
2958ccd4a63SDavid du Colombier {
2968ccd4a63SDavid du Colombier 	Hchar *a, *b;
2978ccd4a63SDavid du Colombier 
2988ccd4a63SDavid du Colombier 	a = (Hchar*)va;
2998ccd4a63SDavid du Colombier 	b = (Hchar*)vb;
3008ccd4a63SDavid du Colombier 	return strcmp(a->s, b->s);
3018ccd4a63SDavid du Colombier }
3028ccd4a63SDavid du Colombier 
3038ccd4a63SDavid du Colombier static int
hrunecmp(const void * va,const void * vb)3048ccd4a63SDavid du Colombier hrunecmp(const void *va, const void *vb)
3058ccd4a63SDavid du Colombier {
3068ccd4a63SDavid du Colombier 	Hchar *a, *b;
3078ccd4a63SDavid du Colombier 
3088ccd4a63SDavid du Colombier 	a = (Hchar*)va;
3098ccd4a63SDavid du Colombier 	b = (Hchar*)vb;
3108ccd4a63SDavid du Colombier 	return a->r - b->r;
3118ccd4a63SDavid du Colombier }
3128ccd4a63SDavid du Colombier 
3138ccd4a63SDavid du Colombier static void
html_init(void)3148ccd4a63SDavid du Colombier html_init(void)
3158ccd4a63SDavid du Colombier {
3168ccd4a63SDavid du Colombier 	static int init;
317*2cba34c7SDavid du Colombier 	int i;
3188ccd4a63SDavid du Colombier 
3198ccd4a63SDavid du Colombier 	if(init)
3208ccd4a63SDavid du Colombier 		return;
3218ccd4a63SDavid du Colombier 	init = 1;
3228ccd4a63SDavid du Colombier 	memmove(byrune, byname, sizeof byrune);
323*2cba34c7SDavid du Colombier 
324*2cba34c7SDavid du Colombier 	/* Eliminate names we aren't allowed to generate. */
325*2cba34c7SDavid du Colombier 	for(i=0; i<nelem(byrune); i++){
326*2cba34c7SDavid du Colombier 		if(byrune[i].s[0] == '_'){
327*2cba34c7SDavid du Colombier 			byrune[i].r = Runeerror;
328*2cba34c7SDavid du Colombier 			byname[i].s++;
329*2cba34c7SDavid du Colombier 		}
330*2cba34c7SDavid du Colombier 	}
331*2cba34c7SDavid du Colombier 
3328ccd4a63SDavid du Colombier 	qsort(byname, nelem(byname), sizeof byname[0], hnamecmp);
3338ccd4a63SDavid du Colombier 	qsort(byrune, nelem(byrune), sizeof byrune[0], hrunecmp);
3348ccd4a63SDavid du Colombier }
3358ccd4a63SDavid du Colombier 
3368ccd4a63SDavid du Colombier static Rune
findbyname(char * s)3378ccd4a63SDavid du Colombier findbyname(char *s)
3388ccd4a63SDavid du Colombier {
3398ccd4a63SDavid du Colombier 	Hchar *h;
3408ccd4a63SDavid du Colombier 	int n, m, x;
3418ccd4a63SDavid du Colombier 
3428ccd4a63SDavid du Colombier 	h = byname;
3438ccd4a63SDavid du Colombier 	n = nelem(byname);
3448ccd4a63SDavid du Colombier 	while(n > 0){
3458ccd4a63SDavid du Colombier 		m = n/2;
3468ccd4a63SDavid du Colombier 		x = strcmp(h[m].s, s);
3478ccd4a63SDavid du Colombier 		if(x == 0)
3488ccd4a63SDavid du Colombier 			return h[m].r;
3498ccd4a63SDavid du Colombier 		if(x < 0){
3508ccd4a63SDavid du Colombier 			h += m+1;
3518ccd4a63SDavid du Colombier 			n -= m+1;
3528ccd4a63SDavid du Colombier 		}else
3538ccd4a63SDavid du Colombier 			n = m;
3548ccd4a63SDavid du Colombier 	}
3558ccd4a63SDavid du Colombier 	return Runeerror;
3568ccd4a63SDavid du Colombier }
3578ccd4a63SDavid du Colombier 
3588ccd4a63SDavid du Colombier static char*
findbyrune(Rune r)3598ccd4a63SDavid du Colombier findbyrune(Rune r)
3608ccd4a63SDavid du Colombier {
3618ccd4a63SDavid du Colombier 	Hchar *h;
3628ccd4a63SDavid du Colombier 	int n, m;
3638ccd4a63SDavid du Colombier 
364*2cba34c7SDavid du Colombier 	if(r == Runeerror)
365*2cba34c7SDavid du Colombier 		return nil;
3668ccd4a63SDavid du Colombier 	h = byrune;
3678ccd4a63SDavid du Colombier 	n = nelem(byrune);
3688ccd4a63SDavid du Colombier 	while(n > 0){
3698ccd4a63SDavid du Colombier 		m = n/2;
3708ccd4a63SDavid du Colombier 		if(h[m].r == r)
3718ccd4a63SDavid du Colombier 			return h[m].s;
3728ccd4a63SDavid du Colombier 		if(h[m].r < r){
3738ccd4a63SDavid du Colombier 			h += m+1;
3748ccd4a63SDavid du Colombier 			n -= m+1;
3758ccd4a63SDavid du Colombier 		}else
3768ccd4a63SDavid du Colombier 			n = m;
3778ccd4a63SDavid du Colombier 	}
3788ccd4a63SDavid du Colombier 	return nil;
3798ccd4a63SDavid du Colombier }
3808ccd4a63SDavid du Colombier 
3818ccd4a63SDavid du Colombier void
html_in(int fd,long * x,struct convert * out)3828ccd4a63SDavid du Colombier html_in(int fd, long *x, struct convert *out)
3838ccd4a63SDavid du Colombier {
3848ccd4a63SDavid du Colombier 	char buf[100], *p;
3858ccd4a63SDavid du Colombier 	Biobuf b;
3868ccd4a63SDavid du Colombier 	Rune rbuf[N];
3878ccd4a63SDavid du Colombier 	Rune *r, *er;
3888ccd4a63SDavid du Colombier 	int c, i;
3898ccd4a63SDavid du Colombier 
3908ccd4a63SDavid du Colombier 	USED(x);
3918ccd4a63SDavid du Colombier 
3928ccd4a63SDavid du Colombier 	html_init();
3938ccd4a63SDavid du Colombier 	r = rbuf;
3948ccd4a63SDavid du Colombier 	er = rbuf+N;
3958ccd4a63SDavid du Colombier 	Binit(&b, fd, OREAD);
3968ccd4a63SDavid du Colombier 	while((c = Bgetrune(&b)) != Beof){
3978ccd4a63SDavid du Colombier 		if(r >= er){
3988ccd4a63SDavid du Colombier 			OUT(out, rbuf, r-rbuf);
3998ccd4a63SDavid du Colombier 			r = rbuf;
4008ccd4a63SDavid du Colombier 		}
4018ccd4a63SDavid du Colombier 		if(c == '&'){
4028ccd4a63SDavid du Colombier 			buf[0] = c;
4038ccd4a63SDavid du Colombier 			for(i=1; i<nelem(buf)-1;){
4048ccd4a63SDavid du Colombier 				c = Bgetc(&b);
4058ccd4a63SDavid du Colombier 				if(c == Beof)
4068ccd4a63SDavid du Colombier 					break;
4078ccd4a63SDavid du Colombier 				buf[i++] = c;
4088ccd4a63SDavid du Colombier 				if(strchr("; \t\r\n", c))
4098ccd4a63SDavid du Colombier 					break;
4108ccd4a63SDavid du Colombier 			}
4118ccd4a63SDavid du Colombier 			buf[i] = 0;
4128ccd4a63SDavid du Colombier 			if(buf[i-1] == ';'){
4138ccd4a63SDavid du Colombier 				buf[i-1] = 0;
4148ccd4a63SDavid du Colombier 				if((c = findbyname(buf+1)) != Runeerror){
4158ccd4a63SDavid du Colombier 					*r++ = c;
4168ccd4a63SDavid du Colombier 					continue;
4178ccd4a63SDavid du Colombier 				}
4188ccd4a63SDavid du Colombier 				buf[i-1] = ';';
4198ccd4a63SDavid du Colombier 				if(buf[1] == '#'){
4208ccd4a63SDavid du Colombier 					if(buf[2] == 'x')
4218ccd4a63SDavid du Colombier 						c = strtol(buf+3, &p, 16);
4228ccd4a63SDavid du Colombier 					else
4238ccd4a63SDavid du Colombier 						c = strtol(buf+2, &p, 10);
4248ccd4a63SDavid du Colombier 					if(*p != ';' || c >= NRUNE || c < 0)
4258ccd4a63SDavid du Colombier 						goto bad;
4268ccd4a63SDavid du Colombier 					*r++ = c;
4278ccd4a63SDavid du Colombier 					continue;
4288ccd4a63SDavid du Colombier 				}
4298ccd4a63SDavid du Colombier 			}
4308ccd4a63SDavid du Colombier 		bad:
4318ccd4a63SDavid du Colombier 			for(p=buf; p<buf+i; ){
4328ccd4a63SDavid du Colombier 				p += chartorune(r++, p);
4338ccd4a63SDavid du Colombier 				if(r >= er){
4348ccd4a63SDavid du Colombier 					OUT(out, rbuf, r-rbuf);
4358ccd4a63SDavid du Colombier 					r = rbuf;
4368ccd4a63SDavid du Colombier 				}
4378ccd4a63SDavid du Colombier 			}
4388ccd4a63SDavid du Colombier 			continue;
4398ccd4a63SDavid du Colombier 		}
4408ccd4a63SDavid du Colombier 		*r++ = c;
4418ccd4a63SDavid du Colombier 	}
4428ccd4a63SDavid du Colombier 	if(r > rbuf)
4438ccd4a63SDavid du Colombier 		OUT(out, rbuf, r-rbuf);
444ec46fab0SDavid du Colombier 	OUT(out, rbuf, 0);
4458ccd4a63SDavid du Colombier }
4468ccd4a63SDavid du Colombier 
4478ccd4a63SDavid du Colombier /*
4488ccd4a63SDavid du Colombier  * use biobuf because can use more than UTFmax bytes per rune
4498ccd4a63SDavid du Colombier  */
4508ccd4a63SDavid du Colombier void
html_out(Rune * r,int n,long * x)4518ccd4a63SDavid du Colombier html_out(Rune *r, int n, long *x)
4528ccd4a63SDavid du Colombier {
4538ccd4a63SDavid du Colombier 	char *s;
4548ccd4a63SDavid du Colombier 	Biobuf b;
4558ccd4a63SDavid du Colombier 	Rune *er;
4568ccd4a63SDavid du Colombier 
4571fa40b8eSDavid du Colombier 	USED(x);
4588ccd4a63SDavid du Colombier 	html_init();
4598ccd4a63SDavid du Colombier 	Binit(&b, 1, OWRITE);
4608ccd4a63SDavid du Colombier 	er = r+n;
4618ccd4a63SDavid du Colombier 	for(; r<er; r++){
4628ccd4a63SDavid du Colombier 		if(*r < Runeself)
4638ccd4a63SDavid du Colombier 			Bputrune(&b, *r);
4648ccd4a63SDavid du Colombier 		else if((s = findbyrune(*r)) != nil)
4658ccd4a63SDavid du Colombier 			Bprint(&b, "&%s;", s);
4668ccd4a63SDavid du Colombier 		else
467426d2b71SDavid du Colombier 			Bprint(&b, "&#%d;", *r);
4688ccd4a63SDavid du Colombier 	}
4698ccd4a63SDavid du Colombier 	Bflush(&b);
4708ccd4a63SDavid du Colombier }
4718ccd4a63SDavid du Colombier 
472