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

Annotation of mandoc/macro.c, Revision 1.6

1.6     ! kristaps    1: /* $Id: macro.c,v 1.5 2008/12/17 17:18:38 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:  */
1.2       kristaps   19: #include <assert.h>
                     20: #include <ctype.h>
1.1       kristaps   21: #include <stdlib.h>
1.2       kristaps   22: #include <stdio.h>
1.5       kristaps   23: #include <string.h>
1.2       kristaps   24:
                     25: #include "private.h"
                     26:
1.3       kristaps   27: #define        _CC(p)  ((const char **)p)
1.2       kristaps   28:
1.6     ! kristaps   29: static int       scope_rewind_exp(struct mdoc *, int, int, int);
1.3       kristaps   30: static int       append_text(struct mdoc *, int,
                     31:                        int, int, char *[]);
1.6     ! kristaps   32: static int       append_scoped(struct mdoc *, int, int, int,
        !            33:                        const char *[], int, const struct mdoc_arg *);
1.3       kristaps   34: static int       args_next(struct mdoc *, int,
                     35:                        int *, char *, char **);
1.6     ! kristaps   36: static int       argv_next(struct mdoc *, int,
        !            37:                        int *, char *, struct mdoc_arg *);
        !            38: static int       args_next_quoted(struct mdoc *, int,
        !            39:                        int *, char *, char **);
        !            40:
        !            41:
        !            42: static int
        !            43: args_next_quoted(struct mdoc *mdoc, int tok,
        !            44:                int *pos, char *buf, char **v)
        !            45: {
        !            46:
        !            47:        if (0 == buf[*pos])
        !            48:                return(0);
        !            49:
        !            50:        assert( ! isspace(buf[*pos]));
        !            51:
        !            52:        if ('\"' != buf[*pos])
        !            53:                return(args_next(mdoc, tok, pos, buf, v));
        !            54:
        !            55:        *v = &buf[++(*pos)];
        !            56:
        !            57:        while (buf[*pos] && '\"' != buf[*pos])
        !            58:                (*pos)++;
        !            59:
        !            60:        if (0 == buf[*pos]) {
        !            61:                (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_UNQUOTE);
        !            62:                return(-1);
        !            63:        }
        !            64:
        !            65:        buf[(*pos)++] = 0;
        !            66:        if (0 == buf[*pos])
        !            67:                return(1);
        !            68:
        !            69:        while (buf[*pos] && isspace(buf[*pos]))
        !            70:                (*pos)++;
        !            71:
        !            72:        if (0 == buf[*pos])
        !            73:                if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN))
        !            74:                        return(-1);
        !            75:
        !            76:        return(1);
        !            77: }
        !            78:
        !            79:
        !            80: static int
        !            81: scope_rewind_exp(struct mdoc *mdoc, int ppos, int tok, int dst)
        !            82: {
        !            83:        struct mdoc_node *n;
        !            84:
        !            85:        /* LINTED */
        !            86:        for (n = mdoc->last; n; n = n->parent) {
        !            87:                if (MDOC_BLOCK != n->type)
        !            88:                        continue;
        !            89:                if (dst == n->data.block.tok)
        !            90:                        break;
        !            91:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
        !            92:        }
        !            93:
        !            94:        if (NULL == (mdoc->last = n))
        !            95:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_NOCTX));
        !            96:
        !            97:        mdoc_msg(mdoc, ppos, "scope: rewound `%s' to `%s'",
        !            98:                        mdoc_macronames[tok], mdoc_macronames[dst]);
        !            99:
        !           100:        return(1);
        !           101: }
        !           102:
        !           103:
        !           104: static int
        !           105: argv_next(struct mdoc *mdoc, int tok,
        !           106:                int *pos, char *buf, struct mdoc_arg *v)
        !           107: {
        !           108:        char            *argv;
        !           109:        int              i, val;
        !           110:
        !           111:        if (0 == buf[*pos])
        !           112:                return(0);
        !           113:
        !           114:        assert( ! isspace(buf[*pos]));
        !           115:
        !           116:        if ('-' != buf[*pos]) {
        !           117:                (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_ARGS);
        !           118:                return(-1);
        !           119:        }
        !           120:
        !           121:        i = *pos;
        !           122:        argv = &buf[++(*pos)];
        !           123:
        !           124:        while (buf[*pos] && ! isspace(buf[*pos]))
        !           125:                (*pos)++;
        !           126:
        !           127:        if (buf[*pos])
        !           128:                buf[(*pos)++] = 0;
        !           129:
        !           130:        /*
        !           131:         * XXX This is a little bit ugly.  The mdoc_argv structure
        !           132:         * points to a pointer array, which we allocate on-the-fly in
        !           133:         * this function.  If there's any failure, we need to release
        !           134:         * this memory, which is done by the caller of this function
        !           135:         * with mdoc_argv_free.  Ew.  This should be simpler.
        !           136:         */
        !           137:
        !           138:        if (MDOC_ARG_MAX == (val = mdoc_argv_lookup(tok, argv))) {
        !           139:                (void)mdoc_err(mdoc, tok, i, ERR_SYNTAX_BADARG);
        !           140:                return(-1);
        !           141:        }
        !           142:
        !           143:        while (buf[*pos] && isspace(buf[*pos]))
        !           144:                (*pos)++;
        !           145:
        !           146:        if ( ! mdoc_argv_parse(mdoc, tok, val, v, pos, buf))
        !           147:                return(-1);
        !           148:
        !           149:        return(1);
        !           150: }
