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

Annotation of mandoc/macro.c, Revision 1.15

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

CVSweb