source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mandoc.bsd.lv
To: source@mandoc.bsd.lv
Subject: mandoc: Some time ago, i simplified mandoc_msg() such that it can be
Date: Wed, 10 Jul 2019 14:39:32 -0500 (EST)	[thread overview]
Message-ID: <8629f1b724761ac4@mandoc.bsd.lv> (raw)

Log Message:
-----------
Some time ago, i simplified mandoc_msg() such that it can be used 
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one 
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.

Modified Files:
--------------
    mandoc:
        Makefile.depend
        main.c
        mandoc.1
        mandoc.h
        mandoc_msg.c
        manpath.c
        read.c
        tag.c

Revision Data
-------------
Index: mandoc_msg.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/mandoc_msg.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -Lmandoc_msg.c -Lmandoc_msg.c -u -p -r1.6 -r1.7
--- mandoc_msg.c
+++ mandoc_msg.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014,2015,2016,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014-2019 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
@@ -29,8 +29,8 @@ static	const enum mandocerr lowest_type[
 	MANDOCERR_WARNING,
 	MANDOCERR_ERROR,
 	MANDOCERR_UNSUPP,
-	MANDOCERR_MAX,
-	MANDOCERR_MAX
+	MANDOCERR_BADARG,
+	MANDOCERR_SYSERR
 };
 
 static	const char *const level_name[MANDOCLEVEL_MAX] = {
@@ -193,7 +193,6 @@ static	const char *const type_message[MA
 	"data block open at end of tbl",
 
 	/* related to document structure and macros */
-	NULL,
 	"duplicate prologue macro",
 	"skipping late title macro",
 	"input stack limit exceeded, infinite loop?",
@@ -240,11 +239,40 @@ static	const char *const type_message[MA
 	"eqn delim option in tbl",
 	"unsupported tbl layout modifier",
 	"ignoring macro in table",
+
+	/* bad command line arguments */
+	NULL,
+	"bad command line argument",
+	"duplicate command line argument",
+	"option has a superfluous value",
+	"missing option value",
+	"bad option value",
+	"duplicate option value",
+	"no such tag",
+
+	/* system errors */
+	NULL,
+	"dup",
+	"exec",
+	"fdopen",
+	"fflush",
+	"fork",
+	"fstat",
+	"getline",
+	"glob",
+	"gzclose",
+	"gzdopen",
+	"mkstemp",
+	"open",
+	"pledge",
+	"read",
+	"wait",
+	"write",
 };
 
 static	FILE		*fileptr = NULL;
 static	const char	*filename = NULL;
-static	enum mandocerr	 min_type = MANDOCERR_MAX;
+static	enum mandocerr	 min_type = MANDOCERR_BADARG;
 static	enum mandoclevel rc = MANDOCLEVEL_OK;
 
 
@@ -297,10 +325,10 @@ mandoc_msg(enum mandocerr t, int line, i
 	va_list			 ap;
 	enum mandoclevel	 level;
 
-	if (t < min_type && t != MANDOCERR_FILE)
+	if (t < min_type)
 		return;
 
-	level = MANDOCLEVEL_UNSUPP;
+	level = MANDOCLEVEL_SYSERR;
 	while (t < lowest_type[level])
 		level--;
 	mandoc_msg_setrc(level);
Index: Makefile.depend
===================================================================
RCS file: /home/cvs/mandoc/mandoc/Makefile.depend,v
retrieving revision 1.43
retrieving revision 1.44
diff -LMakefile.depend -LMakefile.depend -u -p -r1.43 -r1.44
--- Makefile.depend
+++ Makefile.depend
@@ -46,7 +46,7 @@ mandoc_ohash.o: mandoc_ohash.c mandoc_au
 mandoc_xr.o: mandoc_xr.c mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc_xr.h
 mandocd.o: mandocd.c config.h mandoc.h roff.h mdoc.h man.h mandoc_parse.h main.h manconf.h
 mandocdb.o: mandocdb.c config.h compat_fts.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h mdoc.h man.h mandoc_parse.h manconf.h mansearch.h dba_array.h dba.h
-manpath.o: manpath.c config.h mandoc_aux.h manconf.h
+manpath.o: manpath.c config.h mandoc_aux.h mandoc.h manconf.h
 mansearch.o: mansearch.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h manconf.h mansearch.h dbm.h
 mdoc.o: mdoc.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
 mdoc_argv.o: mdoc_argv.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
@@ -67,7 +67,7 @@ roff_term.o: roff_term.c mandoc.h roff.h
 roff_validate.o: roff_validate.c mandoc.h roff.h libmandoc.h roff_int.h
 soelim.o: soelim.c config.h compat_stringlist.h
 st.o: st.c config.h mandoc.h roff.h libmdoc.h
-tag.o: tag.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h tag.h
+tag.o: tag.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h tag.h
 tbl.o: tbl.c config.h mandoc_aux.h mandoc.h tbl.h libmandoc.h tbl_parse.h tbl_int.h
 tbl_data.o: tbl_data.c config.h mandoc_aux.h mandoc.h tbl.h libmandoc.h tbl_int.h
 tbl_html.o: tbl_html.c config.h mandoc.h roff.h tbl.h out.h html.h
Index: main.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/main.c,v
retrieving revision 1.328
retrieving revision 1.329
diff -Lmain.c -Lmain.c -u -p -r1.328 -r1.329
--- main.c
+++ main.c
@@ -98,13 +98,10 @@ static	int		  fs_lookup(const struct man
 static	int		  fs_search(const struct mansearch *,
 				const struct manpaths *, int, char**,
 				struct manpage **, size_t *);
-static	int		  koptions(int *, char *);
-static	void		  moptions(int *, char *);
 static	void		  outdata_alloc(struct curparse *);
 static	void		  parse(struct curparse *, int, const char *);
-static	void		  passthrough(const char *, int, int);
+static	void		  passthrough(int, int);
 static	pid_t		  spawn_pager(struct tag_files *);
-static	int		  toptions(struct curparse *, char *);
 static	void		  usage(enum argmode) __attribute__((__noreturn__));
 static	int		  woptions(struct curparse *, char *);
 
@@ -155,10 +152,11 @@ main(int argc, char *argv[])
 		return mandocdb(argc, argv);
 
 #if HAVE_PLEDGE
-	if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1)
-		err((int)MANDOCLEVEL_SYSERR, "pledge");
+	if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) {
+		mandoc_msg(MANDOCERR_PLEDGE, 0, 0, "%s", strerror(errno));
+		return mandoc_msg_getrc();
+	}
 #endif
-
 #if HAVE_SANDBOX_INIT
 	if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1)
 		errx((int)MANDOCLEVEL_SYSERR, "sandbox_init");
@@ -222,19 +220,29 @@ main(int argc, char *argv[])
 			outmode = OUTMODE_ALL;
 			break;
 		case 'I':
-			if (strncmp(optarg, "os=", 3)) {
-				warnx("-I %s: Bad argument", optarg);
-				return (int)MANDOCLEVEL_BADARG;
+			if (strncmp(optarg, "os=", 3) != 0) {
+				mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0,
+				    "-I %s", optarg);
+				return mandoc_msg_getrc();
 			}
 			if (curp.os_s != NULL) {
-				warnx("-I %s: Duplicate argument", optarg);
-				return (int)MANDOCLEVEL_BADARG;
+				mandoc_msg(MANDOCERR_BADARG_DUPE, 0, 0,
+				    "-I %s", optarg);
+				return mandoc_msg_getrc();
 			}
 			curp.os_s = mandoc_strdup(optarg + 3);
 			break;
 		case 'K':
-			if ( ! koptions(&options, optarg))
-				return (int)MANDOCLEVEL_BADARG;
+			options &= ~(MPARSE_UTF8 | MPARSE_LATIN1);
+			if (strcmp(optarg, "utf-8") == 0)
+				options |=  MPARSE_UTF8;
+			else if (strcmp(optarg, "iso-8859-1") == 0)
+				options |=  MPARSE_LATIN1;
+			else if (strcmp(optarg, "us-ascii") != 0) {
+				mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0,
+				    "-K %s", optarg);
+				return mandoc_msg_getrc();
+			}
 			break;
 		case 'k':
 			search.argmode = ARG_EXPR;
