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

Annotation of mandoc/macro.c, Revision 1.37

1.37    ! kristaps    1: /* $Id: macro.c,v 1.36 2009/01/15 15:46:45 kristaps Exp $ */
1.1       kristaps    2: /*
                      3:  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the
                      7:  * above copyright notice and this permission notice appear in all
                      8:  * copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
                     11:  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
                     12:  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
                     13:  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     14:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     15:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
                     16:  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     17:  * PERFORMANCE OF THIS SOFTWARE.
                     18:  */
1.2       kristaps   19: #include <assert.h>
                     20: #include <ctype.h>
1.1       kristaps   21: #include <stdlib.h>
1.2       kristaps   22: #include <stdio.h>
1.5       kristaps   23: #include <string.h>
1.11      kristaps   24: #ifdef __linux__
                     25: #include <time.h>
                     26: #endif
1.2       kristaps   27:
                     28: #include "private.h"
                     29:
1.10      kristaps   30: /* FIXME: maxlineargs should be per LINE, no per TOKEN. */
                     31:
1.35      kristaps   32: static int       rewind_alt(int);
                     33: static int       rewind_dohalt(int, enum mdoc_type,
                     34:                        const struct mdoc_node *);
                     35: #define        REWIND_REWIND   (1 << 0)
                     36: #define        REWIND_NOHALT   (1 << 1)
                     37: #define        REWIND_HALT     (1 << 2)
                     38: static int       rewind_dobreak(int, enum mdoc_type,
                     39:                        const struct mdoc_node *);
                     40:
                     41:
1.28      kristaps   42: static int       rewind_elem(struct mdoc *, int);
                     43: static int       rewind_impblock(struct mdoc *, int);
                     44: static int       rewind_expblock(struct mdoc *, int);
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:
                     64:        if ( ! mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX_MACLIKE))
                     65:                return(-1);
                     66:        return(MDOC_MAX);
1.24      kristaps   67: }
1.19      kristaps   68:
                     69:
                     70: static int
