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

Annotation of mandoc/macro.c, Revision 1.13

1.13    ! kristaps    1: /* $Id: macro.c,v 1.12 2008/12/29 19:25:29 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. */
1.13    ! kristaps   31: /* FIXME: prologue check should be in macro_call. */
1.10      kristaps   32:
1.3       kristaps   33: #define        _CC(p)  ((const char **)p)
1.2       kristaps   34:
1.6       kristaps   35: static int       scope_rewind_exp(struct mdoc *, int, int, int);
1.7       kristaps   36: static int       scope_rewind_imp(struct mdoc *, int, int);
1.3       kristaps   37: static int       append_text(struct mdoc *, int,
                     38:                        int, int, char *[]);
1.10      kristaps   39: static int       append_const(struct mdoc *, int, int, int, char *[]);
1.13    ! kristaps   40: static int       append_constarg(struct mdoc *, int, int,
        !            41:                         int, const struct mdoc_arg *);
1.6       kristaps   42: static int       append_scoped(struct mdoc *, int, int, int,
                     43:                        const char *[], int, const struct mdoc_arg *);
1.7       kristaps   44: static int       append_delims(struct mdoc *, int, int *, char *);
1.6       kristaps   45:
                     46:
                     47: static int
1.7       kristaps   48: append_delims(struct mdoc *mdoc, int tok, int *pos, char *buf)
1.6       kristaps   49: {
1.7       kristaps   50:        int              c, lastarg;
                     51:        char            *p;
1.6       kristaps   52:
                     53:        if (0 == buf[*pos])
1.7       kristaps   54:                return(1);
1.6       kristaps   55:
1.8       kristaps   56:        mdoc_msg(mdoc, *pos, "`%s' flushing punctuation",
                     57:                        mdoc_macronames[tok]);
1.6       kristaps   58:
1.7       kristaps   59:        for (;;) {
                     60:                lastarg = *pos;
                     61:                c = mdoc_args(mdoc, tok, pos, buf, 0, &p);
                     62:                if (ARGS_ERROR == c)
                     63:                        return(0);
                     64:                else if (ARGS_EOLN == c)
                     65:                        break;
                     66:                assert(mdoc_isdelim(p));
                     67:                mdoc_word_alloc(mdoc, lastarg, p);
1.6       kristaps   68:        }
                     69:
                     70:        return(1);
                     71: }
                     72:
                     73:
                     74: static int
1.7       kristaps   75: scope_rewind_imp(struct mdoc *mdoc, int ppos, int tok)
1.6       kristaps   76: {
                     77:        struct mdoc_node *n;
1.7       kristaps   78:        int               t;
                     79:
                     80:        n = mdoc->last ? mdoc->last->parent : NULL;
1.6       kristaps   81:
                     82:        /* LINTED */
1.7       kristaps   83:        for ( ; n; n = n->parent) {
1.6       kristaps   84:                if (MDOC_BLOCK != n->type)
                     85:                        continue;
1.7       kristaps   86:                if (tok == (t = n->data.block.tok))
1.6       kristaps   87:                        break;
1.7       kristaps   88:                if ( ! (MDOC_EXPLICIT & mdoc_macros[t].flags))
                     89:                        continue;
1.6       kristaps   90:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
                     91:        }
                     92:
1.7       kristaps   93:        if (n) {
                     94:                mdoc->last = n;
                     95:                mdoc_msg(mdoc, ppos, "scope: rewound implicit `%s'",
                     96:                                mdoc_macronames[tok]);
                     97:                return(1);
                     98:        }
1.6       kristaps   99:
1.7       kristaps  100:        mdoc_msg(mdoc, ppos, "scope: new implicit `%s'",
                    101:                        mdoc_macronames[tok]);
1.6       kristaps  102:        return(1);
                    103: }
                    104:
                    105:
                    106: static int
1.7       kristaps  107: scope_rewind_exp(struct mdoc *mdoc, int ppos, int tok, int dst)
1.6       kristaps  108: {
1.7       kristaps  109:        struct mdoc_node *n;
1.6       kristaps  110:
1.7       kristaps  111:        assert(mdoc->last);
1.6       kristaps  112:
1.7       kristaps  113:        /* LINTED */
                    114:        for (n = mdoc->last->parent; n; n = n->parent) {
                    115:                if (MDOC_BLOCK != n->type)
                    116:                        continue;
                    117:                if (dst == n->data.block.tok)
                    118:                        break;
                    119:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_BREAK));
1.6       kristaps  120:        }
                    121:
1.7       kristaps  122:        if (NULL == (mdoc->last = n))
                    123:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_NOCTX));
1.6       kristaps  124:
1.7       kristaps  125:        mdoc_msg(mdoc, ppos, "scope: rewound explicit `%s' to `%s'",
                    126:                        mdoc_macronames[tok], mdoc_macronames[dst]);
1.2       kristaps  127:
1.1       kristaps  128:        return(1);
                    129: }
                    130:
1.2       kristaps  131:
                    132: static int
1.13    ! kristaps  133: append_constarg(struct mdoc *mdoc, int tok, int pos,
        !           134:                int argc, const struct mdoc_arg *argv)
        !           135: {
        !           136:
        !           137:        switch (tok) {
        !           138:        default:
        !           139:                break;
        !           140:        }
        !           141:
        !           142:        mdoc_elem_alloc(mdoc, pos, tok, argc, argv, 0, NULL);
        !           143:        return(1);
        !           144: }
        !           145:
        !           146:
        !           147: /*
        !           148:  * Append a node with implicit or explicit scoping ONLY.  ALL macros
        !           149:  * with the implicit- or explicit-scope callback must be included here.
        !           150:  */
        !           151: static int
1.6       kristaps  152: append_scoped(struct mdoc *mdoc, int tok, int pos,
                    153:                int sz, const char *args[],
                    154:                int argc, const struct mdoc_arg *argv)
