Annotation of mandoc/html.c, Revision 1.30
1.30 ! kristaps 1: /* $Id: html.c,v 1.29 2009/09/16 09:41:24 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.30 ! kristaps 141: static int mdoc_fl_pre(MDOC_ARGS);
1.29 kristaps 142: static int mdoc_nd_pre(MDOC_ARGS);
143: static int mdoc_nm_pre(MDOC_ARGS);
1.30 ! kristaps 144: static int mdoc_op_pre(MDOC_ARGS);
! 145: static void mdoc_op_post(MDOC_ARGS);
1.29 kristaps 146: static int mdoc_pp_pre(MDOC_ARGS);
147: static int mdoc_sh_pre(MDOC_ARGS);
148: static int mdoc_ss_pre(MDOC_ARGS);
1.30 ! kristaps 149: static int mdoc_xr_pre(MDOC_ARGS);
1.29 kristaps 150:
151: static const struct htmlmdoc mdocs[MDOC_MAX] = {
152: {NULL, NULL}, /* Ap */
153: {NULL, NULL}, /* Dd */
154: {NULL, NULL}, /* Dt */
155: {NULL, NULL}, /* Os */
1.30 ! kristaps 156: {mdoc_sh_pre, NULL }, /* Sh */
! 157: {mdoc_ss_pre, NULL }, /* Ss */
1.29 kristaps 158: {mdoc_pp_pre, NULL}, /* Pp */
159: {NULL, NULL}, /* D1 */
160: {NULL, NULL}, /* Dl */
161: {NULL, NULL}, /* Bd */
162: {NULL, NULL}, /* Ed */
163: {NULL, NULL}, /* Bl */
164: {NULL, NULL}, /* El */
165: {NULL, NULL}, /* It */
166: {NULL, NULL}, /* Ad */
167: {NULL, NULL}, /* An */
168: {NULL, NULL}, /* Ar */
169: {NULL, NULL}, /* Cd */
170: {NULL, NULL}, /* Cm */
171: {NULL, NULL}, /* Dv */
172: {NULL, NULL}, /* Er */
173: {NULL, NULL}, /* Ev */
174: {NULL, NULL}, /* Ex */
175: {NULL, NULL}, /* Fa */
176: {NULL, NULL}, /* Fd */
1.30 ! kristaps 177: {mdoc_fl_pre, NULL}, /* Fl */
1.29 kristaps 178: {NULL, NULL}, /* Fn */
179: {NULL, NULL}, /* Ft */
180: {NULL, NULL}, /* Ic */
181: {NULL, NULL}, /* In */
182: {NULL, NULL}, /* Li */
183: {mdoc_nd_pre, NULL}, /* Nd */
1.30 ! kristaps 184: {mdoc_nm_pre, NULL}, /* Nm */
! 185: {mdoc_op_pre, mdoc_op_post}, /* Op */
1.29 kristaps 186: {NULL, NULL}, /* Ot */
187: {NULL, NULL}, /* Pa */
188: {NULL, NULL}, /* Rv */
189: {NULL, NULL}, /* St */
190: {NULL, NULL}, /* Va */
191: {NULL, NULL}, /* Vt */
1.30 ! kristaps 192: {mdoc_xr_pre, NULL}, /* Xr */
1.29 kristaps 193: {NULL, NULL}, /* %A */
194: {NULL, NULL}, /* %B */
195: {NULL, NULL}, /* %D */
196: {NULL, NULL}, /* %I */
197: {NULL, NULL}, /* %J */
198: {NULL, NULL}, /* %N */
199: {NULL, NULL}, /* %O */
200: {NULL, NULL}, /* %P */
201: {NULL, NULL}, /* %R */
202: {NULL, NULL}, /* %T */
203: {NULL, NULL}, /* %V */
204: {NULL, NULL}, /* Ac */
205: {NULL, NULL}, /* Ao */
206: {NULL, NULL}, /* Aq */
207: {NULL, NULL}, /* At */
208: {NULL, NULL}, /* Bc */
209: {NULL, NULL}, /* Bf */
210: {NULL, NULL}, /* Bo */
211: {NULL, NULL}, /* Bq */
212: {NULL, NULL}, /* Bsx */
213: {NULL, NULL}, /* Bx */
214: {NULL, NULL}, /* Db */
215: {NULL, NULL}, /* Dc */
216: {NULL, NULL}, /* Do */
217: {NULL, NULL}, /* Dq */
218: {NULL, NULL}, /* Ec */
219: {NULL, NULL}, /* Ef */
220: {NULL, NULL}, /* Em */
221: {NULL, NULL}, /* Eo */
222: {NULL, NULL}, /* Fx */
223: {NULL, NULL}, /* Ms */
224: {NULL, NULL}, /* No */
225: {NULL, NULL}, /* Ns */
226: {NULL, NULL}, /* Nx */
227: {NULL, NULL}, /* Ox */
228: {NULL, NULL}, /* Pc */
229: {NULL, NULL}, /* Pf */
230: {NULL, NULL}, /* Po */
231: {NULL, NULL}, /* Pq */
232: {NULL, NULL}, /* Qc */
233: {NULL, NULL}, /* Ql */
234: {NULL, NULL}, /* Qo */
235: {NULL, NULL}, /* Qq */
236: {NULL, NULL}, /* Re */
237: {NULL, NULL}, /* Rs */
238: {NULL, NULL}, /* Sc */
239: {NULL, NULL}, /* So */
240: {NULL, NULL}, /* Sq */
241: {NULL, NULL}, /* Sm */
242: {NULL, NULL}, /* Sx */
243: {NULL, NULL}, /* Sy */
244: {NULL, NULL}, /* Tn */
245: {NULL, NULL}, /* Ux */
246: {NULL, NULL}, /* Xc */
247: {NULL, NULL}, /* Xo */
248: {NULL, NULL}, /* Fo */
249: {NULL, NULL}, /* Fc */
250: {NULL, NULL}, /* Oo */
251: {NULL, NULL}, /* Oc */
252: {NULL, NULL}, /* Bk */
253: {NULL, NULL}, /* Ek */
254: {NULL, NULL}, /* Bt */
255: {NULL, NULL}, /* Hf */
256: {NULL, NULL}, /* Fr */
257: {NULL, NULL}, /* Ud */
258: {NULL, NULL}, /* Lb */
259: {NULL, NULL}, /* Lp */
260: {NULL, NULL}, /* Lk */
261: {NULL, NULL}, /* Mt */
262: {NULL, NULL}, /* Brq */
263: {NULL, NULL}, /* Bro */
264: {NULL, NULL}, /* Brc */
265: {NULL, NULL}, /* %C */
266: {NULL, NULL}, /* Es */
267: {NULL, NULL}, /* En */
268: {NULL, NULL}, /* Dx */
269: {NULL, NULL}, /* %Q */
270: {NULL, NULL}, /* br */
271: {NULL, NULL}, /* sp */
272: };
1.10 kristaps 273:
274:
1.30 ! kristaps 275: void
1.29 kristaps 276: html_mdoc(void *arg, const struct mdoc *m)
1.10 kristaps 277: {
1.29 kristaps 278: struct html *h;
1.30 ! kristaps 279: struct tag *t;
1.10 kristaps 280:
1.29 kristaps 281: h = (struct html *)arg;
1.10 kristaps 282:
1.29 kristaps 283: print_gen_doctype(h);
1.30 ! kristaps 284: t = print_otag(h, TAG_HTML, 0, NULL);
1.29 kristaps 285: print_mdoc(mdoc_meta(m), mdoc_node(m), h);
1.30 ! kristaps 286: print_tagq(h, t);
! 287:
1.29 kristaps 288: printf("\n");
1.10 kristaps 289: }
290:
291:
1.30 ! kristaps 292: void
1.29 kristaps 293: html_man(void *arg, const struct man *m)
1.10 kristaps 294: {
1.29 kristaps 295: struct html *h;
1.30 ! kristaps 296: struct tag *t;
1.10 kristaps 297:
1.29 kristaps 298: h = (struct html *)arg;
1.10 kristaps 299:
1.29 kristaps 300: print_gen_doctype(h);
1.30 ! kristaps 301: t = print_otag(h, TAG_HTML, 0, NULL);
1.29 kristaps 302: print_man(man_meta(m), man_node(m), h);
1.30 ! kristaps 303: print_tagq(h, t);
! 304:
1.29 kristaps 305: printf("\n");
1.10 kristaps 306: }
307:
308:
1.29 kristaps 309: void *
310: html_alloc(void)
1.10 kristaps 311: {
1.30 ! kristaps 312: struct html *h;
! 313:
! 314: if (NULL == (h = calloc(1, sizeof(struct html))))
! 315: return(NULL);
1.10 kristaps 316:
1.30 ! kristaps 317: SLIST_INIT(&h->stack);
! 318: return(h);
1.29 kristaps 319: }
1.10 kristaps 320:
1.13 kristaps 321:
1.29 kristaps 322: void
323: html_free(void *p)
324: {
1.30 ! kristaps 325: struct tag *tag;
! 326: struct html *h;
! 327:
! 328: h = (struct html *)p;
1.10 kristaps 329:
1.30 ! kristaps 330: while ( ! SLIST_EMPTY(&h->stack)) {
! 331: tag = SLIST_FIRST(&h->stack);
! 332: SLIST_REMOVE_HEAD(&h->stack, entry);
! 333: free(tag);
! 334: }
! 335: free(h);
1.10 kristaps 336: }
1.2 kristaps 337:
338:
1.29 kristaps 339: static void
340: print_mdoc(MDOC_ARGS)
1.4 kristaps 341: {
1.30 ! kristaps 342: struct tag *t;
1.4 kristaps 343:
1.30 ! kristaps 344: t = print_otag(h, TAG_HEAD, 0, NULL);
1.29 kristaps 345: print_mdoc_head(m, n, h);
1.30 ! kristaps 346: print_tagq(h, t);
! 347:
! 348: t = print_otag(h, TAG_BODY, 0, NULL);
! 349: print_mdoc_title(m, n, h);
1.29 kristaps 350: print_mdoc_node(m, n, h);
1.30 ! kristaps 351: print_tagq(h, t);
1.29 kristaps 352: }
1.4 kristaps 353:
354:
1.29 kristaps 355: static void
356: print_gen_head(struct html *h)
357: {
358: struct htmlpair meta0[2];
359: struct htmlpair meta1[2];
360: struct htmlpair link[4];
361:
362: meta0[0].key = ATTR_HTTPEQUIV;
363: meta0[0].val = "Content-Type";
364: meta0[1].key = ATTR_CONTENT;
365: meta0[1].val = "text/html; charest-utf-8";
366:
367: meta1[0].key = ATTR_NAME;
368: meta1[0].val = "resource-type";
369: meta1[1].key = ATTR_CONTENT;
370: meta1[1].val = "document";
371:
372: link[0].key = ATTR_REL;
373: link[0].val = "stylesheet";
374: link[1].key = ATTR_HREF;
1.30 ! kristaps 375: link[1].val = "style.css"; /* XXX */
1.29 kristaps 376: link[2].key = ATTR_TYPE;
377: link[2].val = "text/css";
378: link[3].key = ATTR_MEDIA;
379: link[3].val = "all";
380:
381: print_otag(h, TAG_META, 2, meta0);
382: print_otag(h, TAG_META, 2, meta1);
383: print_otag(h, TAG_LINK, 4, link);
1.4 kristaps 384: }
385:
386:
1.30 ! kristaps 387: /* ARGSUSED */
1.29 kristaps 388: static void
389: print_mdoc_head(MDOC_ARGS)
1.18 kristaps 390: {
391:
1.29 kristaps 392: print_gen_head(h);
393: print_otag(h, TAG_TITLE, 0, NULL);
394: print_encode(m->title);
1.2 kristaps 395: }
396:
397:
1.30 ! kristaps 398: /* ARGSUSED */
1.29 kristaps 399: static void
1.30 ! kristaps 400: print_mdoc_title(MDOC_ARGS)
1.2 kristaps 401: {
402:
1.30 ! kristaps 403: /* TODO */
1.2 kristaps 404: }
405:
406:
1.29 kristaps 407: static void
408: print_mdoc_node(MDOC_ARGS)
1.2 kristaps 409: {
1.29 kristaps 410: int child;
1.30 ! kristaps 411: struct tag *t;
1.8 kristaps 412:
1.29 kristaps 413: child = 1;
1.30 ! kristaps 414: t = SLIST_FIRST(&h->stack);
1.8 kristaps 415:
1.29 kristaps 416: switch (n->type) {
417: case (MDOC_ROOT):
418: child = mdoc_root_pre(m, n, h);
1.7 kristaps 419: break;
1.29 kristaps 420: case (MDOC_TEXT):
421: print_text(h, n->string);
1.7 kristaps 422: break;
1.3 kristaps 423: default:
1.29 kristaps 424: if (mdocs[n->tok].pre)
425: child = (*mdocs[n->tok].pre)(m, n, h);
1.3 kristaps 426: break;
1.2 kristaps 427: }
428:
1.29 kristaps 429: if (child && n->child)
430: print_mdoc_node(m, n->child, h);
1.8 kristaps 431:
1.30 ! kristaps 432: print_stagq(h, t);
! 433:
1.29 kristaps 434: switch (n->type) {
435: case (MDOC_ROOT):
1.7 kristaps 436: break;
1.29 kristaps 437: case (MDOC_TEXT):
1.7 kristaps 438: break;
1.3 kristaps 439: default:
1.29 kristaps 440: if (mdocs[n->tok].post)
441: (*mdocs[n->tok].post)(m, n, h);
1.3 kristaps 442: break;
443: }
1.2 kristaps 444:
1.29 kristaps 445: if (n->next)
446: print_mdoc_node(m, n->next, h);
1.2 kristaps 447: }
448:
449:
1.29 kristaps 450: static void
451: print_man(MAN_ARGS)
1.9 kristaps 452: {
1.30 ! kristaps 453: struct tag *t;
1.9 kristaps 454:
1.30 ! kristaps 455: t = print_otag(h, TAG_HEAD, 0, NULL);
1.29 kristaps 456: print_man_head(m, n, h);
1.30 ! kristaps 457: print_tagq(h, t);
! 458:
! 459: t = print_otag(h, TAG_BODY, 0, NULL);
1.29 kristaps 460: print_man_body(m, n, h);
1.30 ! kristaps 461: print_tagq(h, t);
1.9 kristaps 462: }
463:
464:
1.30 ! kristaps 465: /* ARGSUSED */
1.9 kristaps 466: static void
1.29 kristaps 467: print_man_head(MAN_ARGS)
1.9 kristaps 468: {
469:
1.29 kristaps 470: print_gen_head(h);
471: print_otag(h, TAG_TITLE, 0, NULL);
472: print_encode(m->title);
473: }
1.9 kristaps 474:
475:
1.30 ! kristaps 476: /* ARGSUSED */
1.29 kristaps 477: static void
478: print_man_body(MAN_ARGS)
479: {
1.30 ! kristaps 480:
! 481: /* TODO */
1.9 kristaps 482: }
483:
484:
1.29 kristaps 485: static void
486: print_encode(const char *p)
487: {
1.14 kristaps 488:
1.29 kristaps 489: printf("%s", p); /* XXX */
1.14 kristaps 490: }
491:
492:
1.30 ! kristaps 493: static struct tag *
1.29 kristaps 494: print_otag(struct html *h, enum htmltag tag,
495: int sz, const struct htmlpair *p)
1.14 kristaps 496: {
1.29 kristaps 497: int i;
1.30 ! kristaps 498: struct tag *t;
! 499:
! 500: if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
! 501: if (NULL == (t = malloc(sizeof(struct tag))))
! 502: err(EXIT_FAILURE, "malloc");
! 503: t->tag = tag;
! 504: SLIST_INSERT_HEAD(&h->stack, t, entry);
! 505: } else
! 506: t = NULL;
1.29 kristaps 507:
508: if ( ! (HTML_NOSPACE & h->flags))
1.30 ! kristaps 509: if ( ! (HTML_CLRLINE & htmltags[tag].flags))
1.29 kristaps 510: printf(" ");
511:
512: printf("<%s", htmltags[tag].name);
513: for (i = 0; i < sz; i++) {
514: printf(" %s=\"", htmlattrs[p[i].key]);
515: assert(p->val);
516: print_encode(p[i].val);
517: printf("\"");
518: }
519: printf(">");
1.14 kristaps 520:
1.29 kristaps 521: h->flags |= HTML_NOSPACE;
1.30 ! kristaps 522: if (HTML_CLRLINE & htmltags[tag].flags)
! 523: h->flags |= HTML_NEWLINE;
! 524: else
! 525: h->flags &= ~HTML_NEWLINE;
1.14 kristaps 526:
1.30 ! kristaps 527: return(t);
1.14 kristaps 528: }
529:
530:
531: /* ARGSUSED */
1.29 kristaps 532: static void
533: print_ctag(struct html *h, enum htmltag tag)
1.14 kristaps 534: {
535:
1.29 kristaps 536: printf("</%s>", htmltags[tag].name);
1.30 ! kristaps 537: if (HTML_CLRLINE & htmltags[tag].flags)
1.29 kristaps 538: h->flags |= HTML_NOSPACE;
1.30 ! kristaps 539: if (HTML_CLRLINE & htmltags[tag].flags)
! 540: h->flags |= HTML_NEWLINE;
! 541: else
! 542: h->flags &= ~HTML_NEWLINE;
1.14 kristaps 543: }
544:
545:
1.29 kristaps 546: /* ARGSUSED */
547: static void
548: print_gen_doctype(struct html *h)
1.1 kristaps 549: {
1.29 kristaps 550:
551: printf("<!DOCTYPE HTML PUBLIC \"%s\" \"%s\">\n", DOCTYPE, DTD);
1.1 kristaps 552: }
553:
554:
1.29 kristaps 555: static void
556: print_text(struct html *h, const char *p)
1.1 kristaps 557: {
558:
1.29 kristaps 559: if (*p && 0 == *(p + 1))
560: switch (*p) {
561: case('.'):
562: /* FALLTHROUGH */
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: h->flags |= HTML_NOSPACE;
1.30 ! kristaps 579: break;
1.29 kristaps 580: default:
581: break;
582: }
1.1 kristaps 583:
1.29 kristaps 584: if ( ! (h->flags & HTML_NOSPACE))
585: printf(" ");
1.30 ! kristaps 586:
1.29 kristaps 587: h->flags &= ~HTML_NOSPACE;
1.30 ! kristaps 588: h->flags &= ~HTML_NEWLINE;
1.1 kristaps 589:
1.29 kristaps 590: if (p)
591: print_encode(p);
1.8 kristaps 592:
1.29 kristaps 593: if (*p && 0 == *(p + 1))
594: switch (*p) {
595: case('('):
596: /* FALLTHROUGH */
597: case('['):
598: /* FALLTHROUGH */
599: case('{'):
600: h->flags |= HTML_NOSPACE;
1.30 ! kristaps 601: break;
1.29 kristaps 602: default:
603: break;
604: }
1.1 kristaps 605: }
1.30 ! kristaps 606:
! 607:
! 608: static void
! 609: print_tagq(struct html *h, const struct tag *until)
! 610: {
! 611: struct tag *tag;
! 612:
! 613: while ( ! SLIST_EMPTY(&h->stack)) {
! 614: tag = SLIST_FIRST(&h->stack);
! 615: print_ctag(h, tag->tag);
! 616: SLIST_REMOVE_HEAD(&h->stack, entry);
! 617: free(tag);
! 618: if (until && tag == until)
! 619: return;
! 620: }
! 621: }
! 622:
! 623:
! 624: static void
! 625: print_stagq(struct html *h, const struct tag *suntil)
! 626: {
! 627: struct tag *tag;
! 628:
! 629: while ( ! SLIST_EMPTY(&h->stack)) {
! 630: tag = SLIST_FIRST(&h->stack);
! 631: if (suntil && tag == suntil)
! 632: return;
! 633: print_ctag(h, tag->tag);
! 634: SLIST_REMOVE_HEAD(&h->stack, entry);
! 635: free(tag);
! 636: }
! 637: }
! 638:
! 639:
! 640: /* ARGSUSED */
! 641: static int
! 642: mdoc_root_pre(MDOC_ARGS)
! 643: {
! 644: struct htmlpair tag;
! 645:
! 646: tag.key = ATTR_CLASS;
! 647: tag.val = "body";
! 648:
! 649: print_otag(h, TAG_DIV, 1, &tag);
! 650: return(1);
! 651: }
! 652:
! 653:
! 654: /* ARGSUSED */
! 655: static int
! 656: mdoc_ss_pre(MDOC_ARGS)
! 657: {
! 658:
! 659: if (MDOC_BODY == n->type)
! 660: print_otag(h, TAG_P, 0, NULL);
! 661: if (MDOC_HEAD == n->type)
! 662: print_otag(h, TAG_H2, 0, NULL);
! 663: return(1);
! 664: }
! 665:
! 666:
! 667: /* ARGSUSED */
! 668: static int
! 669: mdoc_fl_pre(MDOC_ARGS)
! 670: {
! 671: struct htmlpair tag;
! 672:
! 673: tag.key = ATTR_CLASS;
! 674: tag.val = "flag";
! 675:
! 676: print_otag(h, TAG_SPAN, 1, &tag);
! 677: print_text(h, "\\-");
! 678: h->flags |= HTML_NOSPACE;
! 679: return(1);
! 680: }
! 681:
! 682:
! 683: /* ARGSUSED */
! 684: static int
! 685: mdoc_pp_pre(MDOC_ARGS)
! 686: {
! 687:
! 688: print_otag(h, TAG_BR, 0, NULL);
! 689: print_otag(h, TAG_BR, 0, NULL);
! 690: return(0);
! 691: }
! 692:
! 693:
! 694: /* ARGSUSED */
! 695: static int
! 696: mdoc_nd_pre(MDOC_ARGS)
! 697: {
! 698:
! 699: if (MDOC_BODY == n->type)
! 700: print_text(h, "--");
! 701: return(1);
! 702: }
! 703:
! 704:
! 705: /* ARGSUSED */
! 706: static int
! 707: mdoc_op_pre(MDOC_ARGS)
! 708: {
! 709:
! 710: if (MDOC_BODY == n->type) {
! 711: print_text(h, "\\(lB");
! 712: h->flags |= HTML_NOSPACE;
! 713: }
! 714: return(1);
! 715: }
! 716:
! 717:
! 718: /* ARGSUSED */
! 719: static void
! 720: mdoc_op_post(MDOC_ARGS)
! 721: {
! 722:
! 723: if (MDOC_BODY != n->type)
! 724: return;
! 725: h->flags |= HTML_NOSPACE;
! 726: print_text(h, "\\(rB");
! 727: }
! 728:
! 729:
! 730: static int
! 731: mdoc_nm_pre(MDOC_ARGS)
! 732: {
! 733: struct htmlpair class;
! 734:
! 735: if ( ! (HTML_NEWLINE & h->flags))
! 736: if (SEC_SYNOPSIS == n->sec)
! 737: print_otag(h, TAG_BR, 0, NULL);
! 738:
! 739: class.key = ATTR_CLASS;
! 740: class.val = "name";
! 741:
! 742: print_otag(h, TAG_SPAN, 1, &class);
! 743: if (NULL == n->child)
! 744: print_text(h, m->name);
! 745:
! 746: return(1);
! 747: }
! 748:
! 749:
! 750: /* ARGSUSED */
! 751: static int
! 752: mdoc_sh_pre(MDOC_ARGS)
! 753: {
! 754:
! 755: if (MDOC_BODY == n->type)
! 756: print_otag(h, TAG_P, 0, NULL);
! 757: if (MDOC_HEAD == n->type)
! 758: print_otag(h, TAG_H1, 0, NULL);
! 759: return(1);
! 760: }
! 761:
! 762:
! 763: /* ARGSUSED */
! 764: static int
! 765: mdoc_xr_pre(MDOC_ARGS)
! 766: {
! 767: struct htmlpair tag;
! 768:
! 769: tag.key = ATTR_HREF;
! 770: tag.val = "#"; /* TODO */
! 771:
! 772: print_otag(h, TAG_A, 1, &tag);
! 773:
! 774: n = n->child;
! 775: print_text(h, n->string);
! 776: if (NULL == (n = n->next))
! 777: return(0);
! 778:
! 779: h->flags |= HTML_NOSPACE;
! 780: print_text(h, "(");
! 781: h->flags |= HTML_NOSPACE;
! 782: print_text(h, n->string);
! 783: h->flags |= HTML_NOSPACE;
! 784: print_text(h, ")");
! 785:
! 786: return(0);
! 787: }
CVSweb