--- /dev/null	Fri Jul 18 08:34:33 2014
+++ new/usr/src/cmd/mandoc/main.c	Fri Jul 18 08:34:33 2014
@@ -0,0 +1,401 @@
+/*	$Id: main.c,v 1.165 2011/10/06 22:29:12 kristaps Exp $ */
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010, 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mandoc.h"
+#include "main.h"
+#include "mdoc.h"
+#include "man.h"
+
+#if !defined(__GNUC__) || (__GNUC__ < 2)
+# if !defined(lint)
+#  define __attribute__(x)
+# endif
+#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
+
+typedef	void		(*out_mdoc)(void *, const struct mdoc *);
+typedef	void		(*out_man)(void *, const struct man *);
+typedef	void		(*out_free)(void *);
+
+enum	outt {
+	OUTT_ASCII = 0,	/* -Tascii */
+	OUTT_LOCALE,	/* -Tlocale */
+	OUTT_UTF8,	/* -Tutf8 */
+	OUTT_TREE,	/* -Ttree */
+	OUTT_MAN,	/* -Tman */
+	OUTT_HTML,	/* -Thtml */
+	OUTT_XHTML,	/* -Txhtml */
+	OUTT_LINT,	/* -Tlint */
+	OUTT_PS,	/* -Tps */
+	OUTT_PDF	/* -Tpdf */
+};
+
+struct	curparse {
+	struct mparse	 *mp;
+	enum mandoclevel  wlevel;	/* ignore messages below this */
+	int		  wstop;	/* stop after a file with a warning */
+	enum outt	  outtype; 	/* which output to use */
+	out_mdoc	  outmdoc;	/* mdoc output ptr */
+	out_man	  	  outman;	/* man output ptr */
+	out_free	  outfree;	/* free output ptr */
+	void		 *outdata;	/* data for output */
+	char		  outopts[BUFSIZ]; /* buf of output opts */
+};
+
+static	int		  moptions(enum mparset *, char *);
+static	void		  mmsg(enum mandocerr, enum mandoclevel,
+				const char *, int, int, const char *);
+static	void		  parse(struct curparse *, int, 
+				const char *, enum mandoclevel *);
+static	int		  toptions(struct curparse *, char *);
+static	void		  usage(void) __attribute__((noreturn));
+static	void		  version(void) __attribute__((noreturn));
+static	int		  woptions(struct curparse *, char *);
+
+static	const char	 *progname;
+
+int
+main(int argc, char *argv[])
+{
+	int		 c;
+	struct curparse	 curp;
+	enum mparset	 type;
+	enum mandoclevel rc;
+
+	progname = strrchr(argv[0], '/');
+	if (progname == NULL)
+		progname = argv[0];
+	else
+		++progname;
+
+	memset(&curp, 0, sizeof(struct curparse));
+
+	type = MPARSE_AUTO;
+	curp.outtype = OUTT_ASCII;
+	curp.wlevel  = MANDOCLEVEL_FATAL;
+
+	/* LINTED */
+	while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
+		switch (c) {
+		case ('m'):
+			if ( ! moptions(&type, optarg))
+				return((int)MANDOCLEVEL_BADARG);
+			break;
+		case ('O'):
+			(void)strlcat(curp.outopts, optarg, BUFSIZ);
+			(void)strlcat(curp.outopts, ",", BUFSIZ);
+			break;
+		case ('T'):
+			if ( ! toptions(&curp, optarg))
+				return((int)MANDOCLEVEL_BADARG);
+			break;
+		case ('W'):
+			if ( ! woptions(&curp, optarg))
+				return((int)MANDOCLEVEL_BADARG);
+			break;
+		case ('V'):
+			version();
+			/* NOTREACHED */
+		default:
+			usage();
+			/* NOTREACHED */
+		}
+
+	curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp);
+
+	/*
+	 * Conditionally start up the lookaside buffer before parsing.
+	 */
+	if (OUTT_MAN == curp.outtype)
+		mparse_keep(curp.mp);
+
+	argc -= optind;
+	argv += optind;
+
+	rc = MANDOCLEVEL_OK;
+
+	if (NULL == *argv)
+		parse(&curp, STDIN_FILENO, "<stdin>", &rc);
+
+	while (*argv) {
+		parse(&curp, -1, *argv, &rc);
+		if (MANDOCLEVEL_OK != rc && curp.wstop)
+			break;
+		++argv;
+	}
+
+	if (curp.outfree)
+		(*curp.outfree)(curp.outdata);
+	if (curp.mp)
+		mparse_free(curp.mp);
+
+	return((int)rc);
+}
+
+static void
+version(void)
+{
+
+	printf("%s %s\n", progname, VERSION);
+	exit((int)MANDOCLEVEL_OK);
+}
+
+static void
+usage(void)
+{
+
+	fprintf(stderr, "usage: %s "
+			"[-V] "
+			"[-foption] "
+			"[-mformat] "
+			"[-Ooption] "
+			"[-Toutput] "
+			"[-Wlevel] "
+			"[file...]\n", 
+			progname);
+
+	exit((int)MANDOCLEVEL_BADARG);
+}
+
+static void
+parse(struct curparse *curp, int fd, 
+		const char *file, enum mandoclevel *level)
+{
+	enum mandoclevel  rc;
+	struct mdoc	 *mdoc;
+	struct man	 *man;
+
+	/* Begin by parsing the file itself. */
+
+	assert(file);
+	assert(fd >= -1);
+
+	rc = mparse_readfd(curp->mp, fd, file);
+
+	/* Stop immediately if the parse has failed. */
+
+	if (MANDOCLEVEL_FATAL <= rc)
+		goto cleanup;
+
+	/*
+	 * With -Wstop and warnings or errors of at least the requested
+	 * level, do not produce output.
+	 */
+
+	if (MANDOCLEVEL_OK != rc && curp->wstop)
+		goto cleanup;
+
+	/* If unset, allocate output dev now (if applicable). */
+
+	if ( ! (curp->outman && curp->outmdoc)) {
+		switch (curp->outtype) {
+		case (OUTT_XHTML):
+			curp->outdata = xhtml_alloc(curp->outopts);
+			curp->outfree = html_free;
+			break;
+		case (OUTT_HTML):
+			curp->outdata = html_alloc(curp->outopts);
+			curp->outfree = html_free;
+			break;
+		case (OUTT_UTF8):
+			curp->outdata = utf8_alloc(curp->outopts);
+			curp->outfree = ascii_free;
+			break;
+		case (OUTT_LOCALE):
+			curp->outdata = locale_alloc(curp->outopts);
+			curp->outfree = ascii_free;
+			break;
+		case (OUTT_ASCII):
+			curp->outdata = ascii_alloc(curp->outopts);
+			curp->outfree = ascii_free;
+			break;
+		case (OUTT_PDF):
+			curp->outdata = pdf_alloc(curp->outopts);
+			curp->outfree = pspdf_free;
+			break;
+		case (OUTT_PS):
+			curp->outdata = ps_alloc(curp->outopts);
+			curp->outfree = pspdf_free;
+			break;
+		default:
+			break;
+		}
+
+		switch (curp->outtype) {
+		case (OUTT_HTML):
+			/* FALLTHROUGH */
+		case (OUTT_XHTML):
+			curp->outman = html_man;
+			curp->outmdoc = html_mdoc;
+			break;
+		case (OUTT_TREE):
+			curp->outman = tree_man;
+			curp->outmdoc = tree_mdoc;
+			break;
+		case (OUTT_MAN):
+			curp->outmdoc = man_mdoc;
+			curp->outman = man_man;
+			break;
+		case (OUTT_PDF):
+			/* FALLTHROUGH */
+		case (OUTT_ASCII):
+			/* FALLTHROUGH */
+		case (OUTT_UTF8):
+			/* FALLTHROUGH */
+		case (OUTT_LOCALE):
+			/* FALLTHROUGH */
+		case (OUTT_PS):
+			curp->outman = terminal_man;
+			curp->outmdoc = terminal_mdoc;
+			break;
+		default:
+			break;
+		}
+	}
+
+	mparse_result(curp->mp, &mdoc, &man);
+
+	/* Execute the out device, if it exists. */
+
+	if (man && curp->outman)
+		(*curp->outman)(curp->outdata, man);
+	if (mdoc && curp->outmdoc)
+		(*curp->outmdoc)(curp->outdata, mdoc);
+
+ cleanup:
+
+	mparse_reset(curp->mp);
+
+	if (*level < rc)
+		*level = rc;
+}
+
+static int
+moptions(enum mparset *tflags, char *arg)
+{
+
+	if (0 == strcmp(arg, "doc"))
+		*tflags = MPARSE_MDOC;
+	else if (0 == strcmp(arg, "andoc"))
+		*tflags = MPARSE_AUTO;
+	else if (0 == strcmp(arg, "an"))
+		*tflags = MPARSE_MAN;
+	else {
+		fprintf(stderr, "%s: Bad argument\n", arg);
+		return(0);
+	}
+
+	return(1);
+}
+
+static int
+toptions(struct curparse *curp, char *arg)
+{
+
+	if (0 == strcmp(arg, "ascii"))
+		curp->outtype = OUTT_ASCII;
+	else if (0 == strcmp(arg, "lint")) {
+		curp->outtype = OUTT_LINT;
+		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"))
+		curp->outtype = OUTT_UTF8;
+	else if (0 == strcmp(arg, "locale"))
+		curp->outtype = OUTT_LOCALE;
+	else if (0 == strcmp(arg, "xhtml"))
+		curp->outtype = OUTT_XHTML;
+	else if (0 == strcmp(arg, "ps"))
+		curp->outtype = OUTT_PS;
+	else if (0 == strcmp(arg, "pdf"))
+		curp->outtype = OUTT_PDF;
+	else {
+		fprintf(stderr, "%s: Bad argument\n", arg);
+		return(0);
+	}
+
+	return(1);
+}
+
+static int
+woptions(struct curparse *curp, char *arg)
+{
+	char		*v, *o;
+	const char	*toks[6]; 
+
+	toks[0] = "stop";
+	toks[1] = "all";
+	toks[2] = "warning";
+	toks[3] = "error";
+	toks[4] = "fatal";
+	toks[5] = NULL;
+
+	while (*arg) {
+		o = arg;
+		switch (getsubopt(&arg, UNCONST(toks), &v)) {
+		case (0):
+			curp->wstop = 1;
+			break;
+		case (1):
+			/* FALLTHROUGH */
+		case (2):
+			curp->wlevel = MANDOCLEVEL_WARNING;
+			break;
+		case (3):
+			curp->wlevel = MANDOCLEVEL_ERROR;
+			break;
+		case (4):
+			curp->wlevel = MANDOCLEVEL_FATAL;
+			break;
+		default:
+			fprintf(stderr, "-W%s: Bad argument\n", o);
+			return(0);
+		}
+	}
+
+	return(1);
+}
+
+static void
+mmsg(enum mandocerr t, enum mandoclevel lvl, 
+		const char *file, int line, int col, const char *msg)
+{
+
+	fprintf(stderr, "%s:%d:%d: %s: %s", 
+			file, line, col + 1, 
+			mparse_strlevel(lvl),
+			mparse_strerror(t));
+
+	if (msg)
+		fprintf(stderr, ": %s", msg);
+
+	fputc('\n', stderr);
+}
