Annotation of mandoc/mdoc_man.c, Revision 1.36
1.36 ! schwarze 1: /* $Id: mdoc_man.c,v 1.35 2012/07/12 08:55:48 schwarze Exp $ */
1.1 schwarze 2: /*
1.11 schwarze 3: * Copyright (c) 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
1.1 schwarze 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: */
1.7 kristaps 17: #ifdef HAVE_CONFIG_H
18: #include "config.h"
19: #endif
20:
1.12 schwarze 21: #include <assert.h>
1.1 schwarze 22: #include <stdio.h>
23: #include <string.h>
24:
25: #include "mandoc.h"
1.11 schwarze 26: #include "out.h"
1.4 kristaps 27: #include "man.h"
1.1 schwarze 28: #include "mdoc.h"
29: #include "main.h"
30:
1.5 kristaps 31: #define DECL_ARGS const struct mdoc_meta *m, \
1.20 schwarze 32: const struct mdoc_node *n
1.1 schwarze 33:
34: struct manact {
1.5 kristaps 35: int (*cond)(DECL_ARGS); /* DON'T run actions */
36: int (*pre)(DECL_ARGS); /* pre-node action */
37: void (*post)(DECL_ARGS); /* post-node action */
38: const char *prefix; /* pre-node string constant */
39: const char *suffix; /* post-node string constant */
1.1 schwarze 40: };
41:
1.5 kristaps 42: static int cond_body(DECL_ARGS);
1.1 schwarze 43: static int cond_head(DECL_ARGS);
1.26 schwarze 44: static void font_push(char);
45: static void font_pop(void);
1.34 schwarze 46: static void post__t(DECL_ARGS);
1.5 kristaps 47: static void post_bd(DECL_ARGS);
1.27 schwarze 48: static void post_bf(DECL_ARGS);
1.13 schwarze 49: static void post_bk(DECL_ARGS);
1.30 schwarze 50: static void post_bl(DECL_ARGS);
1.5 kristaps 51: static void post_dl(DECL_ARGS);
1.1 schwarze 52: static void post_enc(DECL_ARGS);
1.28 schwarze 53: static void post_eo(DECL_ARGS);
1.17 schwarze 54: static void post_fa(DECL_ARGS);
1.29 schwarze 55: static void post_fd(DECL_ARGS);
1.26 schwarze 56: static void post_fl(DECL_ARGS);
1.16 schwarze 57: static void post_fn(DECL_ARGS);
1.17 schwarze 58: static void post_fo(DECL_ARGS);
1.26 schwarze 59: static void post_font(DECL_ARGS);
1.15 schwarze 60: static void post_in(DECL_ARGS);
1.30 schwarze 61: static void post_it(DECL_ARGS);
1.14 schwarze 62: static void post_lb(DECL_ARGS);
1.5 kristaps 63: static void post_nm(DECL_ARGS);
1.1 schwarze 64: static void post_percent(DECL_ARGS);
1.5 kristaps 65: static void post_pf(DECL_ARGS);
1.3 schwarze 66: static void post_sect(DECL_ARGS);
1.5 kristaps 67: static void post_sp(DECL_ARGS);
1.18 schwarze 68: static void post_vt(DECL_ARGS);
1.34 schwarze 69: static int pre__t(DECL_ARGS);
1.22 schwarze 70: static int pre_an(DECL_ARGS);
1.3 schwarze 71: static int pre_ap(DECL_ARGS);
72: static int pre_bd(DECL_ARGS);
1.27 schwarze 73: static int pre_bf(DECL_ARGS);
1.13 schwarze 74: static int pre_bk(DECL_ARGS);
1.30 schwarze 75: static int pre_bl(DECL_ARGS);
1.3 schwarze 76: static int pre_br(DECL_ARGS);
1.8 schwarze 77: static int pre_bx(DECL_ARGS);
1.1 schwarze 78: static int pre_dl(DECL_ARGS);
1.5 kristaps 79: static int pre_enc(DECL_ARGS);
1.26 schwarze 80: static int pre_em(DECL_ARGS);
1.17 schwarze 81: static int pre_fa(DECL_ARGS);
1.29 schwarze 82: static int pre_fd(DECL_ARGS);
1.26 schwarze 83: static int pre_fl(DECL_ARGS);
1.16 schwarze 84: static int pre_fn(DECL_ARGS);
1.17 schwarze 85: static int pre_fo(DECL_ARGS);
1.23 schwarze 86: static int pre_ft(DECL_ARGS);
1.15 schwarze 87: static int pre_in(DECL_ARGS);
1.1 schwarze 88: static int pre_it(DECL_ARGS);
1.24 schwarze 89: static int pre_lk(DECL_ARGS);
1.26 schwarze 90: static int pre_li(DECL_ARGS);
1.1 schwarze 91: static int pre_nm(DECL_ARGS);
1.25 schwarze 92: static int pre_no(DECL_ARGS);
1.1 schwarze 93: static int pre_ns(DECL_ARGS);
94: static int pre_pp(DECL_ARGS);
1.34 schwarze 95: static int pre_rs(DECL_ARGS);
1.12 schwarze 96: static int pre_sm(DECL_ARGS);
1.3 schwarze 97: static int pre_sp(DECL_ARGS);
1.5 kristaps 98: static int pre_sect(DECL_ARGS);
1.26 schwarze 99: static int pre_sy(DECL_ARGS);
1.23 schwarze 100: static void pre_syn(const struct mdoc_node *);
1.18 schwarze 101: static int pre_vt(DECL_ARGS);
1.8 schwarze 102: static int pre_ux(DECL_ARGS);
1.1 schwarze 103: static int pre_xr(DECL_ARGS);
1.20 schwarze 104: static void print_word(const char *);
1.36 ! schwarze 105: static void print_line(const char *, int);
! 106: static void print_block(const char *, int);
1.20 schwarze 107: static void print_offs(const char *);
1.35 schwarze 108: static void print_width(const char *,
109: const struct mdoc_node *, size_t);
1.30 schwarze 110: static void print_count(int *);
1.5 kristaps 111: static void print_node(DECL_ARGS);
1.1 schwarze 112:
1.3 schwarze 113: static const struct manact manacts[MDOC_MAX + 1] = {
114: { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
115: { NULL, NULL, NULL, NULL, NULL }, /* Dd */
116: { NULL, NULL, NULL, NULL, NULL }, /* Dt */
1.8 schwarze 117: { NULL, NULL, NULL, NULL, NULL }, /* Os */
1.3 schwarze 118: { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */
119: { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */
1.1 schwarze 120: { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
1.3 schwarze 121: { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */
1.1 schwarze 122: { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
1.3 schwarze 123: { cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */
124: { NULL, NULL, NULL, NULL, NULL }, /* Ed */
1.30 schwarze 125: { cond_body, pre_bl, post_bl, NULL, NULL }, /* Bl */
1.3 schwarze 126: { NULL, NULL, NULL, NULL, NULL }, /* El */
1.30 schwarze 127: { NULL, pre_it, post_it, NULL, NULL }, /* It */
1.26 schwarze 128: { NULL, pre_em, post_font, NULL, NULL }, /* Ad */
1.22 schwarze 129: { NULL, pre_an, NULL, NULL, NULL }, /* An */
1.26 schwarze 130: { NULL, pre_em, post_font, NULL, NULL }, /* Ar */
131: { NULL, pre_sy, post_font, NULL, NULL }, /* Cd */
132: { NULL, pre_sy, post_font, NULL, NULL }, /* Cm */
133: { NULL, pre_li, post_font, NULL, NULL }, /* Dv */
134: { NULL, pre_li, post_font, NULL, NULL }, /* Er */
135: { NULL, pre_li, post_font, NULL, NULL }, /* Ev */
1.1 schwarze 136: { NULL, pre_enc, post_enc, "The \\fB",
137: "\\fP\nutility exits 0 on success, and >0 if an error occurs."
138: }, /* Ex */
1.17 schwarze 139: { NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */
1.29 schwarze 140: { NULL, pre_fd, post_fd, NULL, NULL }, /* Fd */
1.26 schwarze 141: { NULL, pre_fl, post_fl, NULL, NULL }, /* Fl */
1.16 schwarze 142: { NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */
1.26 schwarze 143: { NULL, pre_ft, post_font, NULL, NULL }, /* Ft */
144: { NULL, pre_sy, post_font, NULL, NULL }, /* Ic */
1.15 schwarze 145: { NULL, pre_in, post_in, NULL, NULL }, /* In */
1.26 schwarze 146: { NULL, pre_li, post_font, NULL, NULL }, /* Li */
1.1 schwarze 147: { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
148: { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
149: { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
1.8 schwarze 150: { NULL, NULL, NULL, NULL, NULL }, /* Ot */
1.26 schwarze 151: { NULL, pre_em, post_font, NULL, NULL }, /* Pa */
1.6 kristaps 152: { NULL, pre_enc, post_enc, "The \\fB",
153: "\\fP\nfunction returns the value 0 if successful;\n"
154: "otherwise the value -1 is returned and the global\n"
155: "variable \\fIerrno\\fP is set to indicate the error."
156: }, /* Rv */
1.8 schwarze 157: { NULL, NULL, NULL, NULL, NULL }, /* St */
1.26 schwarze 158: { NULL, pre_em, post_font, NULL, NULL }, /* Va */
1.18 schwarze 159: { NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */
1.8 schwarze 160: { NULL, pre_xr, NULL, NULL, NULL }, /* Xr */
1.34 schwarze 161: { NULL, NULL, post_percent, NULL, NULL }, /* %A */
162: { NULL, pre_em, post_percent, NULL, NULL }, /* %B */
163: { NULL, NULL, post_percent, NULL, NULL }, /* %D */
164: { NULL, pre_em, post_percent, NULL, NULL }, /* %I */
165: { NULL, pre_em, post_percent, NULL, NULL }, /* %J */
166: { NULL, NULL, post_percent, NULL, NULL }, /* %N */
167: { NULL, NULL, post_percent, NULL, NULL }, /* %O */
168: { NULL, NULL, post_percent, NULL, NULL }, /* %P */
169: { NULL, NULL, post_percent, NULL, NULL }, /* %R */
170: { NULL, pre__t, post__t, NULL, NULL }, /* %T */
171: { NULL, NULL, post_percent, NULL, NULL }, /* %V */
1.9 schwarze 172: { NULL, NULL, NULL, NULL, NULL }, /* Ac */
173: { cond_body, pre_enc, post_enc, "<", ">" }, /* Ao */
1.1 schwarze 174: { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
1.8 schwarze 175: { NULL, NULL, NULL, NULL, NULL }, /* At */
1.3 schwarze 176: { NULL, NULL, NULL, NULL, NULL }, /* Bc */
1.27 schwarze 177: { NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
1.3 schwarze 178: { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
179: { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
1.8 schwarze 180: { NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */
181: { NULL, pre_bx, NULL, NULL, NULL }, /* Bx */
182: { NULL, NULL, NULL, NULL, NULL }, /* Db */
1.9 schwarze 183: { NULL, NULL, NULL, NULL, NULL }, /* Dc */
184: { cond_body, pre_enc, post_enc, "``", "''" }, /* Do */
1.1 schwarze 185: { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
1.28 schwarze 186: { NULL, NULL, NULL, NULL, NULL }, /* Ec */
187: { NULL, NULL, NULL, NULL, NULL }, /* Ef */
1.26 schwarze 188: { NULL, pre_em, post_font, NULL, NULL }, /* Em */
1.28 schwarze 189: { NULL, NULL, post_eo, NULL, NULL }, /* Eo */
1.8 schwarze 190: { NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */
1.26 schwarze 191: { NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
1.25 schwarze 192: { NULL, pre_no, NULL, NULL, NULL }, /* No */
1.1 schwarze 193: { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
1.8 schwarze 194: { NULL, pre_ux, NULL, "NetBSD", NULL }, /* Nx */
195: { NULL, pre_ux, NULL, "OpenBSD", NULL }, /* Ox */
1.3 schwarze 196: { NULL, NULL, NULL, NULL, NULL }, /* Pc */
197: { NULL, NULL, post_pf, NULL, NULL }, /* Pf */
198: { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
199: { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
1.9 schwarze 200: { NULL, NULL, NULL, NULL, NULL }, /* Qc */
1.1 schwarze 201: { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
1.9 schwarze 202: { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
203: { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
204: { NULL, NULL, NULL, NULL, NULL }, /* Re */
1.34 schwarze 205: { cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
1.9 schwarze 206: { NULL, NULL, NULL, NULL, NULL }, /* Sc */
207: { cond_body, pre_enc, post_enc, "`", "'" }, /* So */
1.1 schwarze 208: { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
1.12 schwarze 209: { NULL, pre_sm, NULL, NULL, NULL }, /* Sm */
1.26 schwarze 210: { NULL, pre_em, post_font, NULL, NULL }, /* Sx */
211: { NULL, pre_sy, post_font, NULL, NULL }, /* Sy */
212: { NULL, pre_li, post_font, NULL, NULL }, /* Tn */
1.8 schwarze 213: { NULL, pre_ux, NULL, "UNIX", NULL }, /* Ux */
1.34 schwarze 214: { NULL, NULL, NULL, NULL, NULL }, /* Xc */
215: { NULL, NULL, NULL, NULL, NULL }, /* Xo */
1.17 schwarze 216: { NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */
217: { NULL, NULL, NULL, NULL, NULL }, /* Fc */
1.3 schwarze 218: { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
1.9 schwarze 219: { NULL, NULL, NULL, NULL, NULL }, /* Oc */
1.13 schwarze 220: { NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */
221: { NULL, NULL, NULL, NULL, NULL }, /* Ek */
1.8 schwarze 222: { NULL, pre_ux, NULL, "is currently in beta test.", NULL }, /* Bt */
223: { NULL, NULL, NULL, NULL, NULL }, /* Hf */
224: { NULL, NULL, NULL, NULL, NULL }, /* Fr */
225: { NULL, pre_ux, NULL, "currently under development.", NULL }, /* Ud */
1.14 schwarze 226: { NULL, NULL, post_lb, NULL, NULL }, /* Lb */
1.3 schwarze 227: { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
1.24 schwarze 228: { NULL, pre_lk, NULL, NULL, NULL }, /* Lk */
1.26 schwarze 229: { NULL, pre_em, post_font, NULL, NULL }, /* Mt */
1.9 schwarze 230: { cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */
231: { cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */
232: { NULL, NULL, NULL, NULL, NULL }, /* Brc */
1.34 schwarze 233: { NULL, NULL, post_percent, NULL, NULL }, /* %C */
1.29 schwarze 234: { NULL, NULL, NULL, NULL, NULL }, /* Es */
235: { NULL, NULL, NULL, NULL, NULL }, /* En */
1.8 schwarze 236: { NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */
1.34 schwarze 237: { NULL, NULL, post_percent, NULL, NULL }, /* %Q */
1.3 schwarze 238: { NULL, pre_br, NULL, NULL, NULL }, /* br */
239: { NULL, pre_sp, post_sp, NULL, NULL }, /* sp */
1.34 schwarze 240: { NULL, NULL, post_percent, NULL, NULL }, /* %U */
241: { NULL, NULL, NULL, NULL, NULL }, /* Ta */
1.3 schwarze 242: { NULL, NULL, NULL, NULL, NULL }, /* ROOT */
1.1 schwarze 243: };
244:
1.20 schwarze 245: static int outflags;
1.36 ! schwarze 246: #define MMAN_spc (1 << 0) /* blank character before next word */
! 247: #define MMAN_spc_force (1 << 1) /* even before trailing punctuation */
! 248: #define MMAN_nl (1 << 2) /* break man(7) code line */
! 249: #define MMAN_br (1 << 3) /* break output line */
! 250: #define MMAN_sp (1 << 4) /* insert a blank output line */
! 251: #define MMAN_PP (1 << 5) /* reset indentation etc. */
! 252: #define MMAN_Sm (1 << 6) /* horizontal spacing mode */
! 253: #define MMAN_Bk (1 << 7) /* word keep mode */
! 254: #define MMAN_An_split (1 << 8) /* author mode is "split" */
! 255: #define MMAN_An_nosplit (1 << 9) /* author mode is "nosplit" */
1.20 schwarze 256:
1.26 schwarze 257: static struct {
258: char *head;
259: char *tail;
260: size_t size;
261: } fontqueue;
262:
263: static void
264: font_push(char newfont)
265: {
266:
267: if (fontqueue.head + fontqueue.size <= ++fontqueue.tail) {
268: fontqueue.size += 8;
269: fontqueue.head = mandoc_realloc(fontqueue.head,
270: fontqueue.size);
271: }
272: *fontqueue.tail = newfont;
273: print_word("\\f");
274: putchar(newfont);
275: outflags &= ~MMAN_spc;
276: }
277:
278: static void
279: font_pop(void)
280: {
281:
282: if (fontqueue.tail > fontqueue.head)
283: fontqueue.tail--;
284: outflags &= ~MMAN_spc;
285: print_word("\\f");
286: putchar(*fontqueue.tail);
287: }
288:
1.1 schwarze 289: static void
1.20 schwarze 290: print_word(const char *s)
1.1 schwarze 291: {
1.5 kristaps 292:
1.36 ! schwarze 293: if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) {
1.5 kristaps 294: /*
295: * If we need a newline, print it now and start afresh.
296: */
1.36 ! schwarze 297: if (MMAN_PP & outflags) {
! 298: if ( ! (MMAN_sp & outflags))
! 299: printf("\n.sp -1v");
! 300: printf("\n.PP\n");
! 301: } else if (MMAN_sp & outflags)
1.21 schwarze 302: printf("\n.sp\n");
303: else if (MMAN_br & outflags)
304: printf("\n.br\n");
305: else if (MMAN_nl & outflags)
306: putchar('\n');
1.36 ! schwarze 307: outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc);
1.20 schwarze 308: } else if (MMAN_spc & outflags && '\0' != s[0])
1.5 kristaps 309: /*
1.25 schwarze 310: * If we need a space, only print it if
311: * (1) it is forced by `No' or
312: * (2) what follows is not terminating punctuation or
313: * (3) what follows is longer than one character.
1.5 kristaps 314: */
1.25 schwarze 315: if (MMAN_spc_force & outflags ||
316: NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) {
1.20 schwarze 317: if (MMAN_Bk & outflags) {
1.13 schwarze 318: putchar('\\');
319: putchar('~');
320: } else
321: putchar(' ');
322: }
1.5 kristaps 323:
324: /*
325: * Reassign needing space if we're not following opening
326: * punctuation.
327: */
1.20 schwarze 328: if (MMAN_Sm & outflags &&
329: (('(' != s[0] && '[' != s[0]) || '\0' != s[1]))
330: outflags |= MMAN_spc;
331: else
332: outflags &= ~MMAN_spc;
1.25 schwarze 333: outflags &= ~MMAN_spc_force;
1.5 kristaps 334:
1.1 schwarze 335: for ( ; *s; s++) {
336: switch (*s) {
337: case (ASCII_NBRSP):
338: printf("\\~");
339: break;
340: case (ASCII_HYPH):
341: putchar('-');
342: break;
343: default:
1.5 kristaps 344: putchar((unsigned char)*s);
1.1 schwarze 345: break;
346: }
347: }
1.4 kristaps 348: }
349:
1.11 schwarze 350: static void
1.36 ! schwarze 351: print_line(const char *s, int newflags)
! 352: {
! 353:
! 354: outflags &= ~MMAN_br;
! 355: outflags |= MMAN_nl;
! 356: print_word(s);
! 357: outflags |= newflags;
! 358: }
! 359:
! 360: static void
! 361: print_block(const char *s, int newflags)
! 362: {
! 363:
! 364: outflags &= ~MMAN_PP;
! 365: if (MMAN_sp & outflags)
! 366: outflags &= ~(MMAN_sp | MMAN_br);
! 367: else
! 368: print_line(".sp -1v", 0);
! 369: outflags |= MMAN_nl;
! 370: print_word(s);
! 371: outflags |= newflags;
! 372: }
! 373:
! 374: static void
1.20 schwarze 375: print_offs(const char *v)
1.11 schwarze 376: {
377: char buf[24];
378: struct roffsu su;
379: size_t sz;
380:
381: if (NULL == v || '\0' == *v || 0 == strcmp(v, "left"))
382: sz = 0;
383: else if (0 == strcmp(v, "indent"))
384: sz = 6;
385: else if (0 == strcmp(v, "indent-two"))
386: sz = 12;
387: else if (a2roffsu(v, &su, SCALE_MAX)) {
1.20 schwarze 388: print_word(v);
1.11 schwarze 389: return;
390: } else
391: sz = strlen(v);
392:
393: snprintf(buf, sizeof(buf), "%ldn", sz);
1.20 schwarze 394: print_word(buf);
1.11 schwarze 395: }
396:
1.4 kristaps 397: void
1.35 schwarze 398: print_width(const char *v, const struct mdoc_node *child, size_t defsz)
1.30 schwarze 399: {
400: char buf[24];
401: struct roffsu su;
1.31 schwarze 402: size_t sz, chsz;
403:
404: /* XXX Rough estimation, might have multiple parts. */
405: chsz = (NULL != child && MDOC_TEXT == child->type) ?
406: strlen(child->string) : 0;
1.30 schwarze 407:
1.35 schwarze 408: if (NULL == v)
409: sz = defsz;
410: else if (a2roffsu(v, &su, SCALE_MAX)) {
1.30 schwarze 411: if (SCALE_EN == su.unit)
412: sz = su.scale;
413: else {
1.31 schwarze 414: if (chsz)
1.36 ! schwarze 415: print_block(".HP", 0);
1.31 schwarze 416: else
1.36 ! schwarze 417: print_block(".TP", 0);
1.30 schwarze 418: print_word(v);
419: return;
420: }
421: } else
422: sz = strlen(v);
423:
1.31 schwarze 424: if (chsz > sz)
1.36 ! schwarze 425: print_block(".HP", 0);
1.31 schwarze 426: else
1.36 ! schwarze 427: print_block(".TP", 0);
1.30 schwarze 428: snprintf(buf, sizeof(buf), "%ldn", sz + 2);
429: print_word(buf);
430: }
431:
432: void
433: print_count(int *count)
434: {
435: char buf[12];
436:
437: snprintf(buf, sizeof(buf), "%d.", ++*count);
438: print_word(buf);
439: }
440:
441: void
1.4 kristaps 442: man_man(void *arg, const struct man *man)
443: {
444:
1.5 kristaps 445: /*
446: * Dump the keep buffer.
447: * We're guaranteed by now that this exists (is non-NULL).
448: * Flush stdout afterward, just in case.
449: */
1.4 kristaps 450: fputs(mparse_getkeep(man_mparse(man)), stdout);
1.5 kristaps 451: fflush(stdout);
1.1 schwarze 452: }
453:
454: void
455: man_mdoc(void *arg, const struct mdoc *mdoc)
456: {
457: const struct mdoc_meta *m;
458: const struct mdoc_node *n;
459:
460: m = mdoc_meta(mdoc);
461: n = mdoc_node(mdoc);
462:
1.3 schwarze 463: printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
1.5 kristaps 464: m->title, m->msec, m->date, m->os, m->vol);
1.1 schwarze 465:
1.20 schwarze 466: outflags = MMAN_nl | MMAN_Sm;
1.26 schwarze 467: if (0 == fontqueue.size) {
468: fontqueue.size = 8;
469: fontqueue.head = fontqueue.tail = mandoc_malloc(8);
470: *fontqueue.tail = 'R';
471: }
1.20 schwarze 472: print_node(m, n);
1.3 schwarze 473: putchar('\n');
1.1 schwarze 474: }
475:
476: static void
477: print_node(DECL_ARGS)
478: {
479: const struct mdoc_node *prev, *sub;
1.5 kristaps 480: const struct manact *act;
1.1 schwarze 481: int cond, do_sub;
1.5 kristaps 482:
483: /*
484: * Break the line if we were parsed subsequent the current node.
485: * This makes the page structure be more consistent.
486: */
1.1 schwarze 487: prev = n->prev ? n->prev : n->parent;
1.27 schwarze 488: if (MMAN_spc & outflags && prev && prev->line < n->line)
1.20 schwarze 489: outflags |= MMAN_nl;
1.1 schwarze 490:
1.5 kristaps 491: act = NULL;
1.1 schwarze 492: cond = 0;
493: do_sub = 1;
1.5 kristaps 494:
1.1 schwarze 495: if (MDOC_TEXT == n->type) {
1.5 kristaps 496: /*
497: * Make sure that we don't happen to start with a
498: * control character at the start of a line.
499: */
1.20 schwarze 500: if (MMAN_nl & outflags && ('.' == *n->string ||
1.5 kristaps 501: '\'' == *n->string)) {
1.20 schwarze 502: print_word("\\&");
503: outflags &= ~MMAN_spc;
1.3 schwarze 504: }
1.20 schwarze 505: print_word(n->string);
1.1 schwarze 506: } else {
1.5 kristaps 507: /*
508: * Conditionally run the pre-node action handler for a
509: * node.
510: */
1.1 schwarze 511: act = manacts + n->tok;
1.20 schwarze 512: cond = NULL == act->cond || (*act->cond)(m, n);
1.1 schwarze 513: if (cond && act->pre)
1.20 schwarze 514: do_sub = (*act->pre)(m, n);
1.1 schwarze 515: }
516:
1.5 kristaps 517: /*
518: * Conditionally run all child nodes.
519: * Note that this iterates over children instead of using
520: * recursion. This prevents unnecessary depth in the stack.
521: */
1.1 schwarze 522: if (do_sub)
523: for (sub = n->child; sub; sub = sub->next)
1.20 schwarze 524: print_node(m, sub);
1.1 schwarze 525:
1.5 kristaps 526: /*
527: * Lastly, conditionally run the post-node handler.
528: */
1.1 schwarze 529: if (cond && act->post)
1.20 schwarze 530: (*act->post)(m, n);
1.1 schwarze 531: }
532:
533: static int
534: cond_head(DECL_ARGS)
535: {
1.5 kristaps 536:
1.1 schwarze 537: return(MDOC_HEAD == n->type);
538: }
539:
540: static int
541: cond_body(DECL_ARGS)
542: {
1.5 kristaps 543:
1.1 schwarze 544: return(MDOC_BODY == n->type);
545: }
546:
547: static int
548: pre_enc(DECL_ARGS)
549: {
1.5 kristaps 550: const char *prefix;
1.1 schwarze 551:
552: prefix = manacts[n->tok].prefix;
553: if (NULL == prefix)
554: return(1);
1.20 schwarze 555: print_word(prefix);
556: outflags &= ~MMAN_spc;
1.1 schwarze 557: return(1);
558: }
559:
560: static void
561: post_enc(DECL_ARGS)
562: {
563: const char *suffix;
564:
565: suffix = manacts[n->tok].suffix;
566: if (NULL == suffix)
567: return;
1.20 schwarze 568: outflags &= ~MMAN_spc;
569: print_word(suffix);
1.26 schwarze 570: }
571:
572: static void
573: post_font(DECL_ARGS)
574: {
575:
576: font_pop();
1.1 schwarze 577: }
578:
579: static void
580: post_percent(DECL_ARGS)
581: {
582:
1.34 schwarze 583: if (pre_em == manacts[n->tok].pre)
584: font_pop();
585: if (n->next) {
1.20 schwarze 586: print_word(",");
1.34 schwarze 587: if (n->prev && n->prev->tok == n->tok &&
588: n->next->tok == n->tok)
589: print_word("and");
590: } else {
1.20 schwarze 591: print_word(".");
592: outflags |= MMAN_nl;
1.1 schwarze 593: }
594: }
595:
1.34 schwarze 596: static int
597: pre__t(DECL_ARGS)
598: {
599:
600: if (n->parent && MDOC_Rs == n->parent->tok &&
601: n->parent->norm->Rs.quote_T) {
602: print_word("\"");
603: outflags &= ~MMAN_spc;
604: } else
605: font_push('I');
606: return(1);
607: }
608:
609: static void
610: post__t(DECL_ARGS)
611: {
612:
613: if (n->parent && MDOC_Rs == n->parent->tok &&
614: n->parent->norm->Rs.quote_T) {
615: outflags &= ~MMAN_spc;
616: print_word("\"");
617: } else
618: font_pop();
619: post_percent(m, n);
620: }
621:
1.5 kristaps 622: /*
623: * Print before a section header.
624: */
1.1 schwarze 625: static int
1.3 schwarze 626: pre_sect(DECL_ARGS)
627: {
628:
629: if (MDOC_HEAD != n->type)
630: return(1);
1.36 ! schwarze 631: outflags |= MMAN_sp;
! 632: print_block(manacts[n->tok].prefix, 0);
1.20 schwarze 633: print_word("\"");
634: outflags &= ~MMAN_spc;
1.3 schwarze 635: return(1);
636: }
637:
1.5 kristaps 638: /*
639: * Print subsequent a section header.
640: */
1.3 schwarze 641: static void
642: post_sect(DECL_ARGS)
643: {
644:
645: if (MDOC_HEAD != n->type)
646: return;
1.20 schwarze 647: outflags &= ~MMAN_spc;
648: print_word("\"");
649: outflags |= MMAN_nl;
1.22 schwarze 650: if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec)
651: outflags &= ~(MMAN_An_split | MMAN_An_nosplit);
652: }
653:
1.23 schwarze 654: /* See mdoc_term.c, synopsis_pre() for comments. */
655: static void
656: pre_syn(const struct mdoc_node *n)
657: {
658:
659: if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
660: return;
661:
662: if (n->prev->tok == n->tok &&
663: MDOC_Ft != n->tok &&
664: MDOC_Fo != n->tok &&
665: MDOC_Fn != n->tok) {
666: outflags |= MMAN_br;
667: return;
668: }
669:
670: switch (n->prev->tok) {
671: case (MDOC_Fd):
672: /* FALLTHROUGH */
673: case (MDOC_Fn):
674: /* FALLTHROUGH */
675: case (MDOC_Fo):
676: /* FALLTHROUGH */
677: case (MDOC_In):
678: /* FALLTHROUGH */
679: case (MDOC_Vt):
680: outflags |= MMAN_sp;
681: break;
682: case (MDOC_Ft):
683: if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
684: outflags |= MMAN_sp;
685: break;
686: }
687: /* FALLTHROUGH */
688: default:
689: outflags |= MMAN_br;
690: break;
691: }
692: }
693:
1.22 schwarze 694: static int
695: pre_an(DECL_ARGS)
696: {
697:
698: switch (n->norm->An.auth) {
699: case (AUTH_split):
700: outflags &= ~MMAN_An_nosplit;
701: outflags |= MMAN_An_split;
702: return(0);
703: case (AUTH_nosplit):
704: outflags &= ~MMAN_An_split;
705: outflags |= MMAN_An_nosplit;
706: return(0);
707: default:
708: if (MMAN_An_split & outflags)
709: outflags |= MMAN_br;
710: else if (SEC_AUTHORS == n->sec &&
711: ! (MMAN_An_nosplit & outflags))
712: outflags |= MMAN_An_split;
713: return(1);
714: }
1.3 schwarze 715: }
716:
717: static int
718: pre_ap(DECL_ARGS)
719: {
720:
1.20 schwarze 721: outflags &= ~MMAN_spc;
722: print_word("'");
723: outflags &= ~MMAN_spc;
1.3 schwarze 724: return(0);
725: }
726:
727: static int
728: pre_bd(DECL_ARGS)
729: {
730:
1.36 ! schwarze 731: outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br);
! 732:
! 733: if (DISP_unfilled == n->norm->Bd.type ||
! 734: DISP_literal == n->norm->Bd.type)
! 735: print_line(".nf", 0);
! 736: if (0 == n->norm->Bd.comp && NULL != n->parent->prev)
1.21 schwarze 737: outflags |= MMAN_sp;
1.36 ! schwarze 738: print_line(".RS", 0);
1.20 schwarze 739: print_offs(n->norm->Bd.offs);
740: outflags |= MMAN_nl;
1.3 schwarze 741: return(1);
742: }
743:
744: static void
745: post_bd(DECL_ARGS)
746: {
747:
1.36 ! schwarze 748: print_line(".RE", MMAN_nl);
1.3 schwarze 749: if (DISP_unfilled == n->norm->Bd.type ||
1.36 ! schwarze 750: DISP_literal == n->norm->Bd.type)
! 751: print_line(".fi", MMAN_nl);
1.13 schwarze 752: }
753:
754: static int
1.27 schwarze 755: pre_bf(DECL_ARGS)
756: {
757:
758: switch (n->type) {
759: case (MDOC_BLOCK):
760: return(1);
761: case (MDOC_BODY):
762: break;
763: default:
764: return(0);
765: }
766: switch (n->norm->Bf.font) {
767: case (FONT_Em):
768: font_push('I');
769: break;
770: case (FONT_Sy):
771: font_push('B');
772: break;
773: default:
774: font_push('R');
775: break;
776: }
777: return(1);
778: }
779:
780: static void
781: post_bf(DECL_ARGS)
782: {
783:
784: if (MDOC_BODY == n->type)
785: font_pop();
786: }
787:
788: static int
1.13 schwarze 789: pre_bk(DECL_ARGS)
790: {
791:
792: switch (n->type) {
793: case (MDOC_BLOCK):
794: return(1);
795: case (MDOC_BODY):
1.20 schwarze 796: outflags |= MMAN_Bk;
1.13 schwarze 797: return(1);
798: default:
799: return(0);
800: }
801: }
802:
803: static void
804: post_bk(DECL_ARGS)
805: {
806:
807: if (MDOC_BODY == n->type)
1.20 schwarze 808: outflags &= ~MMAN_Bk;
1.3 schwarze 809: }
810:
811: static int
1.30 schwarze 812: pre_bl(DECL_ARGS)
813: {
1.33 schwarze 814: size_t icol;
1.30 schwarze 815:
1.33 schwarze 816: switch (n->norm->Bl.type) {
817: case (LIST_enum):
1.30 schwarze 818: n->norm->Bl.count = 0;
1.33 schwarze 819: return(1);
820: case (LIST_column):
821: break;
822: default:
823: return(1);
824: }
825:
1.36 ! schwarze 826: print_line(".TS", MMAN_nl);
1.33 schwarze 827: for (icol = 0; icol < n->norm->Bl.ncols; icol++)
828: print_word("l");
829: print_word(".");
1.36 ! schwarze 830: outflags |= MMAN_nl;
1.30 schwarze 831: return(1);
832: }
833:
834: static void
835: post_bl(DECL_ARGS)
836: {
837:
1.33 schwarze 838: switch (n->norm->Bl.type) {
1.36 ! schwarze 839: case (LIST_column):
! 840: print_line(".TE", 0);
! 841: break;
1.33 schwarze 842: case (LIST_enum):
843: n->norm->Bl.count = 0;
844: break;
845: default:
846: break;
847: }
1.36 ! schwarze 848: outflags |= MMAN_PP | MMAN_nl;
! 849: outflags &= ~(MMAN_sp | MMAN_br);
1.30 schwarze 850: }
851:
852: static int
1.3 schwarze 853: pre_br(DECL_ARGS)
854: {
855:
1.21 schwarze 856: outflags |= MMAN_br;
1.3 schwarze 857: return(0);
858: }
859:
860: static int
1.8 schwarze 861: pre_bx(DECL_ARGS)
862: {
863:
864: n = n->child;
865: if (n) {
1.20 schwarze 866: print_word(n->string);
867: outflags &= ~MMAN_spc;
1.8 schwarze 868: n = n->next;
869: }
1.20 schwarze 870: print_word("BSD");
1.8 schwarze 871: if (NULL == n)
872: return(0);
1.20 schwarze 873: outflags &= ~MMAN_spc;
874: print_word("-");
875: outflags &= ~MMAN_spc;
876: print_word(n->string);
1.8 schwarze 877: return(0);
878: }
879:
880: static int
1.1 schwarze 881: pre_dl(DECL_ARGS)
882: {
883:
1.36 ! schwarze 884: print_line(".RS 6n", MMAN_nl);
1.1 schwarze 885: return(1);
886: }
887:
888: static void
889: post_dl(DECL_ARGS)
890: {
891:
1.36 ! schwarze 892: print_line(".RE", MMAN_nl);
1.16 schwarze 893: }
894:
895: static int
1.26 schwarze 896: pre_em(DECL_ARGS)
897: {
898:
899: font_push('I');
900: return(1);
1.28 schwarze 901: }
902:
903: static void
904: post_eo(DECL_ARGS)
905: {
906:
907: if (MDOC_HEAD == n->type || MDOC_BODY == n->type)
908: outflags &= ~MMAN_spc;
1.26 schwarze 909: }
910:
911: static int
1.17 schwarze 912: pre_fa(DECL_ARGS)
913: {
914:
915: if (MDOC_Fa == n->tok)
916: n = n->child;
917:
918: while (NULL != n) {
1.26 schwarze 919: font_push('I');
1.20 schwarze 920: print_node(m, n);
1.26 schwarze 921: font_pop();
1.17 schwarze 922: if (NULL != (n = n->next))
1.20 schwarze 923: print_word(",");
1.17 schwarze 924: }
925: return(0);
926: }
927:
928: static void
929: post_fa(DECL_ARGS)
930: {
931:
932: if (NULL != n->next && MDOC_Fa == n->next->tok)
1.20 schwarze 933: print_word(",");
1.29 schwarze 934: }
935:
936: static int
937: pre_fd(DECL_ARGS)
938: {
939:
940: pre_syn(n);
941: font_push('B');
942: return(1);
943: }
944:
945: static void
946: post_fd(DECL_ARGS)
947: {
948:
949: font_pop();
950: outflags |= MMAN_br;
1.17 schwarze 951: }
952:
953: static int
1.26 schwarze 954: pre_fl(DECL_ARGS)
955: {
956:
957: font_push('B');
958: print_word("-");
959: outflags &= ~MMAN_spc;
960: return(1);
961: }
962:
963: static void
964: post_fl(DECL_ARGS)
965: {
966:
967: font_pop();
1.27 schwarze 968: if (0 == n->nchild && NULL != n->next &&
969: n->next->line == n->line)
1.26 schwarze 970: outflags &= ~MMAN_spc;
971: }
972:
973: static int
1.16 schwarze 974: pre_fn(DECL_ARGS)
975: {
976:
1.23 schwarze 977: pre_syn(n);
978:
1.16 schwarze 979: n = n->child;
980: if (NULL == n)
981: return(0);
982:
1.26 schwarze 983: font_push('B');
1.20 schwarze 984: print_node(m, n);
1.26 schwarze 985: font_pop();
1.20 schwarze 986: outflags &= ~MMAN_spc;
1.26 schwarze 987: print_word("(");
1.20 schwarze 988: outflags &= ~MMAN_spc;
1.35 schwarze 989:
990: n = n->next;
991: if (NULL != n)
992: pre_fa(m, n);
993: return(0);
1.16 schwarze 994: }
995:
996: static void
997: post_fn(DECL_ARGS)
998: {
999:
1.20 schwarze 1000: print_word(")");
1.16 schwarze 1001: if (MDOC_SYNPRETTY & n->flags) {
1.20 schwarze 1002: print_word(";");
1.21 schwarze 1003: outflags |= MMAN_br;
1.17 schwarze 1004: }
1005: }
1006:
1007: static int
1008: pre_fo(DECL_ARGS)
1009: {
1010:
1011: switch (n->type) {
1.23 schwarze 1012: case (MDOC_BLOCK):
1013: pre_syn(n);
1014: break;
1.17 schwarze 1015: case (MDOC_HEAD):
1.26 schwarze 1016: font_push('B');
1.17 schwarze 1017: break;
1018: case (MDOC_BODY):
1.20 schwarze 1019: outflags &= ~MMAN_spc;
1020: print_word("(");
1021: outflags &= ~MMAN_spc;
1.17 schwarze 1022: break;
1023: default:
1024: break;
1025: }
1026: return(1);
1027: }
1028:
1029: static void
1030: post_fo(DECL_ARGS)
1031: {
1032:
1033: switch (n->type) {
1034: case (MDOC_HEAD):
1.26 schwarze 1035: font_pop();
1.17 schwarze 1036: break;
1037: case (MDOC_BODY):
1.20 schwarze 1038: post_fn(m, n);
1.17 schwarze 1039: break;
1040: default:
1041: break;
1.16 schwarze 1042: }
1.15 schwarze 1043: }
1044:
1045: static int
1.23 schwarze 1046: pre_ft(DECL_ARGS)
1047: {
1048:
1049: pre_syn(n);
1.26 schwarze 1050: font_push('I');
1.23 schwarze 1051: return(1);
1052: }
1053:
1054: static int
1.15 schwarze 1055: pre_in(DECL_ARGS)
1056: {
1057:
1058: if (MDOC_SYNPRETTY & n->flags) {
1.23 schwarze 1059: pre_syn(n);
1.26 schwarze 1060: font_push('B');
1061: print_word("#include <");
1062: outflags &= ~MMAN_spc;
1063: } else {
1064: print_word("<");
1065: outflags &= ~MMAN_spc;
1066: font_push('I');
1067: }
1.15 schwarze 1068: return(1);
1069: }
1070:
1071: static void
1072: post_in(DECL_ARGS)
1073: {
1074:
1075: if (MDOC_SYNPRETTY & n->flags) {
1.26 schwarze 1076: outflags &= ~MMAN_spc;
1077: print_word(">");
1078: font_pop();
1.21 schwarze 1079: outflags |= MMAN_br;
1.26 schwarze 1080: } else {
1081: font_pop();
1082: outflags &= ~MMAN_spc;
1083: print_word(">");
1084: }
1.1 schwarze 1085: }
1086:
1087: static int
1088: pre_it(DECL_ARGS)
1089: {
1090: const struct mdoc_node *bln;
1091:
1.30 schwarze 1092: switch (n->type) {
1093: case (MDOC_HEAD):
1.36 ! schwarze 1094: outflags |= MMAN_PP | MMAN_nl;
1.30 schwarze 1095: bln = n->parent->parent;
1.36 ! schwarze 1096: if (0 == bln->norm->Bl.comp ||
! 1097: NULL == bln->parent->prev)
! 1098: outflags |= MMAN_sp;
! 1099: outflags &= ~MMAN_br;
1.3 schwarze 1100: switch (bln->norm->Bl.type) {
1.30 schwarze 1101: case (LIST_item):
1102: return(0);
1103: case (LIST_inset):
1104: /* FALLTHROUGH */
1105: case (LIST_diag):
1106: /* FALLTHROUGH */
1107: case (LIST_ohang):
1108: if (bln->norm->Bl.type == LIST_diag)
1.36 ! schwarze 1109: print_line(".B \"", 0);
1.30 schwarze 1110: else
1.36 ! schwarze 1111: print_line(".R \"", 0);
1.30 schwarze 1112: outflags &= ~MMAN_spc;
1113: return(1);
1.3 schwarze 1114: case (LIST_bullet):
1.30 schwarze 1115: /* FALLTHROUGH */
1116: case (LIST_dash):
1117: /* FALLTHROUGH */
1118: case (LIST_hyphen):
1.35 schwarze 1119: print_width(bln->norm->Bl.width, NULL, 0);
1.30 schwarze 1120: outflags |= MMAN_nl;
1121: font_push('B');
1122: if (LIST_bullet == bln->norm->Bl.type)
1123: print_word("o");
1124: else
1125: print_word("-");
1126: font_pop();
1127: break;
1128: case (LIST_enum):
1.35 schwarze 1129: print_width(bln->norm->Bl.width, NULL, 0);
1.30 schwarze 1130: outflags |= MMAN_nl;
1131: print_count(&bln->norm->Bl.count);
1.3 schwarze 1132: break;
1.31 schwarze 1133: case (LIST_hang):
1.35 schwarze 1134: print_width(bln->norm->Bl.width, n->child, 6);
1.32 schwarze 1135: break;
1136: case (LIST_tag):
1.35 schwarze 1137: print_width(bln->norm->Bl.width, NULL, 8);
1.31 schwarze 1138: break;
1.3 schwarze 1139: default:
1.32 schwarze 1140: return(1);
1.3 schwarze 1141: }
1.20 schwarze 1142: outflags |= MMAN_nl;
1.30 schwarze 1143: default:
1144: break;
1.1 schwarze 1145: }
1146: return(1);
1.30 schwarze 1147: }
1148:
1149: static void
1150: post_it(DECL_ARGS)
1151: {
1152: const struct mdoc_node *bln;
1153:
1.33 schwarze 1154: bln = n->parent->parent;
1155:
1156: switch (n->type) {
1157: case (MDOC_HEAD):
1.30 schwarze 1158: switch (bln->norm->Bl.type) {
1159: case (LIST_diag):
1160: outflags &= ~MMAN_spc;
1161: print_word("\\ ");
1162: break;
1163: case (LIST_ohang):
1164: outflags |= MMAN_br;
1165: break;
1166: default:
1167: break;
1168: }
1.33 schwarze 1169: break;
1170: case (MDOC_BODY):
1171: if (LIST_column == bln->norm->Bl.type &&
1172: NULL != n->next) {
1173: putchar('\t');
1174: outflags &= ~MMAN_spc;
1175: }
1176: break;
1177: default:
1178: break;
1.30 schwarze 1179: }
1.14 schwarze 1180: }
1181:
1182: static void
1183: post_lb(DECL_ARGS)
1184: {
1185:
1.21 schwarze 1186: if (SEC_LIBRARY == n->sec)
1187: outflags |= MMAN_br;
1.24 schwarze 1188: }
1189:
1190: static int
1191: pre_lk(DECL_ARGS)
1192: {
1193: const struct mdoc_node *link, *descr;
1194:
1195: if (NULL == (link = n->child))
1196: return(0);
1197:
1198: if (NULL != (descr = link->next)) {
1.26 schwarze 1199: font_push('I');
1.24 schwarze 1200: while (NULL != descr) {
1201: print_word(descr->string);
1202: descr = descr->next;
1203: }
1204: print_word(":");
1.26 schwarze 1205: font_pop();
1.24 schwarze 1206: }
1207:
1.26 schwarze 1208: font_push('B');
1.24 schwarze 1209: print_word(link->string);
1.26 schwarze 1210: font_pop();
1.24 schwarze 1211: return(0);
1.1 schwarze 1212: }
1213:
1214: static int
1.26 schwarze 1215: pre_li(DECL_ARGS)
1216: {
1217:
1218: font_push('R');
1219: return(1);
1220: }
1221:
1222: static int
1.1 schwarze 1223: pre_nm(DECL_ARGS)
1224: {
1225:
1.23 schwarze 1226: if (MDOC_BLOCK == n->type)
1227: pre_syn(n);
1.1 schwarze 1228: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
1229: return(1);
1.23 schwarze 1230: if (NULL == n->child && NULL == m->name)
1231: return(0);
1.26 schwarze 1232: font_push('B');
1.1 schwarze 1233: if (NULL == n->child)
1.20 schwarze 1234: print_word(m->name);
1.1 schwarze 1235: return(1);
1236: }
1237:
1238: static void
1239: post_nm(DECL_ARGS)
1240: {
1241:
1242: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
1243: return;
1.26 schwarze 1244: font_pop();
1.25 schwarze 1245: }
1246:
1247: static int
1248: pre_no(DECL_ARGS)
1249: {
1250:
1251: outflags |= MMAN_spc_force;
1252: return(1);
1.1 schwarze 1253: }
1254:
1255: static int
1256: pre_ns(DECL_ARGS)
1257: {
1258:
1.20 schwarze 1259: outflags &= ~MMAN_spc;
1.1 schwarze 1260: return(0);
1261: }
1262:
1.3 schwarze 1263: static void
1264: post_pf(DECL_ARGS)
1265: {
1266:
1.20 schwarze 1267: outflags &= ~MMAN_spc;
1.3 schwarze 1268: }
1269:
1.1 schwarze 1270: static int
1271: pre_pp(DECL_ARGS)
1272: {
1273:
1.36 ! schwarze 1274: if (MDOC_It != n->parent->tok)
! 1275: outflags |= MMAN_PP;
! 1276: outflags |= MMAN_sp | MMAN_nl;
! 1277: outflags &= ~MMAN_br;
1.34 schwarze 1278: return(0);
1279: }
1280:
1281: static int
1282: pre_rs(DECL_ARGS)
1283: {
1284:
1285: if (SEC_SEE_ALSO == n->sec) {
1.36 ! schwarze 1286: outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
! 1287: outflags &= ~MMAN_br;
1.34 schwarze 1288: }
1289: return(1);
1.12 schwarze 1290: }
1291:
1292: static int
1293: pre_sm(DECL_ARGS)
1294: {
1295:
1296: assert(n->child && MDOC_TEXT == n->child->type);
1297: if (0 == strcmp("on", n->child->string))
1.27 schwarze 1298: outflags |= MMAN_Sm | MMAN_spc;
1.12 schwarze 1299: else
1.20 schwarze 1300: outflags &= ~MMAN_Sm;
1.12 schwarze 1301: return(0);
1.1 schwarze 1302: }
1303:
1304: static int
1.3 schwarze 1305: pre_sp(DECL_ARGS)
1.1 schwarze 1306: {
1307:
1.36 ! schwarze 1308: print_line(".sp", MMAN_nl);
1.1 schwarze 1309: return(1);
1310: }
1311:
1312: static void
1.3 schwarze 1313: post_sp(DECL_ARGS)
1.1 schwarze 1314: {
1315:
1.20 schwarze 1316: outflags |= MMAN_nl;
1.18 schwarze 1317: }
1318:
1319: static int
1.26 schwarze 1320: pre_sy(DECL_ARGS)
1321: {
1322:
1323: font_push('B');
1324: return(1);
1325: }
1326:
1327: static int
1.18 schwarze 1328: pre_vt(DECL_ARGS)
1329: {
1330:
1331: if (MDOC_SYNPRETTY & n->flags) {
1332: switch (n->type) {
1333: case (MDOC_BLOCK):
1.23 schwarze 1334: pre_syn(n);
1.18 schwarze 1335: return(1);
1336: case (MDOC_BODY):
1337: break;
1338: default:
1339: return(0);
1340: }
1341: }
1.26 schwarze 1342: font_push('I');
1.18 schwarze 1343: return(1);
1344: }
1345:
1346: static void
1347: post_vt(DECL_ARGS)
1348: {
1349:
1.19 schwarze 1350: if (MDOC_SYNPRETTY & n->flags && MDOC_BODY != n->type)
1.18 schwarze 1351: return;
1.26 schwarze 1352: font_pop();
1.1 schwarze 1353: }
1354:
1355: static int
1356: pre_xr(DECL_ARGS)
1357: {
1358:
1359: n = n->child;
1360: if (NULL == n)
1361: return(0);
1.20 schwarze 1362: print_node(m, n);
1.1 schwarze 1363: n = n->next;
1364: if (NULL == n)
1365: return(0);
1.20 schwarze 1366: outflags &= ~MMAN_spc;
1367: print_word("(");
1368: print_node(m, n);
1369: print_word(")");
1.1 schwarze 1370: return(0);
1.8 schwarze 1371: }
1372:
1373: static int
1374: pre_ux(DECL_ARGS)
1375: {
1376:
1.20 schwarze 1377: print_word(manacts[n->tok].prefix);
1.8 schwarze 1378: if (NULL == n->child)
1379: return(0);
1.20 schwarze 1380: outflags &= ~MMAN_spc;
1381: print_word("\\~");
1382: outflags &= ~MMAN_spc;
1.8 schwarze 1383: return(1);
1.1 schwarze 1384: }
CVSweb