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

Annotation of mandoc/macro.c, Revision 1.35

1.35    ! kristaps    1: /* $Id: macro.c,v 1.34 2009/01/12 17:26:42 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.11      kristaps   24: #ifdef __linux__
                     25: #include <time.h>
                     26: #endif
1.2       kristaps   27:
                     28: #include "private.h"
                     29:
1.10      kristaps   30: /* FIXME: maxlineargs should be per LINE, no per TOKEN. */
                     31:
1.35    ! kristaps   32: static int       rewind_alt(int);
        !            33: static int       rewind_dohalt(int, enum mdoc_type,
        !            34:                        const struct mdoc_node *);
        !            35: #define        REWIND_REWIND   (1 << 0)
        !            36: #define        REWIND_NOHALT   (1 << 1)
        !            37: #define        REWIND_HALT     (1 << 2)
        !            38: static int       rewind_dobreak(int, enum mdoc_type,
        !            39:                        const struct mdoc_node *);
        !            40:
        !            41:
1.28      kristaps   42: static int       rewind_elem(struct mdoc *, int);
                     43: static int       rewind_impblock(struct mdoc *, int);
                     44: static int       rewind_expblock(struct mdoc *, int);
                     45: static int       rewind_head(struct mdoc *, int);
                     46: static int       rewind_body(struct mdoc *, int);
                     47: static int       rewind_last(struct mdoc *, struct mdoc_node *);
1.27      kristaps   48: static int       append_delims(struct mdoc *,
                     49:                        int, int, int *, char *);
1.30      kristaps   50: static int       lookup(struct mdoc *, int, int, int, const char *);
1.24      kristaps   51:
                     52:
                     53: static int
1.30      kristaps   54: lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
1.24      kristaps   55: {
1.30      kristaps   56:        int              res;
1.24      kristaps   57:
1.30      kristaps   58:        res = mdoc_find(mdoc, p);
                     59:        if (MDOC_PARSED & mdoc_macros[from].flags)
                     60:                return(res);
                     61:        if (MDOC_MAX == res)
                     62:                return(res);
                     63:
                     64:        if ( ! mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX_MACLIKE))
                     65:                return(-1);
                     66:        return(MDOC_MAX);
1.24      kristaps   67: }
1.19      kristaps   68:
                     69:
                     70: static int
1.28      kristaps   71: rewind_last(struct mdoc *mdoc, struct mdoc_node *to)
1.25      kristaps   72: {
                     73:
                     74:        assert(to);
1.30      kristaps   75:        mdoc->next = MDOC_NEXT_SIBLING;
                     76:        if (mdoc->last == to) {
                     77:                if ( ! mdoc_valid_post(mdoc))
                     78:                        return(0);
                     79:                if ( ! mdoc_action_post(mdoc))
                     80:                        return(0);
1.35    ! kristaps   81:                mdoc_msg(mdoc, "rewound to %s %s",
        !            82:                                mdoc_type2a(mdoc->last->type),
1.34      kristaps   83:                                mdoc_macronames[mdoc->last->tok]);
1.29      kristaps   84:                return(1);
1.30      kristaps   85:        }
1.29      kristaps   86:
                     87:        do {
                     88:                mdoc->last = mdoc->last->parent;
                     89:                assert(mdoc->last);
1.28      kristaps   90:                if ( ! mdoc_valid_post(mdoc))
1.25      kristaps   91:                        return(0);
1.28      kristaps   92:                if ( ! mdoc_action_post(mdoc))
1.25      kristaps   93:                        return(0);
1.35    ! kristaps   94:                mdoc_msg(mdoc, "rewound to %s %s",
        !            95:                                mdoc_type2a(mdoc->last->type),
1.34      kristaps   96:                                mdoc_macronames[mdoc->last->tok]);
1.29      kristaps   97:        } while (mdoc->last != to);
1.28      kristaps   98:
1.29      kristaps   99:        return(1);
1.25      kristaps  100: }
                    101:
                    102:
                    103: static int