@@ -259,12 +267,37 @@ main(int argc, char *argv[])
 			search.sec = optarg;
 			break;
 		case 'T':
-			if ( ! toptions(&curp, optarg))
-				return (int)MANDOCLEVEL_BADARG;
+			if (strcmp(optarg, "ascii") == 0)
+				curp.outtype = OUTT_ASCII;
+			else if (strcmp(optarg, "lint") == 0) {
+				curp.outtype = OUTT_LINT;
+				mandoc_msg_setoutfile(stdout);
+				mandoc_msg_setmin(MANDOCERR_BASE);
+			} else if (strcmp(optarg, "tree") == 0)
+				curp.outtype = OUTT_TREE;
+			else if (strcmp(optarg, "man") == 0)
+				curp.outtype = OUTT_MAN;
+			else if (strcmp(optarg, "html") == 0)
+				curp.outtype = OUTT_HTML;
+			else if (strcmp(optarg, "markdown") == 0)
+				curp.outtype = OUTT_MARKDOWN;
+			else if (strcmp(optarg, "utf8") == 0)
+				curp.outtype = OUTT_UTF8;
+			else if (strcmp(optarg, "locale") == 0)
+				curp.outtype = OUTT_LOCALE;
+			else if (strcmp(optarg, "ps") == 0)
+				curp.outtype = OUTT_PS;
+			else if (strcmp(optarg, "pdf") == 0)
+				curp.outtype = OUTT_PDF;
+			else {
+				mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0,
+				    "-T %s", optarg);
+				return mandoc_msg_getrc();
+			}
 			break;
 		case 'W':
-			if ( ! woptions(&curp, optarg))
-				return (int)MANDOCLEVEL_BADARG;
+			if (woptions(&curp, optarg) == -1)
+				return mandoc_msg_getrc();
 			break;
 		case 'w':
 			outmode = OUTMODE_FLN;
@@ -302,7 +335,7 @@ main(int argc, char *argv[])
 			while (oarg != NULL) {
 				if (manconf_output(&conf.output,
 				    strsep(&oarg, ","), 0) == -1)
-					return (int)MANDOCLEVEL_BADARG;
+					return mandoc_msg_getrc();
 			}
 		}
 	}
@@ -326,9 +359,13 @@ main(int argc, char *argv[])
 	}
 
 #if HAVE_PLEDGE
-	if (!use_pager)
-		if (pledge("stdio rpath", NULL) == -1)
-			err((int)MANDOCLEVEL_SYSERR, "pledge");
+	if (use_pager == 0) {
+		if (pledge("stdio rpath", NULL) == -1) {
+			mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
+			    "%s", strerror(errno));
+			return mandoc_msg_getrc();
+		}
+	}
 #endif
 
 	/* Parse arguments. */
@@ -393,7 +430,7 @@ main(int argc, char *argv[])
 			usage(search.argmode);
 
 		if (sz == 0 && search.argmode == ARG_NAME)
