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

Annotation of mandoc/mdocml.c, Revision 1.1

1.1     ! kristaps    1: /* $Id$ */
        !             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: #include <sys/stat.h>
        !            21:
        !            22: #include <assert.h>
        !            23: #include <err.h>
        !            24: #include <fcntl.h>
        !            25: #include <getopt.h>
        !            26: #include <stdio.h>
        !            27: #include <stdlib.h>
        !            28: #include <string.h>
        !            29: #include <unistd.h>
        !            30:
        !            31: #include "libmdocml.h"
        !            32:
        !            33: struct md_file {
        !            34:        int              fd;
        !            35:        const char      *name;
        !            36: };
        !            37:
        !            38: struct md_buf {
        !            39:        struct md_file  *file;
        !            40:        char            *buf;
        !            41:        size_t           bufsz;
        !            42:        size_t           line;
        !            43: };
        !            44:
        !            45: static void             usage(void);
        !            46:
        !            47: static int              md_begin(const char *, const char *);
        !            48: static int              md_begin_io(const char *, const char *);
        !            49: static int              md_begin_bufs(struct md_file *, struct md_file *);
        !            50: static int              md_run(struct md_buf *, struct md_buf *);
        !            51: static int              md_line(struct md_buf *, const struct md_buf *,
        !            52:                                const char *, size_t);
        !            53:
        !            54: static ssize_t          md_buf_fill(struct md_buf *);
        !            55:
        !            56:
        !            57: int
        !            58: main(int argc, char *argv[])
        !            59: {
        !            60:        int              c;
        !            61:        char            *out, *in;
        !            62:
        !            63:        extern char     *optarg;
        !            64:        extern int       optind;
        !            65:
        !            66:        out = NULL;
        !            67:
        !            68:        while (-1 != (c = getopt(argc, argv, "o:")))
        !            69:                switch (c) {
        !            70:                case ('o'):
        !            71:                        out = optarg;
        !            72:                        break;
        !            73:                default:
        !            74:                        usage();
        !            75:                        return(1);
        !            76:                }
        !            77:
        !            78:        argv += optind;
        !            79:        if (1 != (argc -= optind)) {
        !            80:                usage();
        !            81:                return(1);
        !            82:        }
        !            83:
        !            84:        argc--;
        !            85:        in = *argv++;
        !            86:
        !            87:        return(md_begin(out, in));
        !            88: }
        !            89:
        !            90:
        !            91: static int
        !            92: md_begin(const char *out, const char *in)
        !            93: {
        !            94:        char             buf[MAXPATHLEN];
        !            95:
        !            96:        assert(in);
        !            97:        if (out)
        !            98:                return(md_begin_io(out, in));
        !            99:
        !           100:        if (strlcpy(buf, in, MAXPATHLEN) >= MAXPATHLEN)
        !           101:                warnx("output filename too long");
        !           102:        else if (strlcat(buf, ".html", MAXPATHLEN) >= MAXPATHLEN)
        !           103:                warnx("output filename too long");
        !           104:        else
        !           105:                return(md_begin_io(buf, in));
        !           106:
        !           107:        return(1);
        !           108: }
        !           109:
        !           110:
        !           111: static int
        !           112: md_begin_io(const char *out, const char *in)
        !           113: {
        !           114:        int              c;
        !           115:        struct md_file   fin, fout;
        !           116:
        !           117:        assert(out);
        !           118:        assert(in);
        !           119:
        !           120:        /* XXX: put an output file in TMPDIR and switch it out when the
        !           121:         * true file is ready to be written.
        !           122:         */
        !           123:
        !           124:        fin.name = in;
        !           125:
        !           126:        if (-1 == (fin.fd = open(fin.name, O_RDONLY, 0))) {
        !           127:                warn("%s", fin.name);
        !           128:                return(1);
        !           129:        }
        !           130:
        !           131:        fout.name = out;
        !           132:
        !           133:        fout.fd = open(fout.name, O_WRONLY | O_CREAT | O_EXCL, 0644);
        !           134:        if (-1 == fout.fd) {
        !           135:                warn("%s", fout.name);
        !           136:                if (-1 == close(fin.fd))
        !           137:                        warn("%s", fin.name);
        !           138:                return(1);
        !           139:        }
        !           140:
        !           141:        c = md_begin_bufs(&fout, &fin);
        !           142:
        !           143:        if (-1 == close(fin.fd)) {
        !           144:                warn("%s", in);
        !           145:                c = 1;
        !           146:        }
        !           147:        if (-1 == close(fout.fd)) {
        !           148:                warn("%s", out);
        !           149:                c = 1;
        !           150:        }
        !           151:
        !           152:        return(c);
        !           153: }
        !           154:
        !           155:
        !           156: static int
        !           157: md_begin_bufs(struct md_file *out, struct md_file *in)
        !           158: {
        !           159:        struct stat      stin, stout;
        !           160:        struct md_buf    inbuf, outbuf;
        !           161:        int              c;
        !           162:
        !           163:        assert(in);
        !           164:        assert(out);
        !           165:
        !           166:        if (-1 == fstat(in->fd, &stin)) {
        !           167:                warn("fstat: %s", in->name);
        !           168:                return(1);
        !           169:        } else if (-1 == fstat(out->fd, &stout)) {
        !           170:                warn("fstat: %s", out->name);
        !           171:                return(1);
        !           172:        }
        !           173:
        !           174:        inbuf.file = in;
        !           175:        inbuf.line = 1;
        !           176:        inbuf.bufsz = MAX(stin.st_blksize, BUFSIZ);
        !           177:
        !           178:        outbuf.file = out;
        !           179:        outbuf.line = 1;
        !           180:        outbuf.bufsz = MAX(stout.st_blksize, BUFSIZ);
        !           181:
        !           182:        if (NULL == (inbuf.buf = malloc(inbuf.bufsz))) {
        !           183:                warn("malloc");
        !           184:                return(1);
        !           185:        } else if (NULL == (outbuf.buf = malloc(outbuf.bufsz))) {
        !           186:                warn("malloc");
        !           187:                free(inbuf.buf);
        !           188:                return(1);
        !           189:        }
        !           190:
        !           191:        c = md_run(&outbuf, &inbuf);
        !           192:
        !           193:        free(inbuf.buf);
        !           194:        free(outbuf.buf);
        !           195:
        !           196:        return(c);
        !           197: }
        !           198:
        !           199:
        !           200: static ssize_t
        !           201: md_buf_fill(struct md_buf *in)
        !           202: {
        !           203:        ssize_t          ssz;
        !           204:
        !           205:        assert(in);
        !           206:        assert(in->file);
        !           207:        assert(in->buf);
        !           208:        assert(in->bufsz > 0);
        !           209:        assert(in->file->name);
        !           210:
        !           211:        if (-1 == (ssz = read(in->file->fd, in->buf, in->bufsz)))
        !           212:                warn("%s", in->file->name);
        !           213:
        !           214:        return(ssz);
        !           215: }
        !           216:
        !           217:
        !           218: static int
        !           219: md_run(struct md_buf *out, struct md_buf *in)
        !           220: {
        !           221:        ssize_t          sz, i;
        !           222:        char             line[BUFSIZ];
        !           223:        size_t           pos;
        !           224:
        !           225:        assert(in);
        !           226:        assert(out);
        !           227:
        !           228:        /* LINTED */
        !           229:        for (pos = 0; ; ) {
        !           230:                if (-1 == (sz = md_buf_fill(in)))
        !           231:                        return(1);
        !           232:                else if (0 == sz)
        !           233:                        break;
        !           234:
        !           235:                for (i = 0; i < sz; i++) {
        !           236:                        if ('\n' == in->buf[i]) {
        !           237:                                if (md_line(out, in, line, pos))
        !           238:                                        return(1);
        !           239:                                in->line++;
        !           240:                                pos = 0;
        !           241:                                continue;
        !           242:                        }
        !           243:
        !           244:                        if (pos < BUFSIZ) {
        !           245:                                /* LINTED */
        !           246:                                line[pos++] = in->buf[i];
        !           247:                                continue;
        !           248:                        }
        !           249:
        !           250:                        warnx("%s: line %zu too long",
        !           251:                                        in->file->name, in->line);
        !           252:                        return(1);
        !           253:                }
        !           254:        }
        !           255:
        !           256:        if (0 != pos)
        !           257:                return(md_line(out, in, line, pos));
        !           258:
        !           259:        return(0);
        !           260: }
        !           261:
        !           262:
        !           263: static int
        !           264: md_line(struct md_buf *out, const struct md_buf *in,
        !           265:                const char *buf, size_t sz)
        !           266: {
        !           267:        size_t           i;
        !           268:
        !           269:        assert(buf);
        !           270:        assert(out);
        !           271:        assert(in);
        !           272:
        !           273:        for (i = 0; i < sz; i++)
        !           274:                (void)putchar(buf[i]);
        !           275:
        !           276:        (void)putchar('\n');
        !           277:        return(0);
        !           278: }
        !           279:
        !           280:
        !           281: static void
        !           282: usage(void)
        !           283: {
        !           284:        extern char     *__progname;
        !           285:
        !           286:        (void)printf("usage: %s [-o outfile] infile\n", __progname);
        !           287: }

CVSweb