1.35    ! kristaps  104: rewind_alt(int tok)
        !           105: {
        !           106:        switch (tok) {
        !           107:        case (MDOC_Ac):
        !           108:                return(MDOC_Ao);
        !           109:        case (MDOC_Bc):
        !           110:                return(MDOC_Bo);
        !           111:        case (MDOC_Dc):
        !           112:                return(MDOC_Do);
        !           113:        case (MDOC_Ec):
        !           114:                return(MDOC_Eo);
        !           115:        case (MDOC_Ed):
        !           116:                return(MDOC_Bd);
        !           117:        case (MDOC_Ef):
        !           118:                return(MDOC_Bf);
        !           119:        case (MDOC_Ek):
        !           120:                return(MDOC_Bk);
        !           121:        case (MDOC_El):
        !           122:                return(MDOC_Bl);
        !           123:        case (MDOC_Fc):
        !           124:                return(MDOC_Fo);
        !           125:        case (MDOC_Oc):
        !           126:                return(MDOC_Oo);
        !           127:        case (MDOC_Pc):
        !           128:                return(MDOC_Po);
        !           129:        case (MDOC_Qc):
        !           130:                return(MDOC_Qo);
        !           131:        case (MDOC_Re):
        !           132:                return(MDOC_Rs);
        !           133:        case (MDOC_Sc):
        !           134:                return(MDOC_So);
        !           135:        case (MDOC_Xc):
        !           136:                return(MDOC_Xo);
        !           137:        default:
        !           138:                break;
        !           139:        }
        !           140:        abort();
        !           141:        /* NOTREACHED */
        !           142: }
        !           143:
        !           144:
        !           145: static int
        !           146: rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
        !           147: {
        !           148:
        !           149:        if (MDOC_ROOT == p->type)
        !           150:                return(REWIND_HALT);
        !           151:        if (MDOC_TEXT == p->type)
        !           152:                return(REWIND_NOHALT);
        !           153:        if (MDOC_ELEM == p->type)
        !           154:                return(REWIND_NOHALT);
        !           155:
        !           156:        switch (tok) {
        !           157:        /* One-liner implicit-scope. */
        !           158:        case (MDOC_Aq):
        !           159:                /* FALLTHROUGH */
        !           160:        case (MDOC_Bq):
        !           161:                /* FALLTHROUGH */
        !           162:        case (MDOC_D1):
        !           163:                /* FALLTHROUGH */
        !           164:        case (MDOC_Dl):
        !           165:                /* FALLTHROUGH */
        !           166:        case (MDOC_Dq):
        !           167:                /* FALLTHROUGH */
        !           168:        case (MDOC_Op):
        !           169:                /* FALLTHROUGH */
        !           170:        case (MDOC_Pq):
        !           171:                /* FALLTHROUGH */
        !           172:        case (MDOC_Ql):
        !           173:                /* FALLTHROUGH */
        !           174:        case (MDOC_Qq):
        !           175:                /* FALLTHROUGH */
        !           176:        case (MDOC_Sq):
        !           177:                assert(MDOC_BODY != type);
        !           178:                assert(MDOC_TAIL != type);
        !           179:                if (type == p->type && tok == p->tok)
        !           180:                        return(REWIND_REWIND);
        !           181:                break;
        !           182:
        !           183:        /* Multi-line implicit-scope. */
        !           184:        case (MDOC_It):
        !           185:                assert(MDOC_TAIL != type);
        !           186:                if (type == p->type && tok == p->tok)
        !           187:                        return(REWIND_REWIND);
        !           188:                if (MDOC_BLOCK == type && MDOC_BODY == p->type &&
        !           189:                                MDOC_Bl == p->tok)
        !           190:                        return(REWIND_HALT);
        !           191:                break;
        !           192:        case (MDOC_Sh):
        !           193:                /* FALLTHROUGH */
        !           194:        case (MDOC_Ss):
        !           195:                if (type == p->type && tok == p->tok)
        !           196:                        return(REWIND_REWIND);
        !           197:                break;
        !           198:
        !           199:        /* Multi-line explicit scope start. */
        !           200:        case (MDOC_Ao):
        !           201:                /* FALLTHROUGH */
        !           202:        case (MDOC_Bd):
        !           203:                /* FALLTHROUGH */
        !           204:        case (MDOC_Bf):
        !           205:                /* FALLTHROUGH */
        !           206:        case (MDOC_Bk):
        !           207:                /* FALLTHROUGH */
        !           208:        case (MDOC_Bl):
        !           209:                /* FALLTHROUGH */
        !           210:        case (MDOC_Bo):
        !           211:                /* FALLTHROUGH */
        !           212:        case (MDOC_Do):
        !           213:                /* FALLTHROUGH */
        !           214:        case (MDOC_Eo):
        !           215:                /* FALLTHROUGH */
        !           216:        case (MDOC_Fo):
        !           217:                /* FALLTHROUGH */
        !           218:        case (MDOC_Oo):
        !           219:                /* FALLTHROUGH */
        !           220:        case (MDOC_Po):
        !           221:                /* FALLTHROUGH */
        !           222:        case (MDOC_Qo):
        !           223:                /* FALLTHROUGH */
        !           224:        case (MDOC_Rs):
        !           225:                /* FALLTHROUGH */
        !           226:        case (MDOC_So):
        !           227:                /* FALLTHROUGH */
        !           228:        case (MDOC_Xo):
        !           229:                if (type == p->type && tok == p->tok)
        !           230:                        return(REWIND_REWIND);
        !           231:                break;
        !           232:
        !           233:        /* Multi-line explicit scope close. */
        !           234:        case (MDOC_Ac):
        !           235:                /* FALLTHROUGH */
        !           236:        case (MDOC_Bc):
        !           237:                /* FALLTHROUGH */
        !           238:        case (MDOC_Dc):
        !           239:                /* FALLTHROUGH */
        !           240:        case (MDOC_Ec):
        !           241:                /* FALLTHROUGH */
        !           242:        case (MDOC_Ed):
        !           243:                /* FALLTHROUGH */
        !           244:        case (MDOC_Ek):
        !           245:                /* FALLTHROUGH */
        !           246:        case (MDOC_El):
        !           247:                /* FALLTHROUGH */
        !           248:        case (MDOC_Fc):
        !           249:                /* FALLTHROUGH */
        !           250:        case (MDOC_Ef):
        !           251:                /* FALLTHROUGH */
        !           252:        case (MDOC_Oc):
        !           253:                /* FALLTHROUGH */
        !           254:        case (MDOC_Pc):
        !           255:                /* FALLTHROUGH */
        !           256:        case (MDOC_Qc):
        !           257:                /* FALLTHROUGH */
        !           258:        case (MDOC_Re):
        !           259:                /* FALLTHROUGH */
        !           260:        case (MDOC_Sc):
        !           261:                /* FALLTHROUGH */
        !           262:        case (MDOC_Xc):
        !           263:                if (type == p->type && rewind_alt(tok) == p->tok)
        !           264:                        return(REWIND_REWIND);
        !           265:                break;
        !           266:        default:
        !           267:                abort();
        !           268:                /* NOTREACHED */
        !           269:        }
        !           270:
        !           271:        return(REWIND_NOHALT);
        !           272: }
        !           273:
        !           274:
        !           275: static int
        !           276: rewind_dobreak(int tok, enum mdoc_type type, const struct mdoc_node *p)
        !           277: {
        !           278:
        !           279:        assert(MDOC_ROOT != p->type);
        !           280:        if (MDOC_ELEM == p->type)
        !           281:                return(1);
        !           282:        if (MDOC_TEXT == p->type)
        !           283:                return(1);
        !           284:
        !           285:        switch (tok) {
        !           286:        case (MDOC_It):
        !           287:                return(MDOC_It == p->tok);
        !           288:        case (MDOC_Ss):
        !           289:                return(MDOC_Ss == p->tok);
        !           290:        case (MDOC_Sh):
        !           291:                if (MDOC_Ss == p->tok)
        !           292:                        return(1);
        !           293:                return(MDOC_Sh == p->tok);
        !           294:        }
        !           295:
        !           296:        if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
        !           297:                return(p->tok == rewind_alt(tok));
        !           298:        else if (MDOC_BLOCK == p->type)
        !           299:                return(1);
        !           300:
        !           301:        return(tok == p->tok);
        !           302: }
        !           303:
        !           304:
        !           305: static int