1.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.28      kristaps  367: rewind_expblock(struct mdoc *mdoc, int tok)
1.6       kristaps  368: {
1.7       kristaps  369:        struct mdoc_node *n;
1.35      kristaps  370:        int               c;
1.6       kristaps  371:
1.36      kristaps  372:        c = rewind_dohalt(tok, MDOC_BLOCK, mdoc->last);
                    373:        if (REWIND_HALT == c)
                    374:                return(mdoc_err(mdoc, ERR_SCOPE_NOCTX));
                    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)
                    382:                        return(mdoc_err(mdoc, ERR_SCOPE_NOCTX));
                    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.37    ! kristaps  387:                return(mdoc_nerr(mdoc, n, "macro 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.28      kristaps  396: rewind_impblock(struct mdoc *mdoc, int tok)
1.21      kristaps  397: {
                    398:        struct mdoc_node *n;
1.35      kristaps  399:        int               c;
1.21      kristaps  400:
1.36      kristaps  401:        printf("1\n");
                    402:        c = rewind_dohalt(tok, MDOC_BLOCK, mdoc->last);
                    403:        if (REWIND_HALT == c)
                    404:                return(1);
                    405:        if (REWIND_REWIND == c)
                    406:                return(rewind_last(tok, MDOC_BLOCK, mdoc, mdoc->last));
                    407:
1.21      kristaps  408:        /* LINTED */
1.36      kristaps  409:        for (n = mdoc->last->parent; n; n = n->parent) {
1.35      kristaps  410:                c = rewind_dohalt(tok, MDOC_BLOCK, n);
                    411:                if (REWIND_HALT == c)
                    412:                        return(1);
                    413:                else if (REWIND_REWIND == c)
1.21      kristaps  414:                        break;
1.35      kristaps  415:                else if (rewind_dobreak(tok, MDOC_BLOCK, n))
1.21      kristaps  416:                        continue;
1.37    ! kristaps  417:                return(mdoc_nerr(mdoc, n, "macro scope broken"));
1.21      kristaps  418:        }
                    419:
1.35      kristaps  420:        assert(n);
1.36      kristaps  421:        return(rewind_last(tok, MDOC_BLOCK, mdoc, n));
1.16      kristaps  422: }
                    423:
                    424:
1.22      kristaps  425: static int
1.27      kristaps  426: append_delims(struct mdoc *mdoc, int tok,
                    427:                int line, int *pos, char *buf)
1.22      kristaps  428: {
                    429:        int              c, lastarg;
                    430:        char            *p;
                    431:
                    432:        if (0 == buf[*pos])
                    433:                return(1);
                    434:
                    435:        for (;;) {
                    436:                lastarg = *pos;
1.28      kristaps  437:                c = mdoc_args(mdoc, line, pos, buf, 0, &p);
1.22      kristaps  438:                if (ARGS_ERROR == c)
                    439:                        return(0);
                    440:                else if (ARGS_EOLN == c)
                    441:                        break;
                    442:                assert(mdoc_isdelim(p));
1.28      kristaps  443:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    444:                        return(0);
1.22      kristaps  445:                mdoc->next = MDOC_NEXT_SIBLING;
                    446:        }
                    447:
                    448:        return(1);
                    449: }
                    450:
                    451:
1.19      kristaps  452: /* ARGSUSED */
                    453: int
1.35      kristaps  454: macro_scoped_close(MACRO_PROT_ARGS)
1.19      kristaps  455: {
1.28      kristaps  456:        int              tt, j, c, lastarg, maxargs, flushed;
1.22      kristaps  457:        char            *p;
1.19      kristaps  458:
                    459:        switch (tok) {
1.22      kristaps  460:        case (MDOC_Ec):
                    461:                maxargs = 1;
                    462:                break;
                    463:        default:
                    464:                maxargs = 0;
                    465:                break;
                    466:        }
                    467:
1.35      kristaps  468:        tt = rewind_alt(tok);
                    469:
1.36      kristaps  470:        mdoc_msg(mdoc, "parse-quiet: %s closing %s",
                    471:                        mdoc_macronames[tok], mdoc_macronames[tt]);
                    472:
1.22      kristaps  473:        if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
1.35      kristaps  474:                if (0 == buf[*pos]) {
1.36      kristaps  475:                        if ( ! rewind_subblock(MDOC_BODY, mdoc, tok))
1.35      kristaps  476:                                return(0);
                    477:                        return(rewind_expblock(mdoc, tok));
                    478:                }
1.28      kristaps  479:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_EQ0));
1.22      kristaps  480:        }
1.19      kristaps  481:
1.36      kristaps  482:        if ( ! rewind_subblock(MDOC_BODY, mdoc, tok))
1.22      kristaps  483:                return(0);
1.19      kristaps  484:
1.22      kristaps  485:        lastarg = ppos;
                    486:        flushed = 0;
1.15      kristaps  487:
1.22      kristaps  488:        if (maxargs > 0) {
1.28      kristaps  489:                if ( ! mdoc_tail_alloc(mdoc, line, ppos, tt))
                    490:                        return(0);
1.22      kristaps  491:                mdoc->next = MDOC_NEXT_CHILD;
                    492:        }
1.15      kristaps  493:
1.22      kristaps  494:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
1.15      kristaps  495:                lastarg = *pos;
1.22      kristaps  496:
                    497:                if (j == maxargs && ! flushed) {
1.35      kristaps  498:                        if ( ! rewind_expblock(mdoc, tok))
1.22      kristaps  499:                                return(0);
                    500:                        flushed = 1;
                    501:                }
                    502:
1.28      kristaps  503:                c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.15      kristaps  504:                if (ARGS_ERROR == c)
                    505:                        return(0);
1.22      kristaps  506:                if (ARGS_PUNCT == c)
                    507:                        break;
                    508:                if (ARGS_EOLN == c)
                    509:                        break;
                    510:
