[BACK]Return to mdoc_man.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/mdoc_man.c, Revision 1.11

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

CVSweb