Annotation of mandoc/html.c, Revision 1.31
1.31 ! kristaps 1: /* $Id: html.c,v 1.30 2009/09/16 22:17:27 kristaps Exp $ */
1.1 kristaps 2: /*
1.29 kristaps 3: * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1 kristaps 4: *
5: * Permission to use, copy, modify, and distribute this software for any
1.29 kristaps 6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
1.1 kristaps 8: *
1.29 kristaps 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 kristaps 16: */
1.30 kristaps 17: #include <sys/queue.h>
18:
1.1 kristaps 19: #include <assert.h>
1.4 kristaps 20: #include <err.h>
1.29 kristaps 21: #include <stdio.h>
1.1 kristaps 22: #include <stdlib.h>
23:
1.29 kristaps 24: #include "mdoc.h"
25: #include "man.h"
1.2 kristaps 26:
1.29 kristaps 27: #define DOCTYPE "-//W3C//DTD HTML 4.01//EN"
28: #define DTD "http://www.w3.org/TR/html4/strict.dtd"
1.8 kristaps 29:
1.29 kristaps 30: enum htmltag {
31: TAG_HTML,
32: TAG_HEAD,
33: TAG_BODY,
34: TAG_META,
35: TAG_TITLE,
36: TAG_DIV,
37: TAG_H1,
38: TAG_H2,
39: TAG_P,
40: TAG_SPAN,
41: TAG_LINK,
1.30 kristaps 42: TAG_BR,
43: TAG_A,
1.29 kristaps 44: TAG_MAX
1.7 kristaps 45: };
46:
1.29 kristaps 47: enum htmlattr {
48: ATTR_HTTPEQUIV,
49: ATTR_CONTENT,
50: ATTR_NAME,
51: ATTR_REL,
52: ATTR_HREF,
53: ATTR_TYPE,
54: ATTR_MEDIA,
55: ATTR_CLASS,
56: ATTR_MAX
1.7 kristaps 57: };
58:
1.29 kristaps 59: struct htmldata {
60: char *name;
61: int flags;
1.30 kristaps 62: #define HTML_CLRLINE (1 << 0)
63: #define HTML_NOSTACK (1 << 1)
1.29 kristaps 64: };
1.7 kristaps 65:
1.29 kristaps 66: static const struct htmldata htmltags[TAG_MAX] = {
1.30 kristaps 67: {"html", HTML_CLRLINE}, /* TAG_HTML */
68: {"head", HTML_CLRLINE}, /* TAG_HEAD */
69: {"body", HTML_CLRLINE}, /* TAG_BODY */
70: {"meta", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_META */
71: {"title", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_TITLE */
72: {"div", HTML_CLRLINE}, /* TAG_DIV */
1.29 kristaps 73: {"h1", 0}, /* TAG_H1 */
74: {"h2", 0}, /* TAG_H2 */
1.30 kristaps 75: {"p", HTML_CLRLINE}, /* TAG_P */
1.29 kristaps 76: {"span", 0}, /* TAG_SPAN */
1.30 kristaps 77: {"link", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_LINK */
78: {"br", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_LINK */
79: {"a", 0}, /* TAG_A */
1.29 kristaps 80: };
1.10 kristaps 81:
1.29 kristaps 82: static const char *const htmlattrs[ATTR_MAX] = {
83: "http-equiv",
84: "content",
85: "name",
86: "rel",
87: "href",
88: "type",
89: "media",
90: "class"
91: };
1.10 kristaps 92:
1.29 kristaps 93: struct htmlpair {
94: enum htmlattr key;
95: char *val;
96: };
1.10 kristaps 97:
1.30 kristaps 98: struct tag {
99: enum htmltag tag;
100: SLIST_ENTRY(tag) entry;
101: };
102:
103: SLIST_HEAD(tagq, tag);
104:
1.29 kristaps 105: struct html {
106: int flags;
107: #define HTML_NOSPACE (1 << 0)
1.30 kristaps 108: #define HTML_NEWLINE (1 << 1)
109: struct tagq stack;
1.29 kristaps 110: };
1.10 kristaps 111:
1.29 kristaps 112: #define MDOC_ARGS const struct mdoc_meta *m, \
113: const struct mdoc_node *n, \
114: struct html *h
115: #define MAN_ARGS const struct man_meta *m, \
116: const struct man_node *n, \
117: struct html *h
118: struct htmlmdoc {
119: int (*pre)(MDOC_ARGS);
120: void (*post)(MDOC_ARGS);
121: };
1.13 kristaps 122:
1.29 kristaps 123: static void print_gen_doctype(struct html *);
124: static void print_gen_head(struct html *);
125: static void print_mdoc(MDOC_ARGS);
126: static void print_mdoc_head(MDOC_ARGS);
1.30 kristaps 127: static void print_mdoc_title(MDOC_ARGS);
1.29 kristaps 128: static void print_mdoc_node(MDOC_ARGS);
129: static void print_man(MAN_ARGS);
130: static void print_man_head(MAN_ARGS);
131: static void print_man_body(MAN_ARGS);
1.30 kristaps 132: static struct tag *print_otag(struct html *, enum htmltag,
1.29 kristaps 133: int, const struct htmlpair *);
1.30 kristaps 134: static void print_tagq(struct html *, const struct tag *);
135: static void print_stagq(struct html *, const struct tag *);
1.29 kristaps 136: static void print_ctag(struct html *, enum htmltag);
137: static void print_encode(const char *);
138: static void print_text(struct html *, const char *);
139: static int mdoc_root_pre(MDOC_ARGS);
140:
1.31 ! kristaps 141: static int mdoc_ar_pre(MDOC_ARGS);
1.30 kristaps 142: static int mdoc_fl_pre(MDOC_ARGS);
1.29 kristaps 143: static int mdoc_nd_pre(MDOC_ARGS);
144: static int mdoc_nm_pre(MDOC_ARGS);
1.31 ! kristaps 145: static int mdoc_ns_pre(MDOC_ARGS);
1.30 kristaps 146: static int mdoc_op_pre(MDOC_ARGS);
147: static void mdoc_op_post(MDOC_ARGS);
1.29 kristaps 148: static int mdoc_pp_pre(MDOC_ARGS);
149: static int mdoc_sh_pre(MDOC_ARGS);
150: static int mdoc_ss_pre(MDOC_ARGS);
1.30 kristaps 151: static int mdoc_xr_pre(MDOC_ARGS);
1.29 kristaps 152:
153: static const struct htmlmdoc mdocs[MDOC_MAX] = {
154: {NULL, NULL}, /* Ap */
155: {NULL, NULL}, /* Dd */
156: {NULL, NULL}, /* Dt */
157: {NULL, NULL}, /* Os */
1.30 kristaps 158: {mdoc_sh_pre, NULL }, /* Sh */
159: {mdoc_ss_pre, NULL }, /* Ss */
1.29 kristaps 160: {mdoc_pp_pre, NULL}, /* Pp */
161: {NULL, NULL}, /* D1 */
162: {NULL, NULL}, /* Dl */
163: {NULL, NULL}, /* Bd */
164: {NULL, NULL}, /* Ed */
165: {NULL, NULL}, /* Bl */
166: {NULL, NULL}, /* El */
167: {NULL, NULL}, /* It */
168: {NULL, NULL}, /* Ad */
169: {NULL, NULL}, /* An */
1.31 ! kristaps 170: {mdoc_ar_pre, NULL}, /* Ar */
1.29 kristaps 171: {NULL, NULL}, /* Cd */
172: {NULL, NULL}, /* Cm */
173: {NULL, NULL}, /* Dv */
174: {NULL, NULL}, /* Er */
175: {NULL, NULL}, /* Ev */
176: {NULL, NULL}, /* Ex */
177: {NULL, NULL}, /* Fa */
178: {NULL, NULL}, /* Fd */
1.30 kristaps 179: {mdoc_fl_pre, NULL}, /* Fl */
1.29 kristaps 180: {NULL, NULL}, /* Fn */
181: {NULL, NULL}, /* Ft */
182: {NULL, NULL}, /* Ic */
183: {NULL, NULL}, /* In */
184: {NULL, NULL}, /* Li */
185: {mdoc_nd_pre, NULL}, /* Nd */
1.30 kristaps 186: {mdoc_nm_pre, NULL}, /* Nm */
187: {mdoc_op_pre, mdoc_op_post}, /* Op */
1.29 kristaps 188: {NULL, NULL}, /* Ot */
189: {NULL, NULL}, /* Pa */
190: {NULL, NULL}, /* Rv */
191: {NULL, NULL}, /* St */
192: {NULL, NULL}, /* Va */
193: {NULL, NULL}, /* Vt */
1.30 kristaps 194: {mdoc_xr_pre, NULL}, /* Xr */
1.29 kristaps 195: {NULL, NULL}, /* %A */
196: {NULL, NULL}, /* %B */
197: {NULL, NULL}, /* %D */
198: {NULL, NULL}, /* %I */
199: {NULL, NULL}, /* %J */
200: {NULL, NULL}, /* %N */
201: {NULL, NULL}, /* %O */
202: {NULL, NULL}, /* %P */
203: {NULL, NULL}, /* %R */
204: {NULL, NULL}, /* %T */
205: {NULL, NULL}, /* %V */
206: {NULL, NULL}, /* Ac */
207: {NULL, NULL}, /* Ao */
208: {NULL, NULL}, /* Aq */
209: {NULL, NULL}, /* At */
210: {NULL, NULL}, /* Bc */
211: {NULL, NULL}, /* Bf */
212: {NULL, NULL}, /* Bo */
213: {NULL, NULL}, /* Bq */
214: {NULL, NULL}, /* Bsx */
215: {NULL, NULL}, /* Bx */
216: {NULL, NULL}, /* Db */
217: {NULL, NULL}, /* Dc */
218: {NULL, NULL}, /* Do */
219: {NULL, NULL}, /* Dq */
220: {NULL, NULL}, /* Ec */
221: {NULL, NULL}, /* Ef */
222: {NULL, NULL}, /* Em */
223: {NULL, NULL}, /* Eo */
224: {NULL, NULL}, /* Fx */
225: {NULL, NULL}, /* Ms */
226: {NULL, NULL}, /* No */
1.31 ! kristaps 227: {mdoc_ns_pre, NULL}, /* Ns */
1.29 kristaps 228: {NULL, NULL}, /* Nx */
229: {NULL, NULL}, /* Ox */
230: {NULL, NULL}, /* Pc */
231: {NULL, NULL}, /* Pf */
232: {NULL, NULL}, /* Po */
233: {NULL, NULL}, /* Pq */
234: {NULL, NULL}, /* Qc */
235: {NULL, NULL}, /* Ql */
236: {NULL, NULL}, /* Qo */
237: {NULL, NULL}, /* Qq */
238: {NULL, NULL}, /* Re */
239: {NULL, NULL}, /* Rs */
240: {NULL, NULL}, /* Sc */
241: {NULL, NULL}, /* So */
242: {NULL, NULL}, /* Sq */
243: {NULL, NULL}, /* Sm */
244: {NULL, NULL}, /* Sx */
245: {NULL, NULL}, /* Sy */
246: {NULL, NULL}, /* Tn */
247: {NULL, NULL}, /* Ux */
248: {NULL, NULL}, /* Xc */
249: {NULL, NULL}, /* Xo */
250: {NULL, NULL}, /* Fo */
251: {NULL, NULL}, /* Fc */
252: {NULL, NULL}, /* Oo */
253: {NULL, NULL}, /* Oc */
254: {NULL, NULL}, /* Bk */
255: {NULL, NULL}, /* Ek */
256: {NULL, NULL}, /* Bt */
257: {NULL, NULL}, /* Hf */
258: {NULL, NULL}, /* Fr */
259: {NULL, NULL}, /* Ud */
260: {NULL, NULL}, /* Lb */
261: {NULL, NULL}, /* Lp */
262: {NULL, NULL}, /* Lk */
263: {NULL, NULL}, /* Mt */
264: {NULL, NULL}, /* Brq */
265: {NULL, NULL}, /* Bro */
266: {NULL, NULL}, /* Brc */
267: {NULL, NULL}, /* %C */
268: {NULL, NULL}, /* Es */
269: {NULL, NULL}, /* En */
270: {NULL, NULL}, /* Dx */
271: {NULL, NULL}, /* %Q */
272: {NULL, NULL}, /* br */
273: {NULL, NULL}, /* sp */
274: };
1.10 kristaps 275:
276:
1.30 kristaps 277: void
1.29 kristaps 278: html_mdoc(void *arg, const struct mdoc *m)
1.10 kristaps 279: {
1.29 kristaps 280: struct html *h;
1.30 kristaps 281: struct tag *t;
1.10 kristaps 282:
1.29 kristaps 283: h = (struct html *)arg;
1.10 kristaps 284:
1.29 kristaps 285: print_gen_doctype(h);
1.30 kristaps 286: t = print_otag(h, TAG_HTML, 0, NULL);
1.29 kristaps 287: print_mdoc(mdoc_meta(m), mdoc_node(m), h);
1.30 kristaps 288: print_tagq(h, t);
289:
1.29 kristaps 290: printf("\n");
1.10 kristaps 291: }
292:
293:
1.30 kristaps 294: void
1.29 kristaps 295: html_man(void *arg, const struct man *m)
1.10 kristaps 296: {
1.29 kristaps 297: struct html *h;
1.30 kristaps 298: struct tag *t;
1.10 kristaps 299:
1.29 kristaps 300: h = (struct html *)arg;
1.10 kristaps 301:
1.29 kristaps 302: print_gen_doctype(h);
1.30 kristaps 303: t = print_otag(h, TAG_HTML, 0, NULL);
1.29 kristaps 304: print_man(man_meta(m), man_node(m), h);
1.30 kristaps 305: print_tagq(h, t);
306:
1.29 kristaps 307: printf("\n");
1.10 kristaps 308: }
309:
310:
1.29 kristaps 311: void *
312: html_alloc(void)
1.10 kristaps 313: {
1.30 kristaps 314: struct html *h;
315:
316: if (NULL == (h = calloc(1, sizeof(struct html))))
317: return(NULL);
1.10 kristaps 318:
1.30 kristaps 319: SLIST_INIT(&h->stack);
320: return(h);
1.29 kristaps 321: }
1.10 kristaps 322:
1.13 kristaps 323:
1.29 kristaps 324: void
325: html_free(void *p)
326: {
1.30 kristaps 327: struct tag *tag;
328: struct html *h;
329:
330: h = (struct html *)p;
1.10 kristaps 331:
1.30 kristaps 332: while ( ! SLIST_EMPTY(&h->stack)) {
333: tag = SLIST_FIRST(&h->stack);
334: SLIST_REMOVE_HEAD(&h->stack, entry);
335: free(tag);
336: }
337: free(h);
1.10 kristaps 338: }
1.2 kristaps 339:
340:
1.29 kristaps 341: static void
342: print_mdoc(MDOC_ARGS)
1.4 kristaps 343: {
1.30 kristaps 344: struct tag *t;
1.4 kristaps 345:
1.30 kristaps 346: t = print_otag(h, TAG_HEAD, 0, NULL);
1.29 kristaps 347: print_mdoc_head(m, n, h);
1.30 kristaps 348: print_tagq(h, t);
349:
350: t = print_otag(h, TAG_BODY, 0, NULL);
351: print_mdoc_title(m, n, h);
1.29 kristaps 352: print_mdoc_node(m, n, h);
1.30 kristaps 353: print_tagq(h, t);
1.29 kristaps 354: }
1.4 kristaps 355:
356:
1.29 kristaps 357: static void
358: print_gen_head(struct html *h)
359: {
360: struct htmlpair meta0[2];
361: struct htmlpair meta1[2];
362: struct htmlpair link[4];
363:
364: meta0[0].key = ATTR_HTTPEQUIV;
365: meta0[0].val = "Content-Type";
366: meta0[1].key = ATTR_CONTENT;
367: meta0[1].val = "text/html; charest-utf-8";
368:
369: meta1[0].key = ATTR_NAME;
370: meta1[0].val = "resource-type";
371: meta1[1].key = ATTR_CONTENT;
372: meta1[1].val = "document";
373:
374: link[0].key = ATTR_REL;
375: link[0].val = "stylesheet";
376: link[1].key = ATTR_HREF;
1.30 kristaps 377: link[1].val = "style.css"; /* XXX */
1.29 kristaps 378: link[2].key = ATTR_TYPE;
379: link[2].val = "text/css";
380: link[3].key = ATTR_MEDIA;
381: link[3].val = "all";
382:
383: print_otag(h, TAG_META, 2, meta0);
384: print_otag(h, TAG_META, 2, meta1);
385: print_otag(h, TAG_LINK, 4, link);
1.4 kristaps 386: }
387:
388:
1.30 kristaps 389: /* ARGSUSED */
1.29 kristaps 390: static void
391: print_mdoc_head(MDOC_ARGS)
1.18 kristaps 392: {
393:
1.29 kristaps 394: print_gen_head(h);
395: print_otag(h, TAG_TITLE, 0, NULL);
396: print_encode(m->title);
1.2 kristaps 397: }
398:
399:
1.30 kristaps 400: /* ARGSUSED */
1.29 kristaps 401: static void
1.30 kristaps 402: print_mdoc_title(MDOC_ARGS)
1.2 kristaps 403: {
404:
1.30 kristaps 405: /* TODO */
1.2 kristaps 406: }
407:
408:
1.29 kristaps 409: static void
410: print_mdoc_node(MDOC_ARGS)
1.2 kristaps 411: {
1.29 kristaps 412: int child;
1.30 kristaps 413: struct tag *t;
1.8 kristaps 414:
1.29 kristaps 415: child = 1;
1.30 kristaps 416: t = SLIST_FIRST(&h->stack);
1.8 kristaps 417:
1.29 kristaps 418: switch (n->type) {
419: case (MDOC_ROOT):
420: child = mdoc_root_pre(m, n, h);
1.7 kristaps 421: break;
1.29 kristaps 422: case (MDOC_TEXT):
423: print_text(h, n->string);
1.7 kristaps 424: break;
1.3 kristaps 425: default:
1.29 kristaps 426: if (mdocs[n->tok].pre)
427: child = (*mdocs[n->tok].pre)(m, n, h);
1.3 kristaps 428: break;
1.2 kristaps 429: }
430:
1.29 kristaps 431: if (child && n->child)
432: print_mdoc_node(m, n->child, h);
1.8 kristaps 433:
1.30 kristaps 434: print_stagq(h, t);
435:
1.29 kristaps 436: switch (n->type) {
437: case (MDOC_ROOT):
1.7 kristaps 438: break;
1.29 kristaps 439: case (MDOC_TEXT):
1.7 kristaps 440: break;
1.3 kristaps 441: default:
1.29 kristaps 442: if (mdocs[n->tok].post)
443: (*mdocs[n->tok].post)(m, n, h);
1.3 kristaps 444: break;
445: }
1.2 kristaps 446:
1.29 kristaps 447: if (n->next)
448: print_mdoc_node(m, n->next, h);
1.2 kristaps 449: }
450:
451:
1.29 kristaps 452: static void
453: print_man(MAN_ARGS)
1.9 kristaps 454: {
1.30 kristaps 455: struct tag *t;
1.9 kristaps 456:
1.30 kristaps 457: t = print_otag(h, TAG_HEAD, 0, NULL);
1.29 kristaps 458: print_man_head(m, n, h);
1.30 kristaps 459: print_tagq(h, t);
460:
461: t = print_otag(h, TAG_BODY, 0, NULL);
1.29 kristaps 462: print_man_body(m, n, h);
1.30 kristaps 463: print_tagq(h, t);
1.9 kristaps 464: }
465:
466:
1.30 kristaps 467: /* ARGSUSED */
1.9 kristaps 468: static void
1.29 kristaps 469: print_man_head(MAN_ARGS)
1.9 kristaps 470: {
471:
1.29 kristaps 472: print_gen_head(h);
473: print_otag(h, TAG_TITLE, 0, NULL);
474: print_encode(m->title);
475: }
1.9 kristaps 476:
477:
1.30 kristaps 478: /* ARGSUSED */
1.29 kristaps 479: static void
480: print_man_body(MAN_ARGS)
481: {
1.30 kristaps 482:
483: /* TODO */
1.9 kristaps 484: }
485:
486:
1.29 kristaps 487: static void
488: print_encode(const char *p)
489: {
1.14 kristaps 490:
1.29 kristaps 491: printf("%s", p); /* XXX */
1.14 kristaps 492: }
493:
494:
1.30 kristaps 495: static struct tag *
1.29 kristaps 496: print_otag(struct html *h, enum htmltag tag,
497: int sz, const struct htmlpair *p)
1.14 kristaps 498: {
1.29 kristaps 499: int i;
1.30 kristaps 500: struct tag *t;
501:
502: if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
503: if (NULL == (t = malloc(sizeof(struct tag))))
504: err(EXIT_FAILURE, "malloc");
505: t->tag = tag;
506: SLIST_INSERT_HEAD(&h->stack, t, entry);
507: } else
508: t = NULL;
1.29 kristaps 509:
510: if ( ! (HTML_NOSPACE & h->flags))
1.30 kristaps 511: if ( ! (HTML_CLRLINE & htmltags[tag].flags))
1.29 kristaps 512: printf(" ");
513:
514: printf("<%s", htmltags[tag].name);
515: for (i = 0; i < sz; i++) {
516: printf(" %s=\"", htmlattrs[p[i].key]);
517: assert(p->val);
518: print_encode(p[i].val);
519: printf("\"");
520: }
521: printf(">");
1.14 kristaps 522:
1.29 kristaps 523: h->flags |= HTML_NOSPACE;
1.30 kristaps 524: if (HTML_CLRLINE & htmltags[tag].flags)
525: h->flags |= HTML_NEWLINE;
526: else
527: h->flags &= ~HTML_NEWLINE;
1.14 kristaps 528:
1.30 kristaps 529: return(t);
1.14 kristaps 530: }
531:
532:
533: /* ARGSUSED */
1.29 kristaps 534: static void
535: print_ctag(struct html *h, enum htmltag tag)
1.14 kristaps 536: {
537:
1.29 kristaps 538: printf("</%s>", htmltags[tag].name);
1.30 kristaps 539: if (HTML_CLRLINE & htmltags[tag].flags)
1.29 kristaps 540: h->flags |= HTML_NOSPACE;
1.30 kristaps 541: if (HTML_CLRLINE & htmltags[tag].flags)
542: h->flags |= HTML_NEWLINE;
543: else
544: h->flags &= ~HTML_NEWLINE;
1.14 kristaps 545: }
546:
547:
1.29 kristaps 548: /* ARGSUSED */
549: static void
550: print_gen_doctype(struct html *h)
1.1 kristaps 551: {
1.29 kristaps 552:
553: printf("<!DOCTYPE HTML PUBLIC \"%s\" \"%s\">\n", DOCTYPE, DTD);
1.1 kristaps 554: }
555:
556:
1.29 kristaps 557: static void
558: print_text(struct html *h, const char *p)
1.1 kristaps 559: {
560:
1.29 kristaps 561: if (*p && 0 == *(p + 1))
562: switch (*p) {
563: case('.'):
564: /* FALLTHROUGH */
565: case(','):
566: /* FALLTHROUGH */
567: case(';'):
568: /* FALLTHROUGH */
569: case(':'):
570: /* FALLTHROUGH */
571: case('?'):
572: /* FALLTHROUGH */
573: case('!'):
574: /* FALLTHROUGH */
575: case(')'):
576: /* FALLTHROUGH */
577: case(']'):
578: /* FALLTHROUGH */
579: case('}'):
580: h->flags |= HTML_NOSPACE;
1.30 kristaps 581: break;
1.29 kristaps 582: default:
583: break;
584: }
1.1 kristaps 585:
1.29 kristaps 586: if ( ! (h->flags & HTML_NOSPACE))
587: printf(" ");
1.30 kristaps 588:
1.29 kristaps 589: h->flags &= ~HTML_NOSPACE;
1.30 kristaps 590: h->flags &= ~HTML_NEWLINE;
1.1 kristaps 591:
1.29 kristaps 592: if (p)
593: print_encode(p);
1.8 kristaps 594:
1.29 kristaps 595: if (*p && 0 == *(p + 1))
596: switch (*p) {
597: case('('):
598: /* FALLTHROUGH */
599: case('['):
600: /* FALLTHROUGH */
601: case('{'):
602: h->flags |= HTML_NOSPACE;
1.30 kristaps 603: break;
1.29 kristaps 604: default:
605: break;
606: }
1.1 kristaps 607: }
1.30 kristaps 608:
609:
610: static void
611: print_tagq(struct html *h, const struct tag *until)
612: {
613: struct tag *tag;
614:
615: while ( ! SLIST_EMPTY(&h->stack)) {
616: tag = SLIST_FIRST(&h->stack);
617: print_ctag(h, tag->tag);
618: SLIST_REMOVE_HEAD(&h->stack, entry);
619: free(tag);
620: if (until && tag == until)
621: return;
622: }
623: }
624:
625:
626: static void
627: print_stagq(struct html *h, const struct tag *suntil)
628: {
629: struct tag *tag;
630:
631: while ( ! SLIST_EMPTY(&h->stack)) {
632: tag = SLIST_FIRST(&h->stack);
633: if (suntil && tag == suntil)
634: return;
635: print_ctag(h, tag->tag);
636: SLIST_REMOVE_HEAD(&h->stack, entry);
637: free(tag);
638: }
639: }
640:
641:
642: /* ARGSUSED */
643: static int
644: mdoc_root_pre(MDOC_ARGS)
645: {
646: struct htmlpair tag;
647:
648: tag.key = ATTR_CLASS;
649: tag.val = "body";
650:
651: print_otag(h, TAG_DIV, 1, &tag);
652: return(1);
653: }
654:
655:
656: /* ARGSUSED */
657: static int
658: mdoc_ss_pre(MDOC_ARGS)
659: {
660:
661: if (MDOC_BODY == n->type)
662: print_otag(h, TAG_P, 0, NULL);
663: if (MDOC_HEAD == n->type)
664: print_otag(h, TAG_H2, 0, NULL);
665: return(1);
666: }
667:
668:
669: /* ARGSUSED */
670: static int
671: mdoc_fl_pre(MDOC_ARGS)
672: {
673: struct htmlpair tag;
674:
675: tag.key = ATTR_CLASS;
676: tag.val = "flag";
677:
678: print_otag(h, TAG_SPAN, 1, &tag);
679: print_text(h, "\\-");
680: h->flags |= HTML_NOSPACE;
681: return(1);
682: }
683:
684:
685: /* ARGSUSED */
686: static int
687: mdoc_pp_pre(MDOC_ARGS)
688: {
689:
690: print_otag(h, TAG_BR, 0, NULL);
691: print_otag(h, TAG_BR, 0, NULL);
692: return(0);
693: }
694:
695:
696: /* ARGSUSED */
697: static int
698: mdoc_nd_pre(MDOC_ARGS)
699: {
700:
701: if (MDOC_BODY == n->type)
1.31 ! kristaps 702: print_text(h, "\\(en");
1.30 kristaps 703: return(1);
704: }
705:
706:
707: /* ARGSUSED */
708: static int
709: mdoc_op_pre(MDOC_ARGS)
710: {
711:
712: if (MDOC_BODY == n->type) {
713: print_text(h, "\\(lB");
714: h->flags |= HTML_NOSPACE;
715: }
716: return(1);
717: }
718:
719:
720: /* ARGSUSED */
721: static void
722: mdoc_op_post(MDOC_ARGS)
723: {
724:
725: if (MDOC_BODY != n->type)
726: return;
727: h->flags |= HTML_NOSPACE;
728: print_text(h, "\\(rB");
729: }
730:
731:
732: static int
733: mdoc_nm_pre(MDOC_ARGS)
734: {
735: struct htmlpair class;
736:
737: if ( ! (HTML_NEWLINE & h->flags))
738: if (SEC_SYNOPSIS == n->sec)
739: print_otag(h, TAG_BR, 0, NULL);
740:
741: class.key = ATTR_CLASS;
742: class.val = "name";
743:
744: print_otag(h, TAG_SPAN, 1, &class);
745: if (NULL == n->child)
746: print_text(h, m->name);
747:
748: return(1);
749: }
750:
751:
752: /* ARGSUSED */
753: static int
754: mdoc_sh_pre(MDOC_ARGS)
755: {
756:
757: if (MDOC_BODY == n->type)
758: print_otag(h, TAG_P, 0, NULL);
759: if (MDOC_HEAD == n->type)
760: print_otag(h, TAG_H1, 0, NULL);
761: return(1);
762: }
763:
764:
765: /* ARGSUSED */
766: static int
767: mdoc_xr_pre(MDOC_ARGS)
768: {
769: struct htmlpair tag;
770:
771: tag.key = ATTR_HREF;
772: tag.val = "#"; /* TODO */
773:
774: print_otag(h, TAG_A, 1, &tag);
775:
776: n = n->child;
777: print_text(h, n->string);
778: if (NULL == (n = n->next))
779: return(0);
780:
781: h->flags |= HTML_NOSPACE;
782: print_text(h, "(");
783: h->flags |= HTML_NOSPACE;
784: print_text(h, n->string);
785: h->flags |= HTML_NOSPACE;
786: print_text(h, ")");
787:
788: return(0);
789: }
1.31 ! kristaps 790:
! 791:
! 792: /* ARGSUSED */
! 793: static int
! 794: mdoc_ns_pre(MDOC_ARGS)
! 795: {
! 796:
! 797: h->flags |= HTML_NOSPACE;
! 798: return(1);
! 799: }
! 800:
! 801:
! 802: /* ARGSUSED */
! 803: static int
! 804: mdoc_ar_pre(MDOC_ARGS)
! 805: {
! 806: struct htmlpair tag;
! 807:
! 808: tag.key = ATTR_CLASS;
! 809: tag.val = "arg";
! 810:
! 811: print_otag(h, TAG_SPAN, 1, &tag);
! 812: return(1);
! 813: }
CVSweb