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