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

Annotation of mandoc/term.c, Revision 1.10

1.10    ! kristaps    1: /* $Id: termact.c,v 1.6 2009/02/22 19:23:48 kristaps Exp $ */
1.1       kristaps    2: /*
1.10    ! kristaps    3:  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1       kristaps    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
                      7:  * above copyright notice and this permission notice appear in all
                      8:  * copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
                     11:  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
                     12:  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
                     13:  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     14:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     15:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
                     16:  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     17:  * PERFORMANCE OF THIS SOFTWARE.
                     18:  */
                     19: #include <assert.h>
                     20: #include <stdlib.h>
                     21: #include <string.h>
                     22:
1.10    ! kristaps   23: #include "term.h"
        !            24:
        !            25: #define        INDENT            4
        !            26:
        !            27: /*
        !            28:  * Performs actions on nodes of the abstract syntax tree.  Both pre- and
        !            29:  * post-fix operations are defined here.
        !            30:  */
        !            31:
        !            32: /* FIXME: indent/tab. */
        !            33:
        !            34: #define        TTYPE_PROG        0
        !            35: #define        TTYPE_CMD_FLAG    1
        !            36: #define        TTYPE_CMD_ARG     2
        !            37: #define        TTYPE_SECTION     3
        !            38: #define        TTYPE_FUNC_DECL   4
        !            39: #define        TTYPE_VAR_DECL    5
        !            40: #define        TTYPE_FUNC_TYPE   6
        !            41: #define        TTYPE_FUNC_NAME   7
        !            42: #define        TTYPE_FUNC_ARG    8
        !            43: #define        TTYPE_LINK        9
        !            44: #define        TTYPE_SSECTION    10
        !            45: #define        TTYPE_FILE        11
        !            46: #define        TTYPE_NMAX        12
        !            47:
        !            48: /*
        !            49:  * These define "styles" for element types, like command arguments or
        !            50:  * executable names.  This is useful when multiple macros must decorate
        !            51:  * the same thing (like .Ex -std cmd and .Nm cmd).
        !            52:  */
        !            53:
        !            54: const  int ttypes[TTYPE_NMAX] = {
        !            55:        TERMP_BOLD,             /* TTYPE_PROG */
        !            56:        TERMP_BOLD,             /* TTYPE_CMD_FLAG */
        !            57:        TERMP_UNDERLINE,        /* TTYPE_CMD_ARG */
        !            58:        TERMP_BOLD,             /* TTYPE_SECTION */
        !            59:        TERMP_BOLD,             /* TTYPE_FUNC_DECL */
        !            60:        TERMP_UNDERLINE,        /* TTYPE_VAR_DECL */
        !            61:        TERMP_UNDERLINE,        /* TTYPE_FUNC_TYPE */
        !            62:        TERMP_BOLD,             /* TTYPE_FUNC_NAME */
        !            63:        TERMP_UNDERLINE,        /* TTYPE_FUNC_ARG */
        !            64:        TERMP_UNDERLINE,        /* TTYPE_LINK */
        !            65:        TERMP_BOLD,             /* TTYPE_SSECTION */
        !            66:        TERMP_UNDERLINE         /* TTYPE_FILE */
        !            67: };
1.7       kristaps   68:
1.10    ! kristaps   69: static int               arg_hasattr(int, size_t,
        !            70:                                const struct mdoc_arg *);
        !            71: static int               arg_getattr(int, size_t,
        !            72:                                const struct mdoc_arg *);
        !            73: static size_t            arg_offset(const char *);
        !            74:
        !            75: /*
        !            76:  * What follows describes prefix and postfix operations for the abstract
        !            77:  * syntax tree descent.
        !            78:  */