1.30      kristaps  511:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    512:                        return(0);
                    513:                else if (MDOC_MAX != c) {
1.22      kristaps  514:                        if ( ! flushed) {
1.35      kristaps  515:                                if ( ! rewind_expblock(mdoc, tok))
1.22      kristaps  516:                                        return(0);
                    517:                                flushed = 1;
                    518:                        }
1.26      kristaps  519:                        if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22      kristaps  520:                                return(0);
1.15      kristaps  521:                        break;
1.30      kristaps  522:                }
1.22      kristaps  523:
1.28      kristaps  524:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    525:                        return(0);
1.16      kristaps  526:                mdoc->next = MDOC_NEXT_SIBLING;
1.15      kristaps  527:        }
1.2       kristaps  528:
1.22      kristaps  529:        if (MDOC_LINEARG_MAX == j)
1.28      kristaps  530:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.22      kristaps  531:
1.35      kristaps  532:        if ( ! flushed && ! rewind_expblock(mdoc, tok))
1.28      kristaps  533:                return(0);
1.22      kristaps  534:
                    535:        if (ppos > 1)
                    536:                return(1);
1.27      kristaps  537:        return(append_delims(mdoc, tok, line, pos, buf));
1.1       kristaps  538: }
                    539:
1.2       kristaps  540:
1.19      kristaps  541: /*
                    542:  * A general text domain macro.  When invoked, this opens a scope that
                    543:  * accepts words until either end-of-line, only-punctuation, or a
                    544:  * callable macro.  If the word is punctuation (not only-punctuation),
                    545:  * then the scope is closed out, the punctuation appended, then the
                    546:  * scope opened again.  If any terminating conditions are met, the scope
                    547:  * is closed out.  If this is the first macro in the line and
                    548:  * only-punctuation remains, this punctuation is flushed.
                    549:  */
                    550: int
                    551: macro_text(MACRO_PROT_ARGS)
1.13      kristaps  552: {
1.28      kristaps  553:        int               la, lastpunct, c, sz, fl, argc;
1.19      kristaps  554:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
                    555:        char             *p;
1.13      kristaps  556:
1.28      kristaps  557:        la = ppos;
1.19      kristaps  558:        lastpunct = 0;
1.17      kristaps  559:
1.19      kristaps  560:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
1.28      kristaps  561:                la = *pos;
1.17      kristaps  562:
1.28      kristaps  563:                c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.19      kristaps  564:                if (ARGV_EOLN == c || ARGV_WORD == c)
                    565:                        break;
                    566:                else if (ARGV_ARG == c)
                    567:                        continue;
                    568:                mdoc_argv_free(argc, argv);
1.14      kristaps  569:                return(0);
1.10      kristaps  570:        }
                    571:
1.28      kristaps  572:        if (MDOC_LINEARG_MAX == argc) {
                    573:                mdoc_argv_free(argc, argv);
                    574:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
                    575:        }
                    576:
                    577:        c = mdoc_elem_alloc(mdoc, line, la, tok, argc, argv);
                    578:
                    579:        if (0 == c) {
1.19      kristaps  580:                mdoc_argv_free(argc, argv);
                    581:                return(0);
1.7       kristaps  582:        }
                    583:
1.28      kristaps  584:        mdoc->next = MDOC_NEXT_CHILD;
                    585:
1.15      kristaps  586:        fl = ARGS_DELIM;
                    587:        if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
                    588:                fl |= ARGS_QUOTED;
1.7       kristaps  589:
1.19      kristaps  590:        for (lastpunct = sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
1.28      kristaps  591:                la = *pos;
1.7       kristaps  592:
1.28      kristaps  593:                c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.19      kristaps  594:                if (ARGS_ERROR == c) {
                    595:                        mdoc_argv_free(argc, argv);
1.7       kristaps  596:                        return(0);
1.19      kristaps  597:                }
                    598:
                    599:                if (ARGS_EOLN == c)
                    600:                        break;
                    601:                if (ARGS_PUNCT == c)
                    602:                        break;
1.2       kristaps  603:
1.30      kristaps  604:                if (-1 == (c = lookup(mdoc, line, la, tok, p)))
                    605:                        return(0);
                    606:                else if (MDOC_MAX != c) {
1.36      kristaps  607:                        if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19      kristaps  608:                                mdoc_argv_free(argc, argv);
                    609:                                return(0);
                    610:                        }
                    611:                        mdoc_argv_free(argc, argv);
1.28      kristaps  612:
                    613:                        c = mdoc_macro(mdoc, c, line, la, pos, buf);
                    614:                        if (0 == c)
1.19      kristaps  615:                                return(0);
                    616:                        if (ppos > 1)
                    617:                                return(1);
1.27      kristaps  618:                        return(append_delims(mdoc, tok, line, pos, buf));
1.19      kristaps  619:                }
1.2       kristaps  620:
1.19      kristaps  621:                if (mdoc_isdelim(p)) {
1.36      kristaps  622:                        if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
1.19      kristaps  623:                                mdoc_argv_free(argc, argv);
                    624:                                return(0);
                    625:                        }
                    626:                        lastpunct = 1;