1.2       kristaps  155: {
1.7       kristaps  156:        enum mdoc_sec     sec;
                    157:        struct mdoc_node *node;
1.5       kristaps  158:
1.4       kristaps  159:        switch (tok) {
                    160:         /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
1.13    ! kristaps  161:
1.4       kristaps  162:        case (MDOC_Sh):
1.13    ! kristaps  163:                /*
        !           164:                 * Check rules for section ordering.  We can have
        !           165:                 * "known" sections (like NAME and so on) and "custom"
        !           166:                 * sections, which are unknown.  If we have a known
        !           167:                 * section, we should fall within the conventional
        !           168:                 * section order.
        !           169:                 */
1.6       kristaps  170:                if (0 == sz)
                    171:                        return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
                    172:
1.5       kristaps  173:                sec = mdoc_atosec((size_t)sz, _CC(args));
                    174:                if (SEC_CUSTOM != sec && sec < mdoc->sec_lastn)
                    175:                        if ( ! mdoc_warn(mdoc, tok, pos, WARN_SEC_OO))
                    176:                                return(0);
                    177:
                    178:                if (SEC_BODY == mdoc->sec_last && SEC_NAME != sec)
                    179:                        return(mdoc_err(mdoc, tok, pos, ERR_SEC_NAME));
                    180:                if (SEC_CUSTOM != sec)
                    181:                        mdoc->sec_lastn = sec;
                    182:                mdoc->sec_last = sec;
1.4       kristaps  183:                break;
1.6       kristaps  184:
1.4       kristaps  185:        case (MDOC_Ss):
1.13    ! kristaps  186:                if (0 != sz)
        !           187:                        break;
        !           188:                return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
1.7       kristaps  189:
                    190:        case (MDOC_Bd):
1.13    ! kristaps  191:                /*
        !           192:                 * We can't be nested within any other block displays
        !           193:                 * (or really any other kind of display, although Bd is
        !           194:                 * the only multi-line one that will show up).
        !           195:                 */
1.7       kristaps  196:                assert(mdoc->last);
1.9       kristaps  197:                node = mdoc->last->parent;
                    198:                /* LINTED */
                    199:                for ( ; node; node = node->parent) {
1.7       kristaps  200:                        if (node->type != MDOC_BLOCK)
                    201:                                continue;
                    202:                        if (node->data.block.tok != MDOC_Bd)
                    203:                                continue;
1.13    ! kristaps  204:                        break;
1.7       kristaps  205:                }
1.13    ! kristaps  206:                if (NULL == node)
        !           207:                        break;
        !           208:                return(mdoc_err(mdoc, tok, pos, ERR_SCOPE_NONEST));
1.6       kristaps  209:
                    210:        case (MDOC_Bl):
1.4       kristaps  211:                break;
1.6       kristaps  212:
1.4       kristaps  213:         /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
                    214:        default:
                    215:                abort();
                    216:                /* NOTREACHED */
                    217:        }
                    218:
1.6       kristaps  219:        mdoc_block_alloc(mdoc, pos, tok, (size_t)argc, argv);
1.3       kristaps  220:        mdoc_head_alloc(mdoc, pos, tok, (size_t)sz, _CC(args));
1.2       kristaps  221:        mdoc_body_alloc(mdoc, pos, tok);
                    222:        return(1);
                    223: }
                    224:
                    225:
1.1       kristaps  226: static int
1.10      kristaps  227: append_const(struct mdoc *mdoc, int tok,
                    228:                int pos, int sz, char *args[])
                    229: {
                    230:
                    231:        switch (tok) {
                    232:         /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
1.13    ! kristaps  233:
        !           234:        /* FIXME: this is the ugliest part of this page. */
1.11      kristaps  235:        case (MDOC_At):
                    236:                /* This needs special handling. */
                    237:                if (0 == sz)
                    238:                        break;
                    239:                else if (sz > 2)
                    240:                        return(mdoc_err(mdoc, tok, pos, ERR_ARGS_LE2));
                    241:
                    242:                if (ATT_DEFAULT != mdoc_atoatt(args[0])) {
                    243:                        mdoc_elem_alloc(mdoc, pos, tok, 0,
                    244:                                        NULL, 1, _CC(&args[0]));
                    245:                } else {
                    246:                        mdoc_elem_alloc(mdoc, pos, tok,
                    247:                                        0, NULL, 0, NULL);
                    248:                        if (mdoc_isdelim(args[0]))
                    249:                                return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_NOPUNCT));
                    250:                        mdoc_word_alloc(mdoc, pos, args[0]);
                    251:                }
                    252:
                    253:                if (1 == sz)
                    254:                        return(1);
                    255:                if (mdoc_isdelim(args[1]))
                    256:                        return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_NOPUNCT));
                    257:                mdoc_word_alloc(mdoc, pos, args[1]);
                    258:                return(1);
                    259:
1.12      kristaps  260:        case (MDOC_Nd):
                    261:                if (sz > 0)
                    262:                        break;
                    263:                if ( ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_GE1))
                    264:                        return(0);
                    265:                break;
                    266:
                    267:        case (MDOC_Hf):
                    268:                if (1 == sz)
                    269:                        break;
                    270:                return(mdoc_err(mdoc, tok, pos, ERR_ARGS_EQ1));
                    271:
1.10      kristaps  272:        case (MDOC_Bx):
                    273:                /* FALLTHROUGH */
                    274:        case (MDOC_Bsx):
                    275:                /* FALLTHROUGH */
                    276:        case (MDOC_Os):
                    277:                /* FALLTHROUGH */
                    278:        case (MDOC_Fx):
                    279:                /* FALLTHROUGH */
                    280:        case (MDOC_Nx):
                    281:                assert(sz <= 1);
                    282:                break;
                    283:
                    284:        case (MDOC_Ux):
                    285:                assert(0 == sz);
                    286:                break;
                    287:
1.11      kristaps  288:        case (MDOC_Bt):
                    289:                /* FALLTHROUGH */
                    290:        case (MDOC_Ud):
                    291:                if (0 == sz)
                    292:                        break;
                    293:                return(mdoc_err(mdoc, tok, pos, ERR_ARGS_EQ0));
                    294:
1.10      kristaps  295:         /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
                    296:        default:
                    297:                abort();
                    298:                /* NOTREACHED */
                    299:        }
                    300:
                    301:        mdoc_elem_alloc(mdoc, pos, tok, 0, NULL, (size_t)sz, _CC(args));
                    302:        return(1);
                    303: }
                    304:
                    305:
                    306: static int
1.3       kristaps  307: append_text(struct mdoc *mdoc, int tok,
                    308:                int pos, int sz, char *args[])
1.1       kristaps  309: {
                    310:
1.2       kristaps  311:        switch (tok) {
1.4       kristaps  312:         /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
1.7       kristaps  313:        case (MDOC_Pp):
                    314:                if (0 == sz)
                    315:                        break;
                    316:                if ( ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_EQ0))
                    317:                        return(0);
                    318:                break;
                    319:
1.2       kristaps  320:        case (MDOC_Ft):
                    321:                /* FALLTHROUGH */
                    322:        case (MDOC_Li):
                    323:                /* FALLTHROUGH */
                    324:        case (MDOC_Ms):
                    325:                /* FALLTHROUGH */
                    326:        case (MDOC_Pa):
                    327:                /* FALLTHROUGH */
                    328:        case (MDOC_Tn):
1.4       kristaps  329:                if (0 < sz)
                    330:                        break;
                    331:                if ( ! mdoc_warn(mdoc, tok, pos, WARN_ARGS_GE1))
1.1       kristaps  332:                        return(0);
1.4       kristaps  333:                break;
1.7       kristaps  334:
1.2       kristaps  335:        case (MDOC_Ar):
                    336:                /* FALLTHROUGH */
                    337:        case (MDOC_Cm):
                    338:                /* FALLTHROUGH */
                    339:        case (MDOC_Fl):
1.7       kristaps  340:                /* These can have no arguments. */
1.4       kristaps  341:                break;
1.7       kristaps  342:
1.2       kristaps  343:        case (MDOC_Ad):
                    344:                /* FALLTHROUGH */
                    345:        case (MDOC_Em):
                    346:                /* FALLTHROUGH */
                    347:        case (MDOC_Er):
                    348:                /* FALLTHROUGH */
                    349:        case (MDOC_Ev):
                    350:                /* FALLTHROUGH */
                    351:        case (MDOC_Fa):
                    352:                /* FALLTHROUGH */
                    353:        case (MDOC_Dv):
                    354:                /* FALLTHROUGH */
                    355:        case (MDOC_Ic):
                    356:                /* FALLTHROUGH */
1.12      kristaps  357:        case (MDOC_Sy):
                    358:                /* FALLTHROUGH */
                    359:        case (MDOC_Sx):
                    360:                /* FALLTHROUGH */
1.2       kristaps  361:        case (MDOC_Va):
                    362:                /* FALLTHROUGH */
                    363:        case (MDOC_Vt):
1.4       kristaps  364:                if (0 < sz)
                    365:                        break;
                    366:                return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
                    367:         /* ======= ADD MORE MACRO CHECKS ABOVE. ======= */
1.2       kristaps  368:        default:
1.4       kristaps  369:                abort();
                    370:                /* NOTREACHED */
1.2       kristaps  371:        }
                    372:
1.7       kristaps  373:        mdoc_elem_alloc(mdoc, pos, tok, 0, NULL, (size_t)sz, _CC(args));
1.4       kristaps  374:        return(1);
1.2       kristaps  375: }
                    376:
1.1       kristaps  377:
1.2       kristaps  378: int
1.5       kristaps  379: macro_text(MACRO_PROT_ARGS)
1.2       kristaps  380: {
1.7       kristaps  381:        int               lastarg, lastpunct, c, j;
1.13    ! kristaps  382:        char             *args[MDOC_LINEARG_MAX];
1.1       kristaps  383:
1.5       kristaps  384:        if (SEC_PROLOGUE == mdoc->sec_lastn)
                    385:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
                    386:
1.7       kristaps  387:        /* Token pre-processing.  */
                    388:
                    389:        switch (tok) {
                    390:        case (MDOC_Pp):
                    391:                /* `.Pp' ignored when following `.Sh' or `.Ss'. */
                    392:                assert(mdoc->last);
                    393:                if (MDOC_BODY != mdoc->last->type)
                    394:                        break;
                    395:                switch (mdoc->last->data.body.tok) {
                    396:                case (MDOC_Ss):
                    397:                        /* FALLTHROUGH */
                    398:                case (MDOC_Sh):
                    399:                        if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_AFTER_BLK))
                    400:                                return(0);
                    401:                        return(1);
                    402:                default:
                    403:                        break;
                    404:                }
                    405:                break;
                    406:        default:
                    407:                break;
                    408:        }
                    409:
                    410:        /* Process line parameters. */
                    411:
                    412:        j = 0;
                    413:        lastarg = ppos;
                    414:        lastpunct = 0;
                    415:
1.2       kristaps  416: again:
1.7       kristaps  417:        if (j == MDOC_LINEARG_MAX)
                    418:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    419:
                    420:        /*
                    421:         * Parse out the next argument, unquoted and unescaped.   If
                    422:         * we're a word (which may be punctuation followed eventually by
                    423:         * a real word), then fall into checking for callables.  If
                    424:         * only punctuation remains and we're the first, then flush
                    425:         * arguments, punctuation and exit; else, return to the caller.
                    426:         */
                    427:
1.6       kristaps  428:        lastarg = *pos;
1.2       kristaps  429:
1.7       kristaps  430:        switch (mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &args[j])) {
                    431:        case (ARGS_ERROR):
1.2       kristaps  432:                return(0);
1.7       kristaps  433:        case (ARGS_WORD):
                    434:                break;
                    435:        case (ARGS_PUNCT):
                    436:                if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
                    437:                        return(0);
1.8       kristaps  438:                if (ppos > 1)
                    439:                        return(1);
1.7       kristaps  440:                return(append_delims(mdoc, tok, pos, buf));
                    441:        case (ARGS_EOLN):
1.8       kristaps  442:                if (lastpunct)
                    443:                        return(1);
1.7       kristaps  444:                return(append_text(mdoc, tok, ppos, j, args));
                    445:        default:
                    446:                abort();
                    447:                /* NOTREACHED */
                    448:        }
1.2       kristaps  449:
1.7       kristaps  450:        /*
                    451:         * Command found.  First flush out arguments, then call the
                    452:         * command.  If we're the line macro when it exits, flush
                    453:         * terminal punctuation.
                    454:         */
1.2       kristaps  455:
                    456:        if (MDOC_MAX != (c = mdoc_find(mdoc, args[j]))) {
1.7       kristaps  457:                if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
                    458:                        return(0);
                    459:                if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
                    460:                        return(0);
                    461:                if (ppos > 1)
                    462:                        return(1);
                    463:                return(append_delims(mdoc, tok, pos, buf));
1.2       kristaps  464:        }
                    465:
1.7       kristaps  466:        /* Word/non-term-punctuation found. */
1.2       kristaps  467:
1.4       kristaps  468:        if ( ! mdoc_isdelim(args[j])) {
1.7       kristaps  469:                /* Words are appended to the array of arguments. */
1.2       kristaps  470:                j++;
1.8       kristaps  471:                lastpunct = 0;
1.2       kristaps  472:                goto again;
                    473:        }
                    474:
1.7       kristaps  475:        /*
                    476:         * For punctuation, flush all collected words, then flush
                    477:         * punctuation, then start collecting again.   Of course, this
                    478:         * is non-terminal punctuation.
                    479:         */
1.2       kristaps  480:
1.7       kristaps  481:        if ( ! lastpunct && ! append_text(mdoc, tok, ppos, j, args))
                    482:                return(0);
1.2       kristaps  483:
1.13    ! kristaps  484:        mdoc_word_alloc(mdoc, lastarg, args[j]);
1.7       kristaps  485:        j = 0;
1.2       kristaps  486:        lastpunct = 1;
                    487:
                    488:        goto again;
                    489:        /* NOTREACHED */
                    490: }
1.1       kristaps  491:
                    492:
1.2       kristaps  493: int
1.5       kristaps  494: macro_prologue_dtitle(MACRO_PROT_ARGS)
                    495: {
1.7       kristaps  496:        int               lastarg, j;
1.5       kristaps  497:        char             *args[MDOC_LINEARG_MAX];
                    498:
                    499:        if (SEC_PROLOGUE != mdoc->sec_lastn)
                    500:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
                    501:        if (0 == mdoc->meta.date)
                    502:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
                    503:        if (mdoc->meta.title[0])
                    504:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
                    505:
                    506:        j = -1;
1.7       kristaps  507:        lastarg = ppos;
1.5       kristaps  508:
                    509: again:
1.6       kristaps  510:        if (j == MDOC_LINEARG_MAX)
                    511:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
1.5       kristaps  512:
1.7       kristaps  513:        lastarg = *pos;
                    514:
                    515:        switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[++j])) {
                    516:        case (ARGS_EOLN):
1.5       kristaps  517:                if (mdoc->meta.title)
                    518:                        return(1);
                    519:                if ( ! mdoc_warn(mdoc, tok, ppos, WARN_ARGS_GE1))
                    520:                        return(0);
                    521:                (void)xstrlcpy(mdoc->meta.title,
                    522:                                "UNTITLED", META_TITLE_SZ);
                    523:                return(1);
1.7       kristaps  524:        case (ARGS_ERROR):
1.5       kristaps  525:                return(0);
1.7       kristaps  526:        default:
                    527:                break;
                    528:        }
                    529:
1.5       kristaps  530:        if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
                    531:                        (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
                    532:                return(0);
                    533:
                    534:        if (0 == j) {
                    535:                if (xstrlcpy(mdoc->meta.title, args[0], META_TITLE_SZ))
                    536:                        goto again;
1.7       kristaps  537:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5       kristaps  538:
                    539:        } else if (1 == j) {
                    540:                mdoc->meta.msec = mdoc_atomsec(args[1]);
                    541:                if (MSEC_DEFAULT != mdoc->meta.msec)
                    542:                        goto again;
1.7       kristaps  543:                return(mdoc_err(mdoc, tok, -1, ERR_SYNTAX_ARGFORM));
1.5       kristaps  544:
                    545:        } else if (2 == j) {
                    546:                mdoc->meta.vol = mdoc_atovol(args[2]);
                    547:                if (VOL_DEFAULT != mdoc->meta.vol)
                    548:                        goto again;
                    549:                mdoc->meta.arch = mdoc_atoarch(args[2]);
                    550:                if (ARCH_DEFAULT != mdoc->meta.arch)
                    551:                        goto again;
1.7       kristaps  552:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5       kristaps  553:        }
                    554:
                    555:        return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    556: }
                    557:
                    558:
                    559: int
