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

Annotation of mandoc/macro.c, Revision 1.18

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

CVSweb