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

Annotation of mandoc/mandoc-db.c, Revision 1.1

1.1     ! kristaps    1: /*     $Id: main.c,v 1.160 2011/03/28 21:49:42 kristaps Exp $ */
        !             2: /*
        !             3:  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
        !             4:  *
        !             5:  * Permission to use, copy, modify, and distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17: #include <sys/param.h>
        !            18:
        !            19: #include <assert.h>
        !            20: #ifdef __linux__
        !            21: # include <db_185.h>
        !            22: #else
        !            23: # include <db.h>
        !            24: #endif
        !            25: #include <fcntl.h>
        !            26: #include <getopt.h>
        !            27: #include <stdio.h>
        !            28: #include <stdint.h>
        !            29: #include <stdlib.h>
        !            30: #include <string.h>
        !            31:
        !            32: #include "man.h"
        !            33: #include "mdoc.h"
        !            34: #include "mandoc.h"
        !            35:
        !            36: #define        MANDOC_DB        "mandoc.db"
        !            37: #define        MANDOC_BUFSZ      10
        !            38:
        !            39: enum   type {
        !            40:        MANDOC_NONE = 0,
        !            41:        MANDOC_NAME,
        !            42:        MANDOC_FUNCTION,
        !            43:        MANDOC_UTILITY,
        !            44:        MANDOC_INCLUDES,
        !            45:        MANDOC_VARIABLE
        !            46: };
        !            47:
        !            48: #define        MDOC_ARGS         DB *db, \
        !            49:                          const char *dbn, \
        !            50:                          DBT *key, size_t *ksz, \
        !            51:                          DBT *val, \
        !            52:                          const struct mdoc_node *n
        !            53:
        !            54: static void              dbt_append(DBT *, size_t *, const char *);
        !            55: static void              dbt_appendb(DBT *, size_t *,
        !            56:                                const void *, size_t);
        !            57: static void              dbt_init(DBT *, size_t *);
        !            58: static void              version(void);
        !            59: static void              usage(void);
        !            60: static void              pmdoc(DB *, const char *,
        !            61:                                DBT *, size_t *,
        !            62:                                DBT *, size_t *,
        !            63:                                const char *, struct mdoc *);
        !            64: static void              pmdoc_node(MDOC_ARGS);
        !            65: static void              pmdoc_Fd(MDOC_ARGS);
        !            66: static void              pmdoc_In(MDOC_ARGS);
        !            67: static void              pmdoc_Fn(MDOC_ARGS);
        !            68: static void              pmdoc_Fo(MDOC_ARGS);
        !            69: static void              pmdoc_Nm(MDOC_ARGS);
        !            70: static void              pmdoc_Vt(MDOC_ARGS);
        !            71:
        !            72: typedef        void            (*pmdoc_nf)(MDOC_ARGS);
        !            73:
        !            74: static const char       *progname;
        !            75:
        !            76: static const pmdoc_nf    mdocs[MDOC_MAX] = {
        !            77:        NULL, /* Ap */
        !            78:        NULL, /* Dd */
        !            79:        NULL, /* Dt */
        !            80:        NULL, /* Os */
        !            81:        NULL, /* Sh */
        !            82:        NULL, /* Ss */
        !            83:        NULL, /* Pp */
        !            84:        NULL, /* D1 */
        !            85:        NULL, /* Dl */
        !            86:        NULL, /* Bd */
        !            87:        NULL, /* Ed */
        !            88:        NULL, /* Bl */
        !            89:        NULL, /* El */
        !            90:        NULL, /* It */
        !            91:        NULL, /* Ad */
        !            92:        NULL, /* An */
        !            93:        NULL, /* Ar */
        !            94:        NULL, /* Cd */
        !            95:        NULL, /* Cm */
        !            96:        NULL, /* Dv */
        !            97:        NULL, /* Er */
        !            98:        NULL, /* Ev */
        !            99:        NULL, /* Ex */
        !           100:        NULL, /* Fa */
        !           101:        pmdoc_Fd, /* Fd */
        !           102:        NULL, /* Fl */
        !           103:        pmdoc_Fn, /* Fn */
        !           104:        NULL, /* Ft */
        !           105:        NULL, /* Ic */
        !           106:        pmdoc_In, /* In */
        !           107:        NULL, /* Li */
        !           108:        NULL, /* Nd */
        !           109:        pmdoc_Nm, /* Nm */
        !           110:        NULL, /* Op */
        !           111:        NULL, /* Ot */
        !           112:        NULL, /* Pa */
        !           113:        NULL, /* Rv */
        !           114:        NULL, /* St */
        !           115:        pmdoc_Vt, /* Va */
        !           116:        pmdoc_Vt, /* Vt */
        !           117:        NULL, /* Xr */
        !           118:        NULL, /* %A */
        !           119:        NULL, /* %B */
        !           120:        NULL, /* %D */
        !           121:        NULL, /* %I */
        !           122:        NULL, /* %J */
        !           123:        NULL, /* %N */
        !           124:        NULL, /* %O */
        !           125:        NULL, /* %P */
        !           126:        NULL, /* %R */
        !           127:        NULL, /* %T */
        !           128:        NULL, /* %V */
        !           129:        NULL, /* Ac */
        !           130:        NULL, /* Ao */
        !           131:        NULL, /* Aq */
        !           132:        NULL, /* At */
        !           133:        NULL, /* Bc */
        !           134:        NULL, /* Bf */
        !           135:        NULL, /* Bo */
        !           136:        NULL, /* Bq */
        !           137:        NULL, /* Bsx */
        !           138:        NULL, /* Bx */
        !           139:        NULL, /* Db */
        !           140:        NULL, /* Dc */
        !           141:        NULL, /* Do */
        !           142:        NULL, /* Dq */
        !           143:        NULL, /* Ec */
        !           144:        NULL, /* Ef */
        !           145:        NULL, /* Em */
        !           146:        NULL, /* Eo */
        !           147:        NULL, /* Fx */
        !           148:        NULL, /* Ms */
        !           149:        NULL, /* No */
        !           150:        NULL, /* Ns */
        !           151:        NULL, /* Nx */
        !           152:        NULL, /* Ox */
        !           153:        NULL, /* Pc */
        !           154:        NULL, /* Pf */
        !           155:        NULL, /* Po */
        !           156:        NULL, /* Pq */
        !           157:        NULL, /* Qc */
        !           158:        NULL, /* Ql */
        !           159:        NULL, /* Qo */
        !           160:        NULL, /* Qq */
        !           161:        NULL, /* Re */
        !           162:        NULL, /* Rs */
        !           163:        NULL, /* Sc */
        !           164:        NULL, /* So */
        !           165:        NULL, /* Sq */
        !           166:        NULL, /* Sm */
        !           167:        NULL, /* Sx */
        !           168:        NULL, /* Sy */
        !           169:        NULL, /* Tn */
        !           170:        NULL, /* Ux */
        !           171:        NULL, /* Xc */
        !           172:        NULL, /* Xo */
        !           173:        pmdoc_Fo, /* Fo */
        !           174:        NULL, /* Fc */
        !           175:        NULL, /* Oo */
        !           176:        NULL, /* Oc */
        !           177:        NULL, /* Bk */
        !           178:        NULL, /* Ek */
        !           179:        NULL, /* Bt */
        !           180:        NULL, /* Hf */
        !           181:        NULL, /* Fr */
        !           182:        NULL, /* Ud */
        !           183:        NULL, /* Lb */
        !           184:        NULL, /* Lp */
        !           185:        NULL, /* Lk */
        !           186:        NULL, /* Mt */
        !           187:        NULL, /* Brq */
        !           188:        NULL, /* Bro */
        !           189:        NULL, /* Brc */
        !           190:        NULL, /* %C */
        !           191:        NULL, /* Es */
        !           192:        NULL, /* En */
        !           193:        NULL, /* Dx */
        !           194:        NULL, /* %Q */
        !           195:        NULL, /* br */
        !           196:        NULL, /* sp */
        !           197:        NULL, /* %U */
        !           198:        NULL, /* Ta */
        !           199: };
        !           200:
        !           201: int
        !           202: main(int argc, char *argv[])
        !           203: {
        !           204:        struct mparse   *mp;
        !           205:        struct mdoc     *mdoc;
        !           206:        struct man      *man;
        !           207:        const char      *f, *fn;
        !           208:        size_t           sz;
        !           209:        char             fbuf[MAXPATHLEN];
        !           210:        int              c;
        !           211:        DB              *db;
        !           212:        DBT              key, val;
        !           213:        size_t           ksz, vsz;
        !           214:        BTREEINFO        info;
        !           215:        extern int       optind;
        !           216:        extern char     *optarg;
        !           217:
        !           218:        f = MANDOC_DB;
        !           219:
        !           220:        progname = strrchr(argv[0], '/');
        !           221:        if (progname == NULL)
        !           222:                progname = argv[0];
        !           223:        else
        !           224:                ++progname;
        !           225:
        !           226:        while (-1 != (c = getopt(argc, argv, "f:V")))
        !           227:                switch (c) {
        !           228:                case ('f'):
        !           229:                        f = optarg;
        !           230:                        break;
        !           231:                case ('V'):
        !           232:                        version();
        !           233:                        return((int)MANDOCLEVEL_OK);
        !           234:                default:
        !           235:                        usage();
        !           236:                        return((int)MANDOCLEVEL_BADARG);
        !           237:                }
        !           238:
        !           239:        argc -= optind;
        !           240:        argv += optind;
        !           241:
        !           242:        /*
        !           243:         * Set up a temporary file-name into which we're going to write
        !           244:         * all of our data.  This is securely renamed to the real
        !           245:         * file-name after we've written all of our data.
        !           246:         */
        !           247:
        !           248:        if (0 == (sz = strlen(f)) || sz + 5 >= MAXPATHLEN) {
        !           249:                fprintf(stderr, "%s: Bad filename\n", progname);
        !           250:                exit((int)MANDOCLEVEL_SYSERR);
        !           251:        }
        !           252:
        !           253:        memcpy(fbuf, f, sz);
        !           254:        memcpy(fbuf + (int)sz, ".bak", 4);
        !           255:        fbuf[(int)sz + 4] = '\0';
        !           256:
        !           257:        /*
        !           258:         * Open a BTREE database that allows duplicates.  If the
        !           259:         * database already exists (it's a backup anyway), then blow it
        !           260:         * away with O_TRUNC.
        !           261:         */
        !           262:
        !           263:        memset(&info, 0, sizeof(BTREEINFO));
        !           264:        info.flags = R_DUP;
        !           265:
        !           266:        db = dbopen(fbuf, O_CREAT|O_TRUNC|O_RDWR,
        !           267:                        0644, DB_BTREE, &info);
        !           268:
        !           269:        if (NULL == db) {
        !           270:                perror(f);
        !           271:                exit((int)MANDOCLEVEL_SYSERR);
        !           272:        }
        !           273:
        !           274:        /* Use the auto-parser and don't report any errors. */
        !           275:
        !           276:        mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
        !           277:
        !           278:        /*
        !           279:         * Try parsing the manuals given on the command line.  If we
        !           280:         * totally fail, then just keep on going.  Take resulting trees
        !           281:         * and push them down into the database code.
        !           282:         */
        !           283:
        !           284:        memset(&key, 0, sizeof(DBT));
        !           285:        memset(&val, 0, sizeof(DBT));
        !           286:        ksz = vsz = 0;
        !           287:
        !           288:        while (NULL != (fn = *argv++)) {
        !           289:                printf("Trying: %s\n", fn);
        !           290:                mparse_reset(mp);
        !           291:                if (mparse_readfd(mp, -1, fn) >= MANDOCLEVEL_FATAL)
        !           292:                        continue;
        !           293:                mparse_result(mp, &mdoc, &man);
        !           294:                if (mdoc)
        !           295:                        pmdoc(db, fbuf, &key, &ksz,
        !           296:                                &val, &vsz, fn, mdoc);
        !           297:        }
        !           298:
        !           299:        (*db->close)(db);
        !           300:        mparse_free(mp);
        !           301:
        !           302:        free(key.data);
        !           303:        free(val.data);
        !           304:
        !           305:        /* Atomically replace the file with our temporary one. */
        !           306:
        !           307:        if (-1 == rename(fbuf, f))
        !           308:                perror(f);
        !           309:
        !           310:        return((int)MANDOCLEVEL_OK);
        !           311: }
        !           312:
        !           313: /*
        !           314:  * Initialise the stored database key whose data buffer is shared
        !           315:  * between uses (as the key must sometimes be constructed from an array
        !           316:  * of
        !           317:  */
        !           318: static void
        !           319: dbt_init(DBT *key, size_t *ksz)
        !           320: {
        !           321:
        !           322:        if (0 == *ksz) {
        !           323:                assert(0 == key->size);
        !           324:                assert(NULL == key->data);
        !           325:                key->data = mandoc_malloc(MANDOC_BUFSZ);
        !           326:                *ksz = MANDOC_BUFSZ;
        !           327:        }
        !           328:
        !           329:        key->size = 0;
        !           330: }
        !           331:
        !           332: /*
        !           333:  * Append a binary value to a database entry.  This can be invoked
        !           334:  * multiple times; the buffer is automatically resized.
        !           335:  */
        !           336: static void
        !           337: dbt_appendb(DBT *key, size_t *ksz, const void *cp, size_t sz)
        !           338: {
        !           339:
        !           340:        assert(key->data);
        !           341:
        !           342:        /* Overshoot by MANDOC_BUFSZ. */
        !           343:
        !           344:        while (key->size + sz >= *ksz) {
        !           345:                *ksz = key->size + sz + MANDOC_BUFSZ;
        !           346:                *ksz = *ksz + (4 - (*ksz % 4));
        !           347:                key->data = mandoc_realloc(key->data, *ksz);
        !           348:        }
        !           349:
        !           350:        memcpy(key->data + (int)key->size, cp, sz);
        !           351:        key->size += sz;
        !           352: }
        !           353:
        !           354: /*
        !           355:  * Append a nil-terminated string to the database entry.  This can be
        !           356:  * invoked multiple times.  The database entry will be nil-terminated as
        !           357:  * well; if invoked multiple times, a space is put between strings.
        !           358:  */
        !           359: static void
        !           360: dbt_append(DBT *key, size_t *ksz, const char *cp)
        !           361: {
        !           362:        size_t           sz;
        !           363:
        !           364:        assert(key->data);
        !           365:        assert(key->size <= *ksz);
        !           366:
        !           367:        if (0 == (sz = strlen(cp)))
        !           368:                return;
        !           369:
        !           370:        /* Overshoot by MANDOC_BUFSZ (and nil terminator). */
        !           371:
        !           372:        while (key->size + sz + 1 >= *ksz) {
        !           373:                *ksz = key->size + sz + 1 + MANDOC_BUFSZ;
        !           374:                *ksz = *ksz + (4 - (*ksz % 4));
        !           375:                key->data = mandoc_realloc(key->data, *ksz);
        !           376:        }
        !           377:
        !           378:        /* Space-separate appended tokens. */
        !           379:
        !           380:        if (key->size)
        !           381:                ((char *)key->data)[(int)key->size - 1] = ' ';
        !           382:
        !           383:        memcpy(key->data + (int)key->size, cp, sz + 1);
        !           384:        key->size += sz + 1;
        !           385: }
        !           386:
        !           387: /* ARGSUSED */
        !           388: static void
        !           389: pmdoc_Fd(MDOC_ARGS)
        !           390: {
        !           391:        uint32_t         fl;
        !           392:        const char      *start, *end;
        !           393:        size_t           sz;
        !           394:        char             nil;
        !           395:
        !           396:        if (SEC_SYNOPSIS != n->sec)
        !           397:                return;
        !           398:        if (NULL == (n = n->child) || MDOC_TEXT != n->type)
        !           399:                return;
        !           400:        if (strcmp("#include", n->string))
        !           401:                return;
        !           402:        if (NULL == (n = n->next) || MDOC_TEXT != n->type)
        !           403:                return;
        !           404:
        !           405:        start = n->string;
        !           406:        if ('<' == *start)
        !           407:                start++;
        !           408:
        !           409:        if (0 == (sz = strlen(start)))
        !           410:                return;
        !           411:
        !           412:        end = &start[(int)sz - 1];
        !           413:        if ('>' == *end)
        !           414:                end--;
        !           415:
        !           416:        nil = '\0';
        !           417:        dbt_appendb(key, ksz, start, end - start + 1);
        !           418:        dbt_appendb(key, ksz, &nil, 1);
        !           419:
        !           420:        fl = MANDOC_INCLUDES;
        !           421:        memcpy(val->data, &fl, 4);
        !           422: }
        !           423:
        !           424: /* ARGSUSED */
        !           425: static void
        !           426: pmdoc_In(MDOC_ARGS)
        !           427: {
        !           428:        uint32_t         fl;
        !           429:
        !           430:        if (SEC_SYNOPSIS != n->sec)
        !           431:                return;
        !           432:        if (NULL == n->child || MDOC_TEXT != n->child->type)
        !           433:                return;
        !           434:
        !           435:        dbt_append(key, ksz, n->child->string);
        !           436:        fl = MANDOC_INCLUDES;
        !           437:        memcpy(val->data, &fl, 4);
        !           438: }
        !           439:
        !           440: /* ARGSUSED */
        !           441: static void
        !           442: pmdoc_Fn(MDOC_ARGS)
        !           443: {
        !           444:        uint32_t         fl;
        !           445:        const char      *cp;
        !           446:
        !           447:        if (SEC_SYNOPSIS != n->sec)
        !           448:                return;
        !           449:        if (NULL == n->child || MDOC_TEXT != n->child->type)
        !           450:                return;
        !           451:
        !           452:        /* .Fn "struct type *arg" "foo" */
        !           453:
        !           454:        cp = strrchr(n->child->string, ' ');
        !           455:        if (NULL == cp)
        !           456:                cp = n->child->string;
        !           457:
        !           458:        /* Ignore pointers. */
        !           459:
        !           460:        while ('*' == *cp)
        !           461:                cp++;
        !           462:
        !           463:        dbt_append(key, ksz, cp);
        !           464:        fl = MANDOC_FUNCTION;
        !           465:        memcpy(val->data, &fl, 4);
        !           466: }
        !           467:
        !           468: /* ARGSUSED */
        !           469: static void
        !           470: pmdoc_Vt(MDOC_ARGS)
        !           471: {
        !           472:        uint32_t         fl;
        !           473:        const char      *start, *end;
        !           474:        size_t           sz;
        !           475:        char             nil;
        !           476:
        !           477:        if (SEC_SYNOPSIS != n->sec)
        !           478:                return;
        !           479:        if (MDOC_Vt == n->tok && MDOC_BODY != n->type)
        !           480:                return;
        !           481:        if (NULL == n->child || MDOC_TEXT != n->child->type)
        !           482:                return;
        !           483:
        !           484:        /*
        !           485:         * Strip away leading '*' and trailing ';'.
        !           486:         */
        !           487:
        !           488:        start = n->last->string;
        !           489:
        !           490:        while ('*' == *start)
        !           491:                start++;
        !           492:
        !           493:        if (0 == (sz = strlen(start)))
        !           494:                return;
        !           495:
        !           496:        end = &start[sz - 1];
        !           497:        while (end > start && ';' == *end)
        !           498:                end--;
        !           499:
        !           500:        if (end == start)
        !           501:                return;
        !           502:
        !           503:        nil = '\0';
        !           504:        dbt_appendb(key, ksz, start, end - start + 1);
        !           505:        dbt_appendb(key, ksz, &nil, 1);
        !           506:        fl = MANDOC_VARIABLE;
        !           507:        memcpy(val->data, &fl, 4);
        !           508: }
        !           509:
        !           510: /* ARGSUSED */
        !           511: static void
        !           512: pmdoc_Fo(MDOC_ARGS)
        !           513: {
        !           514:        uint32_t         fl;
        !           515:
        !           516:        if (SEC_SYNOPSIS != n->sec || MDOC_HEAD != n->type)
        !           517:                return;
        !           518:        if (NULL == n->child || MDOC_TEXT != n->child->type)
        !           519:                return;
        !           520:
        !           521:        dbt_append(key, ksz, n->child->string);
        !           522:        fl = MANDOC_FUNCTION;
        !           523:        memcpy(val->data, &fl, 4);
        !           524: }
        !           525:
        !           526: /* ARGSUSED */
        !           527: static void
        !           528: pmdoc_Nm(MDOC_ARGS)
        !           529: {
        !           530:        uint32_t         fl;
        !           531:
        !           532:        if (SEC_NAME == n->sec) {
        !           533:                for (n = n->child; n; n = n->next) {
        !           534:                        if (MDOC_TEXT != n->type)
        !           535:                                continue;
        !           536:                        dbt_append(key, ksz, n->string);
        !           537:                }
        !           538:                fl = MANDOC_NAME;
        !           539:                memcpy(val->data, &fl, 4);
        !           540:                return;
        !           541:        } else if (SEC_SYNOPSIS != n->sec || MDOC_HEAD != n->type)
        !           542:                return;
        !           543:
        !           544:        for (n = n->child; n; n = n->next) {
        !           545:                if (MDOC_TEXT != n->type)
        !           546:                        continue;
        !           547:                dbt_append(key, ksz, n->string);
        !           548:        }
        !           549:
        !           550:        fl = MANDOC_UTILITY;
        !           551:        memcpy(val->data, &fl, 4);
        !           552: }
        !           553:
        !           554: /*
        !           555:  * Call out to per-macro handlers after clearing the persistent database
        !           556:  * key.  If the macro sets the database key, flush it to the database.
        !           557:  */
        !           558: static void
        !           559: pmdoc_node(MDOC_ARGS)
        !           560: {
        !           561:
        !           562:        if (NULL == n)
        !           563:                return;
        !           564:
        !           565:        switch (n->type) {
        !           566:        case (MDOC_HEAD):
        !           567:                /* FALLTHROUGH */
        !           568:        case (MDOC_BODY):
        !           569:                /* FALLTHROUGH */
        !           570:        case (MDOC_TAIL):
        !           571:                /* FALLTHROUGH */
        !           572:        case (MDOC_BLOCK):
        !           573:                /* FALLTHROUGH */
        !           574:        case (MDOC_ELEM):
        !           575:                if (NULL == mdocs[n->tok])
        !           576:                        break;
        !           577:
        !           578:                dbt_init(key, ksz);
        !           579:                (*mdocs[n->tok])(db, dbn, key, ksz, val, n);
        !           580:
        !           581:                if (0 == key->size)
        !           582:                        break;
        !           583:                if (0 == (*db->put)(db, key, val, 0))
        !           584:                        break;
        !           585:
        !           586:                perror(dbn);
        !           587:                exit((int)MANDOCLEVEL_SYSERR);
        !           588:                /* NOTREACHED */
        !           589:        default:
        !           590:                break;
        !           591:        }
        !           592:
        !           593:        pmdoc_node(db, dbn, key, ksz, val, n->child);
        !           594:        pmdoc_node(db, dbn, key, ksz, val, n->next);
        !           595: }
        !           596:
        !           597: static void
        !           598: pmdoc(DB *db, const char *dbn,
        !           599:                DBT *key, size_t *ksz,
        !           600:                DBT *val, size_t *valsz,
        !           601:                const char *path, struct mdoc *m)
        !           602: {
        !           603:        uint32_t         flag;
        !           604:
        !           605:        flag = MANDOC_NONE;
        !           606:
        !           607:        /*
        !           608:         * Database values are a 4-byte bit-field followed by the path
        !           609:         * of the manual.  Allocate all the space we'll need now; we
        !           610:         * change the bit-field depending on the key type.
        !           611:         */
        !           612:
        !           613:        dbt_init(val, valsz);
        !           614:        dbt_appendb(val, valsz, &flag, 4);
        !           615:        dbt_append(val, valsz, path);
        !           616:
        !           617:        pmdoc_node(db, dbn, key, ksz, val, mdoc_node(m));
        !           618: }
        !           619:
        !           620: static void
        !           621: version(void)
        !           622: {
        !           623:
        !           624:        printf("%s %s\n", progname, VERSION);
        !           625: }
        !           626:
        !           627: static void
        !           628: usage(void)
        !           629: {
        !           630:
        !           631:        fprintf(stderr, "usage: %s "
        !           632:                        "[-V] "
        !           633:                        "[-f path] "
        !           634:                        "[file...]\n",
        !           635:                        progname);
        !           636: }

CVSweb