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

Annotation of mandoc/macro.c, Revision 1.14

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

CVSweb