#include <u.h>#include <libc.h>#include <bio.h>#include "hdr.h"#include "conv.h" typedef struct Hchar Hchar;struct Hchar{ char *s; Rune r;}; /* <, >, ", & intentionally omitted */ /* * Names beginning with _ are names we recognize * (without the underscore) but will not generate, * because they are nonstandard. */static Hchar byname[] ={ {"AElig", 198}, {"Aacute", 193}, {"Acirc", 194}, {"Agrave", 192}, {"Alpha", 913}, {"Aring", 197}, {"Atilde", 195}, {"Auml", 196}, {"Beta", 914}, {"Ccedil", 199}, {"Chi", 935}, {"Dagger", 8225}, {"Delta", 916}, {"ETH", 208}, {"Eacute", 201}, {"Ecirc", 202}, {"Egrave", 200}, {"Epsilon", 917}, {"Eta", 919}, {"Euml", 203}, {"Gamma", 915}, {"Iacute", 205}, {"Icirc", 206}, {"Igrave", 204}, {"Iota", 921}, {"Iuml", 207}, {"Kappa", 922}, {"Lambda", 923}, {"Mu", 924}, {"Ntilde", 209}, {"Nu", 925}, {"OElig", 338}, {"Oacute", 211}, {"Ocirc", 212}, {"Ograve", 210}, {"Omega", 937}, {"Omicron", 927}, {"Oslash", 216}, {"Otilde", 213}, {"Ouml", 214}, {"Phi", 934}, {"Pi", 928}, {"Prime", 8243}, {"Psi", 936}, {"Rho", 929}, {"Scaron", 352}, {"Sigma", 931}, {"THORN", 222}, {"Tau", 932}, {"Theta", 920}, {"Uacute", 218}, {"Ucirc", 219}, {"Ugrave", 217}, {"Upsilon", 933}, {"Uuml", 220}, {"Xi", 926}, {"Yacute", 221}, {"Yuml", 376}, {"Zeta", 918}, {"aacute", 225}, {"acirc", 226}, {"acute", 180}, {"aelig", 230}, {"agrave", 224}, {"alefsym", 8501}, {"alpha", 945}, {"amp", 38}, {"and", 8743}, {"ang", 8736}, {"aring", 229}, {"asymp", 8776}, {"atilde", 227}, {"auml", 228}, {"bdquo", 8222}, {"beta", 946}, {"brvbar", 166}, {"bull", 8226}, {"cap", 8745}, {"ccedil", 231}, {"cdots", 8943}, {"cedil", 184}, {"cent", 162}, {"chi", 967}, {"circ", 710}, {"clubs", 9827}, {"cong", 8773}, {"copy", 169}, {"crarr", 8629}, {"cup", 8746}, {"curren", 164}, {"dArr", 8659}, {"dagger", 8224}, {"darr", 8595}, {"ddots", 8945}, {"deg", 176}, {"delta", 948}, {"diams", 9830}, {"divide", 247}, {"eacute", 233}, {"ecirc", 234}, {"egrave", 232}, {"_emdash", 8212}, /* non-standard but commonly used */ {"empty", 8709}, {"emsp", 8195}, {"_endash", 8211}, /* non-standard but commonly used */ {"ensp", 8194}, {"epsilon", 949}, {"equiv", 8801}, {"eta", 951}, {"eth", 240}, {"euml", 235}, {"euro", 8364}, {"exist", 8707}, {"fnof", 402}, {"forall", 8704}, {"frac12", 189}, {"frac14", 188}, {"frac34", 190}, {"frasl", 8260}, {"gamma", 947}, {"ge", 8805}, {"gt", 62}, {"hArr", 8660}, {"harr", 8596}, {"hearts", 9829}, {"hellip", 8230}, {"iacute", 237}, {"icirc", 238}, {"iexcl", 161}, {"igrave", 236}, {"image", 8465}, {"infin", 8734}, {"int", 8747}, {"iota", 953}, {"iquest", 191}, {"isin", 8712}, {"iuml", 239}, {"kappa", 954}, {"lArr", 8656}, {"lambda", 955}, {"lang", 9001}, {"laquo", 171}, {"larr", 8592}, {"lceil", 8968}, {"_ldots", 8230}, {"ldquo", 8220}, {"le", 8804}, {"lfloor", 8970}, {"lowast", 8727}, {"loz", 9674}, {"lrm", 8206}, {"lsaquo", 8249}, {"lsquo", 8216}, {"lt", 60}, {"macr", 175}, {"mdash", 8212}, {"micro", 181}, {"middot", 183}, {"minus", 8722}, {"mu", 956}, {"nabla", 8711}, {"nbsp", 160}, {"ndash", 8211}, {"ne", 8800}, {"ni", 8715}, {"not", 172}, {"notin", 8713}, {"nsub", 8836}, {"ntilde", 241}, {"nu", 957}, {"oacute", 243}, {"ocirc", 244}, {"oelig", 339}, {"ograve", 242}, {"oline", 8254}, {"omega", 969}, {"omicron", 959}, {"oplus", 8853}, {"or", 8744}, {"ordf", 170}, {"ordm", 186}, {"oslash", 248}, {"otilde", 245}, {"otimes", 8855}, {"ouml", 246}, {"para", 182}, {"part", 8706}, {"permil", 8240}, {"perp", 8869}, {"phi", 966}, {"pi", 960}, {"piv", 982}, {"plusmn", 177}, {"pound", 163}, {"prime", 8242}, {"prod", 8719}, {"prop", 8733}, {"psi", 968}, {"quad", 8193}, {"quot", 34}, {"rArr", 8658}, {"radic", 8730}, {"rang", 9002}, {"raquo", 187}, {"rarr", 8594}, {"rceil", 8969}, {"rdquo", 8221}, {"real", 8476}, {"reg", 174}, {"rfloor", 8971}, {"rho", 961}, {"rlm", 8207}, {"rsaquo", 8250}, {"rsquo", 8217}, {"sbquo", 8218}, {"scaron", 353}, {"sdot", 8901}, {"sect", 167}, {"shy", 173}, {"sigma", 963}, {"sigmaf", 962}, {"sim", 8764}, {"_sp", 8194}, {"spades", 9824}, {"sub", 8834}, {"sube", 8838}, {"sum", 8721}, {"sup", 8835}, {"sup1", 185}, {"sup2", 178}, {"sup3", 179}, {"supe", 8839}, {"szlig", 223}, {"tau", 964}, {"there4", 8756}, {"theta", 952}, {"thetasym", 977}, {"thinsp", 8201}, {"thorn", 254}, {"tilde", 732}, {"times", 215}, {"trade", 8482}, {"uArr", 8657}, {"uacute", 250}, {"uarr", 8593}, {"ucirc", 251}, {"ugrave", 249}, {"uml", 168}, {"upsih", 978}, {"upsilon", 965}, {"uuml", 252}, {"_varepsilon", 8712}, {"varphi", 981}, {"_varpi", 982}, {"varrho", 1009}, {"vdots", 8942}, {"_vsigma", 962}, {"_vtheta", 977}, {"weierp", 8472}, {"xi", 958}, {"yacute", 253}, {"yen", 165}, {"yuml", 255}, {"zeta", 950}, {"zwj", 8205}, {"zwnj", 8204}}; static Hchar byrune[nelem(byname)]; static inthnamecmp(const void *va, const void *vb){ Hchar *a, *b; a = (Hchar*)va; b = (Hchar*)vb; return strcmp(a->s, b->s);} static inthrunecmp(const void *va, const void *vb){ Hchar *a, *b; a = (Hchar*)va; b = (Hchar*)vb; return a->r - b->r;} static voidhtml_init(void){ static int init; int i; if(init) return; init = 1; memmove(byrune, byname, sizeof byrune); /* Eliminate names we aren't allowed to generate. */ for(i=0; i<nelem(byrune); i++){ if(byrune[i].s[0] == '_'){ byrune[i].r = Runeerror; byname[i].s++; } } qsort(byname, nelem(byname), sizeof byname[0], hnamecmp); qsort(byrune, nelem(byrune), sizeof byrune[0], hrunecmp);} static Runefindbyname(char *s){ Hchar *h; int n, m, x; h = byname; n = nelem(byname); while(n > 0){ m = n/2; x = strcmp(h[m].s, s); if(x == 0) return h[m].r; if(x < 0){ h += m+1; n -= m+1; }else n = m; } return Runeerror;} static char*findbyrune(Rune r){ Hchar *h; int n, m; if(r == Runeerror) return nil; h = byrune; n = nelem(byrune); while(n > 0){ m = n/2; if(h[m].r == r) return h[m].s; if(h[m].r < r){ h += m+1; n -= m+1; }else n = m; } return nil;} voidhtml_in(int fd, long *x, struct convert *out){ char buf[100], *p; Biobuf b; Rune rbuf[N]; Rune *r, *er; int c, i; USED(x); html_init(); r = rbuf; er = rbuf+N; Binit(&b, fd, OREAD); while((c = Bgetrune(&b)) != Beof){ if(r >= er){ OUT(out, rbuf, r-rbuf); r = rbuf; } if(c == '&'){ buf[0] = c; for(i=1; i<nelem(buf)-1;){ c = Bgetc(&b); if(c == Beof) break; buf[i++] = c; if(strchr("; \t\r\n", c)) break; } buf[i] = 0; if(buf[i-1] == ';'){ buf[i-1] = 0; if((c = findbyname(buf+1)) != Runeerror){ *r++ = c; continue; } buf[i-1] = ';'; if(buf[1] == '#'){ if(buf[2] == 'x') c = strtol(buf+3, &p, 16); else c = strtol(buf+2, &p, 10); if(*p != ';' || c >= NRUNE || c < 0) goto bad; *r++ = c; continue; } } bad: for(p=buf; p<buf+i; ){ p += chartorune(r++, p); if(r >= er){ OUT(out, rbuf, r-rbuf); r = rbuf; } } continue; } *r++ = c; } if(r > rbuf) OUT(out, rbuf, r-rbuf); OUT(out, rbuf, 0);} /* * use biobuf because can use more than UTFmax bytes per rune */voidhtml_out(Rune *r, int n, long *x){ char *s; Biobuf b; Rune *er; USED(x); html_init(); Binit(&b, 1, OWRITE); er = r+n; for(; r<er; r++){ if(*r < Runeself) Bputrune(&b, *r); else if((s = findbyrune(*r)) != nil) Bprint(&b, "&%s;", s); else Bprint(&b, "&#%d;", *r); } Bflush(&b);}
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "hdr.h"
#include "conv.h"
typedef struct Hchar Hchar;
struct Hchar
{
char *s;
Rune r;
};
/* <, >, ", & intentionally omitted */
/*
* Names beginning with _ are names we recognize
* (without the underscore) but will not generate,
* because they are nonstandard.
*/
static Hchar byname[] =
{
{"AElig", 198},
{"Aacute", 193},
{"Acirc", 194},
{"Agrave", 192},
{"Alpha", 913},
{"Aring", 197},
{"Atilde", 195},
{"Auml", 196},
{"Beta", 914},
{"Ccedil", 199},
{"Chi", 935},
{"Dagger", 8225},
{"Delta", 916},
{"ETH", 208},
{"Eacute", 201},
{"Ecirc", 202},
{"Egrave", 200},
{"Epsilon", 917},
{"Eta", 919},
{"Euml", 203},
{"Gamma", 915},
{"Iacute", 205},
{"Icirc", 206},
{"Igrave", 204},
{"Iota", 921},
{"Iuml", 207},
{"Kappa", 922},
{"Lambda", 923},
{"Mu", 924},
{"Ntilde", 209},
{"Nu", 925},
{"OElig", 338},
{"Oacute", 211},
{"Ocirc", 212},
{"Ograve", 210},
{"Omega", 937},
{"Omicron", 927},
{"Oslash", 216},
{"Otilde", 213},
{"Ouml", 214},
{"Phi", 934},
{"Pi", 928},
{"Prime", 8243},
{"Psi", 936},
{"Rho", 929},
{"Scaron", 352},
{"Sigma", 931},
{"THORN", 222},
{"Tau", 932},
{"Theta", 920},
{"Uacute", 218},
{"Ucirc", 219},
{"Ugrave", 217},
{"Upsilon", 933},
{"Uuml", 220},
{"Xi", 926},
{"Yacute", 221},
{"Yuml", 376},
{"Zeta", 918},
{"aacute", 225},
{"acirc", 226},
{"acute", 180},
{"aelig", 230},
{"agrave", 224},
{"alefsym", 8501},
{"alpha", 945},
{"amp", 38},
{"and", 8743},
{"ang", 8736},
{"aring", 229},
{"asymp", 8776},
{"atilde", 227},
{"auml", 228},
{"bdquo", 8222},
{"beta", 946},
{"brvbar", 166},
{"bull", 8226},
{"cap", 8745},
{"ccedil", 231},
{"cdots", 8943},
{"cedil", 184},
{"cent", 162},
{"chi", 967},
{"circ", 710},
{"clubs", 9827},
{"cong", 8773},
{"copy", 169},
{"crarr", 8629},
{"cup", 8746},
{"curren", 164},
{"dArr", 8659},
{"dagger", 8224},
{"darr", 8595},
{"ddots", 8945},
{"deg", 176},
{"delta", 948},
{"diams", 9830},
{"divide", 247},
{"eacute", 233},
{"ecirc", 234},
{"egrave", 232},
{"_emdash", 8212}, /* non-standard but commonly used */
{"empty", 8709},
{"emsp", 8195},
{"_endash", 8211}, /* non-standard but commonly used */
{"ensp", 8194},
{"epsilon", 949},
{"equiv", 8801},
{"eta", 951},
{"eth", 240},
{"euml", 235},
{"euro", 8364},
{"exist", 8707},
{"fnof", 402},
{"forall", 8704},
{"frac12", 189},
{"frac14", 188},
{"frac34", 190},
{"frasl", 8260},
{"gamma", 947},
{"ge", 8805},
{"gt", 62},
{"hArr", 8660},
{"harr", 8596},
{"hearts", 9829},
{"hellip", 8230},
{"iacute", 237},
{"icirc", 238},
{"iexcl", 161},
{"igrave", 236},
{"image", 8465},
{"infin", 8734},
{"int", 8747},
{"iota", 953},
{"iquest", 191},
{"isin", 8712},
{"iuml", 239},
{"kappa", 954},
{"lArr", 8656},
{"lambda", 955},
{"lang", 9001},
{"laquo", 171},
{"larr", 8592},
{"lceil", 8968},
{"_ldots", 8230},
{"ldquo", 8220},
{"le", 8804},
{"lfloor", 8970},
{"lowast", 8727},
{"loz", 9674},
{"lrm", 8206},
{"lsaquo", 8249},
{"lsquo", 8216},
{"lt", 60},
{"macr", 175},
{"mdash", 8212},
{"micro", 181},
{"middot", 183},
{"minus", 8722},
{"mu", 956},
{"nabla", 8711},
{"nbsp", 160},
{"ndash", 8211},
{"ne", 8800},
{"ni", 8715},
{"not", 172},
{"notin", 8713},
{"nsub", 8836},
{"ntilde", 241},
{"nu", 957},
{"oacute", 243},
{"ocirc", 244},
{"oelig", 339},
{"ograve", 242},
{"oline", 8254},
{"omega", 969},
{"omicron", 959},
{"oplus", 8853},
{"or", 8744},
{"ordf", 170},
{"ordm", 186},
{"oslash", 248},
{"otilde", 245},
{"otimes", 8855},
{"ouml", 246},
{"para", 182},
{"part", 8706},
{"permil", 8240},
{"perp", 8869},
{"phi", 966},
{"pi", 960},
{"piv", 982},
{"plusmn", 177},
{"pound", 163},
{"prime", 8242},
{"prod", 8719},
{"prop", 8733},
{"psi", 968},
{"quad", 8193},
{"quot", 34},
{"rArr", 8658},
{"radic", 8730},
{"rang", 9002},
{"raquo", 187},
{"rarr", 8594},
{"rceil", 8969},
{"rdquo", 8221},
{"real", 8476},
{"reg", 174},
{"rfloor", 8971},
{"rho", 961},
{"rlm", 8207},
{"rsaquo", 8250},
{"rsquo", 8217},
{"sbquo", 8218},
{"scaron", 353},
{"sdot", 8901},
{"sect", 167},
{"shy", 173},
{"sigma", 963},
{"sigmaf", 962},
{"sim", 8764},
{"_sp", 8194},
{"spades", 9824},
{"sub", 8834},
{"sube", 8838},
{"sum", 8721},
{"sup", 8835},
{"sup1", 185},
{"sup2", 178},
{"sup3", 179},
{"supe", 8839},
{"szlig", 223},
{"tau", 964},
{"there4", 8756},
{"theta", 952},
{"thetasym", 977},
{"thinsp", 8201},
{"thorn", 254},
{"tilde", 732},
{"times", 215},
{"trade", 8482},
{"uArr", 8657},
{"uacute", 250},
{"uarr", 8593},
{"ucirc", 251},
{"ugrave", 249},
{"uml", 168},
{"upsih", 978},
{"upsilon", 965},
{"uuml", 252},
{"_varepsilon", 8712},
{"varphi", 981},
{"_varpi", 982},
{"varrho", 1009},
{"vdots", 8942},
{"_vsigma", 962},
{"_vtheta", 977},
{"weierp", 8472},
{"xi", 958},
{"yacute", 253},
{"yen", 165},
{"yuml", 255},
{"zeta", 950},
{"zwj", 8205},
{"zwnj", 8204}
};
static Hchar byrune[nelem(byname)];
static int
hnamecmp(const void *va, const void *vb)
{
Hchar *a, *b;
a = (Hchar*)va;
b = (Hchar*)vb;
return strcmp(a->s, b->s);
}
static int
hrunecmp(const void *va, const void *vb)
{
Hchar *a, *b;
a = (Hchar*)va;
b = (Hchar*)vb;
return a->r - b->r;
}
static void
html_init(void)
{
static int init;
int i;
if(init)
return;
init = 1;
memmove(byrune, byname, sizeof byrune);
/* Eliminate names we aren't allowed to generate. */
for(i=0; i<nelem(byrune); i++){
if(byrune[i].s[0] == '_'){
byrune[i].r = Runeerror;
byname[i].s++;
}
}
qsort(byname, nelem(byname), sizeof byname[0], hnamecmp);
qsort(byrune, nelem(byrune), sizeof byrune[0], hrunecmp);
}
static Rune
findbyname(char *s)
{
Hchar *h;
int n, m, x;
h = byname;
n = nelem(byname);
while(n > 0){
m = n/2;
x = strcmp(h[m].s, s);
if(x == 0)
return h[m].r;
if(x < 0){
h += m+1;
n -= m+1;
}else
n = m;
}
return Runeerror;
}
static char*
findbyrune(Rune r)
{
Hchar *h;
int n, m;
if(r == Runeerror)
return nil;
h = byrune;
n = nelem(byrune);
while(n > 0){
m = n/2;
if(h[m].r == r)
return h[m].s;
if(h[m].r < r){
h += m+1;
n -= m+1;
}else
n = m;
}
return nil;
}
void
html_in(int fd, long *x, struct convert *out)
{
char buf[100], *p;
Biobuf b;
Rune rbuf[N];
Rune *r, *er;
int c, i;
USED(x);
html_init();
r = rbuf;
er = rbuf+N;
Binit(&b, fd, OREAD);
while((c = Bgetrune(&b)) != Beof){
if(r >= er){
OUT(out, rbuf, r-rbuf);
r = rbuf;
}
if(c == '&'){
buf[0] = c;
for(i=1; i<nelem(buf)-1;){
c = Bgetc(&b);
if(c == Beof)
break;
buf[i++] = c;
if(strchr("; \t\r\n", c))
break;
}
buf[i] = 0;
if(buf[i-1] == ';'){
buf[i-1] = 0;
if((c = findbyname(buf+1)) != Runeerror){
*r++ = c;
continue;
}
buf[i-1] = ';';
if(buf[1] == '#'){
if(buf[2] == 'x')
c = strtol(buf+3, &p, 16);
else
c = strtol(buf+2, &p, 10);
if(*p != ';' || c >= NRUNE || c < 0)
goto bad;
*r++ = c;
continue;
}
}
bad:
for(p=buf; p<buf+i; ){
p += chartorune(r++, p);
if(r >= er){
OUT(out, rbuf, r-rbuf);
r = rbuf;
}
}
continue;
}
*r++ = c;
}
if(r > rbuf)
OUT(out, rbuf, r-rbuf);
OUT(out, rbuf, 0);
}
/*
* use biobuf because can use more than UTFmax bytes per rune
*/
void
html_out(Rune *r, int n, long *x)
{
char *s;
Biobuf b;
Rune *er;
USED(x);
html_init();
Binit(&b, 1, OWRITE);
er = r+n;
for(; r<er; r++){
if(*r < Runeself)
Bputrune(&b, *r);
else if((s = findbyrune(*r)) != nil)
Bprint(&b, "&%s;", s);
else
Bprint(&b, "&#%d;", *r);
}
Bflush(&b);
}