1.1       kristaps   79:
1.10    ! kristaps   80: #define        DECL_ARGS \
        !            81:        struct termp *p, \
        !            82:        const struct mdoc_meta *meta, \
        !            83:        const struct mdoc_node *node
        !            84:
        !            85: #define        DECL_PRE(name) \
        !            86: static int               name##_pre(DECL_ARGS)
        !            87: #define        DECL_POST(name) \
        !            88: static void              name##_post(DECL_ARGS)
        !            89: #define        DECL_PREPOST(name) \
        !            90: DECL_PRE(name); \
        !            91: DECL_POST(name);
        !            92:
        !            93: DECL_PREPOST(termp_aq);
        !            94: DECL_PREPOST(termp_ar);
        !            95: DECL_PREPOST(termp_d1);
        !            96: DECL_PREPOST(termp_dq);
        !            97: DECL_PREPOST(termp_fa);
        !            98: DECL_PREPOST(termp_fd);
        !            99: DECL_PREPOST(termp_fl);
        !           100: DECL_PREPOST(termp_fn);
        !           101: DECL_PREPOST(termp_ft);
        !           102: DECL_PREPOST(termp_it);
        !           103: DECL_PREPOST(termp_nm);
        !           104: DECL_PREPOST(termp_op);
        !           105: DECL_PREPOST(termp_pa);
        !           106: DECL_PREPOST(termp_pf);
        !           107: DECL_PREPOST(termp_qq);
        !           108: DECL_PREPOST(termp_sh);
        !           109: DECL_PREPOST(termp_ss);
        !           110: DECL_PREPOST(termp_sq);
        !           111: DECL_PREPOST(termp_sx);
        !           112: DECL_PREPOST(termp_va);
        !           113: DECL_PREPOST(termp_vt);
        !           114:
        !           115: DECL_PRE(termp_bd);
        !           116: DECL_PRE(termp_bx);
        !           117: DECL_PRE(termp_ex);
        !           118: DECL_PRE(termp_nd);
        !           119: DECL_PRE(termp_ns);
        !           120: DECL_PRE(termp_nx);
        !           121: DECL_PRE(termp_ox);
        !           122: DECL_PRE(termp_pp);
        !           123: DECL_PRE(termp_ud);
        !           124: DECL_PRE(termp_xr);
        !           125:
        !           126: DECL_POST(termp_bl);
        !           127:
        !           128: const  struct termact __termacts[MDOC_MAX] = {
        !           129:        { NULL, NULL }, /* \" */
        !           130:        { NULL, NULL }, /* Dd */
        !           131:        { NULL, NULL }, /* Dt */
        !           132:        { NULL, NULL }, /* Os */
        !           133:        { termp_sh_pre, termp_sh_post }, /* Sh */
        !           134:        { termp_ss_pre, termp_ss_post }, /* Ss */
        !           135:        { termp_pp_pre, NULL }, /* Pp */
        !           136:        { termp_d1_pre, termp_d1_post }, /* D1 */
        !           137:        { NULL, NULL }, /* Dl */
        !           138:        { termp_bd_pre, NULL }, /* Bd */
        !           139:        { NULL, NULL }, /* Ed */
        !           140:        { NULL, termp_bl_post }, /* Bl */
        !           141:        { NULL, NULL }, /* El */
        !           142:        { termp_it_pre, termp_it_post }, /* It */
        !           143:        { NULL, NULL }, /* Ad */
        !           144:        { NULL, NULL }, /* An */
        !           145:        { termp_ar_pre, termp_ar_post }, /* Ar */
        !           146:        { NULL, NULL }, /* Cd */
        !           147:        { NULL, NULL }, /* Cm */
        !           148:        { NULL, NULL }, /* Dv */
        !           149:        { NULL, NULL }, /* Er */
        !           150:        { NULL, NULL }, /* Ev */
        !           151:        { termp_ex_pre, NULL }, /* Ex */
        !           152:        { termp_fa_pre, termp_fa_post }, /* Fa */
        !           153:        { termp_fd_pre, termp_fd_post }, /* Fd */
        !           154:        { termp_fl_pre, termp_fl_post }, /* Fl */
        !           155:        { termp_fn_pre, termp_fn_post }, /* Fn */
        !           156:        { termp_ft_pre, termp_ft_post }, /* Ft */
        !           157:        { NULL, NULL }, /* Ic */
        !           158:        { NULL, NULL }, /* In */
        !           159:        { NULL, NULL }, /* Li */
        !           160:        { termp_nd_pre, NULL }, /* Nd */
        !           161:        { termp_nm_pre, termp_nm_post }, /* Nm */
        !           162:        { termp_op_pre, termp_op_post }, /* Op */
        !           163:        { NULL, NULL }, /* Ot */
        !           164:        { termp_pa_pre, termp_pa_post }, /* Pa */
        !           165:        { NULL, NULL }, /* Rv */
        !           166:        { NULL, NULL }, /* St */
        !           167:        { termp_va_pre, termp_va_post }, /* Va */
        !           168:        { termp_vt_pre, termp_vt_post }, /* Vt */
        !           169:        { termp_xr_pre, NULL }, /* Xr */
        !           170:        { NULL, NULL }, /* %A */
        !           171:        { NULL, NULL }, /* %B */
        !           172:        { NULL, NULL }, /* %D */
        !           173:        { NULL, NULL }, /* %I */
        !           174:        { NULL, NULL }, /* %J */
        !           175:        { NULL, NULL }, /* %N */
        !           176:        { NULL, NULL }, /* %O */
        !           177:        { NULL, NULL }, /* %P */
        !           178:        { NULL, NULL }, /* %R */
        !           179:        { NULL, NULL }, /* %T */
        !           180:        { NULL, NULL }, /* %V */
        !           181:        { NULL, NULL }, /* Ac */
        !           182:        { NULL, NULL }, /* Ao */
        !           183:        { termp_aq_pre, termp_aq_post }, /* Aq */
        !           184:        { NULL, NULL }, /* At */
        !           185:        { NULL, NULL }, /* Bc */
        !           186:        { NULL, NULL }, /* Bf */
        !           187:        { NULL, NULL }, /* Bo */
        !           188:        { NULL, NULL }, /* Bq */
        !           189:        { NULL, NULL }, /* Bsx */
        !           190:        { termp_bx_pre, NULL }, /* Bx */
        !           191:        { NULL, NULL }, /* Db */
        !           192:        { NULL, NULL }, /* Dc */
        !           193:        { NULL, NULL }, /* Do */
        !           194:        { termp_dq_pre, termp_dq_post }, /* Dq */
        !           195:        { NULL, NULL }, /* Ec */
        !           196:        { NULL, NULL }, /* Ef */
        !           197:        { NULL, NULL }, /* Em */
        !           198:        { NULL, NULL }, /* Eo */
        !           199:        { NULL, NULL }, /* Fx */
        !           200:        { NULL, NULL }, /* Ms */
        !           201:        { NULL, NULL }, /* No */
        !           202:        { termp_ns_pre, NULL }, /* Ns */
        !           203:        { termp_nx_pre, NULL }, /* Nx */
        !           204:        { termp_ox_pre, NULL }, /* Ox */
        !           205:        { NULL, NULL }, /* Pc */
        !           206:        { termp_pf_pre, termp_pf_post }, /* Pf */
        !           207:        { NULL, NULL }, /* Po */
        !           208:        { NULL, NULL }, /* Pq */
        !           209:        { NULL, NULL }, /* Qc */
        !           210:        { NULL, NULL }, /* Ql */
        !           211:        { NULL, NULL }, /* Qo */
        !           212:        { termp_qq_pre, termp_qq_post }, /* Qq */
        !           213:        { NULL, NULL }, /* Re */
        !           214:        { NULL, NULL }, /* Rs */
        !           215:        { NULL, NULL }, /* Sc */
        !           216:        { NULL, NULL }, /* So */
        !           217:        { termp_sq_pre, termp_sq_post }, /* Sq */
        !           218:        { NULL, NULL }, /* Sm */
        !           219:        { termp_sx_pre, termp_sx_post }, /* Sx */
        !           220:        { NULL, NULL }, /* Sy */
        !           221:        { NULL, NULL }, /* Tn */
        !           222:        { NULL, NULL }, /* Ux */
        !           223:        { NULL, NULL }, /* Xc */
        !           224:        { NULL, NULL }, /* Xo */
        !           225:        { NULL, NULL }, /* Fo */
        !           226:        { NULL, NULL }, /* Fc */
        !           227:        { NULL, NULL }, /* Oo */
        !           228:        { NULL, NULL }, /* Oc */
        !           229:        { NULL, NULL }, /* Bk */
        !           230:        { NULL, NULL }, /* Ek */
        !           231:        { NULL, NULL }, /* Bt */
        !           232:        { NULL, NULL }, /* Hf */
        !           233:        { NULL, NULL }, /* Fr */
        !           234:        { termp_ud_pre, NULL }, /* Ud */
1.2       kristaps  235: };
                    236:
1.10    ! kristaps  237: const struct termact *termacts = __termacts;
        !           238:
        !           239:
        !           240: static size_t
        !           241: arg_offset(const char *v)
        !           242: {
        !           243:        if (0 == strcmp(v, "indent"))
        !           244:                return(INDENT);
        !           245:        if (0 == strcmp(v, "indent-two"))
        !           246:                return(INDENT * 2);
        !           247:
        !           248:        /* TODO */
        !           249:        return(0);
        !           250: }
        !           251:
1.3       kristaps  252:
1.10    ! kristaps  253: static int
        !           254: arg_hasattr(int arg, size_t argc, const struct mdoc_arg *argv)
1.2       kristaps  255: {
                    256:
1.10    ! kristaps  257:        return(-1 != arg_getattr(arg, argc, argv));
        !           258: }
        !           259:
        !           260:
        !           261: static int
        !           262: arg_getattr(int arg, size_t argc, const struct mdoc_arg *argv)
        !           263: {
        !           264:        int              i;
        !           265:
        !           266:        for (i = 0; i < (int)argc; i++)
        !           267:                if (argv[i].arg == arg)
        !           268:                        return(i);
        !           269:        return(-1);
        !           270: }
        !           271:
        !           272:
        !           273: /* ARGSUSED */
        !           274: static int
        !           275: termp_dq_pre(DECL_ARGS)
        !           276: {
        !           277:
        !           278:        if (MDOC_BODY != node->type)
        !           279:                return(1);
        !           280:
        !           281:        word(p, "``");
        !           282:        p->flags |= TERMP_NOSPACE;
        !           283:        return(1);
        !           284: }
        !           285:
        !           286:
        !           287: /* ARGSUSED */
        !           288: static void
        !           289: termp_dq_post(DECL_ARGS)
        !           290: {
        !           291:
        !           292:        if (MDOC_BODY != node->type)
        !           293:                return;
1.3       kristaps  294:
1.10    ! kristaps  295:        p->flags |= TERMP_NOSPACE;
        !           296:        word(p, "''");
        !           297: }
1.2       kristaps  298:
1.3       kristaps  299:
1.10    ! kristaps  300: /* ARGSUSED */
        !           301: static void
        !           302: termp_it_post(DECL_ARGS)
        !           303: {
        !           304:        const struct mdoc_node *n, *it;
        !           305:        const struct mdoc_block *bl;
        !           306:        int              i;
        !           307:        size_t           width;
1.2       kristaps  308:
1.8       kristaps  309:        /*
1.10    ! kristaps  310:         * This (and termp_it_pre()) are the most complicated functions
        !           311:         * here.  They must account for a considerable number of
        !           312:         * switches that completely change the output behaviour, like
        !           313:         * -tag versus -column.  Yech.
1.8       kristaps  314:         */
1.10    ! kristaps  315:
        !           316:        switch (node->type) {
        !           317:        case (MDOC_BODY):
        !           318:                /* FALLTHROUGH */
        !           319:        case (MDOC_HEAD):
        !           320:                break;
        !           321:        default:
1.8       kristaps  322:                return;
                    323:        }
                    324:
1.10    ! kristaps  325:        it = node->parent;
        !           326:        assert(MDOC_BLOCK == it->type);
        !           327:        assert(MDOC_It == it->tok);
        !           328:
        !           329:        n = it->parent;
        !           330:        assert(MDOC_BODY == n->type);
        !           331:        assert(MDOC_Bl == n->tok);
        !           332:        n = n->parent;
        !           333:        bl = &n->data.block;
        !           334:
        !           335:        /* If `-tag', adjust our margins accordingly. */
        !           336:
        !           337:        if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
        !           338:                i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
        !           339:                assert(i >= 0);
        !           340:                assert(1 == bl->argv[i].sz);
        !           341:                width = strlen(*bl->argv[i].value); /* XXX */
        !           342:
        !           343:                if (MDOC_HEAD == node->type) {
        !           344:                        flushln(p);
        !           345:                        /* FIXME: nested lists. */
        !           346:                        p->rmargin = p->maxrmargin;
        !           347:                        p->flags &= ~TERMP_NOBREAK;
        !           348:                } else {
        !           349:                        flushln(p);
        !           350:                        p->offset -= width + 1;
        !           351:                        p->flags &= ~TERMP_NOLPAD;
1.2       kristaps  352:                }
1.10    ! kristaps  353:                return;
        !           354:        }