1.28      kristaps  306: rewind_elem(struct mdoc *mdoc, int tok)
1.19      kristaps  307: {
                    308:        struct mdoc_node *n;
1.2       kristaps  309:
1.19      kristaps  310:        n = mdoc->last;
                    311:        if (MDOC_ELEM != n->type)
                    312:                n = n->parent;
                    313:        assert(MDOC_ELEM == n->type);
1.32      kristaps  314:        assert(tok == n->tok);
1.19      kristaps  315:
1.28      kristaps  316:        return(rewind_last(mdoc, n));
1.19      kristaps  317: }
1.6       kristaps  318:
                    319:
                    320: static int
1.28      kristaps  321: rewind_body(struct mdoc *mdoc, int tok)
1.22      kristaps  322: {
                    323:        struct mdoc_node *n;
1.35    ! kristaps  324:        int               c;
1.28      kristaps  325:
1.22      kristaps  326:        /* LINTED */
                    327:        for (n = mdoc->last; n; n = n->parent) {
1.35    ! kristaps  328:                c = rewind_dohalt(tok, MDOC_BODY, n);
        !           329:                if (REWIND_HALT == c)
        !           330:                        return(1);
        !           331:                if (REWIND_REWIND == c)
1.22      kristaps  332:                        break;
1.35    ! kristaps  333:                else if (rewind_dobreak(tok, MDOC_BODY, n))
1.22      kristaps  334:                        continue;
1.28      kristaps  335:                return(mdoc_verr(mdoc, n, ERR_SCOPE_BREAK));
1.22      kristaps  336:        }
                    337:
1.25      kristaps  338:        assert(n);
1.28      kristaps  339:        return(rewind_last(mdoc, n));
1.22      kristaps  340: }
                    341:
                    342:
                    343: static int
1.28      kristaps  344: rewind_head(struct mdoc *mdoc, int tok)
1.6       kristaps  345: {
                    346:        struct mdoc_node *n;
1.35    ! kristaps  347:        int               c;
1.28      kristaps  348:
1.6       kristaps  349:        /* LINTED */
1.16      kristaps  350:        for (n = mdoc->last; n; n = n->parent) {
1.35    ! kristaps  351:                c = rewind_dohalt(tok, MDOC_HEAD, n);
        !           352:                if (REWIND_HALT == c)
        !           353:                        return(1);
        !           354:                if (REWIND_REWIND == c)
1.6       kristaps  355:                        break;
1.35    ! kristaps  356:                else if (rewind_dobreak(tok, MDOC_HEAD, n))
1.7       kristaps  357:                        continue;
1.28      kristaps  358:                return(mdoc_verr(mdoc, n, ERR_SCOPE_BREAK));
1.6       kristaps  359:        }
                    360:
1.25      kristaps  361:        assert(n);
1.28      kristaps  362:        return(rewind_last(mdoc, n));
1.6       kristaps  363: }
                    364:
                    365:
                    366: static int
1.28      kristaps  367: rewind_expblock(struct mdoc *mdoc, int tok)
1.6       kristaps  368: {
1.7       kristaps  369:        struct mdoc_node *n;
1.35    ! kristaps  370:        int               c;
1.6       kristaps  371:
1.7       kristaps  372:        /* LINTED */
1.35    ! kristaps  373:        for (n = mdoc->last; n; n = n->parent) {
        !           374:                c = rewind_dohalt(tok, MDOC_BLOCK, n);
        !           375:                if (REWIND_HALT == c)
        !           376:                        return(mdoc_err(mdoc, ERR_SCOPE_NOCTX));
        !           377:                if (REWIND_REWIND == c)
1.16      kristaps  378:                        break;
1.35    ! kristaps  379:                else if (rewind_dobreak(tok, MDOC_BLOCK, n))
1.22      kristaps  380:                        continue;
1.28      kristaps  381:                return(mdoc_verr(mdoc, n, ERR_SCOPE_BREAK));
1.16      kristaps  382:        }
                    383:
1.28      kristaps  384:        assert(n);
                    385:        return(rewind_last(mdoc, n));
1.21      kristaps  386: }
                    387:
                    388:
                    389: static int
1.28      kristaps  390: rewind_impblock(struct mdoc *mdoc, int tok)
1.21      kristaps  391: {
                    392:        struct mdoc_node *n;
1.35    ! kristaps  393:        int               c;
1.21      kristaps  394:
                    395:        /* LINTED */
1.35    ! kristaps  396:        for (n = mdoc->last; n; n = n->parent) {
        !           397:                c = rewind_dohalt(tok, MDOC_BLOCK, n);
        !           398:                if (REWIND_HALT == c)
        !           399:                        return(1);
        !           400:                else if (REWIND_REWIND == c)
1.21      kristaps  401:                        break;
1.35    ! kristaps  402:                else if (rewind_dobreak(tok, MDOC_BLOCK, n))
1.21      kristaps  403:                        continue;
1.28      kristaps  404:                return(mdoc_verr(mdoc, n, ERR_SCOPE_BREAK));
1.21      kristaps  405:        }
                    406:
1.35    ! kristaps  407:        assert(n);
1.28      kristaps  408:        return(rewind_last(mdoc, n));
1.16      kristaps  409: }
                    410:
                    411:
1.22      kristaps  412: static int
1.27      kristaps  413: append_delims(struct mdoc *mdoc, int tok,
                    414:                int line, int *pos, char *buf)
1.22      kristaps  415: {
                    416:        int              c, lastarg;
                    417:        char            *p;
                    418:
                    419:        if (0 == buf[*pos])
                    420:                return(1);
                    421:
                    422:        for (;;) {
                    423:                lastarg = *pos;
1.28      kristaps  424:                c = mdoc_args(mdoc, line, pos, buf, 0, &p);
1.22      kristaps  425:                if (ARGS_ERROR == c)
                    426:                        return(0);
                    427:                else if (ARGS_EOLN == c)
                    428:                        break;
                    429:                assert(mdoc_isdelim(p));
1.28      kristaps  430:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    431:                        return(0);
1.22      kristaps  432:                mdoc->next = MDOC_NEXT_SIBLING;
                    433:        }
                    434:
                    435:        return(1);
                    436: }
                    437:
                    438:
1.19      kristaps  439: /* ARGSUSED */
                    440: int
1.35    ! kristaps  441: macro_scoped_close(MACRO_PROT_ARGS)
1.19      kristaps  442: {
1.28      kristaps  443:        int              tt, j, c, lastarg, maxargs, flushed;
1.22      kristaps  444:        char            *p;
1.19      kristaps  445:
                    446:        switch (tok) {
1.22      kristaps  447:        case (MDOC_Ec):
                    448:                maxargs = 1;
                    449:                break;
                    450:        default:
                    451:                maxargs = 0;
                    452:                break;
                    453:        }
                    454:
1.35    ! kristaps  455:        tt = rewind_alt(tok);
        !           456:
1.22      kristaps  457:        if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
1.35    ! kristaps  458:                if (0 == buf[*pos]) {
        !           459:                        if ( ! rewind_body(mdoc, tok))
        !           460:                                return(0);
        !           461:                        return(rewind_expblock(mdoc, tok));
        !           462:                }
1.28      kristaps  463:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_EQ0));
1.22      kristaps  464:        }
1.19      kristaps  465:
1.35    ! kristaps  466:        if ( ! rewind_body(mdoc, tok))
1.22      kristaps  467:                return(0);
1.19      kristaps  468:
1.22      kristaps  469:        lastarg = ppos;
                    470:        flushed = 0;
1.15      kristaps  471:
1.22      kristaps  472:        if (maxargs > 0) {
1.28      kristaps  473:                if ( ! mdoc_tail_alloc(mdoc, line, ppos, tt))
                    474:                        return(0);
1.22      kristaps  475:                mdoc->next = MDOC_NEXT_CHILD;
                    476:        }
1.15      kristaps  477:
1.22      kristaps  478:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
1.15      kristaps  479:                lastarg = *pos;
1.22      kristaps  480:
                    481:                if (j == maxargs && ! flushed) {
1.35    ! kristaps  482:                        if ( ! rewind_expblock(mdoc, tok))
1.22      kristaps  483:                                return(0);
                    484:                        flushed = 1;
                    485:                }
                    486:
1.28      kristaps  487:                c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.15      kristaps  488:                if (ARGS_ERROR == c)
                    489:                        return(0);
1.22      kristaps  490:                if (ARGS_PUNCT == c)
                    491:                        break;
                    492:                if (ARGS_EOLN == c)
                    493:                        break;
                    494:
1.30      kristaps  495:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    496:                        return(0);
                    497:                else if (MDOC_MAX != c) {
1.22      kristaps  498:                        if ( ! flushed) {
1.35    ! kristaps  499:                                if ( ! rewind_expblock(mdoc, tok))
1.22      kristaps  500:                                        return(0);
                    501:                                flushed = 1;
                    502:                        }
1.26      kristaps  503:                        if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22      kristaps  504:                                return(0);
1.15      kristaps  505:                        break;
1.30      kristaps  506:                }
1.22      kristaps  507:
1.28      kristaps  508:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    509:                        return(0);
1.16      kristaps  510:                mdoc->next = MDOC_NEXT_SIBLING;
1.15      kristaps  511:        }
1.2       kristaps  512:
1.22      kristaps  513:        if (MDOC_LINEARG_MAX == j)
1.28      kristaps  514:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.22      kristaps  515:
1.35    ! kristaps  516:        if ( ! flushed && ! rewind_expblock(mdoc, tok))
1.28      kristaps  517:                return(0);
1.22      kristaps  518:
                    519:        if (ppos > 1)
                    520:                return(1);
1.27      kristaps  521:        return(append_delims(mdoc, tok, line, pos, buf));
1.1       kristaps  522: }
                    523:
1.2       kristaps  524:
1.19      kristaps  525: /*
                    526:  * A general text domain macro.  When invoked, this opens a scope that
                    527:  * accepts words until either end-of-line, only-punctuation, or a
                    528:  * callable macro.  If the word is punctuation (not only-punctuation),
                    529:  * then the scope is closed out, the punctuation appended, then the
                    530:  * scope opened again.  If any terminating conditions are met, the scope
                    531:  * is closed out.  If this is the first macro in the line and
                    532:  * only-punctuation remains, this punctuation is flushed.
                    533:  */
                    534: int
                    535: macro_text(MACRO_PROT_ARGS)
