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

Annotation of mandoc/validate.c, Revision 1.11

1.11    ! kristaps    1: /* $Id: validate.c,v 1.10 2008/12/30 19:06:03 kristaps Exp $ */
1.1       kristaps    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>
1.8       kristaps   20: #include <stdlib.h>
1.1       kristaps   21:
                     22: #include "private.h"
                     23:
1.11    ! kristaps   24: /* FIXME: `.St' can only have one argument set. */
1.2       kristaps   25:
1.11    ! kristaps   26: typedef int    (*v_args_sz)(struct mdoc *, int, int, int);
        !            27: typedef int    (*v_args)(struct mdoc *, int, int, int,
1.9       kristaps   28:                        const char *[], int, const struct mdoc_arg *);
1.11    ! kristaps   29: typedef int    (*v_post)(struct mdoc *, int, int);
1.1       kristaps   30:
1.11    ! kristaps   31: static int       need_head_child(struct mdoc *, int, int);
        !            32:
        !            33: static int       assert_eq0(struct mdoc *, int, int, int);
        !            34: static int       assert_le1(struct mdoc *, int, int, int);
        !            35: static int       need_eq0(struct mdoc *, int, int, int);
        !            36: static int       need_eq1(struct mdoc *, int, int, int);
        !            37: static int       need_ge1(struct mdoc *, int, int, int);
        !            38: static int       need_le2(struct mdoc *, int, int, int);
        !            39: static int       want_eq0(struct mdoc *, int, int, int);
        !            40: static int       want_ge1(struct mdoc *, int, int, int);
        !            41:
        !            42: static int       args_ref(struct mdoc *, int, int, int,
        !            43:                        const char *[], int, const struct mdoc_arg *);
        !            44: static int       args_bool(struct mdoc *, int, int, int,
        !            45:                        const char *[], int, const struct mdoc_arg *);
        !            46: static int       args_Sh(struct mdoc *, int, int, int,
1.9       kristaps   47:                        const char *[], int, const struct mdoc_arg *);
1.11    ! kristaps   48: static int       args_blocknest(struct mdoc *, int, int, int,
1.9       kristaps   49:                        const char *[], int, const struct mdoc_arg *);
1.11    ! kristaps   50: static int       args_At(struct mdoc *, int, int, int,
        !            51:                        const char *[], int, const struct mdoc_arg *);
        !            52: static int       args_Xr(struct mdoc *, int, int, int,
1.8       kristaps   53:                        const char *[], int, const struct mdoc_arg *);
1.9       kristaps   54:
                     55: struct valids {
1.11    ! kristaps   56:        v_args_sz sz;
        !            57:        v_args    args;
        !            58:        v_post    post;
1.9       kristaps   59: };
                     60:
                     61:
                     62: const  struct valids mdoc_valids[MDOC_MAX] = {
1.11    ! kristaps   63:        { NULL, NULL, NULL }, /* \" */
        !            64:        { NULL, NULL, NULL }, /* Dd */ /* TODO */
        !            65:        { NULL, NULL, NULL }, /* Dt */ /* TODO */
        !            66:        { NULL, NULL, NULL }, /* Os */ /* TODO */
        !            67:        { NULL, args_Sh, NULL }, /* Sh */
        !            68:        { NULL, NULL, NULL }, /* Ss */
        !            69:        { want_eq0, NULL, NULL }, /* Pp */
        !            70:        { NULL, args_blocknest, need_head_child }, /* D1 */
        !            71:        { NULL, args_blocknest, need_head_child }, /* Dl */
        !            72:        { NULL, args_blocknest, NULL }, /* Bd */
        !            73:        { NULL, NULL, NULL }, /* Ed */
        !            74:        { NULL, NULL, NULL }, /* Bl */
        !            75:        { NULL, NULL, NULL }, /* El */
        !            76:        { NULL, NULL, NULL }, /* It */
        !            77:        { need_ge1, NULL, NULL }, /* Ad */
        !            78:        { NULL, NULL, NULL }, /* An */
        !            79:        { NULL, NULL, NULL }, /* Ar */
        !            80:        { need_ge1, NULL, NULL }, /* Cd */
        !            81:        { NULL, NULL, NULL }, /* Cm */
        !            82:        { need_ge1, NULL, NULL }, /* Dv */
        !            83:        { need_ge1, NULL, NULL }, /* Er */
        !            84:        { need_ge1, NULL, NULL }, /* Ev */
        !            85:        { NULL, NULL, NULL }, /* Ex */
        !            86:        { need_ge1, NULL, NULL }, /* Fa */
        !            87:        { NULL, NULL, NULL }, /* Fd */
        !            88:        { NULL, NULL, NULL }, /* Fl */
        !            89:        { need_ge1, NULL, NULL }, /* Fn */
        !            90:        { want_ge1, NULL, NULL }, /* Ft */
        !            91:        { need_ge1, NULL, NULL }, /* Ic */
        !            92:        { need_eq1, NULL, NULL }, /* In */
        !            93:        { want_ge1, NULL, NULL }, /* Li */
        !            94:        { want_ge1, NULL, NULL }, /* Nd */
        !            95:        { NULL, NULL, NULL }, /* Nm */
        !            96:        { NULL, NULL, NULL }, /* Op */
        !            97:        { NULL, NULL, NULL }, /* Ot */
        !            98:        { want_ge1, NULL, NULL }, /* Pa */
        !            99:        { NULL, NULL, NULL }, /* Rv */
        !           100:        { NULL, NULL, NULL }, /* St */
        !           101:        { need_ge1, NULL, NULL }, /* Va */
        !           102:        { need_ge1, NULL, NULL }, /* Vt */
        !           103:        { need_le2, args_Xr, NULL }, /* Xr */
        !           104:        { need_ge1, args_ref, NULL }, /* %A */
        !           105:        { need_ge1, args_ref, NULL }, /* %B */
        !           106:        { need_ge1, args_ref, NULL }, /* %D */
        !           107:        { need_ge1, args_ref, NULL }, /* %I */
        !           108:        { need_ge1, args_ref, NULL }, /* %J */
        !           109:        { need_ge1, args_ref, NULL }, /* %N */
        !           110:        { need_ge1, args_ref, NULL }, /* %O */
        !           111:        { need_ge1, args_ref, NULL }, /* %P */
        !           112:        { need_ge1, args_ref, NULL }, /* %R */
        !           113:        { need_ge1, args_ref, NULL }, /* %T */
        !           114:        { need_ge1, args_ref, NULL }, /* %V */
        !           115:        { NULL, NULL, NULL }, /* Ac */
        !           116:        { NULL, NULL, NULL }, /* Ao */
        !           117:        { NULL, NULL, NULL }, /* Aq */
        !           118:        { need_le2, args_At, NULL }, /* At */
        !           119:        { NULL, NULL, NULL }, /* Bc */
        !           120:        { NULL, NULL, NULL }, /* Bf */
        !           121:        { NULL, NULL, NULL }, /* Bo */
        !           122:        { NULL, NULL, NULL }, /* Bq */
        !           123:        { assert_le1, NULL, NULL }, /* Bsx */
        !           124:        { assert_le1, NULL, NULL }, /* Bx */
        !           125:        { need_eq1, args_bool, NULL }, /* Db */
        !           126:        { NULL, NULL, NULL }, /* Dc */
        !           127:        { NULL, NULL, NULL }, /* Do */
        !           128:        { NULL, NULL, NULL }, /* Dq */
        !           129:        { NULL, NULL, NULL }, /* Ec */
        !           130:        { NULL, NULL, NULL }, /* Ef */
        !           131:        { need_ge1, NULL, NULL }, /* Em */
        !           132:        { NULL, NULL, NULL }, /* Eo */
        !           133:        { assert_le1, NULL, NULL }, /* Fx */
        !           134:        { want_ge1, NULL, NULL }, /* Ms */
        !           135:        { NULL, NULL, NULL }, /* No */
        !           136:        { NULL, NULL, NULL }, /* Ns */
        !           137:        { assert_le1, NULL, NULL }, /* Nx */
        !           138:        { assert_le1, NULL, NULL }, /* Ox */
        !           139:        { NULL, NULL, NULL }, /* Pc */
        !           140:        { NULL, NULL, NULL }, /* Pf */
        !           141:        { NULL, NULL, NULL }, /* Po */
        !           142:        { NULL, NULL, NULL }, /* Pq */
        !           143:        { NULL, NULL, NULL }, /* Qc */
        !           144:        { NULL, NULL, NULL }, /* Ql */
        !           145:        { NULL, NULL, NULL }, /* Qo */
        !           146:        { NULL, NULL, NULL }, /* Qq */
        !           147:        { NULL, NULL, NULL }, /* Re */
        !           148:        { NULL, NULL, NULL }, /* Rs */
        !           149:        { NULL, NULL, NULL }, /* Sc */
        !           150:        { NULL, NULL, NULL }, /* So */
        !           151:        { NULL, NULL, NULL }, /* Sq */
        !           152:        { need_eq1, args_bool, NULL }, /* Sm */
        !           153:        { need_ge1, NULL, NULL }, /* Sx */
        !           154:        { need_ge1, NULL, NULL }, /* Sy */
        !           155:        { want_ge1, NULL, NULL }, /* Tn */
        !           156:        { assert_eq0, NULL, NULL }, /* Ux */
        !           157:        { NULL, NULL, NULL }, /* Xc */
        !           158:        { NULL, NULL, NULL }, /* Xo */
        !           159:        { NULL, NULL, NULL }, /* Fo */
        !           160:        { NULL, NULL, NULL }, /* Fc */
        !           161:        { NULL, NULL, NULL }, /* Oo */
        !           162:        { NULL, NULL, NULL }, /* Oc */
        !           163:        { NULL, NULL, NULL }, /* Bk */
        !           164:        { NULL, NULL, NULL }, /* Ek */
        !           165:        { need_eq0, NULL, NULL }, /* Bt */
        !           166:        { need_eq1, NULL, NULL }, /* Hf */
        !           167:        { NULL, NULL, NULL }, /* Fr */
        !           168:        { need_eq0, NULL, NULL }, /* Ud */
1.9       kristaps  169: };
1.6       kristaps  170:
                    171:
                    172: static int
