summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmdocml.c172
-rw-r--r--libmdocml.h24
-rw-r--r--mdocml.134
-rw-r--r--mdocml.c302
4 files changed, 284 insertions, 248 deletions
diff --git a/libmdocml.c b/libmdocml.c
index 17dcd525..9e40da80 100644
--- a/libmdocml.c
+++ b/libmdocml.c
@@ -16,6 +16,178 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+#include <assert.h>
+#include <fcntl.h>
+#include <err.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "libmdocml.h"
+
+#define BUFFER_LINE BUFSIZ
+
+typedef int (*md_line) (struct md_mbuf *, const struct md_rbuf *,
+ const char *, size_t);
+
+static int md_line_dummy(struct md_mbuf *,
+ const struct md_rbuf *,
+ const char *, size_t);
+static ssize_t md_buf_fill(struct md_rbuf *);
+static int md_buf_flush(struct md_mbuf *);
+static int md_buf_putchar(struct md_mbuf *, char);
+static int md_buf_puts(struct md_mbuf *,
+ const char *, size_t);
+
+
+ssize_t
+md_buf_fill(struct md_rbuf *in)
+{
+ ssize_t ssz;
+
+ assert(in);
+ assert(in->buf);
+ assert(in->bufsz > 0);
+ assert(in->name);
+
+ if (-1 == (ssz = read(in->fd, in->buf, in->bufsz)))
+ warn("%s", in->name);
+
+ return(ssz);
+}
+
+
+int
+md_buf_flush(struct md_mbuf *buf)
+{
+ ssize_t sz;
+
+ assert(buf);
+ assert(buf->buf);
+ assert(buf->name);
+
+ if (0 == buf->pos)
+ return(1);
+
+ sz = write(buf->fd, buf->buf, buf->pos);
+
+ if (-1 == sz) {
+ warn("%s", buf->name);
+ return(0);
+ } else if ((size_t)sz != buf->pos) {
+ warnx("%s: short write", buf->name);
+ return(0);
+ }
+
+ buf->pos = 0;
+ return(1);
+}
+
+
+int
+md_buf_putchar(struct md_mbuf *buf, char c)
+{
+ return(md_buf_puts(buf, &c, 1));
+}
+
+
+int
+md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)
+{
+ size_t ssz;
+
+ assert(p);
+ assert(buf);
+ assert(buf->buf);
+
+ /* LINTED */
+ while (buf->pos + sz > buf->bufsz) {
+ ssz = buf->bufsz - buf->pos;
+ (void)memcpy(/* LINTED */
+ buf->buf + buf->pos, p, ssz);
+ p += (long)ssz;
+ sz -= ssz;
+ buf->pos += ssz;
+
+ if ( ! md_buf_flush(buf))
+ return(0);
+ }
+
+ (void)memcpy(/* LINTED */
+ buf->buf + buf->pos, p, sz);
+ buf->pos += sz;
+ return(1);
+}
+
+
+int
+md_run(enum md_type type, struct md_mbuf *out, struct md_rbuf *in)
+{
+ ssize_t sz, i;
+ char line[BUFFER_LINE];
+ size_t pos;
+ md_line func;
+
+ assert(in);
+ assert(out);
+
+ out->pos = 0;
+ in->line = 1;
+
+ assert(MD_DUMMY == type);
+ func = md_line_dummy;
+
+ /* 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 ((*func)(out, in, line, pos))
+ return(1);
+ in->line++;
+ pos = 0;
+ continue;
+ }
+
+ if (pos < BUFFER_LINE) {
+ /* LINTED */
+ line[pos++] = in->buf[i];
+ continue;
+ }
+
+ warnx("%s: line %zu too long",
+ in->name, in->line);
+ return(1);
+ }
+ }
+
+ if (0 != pos && (*func)(out, in, line, pos))
+ return(1);
+
+ return(md_buf_flush(out) ? 0 : 1);
+}
+
+
+static int
+md_line_dummy(struct md_mbuf *out, const struct md_rbuf *in,
+ const char *buf, size_t sz)
+{
+
+ assert(buf);
+ assert(out);
+ assert(in);
+
+ if ( ! md_buf_puts(out, buf, sz))
+ return(1);
+ if ( ! md_buf_putchar(out, '\n'))
+ return(1);
+
+ return(0);
+}
+
+
diff --git a/libmdocml.h b/libmdocml.h
index 934ae96a..85843ce6 100644
--- a/libmdocml.h
+++ b/libmdocml.h
@@ -19,8 +19,32 @@
#ifndef LIBMDOCML_H
#define LIBMDOCML_H
+#include <sys/types.h>
+
+struct md_rbuf {
+ int fd;
+ const char *name;
+ char *buf;
+ size_t bufsz;
+ size_t line;
+};
+
+struct md_mbuf {
+ int fd;
+ const char *name;
+ char *buf;
+ size_t bufsz;
+ size_t pos;
+};
+
+enum md_type {
+ MD_DUMMY
+};
+
__BEGIN_DECLS
+int md_run(enum md_type, struct md_mbuf *, struct md_rbuf *);
+
__END_DECLS
#endif /*!LIBMDOCML_H*/
diff --git a/mdocml.1 b/mdocml.1
index 205ad47a..ed7aa238 100644
--- a/mdocml.1
+++ b/mdocml.1
@@ -3,23 +3,35 @@
.\" The following requests are required for all man pages.
.\"
.\" Remove `\&' from the line below.
-.Dd $\&Mdocdate$
-.Dt NAME SECTION#
+.Dd $Mdocdate$
+.Dt mdocml 1
.Os
.Sh NAME
-.Nm program
-.Nd one line about what it does
+.Nm mdocml
+.Nd compile manpage source into mark-up language
.Sh SYNOPSIS
-.\" For a program: program [-abc] file ...
-.Nm program
-.Op Fl abc
-.Ar
+.Nm mdocml
+.Op Fl o Ar outfile
+.Op Ar infile
.Sh DESCRIPTION
The
.Nm
-utility processes files ...
-something
-something.
+utility compiles manpage source into a mark-up language. Its arguments
+are as follows:
+.Bl -tag -width "-o outfile"
+.It Fl o Ar outfile
+Place output in
+.Ar outfile ,
+which may be
+.Qq -
+for standard output. The default is standard output.
+.It Ar infile
+Read input from
+.Ar infile ,
+which may be
+.Qq -
+for standard input. The default is standard input.
+.El
.\" 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
diff --git a/mdocml.c b/mdocml.c
index 2620a31e..dbcb88d0 100644
--- a/mdocml.c
+++ b/mdocml.c
@@ -32,40 +32,14 @@
#define BUFFER_IN_DEF BUFSIZ
#define BUFFER_OUT_DEF BUFSIZ
-#define BUFFER_LINE BUFSIZ
-
-struct md_rbuf {
- int fd;
- const char *name;
- char *buf;
- size_t bufsz;
- size_t line;
-};
-
-struct md_mbuf {
- int fd;
- const char *name;
- char *buf;
- size_t bufsz;
- size_t pos;
-};
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_mbuf *, struct md_rbuf *);
-static int md_run(struct md_mbuf *, struct md_rbuf *);
-static int md_line(struct md_mbuf *, const struct md_rbuf *,
- const char *, size_t);
-
-static ssize_t md_buf_fill(struct md_rbuf *);
-static int md_buf_flush(struct md_mbuf *);
-
-static int md_buf_putchar(struct md_mbuf *, char);
-static int md_buf_puts(struct md_mbuf *,
- const char *, size_t);
-
+static int begin_io(const char *, const char *);
+static int leave_io(const struct md_mbuf *,
+ const struct md_rbuf *, int);
+static int begin_bufs(struct md_mbuf *, struct md_rbuf *);
+static int leave_bufs(const struct md_mbuf *,
+ const struct md_rbuf *, int);
int
main(int argc, char *argv[])
@@ -76,7 +50,7 @@ main(int argc, char *argv[])
extern char *optarg;
extern int optind;
- out = NULL;
+ out = in = NULL;
while (-1 != (c = getopt(argc, argv, "o:")))
switch (c) {
@@ -89,87 +63,93 @@ main(int argc, char *argv[])
}
argv += optind;
- if (1 != (argc -= optind)) {
- usage();
- return(1);
- }
+ argc -= optind;
- argc--;
- in = *argv++;
+ if (1 == argc)
+ in = *argv++;
- return(md_begin(out, in));
+ return(begin_io(out ? out : "-", in ? in : "-"));
}
static int
-md_begin(const char *out, const char *in)
+leave_io(const struct md_mbuf *out,
+ const struct md_rbuf *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);
}
static int
-md_begin_io(const char *out, const char *in)
+begin_io(const char *out, const char *in)
{
- int c;
- struct md_rbuf fin;
- struct md_mbuf fout;
+ struct md_rbuf fi;
+ struct md_mbuf fo;
+
+#define FI_FL O_RDONLY
+#define FO_FL O_WRONLY|O_CREAT|O_TRUNC
assert(out);
assert(in);
- /* TODO: accept "-" as both input and output. */
+ bzero(&fi, sizeof(struct md_rbuf));
+ bzero(&fo, sizeof(struct md_mbuf));
- 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_TRUNC, 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(&fo, &fi)));
+}
- if (-1 == close(fin.fd)) {
- warn("%s", in);
- c = 1;
- }
- if (-1 == close(fout.fd)) {
- warn("%s", out);
- c = 1;
- }
+static int
+leave_bufs(const struct md_mbuf *out,
+ const struct md_rbuf *in, int c)
+{
+ assert(out);
+ assert(in);
+ if (out->buf)
+ free(out->buf);
+ if (in->buf)
+ free(in->buf);
return(c);
}
static int
-md_begin_bufs(struct md_mbuf *out, struct md_rbuf *in)
+begin_bufs(struct md_mbuf *out, struct md_rbuf *in)
{
struct stat stin, stout;
- int c;
assert(in);
assert(out);
@@ -183,169 +163,17 @@ md_begin_bufs(struct md_mbuf *out, struct md_rbuf *in)
}
in->bufsz = MAX(stin.st_blksize, BUFFER_IN_DEF);
-
out->bufsz = MAX(stout.st_blksize, BUFFER_OUT_DEF);
if (NULL == (in->buf = malloc(in->bufsz))) {
warn("malloc");
- return(1);
+ return(leave_bufs(out, in, 1));
} else if (NULL == (out->buf = malloc(out->bufsz))) {
warn("malloc");
- free(in->buf);
- return(1);
- }
-
- c = md_run(out, in);
-
- free(in->buf);
- free(out->buf);
-
- return(c);
-}
-
-
-static ssize_t
-md_buf_fill(struct md_rbuf *in)
-{
- ssize_t ssz;
-
- assert(in);
- assert(in->buf);
- assert(in->bufsz > 0);
- assert(in->name);
-
- if (-1 == (ssz = read(in->fd, in->buf, in->bufsz)))
- warn("%s", in->name);
-
- return(ssz);
-}
-
-
-static int
-md_run(struct md_mbuf *out, struct md_rbuf *in)
-{
- ssize_t sz, i;
- char line[BUFFER_LINE];
- size_t pos;
-
- assert(in);
- assert(out);
-
- out->pos = 0;
- in->line = 1;
-
- /* 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 < BUFFER_LINE) {
- /* LINTED */
- line[pos++] = in->buf[i];
- continue;
- }
-
- warnx("%s: line %zu too long",
- in->name, in->line);
- return(1);
- }
- }
-
- if (0 != pos && md_line(out, in, line, pos))
- return(1);
-
- return(md_buf_flush(out) ? 0 : 1);
-}
-
-
-static int
-md_buf_flush(struct md_mbuf *buf)
-{
- ssize_t sz;
-
- assert(buf);
- assert(buf->buf);
- assert(buf->name);
-
- if (0 == buf->pos)
- return(1);
-
- sz = write(buf->fd, buf->buf, buf->pos);
-
- if (-1 == sz) {
- warn("%s", buf->name);
- return(0);
- } else if ((size_t)sz != buf->pos) {
- warnx("%s: short write", buf->name);
- return(0);
- }
-
- buf->pos = 0;
- return(1);
-}
-
-
-static int
-md_buf_putchar(struct md_mbuf *buf, char c)
-{
- return(md_buf_puts(buf, &c, 1));
-}
-
-
-static int
-md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)
-{
- size_t ssz;
-
- assert(p);
- assert(buf);
- assert(buf->buf);
-
- while (buf->pos + sz > buf->bufsz) {
- ssz = buf->bufsz - buf->pos;
- (void)memcpy(buf->buf + buf->pos, p, ssz);
- p += ssz;
- sz -= ssz;
- buf->pos += ssz;
-
- if ( ! md_buf_flush(buf))
- return(0);
+ return(leave_bufs(out, in, 1));
}
- (void)memcpy(buf->buf + buf->pos, p, sz);
- buf->pos += sz;
- return(1);
-}
-
-
-static int
-md_line(struct md_mbuf *out, const struct md_rbuf *in,
- const char *buf, size_t sz)
-{
-
- /* FIXME: this is just a placeholder function. */
-
- assert(buf);
- assert(out);
- assert(in);
-
- if ( ! md_buf_puts(out, buf, sz))
- return(1);
- if ( ! md_buf_putchar(out, '\n'))
- return(1);
-
- return(0);
+ return(leave_bufs(out, in, md_run(MD_DUMMY, out, in)));
}
@@ -354,5 +182,5 @@ usage(void)
{
extern char *__progname;
- (void)printf("usage: %s [-o outfile] infile\n", __progname);
+ (void)printf("usage: %s [-o outfile] [infile]\n", __progname);
}