-			fs_search(&search, &conf.manpath,
+			(void)fs_search(&search, &conf.manpath,
 			    argc, argv, &res, &sz);
 
 		if (search.argmode == ARG_NAME) {
@@ -401,7 +438,10 @@ main(int argc, char *argv[])
 				if (strchr(argv[c], '/') == NULL)
 					continue;
 				if (access(argv[c], R_OK) == -1) {
-					warn("%s", argv[c]);
+					mandoc_msg_setinfilename(argv[c]);
+					mandoc_msg(MANDOCERR_BADARG_BAD,
+					    0, 0, "%s", strerror(errno));
+					mandoc_msg_setinfilename(NULL);
 					continue;
 				}
 				res = mandoc_reallocarray(res,
@@ -487,16 +527,26 @@ main(int argc, char *argv[])
 
 #if HAVE_PLEDGE
 	if (use_pager) {
-		if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1)
-			err((int)MANDOCLEVEL_SYSERR, "pledge");
+		if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) {
+			mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
+			    "%s", strerror(errno));
+			return mandoc_msg_getrc();
+		}
 	} else {
-		if (pledge("stdio rpath", NULL) == -1)
-			err((int)MANDOCLEVEL_SYSERR, "pledge");
+		if (pledge("stdio rpath", NULL) == -1) {
+			mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
+			    "%s", strerror(errno));
+			return mandoc_msg_getrc();
+		}
 	}
 #endif
 
-	if (search.argmode == ARG_FILE)
-		moptions(&options, auxpaths);
+	if (search.argmode == ARG_FILE && auxpaths != NULL) {
+		if (strcmp(auxpaths, "doc") == 0)
+			options |= MPARSE_MDOC;
+		else if (strcmp(auxpaths, "an") == 0)
+			options |= MPARSE_MAN;
+	}
 
 	mchars_alloc();
 	curp.mp = mparse_alloc(options, curp.os_e, curp.os_s);
@@ -538,6 +588,7 @@ main(int argc, char *argv[])
 		} else
 			thisarg = *argv;
 
+		mandoc_msg_setinfilename(thisarg);
 		fd = mparse_open(curp.mp, thisarg);
 		if (fd != -1) {
 			if (use_pager) {
@@ -547,22 +598,21 @@ main(int argc, char *argv[])
 					tag_files->tagname = conf.output.tag;
 			}
 
-			mandoc_msg_setinfilename(thisarg);
 			if (resp == NULL || resp->form == FORM_SRC)
 				parse(&curp, fd, thisarg);
 			else
-				passthrough(resp->file, fd,
-				    conf.output.synopsisonly);
-			mandoc_msg_setinfilename(NULL);
+				passthrough(fd, conf.output.synopsisonly);
 
 			if (ferror(stdout)) {
 				if (tag_files != NULL) {
-					warn("%s", tag_files->ofn);
+					mandoc_msg(MANDOCERR_WRITE, 0, 0,
+					    "%s: %s", tag_files->ofn,
+					    strerror(errno));
 					tag_unlink();
 					tag_files = NULL;
 				} else
-					warn("stdout");
-				mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
+					mandoc_msg(MANDOCERR_WRITE, 0, 0,
+					    "%s", strerror(errno));
 				break;
 			}
 
@@ -572,8 +622,10 @@ main(int argc, char *argv[])
 				terminal_sepline(curp.outdata);
 			}
 		} else
-			mandoc_msg(MANDOCERR_FILE, 0, 0,
-			    "%s: %s", thisarg, strerror(errno));
+			mandoc_msg(resp == NULL ? MANDOCERR_BADARG_BAD :
+			    MANDOCERR_OPEN, 0, 0, "%s", strerror(errno));
+
+		mandoc_msg_setinfilename(NULL);
 
 		if (curp.wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
 			break;
@@ -665,8 +717,8 @@ out:
 				continue;
 
 			if (pid == -1) {
-				warn("wait");
-				mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
+				mandoc_msg(MANDOCERR_WAIT, 0, 0,
+				    "%s", strerror(errno));
 				break;
 			}
 			if (!WIFSTOPPED(status))
@@ -682,7 +734,6 @@ out:
 static void
 usage(enum argmode argmode)
 {
-
 	switch (argmode) {
 	case ARG_FILE:
 		fputs("usage: mandoc [-ac] [-I os=name] "
@@ -747,7 +798,8 @@ fs_lookup(const struct manpaths *paths, 
 	    paths->paths[ipath], sec, name);
 	globres = glob(file, 0, NULL, &globinfo);
 	if (globres != 0 && globres != GLOB_NOMATCH)
-		warn("%s: glob", file);
+		mandoc_msg(MANDOCERR_GLOB, 0, 0,
+		    "%s: %s", file, strerror(errno));
 	free(file);
 	if (globres == 0)
 		file = mandoc_strdup(*globinfo.gl_pathv);
@@ -758,21 +810,21 @@ fs_lookup(const struct manpaths *paths, 
 		free(file);
 	}
 	if (res != NULL || ipath + 1 != paths->sz)
-		return 0;
+		return -1;
 
 	mandoc_asprintf(&file, "%s.%s", name, sec);
 	globres = stat(file, &sb);
 	free(file);
-	return globres != -1;
+	return globres;
 
 found:
 	warnx("outdated mandoc.db lacks %s(%s) entry, run %s %s",
 	    name, sec, BINM_MAKEWHATIS, paths->paths[ipath]);
 	if (res == NULL) {
 		free(file);
-		return 1;
+		return 0;
 	}
-	*res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage));
+	*res = mandoc_reallocarray(*res, ++*ressz, sizeof(**res));
 	page = *res + (*ressz - 1);
 	page->file = file;
 	page->names = NULL;
@@ -781,7 +833,7 @@ found:
 	page->ipath = ipath;
 	page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10;
 	page->form = form;
-	return 1;
+	return 0;
 }
 
 static int
@@ -803,14 +855,14 @@ fs_search(const struct mansearch *cfg, c
 		for (ipath = 0; ipath < paths->sz; ipath++) {
 			if (cfg->sec != NULL) {
 				if (fs_lookup(paths, ipath, cfg->sec,
-				    cfg->arch, *argv, res, ressz) &&
+				    cfg->arch, *argv, res, ressz) != -1 &&
 				    cfg->firstmatch)
-					return 1;
+					return 0;
 			} else for (isec = 0; isec < nsec; isec++)
 				if (fs_lookup(paths, ipath, sections[isec],
-				    cfg->arch, *argv, res, ressz) &&
+				    cfg->arch, *argv, res, ressz) != -1 &&
 				    cfg->firstmatch)
-					return 1;
+					return 0;
 		}
 		if (res != NULL && *ressz == lastsz &&
 		    strchr(*argv, '/') == NULL) {
@@ -829,7 +881,7 @@ fs_search(const struct mansearch *cfg, c
 		argv++;
 		argc--;
 	}
-	return 0;
+	return -1;
 }
 
 static void
