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

Annotation of mandoc/termact.c, Revision 1.1

1.1     ! kristaps    1: /* $Id: term.c,v 1.4 2009/02/21 15:34:46 kristaps Exp $ */
        !             2: /*
        !             3:  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
        !             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:
        !            23: #include "term.h"
        !            24:
        !            25: #define        TTYPE_PROG        0
        !            26: #define        TTYPE_CMD_FLAG    1
        !            27: #define        TTYPE_CMD_ARG     2
        !            28: #define        TTYPE_SECTION     3
        !            29: #define        TTYPE_NMAX        4
        !            30:
        !            31: /*
        !            32:  * These define "styles" for element types, like command arguments or
        !            33:  * executable names.  This is useful when multiple macros must decorate
        !            34:  * the same thing (like .Ex -std cmd and .Nm cmd).
        !            35:  */
        !            36:
        !            37: const  int ttypes[TTYPE_NMAX] = {
        !            38:        TERMP_BOLD,             /* TTYPE_PROG */
        !            39:        TERMP_BOLD,             /* TTYPE_CMD_FLAG */
        !            40:        TERMP_UNDERLINE,        /* TTYPE_CMD_ARG */
        !            41:        TERMP_BOLD              /* TTYPE_SECTION */
        !            42: };
        !            43:
        !            44: static int               arg_hasattr(int, size_t,
        !            45:                                const struct mdoc_arg *);
        !            46: static int               arg_getattr(int, size_t,
        !            47:                                const struct mdoc_arg *);
        !            48:
        !            49: /*
        !            50:  * What follows describes prefix and postfix operations for the abstract
        !            51:  * syntax tree descent.
        !            52:  */
        !            53:
        !            54: #define        DECL_ARGS \
        !            55:        struct termp *p, \
        !            56:        const struct mdoc_meta *meta, \
        !            57:        const struct mdoc_node *node
        !            58:
        !            59: #define        DECL_PREPOST(name, suffix) \
        !            60: static int               name##_##suffix(DECL_ARGS)
        !            61:
        !            62: #define        DECL_PRE(name)    DECL_PREPOST(name, pre)
        !            63: #define        DECL_POST(name)   DECL_PREPOST(name, post)
        !            64:
        !            65: DECL_PRE(termp_aq);
        !            66: DECL_PRE(termp_ar);
        !            67: DECL_PRE(termp_d1);
        !            68: DECL_PRE(termp_dq);
        !            69: DECL_PRE(termp_ex);
        !            70: DECL_PRE(termp_fl);
        !            71: DECL_PRE(termp_it);
        !            72: DECL_PRE(termp_nd);
        !            73: DECL_PRE(termp_nm);
        !            74: DECL_PRE(termp_ns);
        !            75: DECL_PRE(termp_op);
        !            76: DECL_PRE(termp_pp);
        !            77: DECL_PRE(termp_sh);
        !            78: DECL_PRE(termp_ud);
        !            79: DECL_PRE(termp_xr);
        !            80:
        !            81: DECL_POST(termp_aq);
        !            82: DECL_POST(termp_ar);
        !            83: DECL_POST(termp_bl);
        !            84: DECL_POST(termp_d1);
        !            85: DECL_POST(termp_dq);
        !            86: DECL_POST(termp_fl);
        !            87: DECL_POST(termp_it);
        !            88: DECL_POST(termp_nm);
        !            89: DECL_POST(termp_op);
        !            90: DECL_POST(termp_sh);
        !            91:
        !            92: const  struct termact __termacts[MDOC_MAX] = {
        !            93:        { NULL, NULL }, /* \" */
        !            94:        { NULL, NULL }, /* Dd */
        !            95:        { NULL, NULL }, /* Dt */
        !            96:        { NULL, NULL }, /* Os */
        !            97:        { termp_sh_pre, termp_sh_post }, /* Sh */
        !            98:        { NULL, NULL }, /* Ss */
        !            99:        { termp_pp_pre, NULL }, /* Pp */
        !           100:        { termp_d1_pre, termp_d1_post }, /* D1 */
        !           101:        { NULL, NULL }, /* Dl */
        !           102:        { NULL, NULL }, /* Bd */
        !           103:        { NULL, NULL }, /* Ed */
        !           104:        { NULL, termp_bl_post }, /* Bl */
        !           105:        { NULL, NULL }, /* El */
        !           106:        { termp_it_pre, termp_it_post }, /* It */
        !           107:        { NULL, NULL }, /* Ad */
        !           108:        { NULL, NULL }, /* An */
        !           109:        { termp_ar_pre, termp_ar_post }, /* Ar */
        !           110:        { NULL, NULL }, /* Cd */
        !           111:        { NULL, NULL }, /* Cm */
        !           112:        { NULL, NULL }, /* Dv */
        !           113:        { NULL, NULL }, /* Er */
        !           114:        { NULL, NULL }, /* Ev */
        !           115:        { termp_ex_pre, NULL }, /* Ex */
        !           116:        { NULL, NULL }, /* Fa */
        !           117:        { NULL, NULL }, /* Fd */
        !           118:        { termp_fl_pre, termp_fl_post }, /* Fl */
        !           119:        { NULL, NULL }, /* Fn */
        !           120:        { NULL, NULL }, /* Ft */
        !           121:        { NULL, NULL }, /* Ic */
        !           122:        { NULL, NULL }, /* In */
        !           123:        { NULL, NULL }, /* Li */
        !           124:        { termp_nd_pre, NULL }, /* Nd */
        !           125:        { termp_nm_pre, termp_nm_post }, /* Nm */
        !           126:        { termp_op_pre, termp_op_post }, /* Op */
        !           127:        { NULL, NULL }, /* Ot */
        !           128:        { NULL, NULL }, /* Pa */
        !           129:        { NULL, NULL }, /* Rv */
        !           130:        { NULL, NULL }, /* St */
        !           131:        { NULL, NULL }, /* Va */
        !           132:        { NULL, NULL }, /* Vt */
        !           133:        { termp_xr_pre, NULL }, /* Xr */
        !           134:        { NULL, NULL }, /* %A */
        !           135:        { NULL, NULL }, /* %B */
        !           136:        { NULL, NULL }, /* %D */
        !           137:        { NULL, NULL }, /* %I */
        !           138:        { NULL, NULL }, /* %J */
        !           139:        { NULL, NULL }, /* %N */
        !           140:        { NULL, NULL }, /* %O */
        !           141:        { NULL, NULL }, /* %P */
        !           142:        { NULL, NULL }, /* %R */
        !           143:        { NULL, NULL }, /* %T */
        !           144:        { NULL, NULL }, /* %V */
        !           145:        { NULL, NULL }, /* Ac */
        !           146:        { NULL, NULL }, /* Ao */
        !           147:        { termp_aq_pre, termp_aq_post }, /* Aq */
        !           148:        { NULL, NULL }, /* At */
        !           149:        { NULL, NULL }, /* Bc */
        !           150:        { NULL, NULL }, /* Bf */
        !           151:        { NULL, NULL }, /* Bo */
        !           152:        { NULL, NULL }, /* Bq */
        !           153:        { NULL, NULL }, /* Bsx */
        !           154:        { NULL, NULL }, /* Bx */
        !           155:        { NULL, NULL }, /* Db */
        !           156:        { NULL, NULL }, /* Dc */
        !           157:        { NULL, NULL }, /* Do */
        !           158:        { termp_dq_pre, termp_dq_post }, /* Dq */
        !           159:        { NULL, NULL }, /* Ec */
        !           160:        { NULL, NULL }, /* Ef */
        !           161:        { NULL, NULL }, /* Em */
        !           162:        { NULL, NULL }, /* Eo */
        !           163:        { NULL, NULL }, /* Fx */
        !           164:        { NULL, NULL }, /* Ms */
        !           165:        { NULL, NULL }, /* No */
        !           166:        { termp_ns_pre, NULL }, /* Ns */
        !           167:        { NULL, NULL }, /* Nx */
        !           168:        { NULL, NULL }, /* Ox */
        !           169:        { NULL, NULL }, /* Pc */
        !           170:        { NULL, NULL }, /* Pf */
        !           171:        { NULL, NULL }, /* Po */
        !           172:        { NULL, NULL }, /* Pq */
        !           173:        { NULL, NULL }, /* Qc */
        !           174:        { NULL, NULL }, /* Ql */
        !           175:        { NULL, NULL }, /* Qo */
        !           176:        { NULL, NULL }, /* Qq */
        !           177:        { NULL, NULL }, /* Re */
        !           178:        { NULL, NULL }, /* Rs */
        !           179:        { NULL, NULL }, /* Sc */
        !           180:        { NULL, NULL }, /* So */
        !           181:        { NULL, NULL }, /* Sq */
        !           182:        { NULL, NULL }, /* Sm */
        !           183:        { NULL, NULL }, /* Sx */
        !           184:        { NULL, NULL }, /* Sy */
        !           185:        { NULL, NULL }, /* Tn */
        !           186:        { NULL, NULL }, /* Ux */
        !           187:        { NULL, NULL }, /* Xc */
        !           188:        { NULL, NULL }, /* Xo */
        !           189:        { NULL, NULL }, /* Fo */
        !           190:        { NULL, NULL }, /* Fc */
        !           191:        { NULL, NULL }, /* Oo */
        !           192:        { NULL, NULL }, /* Oc */
        !           193:        { NULL, NULL }, /* Bk */
        !           194:        { NULL, NULL }, /* Ek */
        !           195:        { NULL, NULL }, /* Bt */
        !           196:        { NULL, NULL }, /* Hf */
        !           197:        { NULL, NULL }, /* Fr */
        !           198:        { termp_ud_pre, NULL }, /* Ud */
        !           199: };
        !           200:
        !           201: const struct termact *termacts = __termacts;
        !           202:
        !           203:
        !           204: /* ARGSUSED */
        !           205: static int
        !           206: termp_dq_pre(DECL_ARGS)
        !           207: {
        !           208:
        !           209:        if (MDOC_BODY != node->type)
        !           210:                return(1);
        !           211:
        !           212:        word(p, "``");
        !           213:        p->flags |= TERMP_NOSPACE;
        !           214:        return(1);
        !           215: }
        !           216:
        !           217:
        !           218: /* ARGSUSED */
        !           219: static int
        !           220: termp_dq_post(DECL_ARGS)
        !           221: {
        !           222:
        !           223:        if (MDOC_BODY != node->type)
        !           224:                return(1);
        !           225:
        !           226:        p->flags |= TERMP_NOSPACE;
        !           227:        word(p, "''");
        !           228:        return(1);
        !           229: }
        !           230:
        !           231:
        !           232: /* ARGSUSED */
        !           233: static int
        !           234: termp_it_post(DECL_ARGS)
        !           235: {
        !           236:        const struct mdoc_node *n, *it;
        !           237:        const struct mdoc_block *bl;
        !           238:        int              i;
        !           239:        size_t           width;
        !           240:
        !           241:        /*
        !           242:         * This (and termp_it_pre()) are the most complicated functions
        !           243:         * here.  They must account for a considerable number of
        !           244:         * switches that completely change the output behaviour, like
        !           245:         * -tag versus -column.  Yech.
        !           246:         */
        !           247:
        !           248:        switch (node->type) {
        !           249:        case (MDOC_BODY):
        !           250:                /* FALLTHROUGH */
        !           251:        case (MDOC_HEAD):
        !           252:                break;
        !           253:        default:
        !           254:                return(1);
        !           255:        }
        !           256:
        !           257:        it = node->parent;
        !           258:        assert(MDOC_BLOCK == it->type);
        !           259:        assert(MDOC_It == it->tok);
        !           260:
        !           261:        n = it->parent;
        !           262:        assert(MDOC_BODY == n->type);
        !           263:        assert(MDOC_Bl == n->tok);
        !           264:        n = n->parent;
        !           265:        bl = &n->data.block;
        !           266:
        !           267:        /* If `-tag', adjust our margins accordingly. */
        !           268:
        !           269:        if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
        !           270:                i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
        !           271:                assert(i >= 0);
        !           272:                assert(1 == bl->argv[i].sz);
        !           273:                width = strlen(*bl->argv[i].value); /* XXX */
        !           274:
        !           275:                if (MDOC_HEAD == node->type) {
        !           276:                        flushln(p);
        !           277:                        /* FIXME: nested lists. */
        !           278:                        p->rmargin = p->maxrmargin;
        !           279:                        p->flags &= ~TERMP_NOBREAK;
        !           280:                } else {
        !           281:                        flushln(p);
        !           282:                        p->offset -= width + 1;
        !           283:                        p->flags &= ~TERMP_NOLPAD;
        !           284:                }
        !           285:        }
        !           286:
        !           287:        return(1);
        !           288: }
        !           289:
        !           290:
        !           291: /* ARGSUSED */
        !           292: static int
        !           293: termp_it_pre(DECL_ARGS)
        !           294: {
        !           295:        const struct mdoc_node *n, *it;
        !           296:        const struct mdoc_block *bl;
        !           297:        int              i;
        !           298:        size_t           width;
        !           299:
        !           300:        /*
        !           301:         * Also see termp_it_post() for general comments.
        !           302:         */
        !           303:
        !           304:        switch (node->type) {
        !           305:        case (MDOC_BODY):
        !           306:                /* FALLTHROUGH */
        !           307:        case (MDOC_HEAD):
        !           308:                it = node->parent;
        !           309:                break;
        !           310:        case (MDOC_BLOCK):
        !           311:                it = node;
        !           312:                break;
        !           313:        default:
        !           314:                return(1);
        !           315:        }
        !           316:
        !           317:        assert(MDOC_BLOCK == it->type);
        !           318:        assert(MDOC_It == it->tok);
        !           319:
        !           320:        n = it->parent;
        !           321:        assert(MDOC_BODY == n->type);
        !           322:        assert(MDOC_Bl == n->tok);
        !           323:        n = n->parent;
        !           324:        bl = &n->data.block;
        !           325:
        !           326:        /* If `-compact', don't assert vertical space. */
        !           327:
        !           328:        if (MDOC_BLOCK == node->type) {
        !           329:                if (arg_hasattr(MDOC_Compact, bl->argc, bl->argv))
        !           330:                        newln(p);
        !           331:                else
        !           332:                        vspace(p);
        !           333:                return(1);
        !           334:        }
        !           335:
        !           336:        assert(MDOC_HEAD == node->type
        !           337:                        || MDOC_BODY == node->type);
        !           338:
        !           339:        /* If `-tag', adjust our margins accordingly. */
        !           340:
        !           341:        if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
        !           342:                i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
        !           343:                assert(i >= 0); /* XXX */
        !           344:                assert(1 == bl->argv[i].sz);
        !           345:                width = strlen(*bl->argv[i].value); /* XXX */
        !           346:
        !           347:                /* FIXME: nested lists. */
        !           348:
        !           349:                if (MDOC_HEAD == node->type) {
        !           350:                        p->flags |= TERMP_NOBREAK;
        !           351:                        p->flags |= TERMP_NOSPACE;
        !           352:                        p->rmargin = p->offset + width;
        !           353:                } else {
        !           354:                        p->flags |= TERMP_NOSPACE;
        !           355:                        p->flags |= TERMP_NOLPAD;
        !           356:                        p->offset += width + 1;
        !           357:                }
        !           358:        }
        !           359:
        !           360:        return(1);
        !           361: }
        !           362:
        !           363:
        !           364: /* ARGSUSED */
        !           365: static int
        !           366: termp_nm_post(DECL_ARGS)
        !           367: {
        !           368:
        !           369:        p->flags &= ~ttypes[TTYPE_PROG];
        !           370:        return(1);
        !           371: }
        !           372:
        !           373:
        !           374: /* ARGSUSED */
        !           375: static int
        !           376: termp_fl_post(DECL_ARGS)
        !           377: {
        !           378:
        !           379:        p->flags &= ~ttypes[TTYPE_CMD_FLAG];
        !           380:        return(1);
        !           381: }
        !           382:
        !           383:
        !           384: /* ARGSUSED */
        !           385: static int
        !           386: termp_ar_pre(DECL_ARGS)
        !           387: {
        !           388:
        !           389:        p->flags |= ttypes[TTYPE_CMD_ARG];
        !           390:        if (NULL == node->child)
        !           391:                word(p, "...");
        !           392:        return(1);
        !           393: }
        !           394:
        !           395:
        !           396: /* ARGSUSED */
        !           397: static int
        !           398: termp_nm_pre(DECL_ARGS)
        !           399: {
        !           400:
        !           401:        p->flags |= ttypes[TTYPE_PROG];
        !           402:        if (NULL == node->child)
        !           403:                word(p, meta->name);
        !           404:        return(1);
        !           405: }
        !           406:
        !           407:
        !           408: /* ARGSUSED */
        !           409: static int
        !           410: termp_ns_pre(DECL_ARGS)
        !           411: {
        !           412:
        !           413:        p->flags |= TERMP_NOSPACE;
        !           414:        return(1);
        !           415: }
        !           416:
        !           417:
        !           418: /* ARGSUSED */
        !           419: static int
        !           420: termp_pp_pre(DECL_ARGS)
        !           421: {
        !           422:
        !           423:        vspace(p);
        !           424:        return(1);
        !           425: }
        !           426:
        !           427:
        !           428: /* ARGSUSED */
        !           429: static int
        !           430: termp_ar_post(DECL_ARGS)
        !           431: {
        !           432:
        !           433:        p->flags &= ~ttypes[TTYPE_CMD_ARG];
        !           434:        return(1);
        !           435: }
        !           436:
        !           437:
        !           438: /* ARGSUSED */
        !           439: static int
        !           440: termp_ex_pre(DECL_ARGS)
        !           441: {
        !           442:        int              i;
        !           443:
        !           444:        i = arg_getattr(MDOC_Std, node->data.elem.argc,
        !           445:                        node->data.elem.argv);
        !           446:        assert(i >= 0);
        !           447:
        !           448:        word(p, "The");
        !           449:        p->flags |= ttypes[TTYPE_PROG];
        !           450:        word(p, *node->data.elem.argv[i].value);
        !           451:        p->flags &= ~ttypes[TTYPE_PROG];
        !           452:                word(p, "utility exits 0 on success, and >0 if an error occurs.");
        !           453:
        !           454:        return(1);
        !           455: }
        !           456:
        !           457:
        !           458: /* ARGSUSED */
        !           459: static int
        !           460: termp_nd_pre(DECL_ARGS)
        !           461: {
        !           462:
        !           463:        word(p, "\\-");
        !           464:        return(1);
        !           465: }
        !           466:
        !           467:
        !           468: /* ARGSUSED */
        !           469: static int
        !           470: termp_bl_post(DECL_ARGS)
        !           471: {
        !           472:
        !           473:        switch (node->type) {
        !           474:        case (MDOC_BLOCK):
        !           475:                newln(p);
        !           476:                break;
        !           477:        default:
        !           478:                break;
        !           479:        }
        !           480:        return(1);
        !           481: }
        !           482:
        !           483:
        !           484: /* ARGSUSED */
        !           485: static int
        !           486: termp_op_post(DECL_ARGS)
        !           487: {
        !           488:
        !           489:        switch (node->type) {
        !           490:        case (MDOC_BODY):
        !           491:                p->flags |= TERMP_NOSPACE;
        !           492:                word(p, "\\]");
        !           493:                break;
        !           494:        default:
        !           495:                break;
        !           496:        }
        !           497:        return(1);
        !           498: }
        !           499:
        !           500:
        !           501: /* ARGSUSED */
        !           502: static int
        !           503: termp_sh_post(DECL_ARGS)
        !           504: {
        !           505:
        !           506:        switch (node->type) {
        !           507:        case (MDOC_HEAD):
        !           508:                p->flags &= ~ttypes[TTYPE_SECTION];
        !           509:                newln(p);
        !           510:                break;
        !           511:        case (MDOC_BODY):
        !           512:                newln(p);
        !           513:                p->offset -= 4;
        !           514:                break;
        !           515:        default:
        !           516:                break;
        !           517:        }
        !           518:        return(1);
        !           519: }
        !           520:
        !           521:
        !           522: /* ARGSUSED */
        !           523: static int
        !           524: termp_xr_pre(DECL_ARGS)
        !           525: {
        !           526:        const struct mdoc_node *n;
        !           527:
        !           528:        n = node->child;
        !           529:        assert(n);
        !           530:
        !           531:        assert(MDOC_TEXT == n->type);
        !           532:        word(p, n->data.text.string);
        !           533:
        !           534:        if (NULL == (n = n->next))
        !           535:                return(0);
        !           536:
        !           537:        assert(MDOC_TEXT == n->type);
        !           538:        p->flags |= TERMP_NOSPACE;
        !           539:        word(p, "\\(");
        !           540:        p->flags |= TERMP_NOSPACE;
        !           541:        word(p, n->data.text.string);
        !           542:        p->flags |= TERMP_NOSPACE;
        !           543:        word(p, "\\)");
        !           544:
        !           545:        return(0);
        !           546: }
        !           547:
        !           548:
        !           549: /* ARGSUSED */
        !           550: static int
        !           551: termp_sh_pre(DECL_ARGS)
        !           552: {
        !           553:
        !           554:        switch (node->type) {
        !           555:        case (MDOC_HEAD):
        !           556:                vspace(p);
        !           557:                p->flags |= ttypes[TTYPE_SECTION];
        !           558:                break;
        !           559:        case (MDOC_BODY):
        !           560:                p->offset += 4;
        !           561:                break;
        !           562:        default:
        !           563:                break;
        !           564:        }
        !           565:        return(1);
        !           566: }
        !           567:
        !           568:
        !           569: /* ARGSUSED */
        !           570: static int
        !           571: termp_op_pre(DECL_ARGS)
        !           572: {
        !           573:
        !           574:        switch (node->type) {
        !           575:        case (MDOC_BODY):
        !           576:                word(p, "\\[");
        !           577:                p->flags |= TERMP_NOSPACE;
        !           578:                break;
        !           579:        default:
        !           580:                break;
        !           581:        }
        !           582:        return(1);
        !           583: }
        !           584:
        !           585:
        !           586: /* ARGSUSED */
        !           587: static int
        !           588: termp_ud_pre(DECL_ARGS)
        !           589: {
        !           590:
        !           591:        word(p, "currently under development.");
        !           592:        return(1);
        !           593: }
        !           594:
        !           595:
        !           596: /* ARGSUSED */
        !           597: static int
        !           598: termp_fl_pre(DECL_ARGS)
        !           599: {
        !           600:
        !           601:        p->flags |= ttypes[TTYPE_CMD_FLAG];
        !           602:        word(p, "\\-");
        !           603:        p->flags |= TERMP_NOSPACE;
        !           604:        return(1);
        !           605: }
        !           606:
        !           607:
        !           608: /* ARGSUSED */
        !           609: static int
        !           610: termp_d1_pre(DECL_ARGS)
        !           611: {
        !           612:
        !           613:        if (MDOC_BODY != node->type)
        !           614:                return(1);
        !           615:        newln(p);
        !           616:        p->offset += 4;
        !           617:        return(1);
        !           618: }
        !           619:
        !           620:
        !           621: /* ARGSUSED */
        !           622: static int
        !           623: termp_d1_post(DECL_ARGS)
        !           624: {
        !           625:
        !           626:        if (MDOC_BODY != node->type)
        !           627:                return(1);
        !           628:        newln(p);
        !           629:        p->offset -= 4;
        !           630:        return(1);
        !           631: }
        !           632:
        !           633:
        !           634: /* ARGSUSED */
        !           635: static int
        !           636: termp_aq_pre(DECL_ARGS)
        !           637: {
        !           638:
        !           639:        if (MDOC_BODY != node->type)
        !           640:                return(1);
        !           641:        word(p, "\\<");
        !           642:        p->flags |= TERMP_NOSPACE;
        !           643:        return(1);
        !           644: }
        !           645:
        !           646:
        !           647: /* ARGSUSED */
        !           648: static int
        !           649: termp_aq_post(DECL_ARGS)
        !           650: {
        !           651:
        !           652:        if (MDOC_BODY != node->type)
        !           653:                return(1);
        !           654:        p->flags |= TERMP_NOSPACE;
        !           655:        word(p, "\\>");
        !           656:        return(1);
        !           657: }
        !           658:
        !           659:
        !           660: static int
        !           661: arg_hasattr(int arg, size_t argc, const struct mdoc_arg *argv)
        !           662: {
        !           663:
        !           664:        return(-1 != arg_getattr(arg, argc, argv));
        !           665: }
        !           666:
        !           667:
        !           668: static int
        !           669: arg_getattr(int arg, size_t argc, const struct mdoc_arg *argv)
        !           670: {
        !           671:        int              i;
        !           672:
        !           673:        for (i = 0; i < (int)argc; i++)
        !           674:                if (argv[i].arg == arg)
        !           675:                        return(i);
        !           676:        return(-1);
        !           677: }
        !           678:

CVSweb