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