1.9       kristaps  173: need_le2(struct mdoc *mdoc, int tok, int pos, int sz)
1.6       kristaps  174: {
1.11    ! kristaps  175:        if (sz <= 2)
1.8       kristaps  176:                return(1);
1.9       kristaps  177:        return(mdoc_err(mdoc, tok, pos, ERR_ARGS_LE2));
1.6       kristaps  178: }
                    179:
                    180:
                    181: static int
1.9       kristaps  182: want_ge1(struct mdoc *mdoc, int tok, int pos, int sz)
1.6       kristaps  183: {
1.9       kristaps  184:        if (sz > 0)
1.8       kristaps  185:                return(1);
1.9       kristaps  186:        return(mdoc_warn(mdoc, tok, pos, WARN_ARGS_GE1));
1.6       kristaps  187: }
1.1       kristaps  188:
                    189:
                    190: static int
1.9       kristaps  191: want_eq0(struct mdoc *mdoc, int tok, int pos, int sz)
1.1       kristaps  192: {
1.9       kristaps  193:        if (sz == 0)
                    194:                return(1);
                    195:        return(mdoc_warn(mdoc, tok, pos, WARN_ARGS_EQ0));
1.1       kristaps  196: }
                    197:
                    198:
                    199: static int
1.9       kristaps  200: need_eq0(struct mdoc *mdoc, int tok, int pos, int sz)
1.1       kristaps  201: {
1.9       kristaps  202:        if (sz == 0)
                    203:                return(1);
                    204:        return(mdoc_err(mdoc, tok, pos, ERR_ARGS_EQ0));
1.1       kristaps  205: }
                    206:
                    207:
                    208: static int