1.1       kristaps  151:
                    152:
                    153: static int
1.2       kristaps  154: args_next(struct mdoc *mdoc, int tok,
                    155:                int *pos, char *buf, char **v)
1.1       kristaps  156: {
                    157:
                    158:        if (0 == buf[*pos])
                    159:                return(0);
                    160:
1.2       kristaps  161:        assert( ! isspace(buf[*pos]));
                    162:
1.1       kristaps  163:        if ('\"' == buf[*pos]) {
1.2       kristaps  164:                (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_QUOTE);
1.1       kristaps  165:                return(-1);
                    166:        }
                    167:
                    168:        *v = &buf[*pos];
                    169:
1.2       kristaps  170:        /* Scan ahead to end of token. */
                    171:
1.1       kristaps  172:        while (buf[*pos] && ! isspace(buf[*pos]))
                    173:                (*pos)++;
                    174:
1.2       kristaps  175:        if (buf[*pos] && buf[*pos + 1] && '\\' == buf[*pos]) {
                    176:                (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_WS);
1.1       kristaps  177:                return(-1);
                    178:        }
                    179:
1.2       kristaps  180:        if (0 == buf[*pos])
                    181:                return(1);
                    182:
                    183:        /* Scan ahead over trailing whitespace. */
                    184:
                    185:        buf[(*pos)++] = 0;
                    186:        while (buf[*pos] && isspace(buf[*pos]))
                    187:                (*pos)++;
                    188:
                    189:        if (0 == buf[*pos])
                    190:                if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN))
                    191:                        return(-1);
                    192:
1.1       kristaps  193:        return(1);
                    194: }
                    195:
1.2       kristaps  196:
                    197: static int
1.6     ! kristaps  198: append_scoped(struct mdoc *mdoc, int tok, int pos,
        !           199:                int sz, const char *args[],
        !           200:                int argc, const struct mdoc_arg *argv)
