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

Annotation of mandoc/macro.c, Revision 1.29

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

CVSweb