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

Annotation of mandoc/macro.c, Revision 1.28

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

CVSweb