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

Annotation of mandoc/mdoc.c, Revision 1.1

1.1     ! kristaps    1: /* $Id: roff.c,v 1.64 2008/12/12 10:11:10 kristaps Exp $ */
        !             2: /*
        !             3:  * Copyright (c) 2008 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 <ctype.h>
        !            21: #include <err.h>
        !            22: #include <stdarg.h>
        !            23: #include <stdlib.h>
        !            24: #include <stdio.h>
        !            25: #include <string.h>
        !            26:
        !            27: #include "private.h"
        !            28:
        !            29: extern int     macro_text(struct mdoc *, int, int, int *, char *);
        !            30: extern int     macro_scoped_implicit(struct mdoc *,
        !            31:                        int, int, int *, char *);
        !            32:
        !            33: const  char *const __mdoc_macronames[MDOC_MAX] = {
        !            34:        "\\\"",         "Dd",           "Dt",           "Os",
        !            35:        "Sh",           "Ss",           "Pp",           "D1",
        !            36:        "Dl",           "Bd",           "Ed",           "Bl",
        !            37:        "El",           "It",           "Ad",           "An",
        !            38:        "Ar",           "Cd",           "Cm",           "Dv",
        !            39:        "Er",           "Ev",           "Ex",           "Fa",
        !            40:        "Fd",           "Fl",           "Fn",           "Ft",
        !            41:        "Ic",           "In",           "Li",           "Nd",
        !            42:        "Nm",           "Op",           "Ot",           "Pa",
        !            43:        "Rv",           "St",           "Va",           "Vt",
        !            44:        /* LINTED */
        !            45:        "Xr",           "\%A",          "\%B",          "\%D",
        !            46:        /* LINTED */
        !            47:        "\%I",          "\%J",          "\%N",          "\%O",
        !            48:        /* LINTED */
        !            49:        "\%P",          "\%R",          "\%T",          "\%V",
        !            50:        "Ac",           "Ao",           "Aq",           "At",
        !            51:        "Bc",           "Bf",           "Bo",           "Bq",
        !            52:        "Bsx",          "Bx",           "Db",           "Dc",
        !            53:        "Do",           "Dq",           "Ec",           "Ef",
        !            54:        "Em",           "Eo",           "Fx",           "Ms",
        !            55:        "No",           "Ns",           "Nx",           "Ox",
        !            56:        "Pc",           "Pf",           "Po",           "Pq",
        !            57:        "Qc",           "Ql",           "Qo",           "Qq",
        !            58:        "Re",           "Rs",           "Sc",           "So",
        !            59:        "Sq",           "Sm",           "Sx",           "Sy",
        !            60:        "Tn",           "Ux",           "Xc",           "Xo",
        !            61:        "Fo",           "Fc",           "Oo",           "Oc",
        !            62:        "Bk",           "Ek",           "Bt",           "Hf",
        !            63:        "Fr",           "Ud",
        !            64:        };
        !            65:
        !            66: const  char *const __mdoc_argnames[MDOC_ARG_MAX] = {
        !            67:        "split",                "nosplit",              "ragged",
        !            68:        "unfilled",             "literal",              "file",
        !            69:        "offset",               "bullet",               "dash",
        !            70:        "hyphen",               "item",                 "enum",
        !            71:        "tag",                  "diag",                 "hang",
        !            72:        "ohang",                "inset",                "column",
        !            73:        "width",                "compact",              "std",
        !            74:        "p1003.1-88",           "p1003.1-90",           "p1003.1-96",
        !            75:        "p1003.1-2001",         "p1003.1-2004",         "p1003.1",
        !            76:        "p1003.1b",             "p1003.1b-93",          "p1003.1c-95",
        !            77:        "p1003.1g-2000",        "p1003.2-92",           "p1387.2-95",
        !            78:        "p1003.2",              "p1387.2",              "isoC-90",
        !            79:        "isoC-amd1",            "isoC-tcor1",           "isoC-tcor2",
        !            80:        "isoC-99",              "ansiC",                "ansiC-89",
        !            81:        "ansiC-99",             "ieee754",              "iso8802-3",
        !            82:        "xpg3",                 "xpg4",                 "xpg4.2",
        !            83:        "xpg4.3",               "xbd5",                 "xcu5",
        !            84:        "xsh5",                 "xns5",                 "xns5.2d2.0",
        !            85:        "xcurses4.2",           "susv2",                "susv3",
        !            86:        "svid4",                "filled",               "words",
        !            87:        };
        !            88:
        !            89: const  struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
        !            90:        { NULL, 0 }, /* \" */
        !            91:        { NULL, 0 }, /* Dd */
        !            92:        { NULL, 0 }, /* Dt */
        !            93:        { NULL, 0 }, /* Os */
        !            94:        { macro_scoped_implicit, 0 }, /* Sh */
        !            95:        { macro_scoped_implicit, 0 }, /* Ss */
        !            96:        { NULL, 0 }, /* Pp */
        !            97:        { NULL, 0 }, /* D1 */
        !            98:        { NULL, 0 }, /* Dl */
        !            99:        { NULL, 0 }, /* Bd */
        !           100:        { NULL, 0 }, /* Ed */
        !           101:        { NULL, 0 }, /* Bl */
        !           102:        { NULL, 0 }, /* El */
        !           103:        { NULL, 0 }, /* It */
        !           104:        { macro_text, MDOC_CALLABLE }, /* Ad */
        !           105:        { NULL, 0 }, /* An */
        !           106:        { macro_text, MDOC_CALLABLE }, /* Ar */
        !           107:        { NULL, 0 }, /* Cd */
        !           108:        { macro_text, MDOC_CALLABLE }, /* Cm */
        !           109:        { macro_text, MDOC_CALLABLE }, /* Dv */
        !           110:        { macro_text, MDOC_CALLABLE }, /* Er */
        !           111:        { macro_text, MDOC_CALLABLE }, /* Ev */
        !           112:        { NULL, 0 }, /* Ex */
        !           113:        { macro_text, MDOC_CALLABLE }, /* Fa */
        !           114:        { NULL, 0 }, /* Fd */
        !           115:        { macro_text, MDOC_CALLABLE }, /* Fl */
        !           116:        { NULL, 0 }, /* Fn */
        !           117:        { macro_text, 0 }, /* Ft */
        !           118:        { macro_text, MDOC_CALLABLE }, /* Ic */
        !           119:        { NULL, 0 }, /* In */
        !           120:        { macro_text, MDOC_CALLABLE }, /* Li */
        !           121:        { NULL, 0 }, /* Nd */
        !           122:        { NULL, 0 }, /* Nm */
        !           123:        { NULL, 0 }, /* Op */
        !           124:        { NULL, 0 }, /* Ot */
        !           125:        { macro_text, MDOC_CALLABLE }, /* Pa */
        !           126:        { NULL, 0 }, /* Rv */
        !           127:        { NULL, 0 }, /* St */
        !           128:        { macro_text, MDOC_CALLABLE }, /* Va */
        !           129:        { macro_text, MDOC_CALLABLE }, /* Vt */
        !           130:        { NULL, 0 }, /* Xr */
        !           131:        { NULL, 0 }, /* %A */
        !           132:        { NULL, 0 }, /* %B */
        !           133:        { NULL, 0 }, /* %D */
        !           134:        { NULL, 0 }, /* %I */
        !           135:        { NULL, 0 }, /* %J */
        !           136:        { NULL, 0 }, /* %N */
        !           137:        { NULL, 0 }, /* %O */
        !           138:        { NULL, 0 }, /* %P */
        !           139:        { NULL, 0 }, /* %R */
        !           140:        { NULL, 0 }, /* %T */
        !           141:        { NULL, 0 }, /* %V */
        !           142:        { NULL, 0 }, /* Ac */
        !           143:        { NULL, 0 }, /* Ao */
        !           144:        { NULL, 0 }, /* Aq */
        !           145:        { NULL, 0 }, /* At */
        !           146:        { NULL, 0 }, /* Bc */
        !           147:        { NULL, 0 }, /* Bf */
        !           148:        { NULL, 0 }, /* Bo */
        !           149:        { NULL, 0 }, /* Bq */
        !           150:        { NULL, 0 }, /* Bsx */
        !           151:        { NULL, 0 }, /* Bx */
        !           152:        { NULL, 0 }, /* Db */
        !           153:        { NULL, 0 }, /* Dc */
        !           154:        { NULL, 0 }, /* Do */
        !           155:        { NULL, 0 }, /* Dq */
        !           156:        { NULL, 0 }, /* Ec */
        !           157:        { NULL, 0 }, /* Ef */
        !           158:        { macro_text, MDOC_CALLABLE }, /* Em */
        !           159:        { NULL, 0 }, /* Eo */
        !           160:        { NULL, 0 }, /* Fx */
        !           161:        { macro_text, 0 }, /* Ms */
        !           162:        { NULL, 0 }, /* No */
        !           163:        { NULL, 0 }, /* Ns */
        !           164:        { NULL, 0 }, /* Nx */
        !           165:        { NULL, 0 }, /* Ox */
        !           166:        { NULL, 0 }, /* Pc */
        !           167:        { NULL, 0 }, /* Pf */
        !           168:        { NULL, 0 }, /* Po */
        !           169:        { NULL, 0 }, /* Pq */
        !           170:        { NULL, 0 }, /* Qc */
        !           171:        { NULL, 0 }, /* Ql */
        !           172:        { NULL, 0 }, /* Qo */
        !           173:        { NULL, 0 }, /* Qq */
        !           174:        { NULL, 0 }, /* Re */
        !           175:        { NULL, 0 }, /* Rs */
        !           176:        { NULL, 0 }, /* Sc */
        !           177:        { NULL, 0 }, /* So */
        !           178:        { NULL, 0 }, /* Sq */
        !           179:        { NULL, 0 }, /* Sm */
        !           180:        { NULL, 0 }, /* Sx */
        !           181:        { NULL, 0 }, /* Sy */
        !           182:        { macro_text, MDOC_CALLABLE }, /* Tn */
        !           183:        { NULL, 0 }, /* Ux */
        !           184:        { NULL, 0 }, /* Xc */
        !           185:        { NULL, 0 }, /* Xo */
        !           186:        { NULL, 0 }, /* Fo */
        !           187:        { NULL, 0 }, /* Fc */
        !           188:        { NULL, 0 }, /* Oo */
        !           189:        { NULL, 0 }, /* Oc */
        !           190:        { NULL, 0 }, /* Bk */
        !           191:        { NULL, 0 }, /* Ek */
        !           192:        { NULL, 0 }, /* Bt */
        !           193:        { NULL, 0 }, /* Hf */
        !           194:        { NULL, 0 }, /* Fr */
        !           195:        { NULL, 0 }, /* Ud */
        !           196: };
        !           197:
        !           198: const  char * const *mdoc_macronames = __mdoc_macronames;
        !           199: const  char * const *mdoc_argnames = __mdoc_argnames;
        !           200: const  struct mdoc_macro * const mdoc_macros = __mdoc_macros;
        !           201:
        !           202:
        !           203: static void             *xcalloc(size_t, size_t);
        !           204: static char             *xstrdup(const char *);
        !           205:
        !           206: static struct mdoc_arg  *argdup(size_t, const struct mdoc_arg *);
        !           207: static void              argfree(size_t, struct mdoc_arg *);
        !           208: static void              argcpy(struct mdoc_arg *,
        !           209:                                const struct mdoc_arg *);
        !           210: static char            **paramdup(size_t, const char **);
        !           211: static void              paramfree(size_t, char **);
        !           212:
        !           213: static void              mdoc_node_freelist(struct mdoc_node *);
        !           214: static void              mdoc_node_append(struct mdoc *, int,
        !           215:                                struct mdoc_node *);
        !           216: static void              mdoc_elem_free(struct mdoc_elem *);
        !           217: static void              mdoc_text_free(struct mdoc_text *);
        !           218:
        !           219:
        !           220: const struct mdoc_node *
        !           221: mdoc_result(struct mdoc *mdoc)
        !           222: {
        !           223:
        !           224:        return(mdoc->first);
        !           225: }
        !           226:
        !           227:
        !           228: void
        !           229: mdoc_free(struct mdoc *mdoc)
        !           230: {
        !           231:
        !           232:        if (mdoc->first)
        !           233:                mdoc_node_freelist(mdoc->first);
        !           234:        if (mdoc->htab)
        !           235:                mdoc_hash_free(mdoc->htab);
        !           236:
        !           237:        free(mdoc);
        !           238: }
        !           239:
        !           240:
        !           241: struct mdoc *
        !           242: mdoc_alloc(void *data, const struct mdoc_cb *cb)
        !           243: {
        !           244:        struct mdoc     *p;
        !           245:
        !           246:        p = xcalloc(1, sizeof(struct mdoc));
        !           247:
        !           248:        p->data = data;
        !           249:        (void)memcpy(&p->cb, cb, sizeof(struct mdoc_cb));
        !           250:
        !           251:        p->htab = mdoc_hash_alloc();
        !           252:        return(p);
        !           253: }
        !           254:
        !           255:
        !           256: static void *
        !           257: xcalloc(size_t num, size_t sz)
        !           258: {
        !           259:        void            *p;
        !           260:
        !           261:        if (NULL == (p = calloc(num, sz)))
        !           262:                err(EXIT_FAILURE, "calloc");
        !           263:        return(p);
        !           264: }
        !           265:
        !           266:
        !           267: static char *
        !           268: xstrdup(const char *p)
        !           269: {
        !           270:        char            *pp;
        !           271:
        !           272:        if (NULL == (pp = strdup(p)))
        !           273:                err(EXIT_FAILURE, "strdup");
        !           274:        return(pp);
        !           275: }
        !           276:
        !           277:
        !           278: int
        !           279: mdoc_parseln(struct mdoc *mdoc, char *buf)
        !           280: {
        !           281:        int               c, i;
        !           282:        char              tmp[5];
        !           283:
        !           284:        if ('.' != *buf)  {
        !           285:                /* TODO. */
        !           286:                return(1);
        !           287:        }
        !           288:
        !           289:        if (buf[1] && '\\' == buf[1])
        !           290:                if (buf[2] && '\"' == buf[2])
        !           291:                        return(1);
        !           292:
        !           293:        i = 1;
        !           294:        while (buf[i] && ! isspace(buf[i]) && i < (int)sizeof(tmp))
        !           295:                i++;
        !           296:
        !           297:        if (i == (int)sizeof(tmp))
        !           298:                return(mdoc_err(mdoc, -1, 1, ERR_MACRO_NOTSUP));
        !           299:        else if (i <= 2)
        !           300:                return(mdoc_err(mdoc, -1, 1, ERR_MACRO_NOTSUP));
        !           301:
        !           302:        i--;
        !           303:
        !           304:        (void)memcpy(tmp, buf + 1, i);
        !           305:        tmp[i++] = 0;
        !           306:
        !           307:        if (MDOC_MAX == (c = mdoc_find(mdoc, tmp)))
        !           308:                return(mdoc_err(mdoc, c, 1, ERR_MACRO_NOTSUP));
        !           309:
        !           310:        while (buf[i] && isspace(buf[i]))
        !           311:                i++;
        !           312:
        !           313:        if (NULL == (mdoc_macros[c].fp)) {
        !           314:                (void)mdoc_err(mdoc, c, 1, ERR_MACRO_NOTSUP);
        !           315:                return(0);
        !           316:        }
        !           317:
        !           318:        return((*mdoc_macros[c].fp)(mdoc, c, 1, &i, buf));
        !           319: }
        !           320:
        !           321:
        !           322: void
        !           323: mdoc_msg(struct mdoc *mdoc, int pos, const char *fmt, ...)
        !           324: {
        !           325:        va_list          ap;
        !           326:        char             buf[256];
        !           327:
        !           328:        if (NULL == mdoc->cb.mdoc_msg)
        !           329:                return;
        !           330:
        !           331:        va_start(ap, fmt);
        !           332:        (void)vsnprintf(buf, sizeof(buf), fmt, ap);
        !           333:        va_end(ap);
        !           334:
        !           335:        (*mdoc->cb.mdoc_msg)(mdoc->data, pos, buf);
        !           336: }
        !           337:
        !           338:
        !           339: int
        !           340: mdoc_err(struct mdoc *mdoc, int tok, int pos, enum mdoc_err type)
        !           341: {
        !           342:
        !           343:        if (NULL == mdoc->cb.mdoc_err)
        !           344:                return(0);
        !           345:        return((*mdoc->cb.mdoc_err)(mdoc->data, tok, pos, type));
        !           346: }
        !           347:
        !           348:
        !           349: int
        !           350: mdoc_warn(struct mdoc *mdoc, int tok, int pos, enum mdoc_warn type)
        !           351: {
        !           352:
        !           353:        if (NULL == mdoc->cb.mdoc_warn)
        !           354:                return(0);
        !           355:        return((*mdoc->cb.mdoc_warn)(mdoc->data, tok, pos, type));
        !           356: }
        !           357:
        !           358:
        !           359: int
        !           360: mdoc_macro(struct mdoc *mdoc, int tok, int ppos, int *pos, char *buf)
        !           361: {
        !           362:
        !           363:        if (NULL == (mdoc_macros[tok].fp)) {
        !           364:                (void)mdoc_err(mdoc, tok, ppos, ERR_MACRO_NOTSUP);
        !           365:                return(0);
        !           366:        } else if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
        !           367:                (void)mdoc_err(mdoc, tok, ppos, ERR_MACRO_NOTCALL);
        !           368:                return(0);
        !           369:        }
        !           370:
        !           371:        return((*mdoc_macros[tok].fp)(mdoc, tok, ppos, pos, buf));
        !           372: }
        !           373:
        !           374:
        !           375: static void
        !           376: mdoc_node_append(struct mdoc *mdoc, int pos, struct mdoc_node *p)
        !           377: {
        !           378:        const char       *nn, *on, *nt, *ot, *act;
        !           379:
        !           380:        switch (p->type) {
        !           381:        case (MDOC_TEXT):
        !           382:                nn = "<text>";
        !           383:                nt = "text";
        !           384:                break;
        !           385:        case (MDOC_BODY):
        !           386:                nn = mdoc_macronames[p->data.body.tok];
        !           387:                nt = "body";
        !           388:                break;
        !           389:        case (MDOC_ELEM):
        !           390:                nn = mdoc_macronames[p->data.elem.tok];
        !           391:                nt = "elem";
        !           392:                break;
        !           393:        case (MDOC_HEAD):
        !           394:                nn = mdoc_macronames[p->data.head.tok];
        !           395:                nt = "head";
        !           396:                break;
        !           397:        case (MDOC_BLOCK):
        !           398:                nn = mdoc_macronames[p->data.block.tok];
        !           399:                nt = "block";
        !           400:                break;
        !           401:        }
        !           402:
        !           403:        if (NULL == mdoc->first) {
        !           404:                assert(NULL == mdoc->last);
        !           405:                mdoc->first = p;
        !           406:                mdoc->last = p;
        !           407:                mdoc_msg(mdoc, pos, "parse: root %s `%s'", nt, nn);
        !           408:                return;
        !           409:        }
        !           410:
        !           411:        switch (mdoc->last->type) {
        !           412:        case (MDOC_TEXT):
        !           413:                on = "<text>";
        !           414:                ot = "text";
        !           415:                break;
        !           416:        case (MDOC_BODY):
        !           417:                on = mdoc_macronames[mdoc->last->data.body.tok];
        !           418:                ot = "body";
        !           419:                break;
        !           420:        case (MDOC_ELEM):
        !           421:                on = mdoc_macronames[mdoc->last->data.elem.tok];
        !           422:                ot = "elem";
        !           423:                break;
        !           424:        case (MDOC_HEAD):
        !           425:                on = mdoc_macronames[mdoc->last->data.head.tok];
        !           426:                ot = "head";
        !           427:                break;
        !           428:        case (MDOC_BLOCK):
        !           429:                on = mdoc_macronames[mdoc->last->data.block.tok];
        !           430:                ot = "block";
        !           431:                break;
        !           432:        }
        !           433:
        !           434:        switch (p->type) {
        !           435:        case (MDOC_BODY):
        !           436:                switch (mdoc->last->type) {
        !           437:                case (MDOC_BLOCK):
        !           438:                        p->parent = mdoc->last;
        !           439:                        mdoc->last->child = p;
        !           440:                        act = "child";
        !           441:                        break;
        !           442:                case (MDOC_HEAD):
        !           443:                        p->parent = mdoc->last->parent;
        !           444:                        mdoc->last->next = p;
        !           445:                        act = "sibling";
        !           446:                        break;
        !           447:                default:
        !           448:                        abort();
        !           449:                        /* NOTREACHED */
        !           450:                }
        !           451:                break;
        !           452:        case (MDOC_HEAD):
        !           453:                assert(mdoc->last->type == MDOC_BLOCK);
        !           454:                p->parent = mdoc->last;
        !           455:                mdoc->last->child = p;
        !           456:                act = "child";
        !           457:                break;
        !           458:        default:
        !           459:                switch (mdoc->last->type) {
        !           460:                case (MDOC_BODY):
        !           461:                        /* FALLTHROUGH */
        !           462:                case (MDOC_HEAD):
        !           463:                        p->parent = mdoc->last->parent;
        !           464:                        mdoc->last->child = p;
        !           465:                        act = "child";
        !           466:                        break;
        !           467:                default:
        !           468:                        p->parent = mdoc->last->parent;
        !           469:                        mdoc->last->next = p;
        !           470:                        act = "sibling";
        !           471:                        break;
        !           472:                }
        !           473:                break;
        !           474:        }
        !           475:
        !           476:        mdoc_msg(mdoc, pos, "parse: %s `%s' %s %s `%s'",
        !           477:                        nt, nn, act, ot, on);
        !           478:        mdoc->last = p;
        !           479: }
        !           480:
        !           481:
        !           482: void
        !           483: mdoc_head_alloc(struct mdoc *mdoc, int pos, int tok,
        !           484:                size_t paramsz, const char **params)
        !           485: {
        !           486:        struct mdoc_node *p;
        !           487:
        !           488:        assert(mdoc->first);
        !           489:        assert(mdoc->last);
        !           490:        assert(mdoc->last->type == MDOC_BLOCK);
        !           491:        assert(mdoc->last->data.block.tok == tok);
        !           492:
        !           493:        p = xcalloc(1, sizeof(struct mdoc_node));
        !           494:        p->type = MDOC_HEAD;
        !           495:        p->data.head.tok = tok;
        !           496:        p->data.head.sz = paramsz;
        !           497:        p->data.head.args = paramdup(paramsz, params);
        !           498:
        !           499:        mdoc_node_append(mdoc, pos, p);
        !           500: }
        !           501:
        !           502:
        !           503: void
        !           504: mdoc_body_alloc(struct mdoc *mdoc, int pos, int tok)
        !           505: {
        !           506:        struct mdoc_node *p;
        !           507:
        !           508:        assert(mdoc->first);
        !           509:        assert(mdoc->last);
        !           510:        assert((mdoc->last->type == MDOC_BLOCK) ||
        !           511:                        (mdoc->last->type == MDOC_HEAD));
        !           512:        if (mdoc->last->type == MDOC_BLOCK)
        !           513:                assert(mdoc->last->data.block.tok == tok);
        !           514:        else
        !           515:                assert(mdoc->last->data.head.tok == tok);
        !           516:
        !           517:        p = xcalloc(1, sizeof(struct mdoc_node));
        !           518:
        !           519:        p->type = MDOC_BODY;
        !           520:        p->data.body.tok = tok;
        !           521:
        !           522:        mdoc_node_append(mdoc, pos, p);
        !           523: }
        !           524:
        !           525:
        !           526: void
        !           527: mdoc_block_alloc(struct mdoc *mdoc, int pos, int tok,
        !           528:                size_t argsz, const struct mdoc_arg *args)
        !           529: {
        !           530:        struct mdoc_node *p;
        !           531:
        !           532:        p = xcalloc(1, sizeof(struct mdoc_node));
        !           533:
        !           534:        p->type = MDOC_BLOCK;
        !           535:        p->data.block.tok = tok;
        !           536:        p->data.block.argc = argsz;
        !           537:        p->data.block.argv = argdup(argsz, args);
        !           538:
        !           539:        mdoc_node_append(mdoc, pos, p);
        !           540: }
        !           541:
        !           542:
        !           543: void
        !           544: mdoc_elem_alloc(struct mdoc *mdoc, int pos, int tok,
        !           545:                size_t argsz, const struct mdoc_arg *args,
        !           546:                size_t paramsz, const char **params)
        !           547: {
        !           548:        struct mdoc_node *p;
        !           549:
        !           550:        p = xcalloc(1, sizeof(struct mdoc_node));
        !           551:        p->type = MDOC_ELEM;
        !           552:        p->data.elem.tok = tok;
        !           553:        p->data.elem.sz = paramsz;
        !           554:        p->data.elem.args = paramdup(paramsz, params);
        !           555:        p->data.elem.argc = argsz;
        !           556:        p->data.elem.argv = argdup(argsz, args);
        !           557:
        !           558:        mdoc_node_append(mdoc, pos, p);
        !           559: }
        !           560:
        !           561:
        !           562: void
        !           563: mdoc_word_alloc(struct mdoc *mdoc, int pos, const char *word)
        !           564: {
        !           565:        struct mdoc_node *p;
        !           566:
        !           567:        p = xcalloc(1, sizeof(struct mdoc_node));
        !           568:        p->type = MDOC_TEXT;
        !           569:        p->data.text.string = xstrdup(word);
        !           570:
        !           571:        mdoc_node_append(mdoc, pos, p);
        !           572: }
        !           573:
        !           574:
        !           575: static void
        !           576: argfree(size_t sz, struct mdoc_arg *p)
        !           577: {
        !           578:        size_t           i, j;
        !           579:
        !           580:        if (0 == sz)
        !           581:                return;
        !           582:
        !           583:        assert(p);
        !           584:        for (i = 0; i < sz; i++)
        !           585:                if (p[i].sz > 0) {
        !           586:                        assert(p[i].value);
        !           587:                        for (j = 0; j < p[i].sz; j++)
        !           588:                                free(p[i].value[j]);
        !           589:                }
        !           590:        free(p);
        !           591: }
        !           592:
        !           593:
        !           594: static void
        !           595: mdoc_elem_free(struct mdoc_elem *p)
        !           596: {
        !           597:
        !           598:        paramfree(p->sz, p->args);
        !           599:        argfree(p->argc, p->argv);
        !           600: }
        !           601:
        !           602:
        !           603: static void
        !           604: mdoc_block_free(struct mdoc_block *p)
        !           605: {
        !           606:
        !           607:        argfree(p->argc, p->argv);
        !           608: }
        !           609:
        !           610:
        !           611: static void
        !           612: mdoc_text_free(struct mdoc_text *p)
        !           613: {
        !           614:
        !           615:        if (p->string)
        !           616:                free(p->string);
        !           617: }
        !           618:
        !           619:
        !           620: static void
        !           621: mdoc_head_free(struct mdoc_head *p)
        !           622: {
        !           623:
        !           624:        paramfree(p->sz, p->args);
        !           625: }
        !           626:
        !           627:
        !           628: void
        !           629: mdoc_node_free(struct mdoc_node *p)
        !           630: {
        !           631:
        !           632:        switch (p->type) {
        !           633:        case (MDOC_TEXT):
        !           634:                mdoc_text_free(&p->data.text);
        !           635:                break;
        !           636:        case (MDOC_ELEM):
        !           637:                mdoc_elem_free(&p->data.elem);
        !           638:                break;
        !           639:        case (MDOC_BLOCK):
        !           640:                mdoc_block_free(&p->data.block);
        !           641:                break;
        !           642:        case (MDOC_HEAD):
        !           643:                mdoc_head_free(&p->data.head);
        !           644:                break;
        !           645:        default:
        !           646:                break;
        !           647:        }
        !           648:
        !           649:        free(p);
        !           650: }
        !           651:
        !           652:
        !           653: static void
        !           654: mdoc_node_freelist(struct mdoc_node *p)
        !           655: {
        !           656:
        !           657:        if (p->child)
        !           658:                mdoc_node_freelist(p->child);
        !           659:        if (p->next)
        !           660:                mdoc_node_freelist(p->next);
        !           661:
        !           662:        mdoc_node_free(p);
        !           663: }
        !           664:
        !           665:
        !           666: int
        !           667: mdoc_find(const struct mdoc *mdoc, const char *key)
        !           668: {
        !           669:
        !           670:        return(mdoc_hash_find(mdoc->htab, key));
        !           671: }
        !           672:
        !           673:
        !           674: static void
        !           675: argcpy(struct mdoc_arg *dst, const struct mdoc_arg *src)
        !           676: {
        !           677:        size_t           i;
        !           678:
        !           679:        dst->arg = src->arg;
        !           680:        if (0 == (dst->sz = src->sz))
        !           681:                return;
        !           682:        dst->value = xcalloc(dst->sz, sizeof(char *));
        !           683:        for (i = 0; i < dst->sz; i++)
        !           684:                dst->value[i] = xstrdup(src->value[i]);
        !           685: }
        !           686:
        !           687:
        !           688: static struct mdoc_arg *
        !           689: argdup(size_t argsz, const struct mdoc_arg *args)
        !           690: {
        !           691:        struct mdoc_arg *pp;
        !           692:        size_t           i;
        !           693:
        !           694:        if (0 == argsz)
        !           695:                return(NULL);
        !           696:
        !           697:        pp = xcalloc((size_t)argsz, sizeof(struct mdoc_arg));
        !           698:        for (i = 0; i < argsz; i++)
        !           699:                argcpy(&pp[i], &args[i]);
        !           700:
        !           701:        return(pp);
        !           702: }
        !           703:
        !           704:
        !           705: static void
        !           706: paramfree(size_t sz, char **p)
        !           707: {
        !           708:        size_t           i;
        !           709:
        !           710:        if (0 == sz)
        !           711:                return;
        !           712:
        !           713:        assert(p);
        !           714:        for (i = 0; i < sz; i++)
        !           715:                free(p[i]);
        !           716:        free(p);
        !           717: }
        !           718:
        !           719:
        !           720: static char **
        !           721: paramdup(size_t sz, const char **p)
        !           722: {
        !           723:        char            **pp;
        !           724:        size_t            i;
        !           725:
        !           726:        if (0 == sz)
        !           727:                return(NULL);
        !           728:
        !           729:        pp = xcalloc(sz, sizeof(char *));
        !           730:        for (i = 0; i < sz; i++)
        !           731:                pp[i] = xstrdup(p[i]);
        !           732:
        !           733:        return(pp);
        !           734: }

CVSweb