1.13      kristaps  536: {
1.28      kristaps  537:        int               la, lastpunct, c, sz, fl, argc;
1.19      kristaps  538:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
                    539:        char             *p;
1.13      kristaps  540:
1.28      kristaps  541:        la = ppos;
1.19      kristaps  542:        lastpunct = 0;
1.17      kristaps  543:
1.19      kristaps  544:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1.28      kristaps  545:                la = *pos;
1.17      kristaps  546:
1.28      kristaps  547:                c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.19      kristaps  548:                if (ARGV_EOLN == c || ARGV_WORD == c)
                    549:                        break;
                    550:                else if (ARGV_ARG == c)
                    551:                        continue;
                    552:                mdoc_argv_free(argc, argv);
1.14      kristaps  553:                return(0);
1.10      kristaps  554:        }
                    555:
1.28      kristaps  556:        if (MDOC_LINEARG_MAX == argc) {
                    557:                mdoc_argv_free(argc, argv);
                    558:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
                    559:        }
                    560:
                    561:        c = mdoc_elem_alloc(mdoc, line, la, tok, argc, argv);
                    562:
                    563:        if (0 == c) {
1.19      kristaps  564:                mdoc_argv_free(argc, argv);
                    565:                return(0);
1.7       kristaps  566:        }
                    567:
1.28      kristaps  568:        mdoc->next = MDOC_NEXT_CHILD;
                    569:
1.15      kristaps  570:        fl = ARGS_DELIM;
                    571:        if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
                    572:                fl |= ARGS_QUOTED;
1.7       kristaps  573:
1.19      kristaps  574:        for (lastpunct = sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
1.28      kristaps  575:                la = *pos;
1.7       kristaps  576:
1.19      kristaps  577:                if (lastpunct) {
1.28      kristaps  578:                        c = mdoc_elem_alloc(mdoc, line,
                    579:                                        la, tok, argc, argv);
                    580:                        if (0 == c) {
                    581:                                mdoc_argv_free(argc, argv);
                    582:                                return(0);
                    583:                        }
1.19      kristaps  584:                        mdoc->next = MDOC_NEXT_CHILD;
                    585:                        lastpunct = 0;
                    586:                }
1.2       kristaps  587:
1.28      kristaps  588:                c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.19      kristaps  589:                if (ARGS_ERROR == c) {
                    590:                        mdoc_argv_free(argc, argv);
1.7       kristaps  591:                        return(0);
1.19      kristaps  592:                }
                    593:
                    594:                if (ARGS_EOLN == c)
                    595:                        break;
                    596:                if (ARGS_PUNCT == c)
                    597:                        break;
1.2       kristaps  598:
1.30      kristaps  599:                if (-1 == (c = lookup(mdoc, line, la, tok, p)))
                    600:                        return(0);
                    601:                else if (MDOC_MAX != c) {
1.28      kristaps  602:                        if ( ! rewind_elem(mdoc, tok)) {
1.19      kristaps  603:                                mdoc_argv_free(argc, argv);
                    604:                                return(0);
                    605:                        }
                    606:                        mdoc_argv_free(argc, argv);
1.28      kristaps  607:
                    608:                        c = mdoc_macro(mdoc, c, line, la, pos, buf);
                    609:                        if (0 == c)
1.19      kristaps  610:                                return(0);
                    611:                        if (ppos > 1)
                    612:                                return(1);
1.27      kristaps  613:                        return(append_delims(mdoc, tok, line, pos, buf));
1.19      kristaps  614:                }
1.2       kristaps  615:
1.19      kristaps  616:                if (mdoc_isdelim(p)) {
1.28      kristaps  617:                        if ( ! rewind_elem(mdoc, tok)) {
1.19      kristaps  618:                                mdoc_argv_free(argc, argv);
                    619:                                return(0);
                    620:                        }
                    621:                        lastpunct = 1;
                    622:                }
1.28      kristaps  623:                if ( ! mdoc_word_alloc(mdoc, line, la, p))
                    624:                        return(0);
1.19      kristaps  625:                mdoc->next = MDOC_NEXT_SIBLING;
1.2       kristaps  626:        }
                    627:
1.19      kristaps  628:        mdoc_argv_free(argc, argv);
1.2       kristaps  629:
1.19      kristaps  630:        if (sz == MDOC_LINEARG_MAX)
1.28      kristaps  631:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.2       kristaps  632:
1.28      kristaps  633:        if ( ! rewind_elem(mdoc, tok))
1.7       kristaps  634:                return(0);
1.19      kristaps  635:        if (ppos > 1)
                    636:                return(1);
1.27      kristaps  637:        return(append_delims(mdoc, tok, line, pos, buf));
1.5       kristaps  638: }
                    639:
                    640:
1.19      kristaps  641: /*
1.28      kristaps  642:  * Implicit- or explicit-end multi-line scoped macro.
1.19      kristaps  643:  */
1.5       kristaps  644: int
1.16      kristaps  645: macro_scoped(MACRO_PROT_ARGS)
1.6       kristaps  646: {
1.33      kristaps  647:        int               c, lastarg, argc, j, fl;
1.6       kristaps  648:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
1.24      kristaps  649:        char             *p;
1.6       kristaps  650:
1.16      kristaps  651:        assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1.6       kristaps  652:
1.35    ! kristaps  653:        if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
        !           654:                if ( ! rewind_body(mdoc, tok))
        !           655:                        return(0);
1.28      kristaps  656:                if ( ! rewind_impblock(mdoc, tok))
1.16      kristaps  657:                        return(0);
1.35    ! kristaps  658:        }
1.2       kristaps  659:
1.16      kristaps  660:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
                    661:                lastarg = *pos;
1.28      kristaps  662:                c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.16      kristaps  663:                if (ARGV_EOLN == c || ARGV_WORD == c)
                    664:                        break;
                    665:                else if (ARGV_ARG == c)
                    666:                        continue;
                    667:                mdoc_argv_free(argc, argv);
