summaryrefslogtreecommitdiffstats
path: root/contrib/mdocml/main.c
diff options
context:
space:
mode:
authoruqs <uqs@FreeBSD.org>2012-10-19 22:21:01 +0000
committeruqs <uqs@FreeBSD.org>2012-10-19 22:21:01 +0000
commitbdec3cb5a747bba9c264cfc079075a9cdd270b9b (patch)
treef3e4c243809ab9802585681d5a07885f772eb5b0 /contrib/mdocml/main.c
parent3362252a56bf0d1c15907a461e1692760af910c7 (diff)
parentc2dfbbd38125b2ba3608eb48ca3b5e2e23f819df (diff)
downloadFreeBSD-src-bdec3cb5a747bba9c264cfc079075a9cdd270b9b.zip
FreeBSD-src-bdec3cb5a747bba9c264cfc079075a9cdd270b9b.tar.gz
Merge mandoc from vendor into contrib and provide the necessary Makefile glue.
It's not yet connected to the build.
Diffstat (limited to 'contrib/mdocml/main.c')
-rw-r--r--contrib/mdocml/main.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/contrib/mdocml/main.c b/contrib/mdocml/main.c
new file mode 100644
index 0000000..fec83fb
--- /dev/null
+++ b/contrib/mdocml/main.c
@@ -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);
+}
OpenPOWER on IntegriCloud