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