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

Annotation of mandoc/macro.c, Revision 1.16

1.16    ! kristaps    1: /* $Id: macro.c,v 1.15 2008/12/30 19:06:03 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.3       kristaps   32: #define        _CC(p)  ((const char **)p)
1.2       kristaps   33:
1.16    ! kristaps   34: static int       scope_rewind_imp(struct mdoc *, int, int);
1.6       kristaps   35: static int       scope_rewind_exp(struct mdoc *, int, int, int);
1.16    ! kristaps   36: static int       scope_rewind_line(struct mdoc *, int, int);
1.3       kristaps   37: static int       append_text(struct mdoc *, int,
                     38:                        int, int, char *[]);
1.16    ! kristaps   39: static int       append_text_argv(struct mdoc *, int, int,
        !            40:                        int, char *[], int, const struct mdoc_arg *);
1.7       kristaps   41: static int       append_delims(struct mdoc *, int, int *, char *);
1.6       kristaps   42:
                     43:
                     44: static int
1.16    ! kristaps   45: scope_rewind_line(struct mdoc *mdoc, int ppos, int tok)
1.6       kristaps   46: {
                     47:        struct mdoc_node *n;
1.7       kristaps   48:        int               t;
                     49:
1.6       kristaps   50:        /* LINTED */
1.16    ! kristaps   51:        for (n = mdoc->last; n; n = n->parent) {
        !            52:                if (MDOC_HEAD != n->type)
1.6       kristaps   53:                        continue;
1.16    ! kristaps   54:                if (tok == (t = n->data.head.tok))
1.6       kristaps   55:                        break;
1.7       kristaps   56:                if ( ! (MDOC_EXPLICIT & mdoc_macros[t].flags))
                     57:                        continue;
1.6       kristaps   58:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
                     59:        }
                     60:
1.16    ! kristaps   61:        mdoc->last = n ? n : mdoc->last;
        !            62:        mdoc->next = MDOC_NEXT_SIBLING;
1.6       kristaps   63:        return(1);
                     64: }
                     65:
                     66:
                     67: static int
1.16    ! kristaps   68: scope_rewind_exp(struct mdoc *mdoc, int ppos, int tok, int tt)
1.6       kristaps   69: {
1.7       kristaps   70:        struct mdoc_node *n;
1.6       kristaps   71:
1.7       kristaps   72:        assert(mdoc->last);
1.6       kristaps   73:
1.7       kristaps   74:        /* LINTED */
                     75:        for (n = mdoc->last->parent; n; n = n->parent) {
                     76:                if (MDOC_BLOCK != n->type)
                     77:                        continue;
1.16    ! kristaps   78:                if (tt == n->data.block.tok)
        !            79:                        break;
        !            80:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
        !            81:        }
        !            82:
        !            83:        if (NULL == (mdoc->last = n))
        !            84:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_NOCTX));
        !            85:
        !            86:        mdoc->next = MDOC_NEXT_SIBLING;
        !            87:        return(mdoc_valid_post(mdoc, tok, ppos));
        !            88: }
        !            89:
        !            90:
        !            91: static int
        !            92: scope_rewind_imp(struct mdoc *mdoc, int ppos, int tok)
        !            93: {
        !            94:        struct mdoc_node *n;
        !            95:        int               t;
        !            96:
        !            97:        n = mdoc->last ? mdoc->last->parent : NULL;
        !            98:
        !            99:        /* LINTED */
        !           100:        for ( ; n; n = n->parent) {
        !           101:                if (MDOC_BLOCK != n->type)
        !           102:                        continue;
        !           103:                if (tok == (t = n->data.block.tok))
1.7       kristaps  104:                        break;
1.16    ! kristaps  105:                if ( ! (MDOC_EXPLICIT & mdoc_macros[t].flags))
        !           106:                        continue;
1.7       kristaps  107:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
1.6       kristaps  108:        }
                    109:
1.16    ! kristaps  110:        mdoc->last = n ? n : mdoc->last;
        !           111:        mdoc->next = MDOC_NEXT_SIBLING;
        !           112:        return(mdoc_valid_post(mdoc, tok, ppos));
1.15      kristaps  113: }
1.6       kristaps  114:
1.15      kristaps  115:
                    116: static int
                    117: append_delims(struct mdoc *mdoc, int tok, int *pos, char *buf)
                    118: {
                    119:        int              c, lastarg;
                    120:        char            *p;
                    121:
                    122:        if (0 == buf[*pos])
                    123:                return(1);
                    124:
                    125:        for (;;) {
                    126:                lastarg = *pos;
                    127:                c = mdoc_args(mdoc, tok, pos, buf, 0, &p);
                    128:                if (ARGS_ERROR == c)
                    129:                        return(0);
                    130:                else if (ARGS_EOLN == c)
                    131:                        break;
                    132:                assert(mdoc_isdelim(p));
                    133:                mdoc_word_alloc(mdoc, lastarg, p);
1.16    ! kristaps  134:                mdoc->next = MDOC_NEXT_SIBLING;
1.15      kristaps  135:        }
1.2       kristaps  136:
1.1       kristaps  137:        return(1);
                    138: }
                    139:
1.2       kristaps  140:
                    141: static int
1.16    ! kristaps  142: append_text_argv(struct mdoc *mdoc, int tok, int pos,
        !           143:                int sz, char *args[],
1.13      kristaps  144:                int argc, const struct mdoc_arg *argv)
                    145: {
                    146:
1.16    ! kristaps  147:        if ( ! mdoc_valid_pre(mdoc, tok, pos, 0, NULL, argc, argv))
1.15      kristaps  148:                return(0);
1.16    ! kristaps  149:        mdoc_elem_alloc(mdoc, pos, tok, (size_t)argc,
        !           150:                        argv, (size_t)sz, _CC(args));
        !           151:        mdoc->next = MDOC_NEXT_SIBLING;
1.13      kristaps  152:        return(1);
                    153: }
                    154:
                    155:
                    156: static int
1.16    ! kristaps  157: append_text(struct mdoc *mdoc, int tok,
1.10      kristaps  158:                int pos, int sz, char *args[])
                    159: {
                    160:
1.16    ! kristaps  161:        if ( ! mdoc_valid_pre(mdoc, tok, pos, sz, _CC(args), 0, NULL))
1.14      kristaps  162:                return(0);
                    163:
1.10      kristaps  164:        switch (tok) {
1.11      kristaps  165:        case (MDOC_At):
                    166:                if (0 == sz)
                    167:                        break;
1.15      kristaps  168:                if (ATT_DEFAULT == mdoc_atoatt(args[0])) {
1.11      kristaps  169:                        mdoc_elem_alloc(mdoc, pos, tok,
                    170:                                        0, NULL, 0, NULL);
1.16    ! kristaps  171:                        mdoc->next = MDOC_NEXT_SIBLING;
1.11      kristaps  172:                        mdoc_word_alloc(mdoc, pos, args[0]);
1.16    ! kristaps  173:                        mdoc->next = MDOC_NEXT_SIBLING;
        !           174:                } else {
1.15      kristaps  175:                        mdoc_elem_alloc(mdoc, pos, tok, 0,
                    176:                                        NULL, 1, _CC(&args[0]));
1.16    ! kristaps  177:                        mdoc->next = MDOC_NEXT_SIBLING;
        !           178:                }
1.11      kristaps  179:
1.15      kristaps  180:                if (sz > 1)
                    181:                        mdoc_word_alloc(mdoc, pos, args[1]);
1.16    ! kristaps  182:                mdoc->next = MDOC_NEXT_SIBLING;
1.11      kristaps  183:                return(1);
1.16    ! kristaps  184:
1.14      kristaps  185:        default:
1.10      kristaps  186:                break;
                    187:        }
                    188:
                    189:        mdoc_elem_alloc(mdoc, pos, tok, 0, NULL, (size_t)sz, _CC(args));
1.16    ! kristaps  190:        mdoc->next = MDOC_NEXT_SIBLING;
1.4       kristaps  191:        return(1);
1.2       kristaps  192: }
                    193:
1.1       kristaps  194:
1.2       kristaps  195: int
1.5       kristaps  196: macro_text(MACRO_PROT_ARGS)
1.2       kristaps  197: {
1.15      kristaps  198:        int               lastarg, lastpunct, c, j, fl;
1.13      kristaps  199:        char             *args[MDOC_LINEARG_MAX];
1.1       kristaps  200:
1.7       kristaps  201:        /* Token pre-processing.  */
                    202:
                    203:        switch (tok) {
                    204:        case (MDOC_Pp):
                    205:                /* `.Pp' ignored when following `.Sh' or `.Ss'. */
                    206:                assert(mdoc->last);
                    207:                if (MDOC_BODY != mdoc->last->type)
                    208:                        break;
                    209:                switch (mdoc->last->data.body.tok) {
                    210:                case (MDOC_Ss):
                    211:                        /* FALLTHROUGH */
                    212:                case (MDOC_Sh):
                    213:                        if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_AFTER_BLK))
                    214:                                return(0);
                    215:                        return(1);
                    216:                default:
                    217:                        break;
                    218:                }
                    219:                break;
                    220:        default:
                    221:                break;
                    222:        }
                    223:
                    224:        /* Process line parameters. */
                    225:
                    226:        j = 0;
                    227:        lastarg = ppos;
                    228:        lastpunct = 0;
1.15      kristaps  229:        fl = ARGS_DELIM;
                    230:
                    231:        if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
                    232:                fl |= ARGS_QUOTED;
1.7       kristaps  233:
1.2       kristaps  234: again:
1.7       kristaps  235:        if (j == MDOC_LINEARG_MAX)
                    236:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    237:
                    238:        /*
                    239:         * Parse out the next argument, unquoted and unescaped.   If
                    240:         * we're a word (which may be punctuation followed eventually by
                    241:         * a real word), then fall into checking for callables.  If
                    242:         * only punctuation remains and we're the first, then flush
                    243:         * arguments, punctuation and exit; else, return to the caller.
                    244:         */
                    245:
1.6       kristaps  246:        lastarg = *pos;
1.2       kristaps  247:
1.15      kristaps  248:        switch (mdoc_args(mdoc, tok, pos, buf, fl, &args[j])) {
1.7       kristaps  249:        case (ARGS_ERROR):
1.2       kristaps  250:                return(0);
1.7       kristaps  251:        case (ARGS_WORD):
                    252:                break;
                    253:        case (ARGS_PUNCT):
                    254:                if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
                    255:                        return(0);
1.8       kristaps  256:                if (ppos > 1)
                    257:                        return(1);
1.7       kristaps  258:                return(append_delims(mdoc, tok, pos, buf));
                    259:        case (ARGS_EOLN):
1.8       kristaps  260:                if (lastpunct)
                    261:                        return(1);
1.7       kristaps  262:                return(append_text(mdoc, tok, ppos, j, args));
                    263:        default:
                    264:                abort();
                    265:                /* NOTREACHED */
                    266:        }
1.2       kristaps  267:
1.7       kristaps  268:        /*
                    269:         * Command found.  First flush out arguments, then call the
                    270:         * command.  If we're the line macro when it exits, flush
                    271:         * terminal punctuation.
                    272:         */
1.2       kristaps  273:
                    274:        if (MDOC_MAX != (c = mdoc_find(mdoc, args[j]))) {
1.7       kristaps  275:                if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
                    276:                        return(0);
                    277:                if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
                    278:                        return(0);
                    279:                if (ppos > 1)
                    280:                        return(1);
                    281:                return(append_delims(mdoc, tok, pos, buf));
1.2       kristaps  282:        }
                    283:
1.7       kristaps  284:        /* Word/non-term-punctuation found. */
1.2       kristaps  285:
1.4       kristaps  286:        if ( ! mdoc_isdelim(args[j])) {
1.7       kristaps  287:                /* Words are appended to the array of arguments. */
1.2       kristaps  288:                j++;
1.8       kristaps  289:                lastpunct = 0;
1.2       kristaps  290:                goto again;
                    291:        }
                    292:
1.7       kristaps  293:        /*
                    294:         * For punctuation, flush all collected words, then flush
                    295:         * punctuation, then start collecting again.   Of course, this
                    296:         * is non-terminal punctuation.
                    297:         */
1.2       kristaps  298:
1.7       kristaps  299:        if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
                    300:                return(0);
1.2       kristaps  301:
1.13      kristaps  302:        mdoc_word_alloc(mdoc, lastarg, args[j]);
1.16    ! kristaps  303:        mdoc->next = MDOC_NEXT_SIBLING;
1.7       kristaps  304:        j = 0;
1.2       kristaps  305:        lastpunct = 1;
                    306:
                    307:        goto again;
                    308:        /* NOTREACHED */
                    309: }