1.6       kristaps  560: macro_prologue_os(MACRO_PROT_ARGS)
                    561: {
1.7       kristaps  562:        int               lastarg, j;
1.6       kristaps  563:        char             *args[MDOC_LINEARG_MAX];
                    564:
                    565:        if (SEC_PROLOGUE != mdoc->sec_lastn)
                    566:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
                    567:        if (0 == mdoc->meta.title[0])
                    568:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
                    569:        if (mdoc->meta.os[0])
                    570:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
                    571:
                    572:        j = -1;
1.7       kristaps  573:        lastarg = ppos;
1.6       kristaps  574:
                    575: again:
                    576:        if (j == MDOC_LINEARG_MAX)
                    577:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    578:
1.7       kristaps  579:        lastarg = *pos;
                    580:
                    581:        switch (mdoc_args(mdoc, tok, pos, buf,
                    582:                                ARGS_QUOTED, &args[++j])) {
                    583:        case (ARGS_EOLN):
1.6       kristaps  584:                mdoc->sec_lastn = mdoc->sec_last = SEC_BODY;
                    585:                return(1);
1.7       kristaps  586:        case (ARGS_ERROR):
1.6       kristaps  587:                return(0);
1.7       kristaps  588:        default:
                    589:                break;
                    590:        }
1.6       kristaps  591:
                    592:        if ( ! xstrlcat(mdoc->meta.os, args[j], sizeof(mdoc->meta.os)))
1.7       kristaps  593:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.6       kristaps  594:        if ( ! xstrlcat(mdoc->meta.os, " ", sizeof(mdoc->meta.os)))
1.7       kristaps  595:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.6       kristaps  596:
                    597:        goto again;
                    598:        /* NOTREACHED */
                    599: }
                    600:
                    601:
                    602: int
1.5       kristaps  603: macro_prologue_ddate(MACRO_PROT_ARGS)
                    604: {
1.7       kristaps  605:        int               lastarg, j;
1.5       kristaps  606:        char             *args[MDOC_LINEARG_MAX], date[64];
                    607:
                    608:        if (SEC_PROLOGUE != mdoc->sec_lastn)
                    609:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
                    610:        if (mdoc->meta.title[0])
                    611:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
                    612:        if (mdoc->meta.date)
                    613:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
                    614:
                    615:        j = -1;
                    616:        date[0] = 0;
1.7       kristaps  617:        lastarg = ppos;
1.5       kristaps  618:
                    619: again:
1.6       kristaps  620:        if (j == MDOC_LINEARG_MAX)
                    621:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    622:
1.7       kristaps  623:        lastarg = *pos;
                    624:        switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[++j])) {
                    625:        case (ARGS_EOLN):
1.5       kristaps  626:                if (mdoc->meta.date)
                    627:                        return(1);
                    628:                mdoc->meta.date = mdoc_atotime(date);
                    629:                if (mdoc->meta.date)
                    630:                        return(1);
1.7       kristaps  631:                return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGFORM));
                    632:        case (ARGS_ERROR):
1.5       kristaps  633:                return(0);
1.7       kristaps  634:        default:
                    635:                break;
                    636:        }
1.5       kristaps  637:
                    638:        if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
                    639:                        (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
                    640:                return(0);
                    641:
                    642:        if (0 == j) {
                    643:                if (xstrcmp("$Mdocdate$", args[j])) {
                    644:                        mdoc->meta.date = time(NULL);
                    645:                        goto again;
                    646:                } else if (xstrcmp("$Mdocdate:", args[j]))
                    647:                        goto again;
                    648:        } else if (4 == j)
                    649:                if ( ! xstrcmp("$", args[j]))
                    650:                        goto again;
                    651:
                    652:        if ( ! xstrlcat(date, args[j], sizeof(date)))
1.7       kristaps  653:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5       kristaps  654:        if ( ! xstrlcat(date, " ", sizeof(date)))
1.7       kristaps  655:                return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGFORM));
1.5       kristaps  656:
                    657:        goto again;
                    658:        /* NOTREACHED */
                    659: }
                    660:
                    661:
                    662: int
1.6       kristaps  663: macro_scoped_explicit(MACRO_PROT_ARGS)
                    664: {
                    665:        int               c, lastarg, j;
                    666:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
1.7       kristaps  667:        struct mdoc_node *n;
1.6       kristaps  668:
                    669:        if (SEC_PROLOGUE == mdoc->sec_lastn)
                    670:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
                    671:
                    672:        /*
                    673:         * First close out the explicit scope.  The `end' tags (such as
                    674:         * `.El' to `.Bl' don't cause anything to happen: we merely
                    675:         * readjust our last parse point.
                    676:         */
                    677:
                    678:        switch (tok) {
                    679:        case (MDOC_El):
                    680:                return(scope_rewind_exp(mdoc, ppos, tok, MDOC_Bl));
1.7       kristaps  681:        case (MDOC_Ed):
                    682:                return(scope_rewind_exp(mdoc, ppos, tok, MDOC_Bd));
1.6       kristaps  683:        default:
                    684:                break;
                    685:        }
                    686:
                    687:        assert(MDOC_EXPLICIT & mdoc_macros[tok].flags);
                    688:
1.7       kristaps  689:        /* Token pre-processing. */
                    690:
                    691:        switch (tok) {
                    692:        case (MDOC_Bl):
                    693:                /* FALLTHROUGH */
                    694:        case (MDOC_Bd):
                    695:                /* `.Pp' ignored when preceding `.Bl' or `.Bd'. */
                    696:                assert(mdoc->last);
                    697:                if (MDOC_ELEM != mdoc->last->type)
                    698:                        break;
                    699:                if (MDOC_Pp != mdoc->last->data.elem.tok)
                    700:                        break;
                    701:                if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_BEFORE_BLK))
                    702:                        return(0);
                    703:                assert(mdoc->last->prev);
                    704:                n = mdoc->last;
                    705:                mdoc->last = mdoc->last->prev;
                    706:                mdoc->last->next = NULL;
                    707:                mdoc_node_free(n);
                    708:                break;
                    709:        default:
                    710:                break;
                    711:        }
                    712:
1.6       kristaps  713:        lastarg = *pos;
                    714:
                    715:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
                    716:                lastarg = *pos;