1.2       kristaps  201: {
1.5       kristaps  202:        enum mdoc_sec    sec;
                    203:
1.4       kristaps  204:        switch (tok) {
                    205:         /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
                    206:        case (MDOC_Sh):
1.6     ! kristaps  207:                if (0 == sz)
        !           208:                        return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
        !           209:
1.5       kristaps  210:                sec = mdoc_atosec((size_t)sz, _CC(args));
                    211:                if (SEC_CUSTOM != sec && sec < mdoc->sec_lastn)
                    212:                        if ( ! mdoc_warn(mdoc, tok, pos, WARN_SEC_OO))
                    213:                                return(0);
                    214:
                    215:                if (SEC_BODY == mdoc->sec_last && SEC_NAME != sec)
                    216:                        return(mdoc_err(mdoc, tok, pos, ERR_SEC_NAME));
                    217:
                    218:                if (SEC_CUSTOM != sec)
                    219:                        mdoc->sec_lastn = sec;
                    220:                mdoc->sec_last = sec;
1.4       kristaps  221:                break;
1.6     ! kristaps  222:
1.4       kristaps  223:        case (MDOC_Ss):
1.6     ! kristaps  224:                if (0 == sz)
        !           225:                        return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
        !           226:                break;
        !           227:
        !           228:        case (MDOC_Bl):
1.4       kristaps  229:                break;
1.6     ! kristaps  230:
1.4       kristaps  231:         /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
                    232:        default:
                    233:                abort();
                    234:                /* NOTREACHED */
                    235:        }
                    236:
1.6     ! kristaps  237:        mdoc_block_alloc(mdoc, pos, tok, (size_t)argc, argv);
1.3       kristaps  238:        mdoc_head_alloc(mdoc, pos, tok, (size_t)sz, _CC(args));
1.2       kristaps  239:        mdoc_body_alloc(mdoc, pos, tok);
                    240:        return(1);
                    241: }
                    242:
                    243:
1.1       kristaps  244: static int
1.3       kristaps  245: append_text(struct mdoc *mdoc, int tok,
                    246:                int pos, int sz, char *args[])
1.1       kristaps  247: {
                    248:
1.3       kristaps  249:        assert(sz >= 0);
1.2       kristaps  250:        args[sz] = NULL;
                    251:
                    252:        switch (tok) {
1.4       kristaps  253:         /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
1.2       kristaps  254:        case (MDOC_Ft):
                    255:                /* FALLTHROUGH */
                    256:        case (MDOC_Li):
                    257:                /* FALLTHROUGH */
                    258:        case (MDOC_Ms):
                    259:                /* FALLTHROUGH */
                    260:        case (MDOC_Pa):
                    261:                /* FALLTHROUGH */
                    262:        case (MDOC_Tn):
1.4       kristaps  263:                if (0 < sz)
                    264:                        break;
                    265:                if ( ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_GE1))
1.1       kristaps  266:                        return(0);
1.4       kristaps  267:                break;
1.2       kristaps  268:        case (MDOC_Ar):
                    269:                /* FALLTHROUGH */
                    270:        case (MDOC_Cm):
                    271:                /* FALLTHROUGH */
                    272:        case (MDOC_Fl):
1.4       kristaps  273:                break;
1.2       kristaps  274:        case (MDOC_Ad):
                    275:                /* FALLTHROUGH */
                    276:        case (MDOC_Em):
                    277:                /* FALLTHROUGH */
                    278:        case (MDOC_Er):
                    279:                /* FALLTHROUGH */
                    280:        case (MDOC_Ev):
                    281:                /* FALLTHROUGH */
                    282:        case (MDOC_Fa):
                    283:                /* FALLTHROUGH */
                    284:        case (MDOC_Dv):
                    285:                /* FALLTHROUGH */
                    286:        case (MDOC_Ic):
                    287:                /* FALLTHROUGH */
                    288:        case (MDOC_Va):
                    289:                /* FALLTHROUGH */
                    290:        case (MDOC_Vt):
1.4       kristaps  291:                if (0 < sz)
                    292:                        break;
                    293:                return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
                    294:         /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
1.2       kristaps  295:        default:
1.4       kristaps  296:                abort();
                    297:                /* NOTREACHED */
1.2       kristaps  298:        }
                    299:
1.4       kristaps  300:        mdoc_elem_alloc(mdoc, pos, tok, 0,
                    301:                        NULL, (size_t)sz, _CC(args));
                    302:        return(1);
1.2       kristaps  303: }
                    304:
