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