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

Annotation of mandoc/validate.c, Revision 1.4

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

CVSweb