Annotation of src/usr.bin/mandoc/mdoc_man.c, Revision 1.19
1.19 ! schwarze 1: /* $Id: mdoc_man.c,v 1.18 2012/07/08 15:00:43 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.4 schwarze 40: static void post_bd(DECL_ARGS);
1.10 schwarze 41: static void post_bk(DECL_ARGS);
1.4 schwarze 42: static void post_dl(DECL_ARGS);
1.1 schwarze 43: static void post_enc(DECL_ARGS);
1.14 schwarze 44: static void post_fa(DECL_ARGS);
1.13 schwarze 45: static void post_fn(DECL_ARGS);
1.14 schwarze 46: static void post_fo(DECL_ARGS);
1.12 schwarze 47: static void post_in(DECL_ARGS);
1.11 schwarze 48: static void post_lb(DECL_ARGS);
1.4 schwarze 49: static void post_nm(DECL_ARGS);
1.1 schwarze 50: static void post_percent(DECL_ARGS);
1.4 schwarze 51: static void post_pf(DECL_ARGS);
1.3 schwarze 52: static void post_sect(DECL_ARGS);
1.4 schwarze 53: static void post_sp(DECL_ARGS);
1.15 schwarze 54: static void post_vt(DECL_ARGS);
1.3 schwarze 55: static int pre_ap(DECL_ARGS);
56: static int pre_bd(DECL_ARGS);
1.10 schwarze 57: static int pre_bk(DECL_ARGS);
1.3 schwarze 58: static int pre_br(DECL_ARGS);
1.5 schwarze 59: static int pre_bx(DECL_ARGS);
1.1 schwarze 60: static int pre_dl(DECL_ARGS);
1.4 schwarze 61: static int pre_enc(DECL_ARGS);
1.14 schwarze 62: static int pre_fa(DECL_ARGS);
1.13 schwarze 63: static int pre_fn(DECL_ARGS);
1.14 schwarze 64: static int pre_fo(DECL_ARGS);
1.12 schwarze 65: static int pre_in(DECL_ARGS);
1.1 schwarze 66: static int pre_it(DECL_ARGS);
67: static int pre_nm(DECL_ARGS);
68: static int pre_ns(DECL_ARGS);
69: static int pre_pp(DECL_ARGS);
1.9 schwarze 70: static int pre_sm(DECL_ARGS);
1.3 schwarze 71: static int pre_sp(DECL_ARGS);
1.4 schwarze 72: static int pre_sect(DECL_ARGS);
1.15 schwarze 73: static int pre_vt(DECL_ARGS);
1.5 schwarze 74: static int pre_ux(DECL_ARGS);
1.1 schwarze 75: static int pre_xr(DECL_ARGS);
1.18 schwarze 76: static void print_word(const char *);
77: static void print_offs(const char *);
1.4 schwarze 78: static void print_node(DECL_ARGS);
1.1 schwarze 79:
1.3 schwarze 80: static const struct manact manacts[MDOC_MAX + 1] = {
81: { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
82: { NULL, NULL, NULL, NULL, NULL }, /* Dd */
83: { NULL, NULL, NULL, NULL, NULL }, /* Dt */
1.5 schwarze 84: { NULL, NULL, NULL, NULL, NULL }, /* Os */
1.3 schwarze 85: { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */
86: { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */
1.1 schwarze 87: { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
1.3 schwarze 88: { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */
1.1 schwarze 89: { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
1.3 schwarze 90: { cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */
91: { NULL, NULL, NULL, NULL, NULL }, /* Ed */
92: { NULL, NULL, NULL, NULL, NULL }, /* Bl */
93: { NULL, NULL, NULL, NULL, NULL }, /* El */
1.1 schwarze 94: { NULL, pre_it, NULL, NULL, NULL }, /* _It */
1.6 schwarze 95: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ad */
1.1 schwarze 96: { NULL, NULL, NULL, NULL, NULL }, /* _An */
97: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */
1.6 schwarze 98: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cd */
1.1 schwarze 99: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */
1.6 schwarze 100: { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Dv */
101: { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Er */
102: { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Ev */
1.1 schwarze 103: { NULL, pre_enc, post_enc, "The \\fB",
104: "\\fP\nutility exits 0 on success, and >0 if an error occurs."
105: }, /* Ex */
1.14 schwarze 106: { NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */
1.1 schwarze 107: { NULL, NULL, NULL, NULL, NULL }, /* _Fd */
108: { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */
1.13 schwarze 109: { NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */
110: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ft */
1.3 schwarze 111: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ic */
1.12 schwarze 112: { NULL, pre_in, post_in, NULL, NULL }, /* In */
1.6 schwarze 113: { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Li */
1.1 schwarze 114: { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
115: { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
116: { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
1.5 schwarze 117: { NULL, NULL, NULL, NULL, NULL }, /* Ot */
118: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Pa */
1.4 schwarze 119: { NULL, pre_enc, post_enc, "The \\fB",
120: "\\fP\nfunction returns the value 0 if successful;\n"
121: "otherwise the value -1 is returned and the global\n"
122: "variable \\fIerrno\\fP is set to indicate the error."
123: }, /* Rv */
1.5 schwarze 124: { NULL, NULL, NULL, NULL, NULL }, /* St */
1.17 schwarze 125: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Va */
1.15 schwarze 126: { NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */
1.5 schwarze 127: { NULL, pre_xr, NULL, NULL, NULL }, /* Xr */
1.1 schwarze 128: { NULL, NULL, post_percent, NULL, NULL }, /* _%A */
129: { NULL, NULL, NULL, NULL, NULL }, /* _%B */
130: { NULL, NULL, post_percent, NULL, NULL }, /* _%D */
131: { NULL, NULL, NULL, NULL, NULL }, /* _%I */
132: { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */
133: { NULL, NULL, NULL, NULL, NULL }, /* _%N */
134: { NULL, NULL, NULL, NULL, NULL }, /* _%O */
135: { NULL, NULL, NULL, NULL, NULL }, /* _%P */
136: { NULL, NULL, NULL, NULL, NULL }, /* _%R */
137: { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */
138: { NULL, NULL, NULL, NULL, NULL }, /* _%V */
1.6 schwarze 139: { NULL, NULL, NULL, NULL, NULL }, /* Ac */
140: { cond_body, pre_enc, post_enc, "<", ">" }, /* Ao */
1.1 schwarze 141: { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
1.5 schwarze 142: { NULL, NULL, NULL, NULL, NULL }, /* At */
1.3 schwarze 143: { NULL, NULL, NULL, NULL, NULL }, /* Bc */
1.1 schwarze 144: { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
1.3 schwarze 145: { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
146: { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
1.5 schwarze 147: { NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */
148: { NULL, pre_bx, NULL, NULL, NULL }, /* Bx */
149: { NULL, NULL, NULL, NULL, NULL }, /* Db */
1.6 schwarze 150: { NULL, NULL, NULL, NULL, NULL }, /* Dc */
151: { cond_body, pre_enc, post_enc, "``", "''" }, /* Do */
1.1 schwarze 152: { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
153: { NULL, NULL, NULL, NULL, NULL }, /* _Ec */
154: { NULL, NULL, NULL, NULL, NULL }, /* _Ef */
1.3 schwarze 155: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Em */
1.1 schwarze 156: { NULL, NULL, NULL, NULL, NULL }, /* _Eo */
1.5 schwarze 157: { NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */
1.6 schwarze 158: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ms */
159: { NULL, NULL, NULL, NULL, NULL }, /* No */
1.1 schwarze 160: { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
1.5 schwarze 161: { NULL, pre_ux, NULL, "NetBSD", NULL }, /* Nx */
162: { NULL, pre_ux, NULL, "OpenBSD", NULL }, /* Ox */
1.3 schwarze 163: { NULL, NULL, NULL, NULL, NULL }, /* Pc */
164: { NULL, NULL, post_pf, NULL, NULL }, /* Pf */
165: { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
166: { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
1.6 schwarze 167: { NULL, NULL, NULL, NULL, NULL }, /* Qc */
1.1 schwarze 168: { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
1.6 schwarze 169: { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
170: { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
171: { NULL, NULL, NULL, NULL, NULL }, /* Re */
1.1 schwarze 172: { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */
1.6 schwarze 173: { NULL, NULL, NULL, NULL, NULL }, /* Sc */
174: { cond_body, pre_enc, post_enc, "`", "'" }, /* So */
1.1 schwarze 175: { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
1.9 schwarze 176: { NULL, pre_sm, NULL, NULL, NULL }, /* Sm */
1.3 schwarze 177: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Sx */
178: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Sy */
1.6 schwarze 179: { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Tn */
1.5 schwarze 180: { NULL, pre_ux, NULL, "UNIX", NULL }, /* Ux */
1.1 schwarze 181: { NULL, NULL, NULL, NULL, NULL }, /* _Xc */
182: { NULL, NULL, NULL, NULL, NULL }, /* _Xo */
1.14 schwarze 183: { NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */
184: { NULL, NULL, NULL, NULL, NULL }, /* Fc */
1.3 schwarze 185: { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
1.6 schwarze 186: { NULL, NULL, NULL, NULL, NULL }, /* Oc */
1.10 schwarze 187: { NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */
188: { NULL, NULL, NULL, NULL, NULL }, /* Ek */
1.5 schwarze 189: { NULL, pre_ux, NULL, "is currently in beta test.", NULL }, /* Bt */
190: { NULL, NULL, NULL, NULL, NULL }, /* Hf */
191: { NULL, NULL, NULL, NULL, NULL }, /* Fr */
192: { NULL, pre_ux, NULL, "currently under development.", NULL }, /* Ud */
1.11 schwarze 193: { NULL, NULL, post_lb, NULL, NULL }, /* Lb */
1.3 schwarze 194: { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
1.1 schwarze 195: { NULL, NULL, NULL, NULL, NULL }, /* _Lk */
196: { NULL, NULL, NULL, NULL, NULL }, /* _Mt */
1.6 schwarze 197: { cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */
198: { cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */
199: { NULL, NULL, NULL, NULL, NULL }, /* Brc */
1.1 schwarze 200: { NULL, NULL, NULL, NULL, NULL }, /* _%C */
201: { NULL, NULL, NULL, NULL, NULL }, /* _Es */
202: { NULL, NULL, NULL, NULL, NULL }, /* _En */
1.5 schwarze 203: { NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */
1.1 schwarze 204: { NULL, NULL, NULL, NULL, NULL }, /* _%Q */
1.3 schwarze 205: { NULL, pre_br, NULL, NULL, NULL }, /* br */
206: { NULL, pre_sp, post_sp, NULL, NULL }, /* sp */
1.1 schwarze 207: { NULL, NULL, NULL, NULL, NULL }, /* _%U */
208: { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
1.3 schwarze 209: { NULL, NULL, NULL, NULL, NULL }, /* ROOT */
1.1 schwarze 210: };
211:
1.18 schwarze 212: static int outflags;
213: #define MMAN_spc (1 << 0)
214: #define MMAN_nl (1 << 1)
1.19 ! schwarze 215: #define MMAN_br (1 << 2)
! 216: #define MMAN_sp (1 << 3)
! 217: #define MMAN_Sm (1 << 4)
! 218: #define MMAN_Bk (1 << 5)
1.18 schwarze 219:
1.1 schwarze 220: static void
1.18 schwarze 221: print_word(const char *s)
1.1 schwarze 222: {
1.4 schwarze 223:
1.19 ! schwarze 224: if ((MMAN_sp | MMAN_br | MMAN_nl) & outflags) {
1.4 schwarze 225: /*
226: * If we need a newline, print it now and start afresh.
227: */
1.19 ! schwarze 228: if (MMAN_sp & outflags)
! 229: printf("\n.sp\n");
! 230: else if (MMAN_br & outflags)
! 231: printf("\n.br\n");
! 232: else if (MMAN_nl & outflags)
! 233: putchar('\n');
! 234: outflags &= ~(MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc);
1.18 schwarze 235: } else if (MMAN_spc & outflags && '\0' != s[0])
1.4 schwarze 236: /*
237: * If we need a space, only print it before
238: * (1) a nonzero length word;
239: * (2) a word that is non-punctuation; and
240: * (3) if punctuation, non-terminating puncutation.
241: */
1.10 schwarze 242: if (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) {
1.18 schwarze 243: if (MMAN_Bk & outflags) {
1.10 schwarze 244: putchar('\\');
245: putchar('~');
246: } else
247: putchar(' ');
248: }
1.4 schwarze 249:
250: /*
251: * Reassign needing space if we're not following opening
252: * punctuation.
253: */
1.18 schwarze 254: if (MMAN_Sm & outflags &&
255: (('(' != s[0] && '[' != s[0]) || '\0' != s[1]))
256: outflags |= MMAN_spc;
257: else
258: outflags &= ~MMAN_spc;
1.4 schwarze 259:
1.1 schwarze 260: for ( ; *s; s++) {
261: switch (*s) {
262: case (ASCII_NBRSP):
263: printf("\\~");
264: break;
265: case (ASCII_HYPH):
266: putchar('-');
267: break;
268: default:
1.4 schwarze 269: putchar((unsigned char)*s);
1.1 schwarze 270: break;
271: }
272: }
273: }
274:
1.8 schwarze 275: static void
1.18 schwarze 276: print_offs(const char *v)
1.8 schwarze 277: {
278: char buf[24];
279: struct roffsu su;
280: size_t sz;
281:
282: if (NULL == v || '\0' == *v || 0 == strcmp(v, "left"))
283: sz = 0;
284: else if (0 == strcmp(v, "indent"))
285: sz = 6;
286: else if (0 == strcmp(v, "indent-two"))
287: sz = 12;
288: else if (a2roffsu(v, &su, SCALE_MAX)) {
1.18 schwarze 289: print_word(v);
1.8 schwarze 290: return;
291: } else
292: sz = strlen(v);
293:
294: snprintf(buf, sizeof(buf), "%ldn", sz);
1.18 schwarze 295: print_word(buf);
1.8 schwarze 296: }
297:
1.1 schwarze 298: void
1.4 schwarze 299: man_man(void *arg, const struct man *man)
300: {
301:
302: /*
303: * Dump the keep buffer.
304: * We're guaranteed by now that this exists (is non-NULL).
305: * Flush stdout afterward, just in case.
306: */
307: fputs(mparse_getkeep(man_mparse(man)), stdout);
308: fflush(stdout);
309: }
310:
311: void
1.1 schwarze 312: man_mdoc(void *arg, const struct mdoc *mdoc)
313: {
314: const struct mdoc_meta *m;
315: const struct mdoc_node *n;
316:
317: m = mdoc_meta(mdoc);
318: n = mdoc_node(mdoc);
319:
1.3 schwarze 320: printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
1.4 schwarze 321: m->title, m->msec, m->date, m->os, m->vol);
1.1 schwarze 322:
1.18 schwarze 323: outflags = MMAN_nl | MMAN_Sm;
324: print_node(m, n);
1.3 schwarze 325: putchar('\n');
1.1 schwarze 326: }
327:
328: static void
329: print_node(DECL_ARGS)
330: {
331: const struct mdoc_node *prev, *sub;
1.4 schwarze 332: const struct manact *act;
1.1 schwarze 333: int cond, do_sub;
1.4 schwarze 334:
335: /*
336: * Break the line if we were parsed subsequent the current node.
337: * This makes the page structure be more consistent.
338: */
1.1 schwarze 339: prev = n->prev ? n->prev : n->parent;
1.14 schwarze 340: if (prev && prev->line < n->line &&
341: MDOC_Fo != prev->tok && MDOC_Ns != prev->tok)
1.18 schwarze 342: outflags |= MMAN_nl;
1.1 schwarze 343:
1.4 schwarze 344: act = NULL;
1.1 schwarze 345: cond = 0;
346: do_sub = 1;
1.4 schwarze 347:
1.1 schwarze 348: if (MDOC_TEXT == n->type) {
1.4 schwarze 349: /*
350: * Make sure that we don't happen to start with a
351: * control character at the start of a line.
352: */
1.18 schwarze 353: if (MMAN_nl & outflags && ('.' == *n->string ||
1.4 schwarze 354: '\'' == *n->string)) {
1.18 schwarze 355: print_word("\\&");
356: outflags &= ~MMAN_spc;
1.3 schwarze 357: }
1.18 schwarze 358: print_word(n->string);
1.1 schwarze 359: } else {
1.4 schwarze 360: /*
361: * Conditionally run the pre-node action handler for a
362: * node.
363: */
1.1 schwarze 364: act = manacts + n->tok;
1.18 schwarze 365: cond = NULL == act->cond || (*act->cond)(m, n);
1.1 schwarze 366: if (cond && act->pre)
1.18 schwarze 367: do_sub = (*act->pre)(m, n);
1.1 schwarze 368: }
369:
1.4 schwarze 370: /*
371: * Conditionally run all child nodes.
372: * Note that this iterates over children instead of using
373: * recursion. This prevents unnecessary depth in the stack.
374: */
1.1 schwarze 375: if (do_sub)
376: for (sub = n->child; sub; sub = sub->next)
1.18 schwarze 377: print_node(m, sub);
1.1 schwarze 378:
1.4 schwarze 379: /*
380: * Lastly, conditionally run the post-node handler.
381: */
1.1 schwarze 382: if (cond && act->post)
1.18 schwarze 383: (*act->post)(m, n);
1.1 schwarze 384: }
385:
386: static int
387: cond_head(DECL_ARGS)
388: {
1.4 schwarze 389:
1.1 schwarze 390: return(MDOC_HEAD == n->type);
391: }
392:
393: static int
394: cond_body(DECL_ARGS)
395: {
1.4 schwarze 396:
1.1 schwarze 397: return(MDOC_BODY == n->type);
398: }
399:
1.4 schwarze 400: /*
401: * Output a font encoding before a node, e.g., \fR.
402: * This obviously has no trailing space.
403: */
1.1 schwarze 404: static int
405: pre_enc(DECL_ARGS)
406: {
1.4 schwarze 407: const char *prefix;
1.1 schwarze 408:
409: prefix = manacts[n->tok].prefix;
410: if (NULL == prefix)
411: return(1);
1.18 schwarze 412: print_word(prefix);
413: outflags &= ~MMAN_spc;
1.1 schwarze 414: return(1);
415: }
416:
1.4 schwarze 417: /*
418: * Output a font encoding subsequent a node, e.g., \fP.
419: */
1.1 schwarze 420: static void
421: post_enc(DECL_ARGS)
422: {
423: const char *suffix;
424:
425: suffix = manacts[n->tok].suffix;
426: if (NULL == suffix)
427: return;
1.18 schwarze 428: outflags &= ~MMAN_spc;
429: print_word(suffix);
1.7 schwarze 430: if (MDOC_Fl == n->tok && 0 == n->nchild)
1.18 schwarze 431: outflags &= ~MMAN_spc;
1.1 schwarze 432: }
433:
1.4 schwarze 434: /*
435: * Used in listings (percent = %A, e.g.).
436: * FIXME: this is incomplete.
437: * It doesn't print a nice ", and" for lists.
438: */
1.1 schwarze 439: static void
440: post_percent(DECL_ARGS)
441: {
442:
1.18 schwarze 443: post_enc(m, n);
1.1 schwarze 444: if (n->next)
1.18 schwarze 445: print_word(",");
1.1 schwarze 446: else {
1.18 schwarze 447: print_word(".");
448: outflags |= MMAN_nl;
1.1 schwarze 449: }
450: }
451:
1.4 schwarze 452: /*
453: * Print before a section header.
454: */
1.1 schwarze 455: static int
1.3 schwarze 456: pre_sect(DECL_ARGS)
457: {
458:
459: if (MDOC_HEAD != n->type)
460: return(1);
1.18 schwarze 461: outflags |= MMAN_nl;
462: print_word(manacts[n->tok].prefix);
463: print_word("\"");
464: outflags &= ~MMAN_spc;
1.3 schwarze 465: return(1);
466: }
467:
1.4 schwarze 468: /*
469: * Print subsequent a section header.
470: */
1.3 schwarze 471: static void
472: post_sect(DECL_ARGS)
473: {
474:
475: if (MDOC_HEAD != n->type)
476: return;
1.18 schwarze 477: outflags &= ~MMAN_spc;
478: print_word("\"");
479: outflags |= MMAN_nl;
1.3 schwarze 480: }
481:
482: static int
483: pre_ap(DECL_ARGS)
484: {
485:
1.18 schwarze 486: outflags &= ~MMAN_spc;
487: print_word("'");
488: outflags &= ~MMAN_spc;
1.3 schwarze 489: return(0);
490: }
491:
492: static int
493: pre_bd(DECL_ARGS)
494: {
495:
1.19 ! schwarze 496: if (0 == n->norm->Bd.comp)
! 497: outflags |= MMAN_sp;
1.3 schwarze 498: if (DISP_unfilled == n->norm->Bd.type ||
499: DISP_literal == n->norm->Bd.type) {
1.18 schwarze 500: outflags |= MMAN_nl;
501: print_word(".nf");
1.3 schwarze 502: }
1.18 schwarze 503: outflags |= MMAN_nl;
504: print_word(".RS");
505: print_offs(n->norm->Bd.offs);
506: outflags |= MMAN_nl;
1.3 schwarze 507: return(1);
508: }
509:
510: static void
511: post_bd(DECL_ARGS)
512: {
513:
1.18 schwarze 514: outflags |= MMAN_nl;
515: print_word(".RE");
1.3 schwarze 516: if (DISP_unfilled == n->norm->Bd.type ||
517: DISP_literal == n->norm->Bd.type) {
1.18 schwarze 518: outflags |= MMAN_nl;
519: print_word(".fi");
1.3 schwarze 520: }
1.18 schwarze 521: outflags |= MMAN_nl;
1.10 schwarze 522: }
523:
524: static int
525: pre_bk(DECL_ARGS)
526: {
527:
528: switch (n->type) {
529: case (MDOC_BLOCK):
530: return(1);
531: case (MDOC_BODY):
1.18 schwarze 532: outflags |= MMAN_Bk;
1.10 schwarze 533: return(1);
534: default:
535: return(0);
536: }
537: }
538:
539: static void
540: post_bk(DECL_ARGS)
541: {
542:
543: if (MDOC_BODY == n->type)
1.18 schwarze 544: outflags &= ~MMAN_Bk;
1.3 schwarze 545: }
546:
547: static int
548: pre_br(DECL_ARGS)
549: {
550:
1.19 ! schwarze 551: outflags |= MMAN_br;
1.3 schwarze 552: return(0);
553: }
554:
555: static int
1.5 schwarze 556: pre_bx(DECL_ARGS)
557: {
558:
559: n = n->child;
560: if (n) {
1.18 schwarze 561: print_word(n->string);
562: outflags &= ~MMAN_spc;
1.5 schwarze 563: n = n->next;
564: }
1.18 schwarze 565: print_word("BSD");
1.5 schwarze 566: if (NULL == n)
567: return(0);
1.18 schwarze 568: outflags &= ~MMAN_spc;
569: print_word("-");
570: outflags &= ~MMAN_spc;
571: print_word(n->string);
1.5 schwarze 572: return(0);
573: }
574:
575: static int
1.1 schwarze 576: pre_dl(DECL_ARGS)
577: {
578:
1.18 schwarze 579: outflags |= MMAN_nl;
580: print_word(".RS 6n");
581: outflags |= MMAN_nl;
1.1 schwarze 582: return(1);
583: }
584:
585: static void
586: post_dl(DECL_ARGS)
587: {
588:
1.18 schwarze 589: outflags |= MMAN_nl;
590: print_word(".RE");
591: outflags |= MMAN_nl;
1.13 schwarze 592: }
593:
594: static int
1.14 schwarze 595: pre_fa(DECL_ARGS)
596: {
597:
598: if (MDOC_Fa == n->tok)
599: n = n->child;
600:
601: while (NULL != n) {
1.18 schwarze 602: print_word("\\fI");
603: outflags &= ~MMAN_spc;
604: print_node(m, n);
605: outflags &= ~MMAN_spc;
606: print_word("\\fP");
1.14 schwarze 607: if (NULL != (n = n->next))
1.18 schwarze 608: print_word(",");
1.14 schwarze 609: }
610: return(0);
611: }
612:
613: static void
614: post_fa(DECL_ARGS)
615: {
616:
617: if (NULL != n->next && MDOC_Fa == n->next->tok)
1.18 schwarze 618: print_word(",");
1.14 schwarze 619: }
620:
621: static int
1.13 schwarze 622: pre_fn(DECL_ARGS)
623: {
624:
625: n = n->child;
626: if (NULL == n)
627: return(0);
628:
1.19 ! schwarze 629: if (MDOC_SYNPRETTY & n->flags)
! 630: outflags |= MMAN_br;
1.18 schwarze 631: print_word("\\fB");
632: outflags &= ~MMAN_spc;
633: print_node(m, n);
634: outflags &= ~MMAN_spc;
635: print_word("\\fP(");
636: outflags &= ~MMAN_spc;
637: return(pre_fa(m, n->next));
1.13 schwarze 638: }
639:
640: static void
641: post_fn(DECL_ARGS)
642: {
643:
1.18 schwarze 644: print_word(")");
1.13 schwarze 645: if (MDOC_SYNPRETTY & n->flags) {
1.18 schwarze 646: print_word(";");
1.19 ! schwarze 647: outflags |= MMAN_br;
1.14 schwarze 648: }
649: }
650:
651: static int
652: pre_fo(DECL_ARGS)
653: {
654:
655: switch (n->type) {
656: case (MDOC_HEAD):
1.19 ! schwarze 657: if (MDOC_SYNPRETTY & n->flags)
! 658: outflags |= MMAN_br;
1.18 schwarze 659: print_word("\\fB");
660: outflags &= ~MMAN_spc;
1.14 schwarze 661: break;
662: case (MDOC_BODY):
1.18 schwarze 663: outflags &= ~MMAN_spc;
664: print_word("(");
665: outflags &= ~MMAN_spc;
1.14 schwarze 666: break;
667: default:
668: break;
669: }
670: return(1);
671: }
672:
673: static void
674: post_fo(DECL_ARGS)
675: {
676:
677: switch (n->type) {
678: case (MDOC_HEAD):
1.18 schwarze 679: outflags &= ~MMAN_spc;
680: print_word("\\fP");
1.14 schwarze 681: break;
682: case (MDOC_BODY):
1.18 schwarze 683: post_fn(m, n);
1.14 schwarze 684: break;
685: default:
686: break;
1.13 schwarze 687: }
1.12 schwarze 688: }
689:
690: static int
691: pre_in(DECL_ARGS)
692: {
693:
694: if (MDOC_SYNPRETTY & n->flags) {
1.19 ! schwarze 695: outflags |= MMAN_br;
1.18 schwarze 696: print_word("\\fB#include <");
1.12 schwarze 697: } else
1.18 schwarze 698: print_word("<\\fI");
699: outflags &= ~MMAN_spc;
1.12 schwarze 700: return(1);
701: }
702:
703: static void
704: post_in(DECL_ARGS)
705: {
706:
1.18 schwarze 707: outflags &= ~MMAN_spc;
1.12 schwarze 708: if (MDOC_SYNPRETTY & n->flags) {
1.18 schwarze 709: print_word(">\\fP");
1.19 ! schwarze 710: outflags |= MMAN_br;
1.12 schwarze 711: } else
1.18 schwarze 712: print_word("\\fP>");
1.1 schwarze 713: }
714:
715: static int
716: pre_it(DECL_ARGS)
717: {
718: const struct mdoc_node *bln;
719:
720: if (MDOC_HEAD == n->type) {
1.18 schwarze 721: outflags |= MMAN_nl;
722: print_word(".TP");
1.1 schwarze 723: bln = n->parent->parent->prev;
1.3 schwarze 724: switch (bln->norm->Bl.type) {
725: case (LIST_bullet):
1.18 schwarze 726: print_word("4n");
727: outflags |= MMAN_nl;
728: print_word("\\fBo\\fP");
1.3 schwarze 729: break;
730: default:
731: if (bln->norm->Bl.width)
1.18 schwarze 732: print_word(bln->norm->Bl.width);
1.3 schwarze 733: break;
734: }
1.18 schwarze 735: outflags |= MMAN_nl;
1.1 schwarze 736: }
737: return(1);
1.11 schwarze 738: }
739:
740: static void
741: post_lb(DECL_ARGS)
742: {
743:
1.19 ! schwarze 744: if (SEC_LIBRARY == n->sec)
! 745: outflags |= MMAN_br;
1.1 schwarze 746: }
747:
748: static int
749: pre_nm(DECL_ARGS)
750: {
751:
752: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
753: return(1);
1.19 ! schwarze 754: if (MDOC_SYNPRETTY & n->flags)
! 755: outflags |= MMAN_br;
1.18 schwarze 756: print_word("\\fB");
757: outflags &= ~MMAN_spc;
1.1 schwarze 758: if (NULL == n->child)
1.18 schwarze 759: print_word(m->name);
1.1 schwarze 760: return(1);
761: }
762:
763: static void
764: post_nm(DECL_ARGS)
765: {
766:
767: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
768: return;
1.18 schwarze 769: outflags &= ~MMAN_spc;
770: print_word("\\fP");
1.1 schwarze 771: }
772:
773: static int
774: pre_ns(DECL_ARGS)
775: {
776:
1.18 schwarze 777: outflags &= ~MMAN_spc;
1.1 schwarze 778: return(0);
779: }
780:
1.3 schwarze 781: static void
782: post_pf(DECL_ARGS)
783: {
784:
1.18 schwarze 785: outflags &= ~MMAN_spc;
1.3 schwarze 786: }
787:
1.1 schwarze 788: static int
789: pre_pp(DECL_ARGS)
790: {
791:
1.18 schwarze 792: outflags |= MMAN_nl;
1.1 schwarze 793: if (MDOC_It == n->parent->tok)
1.18 schwarze 794: print_word(".sp");
1.1 schwarze 795: else
1.18 schwarze 796: print_word(".PP");
797: outflags |= MMAN_nl;
1.7 schwarze 798: return(MDOC_Rs == n->tok);
1.9 schwarze 799: }
800:
801: static int
802: pre_sm(DECL_ARGS)
803: {
804:
805: assert(n->child && MDOC_TEXT == n->child->type);
806: if (0 == strcmp("on", n->child->string))
1.18 schwarze 807: outflags |= MMAN_Sm;
1.9 schwarze 808: else
1.18 schwarze 809: outflags &= ~MMAN_Sm;
1.9 schwarze 810: return(0);
1.1 schwarze 811: }
812:
813: static int
1.3 schwarze 814: pre_sp(DECL_ARGS)
1.1 schwarze 815: {
816:
1.18 schwarze 817: outflags |= MMAN_nl;
818: print_word(".sp");
1.1 schwarze 819: return(1);
820: }
821:
822: static void
1.3 schwarze 823: post_sp(DECL_ARGS)
1.1 schwarze 824: {
825:
1.18 schwarze 826: outflags |= MMAN_nl;
1.15 schwarze 827: }
828:
829: static int
830: pre_vt(DECL_ARGS)
831: {
832:
833: if (MDOC_SYNPRETTY & n->flags) {
1.16 schwarze 834: switch (n->type) {
835: case (MDOC_BLOCK):
836: return(1);
837: case (MDOC_BODY):
838: break;
839: default:
840: return(0);
841: }
1.19 ! schwarze 842: outflags |= MMAN_br;
1.15 schwarze 843: }
1.18 schwarze 844: print_word("\\fI");
845: outflags &= ~MMAN_spc;
1.15 schwarze 846: return(1);
847: }
848:
849: static void
850: post_vt(DECL_ARGS)
851: {
1.16 schwarze 852:
1.17 schwarze 853: if (MDOC_SYNPRETTY & n->flags && MDOC_BODY != n->type)
1.16 schwarze 854: return;
1.15 schwarze 855:
1.18 schwarze 856: outflags &= ~MMAN_spc;
857: print_word("\\fP");
1.19 ! schwarze 858: if (MDOC_SYNPRETTY & n->flags)
! 859: outflags |= MMAN_br;
1.1 schwarze 860: }
861:
862: static int
863: pre_xr(DECL_ARGS)
864: {
865:
866: n = n->child;
867: if (NULL == n)
868: return(0);
1.18 schwarze 869: print_node(m, n);
1.1 schwarze 870: n = n->next;
871: if (NULL == n)
872: return(0);
1.18 schwarze 873: outflags &= ~MMAN_spc;
874: print_word("(");
875: print_node(m, n);
876: print_word(")");
1.1 schwarze 877: return(0);
1.5 schwarze 878: }
879:
880: static int
881: pre_ux(DECL_ARGS)
882: {
883:
1.18 schwarze 884: print_word(manacts[n->tok].prefix);
1.5 schwarze 885: if (NULL == n->child)
886: return(0);
1.18 schwarze 887: outflags &= ~MMAN_spc;
888: print_word("\\~");
889: outflags &= ~MMAN_spc;
1.5 schwarze 890: return(1);
1.1 schwarze 891: }