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

Annotation of mandoc/macro.c, Revision 1.23

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

CVSweb