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

Annotation of mandoc/validate.c, Revision 1.5

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

CVSweb