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

Annotation of mandoc/macro.c, Revision 1.9

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

CVSweb