summaryrefslogtreecommitdiff
path: root/usr.bin/mandoc
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2011-09-17 14:45:23 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2011-09-17 14:45:23 +0000
commit7c0319646da9c03bdccac157478d868a2b5722aa (patch)
tree66c76b62f1378adf445f345724a11c18b4031e25 /usr.bin/mandoc
parent525cf98782a1f8b20ccc43f4eb2d8a58018d3a4e (diff)
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@
Diffstat (limited to 'usr.bin/mandoc')
-rw-r--r--usr.bin/mandoc/Makefile3
-rw-r--r--usr.bin/mandoc/main.c8
-rw-r--r--usr.bin/mandoc/main.h4
-rw-r--r--usr.bin/mandoc/mandoc.120
-rw-r--r--usr.bin/mandoc/mdoc_man.c426
5 files changed, 456 insertions, 5 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index 372631562a5..0769e25dcbe 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.57 2011/07/31 16:15:40 schwarze Exp $
+# $OpenBSD: Makefile,v 1.58 2011/09/17 14:45:22 schwarze Exp $
.include <bsd.own.mk>
@@ -16,6 +16,7 @@ SRCS+= mdoc_macro.c mdoc.c mdoc_hash.c \
arch.c vol.c msec.c st.c
SRCS+= man_macro.c man.c man_hash.c man_validate.c
SRCS+= main.c mdoc_term.c chars.c term.c tree.c man_term.c
+SRCS+= mdoc_man.c
SRCS+= html.c mdoc_html.c man_html.c out.c
SRCS+= term_ps.c term_ascii.c tbl_term.c tbl_html.c
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index 3b2fd636dff..a1765f5b52d 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.77 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: main.c,v 1.78 2011/09/17 14:45:22 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -37,6 +37,7 @@ enum outt {
OUTT_LOCALE, /* -Tlocale */
OUTT_UTF8, /* -Tutf8 */
OUTT_TREE, /* -Ttree */
+ OUTT_MAN, /* -Tman */
OUTT_HTML, /* -Thtml */
OUTT_XHTML, /* -Txhtml */
OUTT_LINT, /* -Tlint */
@@ -240,6 +241,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):
@@ -303,6 +307,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/usr.bin/mandoc/main.h b/usr.bin/mandoc/main.h
index 1efb9d34387..88916340d52 100644
--- a/usr.bin/mandoc/main.h
+++ b/usr.bin/mandoc/main.h
@@ -1,4 +1,4 @@
-/* $Id: main.h,v 1.8 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: main.h,v 1.9 2011/09/17 14:45:22 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 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/usr.bin/mandoc/mandoc.1 b/usr.bin/mandoc/mandoc.1
index 6ba97da70c2..5d5d6ab9ecc 100644
--- a/usr.bin/mandoc/mandoc.1
+++ b/usr.bin/mandoc/mandoc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: mandoc.1,v 1.45 2011/05/31 22:44:48 schwarze Exp $
+.\" $OpenBSD: mandoc.1,v 1.46 2011/09/17 14:45:22 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 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: May 31 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/usr.bin/mandoc/mdoc_man.c b/usr.bin/mandoc/mdoc_man.c
new file mode 100644
index 00000000000..d4cdd5f2b41
--- /dev/null
+++ b/usr.bin/mandoc/mdoc_man.c
@@ -0,0 +1,426 @@
+/* $Id: mdoc_man.c,v 1.1 2011/09/17 14:45:22 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);
+}