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

Annotation of mandoc/macro.c, Revision 1.12

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

CVSweb