1.2       kristaps  355:
1.10    ! kristaps  356:        if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
        !           357:                i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
        !           358:                width = 0;
        !           359:                if (i >= 0) {
        !           360:                        assert(1 == bl->argv[i].sz);
        !           361:                        width = arg_offset(*bl->argv[i].value);
1.3       kristaps  362:                }
                    363:
1.10    ! kristaps  364:                flushln(p);
        !           365:                p->offset -= width;
        !           366:                return;
1.2       kristaps  367:        }
1.10    ! kristaps  368: }
        !           369:
        !           370:
        !           371: /* ARGSUSED */
        !           372: static int
        !           373: termp_it_pre(DECL_ARGS)
        !           374: {
        !           375:        const struct mdoc_node *n, *it;
        !           376:        const struct mdoc_block *bl;
        !           377:        int              i;
        !           378:        size_t           width;
1.2       kristaps  379:
1.3       kristaps  380:        /*
1.10    ! kristaps  381:         * Also see termp_it_post() for general comments.
1.3       kristaps  382:         */
                    383:
1.10    ! kristaps  384:        switch (node->type) {
        !           385:        case (MDOC_BODY):
        !           386:                /* FALLTHROUGH */
        !           387:        case (MDOC_HEAD):
        !           388:                it = node->parent;
        !           389:                break;
        !           390:        case (MDOC_BLOCK):
        !           391:                it = node;
        !           392:                break;
        !           393:        default:
        !           394:                return(1);
        !           395:        }
        !           396:
        !           397:        assert(MDOC_BLOCK == it->type);
        !           398:        assert(MDOC_It == it->tok);
        !           399:
        !           400:        n = it->parent;
        !           401:        assert(MDOC_BODY == n->type);
        !           402:        assert(MDOC_Bl == n->tok);
        !           403:        n = n->parent;
        !           404:        bl = &n->data.block;
        !           405:
        !           406:        /* If `-compact', don't assert vertical space. */
        !           407:
        !           408:        if (MDOC_BLOCK == node->type) {
        !           409:                if (arg_hasattr(MDOC_Compact, bl->argc, bl->argv))
        !           410:                        newln(p);
        !           411:                else
        !           412:                        vspace(p);
        !           413:                return(1);
        !           414:        }
        !           415:
        !           416:        assert(MDOC_HEAD == node->type
        !           417:                        || MDOC_BODY == node->type);
        !           418:
        !           419:        /* If `-tag', adjust our margins accordingly. */
        !           420:
        !           421:        if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
        !           422:                i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
        !           423:                assert(i >= 0); /* XXX */
        !           424:                assert(1 == bl->argv[i].sz);
        !           425:                width = strlen(*bl->argv[i].value); /* XXX */
        !           426:
        !           427:                /* FIXME: nested lists. */
        !           428:
        !           429:                if (MDOC_HEAD == node->type) {
        !           430:                        p->flags |= TERMP_NOBREAK;
        !           431:                        p->flags |= TERMP_NOSPACE;
        !           432:                        p->rmargin = p->offset + width;
        !           433:                } else {
        !           434:                        p->flags |= TERMP_NOSPACE;
        !           435:                        p->flags |= TERMP_NOLPAD;
        !           436:                        p->offset += width + 1;
        !           437:                }
        !           438:                return(1);
        !           439:        }
        !           440:
        !           441:        /* If `-ohang', adjust left-margin. */
        !           442:
        !           443:        if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
        !           444:                width = 0;
        !           445:                i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
        !           446:                if (i >= 0) {
        !           447:                        assert(1 == bl->argv[i].sz);
        !           448:                        width = arg_offset(*bl->argv[i].value);
        !           449:                }
        !           450:
        !           451:                p->flags |= TERMP_NOSPACE;
        !           452:                p->offset += width;
        !           453:                return(1);
        !           454:        }
1.3       kristaps  455:
1.10    ! kristaps  456:        return(1);
1.2       kristaps  457: }
                    458:
                    459:
1.10    ! kristaps  460: /* ARGSUSED */
        !           461: static void
        !           462: termp_nm_post(DECL_ARGS)
        !           463: {
        !           464:
        !           465:        p->flags &= ~ttypes[TTYPE_PROG];
        !           466: }
        !           467:
        !           468:
        !           469: /* ARGSUSED */
        !           470: static void
        !           471: termp_fl_post(DECL_ARGS)
        !           472: {
        !           473:
        !           474:        p->flags &= ~ttypes[TTYPE_CMD_FLAG];
        !           475: }
        !           476:
        !           477:
        !           478: /* ARGSUSED */
        !           479: static int
        !           480: termp_ar_pre(DECL_ARGS)
        !           481: {
        !           482:
        !           483:        p->flags |= ttypes[TTYPE_CMD_ARG];
        !           484:        if (NULL == node->child)
        !           485:                word(p, "...");
        !           486:        return(1);
        !           487: }
        !           488:
        !           489:
        !           490: /* ARGSUSED */
        !           491: static int
        !           492: termp_nm_pre(DECL_ARGS)
        !           493: {
        !           494:
        !           495:        p->flags |= ttypes[TTYPE_PROG];
        !           496:        if (NULL == node->child)
        !           497:                word(p, meta->name);
        !           498:        return(1);
        !           499: }
        !           500:
        !           501:
        !           502: /* ARGSUSED */
        !           503: static int
        !           504: termp_ns_pre(DECL_ARGS)
