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