summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2019-07-26 09:51:35 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2019-07-26 09:51:35 +0000
commita5efdeedef481aea3632844ca94a80567a75b5ad (patch)
tree6a7c9e206b8798d24754639cf546c86117f9ede0
parent8f0c701250919da7f99273250017bf536dc73db9 (diff)
downloadsrc-test2-vendor/mandoc.tar.gz
src-test2-vendor/mandoc.zip
Import mandoc snapshot 2019-07-23vendor/mandoc/20190723vendor/mandoc
Notes
Notes: svn path=/vendor/mandoc/dist/; revision=350349 svn path=/vendor/mandoc/20190723/; revision=350350; tag=vendor/mandoc/20190723
-rw-r--r--Makefile.depend12
-rw-r--r--TODO26
-rw-r--r--arch.c4
-rw-r--r--cgi.c3
-rwxr-xr-xconfigure4
-rw-r--r--dbm.c6
-rw-r--r--dbm_map.h4
-rw-r--r--eqn.76
-rw-r--r--eqn_html.c3
-rw-r--r--html.c74
-rw-r--r--html.h17
-rw-r--r--lib.in4
-rw-r--r--libroff.h80
-rw-r--r--main.c359
-rw-r--r--man.716
-rw-r--r--man_html.c6
-rw-r--r--man_term.c108
-rw-r--r--man_validate.c30
-rw-r--r--mandoc.163
-rw-r--r--mandoc.c17
-rw-r--r--mandoc.css29
-rw-r--r--mandoc.h35
-rw-r--r--mandoc_char.78
-rw-r--r--mandoc_headers.3101
-rw-r--r--mandoc_msg.c53
-rw-r--r--mandocdb.c19
-rw-r--r--manpath.c98
-rw-r--r--mansearch.c12
-rw-r--r--mansearch.h3
-rw-r--r--mdoc.738
-rw-r--r--mdoc_argv.c5
-rw-r--r--mdoc_markdown.c4
-rw-r--r--mdoc_term.c25
-rw-r--r--mdoc_validate.c22
-rw-r--r--out.c4
-rw-r--r--read.c39
-rw-r--r--roff.715
-rw-r--r--roff.c66
-rw-r--r--roff_html.c4
-rw-r--r--tag.c49
-rw-r--r--tbl_html.c3
-rw-r--r--tbl_term.c49
-rw-r--r--term.c4
43 files changed, 892 insertions, 635 deletions
diff --git a/Makefile.depend b/Makefile.depend
index a0898095ae7a..3540aeda822c 100644
--- a/Makefile.depend
+++ b/Makefile.depend
@@ -29,7 +29,7 @@ dbm.o: dbm.c config.h mansearch.h dbm_map.h dbm.h
dbm_map.o: dbm_map.c config.h mansearch.h dbm_map.h dbm.h
demandoc.o: demandoc.c config.h mandoc.h roff.h man.h mdoc.h mandoc_parse.h
eqn.o: eqn.c config.h mandoc_aux.h mandoc.h roff.h eqn.h libmandoc.h eqn_parse.h
-eqn_html.o: eqn_html.c config.h mandoc.h eqn.h out.h html.h
+eqn_html.o: eqn_html.c config.h mandoc.h roff.h eqn.h out.h html.h
eqn_term.o: eqn_term.c config.h eqn.h out.h term.h
html.o: html.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h out.h html.h manconf.h main.h
lib.o: lib.c config.h roff.h libmdoc.h lib.in
@@ -37,16 +37,16 @@ main.o: main.c config.h mandoc_aux.h mandoc.h mandoc_xr.h roff.h mdoc.h man.h ma
man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
man_html.o: man_html.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h html.h main.h
man_macro.o: man_macro.c config.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
-man_term.o: man_term.c config.h mandoc_aux.h roff.h man.h out.h term.h main.h
+man_term.o: man_term.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h term.h tag.h main.h
man_validate.o: man_validate.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
mandoc.o: mandoc.c config.h mandoc_aux.h mandoc.h roff.h libmandoc.h roff_int.h
mandoc_aux.o: mandoc_aux.c config.h mandoc.h mandoc_aux.h
-mandoc_msg.o: mandoc_msg.c mandoc.h
+mandoc_msg.o: mandoc_msg.c config.h mandoc.h
mandoc_ohash.o: mandoc_ohash.c mandoc_aux.h mandoc_ohash.h compat_ohash.h
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,10 +67,10 @@ roff_term.o: roff_term.c mandoc.h roff.h out.h term.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 tbl.h out.h html.h
+tbl_html.o: tbl_html.c config.h mandoc.h roff.h tbl.h out.h html.h
tbl_layout.o: tbl_layout.c config.h mandoc_aux.h mandoc.h tbl.h libmandoc.h tbl_int.h
tbl_opts.o: tbl_opts.c config.h mandoc.h tbl.h libmandoc.h tbl_int.h
tbl_term.o: tbl_term.c config.h mandoc.h tbl.h out.h term.h
diff --git a/TODO b/TODO
index 063e2789d2c5..049e6a4f2beb 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,6 @@
************************************************************************
* Official mandoc TODO.
-* $Id: TODO,v 1.289 2019/03/04 13:01:57 schwarze Exp $
+* $Id: TODO,v 1.295 2019/06/11 16:04:36 schwarze Exp $
************************************************************************
Many issues are annotated for difficulty as follows:
@@ -62,6 +62,27 @@ are mere guesses, and some may be wrong.
needed for Tcl_NewStringObj(3) via wiz@ Wed, 5 Mar 2014 22:27:43 +0100
loc ** exist *** algo *** size * imp ***
+- .als only works for macros in mandoc, not for user-defined strings.
+ Also, the "val" field in struct roffkv would have to be replaced
+ with a pointer to a reference-counted wrapper, and an alias
+ would have to point to the same wrapper as the original.
+ .als to undefined does nothing; the alias is not created.
+ .rm'ing the original leaves the alias to point to the old value.
+ .de .als .de changes both, but
+ .de .als .rm .de only changes the new value, not the alias.
+ Found in groffer(1) version 1.19
+ Jan Stary 20 Apr 2019 20:16:54 +0200
+ loc * exist ** algo ** size ** imp *
+
+- roff string condition comparisons fail when vars contain quotes:
+ .ds s '
+ .if '\*s'' \&...
+ hard to fix because of the basic architecture (string replacement
+ happens before roff(7) syntax parsing)
+ Found in groffer(1) version 1.19
+ Jan Stary 20 Apr 2019 20:16:54 +0200
+ loc * exist *** algo *** size ** imp *
+
--- missing mdoc features ----------------------------------------------
- .Bl -column .Xo support is missing
@@ -264,6 +285,9 @@ are mere guesses, and some may be wrong.
https://github.com/schmonz/ikiwiki/compare/mandoc
Amitai Schlair Mon, 19 May 2014 14:05:53 -0400
+- check compatibility with
+ https://git.sr.ht/~sircmpwn/scdoc
+
- check features of the Slackware man.conf(5) format
Carsten Kunze Wed, 11 Mar 2015 17:57:24 +0100
diff --git a/arch.c b/arch.c
index 56b937ec8412..551c86796a21 100644
--- a/arch.c
+++ b/arch.c
@@ -1,4 +1,4 @@
-/* $Id: arch.c,v 1.14 2019/03/04 13:01:57 schwarze Exp $ */
+/* $Id: arch.c,v 1.15 2019/05/21 07:52:00 schwarze Exp $ */
/*
* Copyright (c) 2017, 2019 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -26,7 +26,7 @@ arch_valid(const char *arch, enum mandoc_os os)
const char *openbsd_arch[] = {
"alpha", "amd64", "arm64", "armv7", "hppa", "i386",
"landisk", "loongson", "luna88k", "macppc", "mips64",
- "octeon", "sgi", "socppc", "sparc64", NULL
+ "octeon", "sgi", "sparc64", NULL
};
const char *netbsd_arch[] = {
"acorn26", "acorn32", "algor", "alpha", "amiga",
diff --git a/cgi.c b/cgi.c
index 0af0f1255d40..4762f819d57d 100644
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-/* $Id: cgi.c,v 1.166 2019/03/06 12:32:41 schwarze Exp $ */
+/* $Id: cgi.c,v 1.167 2019/07/10 12:49:20 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2016, 2017, 2018 Ingo Schwarze <schwarze@usta.de>
@@ -869,7 +869,6 @@ resp_format(const struct req *req, const char *file)
memset(&conf, 0, sizeof(conf));
conf.fragment = 1;
conf.style = mandoc_strdup(CSS_DIR "/mandoc.css");
- conf.toc = 1;
usepath = strcmp(req->q.manpath, req->p[0]);
mandoc_asprintf(&conf.man, "/%s%s%s%s%%N.%%S",
scriptname, *scriptname == '\0' ? "" : "/",
diff --git a/configure b/configure
index 5507de7021b8..2df028da0510 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# $Id: configure,v 1.70 2019/03/06 16:04:31 schwarze Exp $
+# $Id: configure,v 1.71 2019/07/01 22:56:24 schwarze Exp $
#
# Copyright (c) 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
#
@@ -529,7 +529,7 @@ fi
echo "extern char *mkdtemp(char *);"
if [ ${HAVE_PROGNAME} -eq 0 ]; then
- echo "extern const char *getprogname(void);"
+ echo "extern const char *getprogname(void);"
echo "extern void setprogname(const char *);"
fi
diff --git a/dbm.c b/dbm.c
index f6b1259ef5ad..7dc07d0674ad 100644
--- a/dbm.c
+++ b/dbm.c
@@ -1,4 +1,4 @@
-/* $Id: dbm.c,v 1.6 2018/11/19 19:22:07 schwarze Exp $ */
+/* $Id: dbm.c,v 1.7 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -233,7 +233,7 @@ static struct dbm_res
page_bytitle(enum iter arg_iter, const struct dbm_match *arg_match)
{
static const struct dbm_match *match;
- static const char *cp;
+ static const char *cp;
static int32_t ip;
struct dbm_res res = {-1, 0};
@@ -315,7 +315,7 @@ page_byarch(const struct dbm_match *arg_match)
static const struct dbm_match *match;
struct dbm_res res = {-1, 0};
static int32_t ip;
- const char *cp;
+ const char *cp;
/* Initialize for a new iteration. */
diff --git a/dbm_map.h b/dbm_map.h
index 9768fc5f2dcc..dc072aef5463 100644
--- a/dbm_map.h
+++ b/dbm_map.h
@@ -1,4 +1,4 @@
-/* $Id: dbm_map.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */
+/* $Id: dbm_map.h,v 1.2 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -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.
*
- * Private interface for low-level routines for the map-based version
+ * Private interface for low-level routines for the map-based version
* of the mandoc database, for read-only access.
* To be used by dbm*.c only.
*/
diff --git a/eqn.7 b/eqn.7
index 244903c56fe9..c9fe483b1719 100644
--- a/eqn.7
+++ b/eqn.7
@@ -1,4 +1,4 @@
-.\" $Id: eqn.7,v 1.37 2017/09/04 10:35:27 schwarze Exp $
+.\" $Id: eqn.7,v 1.38 2019/04/23 17:57:49 schwarze Exp $
.\"
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,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: September 4 2017 $
+.Dd $Mdocdate: April 23 2019 $
.Dt EQN 7
.Os
.Sh NAME
@@ -470,7 +470,7 @@ commands are also ignored.
.%T System for Typesetting Mathematics
.%J Communications of the ACM
.%V 18
-.%P 151\(en157
+.%P pp. 151\(en157
.%D March, 1975
.Re
.Rs
diff --git a/eqn_html.c b/eqn_html.c
index 1fe41ecbfac5..64d06649997f 100644
--- a/eqn_html.c
+++ b/eqn_html.c
@@ -1,4 +1,4 @@
-/* $Id: eqn_html.c,v 1.18 2018/12/13 05:23:38 schwarze Exp $ */
+/* $Id: eqn_html.c,v 1.19 2019/03/17 18:21:45 schwarze Exp $ */
/*
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -26,6 +26,7 @@
#include <string.h>
#include "mandoc.h"
+#include "roff.h"
#include "eqn.h"
#include "out.h"
#include "html.h"
diff --git a/html.c b/html.c
index 1302972a4e13..9c45d3162eaf 100644
--- a/html.c
+++ b/html.c
@@ -1,4 +1,4 @@
-/* $Id: html.c,v 1.254 2019/03/03 13:02:11 schwarze Exp $ */
+/* $Id: html.c,v 1.255 2019/04/30 15:53:00 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -120,6 +120,7 @@ static void print_ctag(struct html *, struct tag *);
static int print_escape(struct html *, char);
static int print_encode(struct html *, const char *, const char *, int);
static void print_href(struct html *, const char *, const char *, int);
+static void print_metaf(struct html *);
void *
@@ -222,55 +223,49 @@ print_gen_head(struct html *h)
print_tagq(h, t);
}
-void
-print_metaf(struct html *h, enum mandoc_esc deco)
+int
+html_setfont(struct html *h, enum mandoc_esc font)
{
- enum htmlfont font;
-
- switch (deco) {
+ switch (font) {
case ESCAPE_FONTPREV:
font = h->metal;
break;
case ESCAPE_FONTITALIC:
- font = HTMLFONT_ITALIC;
- break;
case ESCAPE_FONTBOLD:
- font = HTMLFONT_BOLD;
- break;
case ESCAPE_FONTBI:
- font = HTMLFONT_BI;
- break;
case ESCAPE_FONTCW:
- font = HTMLFONT_CW;
+ case ESCAPE_FONTROMAN:
break;
case ESCAPE_FONT:
- case ESCAPE_FONTROMAN:
- font = HTMLFONT_NONE;
+ font = ESCAPE_FONTROMAN;
break;
default:
- return;
+ return 0;
}
+ h->metal = h->metac;
+ h->metac = font;
+ return 1;
+}
+static void
+print_metaf(struct html *h)
+{
if (h->metaf) {
print_tagq(h, h->metaf);
h->metaf = NULL;
}
-
- h->metal = h->metac;
- h->metac = font;
-
- switch (font) {
- case HTMLFONT_ITALIC:
+ switch (h->metac) {
+ case ESCAPE_FONTITALIC:
h->metaf = print_otag(h, TAG_I, "");
break;
- case HTMLFONT_BOLD:
+ case ESCAPE_FONTBOLD:
h->metaf = print_otag(h, TAG_B, "");
break;
- case HTMLFONT_BI:
+ case ESCAPE_FONTBI:
h->metaf = print_otag(h, TAG_B, "");
print_otag(h, TAG_I, "");
break;
- case HTMLFONT_CW:
+ case ESCAPE_FONTCW:
h->metaf = print_otag(h, TAG_SPAN, "c", "Li");
break;
default:
@@ -479,7 +474,8 @@ print_encode(struct html *h, const char *p, const char *pend, int norecurse)
case ESCAPE_FONTROMAN:
if (0 == norecurse) {
h->flags |= HTML_NOSPACE;
- print_metaf(h, esc);
+ if (html_setfont(h, esc))
+ print_metaf(h);
h->flags &= ~HTML_NOSPACE;
}
continue;
@@ -806,27 +802,9 @@ print_text(struct html *h, const char *word)
print_word(h, "&#x00A0;");
}
- assert(NULL == h->metaf);
- switch (h->metac) {
- case HTMLFONT_ITALIC:
- h->metaf = print_otag(h, TAG_I, "");
- break;
- case HTMLFONT_BOLD:
- h->metaf = print_otag(h, TAG_B, "");
- break;
- case HTMLFONT_BI:
- h->metaf = print_otag(h, TAG_B, "");
- print_otag(h, TAG_I, "");
- break;
- case HTMLFONT_CW:
- h->metaf = print_otag(h, TAG_SPAN, "c", "Li");
- break;
- default:
- print_indent(h);
- break;
- }
-
- assert(word);
+ assert(h->metaf == NULL);
+ print_metaf(h);
+ print_indent(h);
if ( ! print_encode(h, word, NULL, 0)) {
if ( ! (h->flags & HTML_NONOSPACE))
h->flags &= ~HTML_NOSPACE;
@@ -834,7 +812,7 @@ print_text(struct html *h, const char *word)
} else
h->flags |= HTML_NOSPACE | HTML_NONEWLINE;
- if (h->metaf) {
+ if (h->metaf != NULL) {
print_tagq(h, h->metaf);
h->metaf = NULL;
}
diff --git a/html.h b/html.h
index a6bf89119057..242a63a8d624 100644
--- a/html.h
+++ b/html.h
@@ -1,4 +1,4 @@
-/* $Id: html.h,v 1.102 2019/03/01 10:57:18 schwarze Exp $ */
+/* $Id: html.h,v 1.103 2019/04/30 15:53:00 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2017, 2018, 2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -69,15 +69,6 @@ enum htmltag {
TAG_MAX
};
-enum htmlfont {
- HTMLFONT_NONE = 0,
- HTMLFONT_BOLD,
- HTMLFONT_ITALIC,
- HTMLFONT_BI,
- HTMLFONT_CW,
- HTMLFONT_MAX
-};
-
struct tag {
struct tag *next;
int refcnt;
@@ -111,8 +102,8 @@ struct html {
char *base_includes; /* base for include href */
char *style; /* style-sheet URI */
struct tag *metaf; /* current open font scope */
- enum htmlfont metal; /* last used font */
- enum htmlfont metac; /* current font mode */
+ enum mandoc_esc metal; /* last used font */
+ enum mandoc_esc metac; /* current font mode */
int oflags; /* output options */
#define HTML_FRAGMENT (1 << 0) /* don't emit HTML/HEAD/BODY */
#define HTML_TOC (1 << 1) /* emit a table of contents */
@@ -128,7 +119,6 @@ void roff_html_pre(struct html *, const struct roff_node *);
void print_gen_comment(struct html *, struct roff_node *);
void print_gen_decls(struct html *);
void print_gen_head(struct html *);
-void print_metaf(struct html *, enum mandoc_esc);
struct tag *print_otag(struct html *, enum htmltag, const char *, ...);
void print_tagq(struct html *, const struct tag *);
void print_stagq(struct html *, const struct tag *);
@@ -141,3 +131,4 @@ void print_endline(struct html *);
void html_close_paragraph(struct html *);
enum roff_tok html_fillmode(struct html *, enum roff_tok);
char *html_make_id(const struct roff_node *, int);
+int html_setfont(struct html *, enum mandoc_esc);
diff --git a/lib.in b/lib.in
index b8dd87eb99f8..a01f79e1ac48 100644
--- a/lib.in
+++ b/lib.in
@@ -1,4 +1,4 @@
-/* $Id: lib.in,v 1.21 2019/03/04 17:35:21 schwarze Exp $ */
+/* $Id: lib.in,v 1.22 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2009, 2012 Joerg Sonnenberger <joerg@netbsd.org>
@@ -43,7 +43,7 @@ LINE("libcipher", "FreeSec Crypt Library (libcipher, \\-lcipher)")
LINE("libcompat", "Compatibility Library (libcompat, \\-lcompat)")
LINE("libcrypt", "Crypt Library (libcrypt, \\-lcrypt)")
LINE("libcurses", "Curses Library (libcurses, \\-lcurses)")
-LINE("libcuse", "Userland Character Device Library (libcuse, \\-lcuse)")
+LINE("libcuse", "Userland Character Device Library (libcuse, \\-lcuse)")
LINE("libdevattr", "Device attribute and event library (libdevattr, \\-ldevattr)")
LINE("libdevctl", "Device Control Library (libdevctl, \\-ldevctl)")
LINE("libdevinfo", "Device and Resource Information Utility Library (libdevinfo, \\-ldevinfo)")
diff --git a/libroff.h b/libroff.h
deleted file mode 100644
index b6a026d820b3..000000000000
--- a/libroff.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* $Id: libroff.h,v 1.42 2017/07/08 17:52:49 schwarze Exp $ */
-/*
- * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015, 2017 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.
- */
-
-enum tbl_part {
- TBL_PART_OPTS, /* in options (first line) */
- TBL_PART_LAYOUT, /* describing layout */
- TBL_PART_DATA, /* creating data rows */
- TBL_PART_CDATA /* continue previous row */
-};
-
-struct tbl_node {
- struct mparse *parse; /* parse point */
- int pos; /* invocation column */
- int line; /* invocation line */
- enum tbl_part part;
- struct tbl_opts opts;
- struct tbl_row *first_row;
- struct tbl_row *last_row;
- struct tbl_span *first_span;
- struct tbl_span *current_span;
- struct tbl_span *last_span;
- struct tbl_node *next;
-};
-
-struct eqn_node {
- struct mparse *parse; /* main parser, for error reporting */
- struct roff_node *node; /* syntax tree of this equation */
- struct eqn_def *defs; /* array of definitions */
- char *data; /* source code of this equation */
- char *start; /* first byte of the current token */
- char *end; /* first byte of the next token */
- size_t defsz; /* number of definitions */
- size_t sz; /* length of the source code */
- size_t toksz; /* length of the current token */
- int gsize; /* default point size */
- int delim; /* in-line delimiters enabled */
- char odelim; /* in-line opening delimiter */
- char cdelim; /* in-line closing delimiter */
-};
-
-struct eqn_def {
- char *key;
- size_t keysz;
- char *val;
- size_t valsz;
-};
-
-
-struct tbl_node *tbl_alloc(int, int, struct mparse *);
-void tbl_restart(int, int, struct tbl_node *);
-void tbl_free(struct tbl_node *);
-void tbl_reset(struct tbl_node *);
-void tbl_read(struct tbl_node *, int, const char *, int);
-void tbl_option(struct tbl_node *, int, const char *, int *);
-void tbl_layout(struct tbl_node *, int, const char *, int);
-void tbl_data(struct tbl_node *, int, const char *, int);
-void tbl_cdata(struct tbl_node *, int, const char *, int);
-const struct tbl_span *tbl_span(struct tbl_node *);
-int tbl_end(struct tbl_node *);
-struct eqn_node *eqn_alloc(struct mparse *);
-void eqn_box_free(struct eqn_box *);
-void eqn_free(struct eqn_node *);
-void eqn_parse(struct eqn_node *);
-void eqn_read(struct eqn_node *, const char *);
-void eqn_reset(struct eqn_node *);
diff --git a/main.c b/main.c
index b91c15860ab1..b11f7b51c164 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.322 2019/03/06 10:18:58 schwarze Exp $ */
+/* $Id: main.c,v 1.332 2019/07/19 20:27:25 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h> /* MACHINE */
+#include <sys/stat.h>
#include <sys/wait.h>
#include <assert.h>
@@ -97,13 +98,10 @@ static int fs_lookup(const struct manpaths *,
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 *);
@@ -125,7 +123,7 @@ main(int argc, char *argv[])
char *conf_file, *defpaths, *auxpaths;
char *oarg, *tagarg;
unsigned char *uc;
- size_t i, sz;
+ size_t i, sz, ssz;
int prio, best_prio;
enum outmode outmode;
int fd, startdir;
@@ -154,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");
@@ -221,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;
@@ -258,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;
@@ -299,12 +333,9 @@ main(int argc, char *argv[])
search.outkey = oarg;
else {
while (oarg != NULL) {
- thisarg = oarg;
if (manconf_output(&conf.output,
- strsep(&oarg, ","), 0) == 0)
- continue;
- warnx("-O %s: Bad argument", thisarg);
- return (int)MANDOCLEVEL_BADARG;
+ strsep(&oarg, ","), 0) == -1)
+ return mandoc_msg_getrc();
}
}
}
@@ -328,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. */
@@ -355,7 +390,7 @@ main(int argc, char *argv[])
} else if (argc > 1 &&
((uc = (unsigned char *)argv[0]) != NULL) &&
((isdigit(uc[0]) && (uc[1] == '\0' ||
- (isalpha(uc[1]) && uc[2] == '\0'))) ||
+ isalpha(uc[1]))) ||
(uc[0] == 'n' && uc[1] == '\0'))) {
search.sec = (char *)uc;
argv++;
@@ -395,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) {
@@ -403,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,
@@ -411,6 +449,7 @@ main(int argc, char *argv[])
res[sz].file = mandoc_strdup(argv[c]);
res[sz].names = NULL;
res[sz].output = NULL;
+ res[sz].bits = 0;
res[sz].ipath = SIZE_MAX;
res[sz].sec = 10;
res[sz].form = FORM_SRC;
@@ -433,7 +472,7 @@ main(int argc, char *argv[])
if (outmode == OUTMODE_ONE) {
argc = 1;
- best_prio = 20;
+ best_prio = 40;
} else if (outmode == OUTMODE_ALL)
argc = (int)sz;
@@ -452,10 +491,21 @@ main(int argc, char *argv[])
sec = res[i].file;
sec += strcspn(sec, "123456789");
if (sec[0] == '\0')
- continue;
+ continue; /* No section at all. */
prio = sec_prios[sec[0] - '1'];
- if (sec[1] != '/')
- prio += 10;
+ if (search.sec != NULL) {
+ ssz = strlen(search.sec);
+ if (strncmp(sec, search.sec, ssz) == 0)
+ sec += ssz;
+ } else
+ sec++; /* Prefer without suffix. */
+ if (*sec != '/')
+ prio += 10; /* Wrong dir name. */
+ if (search.sec != NULL &&
+ (strlen(sec) <= ssz + 3 ||
+ strcmp(sec + strlen(sec) - ssz,
+ search.sec) != 0))
+ prio += 20; /* Wrong file ext. */
if (prio >= best_prio)
continue;
best_prio = prio;
@@ -477,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);
@@ -494,7 +554,8 @@ main(int argc, char *argv[])
if (argc < 1) {
if (use_pager) {
tag_files = tag_init();
- tag_files->tagname = conf.output.tag;
+ if (tag_files != NULL)
+ tag_files->tagname = conf.output.tag;
}
thisarg = "<stdin>";
mandoc_msg_setinfilename(thisarg);
@@ -527,30 +588,31 @@ main(int argc, char *argv[])
} else
thisarg = *argv;
+ mandoc_msg_setinfilename(thisarg);
fd = mparse_open(curp.mp, thisarg);
if (fd != -1) {
if (use_pager) {
use_pager = 0;
tag_files = tag_init();
- tag_files->tagname = conf.output.tag;
+ if (tag_files != NULL)
+ 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;
}
@@ -560,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;
@@ -653,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))
@@ -663,14 +727,16 @@ out:
signum = WSTOPSIG(status);
}
tag_unlink();
- }
+ } else if (curp.outtype != OUTT_LINT &&
+ (search.argmode == ARG_FILE || sz > 0))
+ mandoc_msg_summary();
+
return (int)mandoc_msg_getrc();
}
static void
usage(enum argmode argmode)
{
-
switch (argmode) {
case ARG_FILE:
fputs("usage: mandoc [-ac] [-I os=name] "
@@ -701,6 +767,7 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
const char *sec, const char *arch, const char *name,
struct manpage **res, size_t *ressz)
{
+ struct stat sb;
glob_t globinfo;
struct manpage *page;
char *file;
@@ -710,13 +777,13 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
form = FORM_SRC;
mandoc_asprintf(&file, "%s/man%s/%s.%s",
paths->paths[ipath], sec, name, sec);
- if (access(file, R_OK) != -1)
+ if (stat(file, &sb) != -1)
goto found;
free(file);
mandoc_asprintf(&file, "%s/cat%s/%s.0",
paths->paths[ipath], sec, name);
- if (access(file, R_OK) != -1) {
+ if (stat(file, &sb) != -1) {
form = FORM_CAT;
goto found;
}
@@ -725,7 +792,7 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
if (arch != NULL) {
mandoc_asprintf(&file, "%s/man%s/%s/%s.%s",
paths->paths[ipath], sec, arch, name, sec);
- if (access(file, R_OK) != -1)
+ if (stat(file, &sb) != -1)
goto found;
free(file);
}
@@ -734,37 +801,42 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
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);
globfree(&globinfo);
- if (globres == 0)
- goto found;
+ if (globres == 0) {
+ if (stat(file, &sb) != -1)
+ goto found;
+ free(file);
+ }
if (res != NULL || ipath + 1 != paths->sz)
- return 0;
+ return -1;
mandoc_asprintf(&file, "%s.%s", name, sec);
- globres = access(file, R_OK);
+ 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;
page->output = NULL;
+ page->bits = NAME_FILE & NAME_MASK;
page->ipath = ipath;
page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10;
page->form = form;
- return 1;
+ return 0;
}
static int
@@ -786,14 +858,14 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
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) {
@@ -812,7 +884,7 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
argv++;
argc--;
}
- return 0;
+ return -1;
}
static void
@@ -919,7 +991,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,
@@ -959,34 +1031,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) {
@@ -1004,94 +1076,20 @@ passthrough(const char *file, int fd, int synopsis_only)
}
}
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
@@ -1135,7 +1133,7 @@ woptions(struct curparse *curp, char *arg)
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);
@@ -1146,11 +1144,11 @@ woptions(struct curparse *curp, char *arg)
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
@@ -1196,7 +1194,7 @@ spawn_pager(struct tag_files *tag_files)
use_ofn = 1;
#if HAVE_LESS_T
- if ((cmdlen = strlen(argv[0])) >= 4) {
+ if (*tag_files->tfn != '\0' && (cmdlen = strlen(argv[0])) >= 4) {
cp = argv[0] + cmdlen - 4;
if (strcmp(cp, "less") == 0) {
argv[argc++] = mandoc_strdup("-T");
@@ -1215,15 +1213,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;
@@ -1231,8 +1233,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);
@@ -1242,5 +1246,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());
}
diff --git a/man.7 b/man.7
index 7706b5ca23df..6b4bece71433 100644
--- a/man.7
+++ b/man.7
@@ -1,4 +1,4 @@
-.\" $Id: man.7,v 1.143 2019/03/02 22:04:40 schwarze Exp $
+.\" $Id: man.7,v 1.144 2019/07/09 03:46:59 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2011-2015,2017,2018,2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -17,7 +17,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: March 2 2019 $
+.Dd $Mdocdate: July 9 2019 $
.Dt MAN 7
.Os
.Sh NAME
@@ -160,7 +160,9 @@ This has no effect unless the tabulator positions were changed with the
.Ic ta
request.
.It Ic EE
-This is a non-standard GNU extension.
+This is a non-standard Version 9
+.At
+extension later adopted by GNU.
In
.Xr mandoc 1 ,
it does the same as the
@@ -168,7 +170,9 @@ it does the same as the
.Ic fi
request (switch to fill mode).
.It Ic EX
-This is a non-standard GNU extension.
+This is a non-standard Version 9
+.At
+extension later adopted by GNU.
In
.Xr mandoc 1 ,
it does the same as the
@@ -496,8 +500,8 @@ The syntax is as follows:
.It Ic BI Ta n Ta current Ta \&
.It Ic BR Ta n Ta current Ta \&
.It Ic DT Ta 0 Ta current Ta \&
-.It Ic EE Ta 0 Ta current Ta GNU
-.It Ic EX Ta 0 Ta current Ta GNU
+.It Ic EE Ta 0 Ta current Ta Version 9 At
+.It Ic EX Ta 0 Ta current Ta Version 9 At
.It Ic I Ta n Ta next-line Ta \&
.It Ic IB Ta n Ta current Ta \&
.It Ic IR Ta n Ta current Ta \&
diff --git a/man_html.c b/man_html.c
index 994a208aa0ee..c0a429c5d6c9 100644
--- a/man_html.c
+++ b/man_html.c
@@ -1,4 +1,4 @@
-/* $Id: man_html.c,v 1.173 2019/03/02 16:30:53 schwarze Exp $ */
+/* $Id: man_html.c,v 1.174 2019/04/30 15:53:00 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -203,9 +203,9 @@ print_man_node(MAN_ARGS)
* Close out scope of font prior to opening a macro
* scope.
*/
- if (HTMLFONT_NONE != h->metac) {
+ if (h->metac != ESCAPE_FONTROMAN) {
h->metal = h->metac;
- h->metac = HTMLFONT_NONE;
+ h->metac = ESCAPE_FONTROMAN;
}
/*
diff --git a/man_term.c b/man_term.c
index d867762dcace..d9ee14ad22ba 100644
--- a/man_term.c
+++ b/man_term.c
@@ -1,4 +1,4 @@
-/* $Id: man_term.c,v 1.228 2019/01/05 21:18:26 schwarze Exp $ */
+/* $Id: man_term.c,v 1.232 2019/07/23 17:53:35 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -27,10 +27,12 @@
#include <string.h>
#include "mandoc_aux.h"
+#include "mandoc.h"
#include "roff.h"
#include "man.h"
#include "out.h"
#include "term.h"
+#include "tag.h"
#include "main.h"
#define MAXMARGINS 64 /* maximum number of indented scopes */
@@ -92,6 +94,8 @@ static void post_SY(DECL_ARGS);
static void post_TP(DECL_ARGS);
static void post_UR(DECL_ARGS);
+static void tag_man(struct termp *, struct roff_node *);
+
static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = {
{ NULL, NULL, 0 }, /* TH */
{ pre_SH, post_SH, 0 }, /* SH */
@@ -146,7 +150,7 @@ terminal_man(void *arg, const struct roff_meta *man)
{
struct mtermp mt;
struct termp *p;
- struct roff_node *n;
+ struct roff_node *n, *nc, *nn;
size_t save_defindent;
p = (struct termp *)arg;
@@ -165,18 +169,23 @@ terminal_man(void *arg, const struct roff_meta *man)
n = man->first->child;
if (p->synopsisonly) {
- while (n != NULL) {
- if (n->tok == MAN_SH &&
- n->child->child->type == ROFFT_TEXT &&
- !strcmp(n->child->child->string, "SYNOPSIS")) {
- if (n->child->next->child != NULL)
- print_man_nodelist(p, &mt,
- n->child->next->child, man);
- term_newln(p);
+ for (nn = NULL; n != NULL; n = n->next) {
+ if (n->tok != MAN_SH)
+ continue;
+ nc = n->child->child;
+ if (nc->type != ROFFT_TEXT)
+ continue;
+ if (strcmp(nc->string, "SYNOPSIS") == 0)
break;
- }
- n = n->next;
+ if (nn == NULL && strcmp(nc->string, "NAME") == 0)
+ nn = n;
}
+ if (n == NULL)
+ n = nn;
+ p->flags |= TERMP_NOSPACE;
+ if (n != NULL && (n = n->child->next->child) != NULL)
+ print_man_nodelist(p, &mt, n, man);
+ term_newln(p);
} else {
term_begin(p, print_man_head, print_man_foot, man);
p->flags |= TERMP_NOSPACE;
@@ -310,7 +319,7 @@ pre_alternate(DECL_ARGS)
assert(nn->type == ROFFT_TEXT);
term_word(p, nn->string);
if (nn->flags & NODE_EOS)
- p->flags |= TERMP_SENTENCE;
+ p->flags |= TERMP_SENTENCE;
if (nn->next != NULL)
p->flags |= TERMP_NOSPACE;
}
@@ -529,8 +538,10 @@ pre_IP(DECL_ARGS)
case ROFFT_HEAD:
p->tcol->offset = mt->offset;
p->tcol->rmargin = mt->offset + len;
- if (n->child != NULL)
+ if (n->child != NULL) {
print_man_node(p, mt, n->child, meta);
+ tag_man(p, n->child);
+ }
return 0;
case ROFFT_BODY:
p->tcol->offset = mt->offset + len;
@@ -610,6 +621,18 @@ pre_TP(DECL_ARGS)
while (nn != NULL && (nn->flags & NODE_LINE) == 0)
nn = nn->next;
+ if (nn == NULL)
+ return 0;
+
+ if (nn->type == ROFFT_TEXT)
+ tag_man(p, nn);
+ else if (nn->child != NULL &&
+ nn->child->type == ROFFT_TEXT &&
+ (nn->tok == MAN_B || nn->tok == MAN_BI ||
+ nn->tok == MAN_BR || nn->tok == MAN_I ||
+ nn->tok == MAN_IB || nn->tok == MAN_IR))
+ tag_man(p, nn->child);
+
while (nn != NULL) {
print_man_node(p, mt, nn, meta);
nn = nn->next;
@@ -1143,3 +1166,60 @@ print_man_head(struct termp *p, const struct roff_meta *meta)
}
free(title);
}
+
+/*
+ * Skip leading whitespace, dashes, backslashes, and font escapes,
+ * then create a tag if the first following byte is a letter.
+ * Priority is high unless whitespace is present.
+ */
+static void
+tag_man(struct termp *p, struct roff_node *n)
+{
+ const char *cp, *arg;
+ int prio, sz;
+
+ assert(n->type == ROFFT_TEXT);
+ cp = n->string;
+ prio = 1;
+ for (;;) {
+ switch (*cp) {
+ case ' ':
+ case '\t':
+ prio = INT_MAX;
+ /* FALLTHROUGH */
+ case '-':
+ cp++;
+ break;
+ case '\\':
+ cp++;
+ switch (mandoc_escape(&cp, &arg, &sz)) {
+ case ESCAPE_FONT:
+ case ESCAPE_FONTROMAN:
+ case ESCAPE_FONTITALIC:
+ case ESCAPE_FONTBOLD:
+ case ESCAPE_FONTPREV:
+ case ESCAPE_FONTBI:
+ break;
+ case ESCAPE_SPECIAL:
+ if (sz != 1)
+ return;
+ switch (*arg) {
+ case '&':
+ case '-':
+ case 'e':
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+ if (isalpha((unsigned char)*cp))
+ tag_put(cp, prio, p->line);
+ return;
+ }
+ }
+}
diff --git a/man_validate.c b/man_validate.c
index 4bfaf764e6c8..0aa550bd08d9 100644
--- a/man_validate.c
+++ b/man_validate.c
@@ -1,4 +1,4 @@
-/* $Id: man_validate.c,v 1.146 2018/12/31 10:04:39 schwarze Exp $ */
+/* $Id: man_validate.c,v 1.149 2019/06/27 15:07:30 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -41,7 +41,7 @@
typedef void (*v_check)(CHKARGS);
-static void check_abort(CHKARGS);
+static void check_abort(CHKARGS) __attribute__((__noreturn__));
static void check_par(CHKARGS);
static void check_part(CHKARGS);
static void check_root(CHKARGS);
@@ -185,8 +185,7 @@ check_root(CHKARGS)
man->meta.title = mandoc_strdup("");
man->meta.msec = mandoc_strdup("");
- man->meta.date = man->quick ? mandoc_strdup("") :
- mandoc_normdate(man, NULL, n->line, n->pos);
+ man->meta.date = mandoc_normdate(man, NULL, n->line, n->pos);
}
if (man->meta.os_e &&
@@ -369,8 +368,8 @@ post_TH(CHKARGS)
/* ->TITLE<- MSEC DATE OS VOL */
n = n->child;
- if (n && n->string) {
- for (p = n->string; '\0' != *p; p++) {
+ if (n != NULL && n->string != NULL) {
+ for (p = n->string; *p != '\0'; p++) {
/* Only warn about this once... */
if (isalpha((unsigned char)*p) &&
! isupper((unsigned char)*p)) {
@@ -388,9 +387,9 @@ post_TH(CHKARGS)
/* TITLE ->MSEC<- DATE OS VOL */
- if (n)
+ if (n != NULL)
n = n->next;
- if (n && n->string)
+ if (n != NULL && n->string != NULL)
man->meta.msec = mandoc_strdup(n->string);
else {
man->meta.msec = mandoc_strdup("");
@@ -400,17 +399,16 @@ post_TH(CHKARGS)
/* TITLE MSEC ->DATE<- OS VOL */
- if (n)
+ if (n != NULL)
n = n->next;
- if (n && n->string && '\0' != n->string[0]) {
- man->meta.date = man->quick ?
- mandoc_strdup(n->string) :
- mandoc_normdate(man, n->string, n->line, n->pos);
- } else {
+ if (n != NULL && n->string != NULL && n->string[0] != '\0')
+ man->meta.date = mandoc_normdate(man,
+ n->string, n->line, n->pos);
+ else {
man->meta.date = mandoc_strdup("");
mandoc_msg(MANDOCERR_DATE_MISSING,
- n ? n->line : nb->line,
- n ? n->pos : nb->pos, "TH");
+ n == NULL ? nb->line : n->line,
+ n == NULL ? nb->pos : n->pos, "TH");
}
/* TITLE MSEC DATE ->OS<- VOL */
diff --git a/mandoc.1 b/mandoc.1
index 79f6e8500d5c..298d5dc70610 100644
--- a/mandoc.1
+++ b/mandoc.1
@@ -1,7 +1,7 @@
-.\" $Id: mandoc.1,v 1.237 2019/02/23 18:53:54 schwarze Exp $
+.\" $Id: mandoc.1,v 1.240 2019/07/10 19:39:01 schwarze Exp $
.\"
.\" 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
@@ -15,7 +15,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: February 23 2019 $
+.Dd $Mdocdate: July 10 2019 $
.Dt MANDOC 1
.Os
.Sh NAME
@@ -222,7 +222,8 @@ reads from standard input.
.Pp
The options
.Fl fhklw
-are also supported and are documented in man(1).
+are also supported and are documented in
+.Xr man 1 .
In
.Fl f
and
@@ -697,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
@@ -777,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
@@ -825,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
@@ -1699,9 +1706,12 @@ The meaning of blank input lines is only well-defined in non-fill mode:
In fill mode, line breaks of text input lines are not supposed to be
significant.
However, for compatibility with groff, blank lines in fill mode
-are replaced with
+are formatted like
.Ic \&sp
requests.
+To request a paragraph break, use
+.Ic \&Pp
+instead of a blank line.
.It Sy "tab in filled text"
.Pq mdoc , man
The meaning of tab characters is only well-defined in non-fill mode:
@@ -2238,6 +2248,43 @@ 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 ,
.Xr man 1 ,
diff --git a/mandoc.c b/mandoc.c
index fb9395a585db..5a2be88e40df 100644
--- a/mandoc.c
+++ b/mandoc.c
@@ -1,4 +1,4 @@
-/* $Id: mandoc.c,v 1.114 2018/12/30 00:49:55 schwarze Exp $ */
+/* $Id: mandoc.c,v 1.116 2019/06/27 15:07:30 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -494,9 +494,10 @@ time2a(time_t t)
size_t ssz;
int isz;
+ buf = NULL;
tm = localtime(&t);
if (tm == NULL)
- return NULL;
+ goto fail;
/*
* Reserve space:
@@ -520,7 +521,8 @@ time2a(time_t t)
* of looking at LC_TIME.
*/
- if ((isz = snprintf(p, 4 + 1, "%d, ", tm->tm_mday)) == -1)
+ isz = snprintf(p, 4 + 1, "%d, ", tm->tm_mday);
+ if (isz < 0 || isz > 4)
goto fail;
p += isz;
@@ -530,7 +532,7 @@ time2a(time_t t)
fail:
free(buf);
- return NULL;
+ return mandoc_strdup("");
}
char *
@@ -539,12 +541,15 @@ mandoc_normdate(struct roff_man *man, char *in, int ln, int pos)
char *cp;
time_t t;
+ if (man->quick)
+ return mandoc_strdup(in == NULL ? "" : in);
+
/* No date specified: use today's date. */
- if (in == NULL || *in == '\0' || strcmp(in, "$" "Mdocdate$") == 0) {
+ if (in == NULL || *in == '\0')
mandoc_msg(MANDOCERR_DATE_MISSING, ln, pos, NULL);
+ if (in == NULL || *in == '\0' || strcmp(in, "$" "Mdocdate$") == 0)
return time2a(time(NULL));
- }
/* Valid mdoc(7) date format. */
diff --git a/mandoc.css b/mandoc.css
index 085f5c08b26d..d75700a28ba7 100644
--- a/mandoc.css
+++ b/mandoc.css
@@ -1,4 +1,4 @@
-/* $Id: mandoc.css,v 1.45 2019/03/01 10:57:18 schwarze Exp $ */
+/* $Id: mandoc.css,v 1.46 2019/06/02 16:57:13 schwarze Exp $ */
/*
* Standard style sheet for mandoc(1) -Thtml and man.cgi(8).
*
@@ -10,8 +10,13 @@
/* Global defaults. */
-html { max-width: 65em; }
-body { font-family: Helvetica,Arial,sans-serif; }
+html { max-width: 65em;
+ --bg: #FFFFFF;
+ --fg: #000000; }
+body { background: var(--bg);
+ color: var(--fg);
+ font-family: Helvetica,Arial,sans-serif; }
+h1 { font-size: 110%; }
table { margin-top: 0em;
margin-bottom: 0em;
border-collapse: collapse; }
@@ -69,8 +74,7 @@ td.foot-os { text-align: right; }
section.Sh { }
h1.Sh { margin-top: 1.2em;
margin-bottom: 0.6em;
- margin-left: -3.2em;
- font-size: 110%; }
+ margin-left: -3.2em; }
section.Ss { }
h2.Ss { margin-top: 1.2em;
margin-bottom: 0.6em;
@@ -310,14 +314,14 @@ h1.Sh::before, h2.Ss::before, .St::before, .Sx::before, .Sy::before,
pointer-events: none;
position: absolute;
bottom: 100%;
- box-shadow: 0 0 .35em #000;
+ box-shadow: 0 0 .35em var(--fg);
padding: .15em .25em;
white-space: nowrap;
font-family: Helvetica,Arial,sans-serif;
font-style: normal;
font-weight: bold;
- color: black;
- background: #fff; }
+ background: var(--bg);
+ color: var(--fg); }
.An:hover::before, .Ar:hover::before, .Cd:hover::before, .Cm:hover::before,
.Dv:hover::before, .Em:hover::before, .Er:hover::before, .Ev:hover::before,
.Fa:hover::before, .Fd:hover::before, .Fl:hover::before, .Fn:hover::before,
@@ -345,3 +349,12 @@ h1.Sh, h2.Ss { margin-left: 0em; }
.HP { margin-left: 2em;
text-indent: -2em; }
}
+
+/* Overrides for a dark color scheme for accessibility. */
+
+@media (prefers-color-scheme: dark) {
+html { --bg: #1E1F21;
+ --fg: #EEEFF1; }
+:link { color: #BAD7FF; }
+:visited { color: #F6BAFF; }
+}
diff --git a/mandoc.h b/mandoc.h
index a44b192e0f4f..4a7e7aa749ad 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -1,7 +1,7 @@
-/* $Id: mandoc.h,v 1.262 2018/12/16 00:17:02 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.264 2019/07/14 18:16:13 schwarze Exp $ */
/*
* 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? */
@@ -242,6 +241,35 @@ enum mandocerr {
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
};
@@ -281,6 +309,7 @@ enum mandoclevel mandoc_msg_getrc(void);
void mandoc_msg_setrc(enum mandoclevel);
void mandoc_msg(enum mandocerr, int, int, const char *, ...)
__attribute__((__format__ (__printf__, 4, 5)));
+void mandoc_msg_summary(void);
void mchars_alloc(void);
void mchars_free(void);
int mchars_num2char(const char *, size_t);
diff --git a/mandoc_char.7 b/mandoc_char.7
index 578f37f180c0..b46575d4d250 100644
--- a/mandoc_char.7
+++ b/mandoc_char.7
@@ -1,4 +1,4 @@
-.\" $Id: mandoc_char.7,v 1.75 2018/12/15 19:30:26 schwarze Exp $
+.\" $Id: mandoc_char.7,v 1.76 2019/03/31 19:17:26 schwarze Exp $
.\"
.\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -16,7 +16,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: December 15 2018 $
+.Dd $Mdocdate: March 31 2019 $
.Dt MANDOC_CHAR 7
.Os
.Sh NAME
@@ -107,8 +107,8 @@ supporting it, for example in
.Fl T Cm utf8
and
.Fl T Cm html .
-But currently, no practically relevant manual page formatter actually
-requires that subtlety, so in manual pages just write plain
+But currently, no practically relevant manual page formatter requires
+that subtlety, so in manual pages, it is sufficient to write plain
.Sq -
to represent hyphen, minus, and hyphen-minus.
.Pp
diff --git a/mandoc_headers.3 b/mandoc_headers.3
index 321384739116..2cda75cba8b3 100644
--- a/mandoc_headers.3
+++ b/mandoc_headers.3
@@ -1,4 +1,20 @@
-.Dd $Mdocdate: December 30 2018 $
+.\" $Id: mandoc_headers.3,v 1.31 2019/03/17 18:21:45 schwarze Exp $
+.\"
+.\" 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
+.\" 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.
+.\"
+.Dd $Mdocdate: March 17 2019 $
.Dt MANDOC_HEADERS 3
.Os
.Sh NAME
@@ -129,19 +145,19 @@ and the function
Uses pointers to the types
.Vt struct ohash
from
-.Pa mandoc_ohash.h ,
+.Qq Pa mandoc_ohash.h ,
.Vt struct mdoc_arg
and
.Vt union mdoc_data
from
-.Pa mdoc.h ,
+.Qq Pa mdoc.h ,
.Vt struct tbl_span
from
-.Pa tbl.h ,
+.Qq Pa tbl.h ,
and
.Vt struct eqn_box
from
-.Pa eqn.h
+.Qq Pa eqn.h
as opaque struct members.
.It Qq Pa tbl.h
Data structures for the
@@ -184,13 +200,13 @@ Top level parser interface, for use in the main program
and in the main parser, but not in formatters.
.Pp
Requires
-.Pa mandoc.h
+.Qq Pa mandoc.h
for
.Vt enum mandocerr
and
.Vt enum mandoclevel
and
-.Pa roff.h
+.Qq Pa roff.h
for
.Vt enum mandoc_os .
.Pp
@@ -202,7 +218,7 @@ for function prototypes.
Uses
.Vt struct roff_meta
from
-.Pa roff.h
+.Qq Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa mandoc_xr.h
Cross reference validation; intended for use in the main program
@@ -251,11 +267,11 @@ described in
Uses the types
.Vt struct roff_node
from
-.Pa roff.h
+.Qq Pa roff.h
and
.Vt struct roff_man
from
-.Pa roff_int.h
+.Qq Pa roff_int.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@@ -269,7 +285,7 @@ described in
Uses the type
.Vt struct roff_man
from
-.Pa roff.h
+.Qq Pa roff.h
as an opaque type for function prototypes.
.Pp
When this header is included, the same file should not include
@@ -305,7 +321,7 @@ for function prototypes.
Uses the type
.Vt struct roff_man
from
-.Pa roff.h
+.Qq Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa roff_int.h
Parser internals shared by multiple parsers.
@@ -334,24 +350,24 @@ and the two special functions
and
.Fn mdoc_argv_free
because the latter two are needed by
-.Qq Pa roff.c .
+.Pa roff.c .
.Pp
Uses the types
.Vt struct ohash
from
-.Pa mandoc_ohash.h ,
+.Qq Pa mandoc_ohash.h ,
.Vt struct roff_node
and
.Vt struct roff_meta
from
-.Pa roff.h ,
+.Qq Pa roff.h ,
.Vt struct roff
from
.Pa roff.c ,
and
.Vt struct mdoc_arg
from
-.Pa mdoc.h
+.Qq Pa mdoc.h
as opaque types for function prototypes.
.It Qq Pa libmdoc.h
Requires
@@ -372,14 +388,14 @@ parser.
Uses the types
.Vt struct roff_node
from
-.Pa roff.h ,
+.Qq Pa roff.h ,
.Vt struct roff_man
from
-.Pa roff_int.h ,
+.Qq Pa roff_int.h ,
and
.Vt struct mdoc_arg
from
-.Pa mdoc.h
+.Qq Pa mdoc.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@@ -399,11 +415,11 @@ parser.
Uses the types
.Vt struct roff_node
from
-.Pa roff.h
+.Qq Pa roff.h
and
.Vt struct roff_man
from
-.Pa roff_int.h
+.Qq Pa roff_int.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@@ -437,12 +453,12 @@ and
Uses the type
.Vt struct eqn_box
from
-.Pa mandoc.h
+.Qq Pa mandoc.h
as an opaque type for function prototypes.
Uses the types
.Vt struct roff_node
from
-.Pa roff.h
+.Qq Pa roff.h
and
.Vt struct eqn_def
from
@@ -466,11 +482,11 @@ Provides the functions documented in
Uses the types
.Vt struct tbl_span
from
-.Pa tbl.h
+.Qq Pa tbl.h
and
.Vt struct tbl_node
from
-.Pa tbl_int.h
+.Qq Pa tbl_int.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@@ -523,11 +539,11 @@ and
Uses
.Vt struct tbl_span
from
-.Pa mandoc.h
+.Qq Pa mandoc.h
as an opaque type for function prototypes.
.Pp
When this header is included, the same file should not include
-.Pa mansearch.h .
+.Qq Pa mansearch.h .
.It Qq Pa term.h
Requires
.In sys/types.h
@@ -558,27 +574,30 @@ Uses
and
.Vt struct eqn_box
from
-.Pa mandoc.h
+.Qq Pa mandoc.h
and
.Vt struct roff_meta
and
.Vt struct roff_node
from
-.Pa roff.h
+.Qq Pa roff.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
-.Pa html.h
+.Qq Pa html.h
or
-.Pa mansearch.h .
+.Qq Pa mansearch.h .
.It Qq Pa html.h
Requires
.In sys/types.h
for
.Vt size_t ,
-.Pa mandoc.h
+.Qq Pa mandoc.h
for
.Vt enum mandoc_esc ,
+.Qq Pa roff.h
+for
+.Vt enum roff_tok ,
and
.Qq Pa out.h
for
@@ -602,17 +621,17 @@ Uses
and
.Vt struct eqn_box
from
-.Pa mandoc.h
+.Qq Pa mandoc.h
and
.Vt struct roff_node
from
-.Pa roff.h
+.Qq Pa roff.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
-.Pa term.h
+.Qq Pa term.h
or
-.Pa mansearch.h .
+.Qq Pa mansearch.h .
.It Qq Pa tag.h
Requires
.In sys/types.h
@@ -631,7 +650,7 @@ Provides the top level steering functions for all formatters.
Uses the type
.Vt struct roff_meta
from
-.Pa roff.h
+.Qq Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa manconf.h
Requires
@@ -671,12 +690,12 @@ and
Uses
.Vt struct manpaths
from
-.Pa manconf.h
+.Qq Pa manconf.h
as an opaque type for function prototypes.
.Pp
When this header is included, the same file should not include
-.Pa out.h ,
-.Pa term.h ,
+.Qq Pa out.h ,
+.Qq Pa term.h ,
or
-.Pa html.h .
+.Qq Pa html.h .
.El
diff --git a/mandoc_msg.c b/mandoc_msg.c
index ff4d80313c2c..e73dcfd830ff 100644
--- a/mandoc_msg.c
+++ b/mandoc_msg.c
@@ -1,7 +1,7 @@
-/* $Id: mandoc_msg.c,v 1.6 2019/03/06 15:55:38 schwarze Exp $ */
+/* $Id: mandoc_msg.c,v 1.8 2019/07/14 18:16:13 schwarze Exp $ */
/*
* 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[MANDOCLEVEL_MAX] = {
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[MANDOCERR_MAX] = {
"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[MANDOCERR_MAX] = {
"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, int col, const char *fmt, ...)
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);
@@ -327,3 +355,12 @@ mandoc_msg(enum mandocerr t, int line, int col, const char *fmt, ...)
}
fputc('\n', fileptr);
}
+
+void
+mandoc_msg_summary(void)
+{
+ if (fileptr != NULL && rc != MANDOCLEVEL_OK)
+ fprintf(fileptr,
+ "%s: see above the output for %s messages\n",
+ getprogname(), level_name[rc]);
+}
diff --git a/mandocdb.c b/mandocdb.c
index 222350c987b6..64ac10115877 100644
--- a/mandocdb.c
+++ b/mandocdb.c
@@ -1,7 +1,7 @@
-/* $Id: mandocdb.c,v 1.262 2018/12/30 00:49:55 schwarze Exp $ */
+/* $Id: mandocdb.c,v 1.263 2019/05/03 18:17:12 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011-2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011-2019 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2016 Ed Maste <emaste@freebsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -1186,9 +1186,11 @@ mpages_merge(struct dba *dba, struct mparse *mp)
mlink->next = mlink_dest->next;
mlink_dest->next = mpage->mlinks;
mpage->mlinks = NULL;
+ goto nextpage;
}
- goto nextpage;
- } else if (meta != NULL && meta->macroset == MACROSET_MDOC) {
+ meta->macroset = MACROSET_NONE;
+ }
+ if (meta != NULL && meta->macroset == MACROSET_MDOC) {
mpage->form = FORM_SRC;
mpage->sec = meta->msec;
mpage->sec = mandoc_strdup(
@@ -1208,12 +1210,15 @@ mpages_merge(struct dba *dba, struct mparse *mp)
}
assert(mpage->desc == NULL);
- if (meta == NULL) {
- mpage->form = FORM_CAT;
+ if (meta == NULL || meta->sodest != NULL) {
mpage->sec = mandoc_strdup(mlink->dsec);
mpage->arch = mandoc_strdup(mlink->arch);
mpage->title = mandoc_strdup(mlink->name);
- parse_cat(mpage, fd);
+ if (meta == NULL) {
+ mpage->form = FORM_CAT;
+ parse_cat(mpage, fd);
+ } else
+ mpage->form = FORM_SRC;
} else if (meta->macroset == MACROSET_MDOC)
parse_mdoc(mpage, meta, meta->first);
else
diff --git a/manpath.c b/manpath.c
index 74f38a95db9e..e4578ccec364 100644
--- a/manpath.c
+++ b/manpath.c
@@ -1,6 +1,6 @@
-/* $Id: manpath.c,v 1.37 2018/11/22 11:30:23 schwarze Exp $ */
+/* $Id: manpath.c,v 1.40 2019/07/10 19:39:01 schwarze Exp $ */
/*
- * 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, const char *file,
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, const char *file,
/* 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, const char *file,
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, char *path, int complain)
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, char *path, int complain)
* 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 char *file)
*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 char *file)
out:
if (*manpath_default != '\0')
- manpath_parseline(&conf->manpath, manpath_default, 0);
+ manpath_parseline(&conf->manpath, manpath_default, '\0');
}
int
@@ -235,14 +233,15 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
"includes", "man", "paper", "style", "indent", "width",
"tag", "fragment", "mdoc", "noval", "toc"
};
+ const size_t ntoks = sizeof(toks) / sizeof(toks[0]);
const char *errstr;
char *oldval;
size_t len, tok;
- for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {
+ 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 == '=')
@@ -254,11 +253,11 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
}
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 && *cp != '\0') {
- warnx("-O %s: Does not take a value: %s", toks[tok], cp);
+ if (tok > 6 && tok < ntoks && *cp != '\0') {
+ mandoc_msg(MANDOCERR_BADVAL, 0, 0, "-O %s=%s", toks[tok], cp);
return -1;
}
@@ -299,7 +298,8 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
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) {
@@ -309,7 +309,8 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
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) {
@@ -331,13 +332,16 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
conf->toc = 1;
return 0;
default:
- if (fromfile)
- 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;
}
diff --git a/mansearch.c b/mansearch.c
index 0c457f95d109..59a35771970c 100644
--- a/mansearch.c
+++ b/mansearch.c
@@ -1,4 +1,4 @@
-/* $Id: mansearch.c,v 1.80 2018/12/13 11:55:46 schwarze Exp $ */
+/* $Id: mansearch.c,v 1.82 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013-2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -191,7 +191,7 @@ mansearch(const struct mansearch *search,
mpage->file, R_OK) == -1) {
warn("%s", mpage->file);
warnx("outdated mandoc.db contains "
- "bogus %s entry, run makewhatis %s",
+ "bogus %s entry, run makewhatis %s",
page->file + 1, paths->paths[i]);
free(mpage->file);
free(rp);
@@ -199,6 +199,7 @@ mansearch(const struct mansearch *search,
}
mpage->names = buildnames(page);
mpage->output = buildoutput(outkey, page);
+ mpage->bits = search->firstmatch ? rp->bits : 0;
mpage->ipath = i;
mpage->sec = *page->sect - '0';
if (mpage->sec < 0 || mpage->sec > 9)
@@ -294,8 +295,10 @@ manmerge_term(struct expr *e, struct ohash *htab)
break;
slot = ohash_lookup_memory(htab,
(char *)&res, sizeof(res.page), res.page);
- if ((rp = ohash_find(htab, slot)) != NULL)
+ if ((rp = ohash_find(htab, slot)) != NULL) {
+ rp->bits |= res.bits;
continue;
+ }
rp = mandoc_malloc(sizeof(*rp));
*rp = res;
ohash_insert(htab, slot, rp);
@@ -408,7 +411,8 @@ manpage_compare(const void *vp1, const void *vp2)
mp1 = vp1;
mp2 = vp2;
- if ((diff = mp1->sec - mp2->sec))
+ if ((diff = mp2->bits - mp1->bits) ||
+ (diff = mp1->sec - mp2->sec))
return diff;
/* Fall back to alphabetic ordering of names. */
diff --git a/mansearch.h b/mansearch.h
index 355873f83e09..8a0aa121d0c6 100644
--- a/mansearch.h
+++ b/mansearch.h
@@ -1,4 +1,4 @@
-/* $Id: mansearch.h,v 1.29 2018/11/22 12:01:46 schwarze Exp $ */
+/* $Id: mansearch.h,v 1.30 2019/04/30 18:51:57 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -92,6 +92,7 @@ struct manpage {
char *file; /* to be prefixed by manpath */
char *names; /* a list of names with sections */
char *output; /* user-defined additional output */
+ uint64_t bits; /* name type mask */
size_t ipath; /* number of the manpath */
int sec; /* section number, 10 means invalid */
enum form form;
diff --git a/mdoc.7 b/mdoc.7
index 0624ce788cd2..deca4ba88c05 100644
--- a/mdoc.7
+++ b/mdoc.7
@@ -1,4 +1,4 @@
-.\" $Id: mdoc.7,v 1.276 2019/02/07 15:45:53 schwarze Exp $
+.\" $Id: mdoc.7,v 1.279 2019/07/15 19:20:30 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010, 2011, 2013-2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,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: February 7 2019 $
+.Dd $Mdocdate: July 15 2019 $
.Dt MDOC 7
.Os
.Sh NAME
@@ -596,6 +596,13 @@ block.
Book or journal page number of an
.Ic \&Rs
block.
+Conventionally, the argument starts with
+.Ql p.\&
+for a single page or
+.Ql pp.\&
+for a range of pages, for example:
+.Pp
+.Dl .%P pp. 42\e(en47
.It Ic \&%Q Ar name
Institutional author (school, government, etc.) of an
.Ic \&Rs
@@ -1156,17 +1163,19 @@ declarations.
This practise is discouraged.
.It Ic \&Cm Ar keyword ...
Command modifiers.
-Typically used for fixed strings passed as arguments, unless
+Typically used for fixed strings passed as arguments to interactive
+commands, to commands in interpreted scripts, or to configuration
+file directives, unless
.Ic \&Fl
is more appropriate.
-Also useful when specifying configuration options or keys.
.Pp
Examples:
.Dl ".Nm mt Fl f Ar device Cm rewind"
.Dl ".Nm ps Fl o Cm pid , Ns Cm command"
.Dl ".Nm dd Cm if= Ns Ar file1 Cm of= Ns Ar file2"
-.Dl ".Cm IdentityFile Pa ~/.ssh/id_rsa"
-.Dl ".Cm LogLevel Dv DEBUG"
+.Dl ".Ic set Fl o Cm vi"
+.Dl ".Ic lookup Cm file bind"
+.Dl ".Ic permit Ar identity Op Cm as Ar target"
.It Ic \&D1 Ar line
One-line indented display.
This is formatted by the default rules and is useful for simple indented
@@ -1677,10 +1686,10 @@ This macro is not implemented in
.Xr mandoc 1 .
It was used to include the contents of a (header) file literally.
.It Ic \&Ic Ar keyword ...
-Designate an internal or interactive command.
-This is similar to
-.Ic \&Cm
-but used for instructions rather than values.
+Internal or interactive command, or configuration instruction
+in a configuration file.
+See also
+.Ic \&Cm .
.Pp
Examples:
.Dl \&.Ic :wq
@@ -2969,7 +2978,7 @@ exclamation mark
Note that even a period preceded by a backslash
.Pq Sq \e.\&
gets this special handling; use
-.Sq \e&.
+.Sq \e&.\&
to prevent that.
.Pp
Many in-line macros interrupt their scope when they encounter
@@ -2996,6 +3005,13 @@ in the same way as a plain
.Sq \&|
character.
Using this predefined string is not recommended in new manuals.
+.Pp
+Appending a zero-width space
+.Pq Sq \e&
+to the end of an input line is also useful to prevent the interpretation
+of a trailing period, exclamation or question mark as the end of a
+sentence, for example when an abbreviation happens to occur
+at the end of a text or macro input line.
.Ss Font handling
In
.Nm
diff --git a/mdoc_argv.c b/mdoc_argv.c
index f4ce4a8730f3..1bfd336b7a97 100644
--- a/mdoc_argv.c
+++ b/mdoc_argv.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc_argv.c,v 1.119 2018/12/21 17:15:19 schwarze Exp $ */
+/* $Id: mdoc_argv.c,v 1.120 2019/07/11 17:06:17 schwarze Exp $ */
/*
* Copyright (c) 2008, 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
@@ -454,6 +454,7 @@ args(struct roff_man *mdoc, int line, int *pos,
mandoc_msg(MANDOCERR_ARG_QUOTE, line, *pos, NULL);
mdoc->flags &= ~MDOC_PHRASELIT;
}
+ mdoc->flags &= ~MDOC_PHRASEQL;
return ARGS_EOLN;
}
diff --git a/mdoc_markdown.c b/mdoc_markdown.c
index e9a931218cc4..88e37c0b188b 100644
--- a/mdoc_markdown.c
+++ b/mdoc_markdown.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_markdown.c,v 1.30 2018/12/30 00:49:55 schwarze Exp $ */
+/* $Id: mdoc_markdown.c,v 1.31 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -1290,7 +1290,7 @@ md_post_It(struct roff_node *n)
while ((n = n->prev) != NULL && n->type != ROFFT_HEAD)
i++;
- /*
+ /*
* If a width was specified for this column,
* subtract what printed, and
* add the same spacing as in mdoc_term.c.
diff --git a/mdoc_term.c b/mdoc_term.c
index 52ff27e17f11..18f0ff09e2c7 100644
--- a/mdoc_term.c
+++ b/mdoc_term.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_term.c,v 1.372 2019/01/04 03:39:01 schwarze Exp $ */
+/* $Id: mdoc_term.c,v 1.374 2019/06/27 12:20:18 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -253,7 +253,7 @@ static int fn_prio;
void
terminal_mdoc(void *arg, const struct roff_meta *mdoc)
{
- struct roff_node *n;
+ struct roff_node *n, *nn;
struct termp *p;
size_t save_defindent;
@@ -265,16 +265,20 @@ terminal_mdoc(void *arg, const struct roff_meta *mdoc)
n = mdoc->first->child;
if (p->synopsisonly) {
- while (n != NULL) {
- if (n->tok == MDOC_Sh && n->sec == SEC_SYNOPSIS) {
- if (n->child->next->child != NULL)
- print_mdoc_nodelist(p, NULL,
- mdoc, n->child->next->child);
- term_newln(p);
+ for (nn = NULL; n != NULL; n = n->next) {
+ if (n->tok != MDOC_Sh)
+ continue;
+ if (n->sec == SEC_SYNOPSIS)
break;
- }
- n = n->next;
+ if (nn == NULL && n->sec == SEC_NAME)
+ nn = n;
}
+ if (n == NULL)
+ n = nn;
+ p->flags |= TERMP_NOSPACE;
+ if (n != NULL && (n = n->child->next->child) != NULL)
+ print_mdoc_nodelist(p, NULL, mdoc, n);
+ term_newln(p);
} else {
save_defindent = p->defindent;
if (p->defindent == 0)
@@ -352,6 +356,7 @@ print_mdoc_node(DECL_ARGS)
* produce output. Note that some pre-handlers do so.
*/
+ act = NULL;
switch (n->type) {
case ROFFT_TEXT:
if (n->flags & NODE_LINE) {
diff --git a/mdoc_validate.c b/mdoc_validate.c
index 7d1575f2f0f1..11cdf00b56cb 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_validate.c,v 1.371 2019/03/04 13:01:57 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.374 2019/06/27 15:07:30 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -64,7 +64,7 @@ static size_t macro2len(enum roff_tok);
static void rewrite_macro2len(struct roff_man *, char **);
static int similar(const char *, const char *);
-static void post_abort(POST_ARGS);
+static void post_abort(POST_ARGS) __attribute__((__noreturn__));
static void post_an(POST_ARGS);
static void post_an_norm(POST_ARGS);
static void post_at(POST_ARGS);
@@ -1903,8 +1903,7 @@ post_root(POST_ARGS)
/* Add missing prologue data. */
if (mdoc->meta.date == NULL)
- mdoc->meta.date = mdoc->quick ? mandoc_strdup("") :
- mandoc_normdate(mdoc, NULL, 0, 0);
+ mdoc->meta.date = mandoc_normdate(mdoc, NULL, 0, 0);
if (mdoc->meta.title == NULL) {
mandoc_msg(MANDOCERR_DT_NOTITLE, 0, 0, "EOF");
@@ -2519,21 +2518,10 @@ post_dd(POST_ARGS)
mandoc_msg(MANDOCERR_PROLOG_ORDER,
n->line, n->pos, "Dd after Os");
- if (n->child == NULL || n->child->string[0] == '\0') {
- mdoc->meta.date = mdoc->quick ? mandoc_strdup("") :
- mandoc_normdate(mdoc, NULL, n->line, n->pos);
- return;
- }
-
datestr = NULL;
deroff(&datestr, n);
- if (mdoc->quick)
- mdoc->meta.date = datestr;
- else {
- mdoc->meta.date = mandoc_normdate(mdoc,
- datestr, n->line, n->pos);
- free(datestr);
- }
+ mdoc->meta.date = mandoc_normdate(mdoc, datestr, n->line, n->pos);
+ free(datestr);
}
static void
diff --git a/out.c b/out.c
index 363d04cf979d..d0b0d0a2ace3 100644
--- a/out.c
+++ b/out.c
@@ -1,4 +1,4 @@
-/* $Id: out.c,v 1.77 2018/12/13 11:55:47 schwarze Exp $ */
+/* $Id: out.c,v 1.78 2019/03/29 21:27:06 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -149,7 +149,7 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp_first,
gp = &first_group;
for (dp = sp->first; dp != NULL; dp = dp->next) {
icol = dp->layout->col;
- while (icol > maxcol)
+ while (maxcol < icol + dp->hspans)
tbl->cols[++maxcol].spacing = SIZE_MAX;
col = tbl->cols + icol;
col->flags |= dp->layout->flags;
diff --git a/read.c b/read.c
index a3a1f982c01c..b3858061e710 100644
--- a/read.c
+++ b/read.c
@@ -1,4 +1,4 @@
-/* $Id: read.c,v 1.211 2019/01/11 17:04:44 schwarze Exp $ */
+/* $Id: read.c,v 1.214 2019/07/10 19:39:01 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -157,7 +157,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
ln.sz = 256;
ln.buf = mandoc_malloc(ln.sz);
ln.next = NULL;
- firstln = loop = NULL;
+ firstln = lastln = loop = NULL;
lnn = curp->line;
pos = 0;
inloop = 0;
@@ -255,6 +255,8 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
/* XXX Ugly hack to mark the end of the input. */
if (i == blk.sz || blk.buf[i] == '\0') {
+ if (pos + 2 > ln.sz)
+ resize_buf(&ln, 256);
ln.buf[pos++] = '\n';
ln.buf[pos] = '\0';
}
@@ -429,9 +431,8 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
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;
}
/*
@@ -444,13 +445,13 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
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) {
@@ -462,15 +463,15 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
* 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;
@@ -482,7 +483,7 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
*with_mmap = 0;
off = 0;
- retval = 0;
+ retval = -1;
fb->sz = 0;
fb->buf = NULL;
for (;;) {
@@ -498,13 +499,13 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
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;
@@ -513,10 +514,10 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
}
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;
}
@@ -555,7 +556,7 @@ mparse_readfd(struct mparse *curp, int fd, const char *filename)
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;
/*
diff --git a/roff.7 b/roff.7
index de76a3c4d246..f129750b1b0e 100644
--- a/roff.7
+++ b/roff.7
@@ -1,4 +1,4 @@
-.\" $Id: roff.7,v 1.111 2019/01/01 03:45:29 schwarze Exp $
+.\" $Id: roff.7,v 1.114 2019/07/15 19:20:30 schwarze Exp $
.\"
.\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,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: January 1 2019 $
+.Dd $Mdocdate: July 15 2019 $
.Dt ROFF 7
.Os
.Sh NAME
@@ -315,12 +315,18 @@ delimiters
The proper spacing is also intelligently preserved if a sentence ends at
the boundary of a macro line.
.Pp
+If an input line happens to end with a period, exclamation or question
+mark that isn't the end of a sentence, append a zero-width space
+.Pq Sq \e& .
+.Pp
Examples:
.Bd -literal -offset indent -compact
Do not end sentences mid-line like this. Instead,
end a sentence like this.
A macro would end like this:
\&.Xr mandoc 1 \&.
+An abbreviation at the end of an input line needs escaping, e.g.\e&
+like this.
.Ed
.Sh REQUEST SYNTAX
A request or macro line consists of:
@@ -503,10 +509,9 @@ This is a Heirloom extension and currently unsupported.
.It Ic \&br
Break the output line.
.It Ic \&break
-Break out of a
+Break out of the innermost
.Ic \&while
loop.
-Currently unsupported.
.It Ic \&breakchar Ar char ...
Optional line break characters.
This is a Heirloom extension and currently ignored.
@@ -2279,7 +2284,7 @@ code.
.Pp
The special semantics of the
.Cm nS
-number register is an idiosyncracy of
+number register is an idiosyncrasy of
.Ox
manuals and not supported by other
.Xr mdoc 7
diff --git a/roff.c b/roff.c
index 2b07352b90a3..f26d9f01f226 100644
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.363 2019/02/06 21:11:43 schwarze Exp $ */
+/* $Id: roff.c,v 1.366 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -133,15 +133,18 @@ struct roff {
char escape; /* escape character */
};
+/*
+ * A macro definition, condition, or ignored block.
+ */
struct roffnode {
enum roff_tok tok; /* type of node */
struct roffnode *parent; /* up one in stack */
int line; /* parse line */
int col; /* parse col */
char *name; /* node name, e.g. macro name */
- char *end; /* end-rules: custom token */
- int endspan; /* end-rules: next-line or infty */
- int rule; /* current evaluation rule */
+ char *end; /* custom end macro of the block */
+ int endspan; /* scope to: 1=eol 2=next line -1=\} */
+ int rule; /* content is: 1=evaluated 0=skipped */
};
#define ROFF_ARGS struct roff *r, /* parse ctx */ \
@@ -181,6 +184,7 @@ static int roff_als(ROFF_ARGS);
static int roff_block(ROFF_ARGS);
static int roff_block_text(ROFF_ARGS);
static int roff_block_sub(ROFF_ARGS);
+static int roff_break(ROFF_ARGS);
static int roff_cblock(ROFF_ARGS);
static int roff_cc(ROFF_ARGS);
static int roff_ccond(struct roff *, int, int);
@@ -400,7 +404,7 @@ static struct roffmac roffs[TOKEN_NONE] = {
{ roff_unsupp, NULL, NULL, 0 }, /* boxa */
{ roff_line_ignore, NULL, NULL, 0 }, /* bp */
{ roff_unsupp, NULL, NULL, 0 }, /* BP */
- { roff_unsupp, NULL, NULL, 0 }, /* break */
+ { roff_break, NULL, NULL, 0 }, /* break */
{ roff_line_ignore, NULL, NULL, 0 }, /* breakchar */
{ roff_line_ignore, NULL, NULL, 0 }, /* brnl */
{ roff_noarg, NULL, NULL, 0 }, /* brp */
@@ -685,7 +689,7 @@ roffhash_find(struct ohash *htab, const char *name, size_t sz)
/*
* Pop the current node off of the stack of roff instructions currently
- * pending.
+ * pending. Return 1 if it is a loop or 0 otherwise.
*/
static int
roffnode_pop(struct roff *r)
@@ -779,7 +783,7 @@ roff_reset(struct roff *r)
void
roff_free(struct roff *r)
{
- int i;
+ int i;
roff_free1(r);
for (i = 0; i < r->mstacksz; i++)
@@ -1586,7 +1590,7 @@ char *
roff_getarg(struct roff *r, char **cpp, int ln, int *pos)
{
struct buf buf;
- char *cp, *start;
+ char *cp, *start;
int newesc, pairs, quoted, white;
/* Quoting can only start with a new word. */
@@ -2002,6 +2006,10 @@ roff_cblock(ROFF_ARGS)
}
+/*
+ * Pop all nodes ending at the end of the current input line.
+ * Return the number of loops ended.
+ */
static int
roffnode_cleanscope(struct roff *r)
{
@@ -2016,6 +2024,11 @@ roffnode_cleanscope(struct roff *r)
return inloop;
}
+/*
+ * Handle the closing \} of a conditional block.
+ * Apart from generating warnings, this only pops nodes.
+ * Return the number of loops ended.
+ */
static int
roff_ccond(struct roff *r, int ln, int ppos)
{
@@ -2235,6 +2248,7 @@ roff_block_text(ROFF_ARGS)
static int
roff_cond_sub(ROFF_ARGS)
{
+ struct roffnode *bl;
char *ep;
int endloop, irc, rr;
enum roff_tok t;
@@ -2282,9 +2296,21 @@ roff_cond_sub(ROFF_ARGS)
*/
t = roff_parse(r, buf->buf, &pos, ln, ppos);
- irc |= t != TOKEN_NONE && (rr || roffs[t].flags & ROFFMAC_STRUCT) ?
- (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs) :
- rr ? ROFF_CONT : ROFF_IGN;
+ if (t == ROFF_break) {
+ if (irc & ROFF_LOOPMASK)
+ irc = ROFF_IGN | ROFF_LOOPEXIT;
+ else if (rr) {
+ for (bl = r->last; bl != NULL; bl = bl->parent) {
+ bl->rule = 0;
+ if (bl->tok == ROFF_while)
+ break;
+ }
+ }
+ } else if (t != TOKEN_NONE &&
+ (rr || roffs[t].flags & ROFFMAC_STRUCT))
+ irc |= (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs);
+ else
+ irc |= rr ? ROFF_CONT : ROFF_IGN;
return irc;
}
@@ -3482,6 +3508,17 @@ roff_als(ROFF_ARGS)
return ROFF_IGN;
}
+/*
+ * The .break request only makes sense inside conditionals,
+ * and that case is already handled in roff_cond_sub().
+ */
+static int
+roff_break(ROFF_ARGS)
+{
+ mandoc_msg(MANDOCERR_BLK_NOTOPEN, ln, pos, "break");
+ return ROFF_IGN;
+}
+
static int
roff_cc(ROFF_ARGS)
{
@@ -3804,6 +3841,11 @@ roff_userdef(ROFF_ARGS)
char *arg, *ap, *dst, *src;
size_t sz;
+ /* If the macro is empty, ignore it altogether. */
+
+ if (*r->current_string == '\0')
+ return ROFF_IGN;
+
/* Initialize a new macro stack context. */
if (++r->mstackpos == r->mstacksz) {
@@ -3851,7 +3893,7 @@ roff_userdef(ROFF_ARGS)
buf->sz = strlen(buf->buf) + 1;
*offs = 0;
- return buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ?
+ return buf->buf[buf->sz - 2] == '\n' ?
ROFF_REPARSE | ROFF_USERCALL : ROFF_IGN | ROFF_APPEND;
}
diff --git a/roff_html.c b/roff_html.c
index 02b8beea3bdc..e525aa2ede68 100644
--- a/roff_html.c
+++ b/roff_html.c
@@ -1,4 +1,4 @@
-/* $Id: roff_html.c,v 1.19 2019/01/07 07:26:29 schwarze Exp $ */
+/* $Id: roff_html.c,v 1.20 2019/04/30 15:53:01 schwarze Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2017, 2018, 2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -94,7 +94,7 @@ roff_html_pre_ft(ROFF_HTML_ARGS)
const char *cp;
cp = n->child->string;
- print_metaf(h, mandoc_font(cp, (int)strlen(cp)));
+ html_setfont(h, mandoc_font(cp, (int)strlen(cp)));
}
static void
diff --git a/tag.c b/tag.c
index 473ea7b6f491..d5e7f89c1a50 100644
--- a/tag.c
+++ b/tag.c
@@ -1,6 +1,6 @@
-/* $Id: tag.c,v 1.21 2018/11/22 11:30:23 schwarze Exp $ */
+/* $Id: tag.c,v 1.24 2019/07/22 03:21:50 schwarze Exp $ */
/*
- * 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);
/*
@@ -142,11 +151,11 @@ tag_put(const char *s, int prio, size_t line)
s += 2;
/*
- * Skip whitespace and whatever follows it,
+ * Skip whitespace and escapes and whatever follows,
* and if there is any, downgrade the priority.
*/
- len = strcspn(s, " \t");
+ len = strcspn(s, " \t\\");
if (len == 0)
return;
@@ -216,21 +225,27 @@ tag_write(void)
struct tag_entry *entry;
size_t i;
unsigned int slot;
+ int empty;
if (tag_files.tfd <= 0)
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));
+ empty = 1;
entry = ohash_first(&tag_data, &slot);
while (entry != NULL) {
- if (stream != NULL && entry->prio >= 0)
- for (i = 0; i < entry->nlines; i++)
+ if (stream != NULL && entry->prio >= 0) {
+ for (i = 0; i < entry->nlines; i++) {
fprintf(stream, "%s %s %zu\n",
entry->s, tag_files.ofn, entry->lines[i]);
+ empty = 0;
+ }
+ }
free(entry->lines);
free(entry);
entry = ohash_next(&tag_data, &slot);
@@ -241,6 +256,10 @@ tag_write(void)
else
close(tag_files.tfd);
tag_files.tfd = -1;
+ if (empty) {
+ unlink(tag_files.tfn);
+ *tag_files.tfn = '\0';
+ }
}
void
diff --git a/tbl_html.c b/tbl_html.c
index 4ab6bed10bd0..e137757dc16c 100644
--- a/tbl_html.c
+++ b/tbl_html.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_html.c,v 1.32 2019/01/06 04:55:09 schwarze Exp $ */
+/* $Id: tbl_html.c,v 1.33 2019/03/17 18:21:45 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -25,6 +25,7 @@
#include <string.h>
#include "mandoc.h"
+#include "roff.h"
#include "tbl.h"
#include "out.h"
#include "html.h"
diff --git a/tbl_term.c b/tbl_term.c
index a197f8ef743a..de88d61c15e1 100644
--- a/tbl_term.c
+++ b/tbl_term.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_term.c,v 1.68 2019/02/09 21:02:47 schwarze Exp $ */
+/* $Id: tbl_term.c,v 1.72 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -46,7 +46,8 @@ static void tbl_fill_border(struct termp *, int, size_t);
static void tbl_fill_char(struct termp *, char, size_t);
static void tbl_fill_string(struct termp *, const char *, size_t);
static void tbl_hrule(struct termp *, const struct tbl_span *,
- const struct tbl_span *, int);
+ const struct tbl_span *, const struct tbl_span *,
+ int);
static void tbl_literal(struct termp *, const struct tbl_dat *,
const struct roffcol *);
static void tbl_number(struct termp *, const struct tbl_opts *,
@@ -163,7 +164,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
const struct tbl_cell *cp, *cpn, *cpp, *cps;
const struct tbl_dat *dp;
static size_t offset;
- size_t save_offset;
+ size_t save_offset;
size_t coloff, tsz;
int hspans, ic, more;
int dvert, fc, horiz, lhori, rhori, uvert;
@@ -222,9 +223,9 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
if (tp->enc == TERMENC_ASCII &&
sp->opts->opts & TBL_OPT_DBOX)
- tbl_hrule(tp, NULL, sp, TBL_OPT_DBOX);
+ tbl_hrule(tp, NULL, sp, sp, TBL_OPT_DBOX);
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX))
- tbl_hrule(tp, NULL, sp, TBL_OPT_BOX);
+ tbl_hrule(tp, NULL, sp, sp, TBL_OPT_BOX);
}
/* Set up the columns. */
@@ -342,7 +343,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
more = 0;
if (horiz)
- tbl_hrule(tp, sp->prev, sp, 0);
+ tbl_hrule(tp, sp->prev, sp, sp->next, 0);
else {
cp = sp->layout->first;
cpn = sp->next == NULL ? NULL :
@@ -557,12 +558,12 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
tp->tcol->rmargin = tp->maxrmargin;
if (sp->next == NULL) {
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) {
- tbl_hrule(tp, sp, NULL, TBL_OPT_BOX);
+ tbl_hrule(tp, sp, sp, NULL, TBL_OPT_BOX);
tp->skipvsp = 1;
}
if (tp->enc == TERMENC_ASCII &&
sp->opts->opts & TBL_OPT_DBOX) {
- tbl_hrule(tp, sp, NULL, TBL_OPT_DBOX);
+ tbl_hrule(tp, sp, sp, NULL, TBL_OPT_DBOX);
tp->skipvsp = 2;
}
assert(tp->tbl.cols);
@@ -571,7 +572,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
} else if (horiz == 0 && sp->opts->opts & TBL_OPT_ALLBOX &&
(sp->next == NULL || sp->next->pos == TBL_SPAN_DATA ||
sp->next->next != NULL))
- tbl_hrule(tp, sp, sp->next, TBL_OPT_ALLBOX);
+ tbl_hrule(tp, sp, sp, sp->next, TBL_OPT_ALLBOX);
tp->tcol->offset = save_offset;
tp->flags &= ~TERMP_NONOSPACE;
@@ -579,9 +580,10 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
static void
tbl_hrule(struct termp *tp, const struct tbl_span *spp,
- const struct tbl_span *spn, int flags)
+ const struct tbl_span *sp, const struct tbl_span *spn, int flags)
{
const struct tbl_cell *cpp; /* Layout cell above this line. */
+ const struct tbl_cell *cp; /* Layout cell in this line. */
const struct tbl_cell *cpn; /* Layout cell below this line. */
const struct tbl_dat *dpn; /* Data cell below this line. */
const struct roffcol *col; /* Contains width and spacing. */
@@ -592,6 +594,7 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
int uw, dw; /* Vertical line widths. */
cpp = spp == NULL ? NULL : spp->layout->first;
+ cp = sp == NULL ? NULL : sp->layout->first;
cpn = spn == NULL ? NULL : spn->layout->first;
dpn = NULL;
if (spn != NULL) {
@@ -600,11 +603,11 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
else if (spn->next != NULL)
dpn = spn->next->first;
}
- opts = spn == NULL ? spp->opts->opts : spn->opts->opts;
+ opts = sp->opts->opts;
bw = opts & TBL_OPT_DBOX ? (tp->enc == TERMENC_UTF8 ? 2 : 1) :
opts & (TBL_OPT_BOX | TBL_OPT_ALLBOX) ? 1 : 0;
hw = flags == TBL_OPT_DBOX || flags == TBL_OPT_BOX ? bw :
- spn->pos == TBL_SPAN_DHORIZ ? 2 : 1;
+ sp->pos == TBL_SPAN_DHORIZ ? 2 : 1;
/* Print the left end of the line. */
@@ -619,14 +622,19 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
(spp == NULL || cpn == NULL ||
cpn->pos != TBL_CELL_DOWN ? BRIGHT * hw : 0), 1);
+ col = tp->tbl.cols;
for (;;) {
- col = tp->tbl.cols + (cpn == NULL ? cpp->col : cpn->col);
+ if (cp == NULL)
+ col++;
+ else
+ col = tp->tbl.cols + cp->col;
/* Print the horizontal line inside this column. */
lw = cpp == NULL || cpn == NULL ||
(cpn->pos != TBL_CELL_DOWN &&
- (dpn == NULL || strcmp(dpn->string, "\\^") != 0))
+ (dpn == NULL || dpn->string == NULL ||
+ strcmp(dpn->string, "\\^") != 0))
? hw : 0;
tbl_direct_border(tp, BHORIZ * lw,
col->width + col->spacing / 2);
@@ -645,7 +653,10 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
uw = 1;
}
cpp = cpp->next;
- }
+ } else if (spp != NULL && opts & TBL_OPT_ALLBOX)
+ uw = 1;
+ if (cp != NULL)
+ cp = cp->next;
if (cpn != NULL) {
if (flags != TBL_OPT_DBOX) {
dw = cpn->vert;
@@ -655,8 +666,9 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
cpn = cpn->next;
while (dpn != NULL && dpn->layout != cpn)
dpn = dpn->next;
- }
- if (cpp == NULL && cpn == NULL)
+ } else if (spn != NULL && opts & TBL_OPT_ALLBOX)
+ dw = 1;
+ if (col + 1 == tp->tbl.cols + sp->opts->cols)
break;
/* Vertical lines do not cross spanned cells. */
@@ -670,7 +682,8 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
rw = cpp == NULL || cpn == NULL ||
(cpn->pos != TBL_CELL_DOWN &&
- (dpn == NULL || strcmp(dpn->string, "\\^") != 0))
+ (dpn == NULL || dpn->string == NULL ||
+ strcmp(dpn->string, "\\^") != 0))
? hw : 0;
/* The line crossing at the end of this column. */
diff --git a/term.c b/term.c
index 8e9762282582..3b9277aaabbc 100644
--- a/term.c
+++ b/term.c
@@ -1,4 +1,4 @@
-/* $Id: term.c,v 1.280 2019/01/15 12:16:18 schwarze Exp $ */
+/* $Id: term.c,v 1.281 2019/06/03 20:23:41 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
@@ -281,6 +281,8 @@ term_fill(struct termp *p, size_t *nbr, size_t *vbr, size_t vtarget)
case ASCII_BREAK:
vn = vis;
break;
+ default:
+ abort();
}
/* Can break at the end of a word. */
if (breakline || vn > vtarget)