/* * To do: * <!doctype> not implemented * forms */#include <u.h>#include <libc.h>#include <libg.h>#include <panel.h>#include "mothra.h"#include "html.h"typedef struct Fontdata Fontdata;struct Fontdata{ char *name; Font *font; int space;}fontlist[4][4]={ "lucidasans/latin1.6", 0, 0, "lucidasans/latin1.7", 0, 0, "lucidasans/latin1.10", 0, 0, "lucidasans/latin1.13", 0, 0, "lucidasans/italiclatin1.6", 0, 0, "lucidasans/italiclatin1.7", 0, 0, "lucidasans/italiclatin1.10", 0, 0, "lucidasans/italiclatin1.13", 0, 0, "lucidasans/boldlatin1.6", 0, 0, "lucidasans/boldlatin1.7", 0, 0, "lucidasans/boldlatin1.10", 0, 0, "lucidasans/boldlatin1.13", 0, 0, "lucidasans/typelatin1.6", 0, 0, "lucidasans/typelatin1.7", 0, 0, "pelm/ascii.12", 0, 0, "pelm/ascii.16", 0, 0,};Fontdata *pl_whichfont(int f, int s){ char name[100]; if(fontlist[f][s].font==0){ sprint(name, "/lib/font/bit/%s.font", fontlist[f][s].name); fontlist[f][s].font=rdfontfile(name, screen.ldepth); if(fontlist[f][s].font==0) fontlist[f][s].font=font; fontlist[f][s].space=strwidth(fontlist[f][s].font, "0"); } return &fontlist[f][s]; }void getfonts(void){ int f, s; for(f=0;f!=4;f++) for(s=0;s!=4;s++) pl_whichfont(f, s);}void pl_pushstate(Hglob *g, int t){ ++g->state; if(g->state==&g->stack[NSTACK]){ htmlerror(g->name, g->lineno, "stack overflow at <%s>", tag[t].name); --g->state; } g->state[0]=g->state[-1]; g->state->tag=t;}void pl_linespace(Hglob *g){ plrtstr(&g->dst->text, 1000000, 1000000, font, "", 0, 0); g->para=0; g->linebrk=0;}void pl_htmloutput(Hglob *g, int nsp, char *s, Field *field){ Fontdata *f; int space, indent; Action *ap; if(g->state->tag==Tag_title/* || g->state->tag==Tag_textarea */ || g->state->tag==Tag_select){ if(s){ if(g->tp!=g->text && g->tp!=g->etext && g->tp[-1]!=' ') *g->tp++=' '; while(g->tp!=g->etext && *s) *g->tp++=*s++; if(g->state->tag==Tag_title) g->dst->changed=1; } return; } f=pl_whichfont(g->state->font, g->state->size); space=f->space; indent=g->state->margin; if(g->para){ space=1000000; indent+=g->state->indent; } else if(g->linebrk) space=1000000; else if(nsp<=0) space=0; if(g->state->image==0 && g->state->link==0 && g->state->name==0 && field==0) ap=0; else{ ap=malloc(sizeof(Action)); if(ap!=0){ ap->image=g->state->image; ap->link=g->state->link; ap->name=g->state->name; ap->ismap=g->state->ismap; ap->imagebits=0; ap->field=field; } } plrtstr(&g->dst->text, space, indent, f->font, strdup(s), g->state->link!=0, ap); g->para=0; g->linebrk=0; g->dst->changed=1;}int pl_readc(Hglob *g){ int n, c; char err[1024]; do{ if(g->hbufp==g->ehbuf){ n=read(g->hfd, g->hbuf, NHBUF); if(n<=0){ if(n<0){ sprint(err, "%r reading %s", g->name); pl_htmloutput(g, 1, err, 0); } if(g->dst->url->cachefd!=-1) close(g->dst->url->cachefd); g->heof=1; return EOF; } if(g->dst->url->cachefd!=-1) write(g->dst->url->cachefd, g->hbuf, n); g->hbufp=g->hbuf; g->ehbuf=g->hbuf+n; } c=*g->hbufp++&255; }while(c=='\r'); /* dos machines? add spurious crs */ if(c=='\n') g->lineno++; return c;}void pl_putback(Hglob *g, int c){ if(g->npeekc==NPEEKC) htmlerror(g->name, g->lineno, "too much putback!"); else if(c!=EOF) g->peekc[g->npeekc++]=c;}int pl_nextc(Hglob *g){ int c; if(g->heof) return EOF; if(g->npeekc!=0) return g->peekc[--g->npeekc]; c=pl_readc(g); if(c=='<'){ c=pl_readc(g); if(c=='/'){ c=pl_readc(g); pl_putback(g, c); pl_putback(g, '/'); if('a'<=c && c<='z' || 'A'<=c && c<='Z') return STAG; return '<'; } pl_putback(g, c); if(c=='!' || 'a'<=c && c<='z' || 'A'<=c && c<='Z') return STAG; return '<'; } if(c=='>') return ETAG; return c;}int entchar(int c){ return c=='#' || 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9';}/* * remove entity references, in place. * Potential bug: * This doesn't work if removing an entity reference can lengthen the string! * Fortunately, this doesn't happen. */void pl_rmentities(Hglob *g, char *s){ char *t, *u, c; Pair *ep; char ebuf[4]; Rune r; t=s; do{ c=*s++; if(c=='&' && ((*s=='#' && ('A'<=s[1] && s[1]<='Z' || '0'<=s[1] && s[1]<='9')) || 'a'<=*s && *s<='z' || 'A'<=*s && *s<='Z')){ u=s; while(entchar(*s)) s++; if(*s!=';'){ htmlerror(g->name, g->lineno, "entity syntax error"); s=u; *t++='&'; } else{ *s++='\0'; if(*u=='#' && '0'<=u[1] && u[1]<='9'){ r=atoi(u+1); if(r==0xa0) r=' '; sprint(ebuf, "%C", r); u=ebuf; } else{ for(ep=pl_entity;ep->name;ep++) if(strcmp(ep->name, u)==0) break; if(ep->name) u=ep->value; else{ htmlerror(g->name, g->lineno, "unknown entity %s", u); s[-1]=';'; s=u; *t++='&'; u=""; } } while(*u) *t++=*u++; } } else *t++=c; }while(c);}/* * Skip over spaces */char *pl_space(char *s){ while(*s==' ' || *s=='\t' || *s=='\n' || *s=='\r') s++; return s;}/* * Skip over alphabetics */char *pl_word(char *s){ while('a'<=*s && *s<='z' || 'A'<=*s && *s<='Z' || '0'<=*s && *s<='9') s++; return s;}/* * Skip to matching quote */char *pl_quote(char *s){ char q; q=*s++; while(*s!=q && *s!='\0') s++; return s;}void pl_tagparse(Hglob *g, char *str){ char *s, *t, *name, c; Pair *ap; Tag *tagp; ap=g->attr; if(str[0]=='!'){ /* test should be strncmp(str, "!--", 3)==0 */ g->tag=Tag_comment; ap->name=0; return; } if(str[0]=='/') str++; name=str; s=pl_word(str); if(*s!=' ' && *s!='\n' && *s!='\t' && *s!='\0'){ htmlerror(g->name, g->lineno, "bad tag name in %s", str); ap->name=0; return; } if(*s!='\0') *s++='\0'; for(t=name;t!=s;t++) if('A'<=*t && *t<='Z') *t+='a'-'A'; /* * Binary search would be faster here */ for(tagp=tag;tagp->name;tagp++) if(strcmp(name, tagp->name)==0) break; g->tag=tagp-tag; if(g->tag==Tag_end) htmlerror(g->name, g->lineno, "no tag %s", name); for(;;){ s=pl_space(s); if(*s=='\0'){ ap->name=0; return; } ap->name=s; s=pl_word(s); t=pl_space(s); c=*t; *s='\0'; for(s=ap->name;*s;s++) if('A'<=*s && *s<='Z') *s+='a'-'A'; if(c=='='){ s=pl_space(t+1); if(*s=='\'' || *s=='"'){ ap->value=s+1; s=pl_quote(s); if(*s=='\0'){ htmlerror(g->name, g->lineno, "No terminating quote in rhs of attribute %s", ap->name); ap->name=0; return; } *s++='\0'; } else{ /* read up to white space or > */ ap->value=s; while(*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0') s++; if(*s!='\0') *s++='\0'; } pl_rmentities(g, ap->value); } else{ if(c!='\0') s++; ap->value=""; } if(ap==&g->attr[NATTR-1]) htmlerror(g->name, g->lineno, "too many attributes!"); else ap++; }}/* * Read a start or end tag -- the caller has read the initial < */int pl_gettag(Hglob *g){ char *tokp; int c; tokp=g->token; while((c=pl_nextc(g))!=ETAG && c!=EOF) if(tokp!=&g->token[NTOKEN-1]) *tokp++=c; *tokp='\0'; if(c==EOF) htmlerror(g->name, g->lineno, "EOF in tag"); pl_tagparse(g, g->token); if(g->token[0]!='/') return TAG; if(g->attr[0].name!=0) htmlerror(g->name, g->lineno, "end tag should not have attributes"); return ENDTAG;}/* * The next token is a tag, an end tag or a sequence of * non-white characters. * If inside <pre>, newlines are converted to <br> and spaces are preserved. * Otherwise, spaces and newlines are noted and discarded. */int pl_gettoken(Hglob *g){ char *tokp; int c; if(g->state->pre) switch(c=pl_nextc(g)){ case STAG: return pl_gettag(g); case EOF: return EOF; case '\n': pl_tagparse(g, "br"); return TAG; default: tokp=g->token; do{ if(c==ETAG) c='>'; if(tokp!=&g->token[NTOKEN-1]) *tokp++=c; c=pl_nextc(g); }while(c!='\n' && c!=STAG && c!=EOF); *tokp='\0'; pl_rmentities(g, g->token); pl_putback(g, c); g->nsp=0; g->spacc=0; return TEXT; } while((c=pl_nextc(g))==' ' || c=='\t' || c=='\n') if(g->spacc!=-1) g->spacc++; switch(c){ case STAG: return pl_gettag(g); case EOF: return EOF; default: tokp=g->token; do{ if(c==ETAG) c='>'; if(tokp!=&g->token[NTOKEN-1]) *tokp++=c; c=pl_nextc(g); }while(c!=' ' && c!='\t' && c!='\n' && c!=STAG && c!=EOF); *tokp='\0'; pl_rmentities(g, g->token); pl_putback(g, c); g->nsp=g->spacc; g->spacc=0; return TEXT; }}char *pl_getattr(Pair *attr, char *name){ for(;attr->name;attr++) if(strcmp(attr->name, name)==0) return attr->value; return 0;}int pl_hasattr(Pair *attr, char *name){ for(;attr->name;attr++) if(strcmp(attr->name, name)==0) return 1; return 0;}#define NLINE 256void plaintext(Hglob *g){ char line[NLINE]; char *lp, *elp; int c; g->state->font=CWIDTH; g->state->size=NORMAL; g->state->pre=1; elp=&line[NLINE+1]; lp=line; for(;;){ c=pl_readc(g); if(c==EOF) break; if(c=='\n' || lp==elp){ *lp='\0'; pl_htmloutput(g, 0, line, 0); lp=line; } if(c!='\n') *lp++=c; } if(lp!=line){ *lp='\0'; pl_htmloutput(g, 0, line, 0); }}void plrdplain(char *name, int fd, Www *dst){ Hglob g; g.state=g.stack; g.state->tag=Tag_html; g.state->font=CWIDTH; g.state->size=NORMAL; g.state->pre=0; g.state->image=0; g.state->link=0; g.state->name=0; g.state->margin=0; g.state->indent=20; g.state->ismap=0; g.dst=dst; g.hfd=fd; g.name=name; g.ehbuf=g.hbufp=g.hbuf; g.npeekc=0; g.heof=0; g.lineno=1; g.linebrk=1; g.para=0; g.text=dst->title; g.tp=g.text; g.etext=g.text+NTITLE-1; g.spacc=0; g.form=0; strncpy(g.text, name, NTITLE); plaintext(&g); dst->finished=1;}void plrdhtml(char *name, int fd, Www *dst){ Stack *sp; char buf[20]; char *str; Hglob g; int tagerr; g.state=g.stack; g.state->tag=Tag_html; g.state->font=ROMAN; g.state->size=NORMAL; g.state->pre=0; g.state->image=0; g.state->link=0; g.state->name=0; g.state->margin=0; g.state->indent=25; g.state->ismap=0; g.dst=dst; g.hfd=fd; g.name=name; g.ehbuf=g.hbufp=g.hbuf; g.npeekc=0; g.heof=0; g.lineno=1; g.linebrk=1; g.para=0; g.text=dst->title; g.tp=g.text; g.etext=g.text+NTITLE-1; g.spacc=0; g.form=0; for(;;) switch(pl_gettoken(&g)){ case TAG: switch(tag[g.tag].action){ case OPTEND: for(sp=g.state;sp!=g.stack && sp->tag!=g.tag;--sp); if(sp->tag!=g.tag) pl_pushstate(&g, g.tag); else for(;g.state!=sp;--g.state) if(tag[g.state->tag].action!=OPTEND) htmlerror(g.name, g.lineno, "end tag </%s> missing", tag[g.state->tag].name); break; case END: pl_pushstate(&g, g.tag); break; } switch(g.tag){ default:Lines 1–500 of 798. Load more
/* * To do: * <!doctype> not implemented * forms */ #include <u.h> #include <libc.h> #include <libg.h> #include <panel.h> #include "mothra.h" #include "html.h" typedef struct Fontdata Fontdata; struct Fontdata{ char *name; Font *font; int space; }fontlist[4][4]={ "lucidasans/latin1.6", 0, 0, "lucidasans/latin1.7", 0, 0, "lucidasans/latin1.10", 0, 0, "lucidasans/latin1.13", 0, 0, "lucidasans/italiclatin1.6", 0, 0, "lucidasans/italiclatin1.7", 0, 0, "lucidasans/italiclatin1.10", 0, 0, "lucidasans/italiclatin1.13", 0, 0, "lucidasans/boldlatin1.6", 0, 0, "lucidasans/boldlatin1.7", 0, 0, "lucidasans/boldlatin1.10", 0, 0, "lucidasans/boldlatin1.13", 0, 0, "lucidasans/typelatin1.6", 0, 0, "lucidasans/typelatin1.7", 0, 0, "pelm/ascii.12", 0, 0, "pelm/ascii.16", 0, 0, }; Fontdata *pl_whichfont(int f, int s){ char name[100]; if(fontlist[f][s].font==0){ sprint(name, "/lib/font/bit/%s.font", fontlist[f][s].name); fontlist[f][s].font=rdfontfile(name, screen.ldepth); if(fontlist[f][s].font==0) fontlist[f][s].font=font; fontlist[f][s].space=strwidth(fontlist[f][s].font, "0"); } return &fontlist[f][s]; } void getfonts(void){ int f, s; for(f=0;f!=4;f++) for(s=0;s!=4;s++) pl_whichfont(f, s); } void pl_pushstate(Hglob *g, int t){ ++g->state; if(g->state==&g->stack[NSTACK]){ htmlerror(g->name, g->lineno, "stack overflow at <%s>", tag[t].name); --g->state; } g->state[0]=g->state[-1]; g->state->tag=t; } void pl_linespace(Hglob *g){ plrtstr(&g->dst->text, 1000000, 1000000, font, "", 0, 0); g->para=0; g->linebrk=0; } void pl_htmloutput(Hglob *g, int nsp, char *s, Field *field){ Fontdata *f; int space, indent; Action *ap; if(g->state->tag==Tag_title /* || g->state->tag==Tag_textarea */ || g->state->tag==Tag_select){ if(s){ if(g->tp!=g->text && g->tp!=g->etext && g->tp[-1]!=' ') *g->tp++=' '; while(g->tp!=g->etext && *s) *g->tp++=*s++; if(g->state->tag==Tag_title) g->dst->changed=1; } return; } f=pl_whichfont(g->state->font, g->state->size); space=f->space; indent=g->state->margin; if(g->para){ space=1000000; indent+=g->state->indent; } else if(g->linebrk) space=1000000; else if(nsp<=0) space=0; if(g->state->image==0 && g->state->link==0 && g->state->name==0 && field==0) ap=0; else{ ap=malloc(sizeof(Action)); if(ap!=0){ ap->image=g->state->image; ap->link=g->state->link; ap->name=g->state->name; ap->ismap=g->state->ismap; ap->imagebits=0; ap->field=field; } } plrtstr(&g->dst->text, space, indent, f->font, strdup(s), g->state->link!=0, ap); g->para=0; g->linebrk=0; g->dst->changed=1; } int pl_readc(Hglob *g){ int n, c; char err[1024]; do{ if(g->hbufp==g->ehbuf){ n=read(g->hfd, g->hbuf, NHBUF); if(n<=0){ if(n<0){ sprint(err, "%r reading %s", g->name); pl_htmloutput(g, 1, err, 0); } if(g->dst->url->cachefd!=-1) close(g->dst->url->cachefd); g->heof=1; return EOF; } if(g->dst->url->cachefd!=-1) write(g->dst->url->cachefd, g->hbuf, n); g->hbufp=g->hbuf; g->ehbuf=g->hbuf+n; } c=*g->hbufp++&255; }while(c=='\r'); /* dos machines? add spurious crs */ if(c=='\n') g->lineno++; return c; } void pl_putback(Hglob *g, int c){ if(g->npeekc==NPEEKC) htmlerror(g->name, g->lineno, "too much putback!"); else if(c!=EOF) g->peekc[g->npeekc++]=c; } int pl_nextc(Hglob *g){ int c; if(g->heof) return EOF; if(g->npeekc!=0) return g->peekc[--g->npeekc]; c=pl_readc(g); if(c=='<'){ c=pl_readc(g); if(c=='/'){ c=pl_readc(g); pl_putback(g, c); pl_putback(g, '/'); if('a'<=c && c<='z' || 'A'<=c && c<='Z') return STAG; return '<'; } pl_putback(g, c); if(c=='!' || 'a'<=c && c<='z' || 'A'<=c && c<='Z') return STAG; return '<'; } if(c=='>') return ETAG; return c; } int entchar(int c){ return c=='#' || 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9'; } /* * remove entity references, in place. * Potential bug: * This doesn't work if removing an entity reference can lengthen the string! * Fortunately, this doesn't happen. */ void pl_rmentities(Hglob *g, char *s){ char *t, *u, c; Pair *ep; char ebuf[4]; Rune r; t=s; do{ c=*s++; if(c=='&' && ((*s=='#' && ('A'<=s[1] && s[1]<='Z' || '0'<=s[1] && s[1]<='9')) || 'a'<=*s && *s<='z' || 'A'<=*s && *s<='Z')){ u=s; while(entchar(*s)) s++; if(*s!=';'){ htmlerror(g->name, g->lineno, "entity syntax error"); s=u; *t++='&'; } else{ *s++='\0'; if(*u=='#' && '0'<=u[1] && u[1]<='9'){ r=atoi(u+1); if(r==0xa0) r=' '; sprint(ebuf, "%C", r); u=ebuf; } else{ for(ep=pl_entity;ep->name;ep++) if(strcmp(ep->name, u)==0) break; if(ep->name) u=ep->value; else{ htmlerror(g->name, g->lineno, "unknown entity %s", u); s[-1]=';'; s=u; *t++='&'; u=""; } } while(*u) *t++=*u++; } } else *t++=c; }while(c); } /* * Skip over spaces */ char *pl_space(char *s){ while(*s==' ' || *s=='\t' || *s=='\n' || *s=='\r') s++; return s; } /* * Skip over alphabetics */ char *pl_word(char *s){ while('a'<=*s && *s<='z' || 'A'<=*s && *s<='Z' || '0'<=*s && *s<='9') s++; return s; } /* * Skip to matching quote */ char *pl_quote(char *s){ char q; q=*s++; while(*s!=q && *s!='\0') s++; return s; } void pl_tagparse(Hglob *g, char *str){ char *s, *t, *name, c; Pair *ap; Tag *tagp; ap=g->attr; if(str[0]=='!'){ /* test should be strncmp(str, "!--", 3)==0 */ g->tag=Tag_comment; ap->name=0; return; } if(str[0]=='/') str++; name=str; s=pl_word(str); if(*s!=' ' && *s!='\n' && *s!='\t' && *s!='\0'){ htmlerror(g->name, g->lineno, "bad tag name in %s", str); ap->name=0; return; } if(*s!='\0') *s++='\0'; for(t=name;t!=s;t++) if('A'<=*t && *t<='Z') *t+='a'-'A'; /* * Binary search would be faster here */ for(tagp=tag;tagp->name;tagp++) if(strcmp(name, tagp->name)==0) break; g->tag=tagp-tag; if(g->tag==Tag_end) htmlerror(g->name, g->lineno, "no tag %s", name); for(;;){ s=pl_space(s); if(*s=='\0'){ ap->name=0; return; } ap->name=s; s=pl_word(s); t=pl_space(s); c=*t; *s='\0'; for(s=ap->name;*s;s++) if('A'<=*s && *s<='Z') *s+='a'-'A'; if(c=='='){ s=pl_space(t+1); if(*s=='\'' || *s=='"'){ ap->value=s+1; s=pl_quote(s); if(*s=='\0'){ htmlerror(g->name, g->lineno, "No terminating quote in rhs of attribute %s", ap->name); ap->name=0; return; } *s++='\0'; } else{ /* read up to white space or > */ ap->value=s; while(*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0') s++; if(*s!='\0') *s++='\0'; } pl_rmentities(g, ap->value); } else{ if(c!='\0') s++; ap->value=""; } if(ap==&g->attr[NATTR-1]) htmlerror(g->name, g->lineno, "too many attributes!"); else ap++; } } /* * Read a start or end tag -- the caller has read the initial < */ int pl_gettag(Hglob *g){ char *tokp; int c; tokp=g->token; while((c=pl_nextc(g))!=ETAG && c!=EOF) if(tokp!=&g->token[NTOKEN-1]) *tokp++=c; *tokp='\0'; if(c==EOF) htmlerror(g->name, g->lineno, "EOF in tag"); pl_tagparse(g, g->token); if(g->token[0]!='/') return TAG; if(g->attr[0].name!=0) htmlerror(g->name, g->lineno, "end tag should not have attributes"); return ENDTAG; } /* * The next token is a tag, an end tag or a sequence of * non-white characters. * If inside <pre>, newlines are converted to <br> and spaces are preserved. * Otherwise, spaces and newlines are noted and discarded. */ int pl_gettoken(Hglob *g){ char *tokp; int c; if(g->state->pre) switch(c=pl_nextc(g)){ case STAG: return pl_gettag(g); case EOF: return EOF; case '\n': pl_tagparse(g, "br"); return TAG; default: tokp=g->token; do{ if(c==ETAG) c='>'; if(tokp!=&g->token[NTOKEN-1]) *tokp++=c; c=pl_nextc(g); }while(c!='\n' && c!=STAG && c!=EOF); *tokp='\0'; pl_rmentities(g, g->token); pl_putback(g, c); g->nsp=0; g->spacc=0; return TEXT; } while((c=pl_nextc(g))==' ' || c=='\t' || c=='\n') if(g->spacc!=-1) g->spacc++; switch(c){ case STAG: return pl_gettag(g); case EOF: return EOF; default: tokp=g->token; do{ if(c==ETAG) c='>'; if(tokp!=&g->token[NTOKEN-1]) *tokp++=c; c=pl_nextc(g); }while(c!=' ' && c!='\t' && c!='\n' && c!=STAG && c!=EOF); *tokp='\0'; pl_rmentities(g, g->token); pl_putback(g, c); g->nsp=g->spacc; g->spacc=0; return TEXT; } } char *pl_getattr(Pair *attr, char *name){ for(;attr->name;attr++) if(strcmp(attr->name, name)==0) return attr->value; return 0; } int pl_hasattr(Pair *attr, char *name){ for(;attr->name;attr++) if(strcmp(attr->name, name)==0) return 1; return 0; } #define NLINE 256 void plaintext(Hglob *g){ char line[NLINE]; char *lp, *elp; int c; g->state->font=CWIDTH; g->state->size=NORMAL; g->state->pre=1; elp=&line[NLINE+1]; lp=line; for(;;){ c=pl_readc(g); if(c==EOF) break; if(c=='\n' || lp==elp){ *lp='\0'; pl_htmloutput(g, 0, line, 0); lp=line; } if(c!='\n') *lp++=c; } if(lp!=line){ *lp='\0'; pl_htmloutput(g, 0, line, 0); } } void plrdplain(char *name, int fd, Www *dst){ Hglob g; g.state=g.stack; g.state->tag=Tag_html; g.state->font=CWIDTH; g.state->size=NORMAL; g.state->pre=0; g.state->image=0; g.state->link=0; g.state->name=0; g.state->margin=0; g.state->indent=20; g.state->ismap=0; g.dst=dst; g.hfd=fd; g.name=name; g.ehbuf=g.hbufp=g.hbuf; g.npeekc=0; g.heof=0; g.lineno=1; g.linebrk=1; g.para=0; g.text=dst->title; g.tp=g.text; g.etext=g.text+NTITLE-1; g.spacc=0; g.form=0; strncpy(g.text, name, NTITLE); plaintext(&g); dst->finished=1; } void plrdhtml(char *name, int fd, Www *dst){ Stack *sp; char buf[20]; char *str; Hglob g; int tagerr; g.state=g.stack; g.state->tag=Tag_html; g.state->font=ROMAN; g.state->size=NORMAL; g.state->pre=0; g.state->image=0; g.state->link=0; g.state->name=0; g.state->margin=0; g.state->indent=25; g.state->ismap=0; g.dst=dst; g.hfd=fd; g.name=name; g.ehbuf=g.hbufp=g.hbuf; g.npeekc=0; g.heof=0; g.lineno=1; g.linebrk=1; g.para=0; g.text=dst->title; g.tp=g.text; g.etext=g.text+NTITLE-1; g.spacc=0; g.form=0; for(;;) switch(pl_gettoken(&g)){ case TAG: switch(tag[g.tag].action){ case OPTEND: for(sp=g.state;sp!=g.stack && sp->tag!=g.tag;--sp); if(sp->tag!=g.tag) pl_pushstate(&g, g.tag); else for(;g.state!=sp;--g.state) if(tag[g.state->tag].action!=OPTEND) htmlerror(g.name, g.lineno, "end tag </%s> missing", tag[g.state->tag].name); break; case END: pl_pushstate(&g, g.tag); break; } switch(g.tag){ default: