6 typedef struct Tag Tag;
7 typedef struct Attr Attr;
8 typedef struct Text Text;
23 void (*close)(Text *, Tag *);
40 Tag *parsetext(Text *, Tag *);
42 int parseattr(Attr *);
47 emit(Text *text, char *fmt, ...)
56 Bvprint(&out, fmt, a);
61 restoreoutput(Text *text, Tag *tag)
63 text->output = tag->restore;
67 ongarbage(Text *text, Tag *tag)
69 tag->restore = text->output;
70 tag->close = restoreoutput;
75 onp(Text *text, Tag *)
81 restorepre(Text *text, Tag *tag)
83 text->pre = tag->restore;
88 onpre(Text *text, Tag *tag)
90 tag->restore = text->pre;
91 tag->close = restorepre;
93 emit(text, ".DS L\n");
97 onli(Text *text, Tag *tag)
99 if(tag->up && cistrcmp(tag->up->tag, "ol") == 0)
102 emit(text, ".IP \\(bu\n");
104 tag->up->close = onp;
108 onh(Text *text, Tag *tag)
110 emit(text, ".SH %c\n", tag->tag[1]);
115 onbr(Text *text, Tag *tag)
119 if(cistrcmp(tag->tag, "hr") == 0)
120 emit(text, "\\l'5i'\n.br\n");
124 restorefont(Text *text, Tag *tag)
126 text->font = tag->aux;
127 text->pos += Bprint(&out, "\\f%s", text->font);
131 onfont(Text *text, Tag *tag)
135 tag->aux = text->font;
136 tag->close = restorefont;
137 if(cistrcmp(tag->tag, "i") == 0)
139 else if(cistrcmp(tag->tag, "b") == 0)
141 text->pos += Bprint(&out, "\\f%s", text->font);
145 ona(Text *text, Tag *)
152 void (*open)(Text *, Tag *);
178 while((c = Bgetc(&in)) > 0){
179 if(strchr("\n\r\t ", c) == nil){
194 while((c = Bgetc(&in)) > 0){
197 if(n == 0 && c == '-'){
198 while((c = Bgetc(&in)) > 0){
200 if(Bgetc(&in) == '-')
201 if(Bgetc(&in) == '>')
205 if(n+1 < sizeof(buf)){
207 if(n != 7 || cistrncmp(buf, "[CDATA[", 7))
209 while((c = Bgetc(&in)) > 0){
211 if(Bgetc(&in) == ']')
212 if(Bgetc(&in) == '>')
226 while((c = Bgetc(&in)) > 0){
227 if(strchr("</>=?!", c)){
231 if(strchr("\n\r\t ", c))
233 if(n < sizeof(a->attr)-1)
241 if(Bgetc(&in) == '='){
244 if(strchr("'\"", c)){
246 while((c = Bgetc(&in)) > 0){
249 if(n < sizeof(a->val)-1)
254 while((c = Bgetc(&in)) > 0){
255 if(strchr("\n\r\t </>?!", c)){
259 if(n < sizeof(a->val)-1)
280 while((c = Bgetc(&in)) > 0){
283 if(strchr("\n\r\t ", c)){
284 if(parseattr(t->attr + t->nattr))
285 if(t->nattr < nelem(t->attr)-1)
289 if(n == 0 && strchr("?!", c)){
301 if(n < sizeof(t->tag)-1)
317 while((c = Bgetc(&in)) > 0){
318 if(strchr(";&</>\n\r\t ", c)){
325 if(n == sizeof(buf)-1)
330 if(strcmp(buf, "lt") == 0)
332 if(strcmp(buf, "gt") == 0)
334 if(strcmp(buf, "quot") == 0)
336 if(strcmp(buf, "amp") == 0)
338 /* use tcs -f html to handle the rest. */
342 if(fullrune(buf, n)){
348 } while((c = Bgetc(&in)) > 0);
369 debugtag(Tag *tag, char *dbg)
375 debugtag(tag->up, nil);
376 fprint(2, "%s %s%s", tag->tag, dbg ? dbg : " > ", dbg ? "\n" : "");
381 parsetext(Text *text, Tag *tag)
388 debugtag(tag, "open");
389 if(tag == nil || tag->closing == 0){
390 while((c = Bgetc(&in)) > 0){
394 memset(&t, 0, sizeof(t));
398 for(c = 0; c < nelem(ontag); c++){
399 if(cistrcmp(t.tag, ontag[c].tag) == 0){
400 ontag[c].open(text, &t);
404 rtag = parsetext(text, &t);
409 } else if(t.closing){
410 while(rtag && cistrcmp(rtag->tag, t.tag))
422 r = substrune(parserune(c));
433 if(r == '\n' || r == '\r')
439 text->pos = Bprint(&out, ".UL ");
440 } else if(text->pos >= 70){
443 } else if(text->pos > 0){
448 if(text->pos == 0 && r == '.'){
457 Bprint(&out, "%C", r);
461 debugtag(tag, "close");
462 if(tag && tag->close)
463 tag->close(text, tag);
472 Binit(&in, 0, OREAD);
473 Binit(&out, 1, OWRITE);
475 memset(&text, 0, sizeof(text));
477 parsetext(&text, nil);