diff options
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | action.c | 2 | ||||
-rw-r--r-- | mdocml.c | 8 | ||||
-rw-r--r-- | term.c | 360 | ||||
-rw-r--r-- | tree.c | 131 |
5 files changed, 506 insertions, 9 deletions
@@ -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 @@ -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); @@ -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); @@ -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); +} + + @@ -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); +} |