]> git.cameronkatri.com Git - mandoc.git/blobdiff - mdocml.c
*** empty log message ***
[mandoc.git] / mdocml.c
index 48bedcb904393333323ea08e6f17375c72698b5d..a22a1092667b2223d8a74859dc3c516082e14745 100644 (file)
--- a/mdocml.c
+++ b/mdocml.c
@@ -1,4 +1,4 @@
-/* $Id: mdocml.c,v 1.1 2008/11/22 14:53:29 kristaps Exp $ */
+/* $Id: mdocml.c,v 1.13 2008/11/27 17:27:50 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
 
 #include "libmdocml.h"
 
-struct md_file {
-       int              fd;
-       const char      *name;
-};
+#define        BUFFER_IN_DEF   BUFSIZ   /* See begin_bufs. */
+#define        BUFFER_OUT_DEF  BUFSIZ   /* See begin_bufs. */
 
-struct md_buf {
-       struct md_file  *file;
-       char            *buf;
-       size_t           bufsz;
-       size_t           line;
-};
-
-static void             usage(void);
-
-static int              md_begin(const char *, const char *);
-static int              md_begin_io(const char *, const char *);
-static int              md_begin_bufs(struct md_file *, struct md_file *);
-static int              md_run(struct md_buf *, struct md_buf *);
-static int              md_line(struct md_buf *, const struct md_buf *,
-                               const char *, size_t);
-
-static ssize_t          md_buf_fill(struct md_buf *);
+static void             usage(void);
 
+static int              begin_io(const struct md_args *, 
+                               char *, char *);
+static int              leave_io(const struct md_buf *, 
+                               const struct md_buf *, int);
+static int              begin_bufs(const struct md_args *,
+                               struct md_buf *, struct md_buf *);
+static int              leave_bufs(const struct md_buf *, 
+                               const struct md_buf *, int);
 
 int
 main(int argc, char *argv[])
 {
        int              c;
        char            *out, *in;
+       struct md_args   args;
 
        extern char     *optarg;
        extern int       optind;
 
-       out = NULL;
+       out = in = NULL;
+
+       (void)memset(&args, 0, sizeof(struct md_args));
        
-       while (-1 != (c = getopt(argc, argv, "o:")))
+       while (-1 != (c = getopt(argc, argv, "o:vW")))
                switch (c) {
                case ('o'):
                        out = optarg;
                        break;
+               case ('v'):
+                       args.verbosity++;
+                       break;
+               case ('W'):
+                       args.warnings |= MD_WARN_ALL;
+                       break;
                default:
                        usage();
                        return(1);
                }
 
        argv += optind;
-       if (1 != (argc -= optind)) {
-               usage();
-               return(1);
-       }
+       argc -= optind;
+
+       if (1 == argc)
+               in = *argv++;
 
-       argc--;
-       in = *argv++;
+       args.type = MD_DUMMY;
 
-       return(md_begin(out, in));
+       return(begin_io(&args, out ? out : "-", in ? in : "-"));
 }
 
 
+/* 
+ * Close out file descriptors opened in begin_io.  If the descriptor
+ * refers to stdin/stdout, then do nothing.
+ */
 static int
-md_begin(const char *out, const char *in)
+leave_io(const struct md_buf *out, 
+               const struct md_buf *in, int c)
 {
-       char             buf[MAXPATHLEN];
-
+       assert(out);
        assert(in);
-       if (out)
-               return(md_begin_io(out, in));
 
-       if (strlcpy(buf, in, MAXPATHLEN) >= MAXPATHLEN)
-               warnx("output filename too long");
-       else if (strlcat(buf, ".html", MAXPATHLEN) >= MAXPATHLEN)
-               warnx("output filename too long");
-       else 
-               return(md_begin_io(buf, in));
+       if (-1 != in->fd && -1 == close(in->fd)) {
+               assert(in->name);
+               warn("%s", in->name);
+               c = 1;
+       }
+       if (-1 != out->fd && STDOUT_FILENO != out->fd &&
+                       -1 == close(out->fd)) {
+               assert(out->name);
+               warn("%s", out->name);
+               c = 1;
+       }
 
-       return(1);
+       return(c);
 }
 
 
+/*
+ * Open file descriptors or assign stdin/stdout, if dictated by the "-"
+ * token instead of a filename.
+ */
 static int
-md_begin_io(const char *out, const char *in)
+begin_io(const struct md_args *args, char *out, char *in)
 {
-       int              c;
-       struct md_file   fin, fout;
+       struct md_buf    fi;
+       struct md_buf    fo;
+
+#define        FI_FL   O_RDONLY
+#define        FO_FL   O_WRONLY|O_CREAT|O_TRUNC
 
+       assert(args);
        assert(out);
        assert(in);
 
-       /* XXX: put an output file in TMPDIR and switch it out when the
-        * true file is ready to be written.
-        */
+       bzero(&fi, sizeof(struct md_buf));
+       bzero(&fo, sizeof(struct md_buf));
 
-       fin.name = in;
+       fi.fd = STDIN_FILENO;
+       fo.fd = STDOUT_FILENO;
 
-       if (-1 == (fin.fd = open(fin.name, O_RDONLY, 0))) {
-               warn("%s", fin.name);
-               return(1);
-       }
+       fi.name = in;
+       fo.name = out;
 
-       fout.name = out;
+       if (0 != strncmp(fi.name, "-", 1))
+               if (-1 == (fi.fd = open(fi.name, FI_FL, 0))) {
+                       warn("%s", fi.name);
+                       return(leave_io(&fo, &fi, 1));
+               }
 
-       fout.fd = open(fout.name, O_WRONLY | O_CREAT | O_EXCL, 0644);
-       if (-1 == fout.fd) {
-               warn("%s", fout.name);
-               if (-1 == close(fin.fd))
-                       warn("%s", fin.name);
-               return(1);
-       }
+       if (0 != strncmp(fo.name, "-", 1)) 
+               if (-1 == (fo.fd = open(fo.name, FO_FL, 0644))) {
+                       warn("%s", fo.name);
+                       return(leave_io(&fo, &fi, 1));
+               }
 
-       c = md_begin_bufs(&fout, &fin);
+       return(leave_io(&fo, &fi, begin_bufs(args, &fo, &fi)));
+}
 