1.2       kristaps  505: {
                    506:
                    507:        p->flags |= TERMP_NOSPACE;
1.10    ! kristaps  508:        return(1);
        !           509: }
        !           510:
        !           511:
        !           512: /* ARGSUSED */
        !           513: static int
        !           514: termp_pp_pre(DECL_ARGS)
        !           515: {
        !           516:
        !           517:        vspace(p);
        !           518:        return(1);
        !           519: }
        !           520:
        !           521:
        !           522: /* ARGSUSED */
        !           523: static void
        !           524: termp_ar_post(DECL_ARGS)
        !           525: {
        !           526:
        !           527:        p->flags &= ~ttypes[TTYPE_CMD_ARG];
        !           528: }
        !           529:
        !           530:
        !           531: /* ARGSUSED */
        !           532: static int
        !           533: termp_ex_pre(DECL_ARGS)
        !           534: {
        !           535:        int              i;
        !           536:
        !           537:        i = arg_getattr(MDOC_Std, node->data.elem.argc,
        !           538:                        node->data.elem.argv);
        !           539:        assert(i >= 0);
        !           540:
        !           541:        word(p, "The");
        !           542:        p->flags |= ttypes[TTYPE_PROG];
        !           543:        word(p, *node->data.elem.argv[i].value);
        !           544:        p->flags &= ~ttypes[TTYPE_PROG];
        !           545:                word(p, "utility exits 0 on success, and >0 if an error occurs.");
        !           546:
        !           547:        return(1);
        !           548: }
        !           549:
        !           550:
        !           551: /* ARGSUSED */
        !           552: static int
        !           553: termp_nd_pre(DECL_ARGS)
        !           554: {
        !           555:
        !           556:        word(p, "\\-");
        !           557:        return(1);
        !           558: }
        !           559:
        !           560:
        !           561: /* ARGSUSED */
        !           562: static void
        !           563: termp_bl_post(DECL_ARGS)
        !           564: {
        !           565:
        !           566:        if (MDOC_BLOCK == node->type)
        !           567:                newln(p);
        !           568: }
        !           569:
        !           570:
        !           571: /* ARGSUSED */
        !           572: static void
        !           573: termp_op_post(DECL_ARGS)
        !           574: {
        !           575:
        !           576:        if (MDOC_BODY != node->type)
1.2       kristaps  577:                return;
1.10    ! kristaps  578:        p->flags |= TERMP_NOSPACE;
        !           579:        word(p, "\\(rB");
        !           580: }
        !           581:
        !           582:
        !           583: /* ARGSUSED */
        !           584: static void
        !           585: termp_sh_post(DECL_ARGS)
        !           586: {
        !           587:
        !           588:        switch (node->type) {
        !           589:        case (MDOC_HEAD):
        !           590:                p->flags &= ~ttypes[TTYPE_SECTION];
        !           591:                newln(p);
        !           592:                break;
        !           593:        case (MDOC_BODY):
        !           594:                newln(p);
        !           595:                p->offset = 0;
        !           596:                break;
        !           597:        default:
        !           598:                break;
        !           599:        }
        !           600: }
        !           601:
        !           602:
        !           603: /* ARGSUSED */
        !           604: static int
        !           605: termp_xr_pre(DECL_ARGS)
        !           606: {
        !           607:        const struct mdoc_node *n;
        !           608:
        !           609:        n = node->child;
        !           610:        assert(n);
        !           611:
        !           612:        assert(MDOC_TEXT == n->type);
        !           613:        word(p, n->data.text.string);
        !           614:
        !           615:        if (NULL == (n = n->next))
        !           616:                return(0);
        !           617:
        !           618:        assert(MDOC_TEXT == n->type);
        !           619:        p->flags |= TERMP_NOSPACE;
        !           620:        word(p, "(");
        !           621:        p->flags |= TERMP_NOSPACE;
        !           622:        word(p, n->data.text.string);
        !           623:        p->flags |= TERMP_NOSPACE;
        !           624:        word(p, ")");
        !           625:
        !           626:        return(0);
1.2       kristaps  627: }
                    628:
                    629:
1.10    ! kristaps  630: /* ARGSUSED */
        !           631: static int
        !           632: termp_vt_pre(DECL_ARGS)
1.2       kristaps  633: {
                    634:
1.10    ! kristaps  635:        /* FIXME: this can be "type name". */
        !           636:        p->flags |= ttypes[TTYPE_VAR_DECL];
        !           637:        return(1);
1.2       kristaps  638: }
                    639:
                    640:
1.10    ! kristaps  641: /* ARGSUSED */
1.2       kristaps  642: static void
1.10    ! kristaps  643: termp_vt_post(DECL_ARGS)
        !           644: {
        !           645:
        !           646:        p->flags &= ~ttypes[TTYPE_VAR_DECL];
        !           647:        if (node->sec == SEC_SYNOPSIS)
        !           648:                vspace(p);
        !           649: }
        !           650:
        !           651:
        !           652: /* ARGSUSED */
        !           653: static int
        !           654: termp_fd_pre(DECL_ARGS)
