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