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

Annotation of mandoc/libmdocml.c, Revision 1.4

1.4     ! kristaps    1: /* $Id: libmdocml.c,v 1.3 2008/11/22 20:15:34 kristaps Exp $ */
1.1       kristaps    2: /*
                      3:  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the
                      7:  * above copyright notice and this permission notice appear in all
                      8:  * copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
                     11:  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
                     12:  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
                     13:  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     14:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     15:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
                     16:  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     17:  * PERFORMANCE OF THIS SOFTWARE.
                     18:  */
1.2       kristaps   19: #include <assert.h>
                     20: #include <fcntl.h>
                     21: #include <err.h>
                     22: #include <stdio.h>
1.1       kristaps   23: #include <stdlib.h>
1.2       kristaps   24: #include <string.h>
                     25: #include <unistd.h>
1.1       kristaps   26:
                     27: #include "libmdocml.h"
1.2       kristaps   28:
                     29: #define        BUFFER_LINE      BUFSIZ
                     30:
1.3       kristaps   31: struct md_rbuf {
                     32:        int              fd;
                     33:        char            *name;
                     34:        char            *buf;
                     35:        size_t           bufsz;
                     36:        size_t           line;
                     37: };
                     38:
                     39: struct md_mbuf {
                     40:        int              fd;
                     41:        char            *name;
                     42:        char            *buf;
                     43:        size_t           bufsz;
                     44:        size_t           pos;
                     45: };
                     46:
                     47: typedef int (*md_line) (const struct md_args *, struct md_mbuf *,
                     48:                                const struct md_rbuf *,
                     49:                                const char *, size_t);
                     50: typedef int (*md_init) (const struct md_args *, struct md_mbuf *);
                     51: typedef int (*md_exit) (const struct md_args *, struct md_mbuf *);
                     52:
                     53: static int              md_line_dummy(const struct md_args *,
                     54:                                struct md_mbuf *,
                     55:                                const struct md_rbuf *,
1.2       kristaps   56:                                const char *, size_t);
                     57:
1.3       kristaps   58: static int              md_line_html4_strict(const struct md_args *,
                     59:                                struct md_mbuf *,
1.2       kristaps   60:                                const struct md_rbuf *,
                     61:                                const char *, size_t);
1.3       kristaps   62: static int              md_init_html4_strict(const struct md_args *,
                     63:                                struct md_mbuf *);
                     64: static int              md_exit_html4_strict(const struct md_args *,
                     65:                                struct md_mbuf *);
                     66:
                     67: static int              md_run_enter(const struct md_args *,
                     68:                                struct md_mbuf *, struct md_rbuf *);
                     69: static int              md_run_leave(const struct md_args *,
                     70:                                struct md_mbuf *,
                     71:                                struct md_rbuf *, int);
                     72:
1.2       kristaps   73: static ssize_t          md_buf_fill(struct md_rbuf *);
                     74: static int              md_buf_flush(struct md_mbuf *);
                     75: static int              md_buf_putchar(struct md_mbuf *, char);
1.4     ! kristaps   76: static int              md_buf_putstring(struct md_mbuf *,
        !            77:                                const char *);
1.2       kristaps   78: static int              md_buf_puts(struct md_mbuf *,
                     79:                                const char *, size_t);
                     80:
                     81:
1.3       kristaps   82: static ssize_t
1.2       kristaps   83: md_buf_fill(struct md_rbuf *in)
                     84: {
                     85:        ssize_t          ssz;
                     86:
                     87:        assert(in);
                     88:        assert(in->buf);
                     89:        assert(in->bufsz > 0);
                     90:        assert(in->name);
                     91:
                     92:        if (-1 == (ssz = read(in->fd, in->buf, in->bufsz)))
                     93:                warn("%s", in->name);
                     94:
                     95:        return(ssz);
                     96: }
                     97:
                     98:
1.3       kristaps   99: static int
1.2       kristaps  100: md_buf_flush(struct md_mbuf *buf)
                    101: {
                    102:        ssize_t          sz;
                    103:
                    104:        assert(buf);
                    105:        assert(buf->buf);
                    106:        assert(buf->name);
                    107:
                    108:        if (0 == buf->pos)
                    109:                return(1);
                    110:
                    111:        sz = write(buf->fd, buf->buf, buf->pos);
                    112:
                    113:        if (-1 == sz) {
                    114:                warn("%s", buf->name);
                    115:                return(0);
                    116:        } else if ((size_t)sz != buf->pos) {
                    117:                warnx("%s: short write", buf->name);
                    118:                return(0);
                    119:        }
                    120:
                    121:        buf->pos = 0;
                    122:        return(1);
                    123: }
                    124:
                    125:
1.3       kristaps  126: static int
1.2       kristaps  127: md_buf_putchar(struct md_mbuf *buf, char c)
                    128: {
                    129:        return(md_buf_puts(buf, &c, 1));
                    130: }
                    131:
                    132:
1.3       kristaps  133: static int
1.4     ! kristaps  134: md_buf_putstring(struct md_mbuf *buf, const char *p)
        !           135: {
        !           136:        return(md_buf_puts(buf, p, strlen(p)));
        !           137: }
        !           138:
        !           139:
        !           140: static int
1.2       kristaps  141: md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)
                    142: {
                    143:        size_t           ssz;
                    144:
                    145:        assert(p);
                    146:        assert(buf);
                    147:        assert(buf->buf);
                    148:
                    149:        /* LINTED */
                    150:        while (buf->pos + sz > buf->bufsz) {
                    151:                ssz = buf->bufsz - buf->pos;
                    152:                (void)memcpy(/* LINTED */
                    153:                                buf->buf + buf->pos, p, ssz);
                    154:                p += (long)ssz;
                    155:                sz -= ssz;
                    156:                buf->pos += ssz;
                    157:
                    158:                if ( ! md_buf_flush(buf))
                    159:                        return(0);
                    160:        }
                    161:
                    162:        (void)memcpy(/* LINTED */
                    163:                        buf->buf + buf->pos, p, sz);
                    164:        buf->pos += sz;
                    165:        return(1);
                    166: }
                    167:
                    168:
1.3       kristaps  169: static int
                    170: md_run_leave(const struct md_args *args,
                    171:                struct md_mbuf *mbuf, struct md_rbuf *rbuf, int c)
                    172: {
                    173:        assert(args);
                    174:        assert(mbuf);
                    175:        assert(rbuf);
                    176:
                    177:        /* Run exiters. */
                    178:        switch (args->type) {
                    179:        case (MD_HTML4_STRICT):
                    180:                if ( ! md_exit_html4_strict(args, mbuf))
                    181:                        return(-1);
                    182:                break;
                    183:        case (MD_DUMMY):
                    184:                break;
                    185:        default:
                    186:                abort();
                    187:        }
                    188:
                    189:        /* Make final flush of buffer. */
                    190:        if ( ! md_buf_flush(mbuf))
                    191:                return(-1);
                    192:
                    193:        return(c);
                    194: }
                    195:
                    196:
                    197: static int
                    198: md_run_enter(const struct md_args *args,
                    199:                struct md_mbuf *mbuf, struct md_rbuf *rbuf)
1.2       kristaps  200: {
                    201:        ssize_t          sz, i;
                    202:        char             line[BUFFER_LINE];
                    203:        size_t           pos;
1.3       kristaps  204:        md_line          fp;
1.2       kristaps  205:
1.3       kristaps  206:        assert(args);
                    207:        assert(mbuf);
                    208:        assert(rbuf);
                    209:
                    210:        /* Function ptrs to line-parsers. */
                    211:        switch (args->type) {
                    212:        case (MD_HTML4_STRICT):
                    213:                fp = md_line_html4_strict;
                    214:                break;
                    215:        case (MD_DUMMY):
                    216:                fp = md_line_dummy;
                    217:                break;
                    218:        default:
                    219:                abort();
                    220:        }
1.2       kristaps  221:
                    222:        /* LINTED */
                    223:        for (pos = 0; ; ) {
1.3       kristaps  224:                if (-1 == (sz = md_buf_fill(rbuf)))
                    225:                        return(-1);
1.2       kristaps  226:                else if (0 == sz)
                    227:                        break;
                    228:
                    229:                for (i = 0; i < sz; i++) {
1.3       kristaps  230:                        if ('\n' == rbuf->buf[i]) {
                    231:                                if ( ! (*fp)(args, mbuf, rbuf, line, pos))
                    232:                                        return(-1);
                    233:                                rbuf->line++;
1.2       kristaps  234:                                pos = 0;
                    235:                                continue;
                    236:                        }
                    237:
                    238:                        if (pos < BUFFER_LINE) {
                    239:                                /* LINTED */
1.3       kristaps  240:                                line[pos++] = rbuf->buf[i];
1.2       kristaps  241:                                continue;
                    242:                        }
                    243:
                    244:                        warnx("%s: line %zu too long",
1.3       kristaps  245:                                        rbuf->name, rbuf->line);
                    246:                        return(-1);
1.2       kristaps  247:                }
                    248:        }
                    249:
1.3       kristaps  250:        if (0 != pos && ! (*fp)(args, mbuf, rbuf, line, pos))
                    251:                return(-1);
                    252:
                    253:        return(md_run_leave(args, mbuf, rbuf, 0));
                    254: }
                    255:
                    256:
                    257: int
                    258: md_run(const struct md_args *args,
                    259:                const struct md_buf *out, const struct md_buf *in)
                    260: {
                    261:        struct md_mbuf   mbuf;
                    262:        struct md_rbuf   rbuf;
                    263:
                    264:        assert(args);
                    265:        assert(in);
                    266:        assert(out);
                    267:
                    268:        (void)memcpy(&mbuf, out, sizeof(struct md_buf));
                    269:        (void)memcpy(&rbuf, in, sizeof(struct md_buf));
                    270:
                    271:        mbuf.pos = 0;
                    272:        rbuf.line = 1;
                    273:
                    274:        /* Run initialisers. */
                    275:        switch (args->type) {
                    276:        case (MD_HTML4_STRICT):
                    277:                if ( ! md_init_html4_strict(args, &mbuf))
                    278:                        return(-1);
                    279:                break;
                    280:        case (MD_DUMMY):
                    281:                break;
                    282:        default:
                    283:                abort();
                    284:        }
1.2       kristaps  285:
1.3       kristaps  286:        /* Go into mainline. */
                    287:        return(md_run_enter(args, &mbuf, &rbuf));
1.2       kristaps  288: }
                    289:
                    290:
                    291: static int
