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