1.9       kristaps  209: assert_le1(struct mdoc *mdoc, int tok, int pos, int sz)
1.1       kristaps  210: {
1.8       kristaps  211:
1.9       kristaps  212:        assert(sz <= 1);
1.8       kristaps  213:        return(1);
                    214: }
1.1       kristaps  215:
                    216:
1.8       kristaps  217: static int
1.9       kristaps  218: assert_eq0(struct mdoc *mdoc, int tok, int pos, int sz)
1.8       kristaps  219: {
1.1       kristaps  220:
1.9       kristaps  221:        assert(sz == 0);
1.1       kristaps  222:        return(1);
                    223: }
                    224:
                    225:
1.8       kristaps  226: static int
1.9       kristaps  227: need_eq1(struct mdoc *mdoc, int tok, int pos, int sz)
1.1       kristaps  228: {
1.9       kristaps  229:        if (sz == 1)
                    230:                return(1);
                    231:        return(mdoc_err(mdoc, tok, pos, ERR_ARGS_EQ1));
1.1       kristaps  232: }
                    233:
                    234:
1.9       kristaps  235: static int
                    236: need_ge1(struct mdoc *mdoc, int tok, int pos, int sz)
1.1       kristaps  237: {
1.9       kristaps  238:        if (sz > 0)
                    239:                return(1);
                    240:        return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
1.1       kristaps  241: }
                    242:
                    243:
1.9       kristaps  244: static int
1.11    ! kristaps  245: need_head_child(struct mdoc *mdoc, int tok, int pos)
        !           246: {
        !           247:        struct mdoc_node *n;
        !           248:
        !           249:        assert(mdoc->last);
        !           250:        n = mdoc->last;
        !           251:
        !           252:        assert(MDOC_BLOCK == n->type);
        !           253:        assert(n->child);
        !           254:
        !           255:        n = n->child;
        !           256:
        !           257:        if (MDOC_HEAD != n->type)
        !           258:                return(mdoc_err(mdoc, tok, pos, ERR_CHILD_HEAD));
        !           259:        if (n->child)
        !           260:                return(1);
        !           261:        return(mdoc_err(mdoc, tok, pos, ERR_CHILD_HEAD));
        !           262: }
        !           263:
        !           264:
        !           265: static int
        !           266: args_Sh(struct mdoc *mdoc, int tok, int pos,
1.9       kristaps  267:                int sz, const char *args[],
                    268:                int argc, const struct mdoc_arg *argv)
1.1       kristaps  269: {
1.9       kristaps  270:        enum mdoc_sec    sec;
1.2       kristaps  271:
1.9       kristaps  272:        sec = mdoc_atosec((size_t)sz, args);
                    273:        if (SEC_CUSTOM != sec && sec < mdoc->sec_lastn)
                    274:                if ( ! mdoc_warn(mdoc, tok, pos, WARN_SEC_OO))
1.8       kristaps  275:                        return(0);
1.9       kristaps  276:        if (SEC_BODY == mdoc->sec_last && SEC_NAME != sec)
                    277:                return(mdoc_err(mdoc, tok, pos, ERR_SEC_NAME));
1.2       kristaps  278:
1.9       kristaps  279:        return(1);
1.1       kristaps  280: }
                    281:
                    282:
1.9       kristaps  283: static int
1.11    ! kristaps  284: args_bool(struct mdoc *mdoc, int tok, int pos,
        !           285:                int sz, const char *args[],
        !           286:                int argc, const struct mdoc_arg *argv)
        !           287: {
        !           288:
        !           289:        assert(1 == sz);
        !           290:        if (xstrcmp(args[0], "on"))
        !           291:                return(1);
        !           292:        if (xstrcmp(args[0], "off"))
        !           293:                return(1);
        !           294:        return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_ARGBAD));
        !           295: }
        !           296:
        !           297:
        !           298: static int
        !           299: args_ref(struct mdoc *mdoc, int tok, int pos,
        !           300:                int sz, const char *args[],
        !           301:                int argc, const struct mdoc_arg *argv)
        !           302: {
        !           303:        struct mdoc_node *n;
        !           304:
        !           305:        assert(mdoc->last);
        !           306:        for (n = mdoc->last ; n; n = n->parent) {
        !           307:                if (MDOC_BLOCK != n->type)
        !           308:                        continue;
        !           309:                if (MDOC_Rs != n->data.block.tok)
        !           310:                        break;
        !           311:                return(1);
        !           312:        }
        !           313:
        !           314:        return(mdoc_err(mdoc, tok, pos, ERR_SCOPE_NOCTX));
        !           315: }
        !           316:
        !           317:
        !           318: static int
        !           319: args_Xr(struct mdoc *mdoc, int tok, int pos,
        !           320:                int sz, const char *args[],
        !           321:                int argc, const struct mdoc_arg *argv)
        !           322: {
        !           323:
        !           324:        if (1 == sz)
        !           325:                return(1);
        !           326:        if (0 == sz)
        !           327:                return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
        !           328:
        !           329:        if (MSEC_DEFAULT == mdoc_atomsec(args[1]))
        !           330:                return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_ARGFORM));
        !           331:        return(1);
        !           332: }
        !           333:
        !           334:
        !           335: static int
        !           336: args_At(struct mdoc *mdoc, int tok, int pos,
1.9       kristaps  337:                int sz, const char *args[],
                    338:                int argc, const struct mdoc_arg *argv)
