diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | mdocml.1 | 21 | ||||
-rw-r--r-- | mdocml.c | 4 | ||||
-rw-r--r-- | private.h | 5 | ||||
-rw-r--r-- | strings.c | 155 | ||||
-rw-r--r-- | term.c | 835 | ||||
-rw-r--r-- | tree.c | 4 |
7 files changed, 811 insertions, 217 deletions
@@ -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 @@ -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 @@ -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); @@ -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 *); @@ -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 */ +} + @@ -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); } @@ -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); |