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

Annotation of mandoc/macro.c, Revision 1.26

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

CVSweb