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

Annotation of mandoc/macro.c, Revision 1.27

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

CVSweb