1.7       kristaps  717:                c = mdoc_argv(mdoc, tok, &argv[j], pos, buf);
1.6       kristaps  718:                if (0 == c)
                    719:                        break;
                    720:                else if (1 == c)
                    721:                        continue;
                    722:
                    723:                mdoc_argv_free(j, argv);
                    724:                return(0);
                    725:        }
                    726:
                    727:        if (MDOC_LINEARG_MAX == j) {
                    728:                mdoc_argv_free(j, argv);
                    729:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    730:        }
                    731:
                    732:        c = append_scoped(mdoc, tok, ppos, 0, NULL, j, argv);
                    733:        mdoc_argv_free(j, argv);
                    734:        return(c);
                    735: }
                    736:
                    737:
1.8       kristaps  738: /*
                    739:  * Implicity-scoped macros, like `.Ss', have a scope that terminates
                    740:  * with a subsequent call to the same macro.  Implicit macros cannot
                    741:  * break the scope of explicitly-scoped macros; however, they can break
                    742:  * the scope of other implicit macros (so `.Sh' can break `.Ss').  This
                    743:  * is ok with macros like `.It' because they exist only within an
                    744:  * explicit context.
                    745:  *
                    746:  * These macros put line arguments (which it's allowed to have) into the
                    747:  * HEAD section and open a BODY scope to be used until the macro scope
                    748:  * closes.
                    749:  */
1.6       kristaps  750: int
1.5       kristaps  751: macro_scoped_implicit(MACRO_PROT_ARGS)
1.2       kristaps  752: {
1.7       kristaps  753:        int               lastarg, j;
1.2       kristaps  754:        char             *args[MDOC_LINEARG_MAX];
                    755:        struct mdoc_node *n;
                    756:
1.5       kristaps  757:        assert( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
1.1       kristaps  758:
1.5       kristaps  759:        if (SEC_PROLOGUE == mdoc->sec_lastn)
                    760:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
1.1       kristaps  761:
1.7       kristaps  762:        /* Token pre-processing. */
1.6       kristaps  763:
1.7       kristaps  764:        switch (tok) {
                    765:        case (MDOC_Ss):
                    766:                /* FALLTHROUGH */
                    767:        case (MDOC_Sh):
                    768:                /* `.Pp' ignored when preceding `.Ss' or `.Sh'. */
                    769:                if (NULL == mdoc->last)
                    770:                        break;
                    771:                if (MDOC_ELEM != mdoc->last->type)
                    772:                        break;
                    773:                if (MDOC_Pp != mdoc->last->data.elem.tok)
1.1       kristaps  774:                        break;
1.7       kristaps  775:                if ( ! mdoc_warn(mdoc, tok, ppos, WARN_IGN_BEFORE_BLK))
                    776:                        return(0);
                    777:                assert(mdoc->last->prev);
                    778:                n = mdoc->last;
1.8       kristaps  779:                mdoc_msg(mdoc, ppos, "removing prior `Pp' macro");
1.7       kristaps  780:                mdoc->last = mdoc->last->prev;
                    781:                mdoc->last->next = NULL;
                    782:                mdoc_node_free(n);
                    783:                break;
                    784:        default:
                    785:                break;
1.2       kristaps  786:        }
                    787:
1.8       kristaps  788:        /* Rewind our scope. */
                    789:
                    790:        if ( ! scope_rewind_imp(mdoc, ppos, tok))
                    791:                return(0);
1.2       kristaps  792:
                    793:        j = 0;
1.7       kristaps  794:        lastarg = ppos;
1.2       kristaps  795:
1.8       kristaps  796:        /*
                    797:         * Process until we hit a line.  Note that current implicit
                    798:         * macros don't have any arguments, so we don't need to do any
                    799:         * argument processing.
                    800:         */
                    801:
1.2       kristaps  802: again:
1.7       kristaps  803:        if (j == MDOC_LINEARG_MAX)
                    804:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    805:
1.6       kristaps  806:        lastarg = *pos;
1.2       kristaps  807:
1.7       kristaps  808:        switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[j])) {
                    809:        case (ARGS_ERROR):
1.2       kristaps  810:                return(0);
1.7       kristaps  811:        case (ARGS_EOLN):
                    812:                return(append_scoped(mdoc, tok, ppos, j, _CC(args), 0, NULL));
                    813:        default:
                    814:                break;
                    815:        }