1.3       kristaps  292: md_line_dummy(const struct md_args *args, struct md_mbuf *out,
                    293:                const struct md_rbuf *in, const char *buf, size_t sz)
1.2       kristaps  294: {
                    295:
                    296:        assert(buf);
                    297:        assert(out);
                    298:        assert(in);
1.3       kristaps  299:        assert(args);
1.2       kristaps  300:
                    301:        if ( ! md_buf_puts(out, buf, sz))
1.3       kristaps  302:                return(0);
1.2       kristaps  303:        if ( ! md_buf_putchar(out, '\n'))
1.3       kristaps  304:                return(0);
                    305:
                    306:        return(1);
                    307: }
                    308:
                    309:
                    310: static int
1.4     ! kristaps  311: md_exit_html4_strict(const struct md_args *args, struct md_mbuf *out)
1.3       kristaps  312: {
1.4     ! kristaps  313:        char            *tail;
1.3       kristaps  314:
1.4     ! kristaps  315:        assert(out);
1.3       kristaps  316:        assert(args);
1.4     ! kristaps  317:
        !           318:        tail =  "               </pre>\n"
        !           319:                "       </body>\n"
        !           320:                "</html>\n";
        !           321:
        !           322:        if ( ! md_buf_putstring(out, tail))
        !           323:                return(0);
        !           324:
1.3       kristaps  325:        return(1);
                    326: }
                    327:
                    328:
                    329: static int
1.4     ! kristaps  330: md_init_html4_strict(const struct md_args *args, struct md_mbuf *out)
1.3       kristaps  331: {
1.4     ! kristaps  332:        char            *head;
1.2       kristaps  333:
1.4     ! kristaps  334:        assert(out);
1.3       kristaps  335:        assert(args);
1.4     ! kristaps  336:
        !           337:        head =  "<html>\n"
        !           338:                "       <head>\n"
        !           339:                "               <title>Manual Page</title>\n"
        !           340:                "       </head>\n"
        !           341:                "       <body>\n"
        !           342:                "               <pre>\n";
        !           343:
        !           344:        if ( ! md_buf_putstring(out, head))
        !           345:                return(0);
        !           346:
1.3       kristaps  347:        return(1);
1.2       kristaps  348: }
                    349:
                    350:
1.4     ! kristaps  351: struct md_roff_macro {
        !           352:        char             name[2];
        !           353:        int              flags;
        !           354: #define        MD_PARSED       (1 << 0)
        !           355: #define        MD_CALLABLE     (1 << 1)
        !           356: #define        MD_TITLE        (1 << 2)
        !           357: };
        !           358:
        !           359: struct md_roff_macro[] = {
        !           360:        { "Dd",         MD_TITLE        },
        !           361:        { "Dt",         MD_TITLE        },
        !           362:        { "Os",         MD_TITLE        },
        !           363:        { "Sh",         MD_PARSED       },
        !           364: };
        !           365:
        !           366:
        !           367: static int
        !           368: md_roff(struct md_mbuf *out, const struct md_rbuf *in,
        !           369:                const char *buf, size_t sz)
        !           370: {
        !           371:
        !           372:        assert(out);
        !           373:        assert(in);
        !           374:        assert(buf);
        !           375:        assert(sz >= 1);
        !           376: }
        !           377:
        !           378:
1.3       kristaps  379: static int
                    380: md_line_html4_strict(const struct md_args *args, struct md_mbuf *out,
                    381:                const struct md_rbuf *in, const char *buf, size_t sz)
                    382: {
                    383:
                    384:        assert(args);
                    385:        assert(in);
                    386:
1.4     ! kristaps  387:        if (0 == sz) {
        !           388:                warnx("%s: blank line (line %zu)", in->name, in->line);
        !           389:                return(0);
        !           390:        }
        !           391:
        !           392:        if ('.' == *buf) {
        !           393:                return(1);
        !           394:        }
        !           395:
        !           396:        return(md_buf_puts(out, buf, sz));
1.3       kristaps  397: }

CVSweb