1.1       kristaps  310:
                    311:
1.16    ! kristaps  312:
        !           313: /* ARGSUSED */
1.2       kristaps  314: int
1.16    ! kristaps  315: macro_close_explicit(MACRO_PROT_ARGS)
1.5       kristaps  316: {
1.16    ! kristaps  317:        int              tt;
1.5       kristaps  318:
1.16    ! kristaps  319:        /*
        !           320:         * First close out the explicit scope.  The `end' tags (such as
        !           321:         * `.El' to `.Bl' don't cause anything to happen: we merely
        !           322:         * readjust our last parse point.
        !           323:         */
1.5       kristaps  324:
1.16    ! kristaps  325:        switch (tok) {
        !           326:        case (MDOC_El):
        !           327:                tt = MDOC_Bl;
        !           328:                break;
        !           329:        case (MDOC_Ed):
        !           330:                tt = MDOC_Bd;
1.7       kristaps  331:                break;
1.16    ! kristaps  332:        case (MDOC_Re):
        !           333:                tt = MDOC_Rs;
1.7       kristaps  334:                break;
                    335:        default:
1.16    ! kristaps  336:                abort();
        !           337:                /* NOTREACHED */
1.7       kristaps  338:        }
1.5       kristaps  339:
1.16    ! kristaps  340:        return(scope_rewind_exp(mdoc, ppos, tok, tt));
1.5       kristaps  341: }
                    342:
                    343:
                    344: int
1.16    ! kristaps  345: macro_scoped(MACRO_PROT_ARGS)
1.6       kristaps  346: {
1.16    ! kristaps  347:        int               i, c, lastarg, argc, sz;
        !           348:        char             *args[MDOC_LINEARG_MAX];
1.6       kristaps  349:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
1.16    ! kristaps  350:        enum mdoc_sec     sec;
1.7       kristaps  351:        struct mdoc_node *n;
1.6       kristaps  352:
1.16    ! kristaps  353:        assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
1.6       kristaps  354:
1.7       kristaps  355:        /* Token pre-processing. */
                    356:
                    357:        switch (tok) {
                    358:        case (MDOC_Bl):
                    359:                /* FALLTHROUGH */
                    360:        case (MDOC_Bd):
                    361:                /* `.Pp' ignored when preceding `.Bl' or `.Bd'. */
                    362:                assert(mdoc->last);
                    363:                if (MDOC_ELEM != mdoc->last->type)
                    364:                        break;
                    365:                if (MDOC_Pp != mdoc->last->data.elem.tok)
                    366:                        break;
                    367:                if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_BEFORE_BLK))
                    368:                        return(0);
                    369:                assert(mdoc->last->prev);
                    370:                n = mdoc->last;
                    371:                mdoc->last = mdoc->last->prev;
                    372:                mdoc->last->next = NULL;
                    373:                mdoc_node_free(n);
                    374:                break;
1.16    ! kristaps  375:        case (MDOC_Sh):
        !           376:                /* FALLTHROUGH */
1.7       kristaps  377:        case (MDOC_Ss):
1.16    ! kristaps  378:                if ( ! scope_rewind_imp(mdoc, ppos, tok))
        !           379:                        return(0);
1.7       kristaps  380:                /* `.Pp' ignored when preceding `.Ss' or `.Sh'. */
                    381:                if (NULL == mdoc->last)
                    382:                        break;
                    383:                if (MDOC_ELEM != mdoc->last->type)
                    384:                        break;
                    385:                if (MDOC_Pp != mdoc->last->data.elem.tok)
1.1       kristaps  386:                        break;
1.7       kristaps  387:                if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_BEFORE_BLK))
                    388:                        return(0);
                    389:                assert(mdoc->last->prev);
                    390:                n = mdoc->last;
1.8       kristaps  391:                mdoc_msg(mdoc, ppos, "removing prior `Pp' macro");
1.7       kristaps  392:                mdoc->last = mdoc->last->prev;
                    393:                mdoc->last->next = NULL;
                    394:                mdoc_node_free(n);
                    395:                break;
                    396:        default:
                    397:                break;
1.2       kristaps  398:        }
                    399:
1.16    ! kristaps  400:        /* Argument processing. */
        !           401:
        !           402:        lastarg = *pos;