1.1       kristaps  339: {
1.9       kristaps  340:        int              i;
1.1       kristaps  341:
1.9       kristaps  342:        if (0 == sz)
1.8       kristaps  343:                return(1);
1.6       kristaps  344:
1.9       kristaps  345:        i = 0;
                    346:        if (ATT_DEFAULT == mdoc_atoatt(args[i]))
                    347:                i++;
1.1       kristaps  348:
1.9       kristaps  349:        for ( ; i < sz; i++) {
                    350:                if ( ! mdoc_isdelim(args[i]))
                    351:                        continue;
                    352:                return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_NOPUNCT));
1.8       kristaps  353:        }
1.9       kristaps  354:        return(1);
1.1       kristaps  355: }
                    356:
                    357:
1.9       kristaps  358: static int
1.11    ! kristaps  359: args_blocknest(struct mdoc *mdoc, int tok, int pos,
1.9       kristaps  360:                int sz, const char *args[],
                    361:                int argc, const struct mdoc_arg *argv)
1.1       kristaps  362: {
1.9       kristaps  363:        struct mdoc_node *node;
1.8       kristaps  364:
                    365:        /*
1.9       kristaps  366:         * We can't be nested within any other block displays (or really
                    367:         * any other kind of display, although Bd is the only multi-line
                    368:         * one that will show up).
1.8       kristaps  369:         */
1.9       kristaps  370:        assert(mdoc->last);
1.8       kristaps  371:
1.9       kristaps  372:        /* LINTED */
1.11    ! kristaps  373:        for (node = mdoc->last; node; node = node->parent) {
1.9       kristaps  374:                if (node->type != MDOC_BLOCK)
                    375:                        continue;
                    376:                if (node->data.block.tok != MDOC_Bd)
1.8       kristaps  377:                        continue;
                    378:                break;
                    379:        }
1.9       kristaps  380:        if (NULL == node)
                    381:                return(1);
                    382:        return(mdoc_err(mdoc, tok, pos, ERR_SCOPE_NONEST));
1.8       kristaps  383: }
                    384:
                    385:
                    386: int
1.11    ! kristaps  387: mdoc_valid_pre(struct mdoc *mdoc, int tok, int pos,
1.9       kristaps  388:                int sz, const char *args[],
                    389:                int argc, const struct mdoc_arg *argv)
1.8       kristaps  390: {
                    391:
1.9       kristaps  392:        assert(tok < MDOC_MAX);
                    393:        if (mdoc_valids[tok].sz)
                    394:                if ( ! (*mdoc_valids[tok].sz)(mdoc, tok, pos, sz))
1.5       kristaps  395:                        return(0);
1.8       kristaps  396:
1.11    ! kristaps  397:        if (NULL == mdoc_valids[tok].args)
1.9       kristaps  398:                return(1);
1.11    ! kristaps  399:        return((*mdoc_valids[tok].args)(mdoc,
        !           400:                        tok, pos, sz, args, argc, argv));
1.1       kristaps  401: }
                    402:
1.11    ! kristaps  403:
        !           404: int
        !           405: mdoc_valid_post(struct mdoc *mdoc, int tok, int pos)
        !           406: {
        !           407:
        !           408:        if (NULL == mdoc_valids[tok].post)
        !           409:                return(1);
        !           410:        return((*mdoc_valids[tok].post)(mdoc, tok, pos));
        !           411: }

CVSweb