1.1       kristaps  816:
1.7       kristaps  817:        if (MDOC_MAX != mdoc_find(mdoc, args[j]))
1.3       kristaps  818:                if ( ! mdoc_warn(mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
1.1       kristaps  819:                        return(0);
                    820:
1.2       kristaps  821:        j++;
                    822:        goto again;
1.8       kristaps  823:        /* NOTREACHED */
                    824: }
                    825:
                    826:
                    827: /*
                    828:  * A line-scoped macro opens a scope for the contents of its line, which
                    829:  * are placed under the HEAD node.  Punctuation trailing the line is put
                    830:  * as a sibling to the HEAD node, under the BLOCK node.
                    831:  */
                    832: int
                    833: macro_scoped_line(MACRO_PROT_ARGS)
                    834: {
                    835:        int               lastarg, c, j;
                    836:        char              *p;
                    837:        struct mdoc_node  *n;
                    838:
                    839:        if (SEC_PROLOGUE == mdoc->sec_lastn)
                    840:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
                    841:
                    842:        assert(1 == ppos);
                    843:
                    844:        /* Token pre-processing.  */
                    845:
                    846:        switch (tok) {
                    847:        case (MDOC_D1):
                    848:                /* FALLTHROUGH */
                    849:        case (MDOC_Dl):
                    850:                /* These can't be nested in a display block. */
                    851:                assert(mdoc->last);
                    852:                for (n = mdoc->last->parent ; n; n = n->parent)
                    853:                        if (MDOC_BLOCK != n->type)
                    854:                                continue;
                    855:                        else if (MDOC_Bd == n->data.block.tok)
                    856:                                break;
                    857:                if (NULL == n)
                    858:                        break;
                    859:                return(mdoc_err(mdoc, tok, ppos, ERR_SCOPE_NONEST));
                    860:        default:
                    861:                break;
                    862:        }
                    863:
                    864:        /*
                    865:         * All line-scoped macros have a HEAD and optionally a BODY
                    866:         * section.  We open our scope here; when we exit this function,
                    867:         * we'll rewind our scope appropriately.
                    868:         */
                    869:
                    870:        mdoc_block_alloc(mdoc, ppos, tok, 0, NULL);
                    871:        mdoc_head_alloc(mdoc, ppos, tok, 0, NULL);
                    872:
                    873:        /* Process line parameters. */
                    874:
                    875:        j = 0;
                    876:        lastarg = ppos;
                    877:
                    878: again:
                    879:        if (j == MDOC_LINEARG_MAX)
                    880:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    881:
                    882:        lastarg = *pos;
                    883:        c = mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &p);
                    884:
                    885:        switch (c) {
                    886:        case (ARGS_ERROR):
                    887:                return(0);
                    888:        case (ARGS_WORD):
                    889:                break;
                    890:        case (ARGS_PUNCT):
                    891:                if ( ! append_delims(mdoc, tok, pos, buf))
                    892:                        return(0);
                    893:                return(scope_rewind_imp(mdoc, ppos, tok));
                    894:        case (ARGS_EOLN):
                    895:                return(scope_rewind_imp(mdoc, ppos, tok));
                    896:        default:
                    897:                abort();
                    898:                /* NOTREACHED */
                    899:        }
                    900:
                    901:        if (MDOC_MAX != (c = mdoc_find(mdoc, p))) {
                    902:                if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
                    903:                        return(0);
                    904:                if ( ! append_delims(mdoc, tok, pos, buf))
                    905:                        return(0);
                    906:                return(scope_rewind_imp(mdoc, ppos, tok));
                    907:        }
1.1       kristaps  908:
1.8       kristaps  909:        if (mdoc_isdelim(p))
                    910:                j = 0;
                    911:
                    912:        mdoc_word_alloc(mdoc, lastarg, p);
                    913:        goto again;
1.2       kristaps  914:        /* NOTREACHED */
1.1       kristaps  915: }
1.5       kristaps  916:
1.7       kristaps  917:
1.9       kristaps  918: /*
                    919:  * Partial-line scope is identical to line scope (macro_scoped_line())
                    920:  * except that trailing punctuation is appended to the BLOCK, instead of
                    921:  * contained within the HEAD.
                    922:  */
1.7       kristaps  923: int
1.8       kristaps  924: macro_scoped_pline(MACRO_PROT_ARGS)
1.7       kristaps  925: {
1.8       kristaps  926:        int               lastarg, c, j;
                    927:        char              *p;
1.7       kristaps  928:
1.8       kristaps  929:        if (SEC_PROLOGUE == mdoc->sec_lastn)
                    930:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
                    931:
                    932:        /* Token pre-processing.  */
                    933:
                    934:        switch (tok) {
1.9       kristaps  935:        case (MDOC_Ql):
                    936:                if ( ! mdoc_warn(mdoc, tok, ppos, WARN_COMPAT_TROFF))
                    937:                        return(0);
                    938:                break;
1.8       kristaps  939:        default:
                    940:                break;
                    941:        }
                    942:
                    943:        mdoc_block_alloc(mdoc, ppos, tok, 0, NULL);
                    944:        mdoc_head_alloc(mdoc, ppos, tok, 0, NULL);
                    945:
                    946:        /* Process line parameters. */
                    947:
                    948:        j = 0;
                    949:        lastarg = ppos;
                    950:
                    951: again:
                    952:        if (j == MDOC_LINEARG_MAX)
                    953:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                    954:
                    955:        lastarg = *pos;
                    956:        c = mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &p);
                    957:
                    958:        switch (c) {
                    959:        case (ARGS_ERROR):
                    960:                return(0);
                    961:        case (ARGS_WORD):
                    962:                break;
                    963:        case (ARGS_PUNCT):
                    964:                if ( ! scope_rewind_imp(mdoc, ppos, tok))
                    965:                        return(0);
                    966:                if (ppos > 1)
                    967:                        return(1);
                    968:                return(append_delims(mdoc, tok, pos, buf));
                    969:        case (ARGS_EOLN):
                    970:                return(scope_rewind_imp(mdoc, ppos, tok));
                    971:        default:
                    972:                abort();
                    973:                /* NOTREACHED */
                    974:        }
                    975:
                    976:        if (MDOC_MAX != (c = mdoc_find(mdoc, p))) {
                    977:                if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
                    978:                        return(0);
                    979:                if ( ! scope_rewind_imp(mdoc, ppos, tok))
                    980:                        return(0);
                    981:                if (ppos > 1)
                    982:                        return(1);
                    983:                return(append_delims(mdoc, tok, pos, buf));
                    984:        }
                    985:
                    986:        if (mdoc_isdelim(p))
                    987:                j = 0;
                    988:
                    989:        mdoc_word_alloc(mdoc, lastarg, p);
                    990:        goto again;
                    991:        /* NOTREACHED */
