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

Annotation of mandoc/validate.c, Revision 1.6

1.6     ! kristaps    1: /* $Id: validate.c,v 1.5 2008/11/30 20:00:08 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 <sys/param.h>
                     20:
                     21: #include <assert.h>
                     22: #include <ctype.h>
                     23: #include <err.h>
                     24: #include <stdio.h>
                     25: #include <stdlib.h>
                     26: #include <string.h>
                     27:
                     28: #include "libmdocml.h"
                     29: #include "private.h"
                     30:
1.2       kristaps   31: #define        INDENT           4
1.6     ! kristaps   32: #define        COLUMNS          72
1.2       kristaps   33:
1.1       kristaps   34: #ifdef __linux__ /* FIXME */
1.2       kristaps   35: #define        strlcat          strncat
1.1       kristaps   36: #endif
                     37:
1.6     ! kristaps   38: enum   md_tok {
        !            39:        MD_BLKIN,
        !            40:        MD_BLKOUT,
        !            41:        MD_IN,
        !            42:        MD_OUT,
        !            43:        MD_TEXT
        !            44: };
        !            45:
1.1       kristaps   46: struct md_valid {
                     47:        const struct md_args    *args;
                     48:        const struct md_rbuf    *rbuf;
1.6     ! kristaps   49:
1.1       kristaps   50:        struct md_mbuf  *mbuf;
                     51:        struct rofftree *tree;
                     52:        size_t           indent;
                     53:        size_t           pos;
1.6     ! kristaps   54:        enum md_tok      last;
1.1       kristaps   55:        int              flags;
1.6     ! kristaps   56: #define        MD_LITERAL      (1 << 0) /* FIXME */
1.1       kristaps   57: };
                     58:
                     59: static void             roffmsg(void *arg, enum roffmsg,
                     60:                                const char *, const char *, char *);
                     61: static int              roffhead(void *);
                     62: static int              rofftail(void *);
1.6     ! kristaps   63: static int              roffin(void *, int, int, int *, char **);
1.4       kristaps   64: static int              roffdata(void *, int, char *);
1.1       kristaps   65: static int              roffout(void *, int);
1.2       kristaps   66: static int              roffblkin(void *, int, int *, char **);
1.1       kristaps   67: static int              roffblkout(void *, int);
                     68: static int              roffspecial(void *, int);
                     69:
                     70: static int              mbuf_newline(struct md_valid *);
                     71: static int              mbuf_indent(struct md_valid *);
1.4       kristaps   72: static int              mbuf_data(struct md_valid *, int, char *);
1.6     ! kristaps   73: static int              mbuf_putstring(struct md_valid *,
        !            74:                                const char *);
        !            75: static int              mbuf_nputstring(struct md_valid *,
        !            76:                                const char *, size_t);
        !            77:
        !            78:
        !            79: static int
        !            80: mbuf_putstring(struct md_valid *p, const char *buf)
        !            81: {
        !            82:
        !            83:        return(mbuf_nputstring(p, buf, strlen(buf)));
        !            84: }
        !            85:
        !            86:
        !            87: static int
        !            88: mbuf_nputstring(struct md_valid *p, const char *buf, size_t sz)
        !            89: {
        !            90:
        !            91:        p->pos += sz;
        !            92:        return(md_buf_puts(p->mbuf, buf, sz));
        !            93: }
1.1       kristaps   94:
                     95:
                     96: static int
                     97: mbuf_indent(struct md_valid *p)
                     98: {
                     99:        size_t           i;
                    100:
1.2       kristaps  101:        assert(p->pos == 0);
1.1       kristaps  102:
1.5       kristaps  103:        /* LINTED */
1.2       kristaps  104:        for (i = 0; i < MIN(p->indent, INDENT); i++)
1.1       kristaps  105:                if ( ! md_buf_putstring(p->mbuf, "    "))
                    106:                        return(0);
                    107:
1.2       kristaps  108:        p->pos += i * INDENT;
1.1       kristaps  109:        return(1);
                    110: }
                    111:
                    112:
                    113: static int
                    114: mbuf_newline(struct md_valid *p)
                    115: {
                    116:
                    117:        if ( ! md_buf_putchar(p->mbuf, '\n'))
                    118:                return(0);
                    119:
                    120:        p->pos = 0;
1.2       kristaps  121:        return(1);
1.1       kristaps  122: }
                    123:
                    124:
                    125: static int
