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

Annotation of mandoc/termact.c, Revision 1.3

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

CVSweb