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

Annotation of mandoc/macro.c, Revision 1.24

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

CVSweb