aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2011-09-17 15:00:51 +0000
committerIngo Schwarze <schwarze@openbsd.org>2011-09-17 15:00:51 +0000
commitd896fc86c4e9a18cefb558d7bfd1c987306de938 (patch)
tree9821eaa5690811ede58dcb6c8ecb6d2319da1540
parent16e745d5f0fcf9edaa4f0733c6dd0a128075b31a (diff)
downloadmandoc-d896fc86c4e9a18cefb558d7bfd1c987306de938.tar.gz
mandoc-d896fc86c4e9a18cefb558d7bfd1c987306de938.tar.zst
mandoc-d896fc86c4e9a18cefb558d7bfd1c987306de938.zip
Initial, incomplete support for -Tman
to convert mdoc(7) documents to the man(7) language. This is work in progress and will be developed in tree. It does already handle the cat(1) manual, but will hardly handle all your fancy manuals yet. go ahead kristaps@ jmc@ millert@ deraadt@
-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);
+}