1.4       kristaps  126: mbuf_data(struct md_valid *p, int space, char *buf)
1.1       kristaps  127: {
                    128:        size_t           sz;
                    129:        char            *bufp;
                    130:
                    131:        assert(p->mbuf);
                    132:        assert(0 != p->indent);
                    133:
1.6     ! kristaps  134:        /*
        !           135:         * FIXME: punctuation/no-space stuff shouldn't have a newline
        !           136:         * before it.
        !           137:         */
        !           138:
1.1       kristaps  139:        if (MD_LITERAL & p->flags)
1.6     ! kristaps  140:                return(mbuf_putstring(p, buf));
1.1       kristaps  141:
                    142:        while (*buf) {
                    143:                while (*buf && isspace(*buf))
                    144:                        buf++;
                    145:
                    146:                if (0 == *buf)
                    147:                        break;
                    148:
                    149:                bufp = buf;
                    150:                while (*buf && ! isspace(*buf))
                    151:                        buf++;
                    152:
                    153:                if (0 != *buf)
                    154:                        *buf++ = 0;
                    155:
                    156:                sz = strlen(bufp);
1.2       kristaps  157:
                    158:                if (0 == p->pos) {
                    159:                        if ( ! mbuf_indent(p))
                    160:                                return(0);
1.6     ! kristaps  161:                        if ( ! mbuf_nputstring(p, bufp, sz))
1.1       kristaps  162:                                return(0);
1.6     ! kristaps  163:                        if (p->indent * INDENT + sz >= COLUMNS) {
1.2       kristaps  164:                                if ( ! mbuf_newline(p))
                    165:                                        return(0);
                    166:                                continue;
                    167:                        }
1.1       kristaps  168:                        continue;
                    169:                }
                    170:
1.6     ! kristaps  171:                if (sz + p->pos >= COLUMNS) {
1.2       kristaps  172:                        if ( ! mbuf_newline(p))
                    173:                                return(0);
                    174:                        if ( ! mbuf_indent(p))
                    175:                                return(0);
1.3       kristaps  176:                } else if (space)
1.6     ! kristaps  177:                        if ( ! mbuf_nputstring(p, " ", 1))
1.3       kristaps  178:                                return(0);
1.1       kristaps  179:
1.6     ! kristaps  180:                if ( ! mbuf_nputstring(p, bufp, sz))
1.1       kristaps  181:                        return(0);
                    182:        }
                    183:
                    184:        return(1);
                    185: }
                    186:
                    187:
                    188: int
                    189: md_line_valid(void *arg, char *buf)
                    190: {
                    191:        struct md_valid *p;
                    192:
                    193:        p = (struct md_valid *)arg;
                    194:        return(roff_engine(p->tree, buf));
                    195: }
                    196:
                    197:
                    198: int
                    199: md_exit_valid(void *data, int flush)
                    200: {
                    201:        int              c;
                    202:        struct md_valid *p;
                    203:
                    204:        p = (struct md_valid *)data;
                    205:        c = roff_free(p->tree, flush);
                    206:        free(p);
                    207:
                    208:        return(c);
                    209: }
                    210:
                    211:
                    212: void *
                    213: md_init_valid(const struct md_args *args,
                    214:                struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
                    215: {
                    216:        struct roffcb    cb;
                    217:        struct md_valid *p;
                    218:
                    219:        cb.roffhead = roffhead;
                    220:        cb.rofftail = rofftail;
                    221:        cb.roffin = roffin;
                    222:        cb.roffout = roffout;
                    223:        cb.roffblkin = roffblkin;
                    224:        cb.roffblkout = roffblkout;
                    225:        cb.roffspecial = roffspecial;
                    226:        cb.roffmsg = roffmsg;
                    227:        cb.roffdata = roffdata;
                    228:
                    229:        if (NULL == (p = calloc(1, sizeof(struct md_valid))))
                    230:                err(1, "malloc");
                    231:
                    232:        p->args = args;
                    233:        p->mbuf = mbuf;
                    234:        p->rbuf = rbuf;
                    235:
                    236:        assert(mbuf);
                    237:
                    238:        if (NULL == (p->tree = roff_alloc(&cb, p))) {
                    239:                free(p);
                    240:                return(NULL);
                    241:        }
                    242:
                    243:        return(p);
                    244: }
                    245:
                    246:
                    247: /* ARGSUSED */
                    248: static int
                    249: roffhead(void *arg)
                    250: {
1.2       kristaps  251:        struct md_valid *p;
                    252:
                    253:        assert(arg);
                    254:        p = (struct md_valid *)arg;
                    255:
1.6     ! kristaps  256:        if ( ! mbuf_putstring(p, "<?xml version=\"1.0\" "
1.4       kristaps  257:                                "encoding=\"UTF-8\"?>\n"))
                    258:                return(0);
1.6     ! kristaps  259:        if ( ! mbuf_nputstring(p, "<mdoc>", 6))
        !           260:                return(0);
1.4       kristaps  261:
1.2       kristaps  262:        p->indent++;
1.4       kristaps  263:        return(mbuf_newline(p));
1.1       kristaps  264: }
                    265:
                    266:
                    267: static int
                    268: rofftail(void *arg)
                    269: {
                    270:        struct md_valid *p;
                    271:
                    272:        assert(arg);
                    273:        p = (struct md_valid *)arg;
                    274:
1.2       kristaps  275:        if (0 != p->pos && ! mbuf_newline(p))
                    276:                return(0);
1.6     ! kristaps  277:
        !           278:        if ( ! mbuf_nputstring(p, "</mdoc>", 7))
        !           279:                return(0);
        !           280:        return(mbuf_newline(p));
1.1       kristaps  281: }
                    282:
                    283:
1.5       kristaps  284: /* ARGSUSED */
1.1       kristaps  285: static int
                    286: roffspecial(void *arg, int tok)
                    287: {
                    288:
                    289:        return(1);
                    290: }
                    291:
                    292:
                    293: static int
1.2       kristaps  294: roffblkin(void *arg, int tok, int *argc, char **argv)
1.1       kristaps  295: {
                    296:        struct md_valid *p;
1.5       kristaps  297:        int              i;
1.1       kristaps  298:
                    299:        assert(arg);
                    300:        p = (struct md_valid *)arg;
                    301:
1.2       kristaps  302:        if (0 != p->pos) {
                    303:                if ( ! mbuf_newline(p))
1.1       kristaps  304:                        return(0);
                    305:                if ( ! mbuf_indent(p))
                    306:                        return(0);
1.2       kristaps  307:        } else if ( ! mbuf_indent(p))
                    308:                return(0);
1.1       kristaps  309:
1.6     ! kristaps  310:        if ( ! mbuf_nputstring(p, "<", 1))
1.2       kristaps  311:                return(0);
1.6     ! kristaps  312:        if ( ! mbuf_putstring(p, toknames[tok]))
1.1       kristaps  313:                return(0);
1.5       kristaps  314:
                    315:        for (i = 0; ROFF_ARGMAX != argc[i]; i++) {
1.6     ! kristaps  316:                if ( ! mbuf_nputstring(p, " ", 1))
1.5       kristaps  317:                        return(0);
1.6     ! kristaps  318:                if ( ! mbuf_putstring(p, tokargnames[argc[i]]))
1.5       kristaps  319:                        return(0);
1.6     ! kristaps  320:                if ( ! mbuf_nputstring(p, "=\"", 2))
1.5       kristaps  321:                        return(0);
1.6     ! kristaps  322:                if ( ! mbuf_putstring(p, argv[i] ? argv[i] : "true"))
1.5       kristaps  323:                        return(0);
1.6     ! kristaps  324:                if ( ! mbuf_nputstring(p, "\"", 1))
1.5       kristaps  325:                        return(0);
                    326:        }
                    327:
1.6     ! kristaps  328:        if ( ! mbuf_nputstring(p, ">", 1))
1.2       kristaps  329:                return(0);
                    330:        if ( ! mbuf_newline(p))
1.1       kristaps  331:                return(0);
                    332:
                    333:        p->indent++;
1.2       kristaps  334:        return(1);
1.1       kristaps  335: }
                    336:
                    337:
                    338: static int
                    339: roffblkout(void *arg, int tok)
                    340: {
                    341:        struct md_valid *p;
                    342:
                    343:        assert(arg);
                    344:        p = (struct md_valid *)arg;
                    345:
1.2       kristaps  346:        p->indent--;
                    347:
                    348:        if (0 != p->pos) {
                    349:                if ( ! mbuf_newline(p))
                    350:                        return(0);
                    351:                if ( ! mbuf_indent(p))
                    352:                        return(0);
                    353:        } else if ( ! mbuf_indent(p))
1.1       kristaps  354:                return(0);
                    355:
1.6     ! kristaps  356:        if ( ! mbuf_nputstring(p, "</", 2))
1.2       kristaps  357:                return(0);
1.6     ! kristaps  358:        if ( ! mbuf_putstring(p, toknames[tok]))
1.2       kristaps  359:                return(0);
1.6     ! kristaps  360:        if ( ! mbuf_nputstring(p, ">", 1))
1.2       kristaps  361:                return(0);
                    362:        if ( ! mbuf_newline(p))
                    363:                return(0);
1.1       kristaps  364:
1.2       kristaps  365:        return(1);
1.1       kristaps  366: }
                    367:
                    368:
                    369: static int
1.6     ! kristaps  370: roffin(void *arg, int tok, int space, int *argc, char **argv)
1.1       kristaps  371: {
1.2       kristaps  372:        struct md_valid *p;
1.5       kristaps  373:        int              i;
1.2       kristaps  374:
                    375:        assert(arg);
                    376:        p = (struct md_valid *)arg;
                    377:
                    378:        if (0 == p->pos && ! mbuf_indent(p))
                    379:                return(0);
                    380:
1.6     ! kristaps  381:        /*
        !           382:         * FIXME: put into a buffer before writing (check line length).
        !           383:         */
1.5       kristaps  384:
1.6     ! kristaps  385:        if (space && ! mbuf_nputstring(p, " ", 1))
        !           386:                return(0);
        !           387:        if ( ! mbuf_nputstring(p, "<", 1))
1.2       kristaps  388:                return(0);
1.6     ! kristaps  389:        if ( ! mbuf_putstring(p, toknames[tok]))
1.2       kristaps  390:                return(0);
1.5       kristaps  391:
                    392:        for (i = 0; ROFF_ARGMAX != argc[i]; i++) {
1.6     ! kristaps  393:                if ( ! mbuf_nputstring(p, " ", 1))
1.5       kristaps  394:                        return(0);
1.6     ! kristaps  395:                if ( ! mbuf_putstring(p, tokargnames[argc[i]]))
1.5       kristaps  396:                        return(0);
1.6     ! kristaps  397:                if ( ! mbuf_nputstring(p, "=\"", 2))
1.5       kristaps  398:                        return(0);
1.6     ! kristaps  399:                if ( ! mbuf_putstring(p, argv[i] ? argv[i] : "true"))
1.5       kristaps  400:                        return(0);
1.6     ! kristaps  401:                if ( ! mbuf_nputstring(p, "\"", 1))
1.5       kristaps  402:                        return(0);
                    403:        }
                    404:
1.6     ! kristaps  405:        return(mbuf_nputstring(p, ">", 1));
1.1       kristaps  406: }
                    407:
                    408:
                    409: static int
                    410: roffout(void *arg, int tok)
                    411: {
1.2       kristaps  412:        struct md_valid *p;
                    413:
                    414:        assert(arg);
                    415:        p = (struct md_valid *)arg;
                    416:
                    417:        if (0 == p->pos && ! mbuf_indent(p))
                    418:                return(0);
                    419:
1.6     ! kristaps  420:        if ( ! mbuf_nputstring(p, "</", 2))
1.2       kristaps  421:                return(0);
1.6     ! kristaps  422:        if ( ! mbuf_putstring(p, toknames[tok]))
1.2       kristaps  423:                return(0);
1.6     ! kristaps  424:        return(mbuf_nputstring(p, ">", 1));
1.1       kristaps  425: }
                    426:
                    427:
                    428: static void
                    429: roffmsg(void *arg, enum roffmsg lvl,
                    430:                const char *buf, const char *pos, char *msg)
                    431: {
                    432:        char            *level;
                    433:        struct md_valid *p;
                    434:
                    435:        assert(arg);
                    436:        p = (struct md_valid *)arg;
                    437:
                    438:        switch (lvl) {
                    439:        case (ROFF_WARN):
                    440:                if ( ! (MD_WARN_ALL & p->args->warnings))
                    441:                        return;
                    442:                level = "warning";
                    443:                break;
                    444:        case (ROFF_ERROR):
                    445:                level = "error";
                    446:                break;
                    447:        default:
                    448:                abort();
                    449:        }
                    450:
                    451:        if (pos)
1.6     ! kristaps  452:                (void)fprintf(stderr, "%s:%zu: %s: %s (column %zu)\n",
        !           453:                                p->rbuf->name, p->rbuf->line, level,
        !           454:                                msg, pos - buf);
1.1       kristaps  455:        else
                    456:                (void)fprintf(stderr, "%s: %s: %s\n",
                    457:                                p->rbuf->name, level, msg);
                    458:
                    459: }
                    460:
                    461:
                    462: static int
1.4       kristaps  463: roffdata(void *arg, int space, char *buf)
1.1       kristaps  464: {
                    465:        struct md_valid *p;
                    466:
                    467:        assert(arg);
                    468:        p = (struct md_valid *)arg;
1.4       kristaps  469:        return(mbuf_data(p, space, buf));
1.1       kristaps  470: }

CVSweb