1.36      kristaps  627:                } else if (lastpunct) {
                    628:                        c = mdoc_elem_alloc(mdoc, line,
                    629:                                        la, tok, argc, argv);
                    630:                        if (0 == c) {
                    631:                                mdoc_argv_free(argc, argv);
                    632:                                return(0);
                    633:                        }
                    634:                        mdoc->next = MDOC_NEXT_CHILD;
                    635:                        lastpunct = 0;
1.19      kristaps  636:                }
1.36      kristaps  637:
1.28      kristaps  638:                if ( ! mdoc_word_alloc(mdoc, line, la, p))
                    639:                        return(0);
1.19      kristaps  640:                mdoc->next = MDOC_NEXT_SIBLING;
1.2       kristaps  641:        }
                    642:
1.19      kristaps  643:        mdoc_argv_free(argc, argv);
1.2       kristaps  644:
1.19      kristaps  645:        if (sz == MDOC_LINEARG_MAX)
1.28      kristaps  646:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.2       kristaps  647:
1.36      kristaps  648:        if (0 == lastpunct && ! rewind_elem(mdoc, tok))
1.7       kristaps  649:                return(0);
1.19      kristaps  650:        if (ppos > 1)
                    651:                return(1);
1.27      kristaps  652:        return(append_delims(mdoc, tok, line, pos, buf));
1.5       kristaps  653: }
                    654:
                    655:
1.19      kristaps  656: /*
1.28      kristaps  657:  * Implicit- or explicit-end multi-line scoped macro.
1.19      kristaps  658:  */
1.5       kristaps  659: int
1.16      kristaps  660: macro_scoped(MACRO_PROT_ARGS)
1.6       kristaps  661: {
1.33      kristaps  662:        int               c, lastarg, argc, j, fl;
1.6       kristaps  663:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
1.24      kristaps  664:        char             *p;
1.6       kristaps  665:
1.16      kristaps  666:        assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1.6       kristaps  667:
1.35      kristaps  668:        if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
1.36      kristaps  669:                if ( ! rewind_subblock(MDOC_BODY, mdoc, tok))
1.35      kristaps  670:                        return(0);
1.28      kristaps  671:                if ( ! rewind_impblock(mdoc, tok))
1.16      kristaps  672:                        return(0);
1.35      kristaps  673:        }
1.2       kristaps  674:
1.16      kristaps  675:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
                    676:                lastarg = *pos;
1.28      kristaps  677:                c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.16      kristaps  678:                if (ARGV_EOLN == c || ARGV_WORD == c)
                    679:                        break;
                    680:                else if (ARGV_ARG == c)
                    681:                        continue;
                    682:                mdoc_argv_free(argc, argv);
1.8       kristaps  683:                return(0);
1.16      kristaps  684:        }
1.2       kristaps  685:
1.28      kristaps  686:        if (MDOC_LINEARG_MAX == argc) {
1.16      kristaps  687:                mdoc_argv_free(argc, argv);
1.28      kristaps  688:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
                    689:        }
                    690:
                    691:        c = mdoc_block_alloc(mdoc, line, ppos,
                    692:                        tok, (size_t)argc, argv);
                    693:        mdoc_argv_free(argc, argv);
                    694:
                    695:        if (0 == c)
1.16      kristaps  696:                return(0);
1.8       kristaps  697:
1.19      kristaps  698:        mdoc->next = MDOC_NEXT_CHILD;
                    699:
1.24      kristaps  700:        if (0 == buf[*pos]) {
1.28      kristaps  701:                if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    702:                        return(0);
1.36      kristaps  703:                if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.28      kristaps  704:                        return(0);
                    705:                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25      kristaps  706:                        return(0);
1.19      kristaps  707:                mdoc->next = MDOC_NEXT_CHILD;
1.24      kristaps  708:                return(1);
                    709:        }
1.19      kristaps  710:
1.28      kristaps  711:        if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    712:                return(0);
1.24      kristaps  713:        mdoc->next = MDOC_NEXT_CHILD;
1.7       kristaps  714:
1.33      kristaps  715:        fl = ARGS_DELIM;
                    716:        if (MDOC_TABSEP & mdoc_macros[tok].flags)
                    717:                fl |= ARGS_TABSEP;
                    718:
1.24      kristaps  719:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
                    720:                lastarg = *pos;
1.33      kristaps  721:                c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.24      kristaps  722:
                    723:                if (ARGS_ERROR == c)
1.19      kristaps  724:                        return(0);
1.24      kristaps  725:                if (ARGS_PUNCT == c)
                    726:                        break;
                    727:                if (ARGS_EOLN == c)
                    728:                        break;
                    729:
1.30      kristaps  730:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    731:                        return(0);
                    732:                else if (MDOC_MAX == c) {
1.28      kristaps  733:                        if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    734:                                return(0);
1.24      kristaps  735:                        mdoc->next = MDOC_NEXT_SIBLING;
                    736:                        continue;
1.30      kristaps  737:                }
1.2       kristaps  738:
1.26      kristaps  739:                if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.24      kristaps  740:                        return(0);
                    741:                break;
1.7       kristaps  742:        }
1.1       kristaps  743:
1.24      kristaps  744:        if (j == MDOC_LINEARG_MAX)
1.28      kristaps  745:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.24      kristaps  746:
1.36      kristaps  747:        if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.24      kristaps  748:                return(0);
1.27      kristaps  749:        if (1 == ppos && ! append_delims(mdoc, tok, line, pos, buf))
1.24      kristaps  750:                return(0);
                    751:
1.28      kristaps  752:        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                    753:                return(0);
1.16      kristaps  754:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  755:
1.16      kristaps  756:        return(1);
1.1       kristaps  757: }
1.5       kristaps  758:
1.7       kristaps  759:
1.19      kristaps  760: /*
                    761:  * When scoped to a line, a macro encompasses all of the contents.  This
                    762:  * differs from constants or text macros, where a new macro will
                    763:  * terminate the existing context.
                    764:  */
1.7       kristaps  765: int
1.16      kristaps  766: macro_scoped_line(MACRO_PROT_ARGS)
1.7       kristaps  767: {
1.8       kristaps  768:        int               lastarg, c, j;
                    769:        char              *p;
1.7       kristaps  770:
1.28      kristaps  771:        if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
                    772:                return(0);
1.16      kristaps  773:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  774:
1.28      kristaps  775:        if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    776:                return(0);
1.16      kristaps  777:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  778:
1.19      kristaps  779:        /* XXX - no known argument macros. */
                    780:
                    781:        for (lastarg = ppos, j = 0; j < MDOC_LINEARG_MAX; j++) {
                    782:                lastarg = *pos;
1.28      kristaps  783:                c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.8       kristaps  784:
1.19      kristaps  785:                if (ARGS_ERROR == c)
                    786:                        return(0);
                    787:                if (ARGS_PUNCT == c)
                    788:                        break;
                    789:                if (ARGS_EOLN == c)
                    790:                        break;
1.8       kristaps  791:
1.30      kristaps  792:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    793:                        return(0);
                    794:                else if (MDOC_MAX == c) {
1.28      kristaps  795:                        if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    796:                                return(0);
1.19      kristaps  797:                        mdoc->next = MDOC_NEXT_SIBLING;
                    798:                        continue;
1.30      kristaps  799:                }
1.8       kristaps  800:
1.26      kristaps  801:                if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19      kristaps  802:                        return(0);
1.8       kristaps  803:                break;
                    804:        }
                    805:
1.19      kristaps  806:        if (j == MDOC_LINEARG_MAX)
1.28      kristaps  807:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.19      kristaps  808:
                    809:        if (1 == ppos) {
1.36      kristaps  810:                if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.16      kristaps  811:                        return(0);
1.27      kristaps  812:                if ( ! append_delims(mdoc, tok, line, pos, buf))
1.8       kristaps  813:                        return(0);
1.36      kristaps  814:        } else if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.35      kristaps  815:                return(0);
1.28      kristaps  816:        return(rewind_impblock(mdoc, tok));
1.22      kristaps  817: }
                    818:
                    819:
1.28      kristaps  820: /*
                    821:  * Constant-scope macros accept a fixed number of arguments and behave
                    822:  * like constant macros except that they're scoped across lines.
                    823:  */
1.22      kristaps  824: int
                    825: macro_constant_scoped(MACRO_PROT_ARGS)
                    826: {
                    827:        int               lastarg, flushed, j, c, maxargs;
                    828:        char             *p;
                    829:
                    830:        lastarg = ppos;
                    831:        flushed = 0;
                    832:
                    833:        switch (tok) {
                    834:        case (MDOC_Eo):
                    835:                maxargs = 1;
                    836:                break;
                    837:        default:
                    838:                maxargs = 0;
                    839:                break;
                    840:        }
                    841:
1.28      kristaps  842:        if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
                    843:                return(0);
1.22      kristaps  844:        mdoc->next = MDOC_NEXT_CHILD;
                    845:
                    846:        if (0 == maxargs) {
1.28      kristaps  847:                if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    848:                        return(0);
1.36      kristaps  849:                if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.28      kristaps  850:                        return(0);
                    851:                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.25      kristaps  852:                        return(0);
1.22      kristaps  853:                flushed = 1;
1.28      kristaps  854:        } else if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
                    855:                return(0);
1.22      kristaps  856:
                    857:        mdoc->next = MDOC_NEXT_CHILD;
                    858:
                    859:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
                    860:                lastarg = *pos;
                    861:
                    862:                if (j == maxargs && ! flushed) {
1.36      kristaps  863:                        if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.22      kristaps  864:                                return(0);
                    865:                        flushed = 1;
1.28      kristaps  866:                        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                    867:                                return(0);
1.22      kristaps  868:                        mdoc->next = MDOC_NEXT_CHILD;
                    869:                }
                    870:
1.28      kristaps  871:                c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.22      kristaps  872:                if (ARGS_ERROR == c)
                    873:                        return(0);
                    874:                if (ARGS_PUNCT == c)
                    875:                        break;
                    876:                if (ARGS_EOLN == c)
                    877:                        break;
                    878:
1.30      kristaps  879:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    880:                        return(0);
                    881:                else if (MDOC_MAX != c) {
1.22      kristaps  882:                        if ( ! flushed) {
1.36      kristaps  883:                                if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.22      kristaps  884:                                        return(0);
                    885:                                flushed = 1;
1.28      kristaps  886:                                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                    887:                                        return(0);
1.22      kristaps  888:                                mdoc->next = MDOC_NEXT_CHILD;
                    889:                        }
1.26      kristaps  890:                        if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.22      kristaps  891:                                return(0);
                    892:                        break;
                    893:                }
                    894:
                    895:                if ( ! flushed && mdoc_isdelim(p)) {
1.36      kristaps  896:                        if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.22      kristaps  897:                                return(0);
                    898:                        flushed = 1;
1.28      kristaps  899:                        if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                    900:                                return(0);
1.22      kristaps  901:                        mdoc->next = MDOC_NEXT_CHILD;
                    902:                }
                    903:
1.28      kristaps  904:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                    905:                        return(0);
1.22      kristaps  906:                mdoc->next = MDOC_NEXT_SIBLING;
                    907:        }
                    908:
                    909:        if (MDOC_LINEARG_MAX == j)
1.28      kristaps  910:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.22      kristaps  911:
                    912:        if ( ! flushed) {
1.36      kristaps  913:                if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok))
1.28      kristaps  914:                        return(0);
                    915:                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
1.22      kristaps  916:                        return(0);
                    917:                mdoc->next = MDOC_NEXT_CHILD;
                    918:        }
                    919:
                    920:        if (ppos > 1)
                    921:                return(1);