1.1       kristaps  305:
1.2       kristaps  306: int
1.5       kristaps  307: macro_text(MACRO_PROT_ARGS)
1.2       kristaps  308: {
1.3       kristaps  309:        int               lastarg, c, lasttok, lastpunct, j;
1.2       kristaps  310:        char             *args[MDOC_LINEARG_MAX], *p;
1.1       kristaps  311:
1.2       kristaps  312:        lasttok = ppos;
                    313:        lastpunct = 0;
                    314:        j = 0;
                    315:
1.5       kristaps  316:        if (SEC_PROLOGUE == mdoc->sec_lastn)
                    317:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
                    318:
1.2       kristaps  319: again:
1.6     ! kristaps  320:        lastarg = *pos;
1.2       kristaps  321:
1.6     ! kristaps  322:        if (j == MDOC_LINEARG_MAX)
        !           323:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
1.2       kristaps  324:        c = args_next(mdoc, tok, pos, buf, &args[j]);
                    325:
                    326:        if (-1 == c)
                    327:                return(0);
                    328:        if (0 == c && ! lastpunct)
                    329:                return(append_text(mdoc, tok, lasttok, j, args));
                    330:        else if (0 == c)
                    331:                return(1);
                    332:
                    333:        /* Command found. */
                    334:
                    335:        if (MDOC_MAX != (c = mdoc_find(mdoc, args[j]))) {
                    336:                if ( ! lastpunct)
                    337:                        if ( ! append_text(mdoc, tok, lasttok, j, args))
1.1       kristaps  338:                                return(0);
1.2       kristaps  339:                return(mdoc_macro(mdoc, c, lastarg, pos, buf));
                    340:        }
                    341:
                    342:        /* Word found. */
                    343:
1.4       kristaps  344:        if ( ! mdoc_isdelim(args[j])) {
1.2       kristaps  345:                j++;
                    346:                goto again;
                    347:        }
                    348:
                    349:        /* Punctuation found.  */
                    350:
                    351:        p = args[j]; /* Save argument (NULL-ified in append). */
                    352:
                    353:        if ( ! lastpunct)
                    354:                if ( ! append_text(mdoc, tok, lasttok, j, args))
                    355:                        return(0);
                    356:
                    357:        args[j] = p;
                    358:
                    359:        mdoc_word_alloc(mdoc, lastarg, args[j]);
                    360:        lastpunct = 1;
                    361:        j = 0;
                    362:
                    363:        goto again;
                    364:
                    365:        /* NOTREACHED */
                    366: }
1.1       kristaps  367:
                    368:
1.2       kristaps  369: int
1.5       kristaps  370: macro_prologue_dtitle(MACRO_PROT_ARGS)
                    371: {
                    372:        int               c, lastarg, j;
                    373:        char             *args[MDOC_LINEARG_MAX];
                    374:
                    375:        if (SEC_PROLOGUE != mdoc->sec_lastn)
                    376:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
                    377:        if (0 == mdoc->meta.date)
                    378:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
                    379:        if (mdoc->meta.title[0])
                    380:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
                    381:
                    382:        j = -1;
                    383:
                    384: again:
                    385:        lastarg = *pos;
1.6     ! kristaps  386:
        !           387:        if (j == MDOC_LINEARG_MAX)
        !           388:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
1.5       kristaps  389:        c = args_next(mdoc, tok, pos, buf, &args[++j]);
                    390:
                    391:        if (0 == c) {
                    392:                if (mdoc->meta.title)
                    393:                        return(1);
                    394:                if ( ! mdoc_warn(mdoc, tok, ppos, WARN_ARGS_GE1))
                    395:                        return(0);
                    396:                (void)xstrlcpy(mdoc->meta.title,
                    397:                                "UNTITLED", META_TITLE_SZ);
                    398:                return(1);
                    399:        } else if (-1 == c)
                    400:                return(0);
                    401:
                    402:        if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
                    403:                        (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
                    404:                return(0);
                    405:
                    406:        if (0 == j) {
                    407:                if (xstrlcpy(mdoc->meta.title, args[0], META_TITLE_SZ))
                    408:                        goto again;
                    409:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
                    410:
                    411:        } else if (1 == j) {
                    412:                mdoc->meta.msec = mdoc_atomsec(args[1]);
                    413:                if (MSEC_DEFAULT != mdoc->meta.msec)
                    414:                        goto again;
                    415:                return(mdoc_err(mdoc, tok, -1, ERR_SYNTAX_ARGS));
                    416:
                    417:        } else if (2 == j) {
                    418:                mdoc->meta.vol = mdoc_atovol(args[2]);
                    419:                if (VOL_DEFAULT != mdoc->meta.vol)
                    420:                        goto again;
                    421:                mdoc->meta.arch = mdoc_atoarch(args[2]);
                    422:                if (ARCH_DEFAULT != mdoc->meta.arch)
                    423:                        goto again;
                    424:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
                    425:        }
                    426:
                    427:        return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    428: }
                    429:
                    430:
                    431: int
1.6     ! kristaps  432: macro_prologue_os(MACRO_PROT_ARGS)
        !           433: {
        !           434:        int               c, lastarg, j;
        !           435:        char             *args[MDOC_LINEARG_MAX];
        !           436:
        !           437:        if (SEC_PROLOGUE != mdoc->sec_lastn)
        !           438:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
        !           439:        if (0 == mdoc->meta.title[0])
        !           440:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
        !           441:        if (mdoc->meta.os[0])
        !           442:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
        !           443:
        !           444:        j = -1;
        !           445:
        !           446: again:
        !           447:        lastarg = *pos;
        !           448:
        !           449:        if (j == MDOC_LINEARG_MAX)
        !           450:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
        !           451:        c = args_next_quoted(mdoc, tok, pos, buf, &args[++j]);
        !           452:
        !           453:        if (0 == c) {
        !           454:                mdoc->sec_lastn = mdoc->sec_last = SEC_BODY;
        !           455:                return(1);
        !           456:        } else if (-1 == c)
        !           457:                return(0);
        !           458:
        !           459:        if ( ! xstrlcat(mdoc->meta.os, args[j], sizeof(mdoc->meta.os)))
        !           460:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
        !           461:        if ( ! xstrlcat(mdoc->meta.os, " ", sizeof(mdoc->meta.os)))
        !           462:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
        !           463:
        !           464:        goto again;
        !           465:        /* NOTREACHED */
        !           466: }
        !           467:
        !           468:
        !           469: int
1.5       kristaps  470: macro_prologue_ddate(MACRO_PROT_ARGS)
                    471: {
                    472:        int               c, lastarg, j;
                    473:        char             *args[MDOC_LINEARG_MAX], date[64];
                    474:
                    475:        if (SEC_PROLOGUE != mdoc->sec_lastn)
                    476:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
                    477:        if (mdoc->meta.title[0])
                    478:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
                    479:        if (mdoc->meta.date)
                    480:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
                    481:
                    482:        j = -1;
                    483:        date[0] = 0;
                    484:
                    485: again:
1.6     ! kristaps  486:        lastarg = *pos;
1.5       kristaps  487:
1.6     ! kristaps  488:        if (j == MDOC_LINEARG_MAX)
        !           489:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
1.5       kristaps  490:        c = args_next(mdoc, tok, pos, buf, &args[++j]);
1.6     ! kristaps  491:
1.5       kristaps  492:        if (0 == c) {
                    493:                if (mdoc->meta.date)
                    494:                        return(1);
                    495:                mdoc->meta.date = mdoc_atotime(date);
                    496:                if (mdoc->meta.date)
                    497:                        return(1);
                    498:                return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGS));
                    499:        } else if (-1 == c)
                    500:                return(0);
                    501:
                    502:        if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
                    503:                        (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
                    504:                return(0);
                    505:
                    506:        if (0 == j) {
                    507:                if (xstrcmp("$Mdocdate$", args[j])) {
                    508:                        mdoc->meta.date = time(NULL);
                    509:                        goto again;
                    510:                } else if (xstrcmp("$Mdocdate:", args[j]))
                    511:                        goto again;
                    512:        } else if (4 == j)
                    513:                if ( ! xstrcmp("$", args[j]))
                    514:                        goto again;
                    515:
                    516:        if ( ! xstrlcat(date, args[j], sizeof(date)))
                    517:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
                    518:        if ( ! xstrlcat(date, " ", sizeof(date)))
                    519:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
                    520:
                    521:        goto again;
                    522:        /* NOTREACHED */
                    523: }
                    524:
                    525:
                    526: int