1.2       kristaps  655: {
                    656:
1.10    ! kristaps  657:        /*
        !           658:         * FIXME: this naming is bad.  This value is used, in general,
        !           659:         * for the #include header or other preprocessor statement.
        !           660:         */
        !           661:        p->flags |= ttypes[TTYPE_FUNC_DECL];
        !           662:        return(1);
1.2       kristaps  663: }
                    664:
                    665:
1.10    ! kristaps  666: /* ARGSUSED */
1.2       kristaps  667: static void
1.10    ! kristaps  668: termp_fd_post(DECL_ARGS)
1.2       kristaps  669: {
                    670:
1.10    ! kristaps  671:        p->flags &= ~ttypes[TTYPE_FUNC_DECL];
        !           672:        if (node->sec == SEC_SYNOPSIS)
        !           673:                vspace(p);
        !           674:
        !           675: }
        !           676:
        !           677:
        !           678: /* ARGSUSED */
        !           679: static int
        !           680: termp_sh_pre(DECL_ARGS)
        !           681: {
1.2       kristaps  682:
1.10    ! kristaps  683:        switch (node->type) {
        !           684:        case (MDOC_HEAD):
        !           685:                vspace(p);
        !           686:                p->flags |= ttypes[TTYPE_SECTION];
1.2       kristaps  687:                break;
1.10    ! kristaps  688:        case (MDOC_BODY):
        !           689:                p->offset = INDENT;
1.2       kristaps  690:                break;
1.10    ! kristaps  691:        default:
        !           692:                break;
        !           693:        }
        !           694:        return(1);
        !           695: }
        !           696:
        !           697:
        !           698: /* ARGSUSED */
        !           699: static int
        !           700: termp_op_pre(DECL_ARGS)
        !           701: {
        !           702:
        !           703:        switch (node->type) {
        !           704:        case (MDOC_BODY):
        !           705:                word(p, "\\(lB");
        !           706:                p->flags |= TERMP_NOSPACE;
1.2       kristaps  707:                break;
                    708:        default:
1.10    ! kristaps  709:                break;
1.2       kristaps  710:        }
1.10    ! kristaps  711:        return(1);
        !           712: }
        !           713:
        !           714:
        !           715: /* ARGSUSED */
        !           716: static int
        !           717: termp_ud_pre(DECL_ARGS)
        !           718: {
        !           719:
        !           720:        word(p, "currently under development.");
        !           721:        return(1);
        !           722: }
        !           723:
        !           724:
        !           725: /* ARGSUSED */
        !           726: static int
        !           727: termp_fl_pre(DECL_ARGS)
        !           728: {
        !           729:
        !           730:        p->flags |= ttypes[TTYPE_CMD_FLAG];
        !           731:        word(p, "\\-");
        !           732:        p->flags |= TERMP_NOSPACE;
        !           733:        return(1);
        !           734: }
        !           735:
        !           736:
        !           737: /* ARGSUSED */
        !           738: static int
        !           739: termp_d1_pre(DECL_ARGS)
        !           740: {
        !           741:
        !           742:        if (MDOC_BODY != node->type)
        !           743:                return(1);
        !           744:        newln(p);
        !           745:        p->offset += INDENT;
        !           746:        return(1);
1.2       kristaps  747: }
                    748:
                    749:
1.10    ! kristaps  750: /* ARGSUSED */
1.2       kristaps  751: static void
1.10    ! kristaps  752: termp_d1_post(DECL_ARGS)
        !           753: {
        !           754:
        !           755:        if (MDOC_BODY != node->type)
        !           756:                return;
        !           757:        newln(p);
        !           758:        p->offset -= INDENT;
        !           759: }
        !           760:
        !           761:
        !           762: /* ARGSUSED */
        !           763: static int
        !           764: termp_aq_pre(DECL_ARGS)
1.6       kristaps  765: {
                    766:
1.10    ! kristaps  767:        if (MDOC_BODY != node->type)
        !           768:                return(1);
        !           769:        word(p, "<");
        !           770:        p->flags |= TERMP_NOSPACE;
        !           771:        return(1);
        !           772: }
1.6       kristaps  773:
                    774:
1.10    ! kristaps  775: /* ARGSUSED */
        !           776: static void
        !           777: termp_aq_post(DECL_ARGS)
        !           778: {
1.6       kristaps  779:
1.10    ! kristaps  780:        if (MDOC_BODY != node->type)
1.6       kristaps  781:                return;
1.10    ! kristaps  782:        p->flags |= TERMP_NOSPACE;
        !           783:        word(p, ">");
        !           784: }
1.6       kristaps  785:
1.10    ! kristaps  786:
        !           787: /* ARGSUSED */
        !           788: static int
        !           789: termp_ft_pre(DECL_ARGS)
        !           790: {
        !           791:
        !           792:        p->flags |= ttypes[TTYPE_FUNC_TYPE];
        !           793:        return(1);
1.6       kristaps  794: }
                    795:
                    796:
1.10    ! kristaps  797: /* ARGSUSED */
1.6       kristaps  798: static void
1.10    ! kristaps  799: termp_ft_post(DECL_ARGS)
1.2       kristaps  800: {
                    801:
1.10    ! kristaps  802:        p->flags &= ~ttypes[TTYPE_FUNC_TYPE];
        !           803:        if (node->sec == SEC_SYNOPSIS)
        !           804:                newln(p);
        !           805:
        !           806: }
1.2       kristaps  807:
                    808:
1.10    ! kristaps  809: /* ARGSUSED */
        !           810: static int
        !           811: termp_fn_pre(DECL_ARGS)
        !           812: {
        !           813:        const struct mdoc_node *n;
        !           814:
        !           815:        assert(node->child);
        !           816:        assert(MDOC_TEXT == node->child->type);
1.2       kristaps  817:
1.10    ! kristaps  818:        /* FIXME: can be "type funcname" "type varname"... */
1.2       kristaps  819:
1.10    ! kristaps  820:        p->flags |= ttypes[TTYPE_FUNC_NAME];
        !           821:        word(p, node->child->data.text.string);
        !           822:        p->flags &= ~ttypes[TTYPE_FUNC_NAME];
        !           823:
        !           824:        p->flags |= TERMP_NOSPACE;
        !           825:        word(p, "(");
        !           826:
        !           827:        p->flags |= TERMP_NOSPACE;
        !           828:        for (n = node->child->next; n; n = n->next) {
        !           829:                assert(MDOC_TEXT == n->type);
        !           830:                p->flags |= ttypes[TTYPE_FUNC_ARG];
        !           831:                word(p, n->data.text.string);
        !           832:                p->flags &= ~ttypes[TTYPE_FUNC_ARG];
        !           833:                if ((n->next))
        !           834:                        word(p, ",");
1.6       kristaps  835:        }
1.2       kristaps  836:
1.10    ! kristaps  837:        p->flags |= TERMP_NOSPACE;
        !           838:        word(p, ")");
        !           839:
        !           840:        if (SEC_SYNOPSIS == node->sec)
        !           841:                word(p, ";");
        !           842:
        !           843:        return(0);
1.2       kristaps  844: }
                    845:
                    846:
1.10    ! kristaps  847: /* ARGSUSED */
        !           848: static void
        !           849: termp_fn_post(DECL_ARGS)
1.2       kristaps  850: {
                    851:
1.10    ! kristaps  852:        if (node->sec == SEC_SYNOPSIS)
        !           853:                vspace(p);
        !           854:
        !           855: }
1.2       kristaps  856:
                    857:
1.10    ! kristaps  858: /* ARGSUSED */
        !           859: static int
        !           860: termp_sx_pre(DECL_ARGS)
        !           861: {
1.8       kristaps  862:
1.10    ! kristaps  863:        p->flags |= ttypes[TTYPE_LINK];
        !           864:        return(1);
1.2       kristaps  865: }
                    866:
                    867:
1.10    ! kristaps  868: /* ARGSUSED */
1.1       kristaps  869: static void
1.10    ! kristaps  870: termp_sx_post(DECL_ARGS)
1.2       kristaps  871: {
                    872:
1.10    ! kristaps  873:        p->flags &= ~ttypes[TTYPE_LINK];
        !           874: }
1.2       kristaps  875:
1.4       kristaps  876:
1.10    ! kristaps  877: /* ARGSUSED */
        !           878: static int
        !           879: termp_fa_pre(DECL_ARGS)
        !           880: {
1.2       kristaps  881:
1.10    ! kristaps  882:        p->flags |= ttypes[TTYPE_FUNC_ARG];
        !           883:        return(1);
        !           884: }
1.2       kristaps  885:
                    886:
1.10    ! kristaps  887: /* ARGSUSED */
        !           888: static void
        !           889: termp_fa_post(DECL_ARGS)
        !           890: {
        !           891:
        !           892:        p->flags &= ~ttypes[TTYPE_FUNC_ARG];
        !           893: }
1.2       kristaps  894:
                    895:
1.10    ! kristaps  896: /* ARGSUSED */
        !           897: static int
        !           898: termp_va_pre(DECL_ARGS)
        !           899: {
1.2       kristaps  900:
1.10    ! kristaps  901:        p->flags |= ttypes[TTYPE_VAR_DECL];
        !           902:        return(1);
1.2       kristaps  903: }
                    904:
                    905:
1.10    ! kristaps  906: /* ARGSUSED */
1.2       kristaps  907: static void
1.10    ! kristaps  908: termp_va_post(DECL_ARGS)
1.1       kristaps  909: {
                    910:
1.10    ! kristaps  911:        p->flags &= ~ttypes[TTYPE_VAR_DECL];
        !           912: }
1.1       kristaps  913:
1.7       kristaps  914:
1.10    ! kristaps  915: /* ARGSUSED */
        !           916: static int
        !           917: termp_bd_pre(DECL_ARGS)
        !           918: {
        !           919:        const struct mdoc_block *bl;
        !           920:        const struct mdoc_node *n;
1.1       kristaps  921:
1.10    ! kristaps  922:        if (MDOC_BLOCK == node->type) {
        !           923:                vspace(p);
        !           924:                return(1);
        !           925:        } else if (MDOC_BODY != node->type)
        !           926:                return(1);
        !           927:
        !           928:        assert(MDOC_BLOCK == node->parent->type);
        !           929:
        !           930:        bl = &node->parent->data.block;
        !           931:        if ( ! arg_hasattr(MDOC_Literal, bl->argc, bl->argv))
        !           932:                return(1);
        !           933:
        !           934:        p->flags |= TERMP_LITERAL;
        !           935:
        !           936:        for (n = node->child; n; n = n->next) {
        !           937:                assert(MDOC_TEXT == n->type); /* FIXME */
        !           938:                if ((*n->data.text.string)) {
        !           939:                        word(p, n->data.text.string);
        !           940:                        flushln(p);
        !           941:                } else
        !           942:                        vspace(p);
1.1       kristaps  943:
1.10    ! kristaps  944:        }
1.1       kristaps  945:
1.10    ! kristaps  946:        p->flags &= ~TERMP_LITERAL;
        !           947:        return(0);
        !           948: }
1.1       kristaps  949:
                    950:
