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