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