summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile35
-rw-r--r--libmdocml.c21
-rw-r--r--libmdocml.h26
-rw-r--r--mdocml.140
-rw-r--r--mdocml.c287
5 files changed, 409 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..43f98cdf
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,35 @@
+CFLAGS += -W -Wall -g
+
+LINTFLAGS += -c -e -f -u
+
+CLEAN = mdocml mdocml.o mdocml.ln libmdocml.o libmdocml.ln
+
+INSTALL = Makefile libmdocml.h mdocml.c libmdocml.c mdocml.1
+
+all: mdocml
+
+lint: mdocml.ln libmdocml.ln
+
+mdocml: mdocml.o libmdocml.o
+ $(CC) $(CFLAGS) -o $@ mdocml.o libmdocml.o
+
+clean:
+ rm -f $(CLEAN)
+
+dist:
+ mkdir -p .dist/mdocml/
+ install -m 0644 $(INSTALL) .dist/mdocml/
+ ( cd .dist/ && tar zcf ../mdocml.tgz mdocml/ )
+ rm -rf .dist/
+
+mdocml.ln: mdocml.c
+
+mdocml.o: mdocml.c
+
+mdocml.c: libmdocml.h
+
+libmdocml.ln: libmdocml.c
+
+libmdocml.o: libmdocml.c
+
+libmdocml.c: libmdocml.h
diff --git a/libmdocml.c b/libmdocml.c
new file mode 100644
index 00000000..17dcd525
--- /dev/null
+++ b/libmdocml.c
@@ -0,0 +1,21 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <stdlib.h>
+
+#include "libmdocml.h"
diff --git a/libmdocml.h b/libmdocml.h
new file mode 100644
index 00000000..934ae96a
--- /dev/null
+++ b/libmdocml.h
@@ -0,0 +1,26 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef LIBMDOCML_H
+#define LIBMDOCML_H
+
+__BEGIN_DECLS
+
+__END_DECLS
+
+#endif /*!LIBMDOCML_H*/
diff --git a/mdocml.1 b/mdocml.1
new file mode 100644
index 00000000..205ad47a
--- /dev/null
+++ b/mdocml.1
@@ -0,0 +1,40 @@
+.\" $OpenBSD: mdoc.template,v 1.10 2007/05/31 22:10:19 jmc Exp $
+.\"
+.\" The following requests are required for all man pages.
+.\"
+.\" Remove `\&' from the line below.
+.Dd $\&Mdocdate$
+.Dt NAME SECTION#
+.Os
+.Sh NAME
+.Nm program
+.Nd one line about what it does
+.Sh SYNOPSIS
+.\" For a program: program [-abc] file ...
+.Nm program
+.Op Fl abc
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility processes files ...
+something
+something.
+.\" The following requests should be uncommented and used where appropriate.
+.\" This next request is for sections 2, 3, and 9 function return values only.
+.\" .Sh RETURN VALUES
+.\" This next request is for sections 1, 6, 7 & 8 only.
+.\" .Sh ENVIRONMENT
+.\" .Sh FILES
+.\" .Sh EXAMPLES
+.\" This next request is for sections 1, 4, 6, and 8 only.
+.\" .Sh DIAGNOSTICS
+.\" The next request is for sections 2, 3, and 9 error and signal handling only.
+.\" .Sh ERRORS
+.\" .Sh SEE ALSO
+.\" .Xr foobar 1
+.\" .Sh STANDARDS
+.\" .Sh HISTORY
+.\" .Sh AUTHORS
+.\" .Sh CAVEATS
+.\" .Sh BUGS
diff --git a/mdocml.c b/mdocml.c
new file mode 100644
index 00000000..c55eff22
--- /dev/null
+++ b/mdocml.c
@@ -0,0 +1,287 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <err.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libmdocml.h"
+
+struct md_file {
+ int fd;
+ const char *name;
+};
+
+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 *);
+
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ char *out, *in;
+
+ extern char *optarg;
+ extern int optind;
+
+ out = NULL;
+
+ while (-1 != (c = getopt(argc, argv, "o:")))
+ switch (c) {
+ case ('o'):
+ out = optarg;
+ break;
+ default:
+ usage();
+ return(1);
+ }
+
+ argv += optind;
+ if (1 != (argc -= optind)) {
+ usage();
+ return(1);
+ }
+
+ argc--;
+ in = *argv++;
+
+ return(md_begin(out, in));
+}
+
+
+static int
+md_begin(const char *out, const char *in)
+{
+ char buf[MAXPATHLEN];
+
+ 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));
+
+ return(1);
+}
+
+
+static int
+md_begin_io(const char *out, const char *in)
+{
+ int c;
+ struct md_file fin, fout;
+
+ assert(out);
+ assert(in);
+
+ /* XXX: put an output file in TMPDIR and switch it out when the
+ * true file is ready to be written.
+ */
+
+ fin.name = in;
+
+ if (-1 == (fin.fd = open(fin.name, O_RDONLY, 0))) {
+ warn("%s", fin.name);
+ return(1);
+ }
+
+ fout.name = out;
+
+ 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);
+ }
+
+ c = md_begin_bufs(&fout, &fin);
+
+ if (-1 == close(fin.fd)) {
+ warn("%s", in);
+ c = 1;
+ }
+ if (-1 == close(fout.fd)) {
+ warn("%s", out);
+ c = 1;
+ }
+
+ return(c);
+}
+
+
+static int
+md_begin_bufs(struct md_file *out, struct md_file *in)
+{
+ struct stat stin, stout;
+ struct md_buf inbuf, outbuf;
+ int c;
+
+ assert(in);
+ assert(out);
+
+ if (-1 == fstat(in->fd, &stin)) {
+ warn("fstat: %s", in->name);
+ return(1);
+ } else if (-1 == fstat(out->fd, &stout)) {
+ warn("fstat: %s", out->name);
+ return(1);
+ }
+
+ inbuf.file = in;
+ inbuf.line = 1;
+ inbuf.bufsz = MAX(stin.st_blksize, BUFSIZ);
+
+ outbuf.file = out;
+ outbuf.line = 1;
+ outbuf.bufsz = MAX(stout.st_blksize, BUFSIZ);
+
+ if (NULL == (inbuf.buf = malloc(inbuf.bufsz))) {
+ warn("malloc");
+ return(1);
+ } else if (NULL == (outbuf.buf = malloc(outbuf.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);
+ }
+ }
+
+ 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);
+}
+
+
+static void
+usage(void)
+{
+ extern char *__progname;
+
+ (void)printf("usage: %s [-o outfile] infile\n", __progname);
+}