1.8       kristaps  668:                return(0);
1.16      kristaps  669:        }
1.2       kristaps  670:
1.28      kristaps  671:        if (MDOC_LINEARG_MAX == argc) {
1.16      kristaps  672:                mdoc_argv_free(argc, argv);
1.28      kristaps  673:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
                    674:        }
                    675:
                    676:        c = mdoc_block_alloc(mdoc, line, ppos,
                    677:                        tok, (size_t)argc, argv);
                    678:        mdoc_argv_free(argc, argv);
                    679:
                    680:        if (0 == c)
1.16      kristaps  681:                return(0);
1.8       kristaps  682:
1.19      kristaps  683:        mdoc->next = MDOC_NEXT_CHILD;
                    684:
1.24      kristaps  685:        if (0 == buf[*pos]) {
1.28      kristaps  686:                if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    687:                        return(0);
                    688:                if ( ! rewind_head(mdoc, tok))
                    689:                        return(0);
                    690:                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25      kristaps  691:                        return(0);
1.19      kristaps  692:                mdoc->next = MDOC_NEXT_CHILD;
1.24      kristaps  693:                return(1);
                    694:        }
1.19      kristaps  695:
1.28      kristaps  696:        if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    697:                return(0);
1.24      kristaps  698:        mdoc->next = MDOC_NEXT_CHILD;
1.7       kristaps  699:
1.33      kristaps  700:        fl = ARGS_DELIM;
                    701:        if (MDOC_TABSEP & mdoc_macros[tok].flags)
                    702:                fl |= ARGS_TABSEP;
                    703:
1.24      kristaps  704:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
                    705:                lastarg = *pos;
1.33      kristaps  706:                c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.24      kristaps  707:
                    708:                if (ARGS_ERROR == c)
1.19      kristaps  709:                        return(0);
1.24      kristaps  710:                if (ARGS_PUNCT == c)
                    711:                        break;
                    712:                if (ARGS_EOLN == c)
                    713:                        break;
                    714:
1.30      kristaps  715:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    716:                        return(0);
                    717:                else if (MDOC_MAX == c) {
1.28      kristaps  718:                        if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    719:                                return(0);
1.24      kristaps  720:                        mdoc->next = MDOC_NEXT_SIBLING;
                    721:                        continue;
1.30      kristaps  722:                }
1.2       kristaps  723:
1.26      kristaps  724:                if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.24      kristaps  725:                        return(0);
                    726:                break;
1.7       kristaps  727:        }
1.1       kristaps  728:
1.24      kristaps  729:        if (j == MDOC_LINEARG_MAX)
1.28      kristaps  730:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.24      kristaps  731:
1.28      kristaps  732:        if ( ! rewind_head(mdoc, tok))
1.24      kristaps  733:                return(0);
1.27      kristaps  734:        if (1 == ppos && ! append_delims(mdoc, tok, line, pos, buf))
1.24      kristaps  735:                return(0);
                    736:
1.28      kristaps  737:        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                    738:                return(0);
1.16      kristaps  739:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  740:
1.16      kristaps  741:        return(1);
1.1       kristaps  742: }
1.5       kristaps  743:
1.7       kristaps  744:
1.19      kristaps  745: /*
                    746:  * When scoped to a line, a macro encompasses all of the contents.  This
                    747:  * differs from constants or text macros, where a new macro will
                    748:  * terminate the existing context.
                    749:  */
1.7       kristaps  750: int
1.16      kristaps  751: macro_scoped_line(MACRO_PROT_ARGS)
1.7       kristaps  752: {
1.8       kristaps  753:        int               lastarg, c, j;
                    754:        char              *p;
1.7       kristaps  755:
1.28      kristaps  756:        if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
                    757:                return(0);
1.16      kristaps  758:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  759:
1.28      kristaps  760:        if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    761:                return(0);
1.16      kristaps  762:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  763:
1.19      kristaps  764:        /* XXX - no known argument macros. */
                    765:
                    766:        for (lastarg = ppos, j = 0; j < MDOC_LINEARG_MAX; j++) {
                    767:                lastarg = *pos;
1.28      kristaps  768:                c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.8       kristaps  769:
1.19      kristaps  770:                if (ARGS_ERROR == c)
                    771:                        return(0);
                    772:                if (ARGS_PUNCT == c)
                    773:                        break;
                    774:                if (ARGS_EOLN == c)
                    775:                        break;
1.8       kristaps  776:
1.30      kristaps  777:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    778:                        return(0);
                    779:                else if (MDOC_MAX == c) {
1.28      kristaps  780:                        if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    781:                                return(0);
1.19      kristaps  782:                        mdoc->next = MDOC_NEXT_SIBLING;
                    783:                        continue;
1.30      kristaps  784:                }
1.8       kristaps  785:
1.26      kristaps  786:                if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19      kristaps  787:                        return(0);
1.8       kristaps  788:                break;
                    789:        }
                    790:
1.19      kristaps  791:        if (j == MDOC_LINEARG_MAX)
1.28      kristaps  792:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.19      kristaps  793:
                    794:        if (1 == ppos) {
1.28      kristaps  795:                if ( ! rewind_head(mdoc, tok))
1.16      kristaps  796:                        return(0);
1.27      kristaps  797:                if ( ! append_delims(mdoc, tok, line, pos, buf))
1.8       kristaps  798:                        return(0);
                    799:        }
1.35    ! kristaps  800:        if ( ! rewind_head(mdoc, tok))
        !           801:                return(0);
1.28      kristaps  802:        return(rewind_impblock(mdoc, tok));
1.22      kristaps  803: }
                    804:
                    805:
1.28      kristaps  806: /*
                    807:  * Constant-scope macros accept a fixed number of arguments and behave
                    808:  * like constant macros except that they're scoped across lines.
                    809:  */
