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

Annotation of mandoc/macro.c, Revision 1.40

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

CVSweb