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

Annotation of mandoc/macro.c, Revision 1.30

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

CVSweb