6 typedef struct Tag Tag;
7 typedef struct Attr Attr;
8 typedef struct Text Text;
23 void (*close)(Text *, Tag *);
39 Tag *parsetext(Text *, Tag *);
41 int parseattr(Attr *);
46 emit(Text *text, char *fmt, ...)
55 Bvprint(&out, fmt, a);
60 restoreoutput(Text *text, Tag *tag)
62 text->output = tag->restore;
66 ongarbage(Text *text, Tag *tag)
68 tag->restore = text->output;
69 tag->close = restoreoutput;
74 onp(Text *text, Tag *)
80 restorepre(Text *text, Tag *tag)
82 text->pre = tag->restore;
87 onpre(Text *text, Tag *tag)
89 tag->restore = text->pre;
90 tag->close = restorepre;
92 emit(text, ".DS L\n");
96 onli(Text *text, Tag *tag)
98 if(tag->up && cistrcmp(tag->up->tag, "ol") == 0)
101 emit(text, ".IP \\(bu\n");
103 tag->up->close = onp;
107 onh(Text *text, Tag *tag)
109 emit(text, ".SH %c\n", tag->tag[1]);
114 onbr(Text *text, Tag *tag)
118 if(cistrcmp(tag->tag, "hr") == 0)
119 emit(text, "\\l'5i'\n.br\n");
123 restorefont(Text *text, Tag *tag)
125 text->font = tag->restore;
126 text->pos += Bprint(&out, "\\f%c", text->font);
130 onfont(Text *text, Tag *tag)
134 tag->restore = text->font;
135 tag->close = restorefont;
136 if(cistrcmp(tag->tag, "i") == 0)
138 else if(cistrcmp(tag->tag, "b") == 0)
140 text->pos += Bprint(&out, "\\f%c", text->font);
145 void (*open)(Text *, Tag *);
169 while((c = Bgetc(&in)) > 0){
170 if(strchr("\n\r\t ", c) == nil){
185 while((c = Bgetc(&in)) > 0){
188 if(n == 0 && c == '-'){
189 while((c = Bgetc(&in)) > 0){
191 if(Bgetc(&in) == '-')
192 if(Bgetc(&in) == '>')
196 if(n+1 < sizeof(buf)){
198 if(n != 7 || cistrncmp(buf, "[CDATA[", 7))
200 while((c = Bgetc(&in)) > 0){
202 if(Bgetc(&in) == ']')
203 if(Bgetc(&in) == '>')
217 while((c = Bgetc(&in)) > 0){
218 if(strchr("</>=?!", c)){
222 if(strchr("\n\r\t ", c))
224 if(n < sizeof(a->attr)-1)
232 if(Bgetc(&in) == '='){
235 if(strchr("'\"", c)){
237 while((c = Bgetc(&in)) > 0){
240 if(n < sizeof(a->val)-1)
245 while((c = Bgetc(&in)) > 0){
246 if(strchr("\n\r\t </>?!", c)){
250 if(n < sizeof(a->val)-1)
271 while((c = Bgetc(&in)) > 0){
274 if(strchr("\n\r\t ", c)){
275 if(parseattr(t->attr + t->nattr))
276 if(t->nattr < nelem(t->attr)-1)
280 if(n == 0 && strchr("?!", c)){
292 if(n < sizeof(t->tag)-1)
308 while((c = Bgetc(&in)) > 0){
309 if(strchr(";&</>\n\r\t ", c)){
316 if(n == sizeof(buf)-1)
321 if(strcmp(buf, "lt") == 0)
323 if(strcmp(buf, "gt") == 0)
325 if(strcmp(buf, "quot") == 0)
327 if(strcmp(buf, "amp") == 0)
329 /* use tcs -f html to handle the rest. */
333 if(fullrune(buf, n)){
339 } while((c = Bgetc(&in)) > 0);
360 debugtag(Tag *tag, char *dbg)
366 debugtag(tag->up, nil);
367 fprint(2, "%s %s%s", tag->tag, dbg ? dbg : " > ", dbg ? "\n" : "");
372 parsetext(Text *text, Tag *tag)
379 debugtag(tag, "open");
380 if(tag == nil || tag->closing == 0){
381 while((c = Bgetc(&in)) > 0){
385 memset(&t, 0, sizeof(t));
389 for(c = 0; c < nelem(ontag); c++){
390 if(cistrcmp(t.tag, ontag[c].tag) == 0){
391 ontag[c].open(text, &t);
395 rtag = parsetext(text, &t);
400 } else if(t.closing){
401 while(rtag && cistrcmp(rtag->tag, t.tag))
413 r = substrune(parserune(c));
424 if(r == '\n' || r == '\r')
431 } else if(text->pos > 0){
436 if(text->pos == 0 && r == '.'){
445 Bprint(&out, "%C", r);
449 debugtag(tag, "close");
450 if(tag && tag->close)
451 tag->close(text, tag);
460 Binit(&in, 0, OREAD);
461 Binit(&out, 1, OWRITE);
463 memset(&text, 0, sizeof(text));
465 parsetext(&text, nil);