1.6     ! kristaps  527: macro_scoped_explicit(MACRO_PROT_ARGS)
        !           528: {
        !           529:        int               c, lastarg, j;
        !           530:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
        !           531:
        !           532:        if (SEC_PROLOGUE == mdoc->sec_lastn)
        !           533:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
        !           534:
        !           535:        /*
        !           536:         * First close out the explicit scope.  The `end' tags (such as
        !           537:         * `.El' to `.Bl' don't cause anything to happen: we merely
        !           538:         * readjust our last parse point.
        !           539:         */
        !           540:
        !           541:        switch (tok) {
        !           542:        case (MDOC_El):
        !           543:                return(scope_rewind_exp(mdoc, ppos, tok, MDOC_Bl));
        !           544:        default:
        !           545:                break;
        !           546:        }
        !           547:
        !           548:        assert(MDOC_EXPLICIT & mdoc_macros[tok].flags);
        !           549:
        !           550:        lastarg = *pos;
        !           551:
        !           552:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
        !           553:                lastarg = *pos;
        !           554:                c = argv_next(mdoc, tok, pos, buf, &argv[j]);
        !           555:                if (0 == c)
        !           556:                        break;
        !           557:                else if (1 == c)
        !           558:                        continue;
        !           559:
        !           560:                mdoc_argv_free(j, argv);
        !           561:                return(0);
        !           562:        }
        !           563:
        !           564:        if (MDOC_LINEARG_MAX == j) {
        !           565:                mdoc_argv_free(j, argv);
        !           566:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
        !           567:        }
        !           568:
        !           569:        c = append_scoped(mdoc, tok, ppos, 0, NULL, j, argv);
        !           570:        mdoc_argv_free(j, argv);
        !           571:        return(c);
        !           572: }
        !           573:
        !           574:
        !           575: int
1.5       kristaps  576: macro_scoped_implicit(MACRO_PROT_ARGS)
1.2       kristaps  577: {
1.3       kristaps  578:        int               t, c, lastarg, j;
1.2       kristaps  579:        char             *args[MDOC_LINEARG_MAX];
                    580:        struct mdoc_node *n;
                    581:
1.5       kristaps  582:        assert( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
1.1       kristaps  583:
1.5       kristaps  584:        if (SEC_PROLOGUE == mdoc->sec_lastn)
                    585:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
1.1       kristaps  586:
1.6     ! kristaps  587:        /* FIXME: put into scope_rewind_imp(). */
        !           588:
1.3       kristaps  589:        /* LINTED */
1.2       kristaps  590:        for (n = mdoc->last; n; n = n->parent) {
                    591:                if (MDOC_BLOCK != n->type)
                    592:                        continue;
                    593:                if (tok == (t = n->data.block.tok))
1.1       kristaps  594:                        break;
1.2       kristaps  595:                if ( ! (MDOC_EXPLICIT & mdoc_macros[t].flags))
                    596:                        continue;
                    597:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
                    598:        }
                    599:
                    600:        if (n) {
                    601:                mdoc->last = n;
                    602:                mdoc_msg(mdoc, ppos, "scope: rewound `%s'",
                    603:                                mdoc_macronames[tok]);
                    604:        } else
                    605:                mdoc_msg(mdoc, ppos, "scope: new `%s'",
                    606:                                mdoc_macronames[tok]);
                    607:
                    608:        j = 0;
                    609:
                    610: again:
1.6     ! kristaps  611:        lastarg = *pos;
1.2       kristaps  612:
1.6     ! kristaps  613:        if (j == MDOC_LINEARG_MAX)
        !           614:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
1.2       kristaps  615:        c = args_next(mdoc, tok, pos, buf, &args[j]);
                    616:
                    617:        if (-1 == c)
                    618:                return(0);
                    619:        if (0 == c)
1.6     ! kristaps  620:                return(append_scoped(mdoc, tok, ppos,
        !           621:                                        j, _CC(args), 0, NULL));
1.1       kristaps  622:
1.2       kristaps  623:        /* Command found. */
1.1       kristaps  624:
1.2       kristaps  625:        if (MDOC_MAX != (c = mdoc_find(mdoc, args[j])))
1.3       kristaps  626:                if ( ! mdoc_warn(mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
1.1       kristaps  627:                        return(0);
                    628:
1.2       kristaps  629:        /* Word found. */
                    630:
                    631:        j++;
                    632:        goto again;
1.1       kristaps  633:
1.2       kristaps  634:        /* NOTREACHED */
1.1       kristaps  635: }
1.5       kristaps  636:

CVSweb