@@ -936,7 +988,7 @@ check_xr(void)
 		search.firstmatch = 1;
 		if (mansearch(&search, &paths, 1, &xr->name, NULL, &sz))
 			continue;
-		if (fs_search(&search, &paths, 1, &xr->name, NULL, &sz))
+		if (fs_search(&search, &paths, 1, &xr->name, NULL, &sz) != -1)
 			continue;
 		if (xr->count == 1)
 			mandoc_msg(MANDOCERR_XR_BAD, xr->line,
@@ -976,34 +1028,34 @@ outdata_alloc(struct curparse *curp)
 }
 
 static void
-passthrough(const char *file, int fd, int synopsis_only)
+passthrough(int fd, int synopsis_only)
 {
 	const char	 synb[] = "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS";
 	const char	 synr[] = "SYNOPSIS";
 
 	FILE		*stream;
-	const char	*syscall;
 	char		*line, *cp;
 	size_t		 linesz;
 	ssize_t		 len, written;
-	int		 print;
+	int		 lno, print;
 
+	stream = NULL;
 	line = NULL;
 	linesz = 0;
 
 	if (fflush(stdout) == EOF) {
-		syscall = "fflush";
-		goto fail;
+		mandoc_msg(MANDOCERR_FFLUSH, 0, 0, "%s", strerror(errno));
+		goto done;
 	}
-
 	if ((stream = fdopen(fd, "r")) == NULL) {
 		close(fd);
-		syscall = "fdopen";
-		goto fail;
+		mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno));
+		goto done;
 	}
 
-	print = 0;
+	lno = print = 0;
 	while ((len = getline(&line, &linesz, stream)) != -1) {
+		lno++;
 		cp = line;
 		if (synopsis_only) {
 			if (print) {
@@ -1021,94 +1073,20 @@ passthrough(const char *file, int fd, in
 			}
 		}
 		for (; len > 0; len -= written) {
-			if ((written = write(STDOUT_FILENO, cp, len)) != -1)
-				continue;
-			fclose(stream);
-			syscall = "write";
-			goto fail;
+			if ((written = write(STDOUT_FILENO, cp, len)) == -1) {
+				mandoc_msg(MANDOCERR_WRITE, 0, 0,
+				    "%s", strerror(errno));
+				goto done;
+			}
 		}
 	}
-
-	if (ferror(stream)) {
-		fclose(stream);
-		syscall = "getline";
-		goto fail;
-	}
+	if (ferror(stream))
+		mandoc_msg(MANDOCERR_GETLINE, lno, 0, "%s", strerror(errno));
 
 done:
 	free(line);
-	fclose(stream);
-	return;
-
-fail:
-	free(line);
-	warn("%s: SYSERR: %s", file, syscall);
-	mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
-}
-
-static int
-koptions(int *options, char *arg)
-{
-
-	if ( ! strcmp(arg, "utf-8")) {
-		*options |=  MPARSE_UTF8;
-		*options &= ~MPARSE_LATIN1;
-	} else if ( ! strcmp(arg, "iso-8859-1")) {
-		*options |=  MPARSE_LATIN1;
-		*options &= ~MPARSE_UTF8;
-	} else if ( ! strcmp(arg, "us-ascii")) {
-		*options &= ~(MPARSE_UTF8 | MPARSE_LATIN1);
-	} else {
-		warnx("-K %s: Bad argument", arg);
-		return 0;
-	}
-	return 1;
-}
-
-static void
-moptions(int *options, char *arg)
-{
-
-	if (arg == NULL)
-		return;
-	if (strcmp(arg, "doc") == 0)
-		*options |= MPARSE_MDOC;
-	else if (strcmp(arg, "an") == 0)
-		*options |= MPARSE_MAN;
-}
-
-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;
-		mandoc_msg_setoutfile(stdout);
-		mandoc_msg_setmin(MANDOCERR_BASE);
-	} 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, "markdown"))
-		curp->outtype = OUTT_MARKDOWN;
-	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, "ps"))
-		curp->outtype = OUTT_PS;
-	else if (0 == strcmp(arg, "pdf"))
-		curp->outtype = OUTT_PDF;
-	else {
-		warnx("-T %s: Bad argument", arg);
-		return 0;
-	}
-
-	return 1;
+	if (stream != NULL)
+		fclose(stream);
 }
 
 static int
@@ -1152,7 +1130,7 @@ woptions(struct curparse *curp, char *ar
 			mandoc_msg_setmin(MANDOCERR_UNSUPP);
 			break;
 		case 7:
-			mandoc_msg_setmin(MANDOCERR_MAX);
+			mandoc_msg_setmin(MANDOCERR_BADARG);
 			break;
 		case 8:
 			mandoc_msg_setmin(MANDOCERR_BASE);
@@ -1163,11 +1141,11 @@ woptions(struct curparse *curp, char *ar
 			curp->os_e = MANDOC_OS_NETBSD;
 			break;
 		default:
-			warnx("-W %s: Bad argument", o);
-			return 0;
+			mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, "-W %s", o);
+			return -1;
 		}
 	}
