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

Annotation of mandoc/html4_strict.c, Revision 1.5

1.5     ! kristaps    1: /* $Id: html4_strict.c,v 1.4 2008/11/23 23:12:47 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:  */
                     19: #include <assert.h>
                     20: #include <ctype.h>
                     21: #include <err.h>
                     22: #include <stdlib.h>
                     23: #include <stdio.h>
                     24: #include <string.h>
                     25: #include <time.h>
                     26:
                     27: #include "libmdocml.h"
                     28: #include "private.h"
                     29:
1.3       kristaps   30: enum   roffd {
                     31:        ROFF_ENTER = 0,
                     32:        ROFF_EXIT
1.1       kristaps   33: };
                     34:
1.3       kristaps   35: enum   rofftype {
                     36:        ROFF_TITLE,
                     37:        ROFF_COMMENT,
                     38:        ROFF_TEXT,
                     39:        ROFF_LAYOUT
1.1       kristaps   40: };
                     41:
1.4       kristaps   42: #define        ROFFCALL_ARGS                                           \
                     43:        const struct md_args *arg, struct md_mbuf *out,         \
                     44:        const struct md_rbuf *in, const char *buf, size_t sz,   \
                     45:        size_t pos, enum roffd type, struct rofftree *tree
1.1       kristaps   46:
1.3       kristaps   47: struct rofftree;
1.1       kristaps   48:
                     49: struct rofftok {
1.3       kristaps   50:        int               id;
1.1       kristaps   51:        char              name[2];
1.3       kristaps   52:        int             (*cb)(ROFFCALL_ARGS);
1.1       kristaps   53:        enum rofftype     type;
                     54:        int               flags;
1.4       kristaps   55: #define        ROFF_NESTED      (1 << 0)
                     56: #define        ROFF_PARSED      (1 << 1)
                     57: #define        ROFF_CALLABLE    (1 << 2)
1.1       kristaps   58: };
                     59:
                     60: struct roffnode {
                     61:        int               tok;
                     62:        struct roffnode  *parent;
1.3       kristaps   63:        size_t            line;
1.1       kristaps   64: };
                     65:
1.3       kristaps   66: struct rofftree {
1.1       kristaps   67:        struct roffnode  *last;
                     68:        time_t            date;
                     69:        char              title[256];
                     70:        char              section[256];
                     71:        char              volume[256];
                     72:        int               state;
1.3       kristaps   73: #define        ROFF_PRELUDE     (1 << 1)
                     74: #define        ROFF_PRELUDE_Os  (1 << 2)
                     75: #define        ROFF_PRELUDE_Dt  (1 << 3)
                     76: #define        ROFF_PRELUDE_Dd  (1 << 4)
                     77: #define        ROFF_BODY        (1 << 5)
1.1       kristaps   78: };
                     79:
1.3       kristaps   80: #define        ROFF___           0
                     81: #define        ROFF_Dd           1
                     82: #define        ROFF_Dt           2
                     83: #define        ROFF_Os           3
                     84: #define        ROFF_Sh           4
                     85: #define        ROFF_An           5
                     86: #define        ROFF_Li           6
                     87: #define        ROFF_Max          7
                     88:
                     89: static int               roff_Dd(ROFFCALL_ARGS);
                     90: static int               roff_Dt(ROFFCALL_ARGS);
                     91: static int               roff_Os(ROFFCALL_ARGS);
                     92: static int               roff_Sh(ROFFCALL_ARGS);
                     93: static int               roff_An(ROFFCALL_ARGS);
                     94: static int               roff_Li(ROFFCALL_ARGS);
                     95:
                     96: static struct roffnode  *roffnode_new(int, size_t,
                     97:                                struct rofftree *);
                     98: static void              roffnode_free(int, struct rofftree *);
                     99:
1.2       kristaps  100: static int               rofffind(const char *);
                    101: static int               roffparse(const struct md_args *,
1.1       kristaps  102:                                struct md_mbuf *,
                    103:                                const struct md_rbuf *,
                    104:                                const char *, size_t,
                    105:                                struct rofftree *);