1.22      kristaps  810: int
                    811: macro_constant_scoped(MACRO_PROT_ARGS)
                    812: {
                    813:        int               lastarg, flushed, j, c, maxargs;
                    814:        char             *p;
                    815:
                    816:        lastarg = ppos;
                    817:        flushed = 0;
                    818:
                    819:        switch (tok) {
                    820:        case (MDOC_Eo):
                    821:                maxargs = 1;
                    822:                break;
                    823:        default:
                    824:                maxargs = 0;
                    825:                break;
                    826:        }
                    827:
1.28      kristaps  828:        if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
                    829:                return(0);
1.22      kristaps  830:        mdoc->next = MDOC_NEXT_CHILD;
                    831:
                    832:        if (0 == maxargs) {
1.28      kristaps  833:                if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    834:                        return(0);
                    835:                if ( ! rewind_head(mdoc, tok))
                    836:                        return(0);
                    837:                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25      kristaps  838:                        return(0);
1.22      kristaps  839:                flushed = 1;
1.28      kristaps  840:        } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    841:                return(0);
1.22      kristaps  842:
                    843:        mdoc->next = MDOC_NEXT_CHILD;
                    844:
                    845:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
                    846:                lastarg = *pos;
                    847:
                    848:                if (j == maxargs && ! flushed) {
1.28      kristaps  849:                        if ( ! rewind_head(mdoc, tok))
1.22      kristaps  850:                                return(0);
                    851:                        flushed = 1;
1.28      kristaps  852:                        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                    853:                                return(0);
1.22      kristaps  854:                        mdoc->next = MDOC_NEXT_CHILD;
                    855:                }
                    856:
1.28      kristaps  857:                c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.22      kristaps  858:                if (ARGS_ERROR == c)
                    859:                        return(0);
                    860:                if (ARGS_PUNCT == c)
                    861:                        break;
                    862:                if (ARGS_EOLN == c)
                    863:                        break;
                    864:
1.30      kristaps  865:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    866:                        return(0);
                    867:                else if (MDOC_MAX != c) {
1.22      kristaps  868:                        if ( ! flushed) {
1.28      kristaps  869:                                if ( ! rewind_head(mdoc, tok))
1.22      kristaps  870:                                        return(0);
                    871:                                flushed = 1;
1.28      kristaps  872:                                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                    873:                                        return(0);
1.22      kristaps  874:                                mdoc->next = MDOC_NEXT_CHILD;
                    875:                        }
1.26      kristaps  876:                        if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22      kristaps  877:                                return(0);
                    878:                        break;
                    879:                }
                    880:
                    881:                if ( ! flushed && mdoc_isdelim(p)) {
1.28      kristaps  882:                        if ( ! rewind_head(mdoc, tok))
1.22      kristaps  883:                                return(0);
                    884:                        flushed = 1;
1.28      kristaps  885:                        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                    886:                                return(0);
1.22      kristaps  887:                        mdoc->next = MDOC_NEXT_CHILD;
                    888:                }
                    889:
1.28      kristaps  890:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    891:                        return(0);
1.22      kristaps  892:                mdoc->next = MDOC_NEXT_SIBLING;
                    893:        }
                    894:
                    895:        if (MDOC_LINEARG_MAX == j)
1.28      kristaps  896:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.22      kristaps  897:
                    898:        if ( ! flushed) {
1.28      kristaps  899:                if ( ! rewind_head(mdoc, tok))
                    900:                        return(0);
                    901:                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.22      kristaps  902:                        return(0);
                    903:                mdoc->next = MDOC_NEXT_CHILD;
                    904:        }
                    905:
                    906:        if (ppos > 1)
                    907:                return(1);
1.27      kristaps  908:        return(append_delims(mdoc, tok, line, pos, buf));
1.7       kristaps  909: }
1.8       kristaps  910:
1.10      kristaps  911:
1.19      kristaps  912: /*
                    913:  * Delimited macros are like text macros except that, should punctuation
                    914:  * be encountered, the macro isn't re-started with remaining tokens
                    915:  * (it's only emitted once).  Delimited macros can have a maximum number
                    916:  * of arguments.
1.17      kristaps  917:  */
1.10      kristaps  918: int
                    919: macro_constant_delimited(MACRO_PROT_ARGS)
                    920: {
1.24      kristaps  921:        int               lastarg, flushed, j, c, maxargs, argc;
                    922:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
1.13      kristaps  923:        char             *p;
1.10      kristaps  924:
                    925:        lastarg = ppos;
                    926:        flushed = 0;
                    927:
                    928:        switch (tok) {
1.16      kristaps  929:        case (MDOC_No):
                    930:                /* FALLTHROUGH */
                    931:        case (MDOC_Ns):
                    932:                /* FALLTHROUGH */
1.10      kristaps  933:        case (MDOC_Ux):
1.24      kristaps  934:                /* FALLTHROUGH */
                    935:        case (MDOC_St):
1.10      kristaps  936:                maxargs = 0;
                    937:                break;
                    938:        default:
                    939:                maxargs = 1;
                    940:                break;
                    941:        }
                    942:
1.24      kristaps  943:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
                    944:                lastarg = *pos;
1.28      kristaps  945:                c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.24      kristaps  946:                if (ARGV_EOLN == c || ARGV_WORD == c)
                    947:                        break;
                    948:                else if (ARGV_ARG == c)
                    949:                        continue;
                    950:                mdoc_argv_free(argc, argv);
                    951:                return(0);
                    952:        }
                    953:
1.28      kristaps  954:        c = mdoc_elem_alloc(mdoc, line, lastarg, tok, argc, argv);
                    955:        mdoc_argv_free(argc, argv);
                    956:
                    957:        if (0 == c)
