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