1.8       kristaps  403:
1.16    ! kristaps  404:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
        !           405:                lastarg = *pos;
        !           406:                c = mdoc_argv(mdoc, tok, &argv[argc], pos, buf);
        !           407:                if (ARGV_EOLN == c || ARGV_WORD == c)
        !           408:                        break;
        !           409:                else if (ARGV_ARG == c)
        !           410:                        continue;
        !           411:                mdoc_argv_free(argc, argv);
1.8       kristaps  412:                return(0);
1.16    ! kristaps  413:        }
1.2       kristaps  414:
1.16    ! kristaps  415:        /* Parameter processing. */
1.2       kristaps  416:
1.16    ! kristaps  417:        for (sz = 0; argc + sz < MDOC_LINEARG_MAX; sz++) {
        !           418:                lastarg = *pos;
        !           419:                c = mdoc_args(mdoc, tok, pos, buf, 0, &args[sz]);
        !           420:                if (ARGS_EOLN == c)
        !           421:                        break;
        !           422:                if (ARGS_WORD == c)
        !           423:                        continue;
        !           424:                mdoc_argv_free(argc, argv);
        !           425:                return(0);
        !           426:        }
1.8       kristaps  427:
1.16    ! kristaps  428:        if (MDOC_LINEARG_MAX == (argc + sz)) {
        !           429:                mdoc_argv_free(argc, argv);
1.7       kristaps  430:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
1.16    ! kristaps  431:        }
1.7       kristaps  432:
1.16    ! kristaps  433:        /* Post-processing. */
1.2       kristaps  434:
1.16    ! kristaps  435:        if ( ! mdoc_valid_pre(mdoc, tok, ppos, sz, _CC(args), argc, argv)) {
        !           436:                mdoc_argv_free(argc, argv);
1.2       kristaps  437:                return(0);
1.7       kristaps  438:        }
1.1       kristaps  439:
1.8       kristaps  440:        switch (tok) {
1.16    ! kristaps  441:        case (MDOC_Sh):
        !           442:                sec = mdoc_atosec((size_t)sz, _CC(args));
        !           443:                if (SEC_CUSTOM != sec)
        !           444:                        mdoc->sec_lastn = sec;
        !           445:                mdoc->sec_last = sec;
        !           446:                break;
1.8       kristaps  447:        default:
                    448:                break;
                    449:        }
                    450:
1.16    ! kristaps  451:        mdoc_block_alloc(mdoc, ppos, tok, (size_t)argc, argv);
        !           452:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  453:
1.16    ! kristaps  454:        mdoc_argv_free(argc, argv);
1.8       kristaps  455:
1.16    ! kristaps  456:        mdoc_head_alloc(mdoc, ppos, tok);
        !           457:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  458:
1.16    ! kristaps  459:        for (i = 0; i < sz; i++) {
        !           460:                mdoc_word_alloc(mdoc, ppos, args[i]);
        !           461:                mdoc->next = MDOC_NEXT_SIBLING;
        !           462:        }
1.8       kristaps  463:
1.16    ! kristaps  464:        if ( ! scope_rewind_line(mdoc, ppos, tok))
1.8       kristaps  465:                return(0);
1.1       kristaps  466:
1.16    ! kristaps  467:        mdoc_body_alloc(mdoc, ppos, tok);
        !           468:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  469:
1.16    ! kristaps  470:        return(1);
1.1       kristaps  471: }
1.5       kristaps  472:
1.7       kristaps  473:
                    474: int