1.7       kristaps  992: }
1.8       kristaps  993:
1.10      kristaps  994:
                    995: /*
                    996:  * A delimited-constant macro is similar to a general text macro: the
                    997:  * macro is followed by a 0 or 1 arguments (possibly-unspecified) then
                    998:  * terminating punctuation, other words, or another callable macro.
                    999:  */
                   1000: int
                   1001: macro_constant_delimited(MACRO_PROT_ARGS)
                   1002: {
                   1003:        int               lastarg, flushed, c, maxargs;
1.13    ! kristaps 1004:        char             *p;
1.10      kristaps 1005:
                   1006:        if (SEC_PROLOGUE == mdoc->sec_lastn)
                   1007:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
                   1008:
                   1009:        /* Process line parameters. */
                   1010:
                   1011:        lastarg = ppos;
                   1012:        flushed = 0;
                   1013:
1.11      kristaps 1014:        /* Token pre-processing. */
                   1015:
1.10      kristaps 1016:        switch (tok) {
                   1017:        case (MDOC_Ux):
                   1018:                maxargs = 0;
                   1019:                break;
                   1020:        default:
                   1021:                maxargs = 1;
                   1022:                break;
                   1023:        }
                   1024:
                   1025: again:
                   1026:        lastarg = *pos;
                   1027:
                   1028:        switch (mdoc_args(mdoc, tok, pos, buf, ARGS_DELIM, &p)) {
                   1029:        case (ARGS_ERROR):
                   1030:                return(0);
                   1031:        case (ARGS_WORD):
                   1032:                break;
                   1033:        case (ARGS_PUNCT):
                   1034:                if ( ! flushed && ! append_const(mdoc, tok, ppos, 0, &p))
                   1035:                        return(0);
                   1036:                if (ppos > 1)
                   1037:                        return(1);
                   1038:                return(append_delims(mdoc, tok, pos, buf));
                   1039:        case (ARGS_EOLN):
                   1040:                if (flushed)
                   1041:                        return(1);
                   1042:                return(append_const(mdoc, tok, ppos, 0, &p));
                   1043:        default:
                   1044:                abort();
                   1045:                /* NOTREACHED */
                   1046:        }
                   1047:
1.11      kristaps 1048:        /* Accepts no arguments: flush out symbol and continue. */
                   1049:
1.10      kristaps 1050:        if (0 == maxargs) {
                   1051:                if ( ! append_const(mdoc, tok, ppos, 0, &p))
                   1052:                        return(0);
                   1053:                flushed = 1;
                   1054:        }
                   1055:
                   1056:        if (MDOC_MAX != (c = mdoc_find(mdoc, p))) {
                   1057:                if ( ! flushed && ! append_const(mdoc, tok, ppos, 0, &p))
                   1058:                        return(0);
                   1059:                if ( ! mdoc_macro(mdoc, c, lastarg, pos, buf))
                   1060:                        return(0);
                   1061:                if (ppos > 1)
                   1062:                        return(1);
                   1063:                return(append_delims(mdoc, tok, pos, buf));
                   1064:        }
                   1065:
1.11      kristaps 1066:        /*
                   1067:         * We only accept one argument; subsequent tokens are considered
                   1068:         * as literal words (until a macro).
                   1069:         */
                   1070:
1.10      kristaps 1071:        if ( ! flushed && ! mdoc_isdelim(p)) {
                   1072:               if ( ! append_const(mdoc, tok, ppos, 1, &p))
                   1073:                        return(0);
                   1074:                flushed = 1;
                   1075:                goto again;
                   1076:        } else if ( ! flushed) {
                   1077:                if ( ! append_const(mdoc, tok, ppos, 0, &p))
                   1078:                        return(0);
                   1079:                flushed = 1;
                   1080:        }
                   1081:
                   1082:        mdoc_word_alloc(mdoc, lastarg, p);
                   1083:        goto again;
                   1084:        /* NOTREACHED */
                   1085: }
1.11      kristaps 1086:
                   1087:
                   1088: int
                   1089: macro_constant(MACRO_PROT_ARGS)
                   1090: {
                   1091:        int               lastarg, j;
                   1092:        char             *args[MDOC_LINEARG_MAX];
                   1093:
                   1094:        if (SEC_PROLOGUE == mdoc->sec_lastn)
                   1095:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
                   1096:
                   1097:        j = 0;
1.13    ! kristaps 1098:        lastarg = ppos;
1.11      kristaps 1099:
                   1100: again:
                   1101:        if (j == MDOC_LINEARG_MAX)
                   1102:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
                   1103:
                   1104:        lastarg = *pos;
                   1105:
                   1106:        switch (mdoc_args(mdoc, tok, pos, buf, 0, &args[j])) {
                   1107:        case (ARGS_ERROR):
                   1108:                return(0);
                   1109:        case (ARGS_WORD):
                   1110:                break;
                   1111:        case (ARGS_EOLN):
                   1112:                return(append_const(mdoc, tok, ppos, j, args));
                   1113:        default:
                   1114:                abort();
                   1115:                /* NOTREACHED */
                   1116:        }
                   1117:
                   1118:        if (MDOC_MAX != mdoc_find(mdoc, args[j]))
                   1119:                if ( ! mdoc_warn(mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
                   1120:                        return(0);
                   1121:
                   1122:        j++;
                   1123:        goto again;
                   1124:        /* NOTREACHED */
                   1125: }
1.13    ! kristaps 1126:
        !          1127:
        !          1128: int
        !          1129: macro_constant_argv(MACRO_PROT_ARGS)
        !          1130: {
        !          1131:        int               c, lastarg, j;
        !          1132:        struct mdoc_arg   argv[MDOC_LINEARG_MAX];
        !          1133:
        !          1134:        if (SEC_PROLOGUE == mdoc->sec_lastn)
        !          1135:                return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
        !          1136:
        !          1137:        lastarg = *pos;
        !          1138:
        !          1139:        for (j = 0; j < MDOC_LINEARG_MAX; j++) {
        !          1140:                lastarg = *pos;
        !          1141:                c = mdoc_argv(mdoc, tok, &argv[j], pos, buf);
        !          1142:                if (0 == c)
        !          1143:                        break;
        !          1144:                else if (1 == c)
        !          1145:                        continue;
        !          1146:
        !          1147:                mdoc_argv_free(j, argv);
        !          1148:                return(0);
        !          1149:        }
        !          1150:
        !          1151:        if (MDOC_LINEARG_MAX == j) {
        !          1152:                mdoc_argv_free(j, argv);
        !          1153:                return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
        !          1154:        }
        !          1155:
        !          1156:        c = append_constarg(mdoc, tok, ppos, j, argv);
        !          1157:        mdoc_argv_free(j, argv);
        !          1158:        return(c);
        !          1159: }

CVSweb