1.27      kristaps  922:        return(append_delims(mdoc, tok, line, pos, buf));
1.7       kristaps  923: }
1.8       kristaps  924:
1.10      kristaps  925:
1.19      kristaps  926: /*
                    927:  * Delimited macros are like text macros except that, should punctuation
                    928:  * be encountered, the macro isn't re-started with remaining tokens
                    929:  * (it's only emitted once).  Delimited macros can have a maximum number
                    930:  * of arguments.
1.17      kristaps  931:  */
1.10      kristaps  932: int
                    933: macro_constant_delimited(MACRO_PROT_ARGS)
                    934: {
1.24      kristaps  935:        int               lastarg, flushed, j, c, maxargs, argc;
                    936:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
1.13      kristaps  937:        char             *p;
1.10      kristaps  938:
                    939:        lastarg = ppos;
                    940:        flushed = 0;
                    941:
                    942:        switch (tok) {
1.16      kristaps  943:        case (MDOC_No):
                    944:                /* FALLTHROUGH */
                    945:        case (MDOC_Ns):
                    946:                /* FALLTHROUGH */
1.10      kristaps  947:        case (MDOC_Ux):
1.24      kristaps  948:                /* FALLTHROUGH */
                    949:        case (MDOC_St):
1.10      kristaps  950:                maxargs = 0;
                    951:                break;
                    952:        default:
                    953:                maxargs = 1;
                    954:                break;
                    955:        }
                    956:
1.24      kristaps  957:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
                    958:                lastarg = *pos;
1.28      kristaps  959:                c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.24      kristaps  960:                if (ARGV_EOLN == c || ARGV_WORD == c)
                    961:                        break;
                    962:                else if (ARGV_ARG == c)
                    963:                        continue;
                    964:                mdoc_argv_free(argc, argv);
                    965:                return(0);
                    966:        }
                    967:
1.28      kristaps  968:        c = mdoc_elem_alloc(mdoc, line, lastarg, tok, argc, argv);
                    969:        mdoc_argv_free(argc, argv);
                    970:
                    971:        if (0 == c)
1.24      kristaps  972:                return(0);
                    973:
1.19      kristaps  974:        mdoc->next = MDOC_NEXT_CHILD;
1.10      kristaps  975:
1.19      kristaps  976:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
                    977:                lastarg = *pos;
1.10      kristaps  978:
1.19      kristaps  979:                if (j == maxargs && ! flushed) {
1.28      kristaps  980:                        if ( ! rewind_elem(mdoc, tok))
1.19      kristaps  981:                                return(0);
                    982:                        flushed = 1;
                    983:                }
1.11      kristaps  984:
1.28      kristaps  985:                c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
1.19      kristaps  986:                if (ARGS_ERROR == c)
1.10      kristaps  987:                        return(0);
1.19      kristaps  988:                if (ARGS_PUNCT == c)
                    989:                        break;
                    990:                if (ARGS_EOLN == c)
                    991:                        break;
                    992:
1.30      kristaps  993:                if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
                    994:                        return(0);
                    995:                else if (MDOC_MAX != c) {
1.28      kristaps  996:                        if ( ! flushed && ! rewind_elem(mdoc, tok))
1.19      kristaps  997:                                return(0);
                    998:                        flushed = 1;
1.26      kristaps  999:                        if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
1.19      kristaps 1000:                                return(0);
                   1001:                        break;
                   1002:                }
1.10      kristaps 1003:
1.22      kristaps 1004:                if ( ! flushed && mdoc_isdelim(p)) {
1.28      kristaps 1005:                        if ( ! rewind_elem(mdoc, tok))
1.19      kristaps 1006:                                return(0);
                   1007:                        flushed = 1;
                   1008:                }
                   1009:
1.28      kristaps 1010:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                   1011:                        return(0);
1.19      kristaps 1012:                mdoc->next = MDOC_NEXT_SIBLING;
1.10      kristaps 1013:        }
                   1014:
1.22      kristaps 1015:        if (MDOC_LINEARG_MAX == j)
1.28      kristaps 1016:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.22      kristaps 1017:
1.28      kristaps 1018:        if ( ! flushed && rewind_elem(mdoc, tok))
1.19      kristaps 1019:                return(0);
1.11      kristaps 1020:
1.19      kristaps 1021:        if (ppos > 1)
                   1022:                return(1);
1.27      kristaps 1023:        return(append_delims(mdoc, tok, line, pos, buf));
1.10      kristaps 1024: }
1.11      kristaps 1025:
                   1026:
1.19      kristaps 1027: /*
                   1028:  * Constant macros span an entire line:  they constitute a macro and all
                   1029:  * of its arguments and child data.
                   1030:  */
1.11      kristaps 1031: int
                   1032: macro_constant(MACRO_PROT_ARGS)
                   1033: {
1.19      kristaps 1034:        int              c, lastarg, argc, sz, fl;
                   1035:        struct mdoc_arg  argv[MDOC_LINEARG_MAX];
                   1036:        char            *p;
1.11      kristaps 1037:
1.28      kristaps 1038:        /* FIXME: parsing macros! */
1.24      kristaps 1039:
1.16      kristaps 1040:        fl = 0;
1.15      kristaps 1041:        if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
                   1042:                fl = ARGS_QUOTED;
1.11      kristaps 1043:
1.16      kristaps 1044:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
                   1045:                lastarg = *pos;
1.28      kristaps 1046:                c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
1.16      kristaps 1047:                if (ARGV_EOLN == c)
                   1048:                        break;
                   1049:                else if (ARGV_ARG == c)
                   1050:                        continue;
                   1051:                else if (ARGV_WORD == c)
                   1052:                        break;
1.11      kristaps 1053:
1.16      kristaps 1054:                mdoc_argv_free(argc, argv);
1.11      kristaps 1055:                return(0);
                   1056:        }
                   1057:
1.28      kristaps 1058:        c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
                   1059:        mdoc_argv_free(argc, argv);
                   1060:
                   1061:        if (0 == c)
                   1062:                return(0);
1.11      kristaps 1063:
1.19      kristaps 1064:        mdoc->next = MDOC_NEXT_CHILD;
                   1065:
1.28      kristaps 1066:        if (MDOC_LINEARG_MAX == argc)
                   1067:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.19      kristaps 1068:
1.16      kristaps 1069:        for (sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
1.13      kristaps 1070:                lastarg = *pos;
1.28      kristaps 1071:                c = mdoc_args(mdoc, line, pos, buf, fl, &p);
1.16      kristaps 1072:                if (ARGS_ERROR == c)
                   1073:                        return(0);
                   1074:                if (ARGS_EOLN == c)
1.13      kristaps 1075:                        break;
1.19      kristaps 1076:
1.28      kristaps 1077:                if ( ! mdoc_word_alloc(mdoc, line, lastarg, p))
                   1078:                        return(0);
1.21      kristaps 1079:                mdoc->next = MDOC_NEXT_SIBLING;
1.13      kristaps 1080:        }
                   1081:
1.19      kristaps 1082:        if (MDOC_LINEARG_MAX == sz + argc)
1.28      kristaps 1083:                return(mdoc_perr(mdoc, line, ppos, ERR_ARGS_MANY));
1.13      kristaps 1084:
1.28      kristaps 1085:        return(rewind_elem(mdoc, tok));
1.13      kristaps 1086: }
1.15      kristaps 1087:
                   1088:
1.16      kristaps 1089: /* ARGSUSED */
1.15      kristaps 1090: int
                   1091: macro_obsolete(MACRO_PROT_ARGS)
                   1092: {
                   1093:
1.28      kristaps 1094:        return(mdoc_pwarn(mdoc, line, ppos, WARN_IGN_OBSOLETE));
1.15      kristaps 1095: }
1.25      kristaps 1096:
                   1097:
                   1098: int
                   1099: macro_end(struct mdoc *mdoc)
                   1100: {
                   1101:
                   1102:        assert(mdoc->first);
                   1103:        assert(mdoc->last);
1.36      kristaps 1104:        return(rewind_last(mdoc->last->tok, mdoc->last->type,
                   1105:                                mdoc, mdoc->first));
1.25      kristaps 1106: }

CVSweb