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

Annotation of mandoc/macro.c, Revision 1.41

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

CVSweb