summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--mdocml.121
-rw-r--r--mdocml.c4
-rw-r--r--private.h5
-rw-r--r--strings.c155
-rw-r--r--term.c835
-rw-r--r--tree.c4
7 files changed, 811 insertions, 217 deletions
diff --git a/Makefile b/Makefile
index 5458a3fc..f9adea02 100644
--- a/Makefile
+++ b/Makefile
@@ -136,9 +136,9 @@ tree.ln: tree.c mdoc.h
tree.o: tree.c mdoc.h
-term.ln: term.c mdoc.h
+term.ln: term.c private.h
-term.o: term.c mdoc.h
+term.o: term.c private.h
strings.ln: strings.c private.h
diff --git a/mdocml.1 b/mdocml.1
index 810d47f2..83171125 100644
--- a/mdocml.1
+++ b/mdocml.1
@@ -2,17 +2,17 @@
.Dd $Mdocdate$
.Dt mdocml 1
.Os
-.\"
+.\" SECTION
.Sh NAME
.Nm mdocml
.Nd mdoc macro compiler
-.\"
+.\" SECTION
.Sh SYNOPSIS
.Nm mdocml
.Op Fl v
.Op Fl W Ns Ar err...
.Op Ar infile
-.\"
+.\" SECTION
.Sh DESCRIPTION
The
.Nm
@@ -44,44 +44,47 @@ which may be
.Dq \-
for stdin.
.El
+.\" PARAGRAPH
.Pp
Parsing and validation rules are drawn entirely from the
.Xr mdoc 7
and
.Xr mdoc.samples 7
manuals.
+.\" PARAGRAPH
.Pp
By default,
.Nm
reads from stdin, writes messages to stdout, and writes errors and
warnings to stderr.
+.\" PARAGRAPH
.Pp
.Ex -std mdocml
+.\" PARAGRAPH
.Pp
.Nm
is
.Ud
-.\"
+.\" SECTION
.Sh EXAMPLES
To validate this manual page:
+.\" PARAGRAPH
.Pp
.D1 % mdocml \-Wall,error mdocml.1
-.\"
+.\" SECTION
.Sh SEE ALSO
.Xr groff 1 ,
.Xr mdoc.samples 7 ,
.Xr mdoc 7 ,
.Xr mdoc 3
-.\" .Sh STANDARDS
-.\" .Sh HISTORY
+.\"
.Sh AUTHORS
The
.Nm
utility was written by
.An Kristaps Dzonsons Aq kristaps@kth.se .
-.\"
+.\" SECTION
.Sh CAVEATS
See
.Xr mdoc 3
for a list of bugs, caveats, and incomplete macros.
-.\" .Sh BUGS
diff --git a/mdocml.c b/mdocml.c
index 8c77b1e2..39e6bc58 100644
--- a/mdocml.c
+++ b/mdocml.c
@@ -226,6 +226,8 @@ parse_leave(struct md_parse *p, int code)
{
extern int termprint(const struct mdoc_node *,
const struct mdoc_meta *);
+ /*extern int treeprint(const struct mdoc_node *,
+ const struct mdoc_meta *);*/
if (NULL == p->mdoc)
return(code);
@@ -236,6 +238,8 @@ parse_leave(struct md_parse *p, int code)
/* TODO */
if (code && ! termprint(mdoc_node(p->mdoc), mdoc_meta(p->mdoc)))
code = 0;
+ /*if (code && ! treeprint(mdoc_node(p->mdoc), mdoc_meta(p->mdoc)))
+ code = 0;*/
mdoc_free(p->mdoc);
return(code);
diff --git a/private.h b/private.h
index b3ec0fa3..af32c542 100644
--- a/private.h
+++ b/private.h
@@ -132,6 +132,11 @@ enum mdoc_arch mdoc_atoarch(const char *);
enum mdoc_att mdoc_atoatt(const char *);
time_t mdoc_atotime(const char *);
+/* FIXME: these three are only for output channels. */
+char *mdoc_arch2a(enum mdoc_arch);
+char *mdoc_vol2a(enum mdoc_vol);
+char *mdoc_msec2a(enum mdoc_msec);
+
char *mdoc_type2a(enum mdoc_type);
char *mdoc_node2a(struct mdoc_node *);
diff --git a/strings.c b/strings.c
index c07e6909..760e89f0 100644
--- a/strings.c
+++ b/strings.c
@@ -334,3 +334,158 @@ mdoc_type2a(enum mdoc_type type)
abort();
/* NOTREACHED */
}
+
+
+char *
+mdoc_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");
+ case (ARCH_DEFAULT):
+ return(NULL);
+ default:
+ break;
+ }
+
+ abort();
+ /* NOTREACHED */
+}
+
+
+char *
+mdoc_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");
+ case (VOL_DEFAULT):
+ return(NULL);
+ default:
+ break;
+ }
+
+ abort();
+ /* NOTREACHED */
+}
+
+
+char *
+mdoc_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");
+ case(MSEC_DEFAULT):
+ return(NULL);
+ default:
+ break;
+ }
+
+ abort();
+ /* NOTREACHED */
+}
+
diff --git a/term.c b/term.c
index 80a6a202..9b97736e 100644
--- a/term.c
+++ b/term.c
@@ -17,6 +17,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
+#include <ctype.h>
#include <curses.h>
#include <err.h>
#include <stdlib.h>
@@ -25,265 +26,639 @@
#include <term.h>
#include <unistd.h>
-#include "mdoc.h"
-
+#include "private.h"
+
+
+enum termesc {
+ ESC_CLEAR,
+ ESC_BOLD,
+ ESC_UNDERLINE
+};
+
+struct termp {
+ size_t maxvisible;
+ size_t maxcols;
+ size_t indent;
+ size_t col;
+ int flags;
+#define TERMP_BOLD (1 << 0)
+#define TERMP_UNDERLINE (1 << 1)
+#define TERMP_NOSPACE (1 << 2)
+ char *buf;
+};
+
+struct termact {
+ int (*pre)(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+ int (*post)(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+};
-static int termprint_r(size_t, size_t,
+static void termprint_r(struct termp *,
+ const struct mdoc_meta *,
const struct mdoc_node *);
-static void termprint_head(size_t,
+static void termprint_header(struct termp *,
const struct mdoc_meta *);
-static void termprint_tail(size_t,
+static void termprint_footer(struct termp *,
const struct mdoc_meta *);
-static char *arch2a(enum mdoc_arch);
-static char *vol2a(enum mdoc_vol);
-static char *msec2a(enum mdoc_msec);
+static void newln(struct termp *);
+static void vspace(struct termp *);
+static void pword(struct termp *, const char *, size_t);
+static void word(struct termp *, const char *);
+
+static int termp_it_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_ns_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_pp_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_fl_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_op_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_op_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_bl_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_sh_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_sh_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_nd_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_bold_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_under_pre(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_bold_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+static int termp_under_post(struct termp *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+
+const struct termact termacts[MDOC_MAX] = {
+ { NULL, NULL }, /* \" */
+ { NULL, NULL }, /* Dd */
+ { NULL, NULL }, /* Dt */
+ { NULL, NULL }, /* Os */
+ { termp_sh_pre, termp_sh_post }, /* Sh */
+ { NULL, NULL }, /* Ss */
+ { termp_pp_pre, NULL }, /* Pp */
+ { NULL, NULL }, /* D1 */
+ { NULL, NULL }, /* Dl */
+ { NULL, NULL }, /* Bd */
+ { NULL, NULL }, /* Ed */
+ { NULL, termp_bl_post }, /* Bl */
+ { NULL, NULL }, /* El */
+ { termp_it_pre, NULL }, /* It */
+ { NULL, NULL }, /* Ad */
+ { NULL, NULL }, /* An */
+ { termp_under_pre, termp_under_post }, /* Ar */
+ { NULL, NULL }, /* Cd */
+ { NULL, NULL }, /* Cm */
+ { NULL, NULL }, /* Dv */
+ { NULL, NULL }, /* Er */
+ { NULL, NULL }, /* Ev */
+ { NULL, NULL }, /* Ex */
+ { NULL, NULL }, /* Fa */
+ { NULL, NULL }, /* Fd */
+ { termp_fl_pre, termp_bold_post }, /* Fl */
+ { NULL, NULL }, /* Fn */
+ { NULL, NULL }, /* Ft */
+ { NULL, NULL }, /* Ic */
+ { NULL, NULL }, /* In */
+ { NULL, NULL }, /* Li */
+ { termp_nd_pre, NULL }, /* Nd */
+ { termp_bold_pre, termp_bold_post }, /* Nm */
+ { termp_op_pre, termp_op_post }, /* Op */
+ { NULL, NULL }, /* Ot */
+ { NULL, NULL }, /* Pa */
+ { NULL, NULL }, /* Rv */
+ { NULL, NULL }, /* St */
+ { NULL, NULL }, /* Va */
+ { NULL, NULL }, /* Vt */
+ { NULL, NULL }, /* Xr */
+ { NULL, NULL }, /* %A */
+ { NULL, NULL }, /* %B */
+ { NULL, NULL }, /* %D */
+ { NULL, NULL }, /* %I */
+ { NULL, NULL }, /* %J */
+ { NULL, NULL }, /* %N */
+ { NULL, NULL }, /* %O */
+ { NULL, NULL }, /* %P */
+ { NULL, NULL }, /* %R */
+ { NULL, NULL }, /* %T */
+ { NULL, NULL }, /* %V */
+ { NULL, NULL }, /* Ac */
+ { NULL, NULL }, /* Ao */
+ { NULL, NULL }, /* Aq */
+ { NULL, NULL }, /* At */
+ { NULL, NULL }, /* Bc */
+ { NULL, NULL }, /* Bf */
+ { NULL, NULL }, /* Bo */
+ { NULL, NULL }, /* Bq */
+ { NULL, NULL }, /* Bsx */
+ { NULL, NULL }, /* Bx */
+ { NULL, NULL }, /* Db */
+ { NULL, NULL }, /* Dc */
+ { NULL, NULL }, /* Do */
+ { NULL, NULL }, /* Dq */
+ { NULL, NULL }, /* Ec */
+ { NULL, NULL }, /* Ef */
+ { NULL, NULL }, /* Em */
+ { NULL, NULL }, /* Eo */
+ { NULL, NULL }, /* Fx */
+ { NULL, NULL }, /* Ms */
+ { NULL, NULL }, /* No */
+ { termp_ns_pre, NULL }, /* Ns */
+ { NULL, NULL }, /* Nx */
+ { NULL, NULL }, /* Ox */
+ { NULL, NULL }, /* Pc */
+ { NULL, NULL }, /* Pf */
+ { NULL, NULL }, /* Po */
+ { NULL, NULL }, /* Pq */
+ { NULL, NULL }, /* Qc */
+ { NULL, NULL }, /* Ql */
+ { NULL, NULL }, /* Qo */
+ { NULL, NULL }, /* Qq */
+ { NULL, NULL }, /* Re */
+ { NULL, NULL }, /* Rs */
+ { NULL, NULL }, /* Sc */
+ { NULL, NULL }, /* So */
+ { NULL, NULL }, /* Sq */
+ { NULL, NULL }, /* Sm */
+ { NULL, NULL }, /* Sx */
+ { NULL, NULL }, /* Sy */
+ { NULL, NULL }, /* Tn */
+ { NULL, NULL }, /* Ux */
+ { NULL, NULL }, /* Xc */
+ { NULL, NULL }, /* Xo */
+ { NULL, NULL }, /* Fo */
+ { NULL, NULL }, /* Fc */
+ { NULL, NULL }, /* Oo */
+ { NULL, NULL }, /* Oc */
+ { NULL, NULL }, /* Bk */
+ { NULL, NULL }, /* Ek */
+ { NULL, NULL }, /* Bt */
+ { NULL, NULL }, /* Hf */
+ { NULL, NULL }, /* Fr */
+ { NULL, NULL }, /* Ud */
+};
+
+
+static void
+flush(struct termp *p)
+{
+ size_t i, j, vsz, vis, maxvis;
+
+ maxvis = p->maxvisible - (p->indent * 4);
+ vis = 0;
+
+ for (j = 0; j < (p->indent * 4); j++)
+ putchar(' ');
+
+ for (i = 0; i < p->col; i++) {
+ for (j = i, vsz = 0; j < p->col; j++) {
+ if (isspace(p->buf[j]))
+ break;
+ else if (27 == p->buf[j]) {
+ assert(j + 4 <= p->col);
+ j += 3;
+ } else
+ vsz++;
+ }
+ assert(vsz > 0);
+
+ if (vis && vis + vsz >= maxvis) {
+ putchar('\n');
+ for (j = 0; j < (p->indent * 4); j++)
+ putchar(' ');
+ vis = 0;
+ }
+
+ for ( ; i < p->col; i++) {
+ if (isspace(p->buf[i]))
+ break;
+ putchar(p->buf[i]);
+ }
+ vis += vsz;
+ if (i < p->col) {
+ putchar(' ');
+ vis++;
+ }
+ }
+
+ putchar('\n');
+ p->col = 0;
+}
+
+
+static void
+newln(struct termp *p)
+{
-static size_t ttitle2a(char *, enum mdoc_vol, enum mdoc_msec,
- enum mdoc_arch, size_t);
+ p->flags |= TERMP_NOSPACE;
+ if (0 == p->col)
+ return;
+ flush(p);
+}
-static char *
-arch2a(enum mdoc_arch arch)
+static void
+vspace(struct termp *p)
{
- 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:
+ newln(p);
+ putchar('\n');
+}
+
+
+static void
+chara(struct termp *p, char c)
+{
+
+ if (p->col + 1 >= p->maxcols)
+ errx(1, "line overrun");
+
+ p->buf[(p->col)++] = c;
+}
+
+
+static void
+escape(struct termp *p, enum termesc esc)
+{
+
+ if (p->col + 4 >= p->maxcols)
+ errx(1, "line overrun");
+
+ p->buf[(p->col)++] = 27;
+ p->buf[(p->col)++] = '[';
+ switch (esc) {
+ case (ESC_CLEAR):
+ p->buf[(p->col)++] = '0';
+ break;
+ case (ESC_BOLD):
+ p->buf[(p->col)++] = '1';
+ break;
+ case (ESC_UNDERLINE):
+ p->buf[(p->col)++] = '4';
break;
+ default:
+ abort();
+ /* NOTREACHED */
}
+ p->buf[(p->col)++] = 'm';
+}
+
+
+static void
+pword(struct termp *p, const char *word, size_t len)
+{
+ size_t i;
+
+ assert(len > 0);
- return(NULL);
+ if ( ! (p->flags & TERMP_NOSPACE))
+ chara(p, ' ');
+
+ p->flags &= ~TERMP_NOSPACE;
+
+ if (p->flags & TERMP_BOLD)
+ escape(p, ESC_BOLD);
+ if (p->flags & TERMP_UNDERLINE)
+ escape(p, ESC_UNDERLINE);
+
+ for (i = 0; i < len; i++)
+ chara(p, word[i]);
+
+ if (p->flags & TERMP_BOLD ||
+ p->flags & TERMP_UNDERLINE)
+ escape(p, ESC_CLEAR);
}
-static char *
-vol2a(enum mdoc_vol vol)
+static void
+word(struct termp *p, const char *word)
{
+ size_t i, j, len;
+
+ /* TODO: delimiters? */
- 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");
+ len = strlen(word);
+ assert(len > 0);
+
+ for (j = i = 0; i < len; i++) {
+ if ( ! isspace(word[i])) {
+ j++;
+ continue;
+ }
+ if (0 == j)
+ continue;
+ assert(i >= j);
+ pword(p, &word[i - j], j);
+ j = 0;
+ }
+ if (j > 0) {
+ assert(i >= j);
+ pword(p, &word[i - j], j);
+ }
+}
+
+
+static int
+termp_it_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ switch (node->type) {
+ case (MDOC_HEAD):
+ /* TODO: only print one, if compat. */
+ vspace(p);
+ break;
default:
break;
}
+ return(1);
+}
+
+
+static int
+termp_bold_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ p->flags &= ~TERMP_BOLD;
+ return(1);
+}
+
+
+static int
+termp_under_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
- return(NULL);
+ p->flags |= TERMP_UNDERLINE;
+ return(1);
}
-static char *
-msec2a(enum mdoc_msec msec)
+static int
+termp_bold_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
{
- 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");
+ p->flags |= TERMP_BOLD;
+ return(1);
+}
+
+
+static int
+termp_ns_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ p->flags |= TERMP_NOSPACE;
+ return(1);
+}
+
+
+static int
+termp_pp_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ vspace(p);
+ return(1);
+}
+
+
+static int
+termp_under_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ p->flags &= ~TERMP_UNDERLINE;
+ return(1);
+}
+
+
+static int
+termp_nd_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ word(p, "-");
+ return(1);
+}
+
+
+static int
+termp_bl_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ switch (node->type) {
+ case (MDOC_BLOCK):
+ newln(p);
+ break;
default:
break;
}
- return(NULL);
+ return(1);
}
-static size_t
-ttitle2a(char *dst, enum mdoc_vol vol, enum mdoc_msec msec,
- enum mdoc_arch arch, size_t sz)
+static int
+termp_op_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
{
- 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);
+ switch (node->type) {
+ case (MDOC_BODY):
+ p->flags |= TERMP_NOSPACE;
+ word(p, "\\(rB");
+ break;
+ default:
+ break;
}
+ return(1);
+}
- return(ssz);
+
+static int
+termp_sh_post(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ switch (node->type) {
+ case (MDOC_HEAD):
+ p->flags &= ~TERMP_BOLD;
+ newln(p);
+ break;
+ case (MDOC_BODY):
+ newln(p);
+ (p->indent)--;
+ break;
+ default:
+ break;
+ }
+ return(1);
}
static int
-termprint_r(size_t cols, size_t indent, const struct mdoc_node *node)
+termp_sh_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
{
+ switch (node->type) {
+ case (MDOC_HEAD):
+ vspace(p);
+ p->flags |= TERMP_BOLD;
+ break;
+ case (MDOC_BODY):
+ (p->indent)++;
+ break;
+ default:
+ break;
+ }
return(1);
}
+static int
+termp_op_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ switch (node->type) {
+ case (MDOC_BODY):
+ word(p, "\\(lB");
+ p->flags |= TERMP_NOSPACE;
+ break;
+ default:
+ break;
+ }
+ return(1);
+}
+
+
+static int
+termp_fl_pre(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ p->flags |= TERMP_BOLD;
+ word(p, "-");
+ p->flags |= TERMP_NOSPACE;
+ return(1);
+}
+
+
+static void
+termprint_r(struct termp *p, const struct mdoc_meta *meta,
+ const struct mdoc_node *node)
+{
+
+ /* Pre-processing ----------------- */
+
+ if (MDOC_TEXT != node->type) {
+ if (termacts[node->tok].pre)
+ if ( ! (*termacts[node->tok].pre)(p, meta, node))
+ return;
+ } else /* MDOC_TEXT == node->type */
+ word(p, node->data.text.string);
+
+ /* Children ---------------------- */
+
+ if (NULL == node->child) {
+ /* No-child processing. */
+ switch (node->type) {
+ case (MDOC_ELEM):
+ switch (node->tok) {
+ case (MDOC_Nm):
+ word(p, "progname"); /* TODO */
+ break;
+ case (MDOC_Ar):
+ word(p, "...");
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ } else
+ termprint_r(p, meta, node->child);
+
+ /* Post-processing --------------- */
+
+ if (MDOC_TEXT != node->type) {
+ if (termacts[node->tok].post)
+ if ( ! (*termacts[node->tok].post)(p, meta, node))
+ return;
+ }
+
+ /* Siblings ---------------------- */
+
+ if (node->next)
+ termprint_r(p, meta, node->next);
+}
+
+
static void
-termprint_tail(size_t cols, const struct mdoc_meta *meta)
+termprint_footer(struct termp *p, const struct mdoc_meta *meta)
{
struct tm *tm;
char *buf, *os;
size_t sz, osz, ssz, i;
- if (NULL == (buf = malloc(cols)))
+ if (NULL == (buf = malloc(p->maxvisible)))
err(1, "malloc");
- if (NULL == (os = malloc(cols)))
+ if (NULL == (os = malloc(p->maxvisible)))
err(1, "malloc");
tm = localtime(&meta->date);
- if (NULL == strftime(buf, cols, "%B %d, %Y", tm))
+ if (NULL == strftime(buf, p->maxvisible, "%B %d, %Y", tm))
err(1, "strftime");
- osz = strlcpy(os, meta->os, cols);
+ osz = strlcpy(os, meta->os, p->maxvisible);
sz = strlen(buf);
ssz = sz + osz + 1;
- if (ssz > cols) {
- ssz -= cols;
+ if (ssz > p->maxvisible) {
+ ssz -= p->maxvisible;
assert(ssz <= osz);
os[osz - ssz] = 0;
ssz = 1;
} else
- ssz = cols - ssz + 1;
+ ssz = p->maxvisible - ssz + 1;
+ printf("\n");
printf("%s", os);
for (i = 0; i < ssz; i++)
printf(" ");
printf("%s\n", buf);
+ fflush(stdout);
free(buf);
free(os);
@@ -291,28 +666,69 @@ termprint_tail(size_t cols, const struct mdoc_meta *meta)
static void
-termprint_head(size_t cols, const struct mdoc_meta *meta)
+termprint_header(struct termp *p, const struct mdoc_meta *meta)
{
- char *msec, *buf, *title;
- size_t ssz, tsz, ttsz, i;
+ char *msec, *buf, *title, *pp;
+ size_t ssz, tsz, ttsz, i;;
- if (NULL == (buf = malloc(cols)))
+ if (NULL == (buf = malloc(p->maxvisible)))
err(1, "malloc");
- if (NULL == (title = malloc(cols)))
+ if (NULL == (title = malloc(p->maxvisible)))
err(1, "malloc");
- /* Format the manual page header. */
+ if (NULL == (pp = mdoc_vol2a(meta->vol)))
+ switch (meta->msec) {
+ case (MSEC_1):
+ /* FALLTHROUGH */
+ case (MSEC_6):
+ /* FALLTHROUGH */
+ case (MSEC_7):
+ pp = mdoc_vol2a(VOL_URM);
+ break;
+ case (MSEC_8):
+ pp = mdoc_vol2a(VOL_SMM);
+ break;
+ case (MSEC_2):
+ /* FALLTHROUGH */
+ case (MSEC_3):
+ /* FALLTHROUGH */
+ case (MSEC_4):
+ /* FALLTHROUGH */
+ case (MSEC_5):
+ pp = mdoc_vol2a(VOL_PRM);
+ break;
+ case (MSEC_9):
+ pp = mdoc_vol2a(VOL_KM);
+ break;
+ default:
+ /* FIXME: capitalise. */
+ if (NULL == (pp = mdoc_msec2a(meta->msec)))
+ pp = mdoc_msec2a(MSEC_local);
+ break;
+ }
+ assert(pp);
+
+ tsz = strlcpy(buf, pp, p->maxvisible);
+ assert(tsz < p->maxvisible);
+
+ if ((pp = mdoc_arch2a(meta->arch))) {
+ tsz = strlcat(buf, " (", p->maxvisible);
+ assert(tsz < p->maxvisible);
+ tsz = strlcat(buf, pp, p->maxvisible);
+ assert(tsz < p->maxvisible);
+ tsz = strlcat(buf, ")", p->maxvisible);
+ assert(tsz < p->maxvisible);
+ }
- tsz = ttitle2a(buf, meta->vol, meta->msec, meta->arch, cols);
- ttsz = strlcpy(title, meta->title, cols);
+ ttsz = strlcpy(title, meta->title, p->maxvisible);
- if (NULL == (msec = msec2a(meta->msec)))
+ if (NULL == (msec = mdoc_msec2a(meta->msec)))
msec = "";
ssz = (2 * (ttsz + 2 + strlen(msec))) + tsz + 2;
- if (ssz > cols) {
- if ((ssz -= cols) % 2)
+ if (ssz > p->maxvisible) {
+ if ((ssz -= p->maxvisible) % 2)
ssz++;
ssz /= 2;
@@ -320,7 +736,7 @@ termprint_head(size_t cols, const struct mdoc_meta *meta)
title[ttsz - ssz] = 0;
ssz = 1;
} else
- ssz = ((cols - ssz) / 2) + 1;
+ ssz = ((p->maxvisible - ssz) / 2) + 1;
printf("%s(%s)", title, msec);
@@ -332,7 +748,8 @@ termprint_head(size_t cols, const struct mdoc_meta *meta)
for (i = 0; i < ssz; i++)
printf(" ");
- printf("%s(%s)\n\n", title, msec);
+ printf("%s(%s)\n", title, msec);
+ fflush(stdout);
free(title);
free(buf);
@@ -343,17 +760,25 @@ int
termprint(const struct mdoc_node *node,
const struct mdoc_meta *meta)
{
- size_t cols;
+ struct termp p;
if (ERR == setupterm(NULL, STDOUT_FILENO, NULL))
return(0);
- cols = columns < 60 ? 60 : (size_t)columns;
+ p.maxvisible = columns < 60 ? 60 : (size_t)columns;
+ p.maxcols = 1024;
+ p.indent = p.col = 0;
+ p.flags = TERMP_NOSPACE;
+
+ if (NULL == (p.buf = malloc(p.maxcols)))
+ err(1, "malloc");
+
+ termprint_header(&p, meta);
+ termprint_r(&p, meta, node);
+ termprint_footer(&p, meta);
+
+ free(p.buf);
- 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
index 4dec0f3c..774a01f6 100644
--- a/tree.c
+++ b/tree.c
@@ -122,8 +122,10 @@ treeprint_r(const struct mdoc_node *n, int indent)
}
+/* ARGSUSED */
int
-treeprint(const struct mdoc_node *node)
+treeprint(const struct mdoc_node *node,
+ const struct mdoc_meta *meta)
{
treeprint_r(node, 0);