1.24      kristaps  958:                return(0);
                    959:
1.19      kristaps  960:        mdoc->next = MDOC_NEXT_CHILD;
1.10      kristaps  961:
1.19      kristaps  962:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
                    963:                lastarg = *pos;
1.10      kristaps  964:
1.19      kristaps  965:                if (j == maxargs && ! flushed) {
1.28      kristaps  966:                        if ( ! rewind_elem(mdoc, tok))
1.19      kristaps  967:                                return(0);
                    968:                        flushed = 1;
                    969:                }
1.11      kristaps  970:
1.28      kristaps  971:                c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.19      kristaps  972:                if (ARGS_ERROR == c)
1.10      kristaps  973:                        return(0);
1.19      kristaps  974:                if (ARGS_PUNCT == c)
                    975:                        break;
                    976:                if (ARGS_EOLN == c)
                    977:                        break;
                    978:
1.30      kristaps  979:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    980:                        return(0);
                    981:                else if (MDOC_MAX != c) {
1.28      kristaps  982:                        if ( ! flushed && ! rewind_elem(mdoc, tok))
1.19      kristaps  983:                                return(0);
                    984:                        flushed = 1;
1.26      kristaps  985:                        if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19      kristaps  986:                                return(0);
                    987:                        break;
                    988:                }
1.10      kristaps  989:
1.22      kristaps  990:                if ( ! flushed && mdoc_isdelim(p)) {
1.28      kristaps  991:                        if ( ! rewind_elem(mdoc, tok))
1.19      kristaps  992:                                return(0);
                    993:                        flushed = 1;
                    994:                }
                    995:
1.28      kristaps  996:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    997:                        return(0);
1.19      kristaps  998:                mdoc->next = MDOC_NEXT_SIBLING;
1.10      kristaps  999:        }
                   1000:
1.22      kristaps 1001:        if (MDOC_LINEARG_MAX == j)
1.28      kristaps 1002:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.22      kristaps 1003:
1.28      kristaps 1004:        if ( ! flushed && rewind_elem(mdoc, tok))
1.19      kristaps 1005:                return(0);
1.11      kristaps 1006:
1.19      kristaps 1007:        if (ppos > 1)
                   1008:                return(1);
1.27      kristaps 1009:        return(append_delims(mdoc, tok, line, pos, buf));
1.10      kristaps 1010: }
1.11      kristaps 1011:
                   1012:
1.19      kristaps 1013: /*
                   1014:  * Constant macros span an entire line:  they constitute a macro and all
                   1015:  * of its arguments and child data.
                   1016:  */
1.11      kristaps 1017: int
                   1018: macro_constant(MACRO_PROT_ARGS)
                   1019: {
1.19      kristaps 1020:        int              c, lastarg, argc, sz, fl;
                   1021:        struct mdoc_arg  argv[MDOC_LINEARG_MAX];
                   1022:        char            *p;
1.11      kristaps 1023:
1.28      kristaps 1024:        /* FIXME: parsing macros! */
1.24      kristaps 1025:
1.16      kristaps 1026:        fl = 0;
1.15      kristaps 1027:        if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
                   1028:                fl = ARGS_QUOTED;
1.11      kristaps 1029:
1.16      kristaps 1030:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
                   1031:                lastarg = *pos;
1.28      kristaps 1032:                c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.16      kristaps 1033:                if (ARGV_EOLN == c)
                   1034:                        break;
                   1035:                else if (ARGV_ARG == c)
                   1036:                        continue;
                   1037:                else if (ARGV_WORD == c)
                   1038:                        break;
1.11      kristaps 1039:
1.16      kristaps 1040:                mdoc_argv_free(argc, argv);
1.11      kristaps 1041:                return(0);
                   1042:        }
                   1043:
1.28      kristaps 1044:        c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
                   1045:        mdoc_argv_free(argc, argv);
                   1046:
                   1047:        if (0 == c)
                   1048:                return(0);
1.11      kristaps 1049:
1.19      kristaps 1050:        mdoc->next = MDOC_NEXT_CHILD;
                   1051:
1.28      kristaps 1052:        if (MDOC_LINEARG_MAX == argc)
                   1053:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.19      kristaps 1054:
1.16      kristaps 1055:        for (sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
1.13      kristaps 1056:                lastarg = *pos;
1.28      kristaps 1057:                c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.16      kristaps 1058:                if (ARGS_ERROR == c)
                   1059:                        return(0);
                   1060:                if (ARGS_EOLN == c)
1.13      kristaps 1061:                        break;
1.19      kristaps 1062:
1.28      kristaps 1063:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                   1064:                        return(0);
1.21      kristaps 1065:                mdoc->next = MDOC_NEXT_SIBLING;
1.13      kristaps 1066:        }
                   1067:
1.19      kristaps 1068:        if (MDOC_LINEARG_MAX == sz + argc)
1.28      kristaps 1069:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.13      kristaps 1070:
1.28      kristaps 1071:        return(rewind_elem(mdoc, tok));
1.13      kristaps 1072: }
1.15      kristaps 1073:
                   1074:
1.16      kristaps 1075: /* ARGSUSED */
1.15      kristaps 1076: int
                   1077: macro_obsolete(MACRO_PROT_ARGS)
                   1078: {
                   1079:
1.28      kristaps 1080:        return(mdoc_pwarn(mdoc, line, ppos, WARN_IGN_OBSOLETE));
1.15      kristaps 1081: }
1.25      kristaps 1082:
                   1083:
                   1084: int
                   1085: macro_end(struct mdoc *mdoc)
                   1086: {
                   1087:
                   1088:        assert(mdoc->first);
                   1089:        assert(mdoc->last);
1.28      kristaps 1090:        return(rewind_last(mdoc, mdoc->first));
1.25      kristaps 1091: }

CVSweb