-	return 1;
+	return 0;
 }
 
 static pid_t
@@ -1232,15 +1210,19 @@ spawn_pager(struct tag_files *tag_files)
 
 	switch (pager_pid = fork()) {
 	case -1:
-		err((int)MANDOCLEVEL_SYSERR, "fork");
+		mandoc_msg(MANDOCERR_FORK, 0, 0, "%s", strerror(errno));
+		exit(mandoc_msg_getrc());
 	case 0:
 		break;
 	default:
 		(void)setpgid(pager_pid, 0);
 		(void)tcsetpgrp(tag_files->ofd, pager_pid);
 #if HAVE_PLEDGE
-		if (pledge("stdio rpath tmppath tty proc", NULL) == -1)
-			err((int)MANDOCLEVEL_SYSERR, "pledge");
+		if (pledge("stdio rpath tmppath tty proc", NULL) == -1) {
+			mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
+			    "%s", strerror(errno));
+			exit(mandoc_msg_getrc());
+		}
 #endif
 		tag_files->pager_pid = pager_pid;
 		return pager_pid;
@@ -1248,8 +1230,10 @@ spawn_pager(struct tag_files *tag_files)
 
 	/* The child process becomes the pager. */
 
-	if (dup2(tag_files->ofd, STDOUT_FILENO) == -1)
-		err((int)MANDOCLEVEL_SYSERR, "pager stdout");
+	if (dup2(tag_files->ofd, STDOUT_FILENO) == -1) {
+		mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
+		_exit(mandoc_msg_getrc());
+	}
 	close(tag_files->ofd);
 	assert(tag_files->tfd == -1);
 
@@ -1259,5 +1243,6 @@ spawn_pager(struct tag_files *tag_files)
 		nanosleep(&timeout, NULL);
 
 	execvp(argv[0], argv);
-	err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]);
+	mandoc_msg(MANDOCERR_EXEC, 0, 0, "%s: %s", argv[0], strerror(errno));
+	_exit(mandoc_msg_getrc());
 }
