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

Annotation of mandoc/macro.c, Revision 1.22

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

CVSweb