1.10    ! kristaps  951: /* ARGSUSED */
        !           952: static int
        !           953: termp_qq_pre(DECL_ARGS)
        !           954: {
1.1       kristaps  955:
1.10    ! kristaps  956:        if (MDOC_BODY != node->type)
        !           957:                return(1);
        !           958:        word(p, "\"");
        !           959:        p->flags |= TERMP_NOSPACE;
        !           960:        return(1);
1.1       kristaps  961: }
                    962:
                    963:
1.10    ! kristaps  964: /* ARGSUSED */
1.1       kristaps  965: static void
1.10    ! kristaps  966: termp_qq_post(DECL_ARGS)
1.1       kristaps  967: {
                    968:
1.10    ! kristaps  969:        if (MDOC_BODY != node->type)
        !           970:                return;
        !           971:        p->flags |= TERMP_NOSPACE;
        !           972:        word(p, "\"");
        !           973: }
        !           974:
        !           975:
        !           976: /* ARGSUSED */
        !           977: static int
        !           978: termp_bx_pre(DECL_ARGS)
        !           979: {
1.1       kristaps  980:
1.10    ! kristaps  981:        word(p, "BSD");
        !           982:        return(1);
        !           983: }
        !           984:
        !           985:
        !           986: /* ARGSUSED */
        !           987: static int
        !           988: termp_ox_pre(DECL_ARGS)
        !           989: {
        !           990:
        !           991:        word(p, "OpenBSD");
        !           992:        return(1);
        !           993: }
        !           994:
        !           995:
        !           996: /* ARGSUSED */
        !           997: static int
        !           998: termp_nx_pre(DECL_ARGS)
        !           999: {
        !          1000:
        !          1001:        word(p, "NetBSD");
        !          1002:        return(1);
        !          1003: }
        !          1004:
        !          1005:
        !          1006: /* ARGSUSED */
        !          1007: static int
        !          1008: termp_sq_pre(DECL_ARGS)
        !          1009: {
        !          1010:
        !          1011:        if (MDOC_BODY != node->type)
        !          1012:                return(1);
        !          1013:        word(p, "`");
        !          1014:        p->flags |= TERMP_NOSPACE;
        !          1015:        return(1);
        !          1016: }
1.1       kristaps 1017:
                   1018:
1.10    ! kristaps 1019: /* ARGSUSED */
        !          1020: static void
        !          1021: termp_sq_post(DECL_ARGS)
        !          1022: {
        !          1023:
        !          1024:        if (MDOC_BODY != node->type)
        !          1025:                return;
        !          1026:        p->flags |= TERMP_NOSPACE;
        !          1027:        word(p, "\'");
        !          1028: }
1.2       kristaps 1029:
                   1030:
1.10    ! kristaps 1031: /* ARGSUSED */
        !          1032: static int
        !          1033: termp_pf_pre(DECL_ARGS)
        !          1034: {
1.1       kristaps 1035:
1.10    ! kristaps 1036:        p->flags |= TERMP_IGNDELIM;
        !          1037:        return(1);
        !          1038: }
1.1       kristaps 1039:
                   1040:
1.10    ! kristaps 1041: /* ARGSUSED */
        !          1042: static void
        !          1043: termp_pf_post(DECL_ARGS)
        !          1044: {
1.1       kristaps 1045:
1.10    ! kristaps 1046:        p->flags &= ~TERMP_IGNDELIM;
        !          1047:        p->flags |= TERMP_NOSPACE;
        !          1048: }
1.1       kristaps 1049:
                   1050:
1.10    ! kristaps 1051: /* ARGSUSED */
        !          1052: static int
        !          1053: termp_ss_pre(DECL_ARGS)
        !          1054: {
1.1       kristaps 1055:
1.10    ! kristaps 1056:        switch (node->type) {
        !          1057:        case (MDOC_HEAD):
        !          1058:                vspace(p);
        !          1059:                p->flags |= ttypes[TTYPE_SSECTION];
        !          1060:                p->offset = INDENT / 2;
        !          1061:                break;
        !          1062:        default:
        !          1063:                break;
        !          1064:        }
1.1       kristaps 1065:
1.10    ! kristaps 1066:        return(1);
1.1       kristaps 1067: }
                   1068:
                   1069:
1.10    ! kristaps 1070: /* ARGSUSED */
        !          1071: static void
        !          1072: termp_ss_post(DECL_ARGS)
1.1       kristaps 1073: {
                   1074:
1.10    ! kristaps 1075:        switch (node->type) {
        !          1076:        case (MDOC_HEAD):
        !          1077:                p->flags &= ~ttypes[TTYPE_SSECTION];
        !          1078:                newln(p);
        !          1079:                p->offset = INDENT;
        !          1080:                break;
        !          1081:        default:
        !          1082:                break;
        !          1083:        }
        !          1084: }
1.2       kristaps 1085:
                   1086:
1.10    ! kristaps 1087: /* ARGSUSED */
        !          1088: static int
        !          1089: termp_pa_pre(DECL_ARGS)
        !          1090: {
1.2       kristaps 1091:
1.10    ! kristaps 1092:        p->flags |= ttypes[TTYPE_FILE];
        !          1093:        return(1);
1.1       kristaps 1094: }
                   1095:
                   1096:
1.10    ! kristaps 1097: /* ARGSUSED */
        !          1098: static void
        !          1099: termp_pa_post(DECL_ARGS)
        !          1100: {
        !          1101:
        !          1102:        p->flags &= ~ttypes[TTYPE_FILE];
        !          1103: }

CVSweb