diff options
-rw-r--r-- | Makefile | 35 | ||||
-rw-r--r-- | libmdocml.c | 21 | ||||
-rw-r--r-- | libmdocml.h | 26 | ||||
-rw-r--r-- | mdocml.1 | 40 | ||||
-rw-r--r-- | mdocml.c | 287 |
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); +} |