summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile14
-rw-r--r--action.c2
-rw-r--r--mdocml.c8
-rw-r--r--term.c360
-rw-r--r--tree.c131
5 files changed, 506 insertions, 9 deletions
diff --git a/Makefile b/Makefile
index a5debd89..5458a3fc 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ CFLAGS += -W -Wall -Wno-unused-parameter -g
LIBLNS = macro.ln mdoc.ln hash.ln strings.ln xstd.ln argv.ln \
validate.ln action.ln
-BINLNS = mdocml.ln
+BINLNS = mdocml.ln term.ln tree.ln
LNS = $(LIBLNS) $(BINLNS)
@@ -16,7 +16,7 @@ LIBS = libmdoc.a
LIBOBJS = macro.o mdoc.o hash.o strings.o xstd.o argv.o \
validate.o action.o
-BINOBJS = mdocml.o
+BINOBJS = mdocml.o term.o tree.o
OBJS = $(LIBOBJS) $(BINOBJS)
@@ -132,6 +132,14 @@ macro.ln: macro.c private.h
macro.o: macro.c private.h
+tree.ln: tree.c mdoc.h
+
+tree.o: tree.c mdoc.h
+
+term.ln: term.c mdoc.h
+
+term.o: term.c mdoc.h
+
strings.ln: strings.c private.h
strings.o: strings.c private.h
@@ -198,5 +206,5 @@ libmdoc.a: $(LIBOBJS)
$(AR) rs $@ $(LIBOBJS)
mdocml: $(BINOBJS) libmdoc.a
- $(CC) $(CFLAGS) -o $@ $(BINOBJS) libmdoc.a
+ $(CC) $(CFLAGS) -o $@ $(BINOBJS) libmdoc.a -lcurses
diff --git a/action.c b/action.c
index e7ece6cd..851910c4 100644
--- a/action.c
+++ b/action.c
@@ -243,7 +243,7 @@ post_dt(struct mdoc *mdoc)
}
if (NULL == mdoc->meta.title)
- mdoc->meta.title = xstrdup("untitled");
+ mdoc->meta.title = xstrdup("UNTITLED");
mdoc_msg(mdoc, "title: %s", mdoc->meta.title);
diff --git a/mdocml.c b/mdocml.c
index f76ee0b5..8c77b1e2 100644
--- a/mdocml.c
+++ b/mdocml.c
@@ -224,6 +224,8 @@ buf_begin(struct md_parse *p)
static int
parse_leave(struct md_parse *p, int code)
{
+ extern int termprint(const struct mdoc_node *,
+ const struct mdoc_meta *);
if (NULL == p->mdoc)
return(code);
@@ -231,13 +233,9 @@ parse_leave(struct md_parse *p, int code)
if ( ! mdoc_endparse(p->mdoc))
code = 0;
-#if 0
/* TODO */
- if (code && ! mdoc_write(p->out, mdoc_node(p->mdoc))) {
- warnx("%s: write error", p->out);
+ if (code && ! termprint(mdoc_node(p->mdoc), mdoc_meta(p->mdoc)))
code = 0;
- }
-#endif
mdoc_free(p->mdoc);
return(code);
diff --git a/term.c b/term.c
new file mode 100644
index 00000000..80a6a202
--- /dev/null
+++ b/term.c
@@ -0,0 +1,360 @@
+/* $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 <assert.h>
+#include <curses.h>
+#include <err.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <term.h>
+#include <unistd.h>
+
+#include "mdoc.h"
+
+
+static int termprint_r(size_t, size_t,
+ const struct mdoc_node *);
+static void termprint_head(size_t,
+ const struct mdoc_meta *);
+static void termprint_tail(size_t,
+ const struct mdoc_meta *);
+
+static char *arch2a(enum mdoc_arch);
+static char *vol2a(enum mdoc_vol);
+static char *msec2a(enum mdoc_msec);
+
+static size_t ttitle2a(char *, enum mdoc_vol, enum mdoc_msec,
+ enum mdoc_arch, size_t);
+
+
+static char *
+arch2a(enum mdoc_arch arch)
+{
+
+ switch (arch) {
+ case (ARCH_alpha):
+ return("Alpha");
+ case (ARCH_amd64):
+ return("AMD64");
+ case (ARCH_amiga):
+ return("Amiga");
+ case (ARCH_arc):
+ return("ARC");
+ case (ARCH_arm):
+ return("ARM");
+ case (ARCH_armish):
+ return("ARMISH");
+ case (ARCH_aviion):
+ return("AViion");
+ case (ARCH_hp300):
+ return("HP300");
+ case (ARCH_hppa):
+ return("HPPA");
+ case (ARCH_hppa64):
+ return("HPPA64");
+ case (ARCH_i386):
+ return("i386");
+ case (ARCH_landisk):
+ return("LANDISK");
+ case (ARCH_luna88k):
+ return("Luna88k");
+ case (ARCH_mac68k):
+ return("Mac68k");
+ case (ARCH_macppc):
+ return("MacPPC");
+ case (ARCH_mvme68k):
+ return("MVME68k");
+ case (ARCH_mvme88k):
+ return("MVME88k");
+ case (ARCH_mvmeppc):
+ return("MVMEPPC");
+ case (ARCH_pmax):
+ return("PMAX");
+ case (ARCH_sgi):
+ return("SGI");
+ case (ARCH_socppc):
+ return("SOCPPC");
+ case (ARCH_sparc):
+ return("SPARC");
+ case (ARCH_sparc64):
+ return("SPARC64");
+ case (ARCH_sun3):
+ return("Sun3");
+ case (ARCH_vax):
+ return("VAX");
+ case (ARCH_zaurus):
+ return("Zaurus");
+ default:
+ break;
+ }
+
+ return(NULL);
+}
+
+
+static char *
+vol2a(enum mdoc_vol vol)
+{
+
+ switch (vol) {
+ case (VOL_AMD):
+ return("OpenBSD Ancestral Manual Documents");
+ case (VOL_IND):
+ return("OpenBSD Manual Master Index");
+ case (VOL_KM):
+ return("OpenBSD Kernel Manual");
+ case (VOL_LOCAL):
+ return("OpenBSD Local Manual");
+ case (VOL_PRM):
+ return("OpenBSD Programmer's Manual");
+ case (VOL_PS1):
+ return("OpenBSD Programmer's Supplementary Documents");
+ case (VOL_SMM):
+ return("OpenBSD System Manager's Manual");
+ case (VOL_URM):
+ return("OpenBSD Reference Manual");
+ case (VOL_USD):
+ return("OpenBSD User's Supplementary Documents");
+ default:
+ break;
+ }
+
+ return(NULL);
+}
+
+
+static char *
+msec2a(enum mdoc_msec msec)
+{
+
+ switch (msec) {
+ case(MSEC_1):
+ return("1");
+ case(MSEC_2):
+ return("2");
+ case(MSEC_3):
+ return("3");
+ case(MSEC_3f):
+ return("3f");
+ case(MSEC_3p):
+ return("3p");
+ case(MSEC_4):
+ return("4");
+ case(MSEC_5):
+ return("5");
+ case(MSEC_6):
+ return("6");
+ case(MSEC_7):
+ return("7");
+ case(MSEC_8):
+ return("8");
+ case(MSEC_9):
+ return("9");
+ case(MSEC_X11):
+ return("X11");
+ case(MSEC_X11R6):
+ return("X11R6");
+ case(MSEC_local):
+ return("local");
+ case(MSEC_n):
+ return("n");
+ case(MSEC_unass):
+ /* FALLTHROUGH */
+ case(MSEC_draft):
+ return("draft");
+ case(MSEC_paper):
+ return("paper");
+ default:
+ break;
+ }
+ return(NULL);
+}
+
+
+static size_t
+ttitle2a(char *dst, enum mdoc_vol vol, enum mdoc_msec msec,
+ enum mdoc_arch arch, size_t sz)
+{
+ char *p;
+ size_t ssz;
+
+ if (NULL == (p = vol2a(vol)))
+ switch (msec) {
+ case (MSEC_1):
+ /* FALLTHROUGH */
+ case (MSEC_6):
+ /* FALLTHROUGH */
+ case (MSEC_7):
+ p = vol2a(VOL_URM);
+ break;
+ case (MSEC_8):
+ p = vol2a(VOL_SMM);
+ break;
+ case (MSEC_2):
+ /* FALLTHROUGH */
+ case (MSEC_3):
+ /* FALLTHROUGH */
+ case (MSEC_4):
+ /* FALLTHROUGH */
+ case (MSEC_5):
+ p = vol2a(VOL_PRM);
+ break;
+ case (MSEC_9):
+ p = vol2a(VOL_KM);
+ break;
+ default:
+ /* FIXME: capitalise. */
+ if (NULL == (p = msec2a(msec)))
+ p = msec2a(MSEC_local);
+ break;
+ }
+ assert(p);
+
+ if ((ssz = strlcpy(dst, p, sz)) >= sz)
+ return(ssz);
+
+ if ((p = arch2a(arch))) {
+ if ((ssz = strlcat(dst, " (", sz)) >= sz)
+ return(ssz);
+ if ((ssz = strlcat(dst, p, sz)) >= sz)
+ return(ssz);
+ if ((ssz = strlcat(dst, ")", sz)) >= sz)
+ return(ssz);
+ }
+
+ return(ssz);
+}
+
+
+static int
+termprint_r(size_t cols, size_t indent, const struct mdoc_node *node)
+{
+
+ return(1);
+}
+
+
+static void
+termprint_tail(size_t cols, const struct mdoc_meta *meta)
+{
+ struct tm *tm;
+ char *buf, *os;
+ size_t sz, osz, ssz, i;
+
+ if (NULL == (buf = malloc(cols)))
+ err(1, "malloc");
+ if (NULL == (os = malloc(cols)))
+ err(1, "malloc");
+
+ tm = localtime(&meta->date);
+ if (NULL == strftime(buf, cols, "%B %d, %Y", tm))
+ err(1, "strftime");
+
+ osz = strlcpy(os, meta->os, cols);
+
+ sz = strlen(buf);
+ ssz = sz + osz + 1;
+
+ if (ssz > cols) {
+ ssz -= cols;
+ assert(ssz <= osz);
+ os[osz - ssz] = 0;
+ ssz = 1;
+ } else
+ ssz = cols - ssz + 1;
+
+ printf("%s", os);
+ for (i = 0; i < ssz; i++)
+ printf(" ");
+
+ printf("%s\n", buf);
+
+ free(buf);
+ free(os);
+}
+
+
+static void
+termprint_head(size_t cols, const struct mdoc_meta *meta)
+{
+ char *msec, *buf, *title;
+ size_t ssz, tsz, ttsz, i;
+
+ if (NULL == (buf = malloc(cols)))
+ err(1, "malloc");
+ if (NULL == (title = malloc(cols)))
+ err(1, "malloc");
+
+ /* Format the manual page header. */
+
+ tsz = ttitle2a(buf, meta->vol, meta->msec, meta->arch, cols);
+ ttsz = strlcpy(title, meta->title, cols);
+
+ if (NULL == (msec = msec2a(meta->msec)))
+ msec = "";
+
+ ssz = (2 * (ttsz + 2 + strlen(msec))) + tsz + 2;
+
+ if (ssz > cols) {
+ if ((ssz -= cols) % 2)
+ ssz++;
+ ssz /= 2;
+
+ assert(ssz <= ttsz);
+ title[ttsz - ssz] = 0;
+ ssz = 1;
+ } else
+ ssz = ((cols - ssz) / 2) + 1;
+
+ printf("%s(%s)", title, msec);
+
+ for (i = 0; i < ssz; i++)
+ printf(" ");
+
+ printf("%s", buf);
+
+ for (i = 0; i < ssz; i++)
+ printf(" ");
+
+ printf("%s(%s)\n\n", title, msec);
+
+ free(title);
+ free(buf);
+}
+
+
+int
+termprint(const struct mdoc_node *node,
+ const struct mdoc_meta *meta)
+{
+ size_t cols;
+
+ if (ERR == setupterm(NULL, STDOUT_FILENO, NULL))
+ return(0);
+
+ cols = columns < 60 ? 60 : (size_t)columns;
+
+ termprint_head(cols, meta);
+ if ( ! termprint_r(cols, 0, node))
+ return(0);
+ termprint_tail(cols, meta);
+ return(1);
+}
+
+
diff --git a/tree.c b/tree.c
new file mode 100644
index 00000000..4dec0f3c
--- /dev/null
+++ b/tree.c
@@ -0,0 +1,131 @@
+/* $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 <stdio.h>
+
+#include "mdoc.h"
+
+#define xprintf (void)printf
+
+static void treeprint_r(const struct mdoc_node *, int);
+
+static void
+treeprint_r(const struct mdoc_node *n, int indent)
+{
+ const char *p, *t;
+ int i, j;
+ size_t argc, sz;
+ char **params;
+ struct mdoc_arg *argv;
+
+ argv = NULL;
+ argc = sz = 0;
+ params = NULL;
+
+ switch (n->type) {
+ case (MDOC_ROOT):
+ t = "root";
+ break;
+ case (MDOC_BLOCK):
+ t = "block";
+ break;
+ case (MDOC_HEAD):
+ t = "block-head";
+ break;
+ case (MDOC_BODY):
+ t = "block-body";
+ break;
+ case (MDOC_TAIL):
+ t = "block-tail";
+ break;
+ case (MDOC_ELEM):
+ t = "elem";
+ break;
+ case (MDOC_TEXT):
+ t = "text";
+ break;
+ default:
+ abort();
+ /* NOTREACHED */
+ }
+
+ switch (n->type) {
+ case (MDOC_TEXT):
+ p = n->data.text.string;
+ break;
+ case (MDOC_BODY):
+ p = mdoc_macronames[n->tok];
+ break;
+ case (MDOC_HEAD):
+ p = mdoc_macronames[n->tok];
+ break;
+ case (MDOC_TAIL):
+ p = mdoc_macronames[n->tok];
+ break;
+ case (MDOC_ELEM):
+ p = mdoc_macronames[n->tok];
+ argv = n->data.elem.argv;
+ argc = n->data.elem.argc;
+ break;
+ case (MDOC_BLOCK):
+ p = mdoc_macronames[n->tok];
+ argv = n->data.block.argv;
+ argc = n->data.block.argc;
+ break;
+ case (MDOC_ROOT):
+ p = "root";
+ break;
+ default:
+ abort();
+ /* NOTREACHED */
+ }
+
+ for (i = 0; i < indent; i++)
+ xprintf(" ");
+ xprintf("%s (%s)", p, t);
+
+ for (i = 0; i < (int)argc; i++) {
+ xprintf(" -%s", mdoc_argnames[argv[i].arg]);
+ if (argv[i].sz > 0)
+ xprintf(" [");
+ for (j = 0; j < (int)argv[i].sz; j++)
+ xprintf(" [%s]", argv[i].value[j]);
+ if (argv[i].sz > 0)
+ xprintf(" ]");
+ }
+
+ for (i = 0; i < (int)sz; i++)
+ xprintf(" [%s]", params[i]);
+
+ xprintf(" %d:%d\n", n->line, n->pos);
+
+ if (n->child)
+ treeprint_r(n->child, indent + 1);
+ if (n->next)
+ treeprint_r(n->next, indent);
+}
+
+
+int
+treeprint(const struct mdoc_node *node)
+{
+
+ treeprint_r(node, 0);
+ return(1);
+}