Index: mandoc.h
===================================================================
RCS file: /home/cvs/mandoc/mandoc/mandoc.h,v
retrieving revision 1.262
retrieving revision 1.263
diff -Lmandoc.h -Lmandoc.h -u -p -r1.262 -r1.263
--- mandoc.h
+++ mandoc.h
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012-2019 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
@@ -193,7 +193,6 @@ enum	mandocerr {
 	MANDOCERR_TBLDATA_BLK, /* data block open at end of tbl: macro */
 
 	/* related to document structure and macros */
-	MANDOCERR_FILE, /* cannot open file */
 	MANDOCERR_PROLOG_REP, /* duplicate prologue macro: macro */
 	MANDOCERR_DT_LATE, /* skipping late title macro: Dt args */
 	MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
@@ -241,6 +240,35 @@ enum	mandocerr {
 	MANDOCERR_TBLOPT_EQN, /* eqn delim option in tbl: arg */
 	MANDOCERR_TBLLAYOUT_MOD, /* unsupported tbl layout modifier: m */
 	MANDOCERR_TBLMACRO, /* ignoring macro in table: macro */
+
+	MANDOCERR_BADARG, /* ===== start of bad invocations ===== */
+
+	MANDOCERR_BADARG_BAD, /* bad argument */
+	MANDOCERR_BADARG_DUPE, /* duplicate argument */
+	MANDOCERR_BADVAL, /* does not take a value */
+	MANDOCERR_BADVAL_MISS, /* missing argument value */
+	MANDOCERR_BADVAL_BAD, /* bad argument value */
+	MANDOCERR_BADVAL_DUPE, /* duplicate argument value */
+	MANDOCERR_TAG, /* no such tag */
+
+	MANDOCERR_SYSERR, /* ===== start of system errors ===== */
+
+	MANDOCERR_DUP,
+	MANDOCERR_EXEC,
+	MANDOCERR_FDOPEN,
+	MANDOCERR_FFLUSH,
+	MANDOCERR_FORK,
+	MANDOCERR_FSTAT,
+	MANDOCERR_GETLINE,
+	MANDOCERR_GLOB,
+	MANDOCERR_GZCLOSE,
+	MANDOCERR_GZDOPEN,
+	MANDOCERR_MKSTEMP,
+	MANDOCERR_OPEN,
+	MANDOCERR_PLEDGE,
+	MANDOCERR_READ,
+	MANDOCERR_WAIT,
+	MANDOCERR_WRITE,
 
 	MANDOCERR_MAX
 };
Index: mandoc.1
===================================================================
RCS file: /home/cvs/mandoc/mandoc/mandoc.1,v
retrieving revision 1.239
retrieving revision 1.240
diff -Lmandoc.1 -Lmandoc.1 -u -p -r1.239 -r1.240
--- mandoc.1
+++ mandoc.1
@@ -1,7 +1,7 @@
 .\"	$Id$
 .\"
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2012, 2014-2018 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2012, 2014-2019 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
@@ -698,7 +698,7 @@ No input files have been read.
 .It 6
 An operating system error occurred, for example exhaustion
 of memory, file descriptors, or process table entries.
-Such errors cause
+Such errors may cause
 .Nm
 to exit at once, possibly in the middle of parsing or formatting a file.
 .El
@@ -778,6 +778,13 @@ fields.
 .Pp
 Message levels have the following meanings:
 .Bl -tag -width "warning"
+.It Cm syserr
+An operating system error occurred.
+There isn't necessarily anything wrong with the input files.
+Output may all the same be missing or incomplete.
+.It Cm badarg
+Invalid command line arguments were specified.
+No input files have been read and no output is produced.
 .It Cm unsupp
 An input file uses unsupported low-level
 .Xr roff 7
@@ -826,8 +833,7 @@ Messages of the
 .Cm error ,
 and
 .Cm unsupp
-levels except those about non-existent or unreadable input files
-are hidden unless their level, or a lower level, is requested using a
+levels are hidden unless their level, or a lower level, is requested using a
 .Fl W
 option or
 .Fl T Cm lint
@@ -2241,6 +2247,43 @@ or
 macro or of an undefined macro.
 The macro is ignored, and its arguments are handled
 as if they were a text line.
+.El
+.Ss Bad command line arguments
+.Bl -ohang
+.It Sy "bad command line argument"
+The argument following one of the
+.Fl IKMmOTW
+command line options is invalid, or a
+.Ar file
+given as a command line argument cannot be opened.
+.It Sy "duplicate command line argument"
+The
+.Fl I
+command line option was specified twice.
+.It Sy "option has a superfluous value"
+An argument to the
+.Fl O
+option has a value but does not accept one.
+.It Sy "missing option value"
+An argument to the
+.Fl O
+option has no argument but requires one.
+.It Sy "bad option value"
+An argument to the
+.Fl O
+.Cm indent
+or
+.Cm width
+option has an invalid value.
+.It Sy "duplicate option value"
+The same
+.Fl O
+option is specified more than once.
+.It Sy "no such tag"
+The
+.Fl O Cm tag
+option was specified but the tag was not found in any of the displayed
+manual pages.
 .El
 .Sh SEE ALSO
 .Xr apropos 1 ,
Index: read.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/read.c,v
retrieving revision 1.213
retrieving revision 1.214
diff -Lread.c -Lread.c -u -p -r1.213 -r1.214
--- read.c
+++ read.c
@@ -431,9 +431,8 @@ read_whole_file(struct mparse *curp, int
 	int		 gzerrnum, retval;
 
 	if (fstat(fd, &st) == -1) {
-		mandoc_msg(MANDOCERR_FILE, 0, 0,
-		    "fstat: %s", strerror(errno));
-		return 0;
+		mandoc_msg(MANDOCERR_FSTAT, 0, 0, "%s", strerror(errno));
+		return -1;
 	}
 
 	/*
@@ -446,13 +445,13 @@ read_whole_file(struct mparse *curp, int
 	if (curp->gzip == 0 && S_ISREG(st.st_mode)) {
 		if (st.st_size > 0x7fffffff) {
 			mandoc_msg(MANDOCERR_TOOLARGE, 0, 0, NULL);
-			return 0;
+			return -1;
 		}
 		*with_mmap = 1;
 		fb->sz = (size_t)st.st_size;
 		fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
 		if (fb->buf != MAP_FAILED)
-			return 1;
+			return 0;
 	}
 
 	if (curp->gzip) {
@@ -464,15 +463,15 @@ read_whole_file(struct mparse *curp, int
 		 * which this function must not do.
 		 */
 		if ((fd = dup(fd)) == -1) {
-			mandoc_msg(MANDOCERR_FILE, 0, 0,
-			    "dup: %s", strerror(errno));
-			return 0;
+			mandoc_msg(MANDOCERR_DUP, 0, 0,
+			    "%s", strerror(errno));
+			return -1;
 		}
 		if ((gz = gzdopen(fd, "rb")) == NULL) {
-			mandoc_msg(MANDOCERR_FILE, 0, 0,
-			    "gzdopen: %s", strerror(errno));
+			mandoc_msg(MANDOCERR_GZDOPEN, 0, 0,
+			    "%s", strerror(errno));
 			close(fd);
-			return 0;
+			return -1;
 		}
 	} else
 		gz = NULL;
@@ -484,7 +483,7 @@ read_whole_file(struct mparse *curp, int
 
 	*with_mmap = 0;
 	off = 0;
-	retval = 0;
+	retval = -1;
 	fb->sz = 0;
 	fb->buf = NULL;
 	for (;;) {
@@ -500,13 +499,13 @@ read_whole_file(struct mparse *curp, int
 		    read(fd, fb->buf + (int)off, fb->sz - off);
 		if (ssz == 0) {
 			fb->sz = off;
-			retval = 1;
+			retval = 0;
 			break;
 		}
 		if (ssz == -1) {
 			if (curp->gzip)
 				(void)gzerror(gz, &gzerrnum);
-			mandoc_msg(MANDOCERR_FILE, 0, 0, "read: %s",
+			mandoc_msg(MANDOCERR_READ, 0, 0, "%s",
 			    curp->gzip && gzerrnum != Z_ERRNO ?
 			    zError(gzerrnum) : strerror(errno));
 			break;
@@ -515,10 +514,10 @@ read_whole_file(struct mparse *curp, int
 	}
 
 	if (curp->gzip && (gzerrnum = gzclose(gz)) != Z_OK)
-		mandoc_msg(MANDOCERR_FILE, 0, 0, "gzclose: %s",
+		mandoc_msg(MANDOCERR_GZCLOSE, 0, 0, "%s",
 		    gzerrnum == Z_ERRNO ? strerror(errno) :
 		    zError(gzerrnum));
-	if (retval == 0) {
+	if (retval == -1) {
 		free(fb->buf);
 		fb->buf = NULL;
 	}
@@ -557,7 +556,7 @@ mparse_readfd(struct mparse *curp, int f
 		mandoc_msg(MANDOCERR_ROFFLOOP, curp->line, 0, NULL);
 		return;
 	}
-	if (read_whole_file(curp, fd, &blk, &with_mmap) == 0)
+	if (read_whole_file(curp, fd, &blk, &with_mmap) == -1)
 		return;
 
 	/*
Index: manpath.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/manpath.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -Lmanpath.c -Lmanpath.c -u -p -r1.39 -r1.40
--- manpath.c
+++ manpath.c
@@ -1,6 +1,6 @@
 /*	$Id$ */
 /*
- * Copyright (c) 2011,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011,2014,2015,2017-2019 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -21,20 +21,19 @@
 #include <sys/stat.h>
 
 #include <ctype.h>
-#if HAVE_ERR
-#include <err.h>
-#endif
+#include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "mandoc_aux.h"
+#include "mandoc.h"
 #include "manconf.h"
 
 static	void	 manconf_file(struct manconf *, const char *);
-static	void	 manpath_add(struct manpaths *, const char *, int);
-static	void	 manpath_parseline(struct manpaths *, char *, int);
+static	void	 manpath_add(struct manpaths *, const char *, char);
+static	void	 manpath_parseline(struct manpaths *, char *, char);
 
 
 void
@@ -44,11 +43,11 @@ manconf_parse(struct manconf *conf, cons
 	char		*insert;
 
 	/* Always prepend -m. */
-	manpath_parseline(&conf->manpath, auxp, 1);
+	manpath_parseline(&conf->manpath, auxp, 'm');
 
 	/* If -M is given, it overrides everything else. */
 	if (NULL != defp) {
-		manpath_parseline(&conf->manpath, defp, 1);
+		manpath_parseline(&conf->manpath, defp, 'M');
 		return;
 	}
 
@@ -66,13 +65,13 @@ manconf_parse(struct manconf *conf, cons
 	/* Prepend man.conf(5) to MANPATH. */
 	if (':' == defp[0]) {
 		manconf_file(conf, file);
-		manpath_parseline(&conf->manpath, defp, 0);
+		manpath_parseline(&conf->manpath, defp, '\0');
 		return;
 	}
 
 	/* Append man.conf(5) to MANPATH. */
 	if (':' == defp[strlen(defp) - 1]) {
-		manpath_parseline(&conf->manpath, defp, 0);
+		manpath_parseline(&conf->manpath, defp, '\0');
 		manconf_file(conf, file);
 		return;
 	}
@@ -81,28 +80,28 @@ manconf_parse(struct manconf *conf, cons
 	insert = strstr(defp, "::");
 	if (NULL != insert) {
 		*insert++ = '\0';
-		manpath_parseline(&conf->manpath, defp, 0);
+		manpath_parseline(&conf->manpath, defp, '\0');
 		manconf_file(conf, file);
-		manpath_parseline(&conf->manpath, insert + 1, 0);
+		manpath_parseline(&conf->manpath, insert + 1, '\0');
 		return;
 	}
 
 	/* MANPATH overrides man.conf(5) completely. */
-	manpath_parseline(&conf->manpath, defp, 0);
+	manpath_parseline(&conf->manpath, defp, '\0');
 }
 
 void
 manpath_base(struct manpaths *dirs)
 {
 	char path_base[] = MANPATH_BASE;
-	manpath_parseline(dirs, path_base, 0);
+	manpath_parseline(dirs, path_base, '\0');
 }
 
 /*
  * Parse a FULL pathname from a colon-separated list of arrays.
  */
 static void
-manpath_parseline(struct manpaths *dirs, char *path, int complain)
+manpath_parseline(struct manpaths *dirs, char *path, char option)
 {
 	char	*dir;
 
@@ -110,7 +109,7 @@ manpath_parseline(struct manpaths *dirs,
 		return;
 
 	for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
-		manpath_add(dirs, dir, complain);
+		manpath_add(dirs, dir, option);
 }
 
 /*
@@ -118,33 +117,32 @@ manpath_parseline(struct manpaths *dirs,
  * Grow the array one-by-one for simplicity's sake.
  */
 static void
-manpath_add(struct manpaths *dirs, const char *dir, int complain)
+manpath_add(struct manpaths *dirs, const char *dir, char option)
 {
 	char		 buf[PATH_MAX];
 	struct stat	 sb;
 	char		*cp;
 	size_t		 i;
 
-	if (NULL == (cp = realpath(dir, buf))) {
-		if (complain)
-			warn("manpath: %s", dir);
-		return;
-	}
+	if ((cp = realpath(dir, buf)) == NULL)
+		goto fail;
 
 	for (i = 0; i < dirs->sz; i++)
-		if (0 == strcmp(dirs->paths[i], dir))
+		if (strcmp(dirs->paths[i], dir) == 0)
 			return;
 
-	if (stat(cp, &sb) == -1) {
-		if (complain)
-			warn("manpath: %s", dir);
-		return;
-	}
+	if (stat(cp, &sb) == -1)
+		goto fail;
 
 	dirs->paths = mandoc_reallocarray(dirs->paths,
-	    dirs->sz + 1, sizeof(char *));
-
+	    dirs->sz + 1, sizeof(*dirs->paths));
 	dirs->paths[dirs->sz++] = mandoc_strdup(cp);
+	return;
+
+fail:
+	if (option != '\0')
+		mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0,
+		    "-%c %s: %s", option, dir, strerror(errno));
 }
 
 void
@@ -210,7 +208,7 @@ manconf_file(struct manconf *conf, const
 			*ep = '\0';
 			/* FALLTHROUGH */
 		case 0:  /* manpath */
-			manpath_add(&conf->manpath, cp, 0);
+			manpath_add(&conf->manpath, cp, '\0');
 			*manpath_default = '\0';
 			break;
 		case 1:  /* output */
@@ -225,7 +223,7 @@ manconf_file(struct manconf *conf, const
 
 out:
 	if (*manpath_default != '\0')
-		manpath_parseline(&conf->manpath, manpath_default, 0);
+		manpath_parseline(&conf->manpath, manpath_default, '\0');
 }
 
 int
@@ -243,7 +241,7 @@ manconf_output(struct manoutput *conf, c
 
 	for (tok = 0; tok < ntoks; tok++) {
 		len = strlen(toks[tok]);
-		if ( ! strncmp(cp, toks[tok], len) &&
+		if (strncmp(cp, toks[tok], len) == 0 &&
 		    strchr(" =	", cp[len]) != NULL) {
 			cp += len;
 			if (*cp == '=')
@@ -255,11 +253,11 @@ manconf_output(struct manoutput *conf, c
 	}
 
 	if (tok < 6 && *cp == '\0') {
-		warnx("-O %s=?: Missing argument value", toks[tok]);
+		mandoc_msg(MANDOCERR_BADVAL_MISS, 0, 0, "-O %s=?", toks[tok]);
 		return -1;
 	}
 	if (tok > 6 && tok < ntoks && *cp != '\0') {
-		warnx("-O %s: Does not take a value: %s", toks[tok], cp);
+		mandoc_msg(MANDOCERR_BADVAL, 0, 0, "-O %s=%s", toks[tok], cp);
 		return -1;
 	}
 
@@ -300,7 +298,8 @@ manconf_output(struct manoutput *conf, c
 		conf->indent = strtonum(cp, 0, 1000, &errstr);
 		if (errstr == NULL)
 			return 0;
-		warnx("-O indent=%s is %s", cp, errstr);
+		mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0,
+		    "-O indent=%s is %s", cp, errstr);
 		return -1;
 	case 5:
 		if (conf->width) {
@@ -310,7 +309,8 @@ manconf_output(struct manoutput *conf, c
 		conf->width = strtonum(cp, 1, 1000, &errstr);
 		if (errstr == NULL)
 			return 0;
-		warnx("-O width=%s is %s", cp, errstr);
+		mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0,
+		    "-O width=%s is %s", cp, errstr);
 		return -1;
 	case 6:
 		if (conf->tag != NULL) {
@@ -332,12 +332,16 @@ manconf_output(struct manoutput *conf, c
 		conf->toc = 1;
 		return 0;
 	default:
-		warnx("-O %s: Bad argument", cp);
+		mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, "-O %s", cp);
+		return -1;
+	}
+	if (fromfile) {
+		free(oldval);
+		return 0;
+	} else {
+		mandoc_msg(MANDOCERR_BADVAL_DUPE, 0, 0,
+		    "-O %s=%s: already set to %s", toks[tok], cp, oldval);
+		free(oldval);
 		return -1;
 	}
-	if (fromfile == 0)
-		warnx("-O %s=%s: Option already set to %s",
-		    toks[tok], cp, oldval);
-	free(oldval);
-	return -1;
 }
Index: tag.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/tag.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -Ltag.c -Ltag.c -u -p -r1.21 -r1.22
--- tag.c
+++ tag.c
@@ -1,6 +1,6 @@
 /*	$Id$ */
 /*
- * Copyright (c) 2015, 2016, 2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2015, 2016, 2018, 2019 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
@@ -18,9 +18,7 @@
 
 #include <sys/types.h>
 
-#if HAVE_ERR
-#include <err.h>
-#endif
+#include <errno.h>
 #include <limits.h>
 #include <signal.h>
 #include <stddef.h>
@@ -32,6 +30,7 @@
 
 #include "mandoc_aux.h"
 #include "mandoc_ohash.h"
+#include "mandoc.h"
 #include "tag.h"
 
 struct tag_entry {
@@ -83,8 +82,10 @@ tag_init(void)
 
 	/* Save the original standard output for use by the pager. */
 
-	if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1)
+	if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1) {
+		mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
 		goto fail;
+	}
 
 	/* Create both temporary output files. */
 
@@ -92,12 +93,20 @@ tag_init(void)
 	    sizeof(tag_files.ofn));
 	(void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
 	    sizeof(tag_files.tfn));
-	if ((ofd = mkstemp(tag_files.ofn)) == -1)
+	if ((ofd = mkstemp(tag_files.ofn)) == -1) {
+		mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
+		    "%s: %s", tag_files.ofn, strerror(errno));
 		goto fail;
-	if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1)
+	}
+	if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1) {
+		mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
+		    "%s: %s", tag_files.tfn, strerror(errno));
 		goto fail;
-	if (dup2(ofd, STDOUT_FILENO) == -1)
+	}
+	if (dup2(ofd, STDOUT_FILENO) == -1) {
+		mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
 		goto fail;
+	}
 	close(ofd);
 
 	/*
@@ -221,10 +230,11 @@ tag_write(void)
 		return;
 	if (tag_files.tagname != NULL && ohash_find(&tag_data,
             ohash_qlookup(&tag_data, tag_files.tagname)) == NULL) {
-		warnx("%s: no such tag", tag_files.tagname);
+		mandoc_msg(MANDOCERR_TAG, 0, 0, "%s", tag_files.tagname);
 		tag_files.tagname = NULL;
 	}
-	stream = fdopen(tag_files.tfd, "w");
+	if ((stream = fdopen(tag_files.tfd, "w")) == NULL)
+		mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno));
 	entry = ohash_first(&tag_data, &slot);
 	while (entry != NULL) {
 		if (stream != NULL && entry->prio >= 0)
--
 To unsubscribe send an email to source+unsubscribe@mandoc.bsd.lv

                 reply	other threads:[~2019-07-10 19:39 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8629f1b724761ac4@mandoc.bsd.lv \
    --to=schwarze@mandoc.bsd.lv \
    --cc=source@mandoc.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).