Annotation of mandoc/man_html.c, Revision 1.163
1.163 ! schwarze 1: /* $Id: man_html.c,v 1.162 2018/12/31 07:08:12 schwarze Exp $ */
1.1 kristaps 2: /*
1.104 kristaps 3: * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
1.163 ! schwarze 4: * Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
1.1 kristaps 5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
1.113 schwarze 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
1.1 kristaps 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1.113 schwarze 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
1.1 kristaps 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
1.25 kristaps 18: #include "config.h"
19:
1.1 kristaps 20: #include <sys/types.h>
21:
1.5 kristaps 22: #include <assert.h>
23: #include <ctype.h>
1.2 kristaps 24: #include <stdio.h>
1.1 kristaps 25: #include <stdlib.h>
1.4 kristaps 26: #include <string.h>
1.1 kristaps 27:
1.94 schwarze 28: #include "mandoc_aux.h"
1.160 schwarze 29: #include "mandoc.h"
1.113 schwarze 30: #include "roff.h"
1.105 schwarze 31: #include "man.h"
1.7 kristaps 32: #include "out.h"
1.1 kristaps 33: #include "html.h"
1.10 kristaps 34: #include "main.h"
1.1 kristaps 35:
1.13 kristaps 36: /* FIXME: have PD set the default vspace width. */
1.4 kristaps 37:
1.115 schwarze 38: #define MAN_ARGS const struct roff_meta *man, \
1.114 schwarze 39: const struct roff_node *n, \
1.3 kristaps 40: struct html *h
41:
1.155 schwarze 42: struct man_html_act {
1.3 kristaps 43: int (*pre)(MAN_ARGS);
44: int (*post)(MAN_ARGS);
45: };
46:
1.93 schwarze 47: static void print_bvspace(struct html *,
1.114 schwarze 48: const struct roff_node *);
1.147 schwarze 49: static void print_man_head(const struct roff_meta *,
50: struct html *);
1.4 kristaps 51: static void print_man_nodelist(MAN_ARGS);
52: static void print_man_node(MAN_ARGS);
1.8 kristaps 53: static int man_B_pre(MAN_ARGS);
1.6 kristaps 54: static int man_HP_pre(MAN_ARGS);
1.86 kristaps 55: static int man_IP_pre(MAN_ARGS);
1.8 kristaps 56: static int man_I_pre(MAN_ARGS);
1.86 kristaps 57: static int man_OP_pre(MAN_ARGS);
1.4 kristaps 58: static int man_PP_pre(MAN_ARGS);
1.9 kristaps 59: static int man_RS_pre(MAN_ARGS);
1.4 kristaps 60: static int man_SH_pre(MAN_ARGS);
1.8 kristaps 61: static int man_SM_pre(MAN_ARGS);
1.4 kristaps 62: static int man_SS_pre(MAN_ARGS);
1.156 schwarze 63: static int man_SY_pre(MAN_ARGS);
1.90 schwarze 64: static int man_UR_pre(MAN_ARGS);
1.158 schwarze 65: static int man_abort_pre(MAN_ARGS);
1.86 kristaps 66: static int man_alt_pre(MAN_ARGS);
67: static int man_ign_pre(MAN_ARGS);
68: static int man_in_pre(MAN_ARGS);
1.147 schwarze 69: static void man_root_post(const struct roff_meta *,
70: struct html *);
71: static void man_root_pre(const struct roff_meta *,
72: struct html *);
1.4 kristaps 73:
1.155 schwarze 74: static const struct man_html_act man_html_acts[MAN_MAX - MAN_TH] = {
1.3 kristaps 75: { NULL, NULL }, /* TH */
1.4 kristaps 76: { man_SH_pre, NULL }, /* SH */
77: { man_SS_pre, NULL }, /* SS */
1.6 kristaps 78: { man_IP_pre, NULL }, /* TP */
1.154 schwarze 79: { man_IP_pre, NULL }, /* TQ */
1.158 schwarze 80: { man_abort_pre, NULL }, /* LP */
1.4 kristaps 81: { man_PP_pre, NULL }, /* PP */
1.158 schwarze 82: { man_abort_pre, NULL }, /* P */
1.5 kristaps 83: { man_IP_pre, NULL }, /* IP */
1.93 schwarze 84: { man_HP_pre, NULL }, /* HP */
1.8 kristaps 85: { man_SM_pre, NULL }, /* SM */
1.56 kristaps 86: { man_SM_pre, NULL }, /* SB */
1.8 kristaps 87: { man_alt_pre, NULL }, /* BI */
88: { man_alt_pre, NULL }, /* IB */
89: { man_alt_pre, NULL }, /* BR */
90: { man_alt_pre, NULL }, /* RB */
1.3 kristaps 91: { NULL, NULL }, /* R */
1.8 kristaps 92: { man_B_pre, NULL }, /* B */
93: { man_I_pre, NULL }, /* I */
94: { man_alt_pre, NULL }, /* IR */
95: { man_alt_pre, NULL }, /* RI */
1.3 kristaps 96: { NULL, NULL }, /* RE */
1.9 kristaps 97: { man_RS_pre, NULL }, /* RS */
1.8 kristaps 98: { man_ign_pre, NULL }, /* DT */
99: { man_ign_pre, NULL }, /* UC */
1.13 kristaps 100: { man_ign_pre, NULL }, /* PD */
1.34 joerg 101: { man_ign_pre, NULL }, /* AT */
1.45 kristaps 102: { man_in_pre, NULL }, /* in */
1.156 schwarze 103: { man_SY_pre, NULL }, /* SY */
104: { NULL, NULL }, /* YS */
1.86 kristaps 105: { man_OP_pre, NULL }, /* OP */
1.132 schwarze 106: { NULL, NULL }, /* EX */
107: { NULL, NULL }, /* EE */
1.90 schwarze 108: { man_UR_pre, NULL }, /* UR */
109: { NULL, NULL }, /* UE */
1.145 schwarze 110: { man_UR_pre, NULL }, /* MT */
111: { NULL, NULL }, /* ME */
1.3 kristaps 112: };
113:
1.93 schwarze 114:
1.74 kristaps 115: /*
116: * Printing leading vertical space before a block.
117: * This is used for the paragraph macros.
118: * The rules are pretty simple, since there's very little nesting going
119: * on here. Basically, if we're the first within another block (SS/SH),
120: * then don't emit vertical space. If we are (RS), then do. If not the
121: * first, print it.
122: */
123: static void
1.114 schwarze 124: print_bvspace(struct html *h, const struct roff_node *n)
1.74 kristaps 125: {
126:
127: if (n->body && n->body->child)
1.113 schwarze 128: if (n->body->child->type == ROFFT_TBL)
1.74 kristaps 129: return;
130:
1.113 schwarze 131: if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS)
1.74 kristaps 132: if (NULL == n->prev)
133: return;
134:
1.103 kristaps 135: print_paragraph(h);
1.74 kristaps 136: }
1.1 kristaps 137:
138: void
1.161 schwarze 139: html_man(void *arg, const struct roff_meta *man)
1.1 kristaps 140: {
1.147 schwarze 141: struct html *h;
142: struct roff_node *n;
143: struct tag *t;
1.82 kristaps 144:
1.117 schwarze 145: h = (struct html *)arg;
1.147 schwarze 146: n = man->first->child;
1.3 kristaps 147:
1.126 schwarze 148: if ((h->oflags & HTML_FRAGMENT) == 0) {
1.82 kristaps 149: print_gen_decls(h);
1.126 schwarze 150: print_otag(h, TAG_HTML, "");
1.147 schwarze 151: if (n->type == ROFFT_COMMENT)
152: print_gen_comment(h, n);
1.126 schwarze 153: t = print_otag(h, TAG_HEAD, "");
1.161 schwarze 154: print_man_head(man, h);
1.126 schwarze 155: print_tagq(h, t);
1.122 schwarze 156: print_otag(h, TAG_BODY, "");
1.126 schwarze 157: }
1.53 kristaps 158:
1.161 schwarze 159: man_root_pre(man, h);
1.127 schwarze 160: t = print_otag(h, TAG_DIV, "c", "manual-text");
1.161 schwarze 161: print_man_nodelist(man, n, h);
1.127 schwarze 162: print_tagq(h, t);
1.161 schwarze 163: man_root_post(man, h);
1.126 schwarze 164: print_tagq(h, NULL);
1.3 kristaps 165: }
166:
167: static void
1.147 schwarze 168: print_man_head(const struct roff_meta *man, struct html *h)
1.3 kristaps 169: {
1.123 schwarze 170: char *cp;
1.3 kristaps 171:
172: print_gen_head(h);
1.123 schwarze 173: mandoc_asprintf(&cp, "%s(%s)", man->title, man->msec);
1.122 schwarze 174: print_otag(h, TAG_TITLE, "");
1.123 schwarze 175: print_text(h, cp);
176: free(cp);
1.1 kristaps 177: }
1.4 kristaps 178:
179: static void
180: print_man_nodelist(MAN_ARGS)
181: {
182:
1.110 schwarze 183: while (n != NULL) {
1.132 schwarze 184: print_man_node(man, n, h);
1.110 schwarze 185: n = n->next;
186: }
1.4 kristaps 187: }
188:
189: static void
190: print_man_node(MAN_ARGS)
191: {
1.132 schwarze 192: struct tag *t;
1.4 kristaps 193: int child;
194:
1.163 ! schwarze 195: html_fillmode(h, n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi);
1.132 schwarze 196:
197: child = 1;
198: switch (n->type) {
199: case ROFFT_TEXT:
1.163 ! schwarze 200: if (*n->string == '\0') {
! 201: print_endline(h);
! 202: return;
! 203: }
1.132 schwarze 204: t = h->tag;
1.163 ! schwarze 205: if (*n->string == ' ' && n->flags & NODE_LINE &&
! 206: (h->flags & HTML_NONEWLINE) == 0)
! 207: print_endline(h);
! 208: else if (n->flags & NODE_DELIMC)
! 209: h->flags |= HTML_NOSPACE;
1.4 kristaps 210: print_text(h, n->string);
1.130 schwarze 211: break;
1.163 ! schwarze 212: case ROFFT_COMMENT:
! 213: return;
1.113 schwarze 214: case ROFFT_EQN:
1.132 schwarze 215: t = h->tag;
1.80 kristaps 216: print_eqn(h, n->eqn);
1.69 kristaps 217: break;
1.113 schwarze 218: case ROFFT_TBL:
1.66 kristaps 219: /*
220: * This will take care of initialising all of the table
221: * state data for the first table, then tearing it down
222: * for the last one.
223: */
1.60 kristaps 224: print_tbl(h, n->span);
1.64 kristaps 225: return;
1.4 kristaps 226: default:
1.93 schwarze 227: /*
1.21 kristaps 228: * Close out scope of font prior to opening a macro
1.66 kristaps 229: * scope.
1.21 kristaps 230: */
1.57 kristaps 231: if (HTMLFONT_NONE != h->metac) {
232: h->metal = h->metac;
233: h->metac = HTMLFONT_NONE;
1.66 kristaps 234: }
235:
236: /*
237: * Close out the current table, if it's open, and unset
238: * the "meta" table state. This will be reopened on the
239: * next table element.
240: */
1.132 schwarze 241: if (h->tblt)
1.66 kristaps 242: print_tblclose(h);
1.132 schwarze 243:
244: t = h->tag;
1.137 schwarze 245: if (n->tok < ROFF_MAX) {
1.138 schwarze 246: roff_html_pre(h, n);
1.163 ! schwarze 247: print_stagq(h, t);
! 248: return;
1.137 schwarze 249: }
250:
251: assert(n->tok >= MAN_TH && n->tok < MAN_MAX);
1.155 schwarze 252: if (man_html_acts[n->tok - MAN_TH].pre != NULL)
253: child = (*man_html_acts[n->tok - MAN_TH].pre)(man,
254: n, h);
1.4 kristaps 255: break;
256: }
257:
1.21 kristaps 258: if (child && n->child)
1.132 schwarze 259: print_man_nodelist(man, n->child, h);
1.21 kristaps 260:
1.24 kristaps 261: /* This will automatically close out any font scope. */
1.132 schwarze 262: print_stagq(h, t);
263:
1.163 ! schwarze 264: if (n->flags & NODE_NOFILL &&
! 265: (n->next == NULL || n->next->flags & NODE_LINE)) {
1.157 schwarze 266: /* In .nf = <pre>, print even empty lines. */
267: h->col++;
1.132 schwarze 268: print_endline(h);
1.157 schwarze 269: }
1.4 kristaps 270: }
271:
1.65 kristaps 272: static void
1.147 schwarze 273: man_root_pre(const struct roff_meta *man, struct html *h)
1.4 kristaps 274: {
275: struct tag *t, *tt;
1.94 schwarze 276: char *title;
1.4 kristaps 277:
1.89 schwarze 278: assert(man->title);
279: assert(man->msec);
1.94 schwarze 280: mandoc_asprintf(&title, "%s(%s)", man->title, man->msec);
1.4 kristaps 281:
1.122 schwarze 282: t = print_otag(h, TAG_TABLE, "c", "head");
283: tt = print_otag(h, TAG_TR, "");
1.4 kristaps 284:
1.122 schwarze 285: print_otag(h, TAG_TD, "c", "head-ltitle");
1.4 kristaps 286: print_text(h, title);
287: print_stagq(h, tt);
288:
1.122 schwarze 289: print_otag(h, TAG_TD, "c", "head-vol");
1.95 schwarze 290: if (NULL != man->vol)
291: print_text(h, man->vol);
1.4 kristaps 292: print_stagq(h, tt);
293:
1.122 schwarze 294: print_otag(h, TAG_TD, "c", "head-rtitle");
1.4 kristaps 295: print_text(h, title);
296: print_tagq(h, t);
1.94 schwarze 297: free(title);
1.4 kristaps 298: }
299:
300: static void
1.147 schwarze 301: man_root_post(const struct roff_meta *man, struct html *h)
1.4 kristaps 302: {
303: struct tag *t, *tt;
304:
1.122 schwarze 305: t = print_otag(h, TAG_TABLE, "c", "foot");
306: tt = print_otag(h, TAG_TR, "");
1.55 kristaps 307:
1.122 schwarze 308: print_otag(h, TAG_TD, "c", "foot-date");
1.89 schwarze 309: print_text(h, man->date);
1.4 kristaps 310: print_stagq(h, tt);
311:
1.122 schwarze 312: print_otag(h, TAG_TD, "c", "foot-os");
1.115 schwarze 313: if (man->os)
314: print_text(h, man->os);
1.4 kristaps 315: print_tagq(h, t);
316: }
317:
318: static int
319: man_SH_pre(MAN_ARGS)
320: {
1.134 schwarze 321: char *id;
322:
323: if (n->type == ROFFT_HEAD) {
1.150 schwarze 324: id = html_make_id(n, 1);
1.134 schwarze 325: print_otag(h, TAG_H1, "cTi", "Sh", id);
1.135 schwarze 326: if (id != NULL)
1.148 schwarze 327: print_otag(h, TAG_A, "chR", "permalink", id);
1.134 schwarze 328: }
1.119 schwarze 329: return 1;
1.4 kristaps 330: }
331:
332: static int
1.8 kristaps 333: man_alt_pre(MAN_ARGS)
334: {
1.114 schwarze 335: const struct roff_node *nn;
1.130 schwarze 336: int i;
1.57 kristaps 337: enum htmltag fp;
338: struct tag *t;
1.8 kristaps 339:
340: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
341: switch (n->tok) {
1.93 schwarze 342: case MAN_BI:
1.57 kristaps 343: fp = i % 2 ? TAG_I : TAG_B;
1.8 kristaps 344: break;
1.93 schwarze 345: case MAN_IB:
1.57 kristaps 346: fp = i % 2 ? TAG_B : TAG_I;
1.8 kristaps 347: break;
1.93 schwarze 348: case MAN_RI:
1.57 kristaps 349: fp = i % 2 ? TAG_I : TAG_MAX;
1.8 kristaps 350: break;
1.93 schwarze 351: case MAN_IR:
1.57 kristaps 352: fp = i % 2 ? TAG_MAX : TAG_I;
1.8 kristaps 353: break;
1.93 schwarze 354: case MAN_BR:
1.57 kristaps 355: fp = i % 2 ? TAG_MAX : TAG_B;
1.8 kristaps 356: break;
1.93 schwarze 357: case MAN_RB:
1.57 kristaps 358: fp = i % 2 ? TAG_B : TAG_MAX;
1.8 kristaps 359: break;
360: default:
361: abort();
362: }
363:
364: if (i)
365: h->flags |= HTML_NOSPACE;
366:
1.130 schwarze 367: if (fp != TAG_MAX)
1.122 schwarze 368: t = print_otag(h, fp, "");
1.57 kristaps 369:
1.130 schwarze 370: print_text(h, nn->string);
1.57 kristaps 371:
1.130 schwarze 372: if (fp != TAG_MAX)
1.57 kristaps 373: print_tagq(h, t);
1.8 kristaps 374: }
1.119 schwarze 375: return 0;
1.8 kristaps 376: }
377:
378: static int
1.56 kristaps 379: man_SM_pre(MAN_ARGS)
1.8 kristaps 380: {
1.122 schwarze 381: print_otag(h, TAG_SMALL, "");
1.56 kristaps 382: if (MAN_SB == n->tok)
1.122 schwarze 383: print_otag(h, TAG_B, "");
1.119 schwarze 384: return 1;
1.8 kristaps 385: }
386:
387: static int
1.4 kristaps 388: man_SS_pre(MAN_ARGS)
389: {
1.134 schwarze 390: char *id;
391:
392: if (n->type == ROFFT_HEAD) {
1.150 schwarze 393: id = html_make_id(n, 1);
1.134 schwarze 394: print_otag(h, TAG_H2, "cTi", "Ss", id);
1.135 schwarze 395: if (id != NULL)
1.148 schwarze 396: print_otag(h, TAG_A, "chR", "permalink", id);
1.134 schwarze 397: }
1.119 schwarze 398: return 1;
1.4 kristaps 399: }
400:
401: static int
402: man_PP_pre(MAN_ARGS)
403: {
404:
1.113 schwarze 405: if (n->type == ROFFT_HEAD)
1.119 schwarze 406: return 0;
1.113 schwarze 407: else if (n->type == ROFFT_BLOCK)
1.74 kristaps 408: print_bvspace(h, n);
1.47 kristaps 409:
1.119 schwarze 410: return 1;
1.5 kristaps 411: }
412:
413: static int
414: man_IP_pre(MAN_ARGS)
415: {
1.114 schwarze 416: const struct roff_node *nn;
1.5 kristaps 417:
1.113 schwarze 418: if (n->type == ROFFT_BODY) {
1.149 schwarze 419: print_otag(h, TAG_DD, "");
1.119 schwarze 420: return 1;
1.113 schwarze 421: } else if (n->type != ROFFT_HEAD) {
1.129 schwarze 422: print_otag(h, TAG_DL, "c", "Bl-tag");
1.119 schwarze 423: return 1;
1.6 kristaps 424: }
425:
1.149 schwarze 426: print_otag(h, TAG_DT, "");
1.6 kristaps 427:
1.154 schwarze 428: switch(n->tok) {
429: case MAN_IP: /* Only print the first header element. */
430: if (n->child != NULL)
431: print_man_node(man, n->child, h);
432: break;
433: case MAN_TP: /* Only print next-line header elements. */
434: case MAN_TQ:
1.91 schwarze 435: nn = n->child;
1.154 schwarze 436: while (nn != NULL && (NODE_LINE & nn->flags) == 0)
1.91 schwarze 437: nn = nn->next;
1.154 schwarze 438: while (nn != NULL) {
1.132 schwarze 439: print_man_node(man, nn, h);
1.91 schwarze 440: nn = nn->next;
441: }
1.154 schwarze 442: break;
443: default:
444: abort();
1.91 schwarze 445: }
1.6 kristaps 446:
1.119 schwarze 447: return 0;
1.6 kristaps 448: }
449:
450: static int
451: man_HP_pre(MAN_ARGS)
452: {
1.113 schwarze 453: if (n->type == ROFFT_HEAD)
1.119 schwarze 454: return 0;
1.72 kristaps 455:
1.151 schwarze 456: if (n->type == ROFFT_BLOCK) {
457: print_bvspace(h, n);
458: print_otag(h, TAG_DIV, "c", "HP");
459: }
1.119 schwarze 460: return 1;
1.4 kristaps 461: }
1.86 kristaps 462:
463: static int
464: man_OP_pre(MAN_ARGS)
465: {
466: struct tag *tt;
467:
468: print_text(h, "[");
469: h->flags |= HTML_NOSPACE;
1.128 schwarze 470: tt = print_otag(h, TAG_SPAN, "c", "Op");
1.86 kristaps 471:
472: if (NULL != (n = n->child)) {
1.122 schwarze 473: print_otag(h, TAG_B, "");
1.86 kristaps 474: print_text(h, n->string);
475: }
476:
477: print_stagq(h, tt);
478:
479: if (NULL != n && NULL != n->next) {
1.122 schwarze 480: print_otag(h, TAG_I, "");
1.86 kristaps 481: print_text(h, n->next->string);
482: }
483:
484: print_stagq(h, tt);
485: h->flags |= HTML_NOSPACE;
486: print_text(h, "]");
1.119 schwarze 487: return 0;
1.86 kristaps 488: }
489:
1.8 kristaps 490: static int
491: man_B_pre(MAN_ARGS)
492: {
1.122 schwarze 493: print_otag(h, TAG_B, "");
1.119 schwarze 494: return 1;
1.8 kristaps 495: }
496:
497: static int
498: man_I_pre(MAN_ARGS)
499: {
1.122 schwarze 500: print_otag(h, TAG_I, "");
1.119 schwarze 501: return 1;
1.45 kristaps 502: }
503:
504: static int
505: man_in_pre(MAN_ARGS)
506: {
1.122 schwarze 507: print_otag(h, TAG_BR, "");
1.119 schwarze 508: return 0;
1.8 kristaps 509: }
510:
511: static int
512: man_ign_pre(MAN_ARGS)
513: {
514:
1.119 schwarze 515: return 0;
1.8 kristaps 516: }
1.9 kristaps 517:
518: static int
519: man_RS_pre(MAN_ARGS)
520: {
1.113 schwarze 521: if (n->type == ROFFT_HEAD)
1.119 schwarze 522: return 0;
1.152 schwarze 523: if (n->type == ROFFT_BLOCK)
524: print_otag(h, TAG_DIV, "c", "Bd-indent");
1.156 schwarze 525: return 1;
526: }
527:
528: static int
529: man_SY_pre(MAN_ARGS)
530: {
531: switch (n->type) {
532: case ROFFT_BLOCK:
533: print_otag(h, TAG_TABLE, "c", "Nm");
534: print_otag(h, TAG_TR, "");
535: break;
536: case ROFFT_HEAD:
537: print_otag(h, TAG_TD, "");
538: print_otag(h, TAG_CODE, "cT", "Nm");
539: break;
540: case ROFFT_BODY:
541: print_otag(h, TAG_TD, "");
542: break;
543: default:
544: abort();
545: }
1.119 schwarze 546: return 1;
1.90 schwarze 547: }
548:
549: static int
550: man_UR_pre(MAN_ARGS)
551: {
1.145 schwarze 552: char *cp;
1.90 schwarze 553: n = n->child;
1.113 schwarze 554: assert(n->type == ROFFT_HEAD);
1.120 schwarze 555: if (n->child != NULL) {
1.113 schwarze 556: assert(n->child->type == ROFFT_TEXT);
1.145 schwarze 557: if (n->tok == MAN_MT) {
558: mandoc_asprintf(&cp, "mailto:%s", n->child->string);
559: print_otag(h, TAG_A, "cTh", "Mt", cp);
560: free(cp);
561: } else
562: print_otag(h, TAG_A, "cTh", "Lk", n->child->string);
1.90 schwarze 563: }
564:
1.113 schwarze 565: assert(n->next->type == ROFFT_BODY);
1.120 schwarze 566: if (n->next->child != NULL)
1.90 schwarze 567: n = n->next;
568:
1.132 schwarze 569: print_man_nodelist(man, n->child, h);
1.90 schwarze 570:
1.119 schwarze 571: return 0;
1.158 schwarze 572: }
573:
574: static int
575: man_abort_pre(MAN_ARGS)
576: {
577: abort();
1.9 kristaps 578: }
CVSweb