xref: /minix3/external/bsd/mdocml/dist/main.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	Id: main.c,v 1.167 2012/11/19 17:22:26 schwarze Exp  */
2d65f6f70SBen Gras /*
3d65f6f70SBen Gras  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*0a6a1f1dSLionel Sambuc  * Copyright (c) 2010, 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
5d65f6f70SBen Gras  *
6d65f6f70SBen Gras  * Permission to use, copy, modify, and distribute this software for any
7d65f6f70SBen Gras  * purpose with or without fee is hereby granted, provided that the above
8d65f6f70SBen Gras  * copyright notice and this permission notice appear in all copies.
9d65f6f70SBen Gras  *
10d65f6f70SBen Gras  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11d65f6f70SBen Gras  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12d65f6f70SBen Gras  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13d65f6f70SBen Gras  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14d65f6f70SBen Gras  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15d65f6f70SBen Gras  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16d65f6f70SBen Gras  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17d65f6f70SBen Gras  */
18d65f6f70SBen Gras #ifdef HAVE_CONFIG_H
19d65f6f70SBen Gras #include "config.h"
20d65f6f70SBen Gras #endif
21d65f6f70SBen Gras 
22d65f6f70SBen Gras #include <assert.h>
23d65f6f70SBen Gras #include <stdio.h>
24d65f6f70SBen Gras #include <stdint.h>
25d65f6f70SBen Gras #include <stdlib.h>
26d65f6f70SBen Gras #include <string.h>
27d65f6f70SBen Gras #include <unistd.h>
28d65f6f70SBen Gras 
29d65f6f70SBen Gras #include "mandoc.h"
30d65f6f70SBen Gras #include "main.h"
31d65f6f70SBen Gras #include "mdoc.h"
32d65f6f70SBen Gras #include "man.h"
33d65f6f70SBen Gras 
34d65f6f70SBen Gras #if !defined(__GNUC__) || (__GNUC__ < 2)
35d65f6f70SBen Gras # if !defined(lint)
36d65f6f70SBen Gras #  define __attribute__(x)
37d65f6f70SBen Gras # endif
38d65f6f70SBen Gras #endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
39d65f6f70SBen Gras 
40d65f6f70SBen Gras typedef	void		(*out_mdoc)(void *, const struct mdoc *);
41d65f6f70SBen Gras typedef	void		(*out_man)(void *, const struct man *);
42d65f6f70SBen Gras typedef	void		(*out_free)(void *);
43d65f6f70SBen Gras 
44d65f6f70SBen Gras enum	outt {
4592395e9cSLionel Sambuc 	OUTT_ASCII = 0,	/* -Tascii */
4692395e9cSLionel Sambuc 	OUTT_LOCALE,	/* -Tlocale */
4792395e9cSLionel Sambuc 	OUTT_UTF8,	/* -Tutf8 */
4892395e9cSLionel Sambuc 	OUTT_TREE,	/* -Ttree */
4992395e9cSLionel Sambuc 	OUTT_MAN,	/* -Tman */
5092395e9cSLionel Sambuc 	OUTT_HTML,	/* -Thtml */
5192395e9cSLionel Sambuc 	OUTT_XHTML,	/* -Txhtml */
5292395e9cSLionel Sambuc 	OUTT_LINT,	/* -Tlint */
5392395e9cSLionel Sambuc 	OUTT_PS,	/* -Tps */
5492395e9cSLionel Sambuc 	OUTT_PDF	/* -Tpdf */
55d65f6f70SBen Gras };
56d65f6f70SBen Gras 
57d65f6f70SBen Gras struct	curparse {
5892395e9cSLionel Sambuc 	struct mparse	 *mp;
5992395e9cSLionel Sambuc 	enum mandoclevel  wlevel;	/* ignore messages below this */
6092395e9cSLionel Sambuc 	int		  wstop;	/* stop after a file with a warning */
61d65f6f70SBen Gras 	enum outt	  outtype; 	/* which output to use */
62d65f6f70SBen Gras 	out_mdoc	  outmdoc;	/* mdoc output ptr */
63d65f6f70SBen Gras 	out_man	  	  outman;	/* man output ptr */
64d65f6f70SBen Gras 	out_free	  outfree;	/* free output ptr */
65d65f6f70SBen Gras 	void		 *outdata;	/* data for output */
66d65f6f70SBen Gras 	char		  outopts[BUFSIZ]; /* buf of output opts */
67d65f6f70SBen Gras };
68d65f6f70SBen Gras 
6992395e9cSLionel Sambuc static	int		  moptions(enum mparset *, char *);
7092395e9cSLionel Sambuc static	void		  mmsg(enum mandocerr, enum mandoclevel,
7192395e9cSLionel Sambuc 				const char *, int, int, const char *);
7292395e9cSLionel Sambuc static	void		  parse(struct curparse *, int,
7392395e9cSLionel Sambuc 				const char *, enum mandoclevel *);
74d65f6f70SBen Gras static	int		  toptions(struct curparse *, char *);
75d65f6f70SBen Gras static	void		  usage(void) __attribute__((noreturn));
76d65f6f70SBen Gras static	void		  version(void) __attribute__((noreturn));
77d65f6f70SBen Gras static	int		  woptions(struct curparse *, char *);
78d65f6f70SBen Gras 
79d65f6f70SBen Gras static	const char	 *progname;
80d65f6f70SBen Gras 
81d65f6f70SBen Gras int
main(int argc,char * argv[])82d65f6f70SBen Gras main(int argc, char *argv[])
83d65f6f70SBen Gras {
84d65f6f70SBen Gras 	int		 c;
85d65f6f70SBen Gras 	struct curparse	 curp;
8692395e9cSLionel Sambuc 	enum mparset	 type;
8792395e9cSLionel Sambuc 	enum mandoclevel rc;
88*0a6a1f1dSLionel Sambuc 	char		*defos;
89d65f6f70SBen Gras 
90d65f6f70SBen Gras 	progname = strrchr(argv[0], '/');
91d65f6f70SBen Gras 	if (progname == NULL)
92d65f6f70SBen Gras 		progname = argv[0];
93d65f6f70SBen Gras 	else
94d65f6f70SBen Gras 		++progname;
95d65f6f70SBen Gras 
96d65f6f70SBen Gras 	memset(&curp, 0, sizeof(struct curparse));
97d65f6f70SBen Gras 
9892395e9cSLionel Sambuc 	type = MPARSE_AUTO;
99d65f6f70SBen Gras 	curp.outtype = OUTT_ASCII;
100d65f6f70SBen Gras 	curp.wlevel  = MANDOCLEVEL_FATAL;
101*0a6a1f1dSLionel Sambuc 	defos = NULL;
102d65f6f70SBen Gras 
103d65f6f70SBen Gras 	/* LINTED */
104*0a6a1f1dSLionel Sambuc 	while (-1 != (c = getopt(argc, argv, "I:m:O:T:VW:")))
105d65f6f70SBen Gras 		switch (c) {
106*0a6a1f1dSLionel Sambuc 		case ('I'):
107*0a6a1f1dSLionel Sambuc 			if (strncmp(optarg, "os=", 3)) {
108*0a6a1f1dSLionel Sambuc 				fprintf(stderr, "-I%s: Bad argument\n",
109*0a6a1f1dSLionel Sambuc 						optarg);
110*0a6a1f1dSLionel Sambuc 				return((int)MANDOCLEVEL_BADARG);
111*0a6a1f1dSLionel Sambuc 			}
112*0a6a1f1dSLionel Sambuc 			if (defos) {
113*0a6a1f1dSLionel Sambuc 				fprintf(stderr, "-I%s: Duplicate argument\n",
114*0a6a1f1dSLionel Sambuc 						optarg);
115*0a6a1f1dSLionel Sambuc 				return((int)MANDOCLEVEL_BADARG);
116*0a6a1f1dSLionel Sambuc 			}
117*0a6a1f1dSLionel Sambuc 			defos = mandoc_strdup(optarg + 3);
118*0a6a1f1dSLionel Sambuc 			break;
119d65f6f70SBen Gras 		case ('m'):
12092395e9cSLionel Sambuc 			if ( ! moptions(&type, optarg))
121d65f6f70SBen Gras 				return((int)MANDOCLEVEL_BADARG);
122d65f6f70SBen Gras 			break;
123d65f6f70SBen Gras 		case ('O'):
124d65f6f70SBen Gras 			(void)strlcat(curp.outopts, optarg, BUFSIZ);
125d65f6f70SBen Gras 			(void)strlcat(curp.outopts, ",", BUFSIZ);
126d65f6f70SBen Gras 			break;
127d65f6f70SBen Gras 		case ('T'):
128d65f6f70SBen Gras 			if ( ! toptions(&curp, optarg))
129d65f6f70SBen Gras 				return((int)MANDOCLEVEL_BADARG);
130d65f6f70SBen Gras 			break;
131d65f6f70SBen Gras 		case ('W'):
132d65f6f70SBen Gras 			if ( ! woptions(&curp, optarg))
133d65f6f70SBen Gras 				return((int)MANDOCLEVEL_BADARG);
134d65f6f70SBen Gras 			break;
135d65f6f70SBen Gras 		case ('V'):
136d65f6f70SBen Gras 			version();
137d65f6f70SBen Gras 			/* NOTREACHED */
138d65f6f70SBen Gras 		default:
139d65f6f70SBen Gras 			usage();
140d65f6f70SBen Gras 			/* NOTREACHED */
141d65f6f70SBen Gras 		}
142d65f6f70SBen Gras 
143*0a6a1f1dSLionel Sambuc 	curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp, defos);
14492395e9cSLionel Sambuc 
14592395e9cSLionel Sambuc 	/*
14692395e9cSLionel Sambuc 	 * Conditionally start up the lookaside buffer before parsing.
14792395e9cSLionel Sambuc 	 */
14892395e9cSLionel Sambuc 	if (OUTT_MAN == curp.outtype)
14992395e9cSLionel Sambuc 		mparse_keep(curp.mp);
15092395e9cSLionel Sambuc 
151d65f6f70SBen Gras 	argc -= optind;
152d65f6f70SBen Gras 	argv += optind;
153d65f6f70SBen Gras 
15492395e9cSLionel Sambuc 	rc = MANDOCLEVEL_OK;
155d65f6f70SBen Gras 
15692395e9cSLionel Sambuc 	if (NULL == *argv)
15792395e9cSLionel Sambuc 		parse(&curp, STDIN_FILENO, "<stdin>", &rc);
158d65f6f70SBen Gras 
159d65f6f70SBen Gras 	while (*argv) {
16092395e9cSLionel Sambuc 		parse(&curp, -1, *argv, &rc);
16192395e9cSLionel Sambuc 		if (MANDOCLEVEL_OK != rc && curp.wstop)
162d65f6f70SBen Gras 			break;
163d65f6f70SBen Gras 		++argv;
164d65f6f70SBen Gras 	}
165d65f6f70SBen Gras 
166d65f6f70SBen Gras 	if (curp.outfree)
167d65f6f70SBen Gras 		(*curp.outfree)(curp.outdata);
16892395e9cSLionel Sambuc 	if (curp.mp)
16992395e9cSLionel Sambuc 		mparse_free(curp.mp);
170*0a6a1f1dSLionel Sambuc 	free(defos);
171d65f6f70SBen Gras 
17292395e9cSLionel Sambuc 	return((int)rc);
173d65f6f70SBen Gras }
174d65f6f70SBen Gras 
175d65f6f70SBen Gras static void
version(void)176d65f6f70SBen Gras version(void)
177d65f6f70SBen Gras {
178d65f6f70SBen Gras 
17992395e9cSLionel Sambuc 	printf("%s %s\n", progname, VERSION);
180d65f6f70SBen Gras 	exit((int)MANDOCLEVEL_OK);
181d65f6f70SBen Gras }
182d65f6f70SBen Gras 
183d65f6f70SBen Gras static void
usage(void)184d65f6f70SBen Gras usage(void)
185d65f6f70SBen Gras {
186d65f6f70SBen Gras 
18792395e9cSLionel Sambuc 	fprintf(stderr, "usage: %s "
188d65f6f70SBen Gras 			"[-V] "
189*0a6a1f1dSLionel Sambuc 			"[-Ios=name] "
190d65f6f70SBen Gras 			"[-mformat] "
191d65f6f70SBen Gras 			"[-Ooption] "
192d65f6f70SBen Gras 			"[-Toutput] "
193*0a6a1f1dSLionel Sambuc 			"[-Wlevel]\n"
194*0a6a1f1dSLionel Sambuc 			"\t      [file ...]\n",
195d65f6f70SBen Gras 			progname);
196d65f6f70SBen Gras 
197d65f6f70SBen Gras 	exit((int)MANDOCLEVEL_BADARG);
198d65f6f70SBen Gras }
199d65f6f70SBen Gras 
200d65f6f70SBen Gras static void
parse(struct curparse * curp,int fd,const char * file,enum mandoclevel * level)20192395e9cSLionel Sambuc parse(struct curparse *curp, int fd,
20292395e9cSLionel Sambuc 		const char *file, enum mandoclevel *level)
203d65f6f70SBen Gras {
20492395e9cSLionel Sambuc 	enum mandoclevel  rc;
20592395e9cSLionel Sambuc 	struct mdoc	 *mdoc;
20692395e9cSLionel Sambuc 	struct man	 *man;
207d65f6f70SBen Gras 
20892395e9cSLionel Sambuc 	/* Begin by parsing the file itself. */
209d65f6f70SBen Gras 
21092395e9cSLionel Sambuc 	assert(file);
21192395e9cSLionel Sambuc 	assert(fd >= -1);
212d65f6f70SBen Gras 
21392395e9cSLionel Sambuc 	rc = mparse_readfd(curp->mp, fd, file);
214d65f6f70SBen Gras 
21592395e9cSLionel Sambuc 	/* Stop immediately if the parse has failed. */
216d65f6f70SBen Gras 
21792395e9cSLionel Sambuc 	if (MANDOCLEVEL_FATAL <= rc)
218d65f6f70SBen Gras 		goto cleanup;
219d65f6f70SBen Gras 
220d65f6f70SBen Gras 	/*
22192395e9cSLionel Sambuc 	 * With -Wstop and warnings or errors of at least the requested
22292395e9cSLionel Sambuc 	 * level, do not produce output.
223d65f6f70SBen Gras 	 */
224d65f6f70SBen Gras 
22592395e9cSLionel Sambuc 	if (MANDOCLEVEL_OK != rc && curp->wstop)
226d65f6f70SBen Gras 		goto cleanup;
227d65f6f70SBen Gras 
228d65f6f70SBen Gras 	/* If unset, allocate output dev now (if applicable). */
229d65f6f70SBen Gras 
230d65f6f70SBen Gras 	if ( ! (curp->outman && curp->outmdoc)) {
231d65f6f70SBen Gras 		switch (curp->outtype) {
232d65f6f70SBen Gras 		case (OUTT_XHTML):
233d65f6f70SBen Gras 			curp->outdata = xhtml_alloc(curp->outopts);
23492395e9cSLionel Sambuc 			curp->outfree = html_free;
235d65f6f70SBen Gras 			break;
236d65f6f70SBen Gras 		case (OUTT_HTML):
237d65f6f70SBen Gras 			curp->outdata = html_alloc(curp->outopts);
23892395e9cSLionel Sambuc 			curp->outfree = html_free;
23992395e9cSLionel Sambuc 			break;
24092395e9cSLionel Sambuc 		case (OUTT_UTF8):
24192395e9cSLionel Sambuc 			curp->outdata = utf8_alloc(curp->outopts);
24292395e9cSLionel Sambuc 			curp->outfree = ascii_free;
24392395e9cSLionel Sambuc 			break;
24492395e9cSLionel Sambuc 		case (OUTT_LOCALE):
24592395e9cSLionel Sambuc 			curp->outdata = locale_alloc(curp->outopts);
24692395e9cSLionel Sambuc 			curp->outfree = ascii_free;
247d65f6f70SBen Gras 			break;
248d65f6f70SBen Gras 		case (OUTT_ASCII):
249d65f6f70SBen Gras 			curp->outdata = ascii_alloc(curp->outopts);
250d65f6f70SBen Gras 			curp->outfree = ascii_free;
251d65f6f70SBen Gras 			break;
252d65f6f70SBen Gras 		case (OUTT_PDF):
253d65f6f70SBen Gras 			curp->outdata = pdf_alloc(curp->outopts);
254d65f6f70SBen Gras 			curp->outfree = pspdf_free;
255d65f6f70SBen Gras 			break;
256d65f6f70SBen Gras 		case (OUTT_PS):
257d65f6f70SBen Gras 			curp->outdata = ps_alloc(curp->outopts);
258d65f6f70SBen Gras 			curp->outfree = pspdf_free;
259d65f6f70SBen Gras 			break;
260d65f6f70SBen Gras 		default:
261d65f6f70SBen Gras 			break;
262d65f6f70SBen Gras 		}
263d65f6f70SBen Gras 
264d65f6f70SBen Gras 		switch (curp->outtype) {
265d65f6f70SBen Gras 		case (OUTT_HTML):
266d65f6f70SBen Gras 			/* FALLTHROUGH */
267d65f6f70SBen Gras 		case (OUTT_XHTML):
268d65f6f70SBen Gras 			curp->outman = html_man;
269d65f6f70SBen Gras 			curp->outmdoc = html_mdoc;
270d65f6f70SBen Gras 			break;
271d65f6f70SBen Gras 		case (OUTT_TREE):
272d65f6f70SBen Gras 			curp->outman = tree_man;
273d65f6f70SBen Gras 			curp->outmdoc = tree_mdoc;
274d65f6f70SBen Gras 			break;
27592395e9cSLionel Sambuc 		case (OUTT_MAN):
27692395e9cSLionel Sambuc 			curp->outmdoc = man_mdoc;
27792395e9cSLionel Sambuc 			curp->outman = man_man;
27892395e9cSLionel Sambuc 			break;
279d65f6f70SBen Gras 		case (OUTT_PDF):
280d65f6f70SBen Gras 			/* FALLTHROUGH */
281d65f6f70SBen Gras 		case (OUTT_ASCII):
282d65f6f70SBen Gras 			/* FALLTHROUGH */
28392395e9cSLionel Sambuc 		case (OUTT_UTF8):
28492395e9cSLionel Sambuc 			/* FALLTHROUGH */
28592395e9cSLionel Sambuc 		case (OUTT_LOCALE):
28692395e9cSLionel Sambuc 			/* FALLTHROUGH */
287d65f6f70SBen Gras 		case (OUTT_PS):
288d65f6f70SBen Gras 			curp->outman = terminal_man;
289d65f6f70SBen Gras 			curp->outmdoc = terminal_mdoc;
290d65f6f70SBen Gras 			break;
291d65f6f70SBen Gras 		default:
292d65f6f70SBen Gras 			break;
293d65f6f70SBen Gras 		}
294d65f6f70SBen Gras 	}
295d65f6f70SBen Gras 
29692395e9cSLionel Sambuc 	mparse_result(curp->mp, &mdoc, &man);
29792395e9cSLionel Sambuc 
298d65f6f70SBen Gras 	/* Execute the out device, if it exists. */
299d65f6f70SBen Gras 
30092395e9cSLionel Sambuc 	if (man && curp->outman)
30192395e9cSLionel Sambuc 		(*curp->outman)(curp->outdata, man);
30292395e9cSLionel Sambuc 	if (mdoc && curp->outmdoc)
30392395e9cSLionel Sambuc 		(*curp->outmdoc)(curp->outdata, mdoc);
304d65f6f70SBen Gras 
305d65f6f70SBen Gras  cleanup:
306d65f6f70SBen Gras 
30792395e9cSLionel Sambuc 	mparse_reset(curp->mp);
308d65f6f70SBen Gras 
30992395e9cSLionel Sambuc 	if (*level < rc)
31092395e9cSLionel Sambuc 		*level = rc;
311d65f6f70SBen Gras }
312d65f6f70SBen Gras 
313d65f6f70SBen Gras static int
moptions(enum mparset * tflags,char * arg)31492395e9cSLionel Sambuc moptions(enum mparset *tflags, char *arg)
315d65f6f70SBen Gras {
316d65f6f70SBen Gras 
317d65f6f70SBen Gras 	if (0 == strcmp(arg, "doc"))
31892395e9cSLionel Sambuc 		*tflags = MPARSE_MDOC;
319d65f6f70SBen Gras 	else if (0 == strcmp(arg, "andoc"))
32092395e9cSLionel Sambuc 		*tflags = MPARSE_AUTO;
321d65f6f70SBen Gras 	else if (0 == strcmp(arg, "an"))
32292395e9cSLionel Sambuc 		*tflags = MPARSE_MAN;
323d65f6f70SBen Gras 	else {
324d65f6f70SBen Gras 		fprintf(stderr, "%s: Bad argument\n", arg);
325d65f6f70SBen Gras 		return(0);
326d65f6f70SBen Gras 	}
327d65f6f70SBen Gras 
328d65f6f70SBen Gras 	return(1);
329d65f6f70SBen Gras }
330d65f6f70SBen Gras 
331d65f6f70SBen Gras static int
toptions(struct curparse * curp,char * arg)332d65f6f70SBen Gras toptions(struct curparse *curp, char *arg)
333d65f6f70SBen Gras {
334d65f6f70SBen Gras 
335d65f6f70SBen Gras 	if (0 == strcmp(arg, "ascii"))
336d65f6f70SBen Gras 		curp->outtype = OUTT_ASCII;
337d65f6f70SBen Gras 	else if (0 == strcmp(arg, "lint")) {
338d65f6f70SBen Gras 		curp->outtype = OUTT_LINT;
339d65f6f70SBen Gras 		curp->wlevel  = MANDOCLEVEL_WARNING;
34092395e9cSLionel Sambuc 	} else if (0 == strcmp(arg, "tree"))
341d65f6f70SBen Gras 		curp->outtype = OUTT_TREE;
34292395e9cSLionel Sambuc 	else if (0 == strcmp(arg, "man"))
34392395e9cSLionel Sambuc 		curp->outtype = OUTT_MAN;
344d65f6f70SBen Gras 	else if (0 == strcmp(arg, "html"))
345d65f6f70SBen Gras 		curp->outtype = OUTT_HTML;
34692395e9cSLionel Sambuc 	else if (0 == strcmp(arg, "utf8"))
34792395e9cSLionel Sambuc 		curp->outtype = OUTT_UTF8;
34892395e9cSLionel Sambuc 	else if (0 == strcmp(arg, "locale"))
34992395e9cSLionel Sambuc 		curp->outtype = OUTT_LOCALE;
350d65f6f70SBen Gras 	else if (0 == strcmp(arg, "xhtml"))
351d65f6f70SBen Gras 		curp->outtype = OUTT_XHTML;
352d65f6f70SBen Gras 	else if (0 == strcmp(arg, "ps"))
353d65f6f70SBen Gras 		curp->outtype = OUTT_PS;
354d65f6f70SBen Gras 	else if (0 == strcmp(arg, "pdf"))
355d65f6f70SBen Gras 		curp->outtype = OUTT_PDF;
356d65f6f70SBen Gras 	else {
357d65f6f70SBen Gras 		fprintf(stderr, "%s: Bad argument\n", arg);
358d65f6f70SBen Gras 		return(0);
359d65f6f70SBen Gras 	}
360d65f6f70SBen Gras 
361d65f6f70SBen Gras 	return(1);
362d65f6f70SBen Gras }
363d65f6f70SBen Gras 
364d65f6f70SBen Gras static int
woptions(struct curparse * curp,char * arg)365d65f6f70SBen Gras woptions(struct curparse *curp, char *arg)
366d65f6f70SBen Gras {
367d65f6f70SBen Gras 	char		*v, *o;
368d65f6f70SBen Gras 	const char	*toks[6];
369d65f6f70SBen Gras 
370d65f6f70SBen Gras 	toks[0] = "stop";
371d65f6f70SBen Gras 	toks[1] = "all";
372d65f6f70SBen Gras 	toks[2] = "warning";
373d65f6f70SBen Gras 	toks[3] = "error";
374d65f6f70SBen Gras 	toks[4] = "fatal";
375d65f6f70SBen Gras 	toks[5] = NULL;
376d65f6f70SBen Gras 
377d65f6f70SBen Gras 	while (*arg) {
378d65f6f70SBen Gras 		o = arg;
379d65f6f70SBen Gras 		switch (getsubopt(&arg, UNCONST(toks), &v)) {
380d65f6f70SBen Gras 		case (0):
381d65f6f70SBen Gras 			curp->wstop = 1;
382d65f6f70SBen Gras 			break;
383d65f6f70SBen Gras 		case (1):
384d65f6f70SBen Gras 			/* FALLTHROUGH */
385d65f6f70SBen Gras 		case (2):
386d65f6f70SBen Gras 			curp->wlevel = MANDOCLEVEL_WARNING;
387d65f6f70SBen Gras 			break;
388d65f6f70SBen Gras 		case (3):
389d65f6f70SBen Gras 			curp->wlevel = MANDOCLEVEL_ERROR;
390d65f6f70SBen Gras 			break;
391d65f6f70SBen Gras 		case (4):
392d65f6f70SBen Gras 			curp->wlevel = MANDOCLEVEL_FATAL;
393d65f6f70SBen Gras 			break;
394d65f6f70SBen Gras 		default:
395d65f6f70SBen Gras 			fprintf(stderr, "-W%s: Bad argument\n", o);
396d65f6f70SBen Gras 			return(0);
397d65f6f70SBen Gras 		}
398d65f6f70SBen Gras 	}
399d65f6f70SBen Gras 
400d65f6f70SBen Gras 	return(1);
401d65f6f70SBen Gras }
402d65f6f70SBen Gras 
40392395e9cSLionel Sambuc static void
mmsg(enum mandocerr t,enum mandoclevel lvl,const char * file,int line,int col,const char * msg)40492395e9cSLionel Sambuc mmsg(enum mandocerr t, enum mandoclevel lvl,
40592395e9cSLionel Sambuc 		const char *file, int line, int col, const char *msg)
406d65f6f70SBen Gras {
407d65f6f70SBen Gras 
408d65f6f70SBen Gras 	fprintf(stderr, "%s:%d:%d: %s: %s",
40992395e9cSLionel Sambuc 			file, line, col + 1,
41092395e9cSLionel Sambuc 			mparse_strlevel(lvl),
41192395e9cSLionel Sambuc 			mparse_strerror(t));
41292395e9cSLionel Sambuc 
413d65f6f70SBen Gras 	if (msg)
414d65f6f70SBen Gras 		fprintf(stderr, ": %s", msg);
41592395e9cSLionel Sambuc 
416d65f6f70SBen Gras 	fputc('\n', stderr);
417d65f6f70SBen Gras }
418