1.16    ! kristaps  475: macro_scoped_line(MACRO_PROT_ARGS)
1.7       kristaps  476: {
1.8       kristaps  477:        int               lastarg, c, j;
                    478:        char              *p;
1.7       kristaps  479:
1.16    ! kristaps  480:        assert(1 == ppos);
        !           481:
        !           482:        mdoc_block_alloc(mdoc, ppos, tok, 0, NULL);
        !           483:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  484:
1.16    ! kristaps  485:        mdoc_head_alloc(mdoc, ppos, tok);
        !           486:        mdoc->next = MDOC_NEXT_CHILD;
1.8       kristaps  487:
1.16    ! kristaps  488:        if ( ! mdoc_valid_pre(mdoc, tok, ppos, 0, NULL, 0, NULL))
        !           489:                return(0);
1.8       kristaps  490:
                    491:        /* Process line parameters. */
                    492:
                    493:        j = 0;
                    494:        lastarg = ppos;
                    495:
                    496: again:
                    497:        if (j == MDOC_LINEARG_MAX)
                    498:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    499:
                    500:        lastarg = *pos;
                    501:        c = mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &p);
                    502:
                    503:        switch (c) {
                    504:        case (ARGS_ERROR):
                    505:                return(0);
                    506:        case (ARGS_WORD):
                    507:                break;
                    508:        case (ARGS_PUNCT):
1.16    ! kristaps  509:                if (ppos > 1)
        !           510:                        return(scope_rewind_imp(mdoc, ppos, tok));
        !           511:                if ( ! scope_rewind_line(mdoc, ppos, tok))
        !           512:                        return(0);
        !           513:                if ( ! append_delims(mdoc, tok, pos, buf))
1.8       kristaps  514:                        return(0);
1.16    ! kristaps  515:                return(scope_rewind_imp(mdoc, ppos, tok));
1.8       kristaps  516:        case (ARGS_EOLN):
                    517:                return(scope_rewind_imp(mdoc, ppos, tok));
                    518:        default:
                    519:                abort();
                    520:                /* NOTREACHED */
                    521:        }
                    522:
                    523:        if (MDOC_MAX != (c = mdoc_find(mdoc, p))) {
                    524:                if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
                    525:                        return(0);
1.16    ! kristaps  526:                if (ppos > 1)
        !           527:                        return(scope_rewind_imp(mdoc, ppos, tok));
        !           528:                if ( ! scope_rewind_line(mdoc, ppos, tok))
        !           529:                        return(0);
        !           530:                if ( ! append_delims(mdoc, tok, pos, buf))
1.8       kristaps  531:                        return(0);
1.16    ! kristaps  532:                return(scope_rewind_imp(mdoc, ppos, tok));
1.8       kristaps  533:        }
                    534:
                    535:        if (mdoc_isdelim(p))
                    536:                j = 0;
                    537:
                    538:        mdoc_word_alloc(mdoc, lastarg, p);
1.16    ! kristaps  539:        mdoc->next = MDOC_NEXT_SIBLING;
1.8       kristaps  540:        goto again;
                    541:        /* NOTREACHED */
1.7       kristaps  542: }
1.8       kristaps  543:
1.10      kristaps  544:
                    545: int
                    546: macro_constant_delimited(MACRO_PROT_ARGS)
                    547: {
                    548:        int               lastarg, flushed, c, maxargs;
1.13      kristaps  549:        char             *p;
1.10      kristaps  550:
                    551:        /* Process line parameters. */
                    552:
                    553:        lastarg = ppos;
                    554:        flushed = 0;
                    555:
1.11      kristaps  556:        /* Token pre-processing. */
                    557:
1.10      kristaps  558:        switch (tok) {
1.16    ! kristaps  559:        case (MDOC_No):
        !           560:                /* FALLTHROUGH */
        !           561:        case (MDOC_Ns):
        !           562:                /* FALLTHROUGH */
1.10      kristaps  563:        case (MDOC_Ux):
                    564:                maxargs = 0;
                    565:                break;
                    566:        default:
                    567:                maxargs = 1;
                    568:                break;
                    569:        }
                    570:
                    571: again:
                    572:        lastarg = *pos;
                    573:
                    574:        switch (mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &p)) {
                    575:        case (ARGS_ERROR):
                    576:                return(0);
                    577:        case (ARGS_WORD):
                    578:                break;
                    579:        case (ARGS_PUNCT):
1.16    ! kristaps  580:                if ( ! flushed && ! append_text(mdoc, tok, ppos, 0, &p))
1.10      kristaps  581:                        return(0);
                    582:                if (ppos > 1)
                    583:                        return(1);
                    584:                return(append_delims(mdoc, tok, pos, buf));
                    585:        case (ARGS_EOLN):
                    586:                if (flushed)
                    587:                        return(1);
1.16    ! kristaps  588:                return(append_text(mdoc, tok, ppos, 0, &p));
1.10      kristaps  589:        default:
                    590:                abort();
                    591:                /* NOTREACHED */
                    592:        }
                    593:
1.11      kristaps  594:        /* Accepts no arguments: flush out symbol and continue. */
                    595:
1.16    ! kristaps  596:        if ( ! flushed && 0 == maxargs) {
        !           597:                if ( ! append_text(mdoc, tok, ppos, 0, &p))
1.10      kristaps  598:                        return(0);
                    599:                flushed = 1;
                    600:        }
                    601:
                    602:        if (MDOC_MAX != (c = mdoc_find(mdoc, p))) {
1.16    ! kristaps  603:                if ( ! flushed && ! append_text(mdoc, tok, ppos, 0, &p))
1.10      kristaps  604:                        return(0);
                    605:                if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
                    606:                        return(0);
                    607:                if (ppos > 1)
                    608:                        return(1);
                    609:                return(append_delims(mdoc, tok, pos, buf));
                    610:        }
                    611:
1.11      kristaps  612:        /*
                    613:         * We only accept one argument; subsequent tokens are considered
                    614:         * as literal words (until a macro).
                    615:         */
                    616:
1.10      kristaps  617:        if ( ! flushed && ! mdoc_isdelim(p)) {
1.16    ! kristaps  618:               if ( ! append_text(mdoc, tok, ppos, 1, &p))
1.10      kristaps  619:                        return(0);
                    620:                flushed = 1;
                    621:                goto again;
                    622:        } else if ( ! flushed) {
1.16    ! kristaps  623:                if ( ! append_text(mdoc, tok, ppos, 0, &p))
1.10      kristaps  624:                        return(0);
                    625:                flushed = 1;
                    626:        }
                    627:
                    628:        mdoc_word_alloc(mdoc, lastarg, p);
1.16    ! kristaps  629:        mdoc->next = MDOC_NEXT_SIBLING;
1.10      kristaps  630:        goto again;
                    631:        /* NOTREACHED */
                    632: }
1.11      kristaps  633:
                    634:
                    635: int
                    636: macro_constant(MACRO_PROT_ARGS)
                    637: {
1.16    ! kristaps  638:        int               c, lastarg, argc, sz, fl;
1.11      kristaps  639:        char             *args[MDOC_LINEARG_MAX];
1.16    ! kristaps  640:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
1.11      kristaps  641:
1.16    ! kristaps  642:        fl = 0;
1.15      kristaps  643:        if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
                    644:                fl = ARGS_QUOTED;
1.11      kristaps  645:
1.16    ! kristaps  646:        for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
        !           647:                lastarg = *pos;
        !           648:                c = mdoc_argv(mdoc, tok, &argv[argc], pos, buf);
        !           649:                if (ARGV_EOLN == c)
        !           650:                        break;
        !           651:                else if (ARGV_ARG == c)
        !           652:                        continue;
        !           653:                else if (ARGV_WORD == c)
        !           654:                        break;
1.11      kristaps  655:
1.16    ! kristaps  656:                mdoc_argv_free(argc, argv);
1.11      kristaps  657:                return(0);
                    658:        }
                    659:
1.16    ! kristaps  660:        if (MDOC_LINEARG_MAX == argc) {
        !           661:                mdoc_argv_free(argc, argv);
        !           662:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
        !           663:        }
1.11      kristaps  664:
1.16    ! kristaps  665:        for (sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
1.13      kristaps  666:                lastarg = *pos;
1.16    ! kristaps  667:                c = mdoc_args(mdoc, tok, pos, buf, fl, &args[sz]);
        !           668:                if (ARGS_ERROR == c)
        !           669:                        return(0);
        !           670:                if (ARGS_EOLN == c)
1.13      kristaps  671:                        break;
                    672:        }
                    673:
1.16    ! kristaps  674:        if (MDOC_LINEARG_MAX == sz + argc) {
        !           675:                mdoc_argv_free(argc, argv);
1.13      kristaps  676:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    677:        }
                    678:
1.16    ! kristaps  679:        c = append_text_argv(mdoc, tok, ppos, sz, args, argc, argv);
        !           680:        mdoc_argv_free(argc, argv);
1.13      kristaps  681:        return(c);
                    682: }
1.15      kristaps  683:
                    684:
1.16    ! kristaps  685: /* ARGSUSED */
1.15      kristaps  686: int
                    687: macro_obsolete(MACRO_PROT_ARGS)
                    688: {
                    689:
                    690:        return(mdoc_warn(mdoc, tok, ppos, WARN_IGN_OBSOLETE));
                    691: }

CVSweb