1.2       kristaps  106: static int               textparse(struct md_mbuf *,
1.1       kristaps  107:                                const struct md_rbuf *,
                    108:                                const char *, size_t,
                    109:                                const struct rofftree *);
                    110:
1.2       kristaps  111: static void              dbg_enter(const struct md_args *, int);
                    112: static void              dbg_leave(const struct md_args *, int);
                    113:
1.1       kristaps  114:
1.3       kristaps  115: static const struct rofftok tokens[ROFF_Max] =
                    116: {
                    117: { ROFF___, "\\\"",     NULL, ROFF_COMMENT,                       0 },
                    118: { ROFF_Dd,   "Dd",  roff_Dd, ROFF_TITLE,                         0 },
                    119: { ROFF_Dt,   "Dt",  roff_Dt, ROFF_TITLE,                         0 },
                    120: { ROFF_Os,   "Os",  roff_Os, ROFF_TITLE,                         0 },
                    121: { ROFF_Sh,   "Sh",  roff_Sh, ROFF_LAYOUT,                        0 },
                    122: { ROFF_An,   "An",  roff_An, ROFF_TEXT,        ROFF_PARSED                 },
                    123: { ROFF_Li,   "Li",  roff_Li, ROFF_TEXT,        ROFF_PARSED | ROFF_CALLABLE },
                    124: };
                    125:
                    126:
1.1       kristaps  127: int
                    128: md_exit_html4_strict(const struct md_args *args, struct md_mbuf *out,
1.3       kristaps  129:                const struct md_rbuf *in, int error, void *data)
1.1       kristaps  130: {
                    131:        struct rofftree *tree;
                    132:
                    133:        assert(args);
                    134:        assert(data);
                    135:        tree = (struct rofftree *)data;
                    136:
1.3       kristaps  137:        if (-1 == error)
                    138:                out = NULL;
                    139:
                    140:        /* LINTED */
1.1       kristaps  141:        while (tree->last)
1.3       kristaps  142:                if ( ! (*tokens[tree->last->tok].cb)(args, out, in,
                    143:                                        NULL, 0, 0, ROFF_EXIT, tree))
                    144:                        out = NULL;
                    145:
                    146:        if (out && (ROFF_PRELUDE & tree->state)) {
                    147:                warnx("%s: prelude never finished", in->name);
                    148:                error = 1;
                    149:        }
1.1       kristaps  150:
                    151:        free(tree);
1.3       kristaps  152:
1.1       kristaps  153:        return(error ? 0 : 1);
                    154: }
                    155:
                    156:
                    157: int
                    158: md_init_html4_strict(const struct md_args *args, struct md_mbuf *out,
                    159:                const struct md_rbuf *in, void **data)
                    160: {
                    161:        struct rofftree *tree;
                    162:
                    163:        assert(args);
                    164:        assert(in);
                    165:        assert(out);
                    166:        assert(data);
                    167:
                    168:        /* TODO: write HTML-DTD header. */
                    169:
                    170:        if (NULL == (tree = calloc(1, sizeof(struct rofftree)))) {
                    171:                warn("malloc");
                    172:                return(0);
                    173:        }
                    174:
1.3       kristaps  175:        tree->state = ROFF_PRELUDE;
                    176:
1.1       kristaps  177:        *data = tree;
                    178:        return(1);
                    179: }
                    180:
                    181:
                    182: int
                    183: md_line_html4_strict(const struct md_args *args, struct md_mbuf *out,
                    184:                const struct md_rbuf *in, const char *buf,
                    185:                size_t sz, void *data)
                    186: {
                    187:        struct rofftree *tree;
                    188:
                    189:        assert(args);
                    190:        assert(in);
                    191:        assert(data);
                    192:
                    193:        tree = (struct rofftree *)data;
                    194:
                    195:        if (0 == sz) {
                    196:                warnx("%s: blank line (line %zu)", in->name, in->line);
                    197:                return(0);
                    198:        } else if ('.' != *buf)
                    199:                return(textparse(out, in, buf, sz, tree));
                    200:
                    201:        return(roffparse(args, out, in, buf, sz, tree));
                    202: }
                    203:
                    204:
                    205: static int
                    206: textparse(struct md_mbuf *out, const struct md_rbuf *in,
                    207:                const char *buf, size_t sz,
                    208:                const struct rofftree *tree)
                    209: {
                    210:
                    211:        assert(tree);
                    212:        assert(out);
                    213:        assert(in);
                    214:        assert(buf);
                    215:        assert(sz > 0);
                    216:
                    217:        if (NULL == tree->last) {
                    218:                warnx("%s: unexpected text (line %zu)",
                    219:                                in->name, in->line);
                    220:                return(0);
                    221:        } else if (NULL == tree->last->parent) {
                    222:                warnx("%s: disallowed text (line %zu)",
                    223:                                in->name, in->line);
                    224:                return(0);
                    225:        }
                    226:
                    227:        if ( ! md_buf_puts(out, buf, sz))
                    228:                return(0);
                    229:        return(md_buf_putstring(out, " "));
                    230: }
                    231:
                    232:
                    233: static int
                    234: roffparse(const struct md_args *args, struct md_mbuf *out,
                    235:                const struct md_rbuf *in, const char *buf,
                    236:                size_t sz, struct rofftree *tree)
                    237: {
                    238:        int              tokid, t;
                    239:        size_t           pos;
                    240:        struct roffnode *node;
                    241:
                    242:        assert(args);
                    243:        assert(out);
                    244:        assert(in);
                    245:        assert(buf);
                    246:        assert(sz > 0);
                    247:        assert(tree);
                    248:
                    249:        /*
                    250:         * Extract the token identifier from the buffer.  If there's no
                    251:         * callback for the token (comment, etc.) then exit immediately.
                    252:         * We don't do any error handling (yet), so if the token doesn't
                    253:         * exist, die.
                    254:         */
                    255:
                    256:        if (3 > sz) {
1.3       kristaps  257:                warnx("%s: malformed line (line %zu)",
1.1       kristaps  258:                                in->name, in->line);
                    259:                return(0);
                    260:        } else if (ROFF_Max == (tokid = rofffind(buf + 1))) {
1.3       kristaps  261:                warnx("%s: unknown line token `%c%c' (line %zu)",
1.1       kristaps  262:                                in->name, *(buf + 1),
                    263:                                *(buf + 2), in->line);
                    264:                return(0);
1.3       kristaps  265:        }
                    266:
                    267:        /* Domain cross-contamination (and sanity) checks. */
                    268:
                    269:        switch (tokens[tokid].type) {
                    270:        case (ROFF_TITLE):
                    271:                if (ROFF_PRELUDE & tree->state) {
                    272:                        assert( ! (ROFF_BODY & tree->state));
                    273:                        break;
                    274:                }
                    275:                assert(ROFF_BODY & tree->state);
                    276:                warnx("%s: prelude token `%s' in body (line %zu)",
                    277:                                in->name, tokens[tokid].name, in->line);
                    278:                return(0);
                    279:        case (ROFF_LAYOUT):
                    280:                /* FALLTHROUGH */
                    281:        case (ROFF_TEXT):
                    282:                if (ROFF_BODY & tree->state) {
                    283:                        assert( ! (ROFF_PRELUDE & tree->state));
                    284:                        break;
                    285:                }
                    286:                assert(ROFF_PRELUDE & tree->state);
1.4       kristaps  287:                warnx("%s: body token `%s' in prelude (line %zu)",
1.3       kristaps  288:                                in->name, tokens[tokid].name, in->line);
                    289:                return(0);
1.4       kristaps  290:        case (ROFF_COMMENT):
                    291:                return(1);
1.3       kristaps  292:        default:
1.4       kristaps  293:                abort();
1.3       kristaps  294:        }
                    295:
                    296:        /*
                    297:         * Text-domain checks.
                    298:         */
1.1       kristaps  299:
1.3       kristaps  300:        if (ROFF_TEXT == tokens[tokid].type &&
                    301:                        ! (ROFF_PARSED & tokens[tokid].flags)) {
                    302:                warnx("%s: text token `%s' not callable (line %zu)",
                    303:                                in->name, tokens[tokid].name, in->line);
                    304:                return(0);
                    305:        }
1.1       kristaps  306:
                    307:        /*
                    308:         * If this is a non-nestable layout token and we're below a
                    309:         * token of the same type, then recurse upward to the token,
                    310:         * closing out the interim scopes.
                    311:         *
                    312:         * If there's a nested token on the chain, then raise an error
                    313:         * as nested tokens have corresponding "ending" tokens and we're
                    314:         * breaking their scope.
                    315:         */
                    316:
                    317:        node = NULL;
1.3       kristaps  318:        pos = 3;
1.1       kristaps  319:
                    320:        if (ROFF_LAYOUT == tokens[tokid].type &&
                    321:                        ! (ROFF_NESTED & tokens[tokid].flags)) {
                    322:                for (node = tree->last; node; node = node->parent) {
                    323:                        if (node->tok == tokid)
                    324:                                break;
                    325:
                    326:                        /* Don't break nested scope. */
                    327:
                    328:                        if ( ! (ROFF_NESTED & tokens[node->tok].flags))
                    329:                                continue;
1.3       kristaps  330:                        warnx("%s: scope of %s (line %zu) broken by "
                    331:                                        "%s (line %zu)", in->name,
                    332:                                        tokens[tokid].name,
                    333:                                        node->line,
1.1       kristaps  334:                                        tokens[node->tok].name,
1.3       kristaps  335:                                        in->line);
1.1       kristaps  336:                        return(0);
                    337:                }
                    338:        }
1.3       kristaps  339:
1.1       kristaps  340:        if (node) {
                    341:                assert(ROFF_LAYOUT == tokens[tokid].type);
                    342:                assert( ! (ROFF_NESTED & tokens[tokid].flags));
                    343:                assert(node->tok == tokid);
                    344:
                    345:                /* Clear up to last scoped token. */
                    346:
1.3       kristaps  347:                /* LINTED */
1.1       kristaps  348:                do {
                    349:                        t = tree->last->tok;
                    350:                        if ( ! (*tokens[tree->last->tok].cb)
                    351:                                        (args, out, in, NULL,
                    352:                                         0, 0, ROFF_EXIT, tree))
                    353:                                return(0);
                    354:                } while (t != tokid);
                    355:        }
                    356:
                    357:        /* Proceed with actual token processing. */
                    358:
                    359:        return((*tokens[tokid].cb)(args, out, in, buf, sz,
                    360:                                pos, ROFF_ENTER, tree));
                    361: }
                    362:
                    363:
                    364: static int
                    365: rofffind(const char *name)
                    366: {
                    367:        size_t           i;
                    368:
                    369:        assert(name);
                    370:        /* FIXME: use a table, this is slow but ok for now. */
1.3       kristaps  371:
                    372:        /* LINTED */
1.1       kristaps  373:        for (i = 0; i < ROFF_Max; i++)
1.3       kristaps  374:                /* LINTED */
1.1       kristaps  375:                if (0 == strncmp(name, tokens[i].name, 2))
1.3       kristaps  376:                        return((int)i);
1.1       kristaps  377:
                    378:        return(ROFF_Max);
                    379: }
                    380:
                    381:
1.3       kristaps  382: static struct roffnode *
                    383: roffnode_new(int tokid, size_t line, struct rofftree *tree)
                    384: {
                    385:        struct roffnode *p;
                    386:
                    387:        if (NULL == (p = malloc(sizeof(struct roffnode)))) {
                    388:                warn("malloc");
                    389:                return(NULL);
                    390:        }
                    391:
                    392:        p->line = line;
                    393:        p->tok = tokid;
                    394:        p->parent = tree->last;
                    395:        tree->last = p;
                    396:        return(p);
                    397: }
                    398:
                    399:
                    400: static void
                    401: roffnode_free(int tokid, struct rofftree *tree)
                    402: {
                    403:        struct roffnode *p;
                    404:
                    405:        assert(tree->last);
                    406:        assert(tree->last->tok == tokid);
                    407:
                    408:        p = tree->last;
                    409:        tree->last = tree->last->parent;
                    410:        free(p);
                    411: }
                    412:
                    413:
1.4       kristaps  414: static int dbg_lvl = 0;
1.3       kristaps  415:
                    416:
                    417: static void
                    418: dbg_enter(const struct md_args *args, int tokid)
                    419: {
                    420:        int              i;
1.4       kristaps  421:        static char      buf[72];
1.3       kristaps  422:
                    423:        assert(args);
                    424:        if ( ! (args->dbg & MD_DBG_TREE))
                    425:                return;
1.4       kristaps  426:        assert(tokid >= 0 && tokid <= ROFF_Max);
1.3       kristaps  427:
1.4       kristaps  428:        buf[0] = 0;
                    429:
                    430:        switch (tokens[tokid].type) {
                    431:        case (ROFF_LAYOUT):
                    432:                /* FALLTHROUGH */
                    433:        case (ROFF_TEXT):
                    434:                (void)strlcat(buf, "body: ", sizeof(buf));
                    435:                break;
                    436:        case (ROFF_TITLE):
                    437:                (void)strlcat(buf, "prelude: ", sizeof(buf));
                    438:                break;
                    439:        default:
                    440:                abort();
                    441:        }
1.3       kristaps  442:
                    443:        /* LINTED */
                    444:        for (i = 0; i < dbg_lvl; i++)
1.4       kristaps  445:                (void)strlcat(buf, "  ", sizeof(buf));
                    446:
                    447:        (void)strlcat(buf, tokens[tokid].name, sizeof(buf));
1.3       kristaps  448:
1.4       kristaps  449:        (void)printf("%s\n", buf);
1.3       kristaps  450:
                    451:        if (ROFF_LAYOUT == tokens[tokid].type)
                    452:                dbg_lvl++;
                    453: }
                    454:
                    455:
                    456: static void
                    457: dbg_leave(const struct md_args *args, int tokid)
                    458: {
                    459:        assert(args);
                    460:        if ( ! (args->dbg & MD_DBG_TREE))
                    461:                return;
                    462:        if (ROFF_LAYOUT != tokens[tokid].type)
                    463:                return;
                    464:
                    465:        assert(tokid >= 0 && tokid <= ROFF_Max);
                    466:        assert(dbg_lvl > 0);
                    467:        dbg_lvl--;
                    468: }
                    469:
                    470:
1.1       kristaps  471: static int
                    472: roff_Dd(ROFFCALL_ARGS)
                    473: {
                    474:
1.5     ! kristaps  475:        dbg_enter(arg, ROFF_Dd);
        !           476:
1.3       kristaps  477:        assert(ROFF_PRELUDE & tree->state);
                    478:        if (ROFF_PRELUDE_Dt & tree->state ||
                    479:                        ROFF_PRELUDE_Dd & tree->state) {
1.4       kristaps  480:                warnx("%s: prelude `Dd' out-of-order (line %zu)",
1.3       kristaps  481:                                in->name, in->line);
1.1       kristaps  482:                return(0);
                    483:        }
                    484:
1.3       kristaps  485:        assert(NULL == tree->last);
1.1       kristaps  486:        tree->state |= ROFF_PRELUDE_Dd;
1.2       kristaps  487:
1.5     ! kristaps  488:        dbg_leave(arg, ROFF_Dd);
        !           489:
1.1       kristaps  490:        return(1);
                    491: }
                    492:
                    493:
                    494: static int
                    495: roff_Dt(ROFFCALL_ARGS)
                    496: {
                    497:
1.5     ! kristaps  498:        dbg_enter(arg, ROFF_Dt);
        !           499:
1.3       kristaps  500:        assert(ROFF_PRELUDE & tree->state);
1.1       kristaps  501:        if ( ! (ROFF_PRELUDE_Dd & tree->state) ||
                    502:                        (ROFF_PRELUDE_Dt & tree->state)) {
1.4       kristaps  503:                warnx("%s: prelude `Dt' out-of-order (line %zu)",
1.3       kristaps  504:                                in->name, in->line);
                    505:                return(0);
1.1       kristaps  506:        }
                    507:
1.3       kristaps  508:        assert(NULL == tree->last);
1.1       kristaps  509:        tree->state |= ROFF_PRELUDE_Dt;
1.2       kristaps  510:
1.5     ! kristaps  511:        dbg_leave(arg, ROFF_Dt);
        !           512:
1.1       kristaps  513:        return(1);
                    514: }
                    515:
                    516:
                    517: static int
                    518: roff_Os(ROFFCALL_ARGS)
                    519: {
                    520:
                    521:        if (ROFF_EXIT == type) {
1.3       kristaps  522:                roffnode_free(ROFF_Os, tree);
1.2       kristaps  523:                dbg_leave(arg, ROFF_Os);
1.1       kristaps  524:                return(1);
                    525:        }
                    526:
1.5     ! kristaps  527:        dbg_enter(arg, ROFF_Os);
        !           528:
1.3       kristaps  529:        assert(ROFF_PRELUDE & tree->state);
                    530:        if ( ! (ROFF_PRELUDE_Dt & tree->state) ||
                    531:                        ! (ROFF_PRELUDE_Dd & tree->state)) {
1.4       kristaps  532:                warnx("%s: prelude `Os' out-of-order (line %zu)",
1.3       kristaps  533:                                in->name, in->line);
1.1       kristaps  534:                return(0);
                    535:        }
                    536:
1.3       kristaps  537:        assert(NULL == tree->last);
                    538:        if (NULL == roffnode_new(ROFF_Os, in->line, tree))
1.1       kristaps  539:                return(0);
                    540:
                    541:        tree->state |= ROFF_PRELUDE_Os;
1.3       kristaps  542:        tree->state &= ~ROFF_PRELUDE;
                    543:        tree->state |= ROFF_BODY;
1.1       kristaps  544:
                    545:        return(1);
                    546: }
                    547:
                    548:
1.3       kristaps  549: static int
1.1       kristaps  550: roff_Sh(ROFFCALL_ARGS)
                    551: {
1.2       kristaps  552:
                    553:        if (ROFF_EXIT == type) {
1.3       kristaps  554:                roffnode_free(ROFF_Sh, tree);
1.2       kristaps  555:                dbg_leave(arg, ROFF_Sh);
                    556:                return(1);
                    557:        }
                    558:
1.5     ! kristaps  559:        dbg_enter(arg, ROFF_Sh);
        !           560:
1.3       kristaps  561:        if (NULL == roffnode_new(ROFF_Sh, in->line, tree))
1.2       kristaps  562:                return(0);
                    563:
1.5     ! kristaps  564:        dbg_leave(arg, ROFF_Li);
        !           565:
1.1       kristaps  566:        return(1);
                    567: }
                    568:
1.2       kristaps  569:
1.3       kristaps  570: static int
                    571: roff_Li(ROFFCALL_ARGS)
1.2       kristaps  572: {
                    573:
1.5     ! kristaps  574:        dbg_enter(arg, ROFF_Li);
        !           575:        dbg_leave(arg, ROFF_Li);
        !           576:
1.3       kristaps  577:        return(1);
1.2       kristaps  578: }
                    579:
                    580:
1.5     ! kristaps  581: #if 0
        !           582: static int
        !           583: parse_args(void)
        !           584: {
        !           585:        skip_whitespace();
        !           586:
        !           587:        while (pos < sz) {
        !           588:
        !           589:                if (is_arg) {
        !           590:                } else if (parsable) {
        !           591:                        if (is_callable_token()) {
        !           592:                        }
        !           593:                }
        !           594:
        !           595:                skip_whitespace();
        !           596:        }
        !           597: }
        !           598: #endif
        !           599:
        !           600:
1.3       kristaps  601: static int
                    602: roff_An(ROFFCALL_ARGS)
1.2       kristaps  603: {
                    604:
1.5     ! kristaps  605:        dbg_enter(arg, ROFF_An);
        !           606:
        !           607:        /* Do our ML stuff. */
        !           608:
        !           609:        /*parse_args();*/
        !           610:
        !           611:        /* Do our trailing whitespace stuff. */
        !           612:
        !           613:        dbg_leave(arg, ROFF_An);
        !           614:
1.3       kristaps  615:        return(1);
1.2       kristaps  616: }

CVSweb