-       if (-1 == close(fin.fd)) {
-               warn("%s", in);
-               c = 1;
-       }
-       if (-1 == close(fout.fd)) {
-               warn("%s", out);
-               c = 1;
-       }
 
+/*
+ * Free buffers allocated in begin_bufs.
+ */
+static int
+leave_bufs(const struct md_buf *out, 
+               const struct md_buf *in, int c)
+{
+       assert(out);
+       assert(in);
+       if (out->buf)
+               free(out->buf);
+       if (in->buf)
+               free(in->buf);
        return(c);
 }
 
 
+/*
+ * Allocate buffers to the maximum of either the input file's blocksize
+ * or BUFFER_IN_DEF/BUFFER_OUT_DEF, which should be around BUFSIZE.
+ */
 static int
-md_begin_bufs(struct md_file *out, struct md_file *in)
+begin_bufs(const struct md_args *args, 
+               struct md_buf *out, struct md_buf *in)
 {
        struct stat      stin, stout;
-       struct md_buf    inbuf, outbuf;
        int              c;
 
+       assert(args);
        assert(in);
        assert(out);
 
        if (-1 == fstat(in->fd, &stin)) {
-               warn("fstat: %s", in->name);
+               warn("%s", in->name);
+               return(1);
+       } else if (STDIN_FILENO != in->fd && 0 == stin.st_size) {
+               warnx("%s: empty file", in->name);
                return(1);
        } else if (-1 == fstat(out->fd, &stout)) {
-               warn("fstat: %s", out->name);
+               warn("%s", out->name);
                return(1);
        }
 
-       inbuf.file = in;
-       inbuf.line = 1;
-       inbuf.bufsz = MAX(stin.st_blksize, BUFSIZ);
+       in->bufsz = MAX(stin.st_blksize, BUFFER_IN_DEF);
+       out->bufsz = MAX(stout.st_blksize, BUFFER_OUT_DEF);
 
-       outbuf.file = out;
-       outbuf.line = 1;
-       outbuf.bufsz = MAX(stout.st_blksize, BUFSIZ);
-
-       if (NULL == (inbuf.buf = malloc(inbuf.bufsz))) {
+       if (NULL == (in->buf = malloc(in->bufsz))) {
                warn("malloc");
-               return(1);
-       } else if (NULL == (outbuf.buf = malloc(outbuf.bufsz))) {
+               return(leave_bufs(out, in, 1));
+       } else if (NULL == (out->buf = malloc(out->bufsz))) {
                warn("malloc");
-               free(inbuf.buf);
-               return(1);
-       }
-
-       c = md_run(&outbuf, &inbuf);
-
-       free(inbuf.buf);
-       free(outbuf.buf);
-
-       return(c);
-}
-
-
-static ssize_t
-md_buf_fill(struct md_buf *in)
-{
-       ssize_t          ssz;
-
-       assert(in);
-       assert(in->file);
-       assert(in->buf);
-       assert(in->bufsz > 0);
-       assert(in->file->name);
-
-       if (-1 == (ssz = read(in->file->fd, in->buf, in->bufsz))) 
-               warn("%s", in->file->name);
-
-       return(ssz);
-}
-
-
-static int
-md_run(struct md_buf *out, struct md_buf *in)
-{
-       ssize_t          sz, i;
-       char             line[BUFSIZ];
-       size_t           pos;
-
-       assert(in);
-       assert(out); 
-
-       /* LINTED */
-       for (pos = 0; ; ) {
-               if (-1 == (sz = md_buf_fill(in)))
-                       return(1);
-               else if (0 == sz)
-                       break;
-
-               for (i = 0; i < sz; i++) {
-                       if ('\n' == in->buf[i]) {
-                               if (md_line(out, in, line, pos))
-                                       return(1);
-                               in->line++;
-                               pos = 0;
-                               continue;
-                       }
-
-                       if (pos < BUFSIZ) {
-                               /* LINTED */
-                               line[pos++] = in->buf[i];
-                               continue;
-                       }
-
-                       warnx("%s: line %zu too long",
-                                       in->file->name, in->line);
-                       return(1);
-               }
+               return(leave_bufs(out, in, 1));
        }
 
-       if (0 != pos)
-               return(md_line(out, in, line, pos));
-
-       return(0);
-}
-
-
-static int
-md_line(struct md_buf *out, const struct md_buf *in,
-               const char *buf, size_t sz)
-{
-       size_t           i;
-
-       assert(buf);
-       assert(out);
-       assert(in);
-
-       for (i = 0; i < sz; i++) 
-               (void)putchar(buf[i]);
-
-       (void)putchar('\n');
-       return(0);
+       c = md_run(args, out, in);
+       return(leave_bufs(out, in, -1 == c ? 1 : 0));
 }
 
 
@@ -283,5 +219,5 @@ usage(void)
 {
        extern char     *__progname;
 
-       (void)printf("usage: %s [-o outfile] infile\n", __progname);
+       (void)printf("usage: %s [-vW] [-o outfile] [infile]\n", __progname);
 }