aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--main.c8
-rw-r--r--main.h4
-rw-r--r--mandoc.120
-rw-r--r--mdoc_man.c426
5 files changed, 460 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index b1fd0219..6497bfbc 100644
--- a/Makefile
+++ b/Makefile
@@ -93,6 +93,7 @@ SRCS = Makefile \
mdoc_hash.c \
mdoc_html.c \
mdoc_macro.c \
+ mdoc_man.c \
mdoc_term.c \
mdoc_validate.c \
msec.c \
@@ -220,6 +221,9 @@ MANDOC_HTML_LNS = eqn_html.ln \
mdoc_html.ln \
tbl_html.ln
+MANDOC_MAN_OBJS = mdoc_man.o
+MANDOC_MAN_LNS = mdoc_man.ln
+
MANDOC_TERM_OBJS = eqn_term.o \
man_term.o \
mdoc_term.o \
@@ -236,11 +240,13 @@ MANDOC_TERM_LNS = eqn_term.ln \
tbl_term.ln
MANDOC_OBJS = $(MANDOC_HTML_OBJS) \
+ $(MANDOC_MAN_OBJS) \
$(MANDOC_TERM_OBJS) \
main.o \
out.o \
tree.o
MANDOC_LNS = $(MANDOC_HTML_LNS) \
+ $(MANDOC_MAN_LNS) \
$(MANDOC_TERM_LNS) \
main.ln \
out.ln \
diff --git a/main.c b/main.c
index 4c2e7e79..b76a6047 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.163 2011/05/20 15:51:18 kristaps Exp $ */
+/* $Id: main.c,v 1.164 2011/09/17 15:00:51 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -46,6 +46,7 @@ enum outt {
OUTT_LOCALE, /* -Tlocale */
OUTT_UTF8, /* -Tutf8 */
OUTT_TREE, /* -Ttree */
+ OUTT_MAN, /* -Tman */
OUTT_HTML, /* -Thtml */
OUTT_XHTML, /* -Txhtml */
OUTT_LINT, /* -Tlint */
@@ -249,6 +250,9 @@ parse(struct curparse *curp, int fd,
curp->outman = tree_man;
curp->outmdoc = tree_mdoc;
break;
+ case (OUTT_MAN):
+ curp->outmdoc = man_mdoc;
+ break;
case (OUTT_PDF):
/* FALLTHROUGH */
case (OUTT_ASCII):
@@ -312,6 +316,8 @@ toptions(struct curparse *curp, char *arg)
curp->wlevel = MANDOCLEVEL_WARNING;
} else if (0 == strcmp(arg, "tree"))
curp->outtype = OUTT_TREE;
+ else if (0 == strcmp(arg, "man"))
+ curp->outtype = OUTT_MAN;
else if (0 == strcmp(arg, "html"))
curp->outtype = OUTT_HTML;
else if (0 == strcmp(arg, "utf8"))
diff --git a/main.h b/main.h
index 07b9e879..7b12b326 100644
--- a/main.h
+++ b/main.h
@@ -1,4 +1,4 @@
-/* $Id: main.h,v 1.12 2011/05/20 15:48:22 kristaps Exp $ */
+/* $Id: main.h,v 1.13 2011/09/17 15:00:51 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -41,6 +41,8 @@ void html_free(void *);
void tree_mdoc(void *, const struct mdoc *);
void tree_man(void *, const struct man *);
+void man_mdoc(void *, const struct mdoc *);
+
void *locale_alloc(char *);
void *utf8_alloc(char *);
void *ascii_alloc(char *);
diff --git a/mandoc.1 b/mandoc.1
index de14205c..c9a9faba 100644
--- a/mandoc.1
+++ b/mandoc.1
@@ -1,4 +1,4 @@
-.\" $Id: mandoc.1,v 1.90 2011/08/18 08:58:43 kristaps Exp $
+.\" $Id: mandoc.1,v 1.91 2011/09/17 15:00:51 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: August 18 2011 $
+.Dd $Mdocdate: September 17 2011 $
.Dt MANDOC 1
.Os
.Sh NAME
@@ -179,6 +179,12 @@ See
Parse only: produce no output.
Implies
.Fl W Ns Cm warning .
+.It Fl T Ns Cm man
+Produce output in
+.Xr man 7
+format; only useful when applied to
+.Fl m Ns Cm doc
+input.
.It Fl T Ns Cm pdf
Produce PDF output.
See
@@ -417,6 +423,16 @@ To check over a large set of manuals:
To produce a series of PostScript manuals for A4 paper:
.Pp
.Dl $ mandoc \-Tps \-Opaper=a4 mdoc.7 man.7 \*(Gt manuals.ps
+.Pp
+Convert a modern
+.Xr mdoc 7
+manual to the older
+.Xr man 7
+format, for use on systems lacking an
+.Xr mdoc 7
+parser:
+.Pp
+.Dl $ mandoc \-Tman foo.mdoc \*(Gt foo.man
.Sh DIAGNOSTICS
Standard error messages reporting parsing errors are prefixed by
.Pp
diff --git a/mdoc_man.c b/mdoc_man.c
new file mode 100644
index 00000000..de62609f
--- /dev/null
+++ b/mdoc_man.c
@@ -0,0 +1,426 @@
+/* $Id: mdoc_man.c,v 1.1 2011/09/17 15:00:51 schwarze Exp $ */
+/*
+ * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+
+#include "mandoc.h"
+#include "mdoc.h"
+#include "main.h"
+
+static int need_space = 0;
+static int need_nl = 0;
+
+#define DECL_ARGS const struct mdoc_meta *m, \
+ const struct mdoc_node *n
+
+struct manact {
+ int (*cond)(DECL_ARGS);
+ int (*pre)(DECL_ARGS);
+ void (*post)(DECL_ARGS);
+ char *prefix;
+ char *suffix;
+};
+
+static void print_word(const char *);
+static void print_node(DECL_ARGS);
+
+static int cond_head(DECL_ARGS);
+static int cond_body(DECL_ARGS);
+static int pre_enc(DECL_ARGS);
+static void post_enc(DECL_ARGS);
+static void post_percent(DECL_ARGS);
+
+static int pre_dl(DECL_ARGS);
+static void post_dl(DECL_ARGS);
+static int pre_it(DECL_ARGS);
+static int pre_nm(DECL_ARGS);
+static void post_nm(DECL_ARGS);
+static int pre_ns(DECL_ARGS);
+static int pre_pp(DECL_ARGS);
+static int pre_sh(DECL_ARGS);
+static void post_sh(DECL_ARGS);
+static int pre_xr(DECL_ARGS);
+
+
+static const struct manact manacts[MDOC_MAX] = {
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ap */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Dd */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Dt */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Os */
+ { NULL, pre_sh, post_sh, NULL, NULL }, /* Sh */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ss */
+ { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
+ { NULL, NULL, NULL, NULL, NULL }, /* _D1 */
+ { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bd */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ed */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bl */
+ { NULL, NULL, NULL, NULL, NULL }, /* _El */
+ { NULL, pre_it, NULL, NULL, NULL }, /* _It */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ad */
+ { NULL, NULL, NULL, NULL, NULL }, /* _An */
+ { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Cd */
+ { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Dv */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Er */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ev */
+ { NULL, pre_enc, post_enc, "The \\fB",
+ "\\fP\nutility exits 0 on success, and >0 if an error occurs."
+ }, /* Ex */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Fa */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Fd */
+ { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Fn */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ft */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ic */
+ { NULL, NULL, NULL, NULL, NULL }, /* _In */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Li */
+ { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
+ { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
+ { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ot */
+ { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Pa */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Rv */
+ { NULL, NULL, NULL, NULL, NULL }, /* _St */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Va */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Vt */
+ { NULL, pre_xr, NULL, NULL, NULL }, /* _Xr */
+ { NULL, NULL, post_percent, NULL, NULL }, /* _%A */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%B */
+ { NULL, NULL, post_percent, NULL, NULL }, /* _%D */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%I */
+ { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%N */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%O */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%P */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%R */
+ { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%V */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ac */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ao */
+ { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
+ { NULL, NULL, NULL, NULL, NULL }, /* _At */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bc */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bo */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bq */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bsx */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bx */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Db */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Dc */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Do */
+ { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ec */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ef */
+ { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Em */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Eo */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Fx */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ms */
+ { NULL, NULL, NULL, NULL, NULL }, /* _No */
+ { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Nx */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ox */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Pc */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Pf */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Po */
+ { cond_body, pre_enc, post_enc, "(", ")" }, /* _Pq */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Qc */
+ { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Qo */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Qq */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Re */
+ { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Sc */
+ { NULL, NULL, NULL, NULL, NULL }, /* _So */
+ { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Sm */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Sx */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Sy */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Tn */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ux */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Xc */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Xo */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Fo */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Fc */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Oo */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Oc */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bk */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ek */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bt */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Hf */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Fr */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ud */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Lb */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Lp */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Lk */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Mt */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Brq */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Bro */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Brc */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%C */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Es */
+ { NULL, NULL, NULL, NULL, NULL }, /* _En */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Dx */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%Q */
+ { NULL, NULL, NULL, NULL, NULL }, /* _br */
+ { NULL, NULL, NULL, NULL, NULL }, /* _sp */
+ { NULL, NULL, NULL, NULL, NULL }, /* _%U */
+ { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
+};
+
+
+static void
+print_word(const char *s)
+{
+ if (need_nl) {
+ putchar('\n');
+ need_space = 0;
+ need_nl = 0;
+ } else if (need_space &&
+ (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]))
+ putchar(' ');
+ need_space = ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
+ for ( ; *s; s++) {
+ switch (*s) {
+ case (ASCII_NBRSP):
+ printf("\\~");
+ break;
+ case (ASCII_HYPH):
+ putchar('-');
+ break;
+ default:
+ putchar(*s);
+ break;
+ }
+ }
+}
+
+void
+man_mdoc(void *arg, const struct mdoc *mdoc)
+{
+ const struct mdoc_meta *m;
+ const struct mdoc_node *n;
+
+ m = mdoc_meta(mdoc);
+ n = mdoc_node(mdoc);
+
+ printf(".TH \"%s\" \"%s\" \"%s\"", m->title, m->msec, m->date);
+ need_nl = 1;
+ need_space = 0;
+
+ print_node(m, n);
+}
+
+static void
+print_node(DECL_ARGS)
+{
+ const struct mdoc_node *prev, *sub;
+ const struct manact *act = NULL;
+ int cond, do_sub;
+
+ prev = n->prev ? n->prev : n->parent;
+ if (prev && prev->line < n->line)
+ need_nl = 1;
+
+ cond = 0;
+ do_sub = 1;
+ if (MDOC_TEXT == n->type) {
+ print_word(n->string);
+ } else {
+ act = manacts + n->tok;
+ cond = NULL == act->cond || (*act->cond)(m, n);
+ if (cond && act->pre)
+ do_sub = (*act->pre)(m, n);
+ }
+
+ if (do_sub)
+ for (sub = n->child; sub; sub = sub->next)
+ print_node(m, sub);
+
+ if (cond && act->post)
+ (*act->post)(m, n);
+}
+
+static int
+cond_head(DECL_ARGS)
+{
+ return(MDOC_HEAD == n->type);
+}
+
+static int
+cond_body(DECL_ARGS)
+{
+ return(MDOC_BODY == n->type);
+}
+
+static int
+pre_enc(DECL_ARGS)
+{
+ const char *prefix;
+
+ prefix = manacts[n->tok].prefix;
+ if (NULL == prefix)
+ return(1);
+ print_word(prefix);
+ need_space = 0;
+ return(1);
+}
+
+static void
+post_enc(DECL_ARGS)
+{
+ const char *suffix;
+
+ suffix = manacts[n->tok].suffix;
+ if (NULL == suffix)
+ return;
+ need_space = 0;
+ print_word(suffix);
+}
+
+static void
+post_percent(DECL_ARGS)
+{
+
+ post_enc(m, n);
+ if (n->next)
+ print_word(",");
+ else {
+ print_word(".");
+ need_nl = 1;
+ }
+}
+
+static int
+pre_dl(DECL_ARGS)
+{
+
+ need_nl = 1;
+ print_word(".RS 6n");
+ need_nl = 1;
+ return(1);
+}
+
+static void
+post_dl(DECL_ARGS)
+{
+
+ need_nl = 1;
+ print_word(".RE");
+ need_nl = 1;
+}
+
+static int
+pre_it(DECL_ARGS)
+{
+ const struct mdoc_node *bln;
+
+ if (MDOC_HEAD == n->type) {
+ need_nl = 1;
+ print_word(".TP");
+ bln = n->parent->parent->prev;
+ print_word(bln->norm->Bl.width);
+ need_nl = 1;
+ }
+ return(1);
+}
+
+static int
+pre_nm(DECL_ARGS)
+{
+
+ if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
+ return(1);
+ print_word("\\fB");
+ need_space = 0;
+ if (NULL == n->child)
+ print_word(m->name);
+ return(1);
+}
+
+static void
+post_nm(DECL_ARGS)
+{
+
+ if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
+ return;
+ need_space = 0;
+ print_word("\\fP");
+}
+
+static int
+pre_ns(DECL_ARGS)
+{
+
+ need_space = 0;
+ return(0);
+}
+
+static int
+pre_pp(DECL_ARGS)
+{
+
+ need_nl = 1;
+ if (MDOC_It == n->parent->tok)
+ print_word(".sp");
+ else
+ print_word(".PP");
+ need_nl = 1;
+ return(1);
+}
+
+static int
+pre_sh(DECL_ARGS)
+{
+
+ if (MDOC_HEAD != n->type)
+ return(1);
+ need_nl = 1;
+ print_word(".SH \"");
+ need_space = 0;
+ return(1);
+}
+
+static void
+post_sh(DECL_ARGS)
+{
+
+ if (MDOC_HEAD != n->type)
+ return;
+ need_space = 0;
+ print_word("\"");
+ need_nl = 1;
+}
+
+static int
+pre_xr(DECL_ARGS)
+{
+
+ n = n->child;
+ if (NULL == n)
+ return(0);
+ print_node(m, n);
+ n = n->next;
+ if (NULL == n)
+ return(0);
+ need_space = 0;
+ print_word("(");
+ print_node(m, n);
+ print_word(")");
+ return(0);
+}