Annotation of mandoc/html.c, Revision 1.49
1.49 ! kristaps 1: /* $Id: html.c,v 1.48 2009/09/21 14:07:07 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.41 kristaps 17: #include <sys/types.h>
1.30 kristaps 18: #include <sys/queue.h>
19:
1.1 kristaps 20: #include <assert.h>
1.33 kristaps 21: #include <ctype.h>
1.4 kristaps 22: #include <err.h>
1.29 kristaps 23: #include <stdio.h>
1.1 kristaps 24: #include <stdlib.h>
1.33 kristaps 25: #include <string.h>
1.45 kristaps 26: #include <unistd.h>
1.1 kristaps 27:
1.32 kristaps 28: #include "chars.h"
1.29 kristaps 29: #include "mdoc.h"
30: #include "man.h"
1.2 kristaps 31:
1.29 kristaps 32: #define DOCTYPE "-//W3C//DTD HTML 4.01//EN"
33: #define DTD "http://www.w3.org/TR/html4/strict.dtd"
1.8 kristaps 34:
1.33 kristaps 35: #define INDENT 5
36: #define HALFINDENT 3
37:
1.29 kristaps 38: enum htmltag {
39: TAG_HTML,
40: TAG_HEAD,
41: TAG_BODY,
42: TAG_META,
43: TAG_TITLE,
44: TAG_DIV,
45: TAG_H1,
46: TAG_H2,
47: TAG_P,
48: TAG_SPAN,
49: TAG_LINK,
1.30 kristaps 50: TAG_BR,
51: TAG_A,
1.33 kristaps 52: TAG_TABLE,
53: TAG_COL,
54: TAG_TR,
55: TAG_TD,
1.34 kristaps 56: TAG_LI,
57: TAG_UL,
58: TAG_OL,
1.41 kristaps 59: TAG_BASE,
1.29 kristaps 60: TAG_MAX
1.7 kristaps 61: };
62:
1.29 kristaps 63: enum htmlattr {
64: ATTR_HTTPEQUIV,
65: ATTR_CONTENT,
66: ATTR_NAME,
67: ATTR_REL,
68: ATTR_HREF,
69: ATTR_TYPE,
70: ATTR_MEDIA,
71: ATTR_CLASS,
1.33 kristaps 72: ATTR_STYLE,
73: ATTR_WIDTH,
74: ATTR_VALIGN,
1.29 kristaps 75: ATTR_MAX
1.7 kristaps 76: };
77:
1.29 kristaps 78: struct htmldata {
79: char *name;
80: int flags;
1.30 kristaps 81: #define HTML_CLRLINE (1 << 0)
82: #define HTML_NOSTACK (1 << 1)
1.29 kristaps 83: };
1.7 kristaps 84:
1.29 kristaps 85: static const struct htmldata htmltags[TAG_MAX] = {
1.30 kristaps 86: {"html", HTML_CLRLINE}, /* TAG_HTML */
87: {"head", HTML_CLRLINE}, /* TAG_HEAD */
88: {"body", HTML_CLRLINE}, /* TAG_BODY */
89: {"meta", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_META */
1.33 kristaps 90: {"title", HTML_CLRLINE}, /* TAG_TITLE */
1.30 kristaps 91: {"div", HTML_CLRLINE}, /* TAG_DIV */
1.29 kristaps 92: {"h1", 0}, /* TAG_H1 */
93: {"h2", 0}, /* TAG_H2 */
1.30 kristaps 94: {"p", HTML_CLRLINE}, /* TAG_P */
1.29 kristaps 95: {"span", 0}, /* TAG_SPAN */
1.30 kristaps 96: {"link", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_LINK */
97: {"br", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_LINK */
98: {"a", 0}, /* TAG_A */
1.33 kristaps 99: {"table", HTML_CLRLINE}, /* TAG_TABLE */
100: {"col", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_COL */
101: {"tr", HTML_CLRLINE}, /* TAG_TR */
102: {"td", HTML_CLRLINE}, /* TAG_TD */
1.34 kristaps 103: {"li", HTML_CLRLINE}, /* TAG_LI */
104: {"ul", HTML_CLRLINE}, /* TAG_UL */
105: {"ol", HTML_CLRLINE}, /* TAG_OL */
1.41 kristaps 106: {"base", HTML_CLRLINE | HTML_NOSTACK}, /* TAG_BASE */
1.29 kristaps 107: };
1.10 kristaps 108:
1.29 kristaps 109: static const char *const htmlattrs[ATTR_MAX] = {
110: "http-equiv",
111: "content",
112: "name",
113: "rel",
114: "href",
115: "type",
116: "media",
1.33 kristaps 117: "class",
118: "style",
119: "width",
120: "valign",
1.29 kristaps 121: };
1.10 kristaps 122:
1.29 kristaps 123: struct htmlpair {
124: enum htmlattr key;
125: char *val;
126: };
1.10 kristaps 127:
1.30 kristaps 128: struct tag {
129: enum htmltag tag;
130: SLIST_ENTRY(tag) entry;
131: };
132:
1.37 kristaps 133: struct ord {
134: int pos;
135: const void *cookie;
136: SLIST_ENTRY(ord) entry;
137: };
138:
1.30 kristaps 139: SLIST_HEAD(tagq, tag);
1.37 kristaps 140: SLIST_HEAD(ordq, ord);
1.30 kristaps 141:
1.29 kristaps 142: struct html {
143: int flags;
144: #define HTML_NOSPACE (1 << 0)
1.30 kristaps 145: #define HTML_NEWLINE (1 << 1)
1.37 kristaps 146: struct tagq tags;
147: struct ordq ords;
1.32 kristaps 148: void *symtab;
1.41 kristaps 149: char *base;
150: char *style;
1.29 kristaps 151: };
1.10 kristaps 152:
1.29 kristaps 153: #define MDOC_ARGS const struct mdoc_meta *m, \
154: const struct mdoc_node *n, \
155: struct html *h
156: #define MAN_ARGS const struct man_meta *m, \
157: const struct man_node *n, \
158: struct html *h
159: struct htmlmdoc {
160: int (*pre)(MDOC_ARGS);
161: void (*post)(MDOC_ARGS);
162: };
1.13 kristaps 163:
1.29 kristaps 164: static void print_gen_doctype(struct html *);
165: static void print_gen_head(struct html *);
166: static void print_mdoc(MDOC_ARGS);
167: static void print_mdoc_head(MDOC_ARGS);
168: static void print_mdoc_node(MDOC_ARGS);
1.39 kristaps 169: static void print_mdoc_nodelist(MDOC_ARGS);
1.29 kristaps 170: static void print_man(MAN_ARGS);
171: static void print_man_head(MAN_ARGS);
1.30 kristaps 172: static struct tag *print_otag(struct html *, enum htmltag,
1.29 kristaps 173: int, const struct htmlpair *);
1.30 kristaps 174: static void print_tagq(struct html *, const struct tag *);
175: static void print_stagq(struct html *, const struct tag *);
1.29 kristaps 176: static void print_ctag(struct html *, enum htmltag);
1.32 kristaps 177: static void print_encode(struct html *, const char *);
178: static void print_escape(struct html *, const char **);
1.29 kristaps 179: static void print_text(struct html *, const char *);
1.32 kristaps 180: static void print_res(struct html *, const char *, int);
181: static void print_spec(struct html *, const char *, int);
1.33 kristaps 182:
1.43 kristaps 183: static int a2width(const char *);
184: static int a2offs(const char *);
185: static int a2list(const struct mdoc_node *);
186:
1.39 kristaps 187: static void mdoc_root_post(MDOC_ARGS);
1.29 kristaps 188: static int mdoc_root_pre(MDOC_ARGS);
1.34 kristaps 189: static int mdoc_tbl_pre(MDOC_ARGS, int);
1.37 kristaps 190: static int mdoc_tbl_block_pre(MDOC_ARGS, int, int, int, int);
1.34 kristaps 191: static int mdoc_tbl_body_pre(MDOC_ARGS, int, int);
192: static int mdoc_tbl_head_pre(MDOC_ARGS, int, int);
1.29 kristaps 193:
1.41 kristaps 194: static int mdoc_ad_pre(MDOC_ARGS);
195: static int mdoc_an_pre(MDOC_ARGS);
1.37 kristaps 196: static void mdoc_aq_post(MDOC_ARGS);
197: static int mdoc_aq_pre(MDOC_ARGS);
1.31 kristaps 198: static int mdoc_ar_pre(MDOC_ARGS);
1.39 kristaps 199: static int mdoc_bd_pre(MDOC_ARGS);
1.37 kristaps 200: static void mdoc_bl_post(MDOC_ARGS);
1.33 kristaps 201: static int mdoc_bl_pre(MDOC_ARGS);
1.41 kristaps 202: static int mdoc_cd_pre(MDOC_ARGS);
1.34 kristaps 203: static int mdoc_d1_pre(MDOC_ARGS);
204: static void mdoc_dq_post(MDOC_ARGS);
205: static int mdoc_dq_pre(MDOC_ARGS);
1.41 kristaps 206: static int mdoc_dv_pre(MDOC_ARGS);
207: static int mdoc_fa_pre(MDOC_ARGS);
208: static int mdoc_fd_pre(MDOC_ARGS);
1.30 kristaps 209: static int mdoc_fl_pre(MDOC_ARGS);
1.41 kristaps 210: static int mdoc_fn_pre(MDOC_ARGS);
211: static int mdoc_ft_pre(MDOC_ARGS);
1.34 kristaps 212: static int mdoc_em_pre(MDOC_ARGS);
1.41 kristaps 213: static int mdoc_er_pre(MDOC_ARGS);
214: static int mdoc_ev_pre(MDOC_ARGS);
1.34 kristaps 215: static int mdoc_ex_pre(MDOC_ARGS);
1.33 kristaps 216: static int mdoc_it_pre(MDOC_ARGS);
1.29 kristaps 217: static int mdoc_nd_pre(MDOC_ARGS);
218: static int mdoc_nm_pre(MDOC_ARGS);
1.31 kristaps 219: static int mdoc_ns_pre(MDOC_ARGS);
1.34 kristaps 220: static void mdoc_op_post(MDOC_ARGS);
1.30 kristaps 221: static int mdoc_op_pre(MDOC_ARGS);
1.39 kristaps 222: static int mdoc_pa_pre(MDOC_ARGS);
1.34 kristaps 223: static void mdoc_pq_post(MDOC_ARGS);
224: static int mdoc_pq_pre(MDOC_ARGS);
1.39 kristaps 225: static void mdoc_qq_post(MDOC_ARGS);
226: static int mdoc_qq_pre(MDOC_ARGS);
1.29 kristaps 227: static int mdoc_sh_pre(MDOC_ARGS);
1.48 kristaps 228: static int mdoc_sp_pre(MDOC_ARGS);
1.34 kristaps 229: static void mdoc_sq_post(MDOC_ARGS);
230: static int mdoc_sq_pre(MDOC_ARGS);
1.29 kristaps 231: static int mdoc_ss_pre(MDOC_ARGS);
1.34 kristaps 232: static int mdoc_sx_pre(MDOC_ARGS);
1.41 kristaps 233: static int mdoc_vt_pre(MDOC_ARGS);
1.30 kristaps 234: static int mdoc_xr_pre(MDOC_ARGS);
1.33 kristaps 235: static int mdoc_xx_pre(MDOC_ARGS);
236:
237: #ifdef __linux__
1.43 kristaps 238: extern int getsubopt(char **, char * const *, char **);
1.35 kristaps 239: extern size_t strlcpy(char *, const char *, size_t);
240: extern size_t strlcat(char *, const char *, size_t);
1.33 kristaps 241: #endif
1.29 kristaps 242:
243: static const struct htmlmdoc mdocs[MDOC_MAX] = {
1.48 kristaps 244: {NULL, NULL}, /* Ap */
1.29 kristaps 245: {NULL, NULL}, /* Dd */
246: {NULL, NULL}, /* Dt */
247: {NULL, NULL}, /* Os */
1.30 kristaps 248: {mdoc_sh_pre, NULL }, /* Sh */
249: {mdoc_ss_pre, NULL }, /* Ss */
1.48 kristaps 250: {mdoc_sp_pre, NULL}, /* Pp */
1.34 kristaps 251: {mdoc_d1_pre, NULL}, /* D1 */
252: {mdoc_d1_pre, NULL}, /* Dl */
1.39 kristaps 253: {mdoc_bd_pre, NULL}, /* Bd */
1.29 kristaps 254: {NULL, NULL}, /* Ed */
1.37 kristaps 255: {mdoc_bl_pre, mdoc_bl_post}, /* Bl */
1.29 kristaps 256: {NULL, NULL}, /* El */
1.33 kristaps 257: {mdoc_it_pre, NULL}, /* It */
1.41 kristaps 258: {mdoc_ad_pre, NULL}, /* Ad */
259: {mdoc_an_pre, NULL}, /* An */
1.31 kristaps 260: {mdoc_ar_pre, NULL}, /* Ar */
1.41 kristaps 261: {mdoc_cd_pre, NULL}, /* Cd */
262: {mdoc_fl_pre, NULL}, /* Cm */
263: {mdoc_dv_pre, NULL}, /* Dv */
264: {mdoc_er_pre, NULL}, /* Er */
265: {mdoc_ev_pre, NULL}, /* Ev */
1.34 kristaps 266: {mdoc_ex_pre, NULL}, /* Ex */
1.41 kristaps 267: {mdoc_fa_pre, NULL}, /* Fa */
268: {mdoc_fd_pre, NULL}, /* Fd */
1.30 kristaps 269: {mdoc_fl_pre, NULL}, /* Fl */
1.41 kristaps 270: {mdoc_fn_pre, NULL}, /* Fn */
271: {mdoc_ft_pre, NULL}, /* Ft */
1.29 kristaps 272: {NULL, NULL}, /* Ic */
273: {NULL, NULL}, /* In */
274: {NULL, NULL}, /* Li */
275: {mdoc_nd_pre, NULL}, /* Nd */
1.30 kristaps 276: {mdoc_nm_pre, NULL}, /* Nm */
277: {mdoc_op_pre, mdoc_op_post}, /* Op */
1.29 kristaps 278: {NULL, NULL}, /* Ot */
1.39 kristaps 279: {mdoc_pa_pre, NULL}, /* Pa */
1.29 kristaps 280: {NULL, NULL}, /* Rv */
281: {NULL, NULL}, /* St */
282: {NULL, NULL}, /* Va */
1.41 kristaps 283: {mdoc_vt_pre, NULL}, /* Vt */
1.30 kristaps 284: {mdoc_xr_pre, NULL}, /* Xr */
1.29 kristaps 285: {NULL, NULL}, /* %A */
286: {NULL, NULL}, /* %B */
287: {NULL, NULL}, /* %D */
288: {NULL, NULL}, /* %I */
289: {NULL, NULL}, /* %J */
290: {NULL, NULL}, /* %N */
291: {NULL, NULL}, /* %O */
292: {NULL, NULL}, /* %P */
293: {NULL, NULL}, /* %R */
294: {NULL, NULL}, /* %T */
295: {NULL, NULL}, /* %V */
296: {NULL, NULL}, /* Ac */
1.37 kristaps 297: {mdoc_aq_pre, mdoc_aq_post}, /* Ao */
298: {mdoc_aq_pre, mdoc_aq_post}, /* Aq */
1.29 kristaps 299: {NULL, NULL}, /* At */
300: {NULL, NULL}, /* Bc */
301: {NULL, NULL}, /* Bf */
302: {NULL, NULL}, /* Bo */
303: {NULL, NULL}, /* Bq */
1.33 kristaps 304: {mdoc_xx_pre, NULL}, /* Bsx */
1.29 kristaps 305: {NULL, NULL}, /* Bx */
306: {NULL, NULL}, /* Db */
307: {NULL, NULL}, /* Dc */
308: {NULL, NULL}, /* Do */
1.34 kristaps 309: {mdoc_dq_pre, mdoc_dq_post}, /* Dq */
1.29 kristaps 310: {NULL, NULL}, /* Ec */
311: {NULL, NULL}, /* Ef */
1.34 kristaps 312: {mdoc_em_pre, NULL}, /* Em */
1.29 kristaps 313: {NULL, NULL}, /* Eo */
1.33 kristaps 314: {mdoc_xx_pre, NULL}, /* Fx */
1.29 kristaps 315: {NULL, NULL}, /* Ms */
316: {NULL, NULL}, /* No */
1.31 kristaps 317: {mdoc_ns_pre, NULL}, /* Ns */
1.33 kristaps 318: {mdoc_xx_pre, NULL}, /* Nx */
319: {mdoc_xx_pre, NULL}, /* Ox */
1.29 kristaps 320: {NULL, NULL}, /* Pc */
321: {NULL, NULL}, /* Pf */
1.34 kristaps 322: {mdoc_pq_pre, mdoc_pq_post}, /* Po */
323: {mdoc_pq_pre, mdoc_pq_post}, /* Pq */
1.29 kristaps 324: {NULL, NULL}, /* Qc */
325: {NULL, NULL}, /* Ql */
1.39 kristaps 326: {mdoc_qq_pre, mdoc_qq_post}, /* Qo */
327: {mdoc_qq_pre, mdoc_qq_post}, /* Qq */
1.29 kristaps 328: {NULL, NULL}, /* Re */
329: {NULL, NULL}, /* Rs */
330: {NULL, NULL}, /* Sc */
1.34 kristaps 331: {mdoc_sq_pre, mdoc_sq_post}, /* So */
332: {mdoc_sq_pre, mdoc_sq_post}, /* Sq */
1.29 kristaps 333: {NULL, NULL}, /* Sm */
1.34 kristaps 334: {mdoc_sx_pre, NULL}, /* Sx */
1.29 kristaps 335: {NULL, NULL}, /* Sy */
336: {NULL, NULL}, /* Tn */
1.33 kristaps 337: {mdoc_xx_pre, NULL}, /* Ux */
1.29 kristaps 338: {NULL, NULL}, /* Xc */
339: {NULL, NULL}, /* Xo */
340: {NULL, NULL}, /* Fo */
341: {NULL, NULL}, /* Fc */
342: {NULL, NULL}, /* Oo */
343: {NULL, NULL}, /* Oc */
344: {NULL, NULL}, /* Bk */
345: {NULL, NULL}, /* Ek */
346: {NULL, NULL}, /* Bt */
347: {NULL, NULL}, /* Hf */
348: {NULL, NULL}, /* Fr */
349: {NULL, NULL}, /* Ud */
350: {NULL, NULL}, /* Lb */
1.48 kristaps 351: {mdoc_sp_pre, NULL}, /* Lp */
1.29 kristaps 352: {NULL, NULL}, /* Lk */
353: {NULL, NULL}, /* Mt */
354: {NULL, NULL}, /* Brq */
355: {NULL, NULL}, /* Bro */
356: {NULL, NULL}, /* Brc */
357: {NULL, NULL}, /* %C */
358: {NULL, NULL}, /* Es */
359: {NULL, NULL}, /* En */
1.33 kristaps 360: {mdoc_xx_pre, NULL}, /* Dx */
1.29 kristaps 361: {NULL, NULL}, /* %Q */
1.48 kristaps 362: {mdoc_sp_pre, NULL}, /* br */
363: {mdoc_sp_pre, NULL}, /* sp */
1.29 kristaps 364: };
1.10 kristaps 365:
1.35 kristaps 366: static char buf[BUFSIZ]; /* XXX */
367:
368: #define bufcat(x) (void)strlcat(buf, (x), BUFSIZ)
369: #define bufinit() buf[0] = 0
370: #define buffmt(...) (void)snprintf(buf, BUFSIZ - 1, __VA_ARGS__)
1.33 kristaps 371:
1.30 kristaps 372: void
1.29 kristaps 373: html_mdoc(void *arg, const struct mdoc *m)
1.10 kristaps 374: {
1.29 kristaps 375: struct html *h;
1.30 kristaps 376: struct tag *t;
1.10 kristaps 377:
1.29 kristaps 378: h = (struct html *)arg;
1.10 kristaps 379:
1.29 kristaps 380: print_gen_doctype(h);
1.30 kristaps 381: t = print_otag(h, TAG_HTML, 0, NULL);
1.29 kristaps 382: print_mdoc(mdoc_meta(m), mdoc_node(m), h);
1.30 kristaps 383: print_tagq(h, t);
384:
1.29 kristaps 385: printf("\n");
1.10 kristaps 386: }
387:
1.33 kristaps 388:
1.30 kristaps 389: void
1.29 kristaps 390: html_man(void *arg, const struct man *m)
1.10 kristaps 391: {
1.29 kristaps 392: struct html *h;
1.30 kristaps 393: struct tag *t;
1.10 kristaps 394:
1.29 kristaps 395: h = (struct html *)arg;
1.10 kristaps 396:
1.29 kristaps 397: print_gen_doctype(h);
1.30 kristaps 398: t = print_otag(h, TAG_HTML, 0, NULL);
1.29 kristaps 399: print_man(man_meta(m), man_node(m), h);
1.30 kristaps 400: print_tagq(h, t);
401:
1.29 kristaps 402: printf("\n");
1.10 kristaps 403: }
404:
1.33 kristaps 405:
1.29 kristaps 406: void *
1.43 kristaps 407: html_alloc(char *outopts)
1.10 kristaps 408: {
1.30 kristaps 409: struct html *h;
1.44 kristaps 410: char *toks[3], *v;
1.43 kristaps 411:
412: toks[0] = "style";
413: toks[1] = "base";
414: toks[2] = NULL;
1.30 kristaps 415:
416: if (NULL == (h = calloc(1, sizeof(struct html))))
417: return(NULL);
1.10 kristaps 418:
1.37 kristaps 419: SLIST_INIT(&h->tags);
420: SLIST_INIT(&h->ords);
421:
1.32 kristaps 422: if (NULL == (h->symtab = chars_init(CHARS_HTML))) {
423: free(h);
424: return(NULL);
425: }
1.41 kristaps 426:
1.47 kristaps 427: while (outopts && *outopts)
1.43 kristaps 428: switch (getsubopt(&outopts, toks, &v)) {
429: case (0):
430: h->style = v;
431: break;
432: case (1):
433: h->base = v;
434: break;
435: default:
436: break;
437: }
438:
1.30 kristaps 439: return(h);
1.29 kristaps 440: }
1.10 kristaps 441:
1.33 kristaps 442:
1.29 kristaps 443: void
444: html_free(void *p)
445: {
1.30 kristaps 446: struct tag *tag;
1.37 kristaps 447: struct ord *ord;
1.30 kristaps 448: struct html *h;
449:
450: h = (struct html *)p;
1.10 kristaps 451:
1.37 kristaps 452: while ( ! SLIST_EMPTY(&h->ords)) {
453: ord = SLIST_FIRST(&h->ords);
454: SLIST_REMOVE_HEAD(&h->ords, entry);
455: free(ord);
456: }
457:
458: while ( ! SLIST_EMPTY(&h->tags)) {
459: tag = SLIST_FIRST(&h->tags);
460: SLIST_REMOVE_HEAD(&h->tags, entry);
1.30 kristaps 461: free(tag);
462: }
1.36 kristaps 463:
464: if (h->symtab)
465: chars_free(h->symtab);
1.30 kristaps 466: free(h);
1.10 kristaps 467: }
1.2 kristaps 468:
1.33 kristaps 469:
1.43 kristaps 470: static int
471: a2list(const struct mdoc_node *n)
472: {
473: int i;
474:
475: assert(MDOC_BLOCK == n->type && MDOC_Bl == n->tok);
476: assert(n->args);
477:
478: for (i = 0; i < (int)n->args->argc; i++)
479: switch (n->args->argv[i].arg) {
480: case (MDOC_Enum):
481: /* FALLTHROUGH */
482: case (MDOC_Dash):
483: /* FALLTHROUGH */
484: case (MDOC_Hyphen):
485: /* FALLTHROUGH */
486: case (MDOC_Bullet):
487: /* FALLTHROUGH */
488: case (MDOC_Tag):
489: /* FALLTHROUGH */
490: case (MDOC_Hang):
491: /* FALLTHROUGH */
492: case (MDOC_Inset):
493: /* FALLTHROUGH */
494: case (MDOC_Diag):
495: /* FALLTHROUGH */
496: case (MDOC_Item):
497: /* FALLTHROUGH */
498: case (MDOC_Column):
499: /* FALLTHROUGH */
500: case (MDOC_Ohang):
501: return(n->args->argv[i].arg);
502: default:
503: break;
504: }
505:
506: abort();
507: /* NOTREACHED */
508: }
509:
510:
511: static int
512: a2width(const char *p)
513: {
514: int i, len;
515:
516: if (0 == (len = (int)strlen(p)))
517: return(0);
518: for (i = 0; i < len - 1; i++)
519: if ( ! isdigit((u_char)p[i]))
520: break;
521:
522: if (i == len - 1)
523: if ('n' == p[len - 1] || 'm' == p[len - 1])
524: return(atoi(p) + 2);
525:
526: return(len + 2);
527: }
528:
529:
530: static int
531: a2offs(const char *p)
532: {
533: int len, i;
534:
535: if (0 == strcmp(p, "left"))
536: return(0);
537: if (0 == strcmp(p, "indent"))
538: return(INDENT + 1);
539: if (0 == strcmp(p, "indent-two"))
540: return((INDENT + 1) * 2);
541:
542: if (0 == (len = (int)strlen(p)))
543: return(0);
544:
545: for (i = 0; i < len - 1; i++)
546: if ( ! isdigit((u_char)p[i]))
547: break;
548:
549: if (i == len - 1)
550: if ('n' == p[len - 1] || 'm' == p[len - 1])
551: return(atoi(p));
552:
553: return(len);
554: }
555:
556:
1.29 kristaps 557: static void
558: print_mdoc(MDOC_ARGS)
1.4 kristaps 559: {
1.30 kristaps 560: struct tag *t;
1.46 kristaps 561: struct htmlpair tag;
1.4 kristaps 562:
1.30 kristaps 563: t = print_otag(h, TAG_HEAD, 0, NULL);
1.29 kristaps 564: print_mdoc_head(m, n, h);
1.30 kristaps 565: print_tagq(h, t);
566:
567: t = print_otag(h, TAG_BODY, 0, NULL);
1.46 kristaps 568:
569: tag.key = ATTR_CLASS;
570: tag.val = "body";
571: print_otag(h, TAG_DIV, 1, &tag);
572:
1.39 kristaps 573: print_mdoc_nodelist(m, n, h);
1.30 kristaps 574: print_tagq(h, t);
1.29 kristaps 575: }
1.4 kristaps 576:
1.33 kristaps 577:
1.29 kristaps 578: static void
579: print_gen_head(struct html *h)
580: {
1.41 kristaps 581: struct htmlpair tag[4];
582:
583: tag[0].key = ATTR_HTTPEQUIV;
584: tag[0].val = "Content-Type";
585: tag[1].key = ATTR_CONTENT;
586: tag[1].val = "text/html; charset=utf-8";
587: print_otag(h, TAG_META, 2, tag);
588:
589: tag[0].key = ATTR_NAME;
590: tag[0].val = "resource-type";
591: tag[1].key = ATTR_CONTENT;
592: tag[1].val = "document";
593: print_otag(h, TAG_META, 2, tag);
594:
595: if (h->style) {
596: tag[0].key = ATTR_REL;
597: tag[0].val = "stylesheet";
598: tag[1].key = ATTR_HREF;
599: tag[1].val = h->style;
600: tag[2].key = ATTR_TYPE;
601: tag[2].val = "text/css";
602: tag[3].key = ATTR_MEDIA;
603: tag[3].val = "all";
604: print_otag(h, TAG_LINK, 4, tag);
605: }
606:
607: if (h->base) {
608: tag[0].key = ATTR_HREF;
609: tag[1].val = h->base;
610: print_otag(h, TAG_BASE, 1, tag);
611: }
1.4 kristaps 612: }
613:
1.33 kristaps 614:
1.30 kristaps 615: /* ARGSUSED */
1.29 kristaps 616: static void
617: print_mdoc_head(MDOC_ARGS)
1.18 kristaps 618: {
619:
1.29 kristaps 620: print_gen_head(h);
621: print_otag(h, TAG_TITLE, 0, NULL);
1.41 kristaps 622: print_text(h, m->title);
1.2 kristaps 623: }
624:
1.33 kristaps 625:
1.29 kristaps 626: static void
1.39 kristaps 627: print_mdoc_nodelist(MDOC_ARGS)
628: {
629:
630: print_mdoc_node(m, n, h);
631: if (n->next)
632: print_mdoc_nodelist(m, n->next, h);
633: }
634:
635:
636: static void
1.29 kristaps 637: print_mdoc_node(MDOC_ARGS)
1.2 kristaps 638: {
1.29 kristaps 639: int child;
1.30 kristaps 640: struct tag *t;
1.8 kristaps 641:
1.29 kristaps 642: child = 1;
1.37 kristaps 643: t = SLIST_FIRST(&h->tags);
1.8 kristaps 644:
1.35 kristaps 645: bufinit();
646:
1.29 kristaps 647: switch (n->type) {
648: case (MDOC_ROOT):
649: child = mdoc_root_pre(m, n, h);
1.7 kristaps 650: break;
1.29 kristaps 651: case (MDOC_TEXT):
652: print_text(h, n->string);
1.7 kristaps 653: break;
1.3 kristaps 654: default:
1.29 kristaps 655: if (mdocs[n->tok].pre)
656: child = (*mdocs[n->tok].pre)(m, n, h);
1.3 kristaps 657: break;
1.2 kristaps 658: }
659:
1.29 kristaps 660: if (child && n->child)
1.39 kristaps 661: print_mdoc_nodelist(m, n->child, h);
1.8 kristaps 662:
1.30 kristaps 663: print_stagq(h, t);
664:
1.35 kristaps 665: bufinit();
666:
1.29 kristaps 667: switch (n->type) {
668: case (MDOC_ROOT):
1.39 kristaps 669: mdoc_root_post(m, n, h);
1.7 kristaps 670: break;
1.29 kristaps 671: case (MDOC_TEXT):
1.7 kristaps 672: break;
1.3 kristaps 673: default:
1.29 kristaps 674: if (mdocs[n->tok].post)
675: (*mdocs[n->tok].post)(m, n, h);
1.3 kristaps 676: break;
677: }
1.2 kristaps 678: }
679:
1.33 kristaps 680:
1.29 kristaps 681: static void
682: print_man(MAN_ARGS)
1.9 kristaps 683: {
1.30 kristaps 684: struct tag *t;
1.9 kristaps 685:
1.30 kristaps 686: t = print_otag(h, TAG_HEAD, 0, NULL);
1.29 kristaps 687: print_man_head(m, n, h);
1.30 kristaps 688: print_tagq(h, t);
689:
690: t = print_otag(h, TAG_BODY, 0, NULL);
1.41 kristaps 691: /*print_man_body(m, n, h);*/
1.30 kristaps 692: print_tagq(h, t);
1.9 kristaps 693: }
694:
1.33 kristaps 695:
1.30 kristaps 696: /* ARGSUSED */
1.9 kristaps 697: static void
1.29 kristaps 698: print_man_head(MAN_ARGS)
1.9 kristaps 699: {
700:
1.29 kristaps 701: print_gen_head(h);
702: print_otag(h, TAG_TITLE, 0, NULL);
1.41 kristaps 703: print_text(h, m->title);
1.9 kristaps 704: }
705:
1.33 kristaps 706:
1.32 kristaps 707: static void
708: print_spec(struct html *h, const char *p, int len)
709: {
710: const char *rhs;
711: int i;
712: size_t sz;
713:
714: rhs = chars_a2ascii(h->symtab, p, (size_t)len, &sz);
715:
716: if (NULL == rhs)
717: return;
718: for (i = 0; i < (int)sz; i++)
719: putchar(rhs[i]);
720: }
721:
1.33 kristaps 722:
1.32 kristaps 723: static void
724: print_res(struct html *h, const char *p, int len)
725: {
726: const char *rhs;
727: int i;
728: size_t sz;
729:
730: rhs = chars_a2res(h->symtab, p, (size_t)len, &sz);
731:
732: if (NULL == rhs)
733: return;
734: for (i = 0; i < (int)sz; i++)
735: putchar(rhs[i]);
736: }
737:
1.33 kristaps 738:
1.32 kristaps 739: static void
740: print_escape(struct html *h, const char **p)
741: {
742: int j, type;
743: const char *wp;
744:
745: wp = *p;
746: type = 1;
747:
748: if (0 == *(++wp)) {
749: *p = wp;
750: return;
751: }
752:
753: if ('(' == *wp) {
754: wp++;
755: if (0 == *wp || 0 == *(wp + 1)) {
756: *p = 0 == *wp ? wp : wp + 1;
757: return;
758: }
759:
760: print_spec(h, wp, 2);
761: *p = ++wp;
762: return;
763:
764: } else if ('*' == *wp) {
765: if (0 == *(++wp)) {
766: *p = wp;
767: return;
768: }
769:
770: switch (*wp) {
771: case ('('):
772: wp++;
773: if (0 == *wp || 0 == *(wp + 1)) {
774: *p = 0 == *wp ? wp : wp + 1;
775: return;
776: }
777:
778: print_res(h, wp, 2);
779: *p = ++wp;
780: return;
781: case ('['):
782: type = 0;
783: break;
784: default:
785: print_res(h, wp, 1);
786: *p = wp;
787: return;
788: }
789:
790: } else if ('f' == *wp) {
791: if (0 == *(++wp)) {
792: *p = wp;
793: return;
794: }
795:
796: switch (*wp) {
797: case ('B'):
798: /* TODO */
799: break;
800: case ('I'):
801: /* TODO */
802: break;
803: case ('P'):
804: /* FALLTHROUGH */
805: case ('R'):
806: /* TODO */
807: break;
808: default:
809: break;
810: }
811:
812: *p = wp;
813: return;
814:
815: } else if ('[' != *wp) {
816: print_spec(h, wp, 1);
817: *p = wp;
818: return;
819: }
820:
821: wp++;
822: for (j = 0; *wp && ']' != *wp; wp++, j++)
823: /* Loop... */ ;
824:
825: if (0 == *wp) {
826: *p = wp;
827: return;
828: }
829:
830: if (type)
831: print_spec(h, wp - j, j);
832: else
833: print_res(h, wp - j, j);
834:
835: *p = wp;
836: }
837:
1.9 kristaps 838:
1.29 kristaps 839: static void
1.32 kristaps 840: print_encode(struct html *h, const char *p)
1.29 kristaps 841: {
1.14 kristaps 842:
1.32 kristaps 843: for (; *p; p++) {
1.34 kristaps 844: if ('\\' == *p) {
845: print_escape(h, &p);
846: continue;
847: }
848: switch (*p) {
849: case ('<'):
850: printf("<");
851: break;
852: case ('>'):
853: printf(">");
854: break;
855: case ('&'):
856: printf("&");
857: break;
858: default:
1.32 kristaps 859: putchar(*p);
1.34 kristaps 860: break;
1.32 kristaps 861: }
862: }
1.14 kristaps 863: }
864:
865:
1.30 kristaps 866: static struct tag *
1.29 kristaps 867: print_otag(struct html *h, enum htmltag tag,
868: int sz, const struct htmlpair *p)
1.14 kristaps 869: {
1.29 kristaps 870: int i;
1.30 kristaps 871: struct tag *t;
872:
873: if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
874: if (NULL == (t = malloc(sizeof(struct tag))))
875: err(EXIT_FAILURE, "malloc");
876: t->tag = tag;
1.37 kristaps 877: SLIST_INSERT_HEAD(&h->tags, t, entry);
1.30 kristaps 878: } else
879: t = NULL;
1.29 kristaps 880:
881: if ( ! (HTML_NOSPACE & h->flags))
1.30 kristaps 882: if ( ! (HTML_CLRLINE & htmltags[tag].flags))
1.29 kristaps 883: printf(" ");
884:
885: printf("<%s", htmltags[tag].name);
886: for (i = 0; i < sz; i++) {
887: printf(" %s=\"", htmlattrs[p[i].key]);
888: assert(p->val);
1.32 kristaps 889: print_encode(h, p[i].val);
1.29 kristaps 890: printf("\"");
891: }
892: printf(">");
1.14 kristaps 893:
1.29 kristaps 894: h->flags |= HTML_NOSPACE;
1.30 kristaps 895: if (HTML_CLRLINE & htmltags[tag].flags)
896: h->flags |= HTML_NEWLINE;
897: else
898: h->flags &= ~HTML_NEWLINE;
1.14 kristaps 899:
1.30 kristaps 900: return(t);
1.14 kristaps 901: }
902:
903:
904: /* ARGSUSED */
1.29 kristaps 905: static void
906: print_ctag(struct html *h, enum htmltag tag)
1.14 kristaps 907: {
908:
1.29 kristaps 909: printf("</%s>", htmltags[tag].name);
1.30 kristaps 910: if (HTML_CLRLINE & htmltags[tag].flags)
1.29 kristaps 911: h->flags |= HTML_NOSPACE;
1.30 kristaps 912: if (HTML_CLRLINE & htmltags[tag].flags)
913: h->flags |= HTML_NEWLINE;
914: else
915: h->flags &= ~HTML_NEWLINE;
1.14 kristaps 916: }
917:
918:
1.29 kristaps 919: /* ARGSUSED */
920: static void
921: print_gen_doctype(struct html *h)
1.1 kristaps 922: {
1.29 kristaps 923:
1.46 kristaps 924: printf("<!DOCTYPE HTML PUBLIC \"%s\" \"%s\">", DOCTYPE, DTD);
1.1 kristaps 925: }
926:
927:
1.29 kristaps 928: static void
929: print_text(struct html *h, const char *p)
1.1 kristaps 930: {
931:
1.29 kristaps 932: if (*p && 0 == *(p + 1))
933: switch (*p) {
934: case('.'):
935: /* FALLTHROUGH */
936: case(','):
937: /* FALLTHROUGH */
938: case(';'):
939: /* FALLTHROUGH */
940: case(':'):
941: /* FALLTHROUGH */
942: case('?'):
943: /* FALLTHROUGH */
944: case('!'):
945: /* FALLTHROUGH */
946: case(')'):
947: /* FALLTHROUGH */
948: case(']'):
949: /* FALLTHROUGH */
950: case('}'):
951: h->flags |= HTML_NOSPACE;
1.30 kristaps 952: break;
1.29 kristaps 953: default:
954: break;
955: }
1.1 kristaps 956:
1.29 kristaps 957: if ( ! (h->flags & HTML_NOSPACE))
958: printf(" ");
1.30 kristaps 959:
1.29 kristaps 960: h->flags &= ~HTML_NOSPACE;
1.30 kristaps 961: h->flags &= ~HTML_NEWLINE;
1.1 kristaps 962:
1.29 kristaps 963: if (p)
1.32 kristaps 964: print_encode(h, p);
1.8 kristaps 965:
1.29 kristaps 966: if (*p && 0 == *(p + 1))
967: switch (*p) {
968: case('('):
969: /* FALLTHROUGH */
970: case('['):
971: /* FALLTHROUGH */
972: case('{'):
973: h->flags |= HTML_NOSPACE;
1.30 kristaps 974: break;
1.29 kristaps 975: default:
976: break;
977: }
1.1 kristaps 978: }
1.30 kristaps 979:
980:
981: static void
982: print_tagq(struct html *h, const struct tag *until)
983: {
984: struct tag *tag;
985:
1.37 kristaps 986: while ( ! SLIST_EMPTY(&h->tags)) {
987: tag = SLIST_FIRST(&h->tags);
1.30 kristaps 988: print_ctag(h, tag->tag);
1.37 kristaps 989: SLIST_REMOVE_HEAD(&h->tags, entry);
1.30 kristaps 990: free(tag);
991: if (until && tag == until)
992: return;
993: }
994: }
995:
996:
997: static void
998: print_stagq(struct html *h, const struct tag *suntil)
999: {
1000: struct tag *tag;
1001:
1.37 kristaps 1002: while ( ! SLIST_EMPTY(&h->tags)) {
1003: tag = SLIST_FIRST(&h->tags);
1.30 kristaps 1004: if (suntil && tag == suntil)
1005: return;
1006: print_ctag(h, tag->tag);
1.37 kristaps 1007: SLIST_REMOVE_HEAD(&h->tags, entry);
1.30 kristaps 1008: free(tag);
1009: }
1010: }
1011:
1012:
1.39 kristaps 1013: /* ARGSUSED */
1014: static void
1015: mdoc_root_post(MDOC_ARGS)
1016: {
1.41 kristaps 1017: struct tm tm;
1018: struct htmlpair tag[2];
1019: struct tag *t, *tt;
1020: char b[BUFSIZ];
1.39 kristaps 1021:
1.41 kristaps 1022: (void)localtime_r(&m->date, &tm);
1.39 kristaps 1023:
1.41 kristaps 1024: if (0 == strftime(b, BUFSIZ - 1, "%B %e, %Y", &tm))
1.39 kristaps 1025: err(EXIT_FAILURE, "strftime");
1.33 kristaps 1026:
1.41 kristaps 1027: tag[0].key = ATTR_CLASS;
1028: tag[0].val = "footer";
1029: tag[1].key = ATTR_STYLE;
1030: tag[1].val = "width: 100%;";
1031: t = print_otag(h, TAG_TABLE, 2, tag);
1032: tt = print_otag(h, TAG_TR, 0, NULL);
1.33 kristaps 1033:
1.41 kristaps 1034: tag[0].key = ATTR_STYLE;
1035: tag[0].val = "width: 50%;";
1036: print_otag(h, TAG_TD, 1, tag);
1.39 kristaps 1037: print_text(h, b);
1.41 kristaps 1038: print_stagq(h, tt);
1.39 kristaps 1039:
1.41 kristaps 1040: tag[0].key = ATTR_STYLE;
1041: tag[0].val = "width: 50%; text-align: right;";
1042: print_otag(h, TAG_TD, 1, tag);
1043: print_text(h, m->os);
1.39 kristaps 1044: print_tagq(h, t);
1045: }
1046:
1047:
1.30 kristaps 1048: /* ARGSUSED */
1049: static int
1050: mdoc_root_pre(MDOC_ARGS)
1051: {
1.41 kristaps 1052: struct htmlpair tag[2];
1.39 kristaps 1053: struct tag *t, *tt;
1054: char b[BUFSIZ], title[BUFSIZ];
1055:
1056: (void)strlcpy(b, m->vol, BUFSIZ);
1057:
1058: if (m->arch) {
1.41 kristaps 1059: (void)strlcat(b, " (", BUFSIZ);
1060: (void)strlcat(b, m->arch, BUFSIZ);
1061: (void)strlcat(b, ")", BUFSIZ);
1.39 kristaps 1062: }
1063:
1.41 kristaps 1064: (void)snprintf(title, BUFSIZ - 1,
1065: "%s(%d)", m->title, m->msec);
1.39 kristaps 1066:
1.41 kristaps 1067: tag[0].key = ATTR_CLASS;
1068: tag[0].val = "header";
1069: tag[1].key = ATTR_STYLE;
1070: tag[1].val = "width: 100%;";
1.46 kristaps 1071: t = print_otag(h, TAG_TABLE, 2, tag);
1.41 kristaps 1072: tt = print_otag(h, TAG_TR, 0, NULL);
1.39 kristaps 1073:
1.41 kristaps 1074: tag[0].key = ATTR_STYLE;
1075: tag[0].val = "width: 33%;";
1076: print_otag(h, TAG_TD, 1, tag);
1.39 kristaps 1077: print_text(h, b);
1078: print_stagq(h, tt);
1079:
1.41 kristaps 1080: tag[0].key = ATTR_STYLE;
1081: tag[0].val = "width: 33%; text-align: center;";
1082: print_otag(h, TAG_TD, 1, tag);
1.39 kristaps 1083: print_text(h, title);
1084: print_stagq(h, tt);
1085:
1.41 kristaps 1086: tag[0].key = ATTR_STYLE;
1087: tag[0].val = "width: 33%; text-align: right;";
1088: print_otag(h, TAG_TD, 1, tag);
1.39 kristaps 1089: print_text(h, b);
1.46 kristaps 1090: print_tagq(h, t);
1.30 kristaps 1091:
1092: return(1);
1093: }
1094:
1095:
1096: /* ARGSUSED */
1097: static int
1.35 kristaps 1098: mdoc_sh_pre(MDOC_ARGS)
1.30 kristaps 1099: {
1.41 kristaps 1100: struct htmlpair tag[2];
1101: const struct mdoc_node *nn;
1.34 kristaps 1102:
1.35 kristaps 1103: if (MDOC_HEAD == n->type) {
1104: tag[0].key = ATTR_CLASS;
1105: tag[0].val = "sec-head";
1106: print_otag(h, TAG_DIV, 1, tag);
1107: print_otag(h, TAG_SPAN, 1, tag);
1.41 kristaps 1108:
1109: for (nn = n->child; nn; nn = nn->next) {
1110: bufcat(nn->string);
1111: if (nn->next)
1112: bufcat(" ");
1113: }
1114: tag[0].key = ATTR_NAME;
1115: tag[0].val = buf;
1116: print_otag(h, TAG_A, 1, tag);
1.35 kristaps 1117: return(1);
1118: } else if (MDOC_BLOCK == n->type) {
1119: tag[0].key = ATTR_CLASS;
1120: tag[0].val = "sec-block";
1.39 kristaps 1121:
1122: if (n->prev && NULL == n->prev->body->child) {
1123: print_otag(h, TAG_DIV, 1, tag);
1124: return(1);
1125: }
1126:
1.40 kristaps 1127: bufcat("margin-top: 1em;");
1128: if (NULL == n->next)
1129: bufcat("margin-bottom: 1em;");
1130:
1.39 kristaps 1131: tag[1].key = ATTR_STYLE;
1.40 kristaps 1132: tag[1].val = buf;
1.39 kristaps 1133:
1134: print_otag(h, TAG_DIV, 2, tag);
1.35 kristaps 1135: return(1);
1136: }
1137:
1138: buffmt("margin-left: %dem;", INDENT);
1139:
1.34 kristaps 1140: tag[0].key = ATTR_CLASS;
1.35 kristaps 1141: tag[0].val = "sec-body";
1142: tag[1].key = ATTR_STYLE;
1143: tag[1].val = buf;
1144:
1145: print_otag(h, TAG_DIV, 2, tag);
1146: return(1);
1147: }
1148:
1149:
1150: /* ARGSUSED */
1151: static int
1152: mdoc_ss_pre(MDOC_ARGS)
1153: {
1.41 kristaps 1154: struct htmlpair tag[2];
1155: int i;
1156: const struct mdoc_node *nn;
1.35 kristaps 1157:
1158: i = 0;
1159:
1160: if (MDOC_BODY == n->type) {
1161: tag[i].key = ATTR_CLASS;
1162: tag[i++].val = "ssec-body";
1163: if (n->parent->next && n->child) {
1164: bufcat("margin-bottom: 1em;");
1165: tag[i].key = ATTR_STYLE;
1166: tag[i++].val = buf;
1167: }
1168: print_otag(h, TAG_DIV, i, tag);
1169: return(1);
1170: } else if (MDOC_BLOCK == n->type) {
1171: tag[i].key = ATTR_CLASS;
1172: tag[i++].val = "ssec-block";
1173: if (n->prev) {
1174: bufcat("margin-top: 1em;");
1175: tag[i].key = ATTR_STYLE;
1176: tag[i++].val = buf;
1177: }
1178: print_otag(h, TAG_DIV, i, tag);
1179: return(1);
1180: }
1181:
1182: buffmt("margin-left: -%dem;", INDENT - HALFINDENT);
1.34 kristaps 1183:
1.35 kristaps 1184: tag[0].key = ATTR_CLASS;
1185: tag[0].val = "ssec-head";
1.34 kristaps 1186: tag[1].key = ATTR_STYLE;
1.35 kristaps 1187: tag[1].val = buf;
1.30 kristaps 1188:
1.35 kristaps 1189: print_otag(h, TAG_DIV, 2, tag);
1190: print_otag(h, TAG_SPAN, 1, tag);
1.41 kristaps 1191:
1192: bufinit();
1193: for (nn = n->child; nn; nn = nn->next) {
1194: bufcat(nn->string);
1195: if (nn->next)
1196: bufcat(" ");
1197: }
1198: tag[0].key = ATTR_NAME;
1199: tag[0].val = buf;
1200: print_otag(h, TAG_A, 1, tag);
1201:
1.30 kristaps 1202: return(1);
1203: }
1204:
1205:
1206: /* ARGSUSED */
1207: static int
1208: mdoc_fl_pre(MDOC_ARGS)
1209: {
1210: struct htmlpair tag;
1211:
1212: tag.key = ATTR_CLASS;
1213: tag.val = "flag";
1214:
1215: print_otag(h, TAG_SPAN, 1, &tag);
1.41 kristaps 1216: if (MDOC_Fl == n->tok) {
1217: print_text(h, "\\-");
1218: h->flags |= HTML_NOSPACE;
1219: }
1.30 kristaps 1220: return(1);
1221: }
1222:
1223:
1224: /* ARGSUSED */
1225: static int
1226: mdoc_nd_pre(MDOC_ARGS)
1227: {
1.35 kristaps 1228: struct htmlpair tag;
1229:
1230: if (MDOC_BODY != n->type)
1231: return(1);
1.30 kristaps 1232:
1.35 kristaps 1233: /* XXX - this can contain block elements! */
1234: print_text(h, "\\(em");
1235: tag.key = ATTR_CLASS;
1236: tag.val = "desc-body";
1237: print_otag(h, TAG_SPAN, 1, &tag);
1.30 kristaps 1238: return(1);
1239: }
1240:
1241:
1242: /* ARGSUSED */
1243: static int
1244: mdoc_op_pre(MDOC_ARGS)
1245: {
1.35 kristaps 1246: struct htmlpair tag;
1247:
1248: if (MDOC_BODY != n->type)
1249: return(1);
1.30 kristaps 1250:
1.35 kristaps 1251: /* XXX - this can contain block elements! */
1252: print_text(h, "\\(lB");
1.46 kristaps 1253: h->flags |= HTML_NOSPACE;
1.35 kristaps 1254: tag.key = ATTR_CLASS;
1255: tag.val = "opt";
1256: print_otag(h, TAG_SPAN, 1, &tag);
1.30 kristaps 1257: return(1);
1258: }
1259:
1260:
1261: /* ARGSUSED */
1262: static void
1263: mdoc_op_post(MDOC_ARGS)
1264: {
1265:
1266: if (MDOC_BODY != n->type)
1267: return;
1268: h->flags |= HTML_NOSPACE;
1269: print_text(h, "\\(rB");
1270: }
1271:
1272:
1273: static int
1274: mdoc_nm_pre(MDOC_ARGS)
1275: {
1.35 kristaps 1276: struct htmlpair tag;
1.30 kristaps 1277:
1278: if ( ! (HTML_NEWLINE & h->flags))
1.35 kristaps 1279: if (SEC_SYNOPSIS == n->sec) {
1280: tag.key = ATTR_STYLE;
1281: tag.val = "clear: both;";
1282: print_otag(h, TAG_BR, 1, &tag);
1283: }
1.30 kristaps 1284:
1.35 kristaps 1285: tag.key = ATTR_CLASS;
1286: tag.val = "name";
1.30 kristaps 1287:
1.35 kristaps 1288: print_otag(h, TAG_SPAN, 1, &tag);
1.30 kristaps 1289: if (NULL == n->child)
1290: print_text(h, m->name);
1291:
1292: return(1);
1293: }
1294:
1295:
1296: /* ARGSUSED */
1297: static int
1298: mdoc_xr_pre(MDOC_ARGS)
1299: {
1.41 kristaps 1300: struct htmlpair tag[2];
1301: const char *name, *sec;
1302: const struct mdoc_node *nn;
1303:
1304: nn = n->child;
1305: name = nn && nn->string ? nn->string : "";
1306: nn = nn ? nn->next : NULL;
1307: sec = nn && nn->string ? nn->string : "";
1308:
1309: buffmt("%s%s%s.html", name, name && sec ? "." : "", sec);
1.30 kristaps 1310:
1.35 kristaps 1311: tag[0].key = ATTR_CLASS;
1312: tag[0].val = "link-man";
1313: tag[1].key = ATTR_HREF;
1.41 kristaps 1314: tag[1].val = buf;
1.35 kristaps 1315: print_otag(h, TAG_A, 2, tag);
1.30 kristaps 1316:
1.41 kristaps 1317: nn = n->child;
1318: print_text(h, nn->string);
1319: if (NULL == (nn = nn->next))
1.30 kristaps 1320: return(0);
1321:
1322: h->flags |= HTML_NOSPACE;
1323: print_text(h, "(");
1324: h->flags |= HTML_NOSPACE;
1.41 kristaps 1325: print_text(h, nn->string);
1.30 kristaps 1326: h->flags |= HTML_NOSPACE;
1327: print_text(h, ")");
1328:
1329: return(0);
1330: }
1.31 kristaps 1331:
1332:
1333: /* ARGSUSED */
1334: static int
1335: mdoc_ns_pre(MDOC_ARGS)
1336: {
1337:
1338: h->flags |= HTML_NOSPACE;
1339: return(1);
1340: }
1341:
1.35 kristaps 1342:
1.31 kristaps 1343: /* ARGSUSED */
1344: static int
1345: mdoc_ar_pre(MDOC_ARGS)
1346: {
1347: struct htmlpair tag;
1348:
1349: tag.key = ATTR_CLASS;
1350: tag.val = "arg";
1351:
1352: print_otag(h, TAG_SPAN, 1, &tag);
1353: return(1);
1354: }
1.33 kristaps 1355:
1.35 kristaps 1356:
1.33 kristaps 1357: /* ARGSUSED */
1358: static int
1359: mdoc_xx_pre(MDOC_ARGS)
1360: {
1361: const char *pp;
1.35 kristaps 1362: struct htmlpair tag;
1.33 kristaps 1363:
1364: switch (n->tok) {
1365: case (MDOC_Bsx):
1366: pp = "BSDI BSD/OS";
1367: break;
1368: case (MDOC_Dx):
1369: pp = "DragonFlyBSD";
1370: break;
1371: case (MDOC_Fx):
1372: pp = "FreeBSD";
1373: break;
1374: case (MDOC_Nx):
1375: pp = "NetBSD";
1376: break;
1377: case (MDOC_Ox):
1378: pp = "OpenBSD";
1379: break;
1380: case (MDOC_Ux):
1381: pp = "UNIX";
1382: break;
1383: default:
1384: return(1);
1385: }
1386:
1.35 kristaps 1387: tag.key = ATTR_CLASS;
1388: tag.val = "unix";
1389:
1390: print_otag(h, TAG_SPAN, 1, &tag);
1.33 kristaps 1391: print_text(h, pp);
1392: return(1);
1393: }
1394:
1395:
1.35 kristaps 1396: /* ARGSUSED */
1.33 kristaps 1397: static int
1.37 kristaps 1398: mdoc_tbl_block_pre(MDOC_ARGS, int t, int w, int o, int c)
1.34 kristaps 1399: {
1400: struct htmlpair tag;
1401:
1.37 kristaps 1402: switch (t) {
1.38 kristaps 1403: case (MDOC_Column):
1404: /* FALLTHROUGH */
1.37 kristaps 1405: case (MDOC_Item):
1406: /* FALLTHROUGH */
1407: case (MDOC_Ohang):
1408: buffmt("margin-left: %dem; clear: both;", o);
1409: break;
1410: default:
1411: buffmt("margin-left: %dem; clear: both;", w + o);
1412: break;
1413: }
1.34 kristaps 1414:
1.46 kristaps 1415: if ( ! c && MDOC_Column != t) {
1416: if (n->prev && n->prev->body->child)
1417: bufcat("padding-top: 1em;");
1418: else if (NULL == n->prev)
1419: bufcat("padding-top: 1em;");
1420: }
1.34 kristaps 1421:
1422: tag.key = ATTR_STYLE;
1423: tag.val = buf;
1424: print_otag(h, TAG_DIV, 1, &tag);
1425: return(1);
1426: }
1427:
1428:
1.35 kristaps 1429: /* ARGSUSED */
1.34 kristaps 1430: static int
1431: mdoc_tbl_body_pre(MDOC_ARGS, int t, int w)
1432: {
1433:
1.37 kristaps 1434: print_otag(h, TAG_DIV, 0, NULL);
1.34 kristaps 1435: return(1);
1436: }
1437:
1438:
1.35 kristaps 1439: /* ARGSUSED */
1.34 kristaps 1440: static int
1.35 kristaps 1441: mdoc_tbl_head_pre(MDOC_ARGS, int t, int w)
1.33 kristaps 1442: {
1.34 kristaps 1443: struct htmlpair tag;
1.37 kristaps 1444: struct ord *ord;
1445: char nbuf[BUFSIZ];
1.34 kristaps 1446:
1.35 kristaps 1447: switch (t) {
1.37 kristaps 1448: case (MDOC_Item):
1.35 kristaps 1449: /* FALLTHROUGH */
1.37 kristaps 1450: case (MDOC_Ohang):
1451: print_otag(h, TAG_DIV, 0, NULL);
1452: break;
1.38 kristaps 1453: case (MDOC_Column):
1454: buffmt("min-width: %dem;", w);
1455: bufcat("clear: none;");
1456: if (n->next && MDOC_HEAD == n->next->type)
1457: bufcat("float: left;");
1458: tag.key = ATTR_STYLE;
1459: tag.val = buf;
1460: print_otag(h, TAG_DIV, 1, &tag);
1461: break;
1.37 kristaps 1462: default:
1.35 kristaps 1463: buffmt("margin-left: -%dem;", w);
1464: bufcat("clear: left;");
1465: bufcat("float: left;");
1466: bufcat("padding-right: 1em;");
1.37 kristaps 1467: tag.key = ATTR_STYLE;
1468: tag.val = buf;
1469: print_otag(h, TAG_DIV, 1, &tag);
1.34 kristaps 1470: break;
1.37 kristaps 1471: }
1472:
1473: switch (t) {
1474: case (MDOC_Diag):
1475: tag.key = ATTR_CLASS;
1476: tag.val = "diag";
1477: print_otag(h, TAG_SPAN, 1, &tag);
1478: break;
1479: case (MDOC_Enum):
1480: ord = SLIST_FIRST(&h->ords);
1481: assert(ord);
1482: nbuf[BUFSIZ - 1] = 0;
1483: (void)snprintf(nbuf, BUFSIZ - 1, "%d.", ord->pos++);
1484: print_text(h, nbuf);
1485: return(0);
1486: case (MDOC_Dash):
1487: print_text(h, "\\(en");
1488: return(0);
1489: case (MDOC_Hyphen):
1490: print_text(h, "\\-");
1491: return(0);
1492: case (MDOC_Bullet):
1493: print_text(h, "\\(bu");
1494: return(0);
1.34 kristaps 1495: default:
1496: break;
1.33 kristaps 1497: }
1498:
1.34 kristaps 1499: return(1);
1500: }
1501:
1502:
1503: static int
1504: mdoc_tbl_pre(MDOC_ARGS, int type)
1505: {
1.38 kristaps 1506: int i, w, o, c, wp;
1507: const struct mdoc_node *bl, *nn;
1.34 kristaps 1508:
1.33 kristaps 1509: bl = n->parent->parent;
1510: if (MDOC_BLOCK != n->type)
1511: bl = bl->parent;
1512:
1.34 kristaps 1513: /* FIXME: fmt_vspace() equivalent. */
1514:
1.33 kristaps 1515: assert(bl->args);
1516:
1.34 kristaps 1517: w = o = c = 0;
1.38 kristaps 1518: wp = -1;
1.34 kristaps 1519:
1520: for (i = 0; i < (int)bl->args->argc; i++)
1.33 kristaps 1521: if (MDOC_Width == bl->args->argv[i].arg) {
1522: assert(bl->args->argv[i].sz);
1.38 kristaps 1523: wp = i;
1.43 kristaps 1524: w = a2width(bl->args->argv[i].value[0]);
1.34 kristaps 1525: } else if (MDOC_Offset == bl->args->argv[i].arg) {
1526: assert(bl->args->argv[i].sz);
1.43 kristaps 1527: o = a2offs(bl->args->argv[i].value[0]);
1.34 kristaps 1528: } else if (MDOC_Compact == bl->args->argv[i].arg)
1529: c = 1;
1.38 kristaps 1530:
1531: if (MDOC_HEAD == n->type && MDOC_Column == type) {
1532: nn = n->parent->child;
1533: assert(nn && MDOC_HEAD == nn->type);
1534: for (i = 0; nn && nn != n; nn = nn->next, i++)
1535: /* Counter... */ ;
1536: assert(nn);
1537: if (wp >= 0 && i < (int)bl->args[wp].argv->sz)
1.43 kristaps 1538: w = a2width(bl->args->argv[wp].value[i]);
1.38 kristaps 1539: }
1.34 kristaps 1540:
1.37 kristaps 1541: switch (type) {
1542: case (MDOC_Enum):
1543: /* FALLTHROUGH */
1544: case (MDOC_Dash):
1545: /* FALLTHROUGH */
1546: case (MDOC_Hyphen):
1547: /* FALLTHROUGH */
1548: case (MDOC_Bullet):
1549: if (w < 4)
1550: w = 4;
1551: break;
1552: case (MDOC_Inset):
1553: /* FALLTHROUGH */
1554: case (MDOC_Diag):
1555: w = 1;
1556: break;
1557: default:
1558: if (0 == w)
1559: w = 10;
1560: break;
1561: }
1562:
1.34 kristaps 1563: switch (n->type) {
1564: case (MDOC_BLOCK):
1565: break;
1566: case (MDOC_HEAD):
1567: return(mdoc_tbl_head_pre(m, n, h, type, w));
1568: case (MDOC_BODY):
1569: return(mdoc_tbl_body_pre(m, n, h, type, w));
1570: default:
1571: abort();
1572: /* NOTREACHED */
1573: }
1574:
1.37 kristaps 1575: return(mdoc_tbl_block_pre(m, n, h, type, w, o, c));
1.34 kristaps 1576: }
1577:
1578:
1.41 kristaps 1579: /* ARGSUSED */
1.34 kristaps 1580: static int
1.37 kristaps 1581: mdoc_bl_pre(MDOC_ARGS)
1.34 kristaps 1582: {
1.37 kristaps 1583: struct ord *ord;
1.34 kristaps 1584:
1585: if (MDOC_BLOCK != n->type)
1586: return(1);
1.43 kristaps 1587: if (MDOC_Enum != a2list(n))
1.37 kristaps 1588: return(1);
1.34 kristaps 1589:
1.37 kristaps 1590: ord = malloc(sizeof(struct ord));
1591: if (NULL == ord)
1592: err(EXIT_FAILURE, "malloc");
1593: ord->cookie = n;
1594: ord->pos = 1;
1595: SLIST_INSERT_HEAD(&h->ords, ord, entry);
1.33 kristaps 1596:
1597: return(1);
1598: }
1599:
1600:
1.41 kristaps 1601: /* ARGSUSED */
1.37 kristaps 1602: static void
1603: mdoc_bl_post(MDOC_ARGS)
1.33 kristaps 1604: {
1.37 kristaps 1605: struct ord *ord;
1.33 kristaps 1606:
1.34 kristaps 1607: if (MDOC_BLOCK != n->type)
1.37 kristaps 1608: return;
1.43 kristaps 1609: if (MDOC_Enum != a2list(n))
1.37 kristaps 1610: return;
1.33 kristaps 1611:
1.37 kristaps 1612: ord = SLIST_FIRST(&h->ords);
1613: assert(ord);
1614: SLIST_REMOVE_HEAD(&h->ords, entry);
1615: free(ord);
1.33 kristaps 1616: }
1617:
1618:
1619: static int
1.34 kristaps 1620: mdoc_it_pre(MDOC_ARGS)
1.33 kristaps 1621: {
1.37 kristaps 1622: int type;
1.33 kristaps 1623:
1.34 kristaps 1624: if (MDOC_BLOCK == n->type)
1.43 kristaps 1625: type = a2list(n->parent->parent);
1.34 kristaps 1626: else
1.43 kristaps 1627: type = a2list(n->parent->parent->parent);
1.33 kristaps 1628:
1.37 kristaps 1629: return(mdoc_tbl_pre(m, n, h, type));
1.33 kristaps 1630: }
1.34 kristaps 1631:
1632:
1633: /* ARGSUSED */
1634: static int
1635: mdoc_ex_pre(MDOC_ARGS)
1636: {
1637: const struct mdoc_node *nn;
1638: struct tag *t;
1639: struct htmlpair tag;
1640:
1641: print_text(h, "The");
1642:
1643: tag.key = ATTR_CLASS;
1644: tag.val = "utility";
1645:
1646: for (nn = n->child; nn; nn = nn->next) {
1647: t = print_otag(h, TAG_SPAN, 1, &tag);
1648: print_text(h, nn->string);
1649: print_tagq(h, t);
1650:
1651: h->flags |= HTML_NOSPACE;
1652:
1653: if (nn->next && NULL == nn->next->next)
1654: print_text(h, ", and");
1655: else if (nn->next)
1656: print_text(h, ",");
1657: else
1658: h->flags &= ~HTML_NOSPACE;
1659: }
1660:
1661: if (n->child->next)
1662: print_text(h, "utilities exit");
1663: else
1664: print_text(h, "utility exits");
1665:
1666: print_text(h, "0 on success, and >0 if an error occurs.");
1667: return(0);
1668: }
1669:
1670:
1671: /* ARGSUSED */
1672: static int
1673: mdoc_dq_pre(MDOC_ARGS)
1674: {
1675:
1676: if (MDOC_BODY != n->type)
1677: return(1);
1678: print_text(h, "\\(lq");
1679: h->flags |= HTML_NOSPACE;
1680: return(1);
1681: }
1682:
1683:
1684: /* ARGSUSED */
1685: static void
1686: mdoc_dq_post(MDOC_ARGS)
1687: {
1688:
1689: if (MDOC_BODY != n->type)
1690: return;
1691: h->flags |= HTML_NOSPACE;
1692: print_text(h, "\\(rq");
1693: }
1694:
1695:
1696: /* ARGSUSED */
1697: static int
1698: mdoc_pq_pre(MDOC_ARGS)
1699: {
1700:
1701: if (MDOC_BODY != n->type)
1702: return(1);
1703: print_text(h, "\\&(");
1704: h->flags |= HTML_NOSPACE;
1705: return(1);
1706: }
1707:
1708:
1709: /* ARGSUSED */
1710: static void
1711: mdoc_pq_post(MDOC_ARGS)
1712: {
1713:
1714: if (MDOC_BODY != n->type)
1715: return;
1716: print_text(h, ")");
1717: }
1718:
1719:
1720: /* ARGSUSED */
1721: static int
1722: mdoc_sq_pre(MDOC_ARGS)
1723: {
1724:
1725: if (MDOC_BODY != n->type)
1726: return(1);
1727: print_text(h, "\\(oq");
1728: h->flags |= HTML_NOSPACE;
1729: return(1);
1730: }
1731:
1732:
1733: /* ARGSUSED */
1734: static void
1735: mdoc_sq_post(MDOC_ARGS)
1736: {
1737:
1738: if (MDOC_BODY != n->type)
1739: return;
1740: h->flags |= HTML_NOSPACE;
1741: print_text(h, "\\(aq");
1742: }
1743:
1744:
1745: /* ARGSUSED */
1746: static int
1747: mdoc_em_pre(MDOC_ARGS)
1748: {
1749: struct htmlpair tag;
1750:
1751: tag.key = ATTR_CLASS;
1752: tag.val = "emph";
1753:
1754: print_otag(h, TAG_SPAN, 1, &tag);
1755: return(1);
1756: }
1757:
1758:
1759: /* ARGSUSED */
1760: static int
1761: mdoc_d1_pre(MDOC_ARGS)
1762: {
1.35 kristaps 1763: struct htmlpair tag[2];
1.34 kristaps 1764:
1765: if (MDOC_BLOCK != n->type)
1766: return(1);
1767:
1.35 kristaps 1768: buffmt("margin-left: %dem;", INDENT);
1.34 kristaps 1769:
1.35 kristaps 1770: tag[0].key = ATTR_CLASS;
1771: tag[0].val = "lit-block";
1772: tag[1].key = ATTR_STYLE;
1773: tag[1].val = buf;
1.34 kristaps 1774:
1.35 kristaps 1775: print_otag(h, TAG_DIV, 2, tag);
1.34 kristaps 1776: return(1);
1777: }
1778:
1779:
1780: /* ARGSUSED */
1781: static int
1782: mdoc_sx_pre(MDOC_ARGS)
1783: {
1.41 kristaps 1784: struct htmlpair tag[2];
1785: const struct mdoc_node *nn;
1786:
1787: bufcat("#");
1788: for (nn = n->child; nn; nn = nn->next) {
1789: bufcat(nn->string);
1790: if (nn->next)
1791: bufcat(" ");
1792: }
1.34 kristaps 1793:
1.35 kristaps 1794: tag[0].key = ATTR_HREF;
1.41 kristaps 1795: tag[0].val = buf;
1.35 kristaps 1796: tag[1].key = ATTR_CLASS;
1797: tag[1].val = "link-sec";
1.34 kristaps 1798:
1.35 kristaps 1799: print_otag(h, TAG_A, 2, tag);
1.34 kristaps 1800: return(1);
1801: }
1.37 kristaps 1802:
1803:
1804: /* ARGSUSED */
1805: static int
1806: mdoc_aq_pre(MDOC_ARGS)
1807: {
1808:
1809: if (MDOC_BODY != n->type)
1810: return(1);
1811: print_text(h, "\\(la");
1812: h->flags |= HTML_NOSPACE;
1813: return(1);
1814: }
1815:
1816:
1817: /* ARGSUSED */
1818: static void
1819: mdoc_aq_post(MDOC_ARGS)
1820: {
1821:
1822: if (MDOC_BODY != n->type)
1823: return;
1824: h->flags |= HTML_NOSPACE;
1825: print_text(h, "\\(ra");
1826: }
1827:
1.39 kristaps 1828:
1829: /* ARGSUSED */
1830: static int
1831: mdoc_bd_pre(MDOC_ARGS)
1832: {
1833: struct htmlpair tag[2];
1834: int t, c, o, i;
1835: const struct mdoc_node *bl;
1836:
1837: /* FIXME: fmt_vspace() shit. */
1838:
1839: if (MDOC_BLOCK == n->type)
1840: bl = n;
1841: else if (MDOC_HEAD == n->type)
1842: return(0);
1843: else
1844: bl = n->parent;
1845:
1846: t = o = c = 0;
1847:
1848: for (i = 0; i < (int)bl->args->argc; i++)
1849: switch (bl->args->argv[i].arg) {
1850: case (MDOC_Offset):
1851: assert(bl->args->argv[i].sz);
1.43 kristaps 1852: o = a2offs (bl->args->argv[i].value[0]);
1.39 kristaps 1853: break;
1854: case (MDOC_Compact):
1855: c = 1;
1856: break;
1857: case (MDOC_Ragged):
1858: /* FALLTHROUGH */
1859: case (MDOC_Filled):
1860: /* FALLTHROUGH */
1861: case (MDOC_Unfilled):
1862: /* FALLTHROUGH */
1863: case (MDOC_Literal):
1864: t = bl->args->argv[i].arg;
1865: break;
1866: }
1867:
1868: if (MDOC_BLOCK == n->type) {
1869: if (o)
1870: buffmt("margin-left: %dem;", o);
1871: bufcat("margin-top: 1em;");
1872: tag[0].key = ATTR_STYLE;
1873: tag[0].val = buf;
1874: print_otag(h, TAG_DIV, 1, tag);
1875: return(1);
1876: }
1877:
1878: switch (t) {
1879: case (MDOC_Unfilled):
1880: case (MDOC_Literal):
1881: break;
1882: default:
1883: return(1);
1884: }
1885:
1886: bufcat("white-space: pre;");
1887: tag[0].key = ATTR_STYLE;
1888: tag[0].val = buf;
1889: tag[1].key = ATTR_CLASS;
1890: tag[1].val = "lit-block";
1891:
1892: print_otag(h, TAG_DIV, 2, tag);
1893:
1894: for (n = n->child; n; n = n->next) {
1895: h->flags |= HTML_NOSPACE;
1896: print_mdoc_node(m, n, h);
1897: if (n->next)
1898: print_text(h, "\n");
1899: }
1900:
1901: return(0);
1902: }
1903:
1904:
1905: /* ARGSUSED */
1906: static int
1907: mdoc_pa_pre(MDOC_ARGS)
1908: {
1909: struct htmlpair tag;
1910:
1911: tag.key = ATTR_CLASS;
1912: tag.val = "file";
1913:
1914: print_otag(h, TAG_SPAN, 1, &tag);
1915: return(1);
1916: }
1917:
1918:
1919: /* ARGSUSED */
1920: static int
1921: mdoc_qq_pre(MDOC_ARGS)
1922: {
1923:
1924: if (MDOC_BODY != n->type)
1925: return(1);
1926: print_text(h, "\\*q");
1927: h->flags |= HTML_NOSPACE;
1928: return(1);
1929: }
1930:
1931:
1932: /* ARGSUSED */
1933: static void
1934: mdoc_qq_post(MDOC_ARGS)
1935: {
1936:
1937: if (MDOC_BODY != n->type)
1938: return;
1939: h->flags |= HTML_NOSPACE;
1940: print_text(h, "\\*q");
1941: }
1.41 kristaps 1942:
1943:
1944: /* ARGSUSED */
1945: static int
1946: mdoc_ad_pre(MDOC_ARGS)
1947: {
1948: struct htmlpair tag;
1949:
1950: tag.key = ATTR_CLASS;
1951: tag.val = "addr";
1952: print_otag(h, TAG_SPAN, 1, &tag);
1953: return(1);
1954: }
1955:
1956:
1957: /* ARGSUSED */
1958: static int
1959: mdoc_an_pre(MDOC_ARGS)
1960: {
1961: struct htmlpair tag;
1962:
1963: tag.key = ATTR_CLASS;
1964: tag.val = "author";
1965: print_otag(h, TAG_SPAN, 1, &tag);
1966: return(1);
1967: }
1968:
1969:
1970: /* ARGSUSED */
1971: static int
1972: mdoc_cd_pre(MDOC_ARGS)
1973: {
1974: struct htmlpair tag;
1975:
1976: tag.key = ATTR_CLASS;
1977: tag.val = "config";
1978: print_otag(h, TAG_SPAN, 1, &tag);
1979: return(1);
1980: }
1981:
1982:
1983: /* ARGSUSED */
1984: static int
1985: mdoc_dv_pre(MDOC_ARGS)
1986: {
1987: struct htmlpair tag;
1988:
1989: tag.key = ATTR_CLASS;
1990: tag.val = "define";
1991: print_otag(h, TAG_SPAN, 1, &tag);
1992: return(1);
1993: }
1994:
1995:
1996: /* ARGSUSED */
1997: static int
1998: mdoc_ev_pre(MDOC_ARGS)
1999: {
2000: struct htmlpair tag;
2001:
2002: tag.key = ATTR_CLASS;
2003: tag.val = "env";
2004: print_otag(h, TAG_SPAN, 1, &tag);
2005: return(1);
2006: }
2007:
2008:
2009: /* ARGSUSED */
2010: static int
2011: mdoc_er_pre(MDOC_ARGS)
2012: {
2013: struct htmlpair tag;
2014:
2015: tag.key = ATTR_CLASS;
2016: tag.val = "errno";
2017: print_otag(h, TAG_SPAN, 1, &tag);
2018: return(1);
2019: }
2020:
2021:
2022: /* ARGSUSED */
2023: static int
2024: mdoc_fa_pre(MDOC_ARGS)
2025: {
2026: const struct mdoc_node *nn;
2027: struct htmlpair tag;
2028: struct tag *t;
2029:
2030: tag.key = ATTR_CLASS;
2031: tag.val = "farg";
2032:
2033: if (n->parent->tok != MDOC_Fo) {
2034: print_otag(h, TAG_SPAN, 1, &tag);
2035: return(1);
2036: }
2037:
2038: for (nn = n->child; nn; nn = nn->next) {
2039: t = print_otag(h, TAG_SPAN, 1, &tag);
2040: print_text(h, nn->string);
2041: print_tagq(h, t);
2042: if (nn->next)
2043: print_text(h, ",");
2044: }
2045:
2046: if (n->child && n->next && n->next->tok == MDOC_Fa)
2047: print_text(h, ",");
2048:
2049: return(0);
2050: }
2051:
2052:
2053: /* ARGSUSED */
2054: static int
2055: mdoc_fd_pre(MDOC_ARGS)
2056: {
2057: struct htmlpair tag;
2058:
2059: if (SEC_SYNOPSIS == n->sec) {
2060: if (n->next && MDOC_Fd != n->next->tok) {
2061: tag.key = ATTR_STYLE;
2062: tag.val = "margin-bottom: 1em;";
2063: print_otag(h, TAG_DIV, 1, &tag);
2064: } else
2065: print_otag(h, TAG_DIV, 0, NULL);
2066: }
2067:
2068: tag.key = ATTR_CLASS;
2069: tag.val = "macro";
2070: print_otag(h, TAG_SPAN, 1, &tag);
2071: return(1);
2072: }
2073:
2074:
2075: /* ARGSUSED */
2076: static int
2077: mdoc_vt_pre(MDOC_ARGS)
2078: {
2079: struct htmlpair tag;
2080:
2081: if (SEC_SYNOPSIS == n->sec) {
2082: if (n->next && MDOC_Vt != n->next->tok) {
2083: tag.key = ATTR_STYLE;
2084: tag.val = "margin-bottom: 1em;";
2085: print_otag(h, TAG_DIV, 1, &tag);
2086: } else
2087: print_otag(h, TAG_DIV, 0, NULL);
2088: }
2089:
2090: tag.key = ATTR_CLASS;
2091: tag.val = "type";
2092: print_otag(h, TAG_SPAN, 1, &tag);
2093: return(1);
2094: }
2095:
2096: /* ARGSUSED */
2097: static int
2098: mdoc_ft_pre(MDOC_ARGS)
2099: {
2100: struct htmlpair tag;
2101:
2102: if (SEC_SYNOPSIS == n->sec) {
2103: if (n->prev && MDOC_Fo == n->prev->tok) {
2104: tag.key = ATTR_STYLE;
2105: tag.val = "magin-bottom: 1em;";
2106: print_otag(h, TAG_DIV, 1, &tag);
2107: } else
2108: print_otag(h, TAG_DIV, 0, NULL);
2109: }
2110:
2111: tag.key = ATTR_CLASS;
2112: tag.val = "type";
2113: print_otag(h, TAG_SPAN, 1, &tag);
2114: return(1);
2115: }
2116:
2117:
2118: /* ARGSUSED */
2119: static int
2120: mdoc_fn_pre(MDOC_ARGS)
2121: {
2122: struct tag *t;
2123: struct htmlpair tag;
2124: const struct mdoc_node *nn;
2125:
2126: if (SEC_SYNOPSIS == n->sec) {
2127: if (n->next) {
2128: tag.key = ATTR_STYLE;
2129: tag.val = "margin-bottom: 1em";
2130: print_otag(h, TAG_DIV, 1, &tag);
2131: } else
2132: print_otag(h, TAG_DIV, 0, NULL);
2133: }
2134:
2135: tag.key = ATTR_CLASS;
2136: tag.val = "type";
2137:
2138: t = print_otag(h, TAG_SPAN, 1, &tag);
2139: print_text(h, n->child->string);
2140: print_tagq(h, t);
2141:
2142: h->flags |= HTML_NOSPACE;
2143: print_text(h, "(");
2144:
2145: for (nn = n->child->next; nn; nn = nn->next) {
2146: tag.key = ATTR_CLASS;
2147: tag.val = "farg";
2148: t = print_otag(h, TAG_SPAN, 1, &tag);
2149: print_text(h, nn->string);
2150: print_tagq(h, t);
2151: if (nn->next)
2152: print_text(h, ",");
2153: }
2154:
2155: print_text(h, ")");
2156:
2157: if (SEC_SYNOPSIS == n->sec)
2158: print_text(h, ";");
2159:
2160: return(0);
2161: }
1.48 kristaps 2162:
2163:
2164: /* ARGSUSED */
2165: static int
2166: mdoc_sp_pre(MDOC_ARGS)
2167: {
2168: int len;
2169: struct htmlpair tag;
2170:
1.49 ! kristaps 2171: switch (n->tok) {
! 2172: case (MDOC_sp):
1.48 kristaps 2173: len = n->child ? atoi(n->child->string) : 1;
1.49 ! kristaps 2174: break;
! 2175: case (MDOC_br):
! 2176: len = 0;
! 2177: break;
! 2178: default:
1.48 kristaps 2179: len = 1;
1.49 ! kristaps 2180: break;
! 2181: }
1.48 kristaps 2182:
2183: buffmt("height: %dem", len);
2184: tag.key = ATTR_STYLE;
2185: tag.val = buf;
2186: print_otag(h, TAG_DIV, 1, &tag);
2187: return(1);
2188:
2189: }
CVSweb