7697 lines
219 KiB
Diff
7697 lines
219 KiB
Diff
|
--- a/Makefile.depend
|
|||
|
+++ b/Makefile.depend
|
|||
|
@@ -29,7 +29,7 @@ dbm.o: dbm.c config.h mansearch.h dbm_ma
|
|||
|
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 man
|
|||
|
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
|
|||
|
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
|
|||
|
--- a/NEWS
|
|||
|
+++ b/NEWS
|
|||
|
@@ -2,6 +2,88 @@ $Id: NEWS,v 1.34 2019/03/10 09:32:00 sch
|
|||
|
|
|||
|
This file lists the most important changes in the mandoc.bsd.lv distribution.
|
|||
|
|
|||
|
+Changes in version 1.14.6, released on XXX XXX, 2019
|
|||
|
+
|
|||
|
+ --- MAJOR NEW FEATURES ---
|
|||
|
+ * man(1) -T ascii: slowly start implementing tagging support for man(7)
|
|||
|
+ pages: tag alphabetic arguments of .IP, .TP, and .TQ macros
|
|||
|
+ * -T html: wrap text and phrasing elements in paragraphs unless
|
|||
|
+ already contained in flow containers; never put them directly
|
|||
|
+ into sections. This helps to format paragraphs with the CSS
|
|||
|
+ class selector .Pp.
|
|||
|
+ --- MINOR NEW FEATURES ---
|
|||
|
+ * roff(7): implement the .break request (break out of a .while loop)
|
|||
|
+ * if messages are shown and output is printed without a pager,
|
|||
|
+ display a heads-up on stderr at the end because otherwise, users
|
|||
|
+ may easily miss the messages
|
|||
|
+ * mandoc.css: support prefers-color-scheme: dark
|
|||
|
+ --- RELIABILITY BUGFIXES ---
|
|||
|
+ * man(1): do not segfault if /tmp/ is not writeable
|
|||
|
+ * tbl(7): fix a crash when the last column is only reached by spans
|
|||
|
+ * tbl(7) -T ascii: fix a NULL pointer access on empty data cells
|
|||
|
+ * tbl(7) -T ascii: fix a NULL pointer access on a line next to a short row
|
|||
|
+ * -T html: fix an assertion failure caused by .ft in rare situations
|
|||
|
+ * roff(7): fix a rare case of writing one byte past the end of the input buffer
|
|||
|
+ --- MINOR FUNCTIONAL IMPROVEMENTS ---
|
|||
|
+ * man(1) -h: for pages lacking a SYNOPSIS, show the NAME section
|
|||
|
+ * man(1): when the first argument starts with a digit, optionally
|
|||
|
+ followed by a letter, and at least one more argument follows,
|
|||
|
+ interpret the first argument as a section name even when additional
|
|||
|
+ characters follow after the digit and letter
|
|||
|
+ * man(1): with a specific section requested, try harder to find
|
|||
|
+ the best match; use this order of preference:
|
|||
|
+ 1. The section in both the directory name and the file name matches exactly.
|
|||
|
+ 2. The section in the file name matches exactly.
|
|||
|
+ 3. The section in the directory name matches exactly.
|
|||
|
+ 4. Neither of them matches exactly.
|
|||
|
+ * man(1): if no tags were generated at all, unlink(2) the empty
|
|||
|
+ tags file as soon the condition can be detected and do not pass
|
|||
|
+ it to less(1)
|
|||
|
+ * makewhatis(8): handle both dangling symlinks and .so links
|
|||
|
+ in manual page directories more gracefully
|
|||
|
+ * man.cgi(8): for invalid queries and for valid queries returning
|
|||
|
+ no result, return the appropriate 40x status code rather than 200
|
|||
|
+ * tbl(7) -T utf8: improved rendering of horizontal lines
|
|||
|
+ * mdoc(7) -T html: format .Nd with <span> rather than <div>
|
|||
|
+ * mdoc(7) -T lint: do not warn about $Mdocdate$ without an actual date
|
|||
|
+ * mdoc(7) -T lint: do not complain about function types of the
|
|||
|
+ form "ret_type (fname)(args)", but otherwise check names more strictly
|
|||
|
+ --- MINOR BUGFIXES ---
|
|||
|
+ * man(1): do the search for each name independently, and show the
|
|||
|
+ results in the order of the command line argument
|
|||
|
+ * man(1): when asking for a single manual page by name, prefer
|
|||
|
+ file name matches over .Dt/.TH matches over first NAME matches
|
|||
|
+ over later NAME matches, but do not change the ordering for
|
|||
|
+ apropos(1) nor for man -a
|
|||
|
+ * roff(7): when calling an empty macro, do not clobber existing arguments
|
|||
|
+ * mdoc(7) .Bl -column: parse Macro in .It "word<tab>word" Ta word Macro<eol>
|
|||
|
+ * -T html: remove some spurious line breaks, in particular inside <pre>
|
|||
|
+ --- STRUCTURAL IMPROVEMENTS ---
|
|||
|
+ * move some code out of the giant main() into separate functions
|
|||
|
+ doing one well-defined task each
|
|||
|
+ * clearly separate parser state (struct curparse) and formatter state
|
|||
|
+ (struct outstate), don't mix them in the same struct
|
|||
|
+ * in the HTML formatter, assert(3) that no HTML nesting violation occurs
|
|||
|
+ * let html_close_paragraph() close any phrasing context
|
|||
|
+ --- THANKS TO ---
|
|||
|
+ * Marc Espie (OpenBSD) for a patch and for suggesting a feature impovement
|
|||
|
+ * Anton Lindqvist (OpenBSD) for a patch
|
|||
|
+ * Armin Besirovic for a contribution to mandoc.css
|
|||
|
+ * Lorenzo Beretta for three bug reports
|
|||
|
+ and for suggesting two feature impovements
|
|||
|
+ * Anthony Bentley (OpenBSD) for three bug reports
|
|||
|
+ and for suggesting a feature impovement
|
|||
|
+ * Michael Stapelberg (Debian) and Jan Stary for a bug report
|
|||
|
+ and for suggesting a feature impovement
|
|||
|
+ * Stephen Gregoratto for two bug reports
|
|||
|
+ * Brian Callahan, Klemens Nanni (OpenBSD), Jason Thorpe (NetBSD),
|
|||
|
+ Yuri Pankov (FreeBSD), and Edgar Pettijohn for bug reports
|
|||
|
+ * Theo Buehler (OpenBSD), Leah Neukirchen (Void Linux), Colin Watson (Debian),
|
|||
|
+ and John Gardner for suggesting feature impovements
|
|||
|
+ * TJ Townsend (OpenBSD) for help with CSS
|
|||
|
+ * Christos Zoulas (NetBSD) for a report regarding portability
|
|||
|
+ * Michal Nowak for reporting four code style issues
|
|||
|
+
|
|||
|
Changes in version 1.14.5, released on March 10, 2019
|
|||
|
|
|||
|
--- MAJOR NEW FEATURES ---
|
|||
|
--- a/TODO
|
|||
|
+++ b/TODO
|
|||
|
@@ -62,8 +62,33 @@ 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 ----------------------------------------------
|
|||
|
|
|||
|
+- .Sh and .Ss should be parsed and partially callable, see groff_mdoc(7)
|
|||
|
+ reed at reedmedia dot net Sat, 21 Dec 2019 17:13:07 -0600
|
|||
|
+ loc ** exist ** algo ** size ** imp *
|
|||
|
+
|
|||
|
- .Bl -column .Xo support is missing
|
|||
|
ultimate goal:
|
|||
|
restore .Xr and .Dv to
|
|||
|
@@ -264,6 +289,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
|
|||
|
|
|||
|
@@ -350,6 +378,11 @@ are mere guesses, and some may be wrong.
|
|||
|
|
|||
|
--- HTML issues --------------------------------------------------------
|
|||
|
|
|||
|
+- get rid of the last handful of style= attributes such that
|
|||
|
+ Content-Security-Policy: can be enabled without unsafe-inline
|
|||
|
+ suggested by bentley@ Nov 10, 2019 at 06:02:49AM -0700
|
|||
|
+ loc * exist * algo * size * imp **
|
|||
|
+
|
|||
|
- .Bf at the beginning of a paragraph inserts a bogus 1ex horizontal
|
|||
|
space, see for example random(3). Introduced in
|
|||
|
http://mdocml.bsd.lv/cgi-bin/cvsweb/mdoc_html.c.diff?r1=1.91&r2=1.92
|
|||
|
@@ -362,6 +395,11 @@ are mere guesses, and some may be wrong.
|
|||
|
https://github.com/Debian/debiman/issues/15
|
|||
|
loc * exist * algo ** size ** imp **
|
|||
|
|
|||
|
+- space characters can end up in href= attributes, for example coming
|
|||
|
+ from the first .Xr argument (where they make no sense, but still);
|
|||
|
+ does this affect other characters, other source macros...?
|
|||
|
+ Jackson Pauls 29 Aug 2017 16:56:27 +0100
|
|||
|
+
|
|||
|
- The tables used to render the three-part page headers actually force
|
|||
|
the width of the <body> to the max-width given for <html>.
|
|||
|
Not yet sure how to fix that...
|
|||
|
@@ -538,6 +576,15 @@ are mere guesses, and some may be wrong.
|
|||
|
* to improve in the groff_mdoc(7) macros
|
|||
|
************************************************************************
|
|||
|
|
|||
|
+- delete OS release verification from .Dx, .Fx, .Nx, .Ox etc.
|
|||
|
+ https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=629161
|
|||
|
+ also Branden Robinson 18 Dec 2019 00:59:52 +1100
|
|||
|
+
|
|||
|
+- Can the distinction between .Vt and .Va be made stricter,
|
|||
|
+ recommending .Vt extern char * Ns Va optarg ; ?
|
|||
|
+ What about the block macro properties of .Vt in the SYNOPSIS?
|
|||
|
+ zeurkous 25 Dec 2019 08:48:36 +0100
|
|||
|
+
|
|||
|
- .Cd # arch1, arch2 in section 4 pages:
|
|||
|
find better way to indicate multiple architectures, maybe:
|
|||
|
allow .Dt vgafb 4 "macppc sparc64"
|
|||
|
--- a/arch.c
|
|||
|
+++ b/arch.c
|
|||
|
@@ -26,7 +26,7 @@ arch_valid(const char *arch, enum mandoc
|
|||
|
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",
|
|||
|
--- a/cgi.c
|
|||
|
+++ b/cgi.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: cgi.c,v 1.166 2019/03/06 12:32:41 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2014, 2015, 2016, 2017, 2018 Ingo Schwarze <schwarze@usta.de>
|
|||
|
+ * Copyright (c) 2014-2019 Ingo Schwarze <schwarze@usta.de>
|
|||
|
*
|
|||
|
* Permission to use, copy, modify, and distribute this software for any
|
|||
|
* purpose with or without fee is hereby granted, provided that the above
|
|||
|
@@ -77,7 +77,8 @@ static void parse_query_string(struct
|
|||
|
static void pg_error_badrequest(const char *);
|
|||
|
static void pg_error_internal(void);
|
|||
|
static void pg_index(const struct req *);
|
|||
|
-static void pg_noresult(const struct req *, const char *);
|
|||
|
+static void pg_noresult(const struct req *, int, const char *,
|
|||
|
+ const char *);
|
|||
|
static void pg_redirect(const struct req *, const char *);
|
|||
|
static void pg_search(const struct req *);
|
|||
|
static void pg_searchres(const struct req *,
|
|||
|
@@ -339,6 +340,8 @@ resp_begin_http(int code, const char *ms
|
|||
|
|
|||
|
printf("Content-Type: text/html; charset=utf-8\r\n"
|
|||
|
"Cache-Control: no-cache\r\n"
|
|||
|
+ "Content-Security-Policy: default-src 'none'; "
|
|||
|
+ "style-src 'self' 'unsafe-inline'\r\n"
|
|||
|
"Pragma: no-cache\r\n"
|
|||
|
"\r\n");
|
|||
|
|
|||
|
@@ -408,7 +411,8 @@ resp_searchform(const struct req *req, e
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
- printf("<form action=\"/%s\" method=\"get\">\n"
|
|||
|
+ printf("<form action=\"/%s\" method=\"get\" "
|
|||
|
+ "autocomplete=\"off\" autocapitalize=\"none\">\n"
|
|||
|
" <fieldset>\n"
|
|||
|
" <legend>Manual Page Search Parameters</legend>\n",
|
|||
|
scriptname);
|
|||
|
@@ -546,12 +550,13 @@ pg_index(const struct req *req)
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
-pg_noresult(const struct req *req, const char *msg)
|
|||
|
+pg_noresult(const struct req *req, int code, const char *http_msg,
|
|||
|
+ const char *user_msg)
|
|||
|
{
|
|||
|
- resp_begin_html(200, NULL, NULL);
|
|||
|
+ resp_begin_html(code, http_msg, NULL);
|
|||
|
resp_searchform(req, FOCUS_QUERY);
|
|||
|
puts("<p>");
|
|||
|
- puts(msg);
|
|||
|
+ puts(user_msg);
|
|||
|
puts("</p>");
|
|||
|
resp_end_html();
|
|||
|
}
|
|||
|
@@ -869,7 +874,6 @@ resp_format(const struct req *req, const
|
|||
|
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' ? "" : "/",
|
|||
|
@@ -1017,9 +1021,10 @@ pg_search(const struct req *req)
|
|||
|
if (req->isquery && req->q.equal && argc == 1)
|
|||
|
pg_redirect(req, argv[0]);
|
|||
|
else if (mansearch(&search, &paths, argc, argv, &res, &ressz) == 0)
|
|||
|
- pg_noresult(req, "You entered an invalid query.");
|
|||
|
+ pg_noresult(req, 400, "Bad Request",
|
|||
|
+ "You entered an invalid query.");
|
|||
|
else if (ressz == 0)
|
|||
|
- pg_noresult(req, "No results found.");
|
|||
|
+ pg_noresult(req, 404, "Not Found", "No results found.");
|
|||
|
else
|
|||
|
pg_searchres(req, res, ressz);
|
|||
|
|
|||
|
--- a/configure
|
|||
|
+++ b/configure
|
|||
|
@@ -41,7 +41,7 @@ OSENUM=
|
|||
|
OSNAME=
|
|||
|
UTF8_LOCALE=
|
|||
|
|
|||
|
-CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | env -i make -sf -`
|
|||
|
+CC=cc
|
|||
|
CFLAGS=
|
|||
|
LDADD=
|
|||
|
LDFLAGS=
|
|||
|
@@ -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
|
|||
|
|
|||
|
--- a/configure.local.example
|
|||
|
+++ b/configure.local.example
|
|||
|
@@ -28,6 +28,14 @@
|
|||
|
|
|||
|
# --- user settings relevant for all builds ----------------------------
|
|||
|
|
|||
|
+# By default, "cc" is used as the C compiler, but it can be overridden.
|
|||
|
+# For example, the system compiler in SunOS 5.9 may not provide <stdint.h>,
|
|||
|
+# which may require this line:
|
|||
|
+CC=gcc
|
|||
|
+
|
|||
|
+# IBM AIX may need:
|
|||
|
+CC=xlc
|
|||
|
+
|
|||
|
# For -Tutf8 and -Tlocale operation, mandoc(1) requires <locale.h>
|
|||
|
# providing setlocale(3) and <wchar.h> providing wcwidth(3) and
|
|||
|
# putwchar(3) with a wchar_t storing UCS-4 values. Theoretically,
|
|||
|
@@ -268,21 +276,6 @@ BINM_CATMAN=mcatman # default is "catma
|
|||
|
|
|||
|
# Do not set these variables unless you really need to.
|
|||
|
|
|||
|
-# You can manually override the compiler to be used.
|
|||
|
-# But that's rarely useful because ./configure asks your make(1)
|
|||
|
-# which compiler to use, and that answer will hardly be wrong.
|
|||
|
-
|
|||
|
-CC=cc
|
|||
|
-
|
|||
|
-# Because the system compiler may not provide <stdint.h>,
|
|||
|
-# SunOS 5.9 may need:
|
|||
|
-
|
|||
|
-CC=gcc
|
|||
|
-
|
|||
|
-# IBM AIX may need:
|
|||
|
-
|
|||
|
-CC=xlc
|
|||
|
-
|
|||
|
# Normally, leave CFLAGS unset. In that case, -g will automatically
|
|||
|
# be used, and various -W options will be added if the compiler
|
|||
|
# supports them. If you define CFLAGS manually, it will be used
|
|||
|
--- a/dbm.c
|
|||
|
+++ b/dbm.c
|
|||
|
@@ -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_
|
|||
|
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. */
|
|||
|
|
|||
|
--- a/dbm_map.h
|
|||
|
+++ b/dbm_map.h
|
|||
|
@@ -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.
|
|||
|
*/
|
|||
|
--- a/eqn.7
|
|||
|
+++ b/eqn.7
|
|||
|
@@ -44,28 +44,16 @@ specification (see
|
|||
|
.Sx SEE ALSO
|
|||
|
for references).
|
|||
|
.Pp
|
|||
|
-Equations within
|
|||
|
-.Xr mdoc 7
|
|||
|
-or
|
|||
|
-.Xr man 7
|
|||
|
-documents are enclosed by the standalone
|
|||
|
-.Sq \&.EQ
|
|||
|
-and
|
|||
|
-.Sq \&.EN
|
|||
|
-tags.
|
|||
|
-Equations are multi-line blocks consisting of formulas and control
|
|||
|
-statements.
|
|||
|
-.Sh EQUATION STRUCTURE
|
|||
|
-Each equation is bracketed by
|
|||
|
-.Sq \&.EQ
|
|||
|
-and
|
|||
|
-.Sq \&.EN
|
|||
|
-strings.
|
|||
|
-.Em Note :
|
|||
|
-these are not the same as
|
|||
|
-.Xr roff 7
|
|||
|
-macros, and may only be invoked as
|
|||
|
-.Sq \&.EQ .
|
|||
|
+An equation starts with an input line containing exactly the characters
|
|||
|
+.Sq \&.EQ ,
|
|||
|
+may contain multiple input lines, and ends with an input line
|
|||
|
+containing exactly the characters
|
|||
|
+.Sq \&.EN .
|
|||
|
+Equivalently, an equation can be given in the middle of a single
|
|||
|
+text input line by surrounding it with the equation delimiters
|
|||
|
+defined with the
|
|||
|
+.Cm delim
|
|||
|
+statement.
|
|||
|
.Pp
|
|||
|
The equation grammar is as follows, where quoted strings are
|
|||
|
case-sensitive literals in the input:
|
|||
|
@@ -178,6 +166,25 @@ statement is a synonym for
|
|||
|
while
|
|||
|
.Cm tdefine
|
|||
|
is discarded.
|
|||
|
+.It Cm delim
|
|||
|
+This statement takes a string argument consisting of two bytes,
|
|||
|
+to be used as the opening and closing delimiters for equations
|
|||
|
+in the middle of text input lines.
|
|||
|
+Conventionally, the dollar sign is used for both delimiters,
|
|||
|
+as follows:
|
|||
|
+.Bd -literal -offset indent
|
|||
|
+\&.EQ
|
|||
|
+delim $$
|
|||
|
+\&.EN
|
|||
|
+An equation like $sin pi = 0$ can now be entered
|
|||
|
+in the middle of a text input line.
|
|||
|
+.Ed
|
|||
|
+.Pp
|
|||
|
+The special statement
|
|||
|
+.Cm delim off
|
|||
|
+temporarily disables previously declared delimiters and
|
|||
|
+.Cm delim on
|
|||
|
+reenables them.
|
|||
|
.It Cm gfont
|
|||
|
Set the default font of subsequent output.
|
|||
|
Its syntax is as follows:
|
|||
|
@@ -470,7 +477,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
|
|||
|
--- a/eqn.c
|
|||
|
+++ b/eqn.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: eqn.c,v 1.83 2018/12/14 06:33:14 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2014, 2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2014,2015,2017,2018,2020 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
|
|||
|
@@ -399,6 +399,14 @@ eqn_next(struct eqn_node *ep, enum parse
|
|||
|
case '"':
|
|||
|
quoted = 1;
|
|||
|
break;
|
|||
|
+ case ' ':
|
|||
|
+ case '\t':
|
|||
|
+ case '~':
|
|||
|
+ case '^':
|
|||
|
+ if (quoted)
|
|||
|
+ break;
|
|||
|
+ ep->start++;
|
|||
|
+ continue;
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
@@ -669,7 +677,7 @@ eqn_parse(struct eqn_node *ep)
|
|||
|
if (ep->data == NULL)
|
|||
|
return;
|
|||
|
|
|||
|
- ep->start = ep->end = ep->data + strspn(ep->data, " ^~");
|
|||
|
+ ep->start = ep->end = ep->data;
|
|||
|
|
|||
|
next_tok:
|
|||
|
tok = eqn_next(ep, MODE_TOK);
|
|||
|
--- a/eqn_html.c
|
|||
|
+++ b/eqn_html.c
|
|||
|
@@ -26,6 +26,7 @@
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
#include "mandoc.h"
|
|||
|
+#include "roff.h"
|
|||
|
#include "eqn.h"
|
|||
|
#include "out.h"
|
|||
|
#include "html.h"
|
|||
|
--- a/html.c
|
|||
|
+++ b/html.c
|
|||
|
@@ -42,34 +42,30 @@
|
|||
|
struct htmldata {
|
|||
|
const char *name;
|
|||
|
int flags;
|
|||
|
-#define HTML_NOSTACK (1 << 0)
|
|||
|
-#define HTML_AUTOCLOSE (1 << 1)
|
|||
|
-#define HTML_NLBEFORE (1 << 2)
|
|||
|
-#define HTML_NLBEGIN (1 << 3)
|
|||
|
-#define HTML_NLEND (1 << 4)
|
|||
|
-#define HTML_NLAFTER (1 << 5)
|
|||
|
+#define HTML_INPHRASE (1 << 0) /* Can appear in phrasing context. */
|
|||
|
+#define HTML_TOPHRASE (1 << 1) /* Establishes phrasing context. */
|
|||
|
+#define HTML_NOSTACK (1 << 2) /* Does not have an end tag. */
|
|||
|
+#define HTML_NLBEFORE (1 << 3) /* Output line break before opening. */
|
|||
|
+#define HTML_NLBEGIN (1 << 4) /* Output line break after opening. */
|
|||
|
+#define HTML_NLEND (1 << 5) /* Output line break before closing. */
|
|||
|
+#define HTML_NLAFTER (1 << 6) /* Output line break after closing. */
|
|||
|
#define HTML_NLAROUND (HTML_NLBEFORE | HTML_NLAFTER)
|
|||
|
#define HTML_NLINSIDE (HTML_NLBEGIN | HTML_NLEND)
|
|||
|
#define HTML_NLALL (HTML_NLAROUND | HTML_NLINSIDE)
|
|||
|
-#define HTML_INDENT (1 << 6)
|
|||
|
-#define HTML_NOINDENT (1 << 7)
|
|||
|
+#define HTML_INDENT (1 << 7) /* Indent content by two spaces. */
|
|||
|
+#define HTML_NOINDENT (1 << 8) /* Exception: never indent content. */
|
|||
|
};
|
|||
|
|
|||
|
static const struct htmldata htmltags[TAG_MAX] = {
|
|||
|
{"html", HTML_NLALL},
|
|||
|
{"head", HTML_NLALL | HTML_INDENT},
|
|||
|
- {"body", HTML_NLALL},
|
|||
|
- {"meta", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL},
|
|||
|
+ {"meta", HTML_NOSTACK | HTML_NLALL},
|
|||
|
+ {"link", HTML_NOSTACK | HTML_NLALL},
|
|||
|
+ {"style", HTML_NLALL | HTML_INDENT},
|
|||
|
{"title", HTML_NLAROUND},
|
|||
|
+ {"body", HTML_NLALL},
|
|||
|
{"div", HTML_NLAROUND},
|
|||
|
- {"div", 0},
|
|||
|
{"section", HTML_NLALL},
|
|||
|
- {"h1", HTML_NLAROUND},
|
|||
|
- {"h2", HTML_NLAROUND},
|
|||
|
- {"span", 0},
|
|||
|
- {"link", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL},
|
|||
|
- {"br", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL},
|
|||
|
- {"a", 0},
|
|||
|
{"table", HTML_NLALL | HTML_INDENT},
|
|||
|
{"tr", HTML_NLALL | HTML_INDENT},
|
|||
|
{"td", HTML_NLAROUND},
|
|||
|
@@ -79,16 +75,21 @@ static const struct htmldata htmltags[TA
|
|||
|
{"dl", HTML_NLALL | HTML_INDENT},
|
|||
|
{"dt", HTML_NLAROUND},
|
|||
|
{"dd", HTML_NLAROUND | HTML_INDENT},
|
|||
|
- {"p", HTML_NLAROUND | HTML_INDENT},
|
|||
|
- {"pre", HTML_NLALL | HTML_NOINDENT},
|
|||
|
- {"var", 0},
|
|||
|
- {"cite", 0},
|
|||
|
- {"b", 0},
|
|||
|
- {"i", 0},
|
|||
|
- {"code", 0},
|
|||
|
- {"small", 0},
|
|||
|
- {"style", HTML_NLALL | HTML_INDENT},
|
|||
|
- {"math", HTML_NLALL | HTML_INDENT},
|
|||
|
+ {"h1", HTML_TOPHRASE | HTML_NLAROUND},
|
|||
|
+ {"h2", HTML_TOPHRASE | HTML_NLAROUND},
|
|||
|
+ {"p", HTML_TOPHRASE | HTML_NLAROUND | HTML_INDENT},
|
|||
|
+ {"pre", HTML_TOPHRASE | HTML_NLALL | HTML_NOINDENT},
|
|||
|
+ {"a", HTML_INPHRASE | HTML_TOPHRASE},
|
|||
|
+ {"b", HTML_INPHRASE | HTML_TOPHRASE},
|
|||
|
+ {"cite", HTML_INPHRASE | HTML_TOPHRASE},
|
|||
|
+ {"code", HTML_INPHRASE | HTML_TOPHRASE},
|
|||
|
+ {"i", HTML_INPHRASE | HTML_TOPHRASE},
|
|||
|
+ {"small", HTML_INPHRASE | HTML_TOPHRASE},
|
|||
|
+ {"span", HTML_INPHRASE | HTML_TOPHRASE},
|
|||
|
+ {"var", HTML_INPHRASE | HTML_TOPHRASE},
|
|||
|
+ {"br", HTML_INPHRASE | HTML_NOSTACK | HTML_NLALL},
|
|||
|
+ {"mark", HTML_INPHRASE | HTML_NOSTACK },
|
|||
|
+ {"math", HTML_INPHRASE | HTML_NLALL | HTML_INDENT},
|
|||
|
{"mrow", 0},
|
|||
|
{"mi", 0},
|
|||
|
{"mn", 0},
|
|||
|
@@ -120,6 +121,7 @@ static void print_ctag(struct html *, s
|
|||
|
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 *
|
|||
|
@@ -202,75 +204,64 @@ print_gen_head(struct html *h)
|
|||
|
print_endline(h);
|
|||
|
print_text(h, "td.head-vol { text-align: center; }");
|
|||
|
print_endline(h);
|
|||
|
- print_text(h, "div.Pp { margin: 1ex 0ex; }");
|
|||
|
- print_endline(h);
|
|||
|
- print_text(h, "div.Nd, div.Bf, div.Op { display: inline; }");
|
|||
|
+ print_text(h, ".Nd, .Bf, .Op { display: inline; }");
|
|||
|
print_endline(h);
|
|||
|
- print_text(h, "span.Pa, span.Ad { font-style: italic; }");
|
|||
|
+ print_text(h, ".Pa, .Ad { font-style: italic; }");
|
|||
|
print_endline(h);
|
|||
|
- print_text(h, "span.Ms { font-weight: bold; }");
|
|||
|
+ print_text(h, ".Ms { font-weight: bold; }");
|
|||
|
print_endline(h);
|
|||
|
- print_text(h, "dl.Bl-diag ");
|
|||
|
+ print_text(h, ".Bl-diag ");
|
|||
|
print_byte(h, '>');
|
|||
|
print_text(h, " dt { font-weight: bold; }");
|
|||
|
print_endline(h);
|
|||
|
- print_text(h, "code.Nm, code.Fl, code.Cm, code.Ic, "
|
|||
|
- "code.In, code.Fd, code.Fn,");
|
|||
|
- print_endline(h);
|
|||
|
- print_text(h, "code.Cd { font-weight: bold; "
|
|||
|
- "font-family: inherit; }");
|
|||
|
+ print_text(h, "code.Nm, .Fl, .Cm, .Ic, code.In, .Fd, .Fn, .Cd "
|
|||
|
+ "{ font-weight: bold; font-family: inherit; }");
|
|||
|
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:
|
|||
|
@@ -281,21 +272,18 @@ print_metaf(struct html *h, enum mandoc_
|
|||
|
void
|
|||
|
html_close_paragraph(struct html *h)
|
|||
|
{
|
|||
|
- struct tag *t;
|
|||
|
+ struct tag *this, *next;
|
|||
|
+ int flags;
|
|||
|
|
|||
|
- for (t = h->tag; t != NULL && t->closed == 0; t = t->next) {
|
|||
|
- switch(t->tag) {
|
|||
|
- case TAG_P:
|
|||
|
- case TAG_PRE:
|
|||
|
- print_tagq(h, t);
|
|||
|
+ this = h->tag;
|
|||
|
+ for (;;) {
|
|||
|
+ next = this->next;
|
|||
|
+ flags = htmltags[this->tag].flags;
|
|||
|
+ if (flags & (HTML_INPHRASE | HTML_TOPHRASE))
|
|||
|
+ print_ctag(h, this);
|
|||
|
+ if ((flags & HTML_INPHRASE) == 0)
|
|||
|
break;
|
|||
|
- case TAG_A:
|
|||
|
- print_tagq(h, t);
|
|||
|
- continue;
|
|||
|
- default:
|
|||
|
- continue;
|
|||
|
- }
|
|||
|
- break;
|
|||
|
+ this = next;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@@ -479,7 +467,8 @@ print_encode(struct html *h, const char
|
|||
|
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;
|
|||
|
@@ -593,6 +582,25 @@ print_otag(struct html *h, enum htmltag
|
|||
|
|
|||
|
tflags = htmltags[tag].flags;
|
|||
|
|
|||
|
+ /* Flow content is not allowed in phrasing context. */
|
|||
|
+
|
|||
|
+ if ((tflags & HTML_INPHRASE) == 0) {
|
|||
|
+ for (t = h->tag; t != NULL; t = t->next) {
|
|||
|
+ if (t->closed)
|
|||
|
+ continue;
|
|||
|
+ assert((htmltags[t->tag].flags & HTML_TOPHRASE) == 0);
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /*
|
|||
|
+ * Always wrap phrasing elements in a paragraph
|
|||
|
+ * unless already contained in some flow container;
|
|||
|
+ * never put them directly into a section.
|
|||
|
+ */
|
|||
|
+
|
|||
|
+ } else if (tflags & HTML_TOPHRASE && h->tag->tag == TAG_SECTION)
|
|||
|
+ print_otag(h, TAG_P, "c", "Pp");
|
|||
|
+
|
|||
|
/* Push this tag onto the stack of open scopes. */
|
|||
|
|
|||
|
if ((tflags & HTML_NOSTACK) == 0) {
|
|||
|
@@ -710,7 +718,7 @@ print_otag(struct html *h, enum htmltag
|
|||
|
|
|||
|
/* Accommodate for "well-formed" singleton escaping. */
|
|||
|
|
|||
|
- if (HTML_AUTOCLOSE & htmltags[tag].flags)
|
|||
|
+ if (htmltags[tag].flags & HTML_NOSTACK)
|
|||
|
print_byte(h, '/');
|
|||
|
|
|||
|
print_byte(h, '>');
|
|||
|
@@ -797,6 +805,16 @@ print_gen_comment(struct html *h, struct
|
|||
|
void
|
|||
|
print_text(struct html *h, const char *word)
|
|||
|
{
|
|||
|
+ /*
|
|||
|
+ * Always wrap text in a paragraph unless already contained in
|
|||
|
+ * some flow container; never put it directly into a section.
|
|||
|
+ */
|
|||
|
+
|
|||
|
+ if (h->tag->tag == TAG_SECTION)
|
|||
|
+ print_otag(h, TAG_P, "c", "Pp");
|
|||
|
+
|
|||
|
+ /* Output whitespace before this text? */
|
|||
|
+
|
|||
|
if (h->col && (h->flags & HTML_NOSPACE) == 0) {
|
|||
|
if ( ! (HTML_KEEP & h->flags)) {
|
|||
|
if (HTML_PREKEEP & h->flags)
|
|||
|
@@ -806,27 +824,14 @@ print_text(struct html *h, const char *w
|
|||
|
print_word(h, " ");
|
|||
|
}
|
|||
|
|
|||
|
- 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;
|
|||
|
- }
|
|||
|
+ /*
|
|||
|
+ * Print the text, optionally surrounded by HTML whitespace,
|
|||
|
+ * optionally manually switching fonts before and after.
|
|||
|
+ */
|
|||
|
|
|||
|
- 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 +839,7 @@ print_text(struct html *h, const char *w
|
|||
|
} else
|
|||
|
h->flags |= HTML_NOSPACE | HTML_NONEWLINE;
|
|||
|
|
|||
|
- if (h->metaf) {
|
|||
|
+ if (h->metaf != NULL) {
|
|||
|
print_tagq(h, h->metaf);
|
|||
|
h->metaf = NULL;
|
|||
|
}
|
|||
|
@@ -964,15 +969,12 @@ print_indent(struct html *h)
|
|||
|
{
|
|||
|
size_t i;
|
|||
|
|
|||
|
- if (h->col)
|
|||
|
+ if (h->col || h->noindent)
|
|||
|
return;
|
|||
|
|
|||
|
- if (h->noindent == 0) {
|
|||
|
- h->col = h->indent * 2;
|
|||
|
- for (i = 0; i < h->col; i++)
|
|||
|
- putchar(' ');
|
|||
|
- }
|
|||
|
- h->flags &= ~HTML_NOSPACE;
|
|||
|
+ h->col = h->indent * 2;
|
|||
|
+ for (i = 0; i < h->col; i++)
|
|||
|
+ putchar(' ');
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
--- a/html.h
|
|||
|
+++ b/html.h
|
|||
|
@@ -19,18 +19,13 @@
|
|||
|
enum htmltag {
|
|||
|
TAG_HTML,
|
|||
|
TAG_HEAD,
|
|||
|
- TAG_BODY,
|
|||
|
TAG_META,
|
|||
|
+ TAG_LINK,
|
|||
|
+ TAG_STYLE,
|
|||
|
TAG_TITLE,
|
|||
|
+ TAG_BODY,
|
|||
|
TAG_DIV,
|
|||
|
- TAG_IDIV,
|
|||
|
TAG_SECTION,
|
|||
|
- TAG_H1,
|
|||
|
- TAG_H2,
|
|||
|
- TAG_SPAN,
|
|||
|
- TAG_LINK,
|
|||
|
- TAG_BR,
|
|||
|
- TAG_A,
|
|||
|
TAG_TABLE,
|
|||
|
TAG_TR,
|
|||
|
TAG_TD,
|
|||
|
@@ -40,15 +35,20 @@ enum htmltag {
|
|||
|
TAG_DL,
|
|||
|
TAG_DT,
|
|||
|
TAG_DD,
|
|||
|
+ TAG_H1,
|
|||
|
+ TAG_H2,
|
|||
|
TAG_P,
|
|||
|
TAG_PRE,
|
|||
|
- TAG_VAR,
|
|||
|
- TAG_CITE,
|
|||
|
+ TAG_A,
|
|||
|
TAG_B,
|
|||
|
- TAG_I,
|
|||
|
+ TAG_CITE,
|
|||
|
TAG_CODE,
|
|||
|
+ TAG_I,
|
|||
|
TAG_SMALL,
|
|||
|
- TAG_STYLE,
|
|||
|
+ TAG_SPAN,
|
|||
|
+ TAG_VAR,
|
|||
|
+ TAG_BR,
|
|||
|
+ TAG_MARK,
|
|||
|
TAG_MATH,
|
|||
|
TAG_MROW,
|
|||
|
TAG_MI,
|
|||
|
@@ -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 *, con
|
|||
|
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);
|
|||
|
--- a/lib.in
|
|||
|
+++ b/lib.in
|
|||
|
@@ -43,7 +43,7 @@ LINE("libcipher", "FreeSec Crypt Library
|
|||
|
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)")
|
|||
|
--- a/libmandoc.h
|
|||
|
+++ b/libmandoc.h
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: libmandoc.h,v 1.77 2018/12/21 17:15:18 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2013,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2013-2015,2017,2018,2020 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
|
|||
|
@@ -47,8 +47,9 @@ struct buf {
|
|||
|
|
|||
|
struct roff;
|
|||
|
struct roff_man;
|
|||
|
+struct roff_node;
|
|||
|
|
|||
|
-char *mandoc_normdate(struct roff_man *, char *, int, int);
|
|||
|
+char *mandoc_normdate(struct roff_node *, struct roff_node *);
|
|||
|
int mandoc_eos(const char *, size_t);
|
|||
|
int mandoc_strntoi(const char *, size_t, int);
|
|||
|
const char *mandoc_a2msec(const char*);
|
|||
|
--- a/main.c
|
|||
|
+++ b/main.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: main.c,v 1.322 2019/03/06 10:18:58 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2010-2012, 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2010-2012, 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
|
|||
|
*
|
|||
|
* Permission to use, copy, modify, and distribute this software for any
|
|||
|
@@ -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>
|
|||
|
@@ -31,6 +32,7 @@
|
|||
|
#include <errno.h>
|
|||
|
#include <fcntl.h>
|
|||
|
#include <glob.h>
|
|||
|
+#include <limits.h>
|
|||
|
#if HAVE_SANDBOX_INIT
|
|||
|
#include <sandbox.h>
|
|||
|
#endif
|
|||
|
@@ -76,13 +78,12 @@ enum outt {
|
|||
|
OUTT_PDF /* -Tpdf */
|
|||
|
};
|
|||
|
|
|||
|
-struct curparse {
|
|||
|
- struct mparse *mp;
|
|||
|
- struct manoutput *outopts; /* output options */
|
|||
|
+struct outstate {
|
|||
|
+ struct tag_files *tag_files; /* Tagging state variables. */
|
|||
|
void *outdata; /* data for output */
|
|||
|
- char *os_s; /* operating system for display */
|
|||
|
+ int use_pager;
|
|||
|
int wstop; /* stop after a file with a warning */
|
|||
|
- enum mandoc_os os_e; /* check base system conventions */
|
|||
|
+ int had_output; /* Some output was generated. */
|
|||
|
enum outt outtype; /* which output to use */
|
|||
|
};
|
|||
|
|
|||
|
@@ -95,17 +96,18 @@ static int fs_lookup(const struct man
|
|||
|
const char *, const char *,
|
|||
|
struct manpage **, size_t *);
|
|||
|
static int fs_search(const struct mansearch *,
|
|||
|
- const struct manpaths *, int, char**,
|
|||
|
+ const struct manpaths *, const 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 outdata_alloc(struct outstate *, struct manoutput *);
|
|||
|
+static void parse(struct mparse *, int, const char *,
|
|||
|
+ struct outstate *, struct manoutput *);
|
|||
|
+static void passthrough(int, int);
|
|||
|
+static void process_onefile(struct mparse *, struct manpage *,
|
|||
|
+ int, struct outstate *, struct manconf *);
|
|||
|
+static void run_pager(struct tag_files *);
|
|||
|
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 *);
|
|||
|
+static int woptions(char *, enum mandoc_os *, int *);
|
|||
|
|
|||
|
static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
|
|||
|
static char help_arg[] = "help";
|
|||
|
@@ -115,26 +117,31 @@ static char *help_argv[] = {help_arg,
|
|||
|
int
|
|||
|
main(int argc, char *argv[])
|
|||
|
{
|
|||
|
- struct manconf conf;
|
|||
|
- struct mansearch search;
|
|||
|
- struct curparse curp;
|
|||
|
- struct winsize ws;
|
|||
|
- struct tag_files *tag_files;
|
|||
|
- struct manpage *res, *resp;
|
|||
|
- const char *progname, *sec, *thisarg;
|
|||
|
- char *conf_file, *defpaths, *auxpaths;
|
|||
|
- char *oarg, *tagarg;
|
|||
|
+ struct manconf conf; /* Manpaths and output options. */
|
|||
|
+ struct outstate outst; /* Output state. */
|
|||
|
+ struct winsize ws; /* Result of ioctl(TIOCGWINSZ). */
|
|||
|
+ struct mansearch search; /* Search options. */
|
|||
|
+ struct manpage *res; /* Complete list of search results. */
|
|||
|
+ struct manpage *resn; /* Search results for one name. */
|
|||
|
+ struct mparse *mp; /* Opaque parser object. */
|
|||
|
+ const char *conf_file; /* -C: alternate config file. */
|
|||
|
+ const char *os_s; /* -I: Operating system for display. */
|
|||
|
+ const char *progname, *sec;
|
|||
|
+ char *defpaths; /* -M: override manpaths. */
|
|||
|
+ char *auxpaths; /* -m: additional manpaths. */
|
|||
|
+ char *oarg; /* -O: output option string. */
|
|||
|
+ char *tagarg; /* -O tag: default value. */
|
|||
|
unsigned char *uc;
|
|||
|
- size_t i, sz;
|
|||
|
+ size_t ressz; /* Number of elements in res[]. */
|
|||
|
+ size_t resnsz; /* Number of elements in resn[]. */
|
|||
|
+ size_t i, ib, ssz;
|
|||
|
+ int options; /* Parser options. */
|
|||
|
+ int show_usage; /* Invalid argument: give up. */
|
|||
|
int prio, best_prio;
|
|||
|
- enum outmode outmode;
|
|||
|
- int fd, startdir;
|
|||
|
- int show_usage;
|
|||
|
- int options;
|
|||
|
- int use_pager;
|
|||
|
- int status, signum;
|
|||
|
+ int startdir;
|
|||
|
int c;
|
|||
|
- pid_t pager_pid, tc_pgid, man_pgid, pid;
|
|||
|
+ enum mandoc_os os_e; /* Check base system conventions. */
|
|||
|
+ enum outmode outmode; /* According to command line. */
|
|||
|
|
|||
|
#if HAVE_PROGNAME
|
|||
|
progname = getprogname();
|
|||
|
@@ -154,10 +161,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");
|
|||
|
@@ -166,8 +174,8 @@ main(int argc, char *argv[])
|
|||
|
/* Search options. */
|
|||
|
|
|||
|
memset(&conf, 0, sizeof(conf));
|
|||
|
- conf_file = defpaths = NULL;
|
|||
|
- auxpaths = NULL;
|
|||
|
+ conf_file = NULL;
|
|||
|
+ defpaths = auxpaths = NULL;
|
|||
|
|
|||
|
memset(&search, 0, sizeof(struct mansearch));
|
|||
|
search.outkey = "Nd";
|
|||
|
@@ -184,15 +192,19 @@ main(int argc, char *argv[])
|
|||
|
else
|
|||
|
search.argmode = ARG_FILE;
|
|||
|
|
|||
|
- /* Parser and formatter options. */
|
|||
|
+ /* Parser options. */
|
|||
|
|
|||
|
- memset(&curp, 0, sizeof(struct curparse));
|
|||
|
- curp.outtype = OUTT_LOCALE;
|
|||
|
- curp.outopts = &conf.output;
|
|||
|
options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1;
|
|||
|
+ os_e = MANDOC_OS_OTHER;
|
|||
|
+ os_s = NULL;
|
|||
|
+
|
|||
|
+ /* Formatter options. */
|
|||
|
+
|
|||
|
+ memset(&outst, 0, sizeof(outst));
|
|||
|
+ outst.tag_files = NULL;
|
|||
|
+ outst.outtype = OUTT_LOCALE;
|
|||
|
+ outst.use_pager = 1;
|
|||
|
|
|||
|
- use_pager = 1;
|
|||
|
- tag_files = NULL;
|
|||
|
show_usage = 0;
|
|||
|
outmode = OUTMODE_DEF;
|
|||
|
|
|||
|
@@ -210,30 +222,40 @@ main(int argc, char *argv[])
|
|||
|
conf_file = optarg;
|
|||
|
break;
|
|||
|
case 'c':
|
|||
|
- use_pager = 0;
|
|||
|
+ outst.use_pager = 0;
|
|||
|
break;
|
|||
|
case 'f':
|
|||
|
search.argmode = ARG_WORD;
|
|||
|
break;
|
|||
|
case 'h':
|
|||
|
conf.output.synopsisonly = 1;
|
|||
|
- use_pager = 0;
|
|||
|
+ outst.use_pager = 0;
|
|||
|
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;
|
|||
|
+ if (os_s != NULL) {
|
|||
|
+ mandoc_msg(MANDOCERR_BADARG_DUPE, 0, 0,
|
|||
|
+ "-I %s", optarg);
|
|||
|
+ return mandoc_msg_getrc();
|
|||
|
}
|
|||
|
- curp.os_s = mandoc_strdup(optarg + 3);
|
|||
|
+ os_s = 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 +280,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)
|
|||
|
+ outst.outtype = OUTT_ASCII;
|
|||
|
+ else if (strcmp(optarg, "lint") == 0) {
|
|||
|
+ outst.outtype = OUTT_LINT;
|
|||
|
+ mandoc_msg_setoutfile(stdout);
|
|||
|
+ mandoc_msg_setmin(MANDOCERR_BASE);
|
|||
|
+ } else if (strcmp(optarg, "tree") == 0)
|
|||
|
+ outst.outtype = OUTT_TREE;
|
|||
|
+ else if (strcmp(optarg, "man") == 0)
|
|||
|
+ outst.outtype = OUTT_MAN;
|
|||
|
+ else if (strcmp(optarg, "html") == 0)
|
|||
|
+ outst.outtype = OUTT_HTML;
|
|||
|
+ else if (strcmp(optarg, "markdown") == 0)
|
|||
|
+ outst.outtype = OUTT_MARKDOWN;
|
|||
|
+ else if (strcmp(optarg, "utf8") == 0)
|
|||
|
+ outst.outtype = OUTT_UTF8;
|
|||
|
+ else if (strcmp(optarg, "locale") == 0)
|
|||
|
+ outst.outtype = OUTT_LOCALE;
|
|||
|
+ else if (strcmp(optarg, "ps") == 0)
|
|||
|
+ outst.outtype = OUTT_PS;
|
|||
|
+ else if (strcmp(optarg, "pdf") == 0)
|
|||
|
+ outst.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(optarg, &os_e, &outst.wstop) == -1)
|
|||
|
+ return mandoc_msg_getrc();
|
|||
|
break;
|
|||
|
case 'w':
|
|||
|
outmode = OUTMODE_FLN;
|
|||
|
@@ -279,11 +326,12 @@ main(int argc, char *argv[])
|
|||
|
|
|||
|
/* Postprocess options. */
|
|||
|
|
|||
|
- if (outmode == OUTMODE_DEF) {
|
|||
|
+ switch (outmode) {
|
|||
|
+ case OUTMODE_DEF:
|
|||
|
switch (search.argmode) {
|
|||
|
case ARG_FILE:
|
|||
|
outmode = OUTMODE_ALL;
|
|||
|
- use_pager = 0;
|
|||
|
+ outst.use_pager = 0;
|
|||
|
break;
|
|||
|
case ARG_NAME:
|
|||
|
outmode = OUTMODE_ONE;
|
|||
|
@@ -292,6 +340,16 @@ main(int argc, char *argv[])
|
|||
|
outmode = OUTMODE_LST;
|
|||
|
break;
|
|||
|
}
|
|||
|
+ break;
|
|||
|
+ case OUTMODE_FLN:
|
|||
|
+ if (search.argmode == ARG_FILE)
|
|||
|
+ outmode = OUTMODE_ALL;
|
|||
|
+ break;
|
|||
|
+ case OUTMODE_ALL:
|
|||
|
+ break;
|
|||
|
+ case OUTMODE_LST:
|
|||
|
+ case OUTMODE_ONE:
|
|||
|
+ abort();
|
|||
|
}
|
|||
|
|
|||
|
if (oarg != NULL) {
|
|||
|
@@ -299,25 +357,22 @@ 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();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
- if (curp.outtype != OUTT_TREE || !curp.outopts->noval)
|
|||
|
+ if (outst.outtype != OUTT_TREE || conf.output.noval == 0)
|
|||
|
options |= MPARSE_VALIDATE;
|
|||
|
|
|||
|
if (outmode == OUTMODE_FLN ||
|
|||
|
outmode == OUTMODE_LST ||
|
|||
|
!isatty(STDOUT_FILENO))
|
|||
|
- use_pager = 0;
|
|||
|
+ outst.use_pager = 0;
|
|||
|
|
|||
|
- if (use_pager &&
|
|||
|
+ if (outst.use_pager &&
|
|||
|
(conf.output.width == 0 || conf.output.indent == 0) &&
|
|||
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 &&
|
|||
|
ws.ws_col > 1) {
|
|||
|
@@ -328,9 +383,13 @@ main(int argc, char *argv[])
|
|||
|
}
|
|||
|
|
|||
|
#if HAVE_PLEDGE
|
|||
|
- if (!use_pager)
|
|||
|
- if (pledge("stdio rpath", NULL) == -1)
|
|||
|
- err((int)MANDOCLEVEL_SYSERR, "pledge");
|
|||
|
+ if (outst.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. */
|
|||
|
@@ -339,11 +398,10 @@ main(int argc, char *argv[])
|
|||
|
argc -= optind;
|
|||
|
argv += optind;
|
|||
|
}
|
|||
|
- resp = NULL;
|
|||
|
|
|||
|
/*
|
|||
|
- * Quirks for help(1)
|
|||
|
- * and for a man(1) section argument without -s.
|
|||
|
+ * Quirks for help(1) and man(1),
|
|||
|
+ * in particular for a section argument without -s.
|
|||
|
*/
|
|||
|
|
|||
|
if (search.argmode == ARG_NAME) {
|
|||
|
@@ -355,7 +413,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++;
|
|||
|
@@ -367,6 +425,8 @@ main(int argc, char *argv[])
|
|||
|
if (search.arch == NULL)
|
|||
|
search.arch = MACHINE;
|
|||
|
#endif
|
|||
|
+ if (outmode == OUTMODE_ONE)
|
|||
|
+ search.firstmatch = 1;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
@@ -380,128 +440,155 @@ main(int argc, char *argv[])
|
|||
|
conf.output.tag = tagarg == NULL ? *argv : tagarg + 1;
|
|||
|
}
|
|||
|
|
|||
|
- /* man(1), whatis(1), apropos(1) */
|
|||
|
-
|
|||
|
- if (search.argmode != ARG_FILE) {
|
|||
|
- if (search.argmode == ARG_NAME &&
|
|||
|
- outmode == OUTMODE_ONE)
|
|||
|
- search.firstmatch = 1;
|
|||
|
-
|
|||
|
- /* Access the mandoc database. */
|
|||
|
+ /* Read the configuration file. */
|
|||
|
|
|||
|
+ if (search.argmode != ARG_FILE)
|
|||
|
manconf_parse(&conf, conf_file, defpaths, auxpaths);
|
|||
|
- if ( ! mansearch(&search, &conf.manpath,
|
|||
|
- argc, argv, &res, &sz))
|
|||
|
- usage(search.argmode);
|
|||
|
|
|||
|
- if (sz == 0 && search.argmode == ARG_NAME)
|
|||
|
- fs_search(&search, &conf.manpath,
|
|||
|
- argc, argv, &res, &sz);
|
|||
|
-
|
|||
|
- if (search.argmode == ARG_NAME) {
|
|||
|
- for (c = 0; c < argc; c++) {
|
|||
|
- if (strchr(argv[c], '/') == NULL)
|
|||
|
- continue;
|
|||
|
- if (access(argv[c], R_OK) == -1) {
|
|||
|
- warn("%s", argv[c]);
|
|||
|
+ /* man(1): Resolve each name individually. */
|
|||
|
+
|
|||
|
+ if (search.argmode == ARG_NAME) {
|
|||
|
+ if (argc < 1) {
|
|||
|
+ if (outmode != OUTMODE_FLN)
|
|||
|
+ usage(ARG_NAME);
|
|||
|
+ if (conf.manpath.sz == 0) {
|
|||
|
+ warnx("The manpath is empty.");
|
|||
|
+ mandoc_msg_setrc(MANDOCLEVEL_BADARG);
|
|||
|
+ } else {
|
|||
|
+ for (i = 0; i + 1 < conf.manpath.sz; i++)
|
|||
|
+ printf("%s:", conf.manpath.paths[i]);
|
|||
|
+ printf("%s\n", conf.manpath.paths[i]);
|
|||
|
+ }
|
|||
|
+ manconf_free(&conf);
|
|||
|
+ return (int)mandoc_msg_getrc();
|
|||
|
+ }
|
|||
|
+ for (res = NULL, ressz = 0; argc > 0; argc--, argv++) {
|
|||
|
+ (void)mansearch(&search, &conf.manpath,
|
|||
|
+ 1, argv, &resn, &resnsz);
|
|||
|
+ if (resnsz == 0)
|
|||
|
+ (void)fs_search(&search, &conf.manpath,
|
|||
|
+ *argv, &resn, &resnsz);
|
|||
|
+ if (resnsz == 0 && strchr(*argv, '/') == NULL) {
|
|||
|
+ if (search.arch != NULL &&
|
|||
|
+ arch_valid(search.arch, OSENUM) == 0)
|
|||
|
+ warnx("Unknown architecture \"%s\".",
|
|||
|
+ search.arch);
|
|||
|
+ else if (search.sec != NULL)
|
|||
|
+ warnx("No entry for %s in "
|
|||
|
+ "section %s of the manual.",
|
|||
|
+ *argv, search.sec);
|
|||
|
+ else
|
|||
|
+ warnx("No entry for %s in "
|
|||
|
+ "the manual.", *argv);
|
|||
|
+ mandoc_msg_setrc(MANDOCLEVEL_BADARG);
|
|||
|
+ continue;
|
|||
|
+ }
|
|||
|
+ if (resnsz == 0) {
|
|||
|
+ if (access(*argv, R_OK) == -1) {
|
|||
|
+ mandoc_msg_setinfilename(*argv);
|
|||
|
+ mandoc_msg(MANDOCERR_BADARG_BAD,
|
|||
|
+ 0, 0, "%s", strerror(errno));
|
|||
|
+ mandoc_msg_setinfilename(NULL);
|
|||
|
continue;
|
|||
|
}
|
|||
|
+ resnsz = 1;
|
|||
|
+ resn = mandoc_calloc(resnsz, sizeof(*res));
|
|||
|
+ resn->file = mandoc_strdup(*argv);
|
|||
|
+ resn->ipath = SIZE_MAX;
|
|||
|
+ resn->form = FORM_SRC;
|
|||
|
+ }
|
|||
|
+ if (outmode != OUTMODE_ONE || resnsz == 1) {
|
|||
|
res = mandoc_reallocarray(res,
|
|||
|
- sz + 1, sizeof(*res));
|
|||
|
- res[sz].file = mandoc_strdup(argv[c]);
|
|||
|
- res[sz].names = NULL;
|
|||
|
- res[sz].output = NULL;
|
|||
|
- res[sz].ipath = SIZE_MAX;
|
|||
|
- res[sz].sec = 10;
|
|||
|
- res[sz].form = FORM_SRC;
|
|||
|
- sz++;
|
|||
|
+ ressz + resnsz, sizeof(*res));
|
|||
|
+ memcpy(res + ressz, resn,
|
|||
|
+ sizeof(*resn) * resnsz);
|
|||
|
+ ressz += resnsz;
|
|||
|
+ continue;
|
|||
|
}
|
|||
|
- }
|
|||
|
|
|||
|
- if (sz == 0) {
|
|||
|
- if (search.argmode != ARG_NAME)
|
|||
|
- warnx("nothing appropriate");
|
|||
|
- mandoc_msg_setrc(MANDOCLEVEL_BADARG);
|
|||
|
- goto out;
|
|||
|
- }
|
|||
|
+ /* Search for the best section. */
|
|||
|
|
|||
|
- /*
|
|||
|
- * For standard man(1) and -a output mode,
|
|||
|
- * prepare for copying filename pointers
|
|||
|
- * into the program parameter array.
|
|||
|
- */
|
|||
|
-
|
|||
|
- if (outmode == OUTMODE_ONE) {
|
|||
|
- argc = 1;
|
|||
|
- best_prio = 20;
|
|||
|
- } else if (outmode == OUTMODE_ALL)
|
|||
|
- argc = (int)sz;
|
|||
|
-
|
|||
|
- /* Iterate all matching manuals. */
|
|||
|
-
|
|||
|
- resp = res;
|
|||
|
- for (i = 0; i < sz; i++) {
|
|||
|
- if (outmode == OUTMODE_FLN)
|
|||
|
- puts(res[i].file);
|
|||
|
- else if (outmode == OUTMODE_LST)
|
|||
|
- printf("%s - %s\n", res[i].names,
|
|||
|
- res[i].output == NULL ? "" :
|
|||
|
- res[i].output);
|
|||
|
- else if (outmode == OUTMODE_ONE) {
|
|||
|
- /* Search for the best section. */
|
|||
|
- sec = res[i].file;
|
|||
|
+ best_prio = 40;
|
|||
|
+ for (ib = i = 0; i < resnsz; i++) {
|
|||
|
+ sec = resn[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;
|
|||
|
- resp = res + i;
|
|||
|
+ ib = i;
|
|||
|
}
|
|||
|
+ res = mandoc_reallocarray(res, ressz + 1,
|
|||
|
+ sizeof(*res));
|
|||
|
+ memcpy(res + ressz++, resn + ib, sizeof(*resn));
|
|||
|
}
|
|||
|
|
|||
|
- /*
|
|||
|
- * For man(1), -a and -i output mode, fall through
|
|||
|
- * to the main mandoc(1) code iterating files
|
|||
|
- * and running the parsers on each of them.
|
|||
|
- */
|
|||
|
+ /* apropos(1), whatis(1): Process the full search expression. */
|
|||
|
+
|
|||
|
+ } else if (search.argmode != ARG_FILE) {
|
|||
|
+ if (mansearch(&search, &conf.manpath,
|
|||
|
+ argc, argv, &res, &ressz) == 0)
|
|||
|
+ usage(search.argmode);
|
|||
|
|
|||
|
- if (outmode == OUTMODE_FLN || outmode == OUTMODE_LST)
|
|||
|
+ if (ressz == 0) {
|
|||
|
+ warnx("nothing appropriate");
|
|||
|
+ mandoc_msg_setrc(MANDOCLEVEL_BADARG);
|
|||
|
goto out;
|
|||
|
- }
|
|||
|
+ }
|
|||
|
|
|||
|
- /* mandoc(1) */
|
|||
|
+ /* mandoc(1): Take command line arguments as file names. */
|
|||
|
|
|||
|
-#if HAVE_PLEDGE
|
|||
|
- if (use_pager) {
|
|||
|
- if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1)
|
|||
|
- err((int)MANDOCLEVEL_SYSERR, "pledge");
|
|||
|
} else {
|
|||
|
- if (pledge("stdio rpath", NULL) == -1)
|
|||
|
- err((int)MANDOCLEVEL_SYSERR, "pledge");
|
|||
|
+ ressz = argc > 0 ? argc : 1;
|
|||
|
+ res = mandoc_calloc(ressz, sizeof(*res));
|
|||
|
+ for (i = 0; i < ressz; i++) {
|
|||
|
+ if (argc > 0)
|
|||
|
+ res[i].file = mandoc_strdup(argv[i]);
|
|||
|
+ res[i].ipath = SIZE_MAX;
|
|||
|
+ res[i].form = FORM_SRC;
|
|||
|
+ }
|
|||
|
}
|
|||
|
-#endif
|
|||
|
|
|||
|
- if (search.argmode == ARG_FILE)
|
|||
|
- moptions(&options, auxpaths);
|
|||
|
-
|
|||
|
- mchars_alloc();
|
|||
|
- curp.mp = mparse_alloc(options, curp.os_e, curp.os_s);
|
|||
|
+ switch (outmode) {
|
|||
|
+ case OUTMODE_FLN:
|
|||
|
+ for (i = 0; i < ressz; i++)
|
|||
|
+ puts(res[i].file);
|
|||
|
+ goto out;
|
|||
|
+ case OUTMODE_LST:
|
|||
|
+ for (i = 0; i < ressz; i++)
|
|||
|
+ printf("%s - %s\n", res[i].names,
|
|||
|
+ res[i].output == NULL ? "" :
|
|||
|
+ res[i].output);
|
|||
|
+ goto out;
|
|||
|
+ default:
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
|
|||
|
- if (argc < 1) {
|
|||
|
- if (use_pager) {
|
|||
|
- tag_files = tag_init();
|
|||
|
- tag_files->tagname = conf.output.tag;
|
|||
|
- }
|
|||
|
- thisarg = "<stdin>";
|
|||
|
- mandoc_msg_setinfilename(thisarg);
|
|||
|
- parse(&curp, STDIN_FILENO, thisarg);
|
|||
|
- mandoc_msg_setinfilename(NULL);
|
|||
|
+ 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();
|
|||
|
+ mp = mparse_alloc(options, os_e, os_s);
|
|||
|
+
|
|||
|
/*
|
|||
|
* Remember the original working directory, if possible.
|
|||
|
* This will be needed if some names on the command line
|
|||
|
@@ -511,166 +598,57 @@ main(int argc, char *argv[])
|
|||
|
*/
|
|||
|
startdir = open(".", O_RDONLY | O_DIRECTORY);
|
|||
|
|
|||
|
- while (argc > 0) {
|
|||
|
-
|
|||
|
- /*
|
|||
|
- * Changing directories is not needed in ARG_FILE mode.
|
|||
|
- * Do it on a best-effort basis. Even in case of
|
|||
|
- * failure, some functionality may still work.
|
|||
|
- */
|
|||
|
- if (resp != NULL) {
|
|||
|
- if (resp->ipath != SIZE_MAX)
|
|||
|
- (void)chdir(conf.manpath.paths[resp->ipath]);
|
|||
|
- else if (startdir != -1)
|
|||
|
- (void)fchdir(startdir);
|
|||
|
- thisarg = resp->file;
|
|||
|
- } else
|
|||
|
- thisarg = *argv;
|
|||
|
-
|
|||
|
- 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;
|
|||
|
- }
|
|||
|
-
|
|||
|
- 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);
|
|||
|
-
|
|||
|
- if (ferror(stdout)) {
|
|||
|
- if (tag_files != NULL) {
|
|||
|
- warn("%s", tag_files->ofn);
|
|||
|
- tag_unlink();
|
|||
|
- tag_files = NULL;
|
|||
|
- } else
|
|||
|
- warn("stdout");
|
|||
|
- mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
|
|||
|
- break;
|
|||
|
- }
|
|||
|
-
|
|||
|
- if (argc > 1 && curp.outtype <= OUTT_UTF8) {
|
|||
|
- if (curp.outdata == NULL)
|
|||
|
- outdata_alloc(&curp);
|
|||
|
- terminal_sepline(curp.outdata);
|
|||
|
- }
|
|||
|
- } else
|
|||
|
- mandoc_msg(MANDOCERR_FILE, 0, 0,
|
|||
|
- "%s: %s", thisarg, strerror(errno));
|
|||
|
-
|
|||
|
- if (curp.wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
|
|||
|
+ for (i = 0; i < ressz; i++) {
|
|||
|
+ process_onefile(mp, res + i, startdir, &outst, &conf);
|
|||
|
+ if (outst.wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
|
|||
|
break;
|
|||
|
-
|
|||
|
- if (resp != NULL)
|
|||
|
- resp++;
|
|||
|
- else
|
|||
|
- argv++;
|
|||
|
- if (--argc)
|
|||
|
- mparse_reset(curp.mp);
|
|||
|
}
|
|||
|
if (startdir != -1) {
|
|||
|
(void)fchdir(startdir);
|
|||
|
close(startdir);
|
|||
|
}
|
|||
|
|
|||
|
- if (curp.outdata != NULL) {
|
|||
|
- switch (curp.outtype) {
|
|||
|
+ if (outst.outdata != NULL) {
|
|||
|
+ switch (outst.outtype) {
|
|||
|
case OUTT_HTML:
|
|||
|
- html_free(curp.outdata);
|
|||
|
+ html_free(outst.outdata);
|
|||
|
break;
|
|||
|
case OUTT_UTF8:
|
|||
|
case OUTT_LOCALE:
|
|||
|
case OUTT_ASCII:
|
|||
|
- ascii_free(curp.outdata);
|
|||
|
+ ascii_free(outst.outdata);
|
|||
|
break;
|
|||
|
case OUTT_PDF:
|
|||
|
case OUTT_PS:
|
|||
|
- pspdf_free(curp.outdata);
|
|||
|
+ pspdf_free(outst.outdata);
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
mandoc_xr_free();
|
|||
|
- mparse_free(curp.mp);
|
|||
|
+ mparse_free(mp);
|
|||
|
mchars_free();
|
|||
|
|
|||
|
out:
|
|||
|
- if (search.argmode != ARG_FILE) {
|
|||
|
+ mansearch_free(res, ressz);
|
|||
|
+ if (search.argmode != ARG_FILE)
|
|||
|
manconf_free(&conf);
|
|||
|
- mansearch_free(res, sz);
|
|||
|
- }
|
|||
|
|
|||
|
- free(curp.os_s);
|
|||
|
-
|
|||
|
- /*
|
|||
|
- * When using a pager, finish writing both temporary files,
|
|||
|
- * fork it, wait for the user to close it, and clean up.
|
|||
|
- */
|
|||
|
-
|
|||
|
- if (tag_files != NULL) {
|
|||
|
+ if (outst.tag_files != NULL) {
|
|||
|
fclose(stdout);
|
|||
|
tag_write();
|
|||
|
- man_pgid = getpgid(0);
|
|||
|
- tag_files->tcpgid = man_pgid == getpid() ?
|
|||
|
- getpgid(getppid()) : man_pgid;
|
|||
|
- pager_pid = 0;
|
|||
|
- signum = SIGSTOP;
|
|||
|
- for (;;) {
|
|||
|
-
|
|||
|
- /* Stop here until moved to the foreground. */
|
|||
|
-
|
|||
|
- tc_pgid = tcgetpgrp(tag_files->ofd);
|
|||
|
- if (tc_pgid != man_pgid) {
|
|||
|
- if (tc_pgid == pager_pid) {
|
|||
|
- (void)tcsetpgrp(tag_files->ofd,
|
|||
|
- man_pgid);
|
|||
|
- if (signum == SIGTTIN)
|
|||
|
- continue;
|
|||
|
- } else
|
|||
|
- tag_files->tcpgid = tc_pgid;
|
|||
|
- kill(0, signum);
|
|||
|
- continue;
|
|||
|
- }
|
|||
|
-
|
|||
|
- /* Once in the foreground, activate the pager. */
|
|||
|
-
|
|||
|
- if (pager_pid) {
|
|||
|
- (void)tcsetpgrp(tag_files->ofd, pager_pid);
|
|||
|
- kill(pager_pid, SIGCONT);
|
|||
|
- } else
|
|||
|
- pager_pid = spawn_pager(tag_files);
|
|||
|
-
|
|||
|
- /* Wait for the pager to stop or exit. */
|
|||
|
-
|
|||
|
- while ((pid = waitpid(pager_pid, &status,
|
|||
|
- WUNTRACED)) == -1 && errno == EINTR)
|
|||
|
- continue;
|
|||
|
-
|
|||
|
- if (pid == -1) {
|
|||
|
- warn("wait");
|
|||
|
- mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
|
|||
|
- break;
|
|||
|
- }
|
|||
|
- if (!WIFSTOPPED(status))
|
|||
|
- break;
|
|||
|
-
|
|||
|
- signum = WSTOPSIG(status);
|
|||
|
- }
|
|||
|
+ run_pager(outst.tag_files);
|
|||
|
tag_unlink();
|
|||
|
- }
|
|||
|
+ } else if (outst.had_output && outst.outtype != OUTT_LINT)
|
|||
|
+ 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 +679,7 @@ fs_lookup(const struct manpaths *paths,
|
|||
|
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 +689,13 @@ fs_lookup(const struct manpaths *paths,
|
|||
|
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 +704,7 @@ fs_lookup(const struct manpaths *paths,
|
|||
|
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,98 +713,150 @@ fs_lookup(const struct manpaths *paths,
|
|||
|
paths->paths[ipath], sec, name);
|
|||
|
globres = glob(file, 0, NULL, &globinfo);
|
|||
|
if (globres != 0 && globres != GLOB_NOMATCH)
|
|||
|
- warn("%s: glob", file);
|
|||
|
+ mandoc_msg(MANDOCERR_GLOB, 0, 0,
|
|||
|
+ "%s: %s", file, strerror(errno));
|
|||
|
free(file);
|
|||
|
if (globres == 0)
|
|||
|
file = mandoc_strdup(*globinfo.gl_pathv);
|
|||
|
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
|
|||
|
fs_search(const struct mansearch *cfg, const struct manpaths *paths,
|
|||
|
- int argc, char **argv, struct manpage **res, size_t *ressz)
|
|||
|
+ const char *name, struct manpage **res, size_t *ressz)
|
|||
|
{
|
|||
|
const char *const sections[] =
|
|||
|
{"1", "8", "6", "2", "3", "5", "7", "4", "9", "3p"};
|
|||
|
const size_t nsec = sizeof(sections)/sizeof(sections[0]);
|
|||
|
|
|||
|
- size_t ipath, isec, lastsz;
|
|||
|
+ size_t ipath, isec;
|
|||
|
|
|||
|
assert(cfg->argmode == ARG_NAME);
|
|||
|
-
|
|||
|
if (res != NULL)
|
|||
|
*res = NULL;
|
|||
|
- *ressz = lastsz = 0;
|
|||
|
- while (argc) {
|
|||
|
- for (ipath = 0; ipath < paths->sz; ipath++) {
|
|||
|
- if (cfg->sec != NULL) {
|
|||
|
- if (fs_lookup(paths, ipath, cfg->sec,
|
|||
|
- cfg->arch, *argv, res, ressz) &&
|
|||
|
- cfg->firstmatch)
|
|||
|
- return 1;
|
|||
|
- } else for (isec = 0; isec < nsec; isec++)
|
|||
|
+ *ressz = 0;
|
|||
|
+ for (ipath = 0; ipath < paths->sz; ipath++) {
|
|||
|
+ if (cfg->sec != NULL) {
|
|||
|
+ if (fs_lookup(paths, ipath, cfg->sec, cfg->arch,
|
|||
|
+ name, res, ressz) != -1 && cfg->firstmatch)
|
|||
|
+ return 0;
|
|||
|
+ } else {
|
|||
|
+ for (isec = 0; isec < nsec; isec++)
|
|||
|
if (fs_lookup(paths, ipath, sections[isec],
|
|||
|
- cfg->arch, *argv, res, ressz) &&
|
|||
|
+ cfg->arch, name, res, ressz) != -1 &&
|
|||
|
cfg->firstmatch)
|
|||
|
- return 1;
|
|||
|
+ return 0;
|
|||
|
}
|
|||
|
- if (res != NULL && *ressz == lastsz &&
|
|||
|
- strchr(*argv, '/') == NULL) {
|
|||
|
- if (cfg->arch != NULL &&
|
|||
|
- arch_valid(cfg->arch, OSENUM) == 0)
|
|||
|
- warnx("Unknown architecture \"%s\".",
|
|||
|
- cfg->arch);
|
|||
|
- else if (cfg->sec == NULL)
|
|||
|
- warnx("No entry for %s in the manual.",
|
|||
|
- *argv);
|
|||
|
- else
|
|||
|
- warnx("No entry for %s in section %s "
|
|||
|
- "of the manual.", *argv, cfg->sec);
|
|||
|
- }
|
|||
|
- lastsz = *ressz;
|
|||
|
- argv++;
|
|||
|
- argc--;
|
|||
|
}
|
|||
|
- return 0;
|
|||
|
+ return -1;
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
-parse(struct curparse *curp, int fd, const char *file)
|
|||
|
+process_onefile(struct mparse *mp, struct manpage *resp, int startdir,
|
|||
|
+ struct outstate *outst, struct manconf *conf)
|
|||
|
{
|
|||
|
- struct roff_meta *meta;
|
|||
|
+ int fd;
|
|||
|
+
|
|||
|
+ /*
|
|||
|
+ * Changing directories is not needed in ARG_FILE mode.
|
|||
|
+ * Do it on a best-effort basis. Even in case of
|
|||
|
+ * failure, some functionality may still work.
|
|||
|
+ */
|
|||
|
+ if (resp->ipath != SIZE_MAX)
|
|||
|
+ (void)chdir(conf->manpath.paths[resp->ipath]);
|
|||
|
+ else if (startdir != -1)
|
|||
|
+ (void)fchdir(startdir);
|
|||
|
+
|
|||
|
+ mandoc_msg_setinfilename(resp->file);
|
|||
|
+ if (resp->file != NULL) {
|
|||
|
+ if ((fd = mparse_open(mp, resp->file)) == -1) {
|
|||
|
+ mandoc_msg(resp->ipath == SIZE_MAX ?
|
|||
|
+ MANDOCERR_BADARG_BAD : MANDOCERR_OPEN,
|
|||
|
+ 0, 0, "%s", strerror(errno));
|
|||
|
+ mandoc_msg_setinfilename(NULL);
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
+ } else
|
|||
|
+ fd = STDIN_FILENO;
|
|||
|
+
|
|||
|
+ if (outst->use_pager) {
|
|||
|
+ outst->use_pager = 0;
|
|||
|
+ outst->tag_files = tag_init(conf->output.tag);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (outst->had_output && outst->outtype <= OUTT_UTF8) {
|
|||
|
+ if (outst->outdata == NULL)
|
|||
|
+ outdata_alloc(outst, &conf->output);
|
|||
|
+ terminal_sepline(outst->outdata);
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ if (resp->form == FORM_SRC)
|
|||
|
+ parse(mp, fd, resp->file, outst, &conf->output);
|
|||
|
+ else {
|
|||
|
+ passthrough(fd, conf->output.synopsisonly);
|
|||
|
+ outst->had_output = 1;
|
|||
|
+ }
|
|||
|
|
|||
|
- /* Begin by parsing the file itself. */
|
|||
|
+ if (ferror(stdout)) {
|
|||
|
+ if (outst->tag_files != NULL) {
|
|||
|
+ mandoc_msg(MANDOCERR_WRITE, 0, 0, "%s: %s",
|
|||
|
+ outst->tag_files->ofn, strerror(errno));
|
|||
|
+ tag_unlink();
|
|||
|
+ outst->tag_files = NULL;
|
|||
|
+ } else
|
|||
|
+ mandoc_msg(MANDOCERR_WRITE, 0, 0, "%s",
|
|||
|
+ strerror(errno));
|
|||
|
+ }
|
|||
|
+ mandoc_msg_setinfilename(NULL);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static void
|
|||
|
+parse(struct mparse *mp, int fd, const char *file,
|
|||
|
+ struct outstate *outst, struct manoutput *outconf)
|
|||
|
+{
|
|||
|
+ static int previous;
|
|||
|
+ struct roff_meta *meta;
|
|||
|
|
|||
|
- assert(file);
|
|||
|
assert(fd >= 0);
|
|||
|
+ if (file == NULL)
|
|||
|
+ file = "<stdin>";
|
|||
|
+
|
|||
|
+ if (previous)
|
|||
|
+ mparse_reset(mp);
|
|||
|
+ else
|
|||
|
+ previous = 1;
|
|||
|
|
|||
|
- mparse_readfd(curp->mp, fd, file);
|
|||
|
+ mparse_readfd(mp, fd, file);
|
|||
|
if (fd != STDIN_FILENO)
|
|||
|
close(fd);
|
|||
|
|
|||
|
@@ -834,61 +865,62 @@ parse(struct curparse *curp, int fd, con
|
|||
|
* level, do not produce output.
|
|||
|
*/
|
|||
|
|
|||
|
- if (curp->wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
|
|||
|
+ if (outst->wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
|
|||
|
return;
|
|||
|
|
|||
|
- if (curp->outdata == NULL)
|
|||
|
- outdata_alloc(curp);
|
|||
|
- else if (curp->outtype == OUTT_HTML)
|
|||
|
- html_reset(curp);
|
|||
|
+ if (outst->outdata == NULL)
|
|||
|
+ outdata_alloc(outst, outconf);
|
|||
|
+ else if (outst->outtype == OUTT_HTML)
|
|||
|
+ html_reset(outst);
|
|||
|
|
|||
|
mandoc_xr_reset();
|
|||
|
- meta = mparse_result(curp->mp);
|
|||
|
+ meta = mparse_result(mp);
|
|||
|
|
|||
|
/* Execute the out device, if it exists. */
|
|||
|
|
|||
|
+ outst->had_output = 1;
|
|||
|
if (meta->macroset == MACROSET_MDOC) {
|
|||
|
- switch (curp->outtype) {
|
|||
|
+ switch (outst->outtype) {
|
|||
|
case OUTT_HTML:
|
|||
|
- html_mdoc(curp->outdata, meta);
|
|||
|
+ html_mdoc(outst->outdata, meta);
|
|||
|
break;
|
|||
|
case OUTT_TREE:
|
|||
|
- tree_mdoc(curp->outdata, meta);
|
|||
|
+ tree_mdoc(outst->outdata, meta);
|
|||
|
break;
|
|||
|
case OUTT_MAN:
|
|||
|
- man_mdoc(curp->outdata, meta);
|
|||
|
+ man_mdoc(outst->outdata, meta);
|
|||
|
break;
|
|||
|
case OUTT_PDF:
|
|||
|
case OUTT_ASCII:
|
|||
|
case OUTT_UTF8:
|
|||
|
case OUTT_LOCALE:
|
|||
|
case OUTT_PS:
|
|||
|
- terminal_mdoc(curp->outdata, meta);
|
|||
|
+ terminal_mdoc(outst->outdata, meta);
|
|||
|
break;
|
|||
|
case OUTT_MARKDOWN:
|
|||
|
- markdown_mdoc(curp->outdata, meta);
|
|||
|
+ markdown_mdoc(outst->outdata, meta);
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (meta->macroset == MACROSET_MAN) {
|
|||
|
- switch (curp->outtype) {
|
|||
|
+ switch (outst->outtype) {
|
|||
|
case OUTT_HTML:
|
|||
|
- html_man(curp->outdata, meta);
|
|||
|
+ html_man(outst->outdata, meta);
|
|||
|
break;
|
|||
|
case OUTT_TREE:
|
|||
|
- tree_man(curp->outdata, meta);
|
|||
|
+ tree_man(outst->outdata, meta);
|
|||
|
break;
|
|||
|
case OUTT_MAN:
|
|||
|
- mparse_copy(curp->mp);
|
|||
|
+ mparse_copy(mp);
|
|||
|
break;
|
|||
|
case OUTT_PDF:
|
|||
|
case OUTT_ASCII:
|
|||
|
case OUTT_UTF8:
|
|||
|
case OUTT_LOCALE:
|
|||
|
case OUTT_PS:
|
|||
|
- terminal_man(curp->outdata, meta);
|
|||
|
+ terminal_man(outst->outdata, meta);
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
@@ -919,7 +951,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, xr->name, NULL, &sz) != -1)
|
|||
|
continue;
|
|||
|
if (xr->count == 1)
|
|||
|
mandoc_msg(MANDOCERR_XR_BAD, xr->line,
|
|||
|
@@ -932,26 +964,26 @@ check_xr(void)
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
-outdata_alloc(struct curparse *curp)
|
|||
|
+outdata_alloc(struct outstate *outst, struct manoutput *outconf)
|
|||
|
{
|
|||
|
- switch (curp->outtype) {
|
|||
|
+ switch (outst->outtype) {
|
|||
|
case OUTT_HTML:
|
|||
|
- curp->outdata = html_alloc(curp->outopts);
|
|||
|
+ outst->outdata = html_alloc(outconf);
|
|||
|
break;
|
|||
|
case OUTT_UTF8:
|
|||
|
- curp->outdata = utf8_alloc(curp->outopts);
|
|||
|
+ outst->outdata = utf8_alloc(outconf);
|
|||
|
break;
|
|||
|
case OUTT_LOCALE:
|
|||
|
- curp->outdata = locale_alloc(curp->outopts);
|
|||
|
+ outst->outdata = locale_alloc(outconf);
|
|||
|
break;
|
|||
|
case OUTT_ASCII:
|
|||
|
- curp->outdata = ascii_alloc(curp->outopts);
|
|||
|
+ outst->outdata = ascii_alloc(outconf);
|
|||
|
break;
|
|||
|
case OUTT_PDF:
|
|||
|
- curp->outdata = pdf_alloc(curp->outopts);
|
|||
|
+ outst->outdata = pdf_alloc(outconf);
|
|||
|
break;
|
|||
|
case OUTT_PS:
|
|||
|
- curp->outdata = ps_alloc(curp->outopts);
|
|||
|
+ outst->outdata = ps_alloc(outconf);
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
@@ -959,34 +991,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,98 +1036,24 @@ passthrough(const char *file, int fd, in
|
|||
|
}
|
|||
|
}
|
|||
|
for (; len > 0; len -= written) {
|
|||
|
- if ((written = write(STDOUT_FILENO, cp, len)) != -1)
|
|||
|
- continue;
|
|||
|
- fclose(stream);
|
|||
|
- syscall = "write";
|
|||
|
- goto fail;
|
|||
|
+ if ((written = write(STDOUT_FILENO, cp, len)) == -1) {
|
|||
|
+ mandoc_msg(MANDOCERR_WRITE, 0, 0,
|
|||
|
+ "%s", strerror(errno));
|
|||
|
+ goto done;
|
|||
|
+ }
|
|||
|
}
|
|||
|
}
|
|||
|
-
|
|||
|
- if (ferror(stream)) {
|
|||
|
- fclose(stream);
|
|||
|
- syscall = "getline";
|
|||
|
- goto fail;
|
|||
|
- }
|
|||
|
+ if (ferror(stream))
|
|||
|
+ mandoc_msg(MANDOCERR_GETLINE, lno, 0, "%s", strerror(errno));
|
|||
|
|
|||
|
done:
|
|||
|
free(line);
|
|||
|
- fclose(stream);
|
|||
|
- return;
|
|||
|
-
|
|||
|
-fail:
|
|||
|
- free(line);
|
|||
|
- warn("%s: SYSERR: %s", file, syscall);
|
|||
|
- mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
|
|||
|
-}
|
|||
|
-
|
|||
|
-static int
|
|||
|
-koptions(int *options, char *arg)
|
|||
|
-{
|
|||
|
-
|
|||
|
- if ( ! strcmp(arg, "utf-8")) {
|
|||
|
- *options |= MPARSE_UTF8;
|
|||
|
- *options &= ~MPARSE_LATIN1;
|
|||
|
- } else if ( ! strcmp(arg, "iso-8859-1")) {
|
|||
|
- *options |= MPARSE_LATIN1;
|
|||
|
- *options &= ~MPARSE_UTF8;
|
|||
|
- } else if ( ! strcmp(arg, "us-ascii")) {
|
|||
|
- *options &= ~(MPARSE_UTF8 | MPARSE_LATIN1);
|
|||
|
- } else {
|
|||
|
- warnx("-K %s: Bad argument", arg);
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
- return 1;
|
|||
|
-}
|
|||
|
-
|
|||
|
-static void
|
|||
|
-moptions(int *options, char *arg)
|
|||
|
-{
|
|||
|
-
|
|||
|
- if (arg == NULL)
|
|||
|
- return;
|
|||
|
- if (strcmp(arg, "doc") == 0)
|
|||
|
- *options |= MPARSE_MDOC;
|
|||
|
- else if (strcmp(arg, "an") == 0)
|
|||
|
- *options |= MPARSE_MAN;
|
|||
|
-}
|
|||
|
-
|
|||
|
-static int
|
|||
|
-toptions(struct curparse *curp, char *arg)
|
|||
|
-{
|
|||
|
-
|
|||
|
- if (0 == strcmp(arg, "ascii"))
|
|||
|
- curp->outtype = OUTT_ASCII;
|
|||
|
- else if (0 == strcmp(arg, "lint")) {
|
|||
|
- curp->outtype = OUTT_LINT;
|
|||
|
- mandoc_msg_setoutfile(stdout);
|
|||
|
- mandoc_msg_setmin(MANDOCERR_BASE);
|
|||
|
- } else if (0 == strcmp(arg, "tree"))
|
|||
|
- curp->outtype = OUTT_TREE;
|
|||
|
- else if (0 == strcmp(arg, "man"))
|
|||
|
- curp->outtype = OUTT_MAN;
|
|||
|
- else if (0 == strcmp(arg, "html"))
|
|||
|
- curp->outtype = OUTT_HTML;
|
|||
|
- else if (0 == strcmp(arg, "markdown"))
|
|||
|
- curp->outtype = OUTT_MARKDOWN;
|
|||
|
- else if (0 == strcmp(arg, "utf8"))
|
|||
|
- curp->outtype = OUTT_UTF8;
|
|||
|
- else if (0 == strcmp(arg, "locale"))
|
|||
|
- curp->outtype = OUTT_LOCALE;
|
|||
|
- else if (0 == strcmp(arg, "ps"))
|
|||
|
- curp->outtype = OUTT_PS;
|
|||
|
- else if (0 == strcmp(arg, "pdf"))
|
|||
|
- curp->outtype = OUTT_PDF;
|
|||
|
- else {
|
|||
|
- warnx("-T %s: Bad argument", arg);
|
|||
|
- return 0;
|
|||
|
- }
|
|||
|
-
|
|||
|
- return 1;
|
|||
|
+ if (stream != NULL)
|
|||
|
+ fclose(stream);
|
|||
|
}
|
|||
|
|
|||
|
static int
|
|||
|
-woptions(struct curparse *curp, char *arg)
|
|||
|
+woptions(char *arg, enum mandoc_os *os_e, int *wstop)
|
|||
|
{
|
|||
|
char *v, *o;
|
|||
|
const char *toks[11];
|
|||
|
@@ -1116,7 +1074,7 @@ woptions(struct curparse *curp, char *ar
|
|||
|
o = arg;
|
|||
|
switch (getsubopt(&arg, (char * const *)toks, &v)) {
|
|||
|
case 0:
|
|||
|
- curp->wstop = 1;
|
|||
|
+ *wstop = 1;
|
|||
|
break;
|
|||
|
case 1:
|
|||
|
case 2:
|
|||
|
@@ -1135,22 +1093,80 @@ woptions(struct curparse *curp, char *ar
|
|||
|
mandoc_msg_setmin(MANDOCERR_UNSUPP);
|
|||
|
break;
|
|||
|
case 7:
|
|||
|
- mandoc_msg_setmin(MANDOCERR_MAX);
|
|||
|
+ mandoc_msg_setmin(MANDOCERR_BADARG);
|
|||
|
break;
|
|||
|
case 8:
|
|||
|
mandoc_msg_setmin(MANDOCERR_BASE);
|
|||
|
- curp->os_e = MANDOC_OS_OPENBSD;
|
|||
|
+ *os_e = MANDOC_OS_OPENBSD;
|
|||
|
break;
|
|||
|
case 9:
|
|||
|
mandoc_msg_setmin(MANDOCERR_BASE);
|
|||
|
- curp->os_e = MANDOC_OS_NETBSD;
|
|||
|
+ *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 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
+/*
|
|||
|
+ * Wait until moved to the foreground,
|
|||
|
+ * then fork the pager and wait for the user to close it.
|
|||
|
+ */
|
|||
|
+static void
|
|||
|
+run_pager(struct tag_files *tag_files)
|
|||
|
+{
|
|||
|
+ int signum, status;
|
|||
|
+ pid_t man_pgid, tc_pgid;
|
|||
|
+ pid_t pager_pid, wait_pid;
|
|||
|
+
|
|||
|
+ man_pgid = getpgid(0);
|
|||
|
+ tag_files->tcpgid = man_pgid == getpid() ? getpgid(getppid()) :
|
|||
|
+ man_pgid;
|
|||
|
+ pager_pid = 0;
|
|||
|
+ signum = SIGSTOP;
|
|||
|
+
|
|||
|
+ for (;;) {
|
|||
|
+ /* Stop here until moved to the foreground. */
|
|||
|
+
|
|||
|
+ tc_pgid = tcgetpgrp(tag_files->ofd);
|
|||
|
+ if (tc_pgid != man_pgid) {
|
|||
|
+ if (tc_pgid == pager_pid) {
|
|||
|
+ (void)tcsetpgrp(tag_files->ofd, man_pgid);
|
|||
|
+ if (signum == SIGTTIN)
|
|||
|
+ continue;
|
|||
|
+ } else
|
|||
|
+ tag_files->tcpgid = tc_pgid;
|
|||
|
+ kill(0, signum);
|
|||
|
+ continue;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ /* Once in the foreground, activate the pager. */
|
|||
|
+
|
|||
|
+ if (pager_pid) {
|
|||
|
+ (void)tcsetpgrp(tag_files->ofd, pager_pid);
|
|||
|
+ kill(pager_pid, SIGCONT);
|
|||
|
+ } else
|
|||
|
+ pager_pid = spawn_pager(tag_files);
|
|||
|
+
|
|||
|
+ /* Wait for the pager to stop or exit. */
|
|||
|
+
|
|||
|
+ while ((wait_pid = waitpid(pager_pid, &status,
|
|||
|
+ WUNTRACED)) == -1 && errno == EINTR)
|
|||
|
+ continue;
|
|||
|
+
|
|||
|
+ if (wait_pid == -1) {
|
|||
|
+ mandoc_msg(MANDOCERR_WAIT, 0, 0,
|
|||
|
+ "%s", strerror(errno));
|
|||
|
+ break;
|
|||
|
}
|
|||
|
+ if (!WIFSTOPPED(status))
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ signum = WSTOPSIG(status);
|
|||
|
}
|
|||
|
- return 1;
|
|||
|
}
|
|||
|
|
|||
|
static pid_t
|
|||
|
@@ -1196,7 +1212,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 +1231,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 +1251,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 +1264,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());
|
|||
|
}
|
|||
|
--- a/man.1
|
|||
|
+++ b/man.1
|
|||
|
@@ -3,7 +3,7 @@
|
|||
|
.\" Copyright (c) 1989, 1990, 1993
|
|||
|
.\" The Regents of the University of California. All rights reserved.
|
|||
|
.\" Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
|
|||
|
-.\" Copyright (c) 2010, 2011, 2014-2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+.\" Copyright (c) 2010, 2011, 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
.\"
|
|||
|
.\" Redistribution and use in source and binary forms, with or without
|
|||
|
.\" modification, are permitted provided that the following conditions
|
|||
|
@@ -51,7 +51,7 @@ The
|
|||
|
.Nm
|
|||
|
utility
|
|||
|
displays the
|
|||
|
-manual pages entitled
|
|||
|
+manual page entitled
|
|||
|
.Ar name .
|
|||
|
Pages may be selected according to
|
|||
|
a specific category
|
|||
|
@@ -64,7 +64,6 @@ The options are as follows:
|
|||
|
.Bl -tag -width Ds
|
|||
|
.It Fl a
|
|||
|
Display all matching manual pages.
|
|||
|
-Normally, only the first page found is displayed.
|
|||
|
.It Fl C Ar file
|
|||
|
Use the specified
|
|||
|
.Ar file
|
|||
|
@@ -129,31 +128,31 @@ are ignored.
|
|||
|
This option implies
|
|||
|
.Fl a .
|
|||
|
.It Fl M Ar path
|
|||
|
-Override the list of standard directories which
|
|||
|
-.Nm
|
|||
|
-searches for manual pages.
|
|||
|
+Override the list of directories to search for manual pages.
|
|||
|
The supplied
|
|||
|
.Ar path
|
|||
|
must be a colon
|
|||
|
.Pq Ql \&:
|
|||
|
separated list of directories.
|
|||
|
-This search path may also be set using the environment variable
|
|||
|
-.Ev MANPATH .
|
|||
|
+This option also overrides the environment variable
|
|||
|
+.Ev MANPATH
|
|||
|
+and any directories specified in the
|
|||
|
+.Xr man.conf 5
|
|||
|
+file.
|
|||
|
.It Fl m Ar path
|
|||
|
-Augment the list of standard directories which
|
|||
|
-.Nm
|
|||
|
-searches for manual pages.
|
|||
|
+Augment the list of directories to search for manual pages.
|
|||
|
The supplied
|
|||
|
.Ar path
|
|||
|
must be a colon
|
|||
|
.Pq Ql \&:
|
|||
|
separated list of directories.
|
|||
|
-These directories will be searched before the standard directories or
|
|||
|
-the directories specified using the
|
|||
|
+These directories will be searched before those specified using the
|
|||
|
.Fl M
|
|||
|
-option or the
|
|||
|
+option, the
|
|||
|
.Ev MANPATH
|
|||
|
-environment variable.
|
|||
|
+environment variable, the
|
|||
|
+.Xr man.conf 5
|
|||
|
+file, or the default directories.
|
|||
|
.It Fl S Ar subsection
|
|||
|
Only show pages for the specified
|
|||
|
.Xr machine 1
|
|||
|
@@ -197,13 +196,12 @@ System maintenance and operation command
|
|||
|
.It 9
|
|||
|
Kernel internals.
|
|||
|
.El
|
|||
|
-.Pp
|
|||
|
-If not specified and a match is found in more than one section,
|
|||
|
-the first match is selected from the following list:
|
|||
|
-1, 8, 6, 2, 3, 5, 7, 4, 9, 3p.
|
|||
|
.It Fl w
|
|||
|
List the pathnames of all matching manual pages instead of displaying
|
|||
|
any of them.
|
|||
|
+If no
|
|||
|
+.Ar name
|
|||
|
+is given, list the directories that would be searched.
|
|||
|
.El
|
|||
|
.Pp
|
|||
|
The options
|
|||
|
@@ -214,9 +212,23 @@ The options
|
|||
|
.Fl fkl
|
|||
|
are mutually exclusive and override each other.
|
|||
|
.Pp
|
|||
|
-Guidelines for writing
|
|||
|
-man pages can be found in
|
|||
|
-.Xr mdoc 7 .
|
|||
|
+The search starts with the
|
|||
|
+.Fl m
|
|||
|
+argument if provided, then continues with the
|
|||
|
+.Fl M
|
|||
|
+argument, the
|
|||
|
+.Ev MANPATH
|
|||
|
+variable, the
|
|||
|
+.Ic manpath
|
|||
|
+entries in the
|
|||
|
+.Xr man.conf 5
|
|||
|
+file, or with
|
|||
|
+.Pa /usr/share/man : Ns Pa /usr/X11R6/man : Ns Pa /usr/local/man
|
|||
|
+by default.
|
|||
|
+Within each of these, directories are searched in the order provided.
|
|||
|
+Within each directory, the search proceeds according to the following
|
|||
|
+list of sections: 1, 8, 6, 2, 3, 5, 7, 4, 9, 3p.
|
|||
|
+The first match found is shown.
|
|||
|
.Pp
|
|||
|
The
|
|||
|
.Xr mandoc.db 5
|
|||
|
@@ -236,6 +248,10 @@ The database is kept up to date with
|
|||
|
which is run by the
|
|||
|
.Xr weekly 8
|
|||
|
maintenance script.
|
|||
|
+.Pp
|
|||
|
+Guidelines for writing
|
|||
|
+man pages can be found in
|
|||
|
+.Xr mdoc 7 .
|
|||
|
.Sh ENVIRONMENT
|
|||
|
.Bl -tag -width MANPATHX
|
|||
|
.It Ev MACHINE
|
|||
|
@@ -286,15 +302,15 @@ manual opens a manual page at the defini
|
|||
|
.Ar term
|
|||
|
rather than at the beginning.
|
|||
|
.It Ev MANPATH
|
|||
|
-The standard search path used by
|
|||
|
-.Nm
|
|||
|
-may be changed by specifying a path in the
|
|||
|
+Override the standard search path which is either specified in
|
|||
|
+.Xr man.conf 5
|
|||
|
+or the default path.
|
|||
|
+The format of
|
|||
|
.Ev MANPATH
|
|||
|
-environment variable.
|
|||
|
-The format of the path is a colon
|
|||
|
+is a colon
|
|||
|
.Pq Ql \&:
|
|||
|
separated list of directories.
|
|||
|
-Invalid paths are ignored.
|
|||
|
+Invalid directories are ignored.
|
|||
|
Overridden by
|
|||
|
.Fl M ,
|
|||
|
ignored if
|
|||
|
@@ -303,12 +319,10 @@ is specified.
|
|||
|
.Pp
|
|||
|
If
|
|||
|
.Ev MANPATH
|
|||
|
-begins with a colon, it is appended to the default list;
|
|||
|
-if it ends with a colon, it is prepended to the default list;
|
|||
|
+begins with a colon, it is appended to the standard path;
|
|||
|
+if it ends with a colon, it is prepended to the standard path;
|
|||
|
or if it contains two adjacent colons,
|
|||
|
-the standard search path is inserted between the colons.
|
|||
|
-If none of these conditions are met, it overrides the
|
|||
|
-standard search path.
|
|||
|
+the standard path is inserted between the colons.
|
|||
|
.It Ev PAGER
|
|||
|
Specifies the pagination program to use when
|
|||
|
.Ev MANPAGER
|
|||
|
@@ -321,7 +335,9 @@ is used.
|
|||
|
.Sh FILES
|
|||
|
.Bl -tag -width /etc/man.conf -compact
|
|||
|
.It Pa /etc/man.conf
|
|||
|
-default man configuration file
|
|||
|
+default
|
|||
|
+.Nm
|
|||
|
+configuration file
|
|||
|
.El
|
|||
|
.Sh EXIT STATUS
|
|||
|
.Ex -std man
|
|||
|
@@ -365,7 +381,7 @@ are extensions to that specification.
|
|||
|
A
|
|||
|
.Nm
|
|||
|
command first appeared in
|
|||
|
-.At v3 .
|
|||
|
+.At v2 .
|
|||
|
.Pp
|
|||
|
The
|
|||
|
.Fl w
|
|||
|
--- a/man.7
|
|||
|
+++ b/man.7
|
|||
|
@@ -160,7 +160,9 @@ This has no effect unless the tabulator
|
|||
|
.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 \&
|
|||
|
--- a/man.conf.5
|
|||
|
+++ b/man.conf.5
|
|||
|
@@ -101,15 +101,11 @@ manual.
|
|||
|
.It Ic toc Ta none Ta Cm html Ta print table of contents
|
|||
|
.It Ic width Ta integer Ta Cm ascii , utf8 Ta right margin
|
|||
|
.El
|
|||
|
-.It Ic _whatdb Ar path Ns Cm /whatis.db
|
|||
|
-This directive provides the same functionality as
|
|||
|
-.Ic manpath ,
|
|||
|
-but using a historic and misleading syntax.
|
|||
|
-It is kept for backward compatibility for now,
|
|||
|
-but will eventually be removed.
|
|||
|
.El
|
|||
|
.Sh FILES
|
|||
|
-.Pa /etc/man.conf
|
|||
|
+.Bl -tag -width /etc/examples/man.conf -compact
|
|||
|
+.It Pa /etc/man.conf
|
|||
|
+.El
|
|||
|
.Sh EXAMPLES
|
|||
|
The following configuration file reproduces the defaults:
|
|||
|
installing it is equivalent to not having a
|
|||
|
--- a/man_html.c
|
|||
|
+++ b/man_html.c
|
|||
|
@@ -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;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
--- a/man_term.c
|
|||
|
+++ b/man_term.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: man_term.c,v 1.228 2019/01/05 21:18:26 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2010-2015, 2017-2020 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
|
|||
|
@@ -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 rof
|
|||
|
{
|
|||
|
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 rof
|
|||
|
|
|||
|
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 st
|
|||
|
}
|
|||
|
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 = TAG_STRONG;
|
|||
|
+ for (;;) {
|
|||
|
+ switch (*cp) {
|
|||
|
+ case ' ':
|
|||
|
+ case '\t':
|
|||
|
+ prio = TAG_WEAK;
|
|||
|
+ /* 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;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
+}
|
|||
|
--- a/man_validate.c
|
|||
|
+++ b/man_validate.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: man_validate.c,v 1.146 2018/12/31 10:04:39 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2010, 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2010, 2012-2020 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
|
|||
|
@@ -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(NULL, NULL);
|
|||
|
}
|
|||
|
|
|||
|
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,18 +399,12 @@ 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 (man->quick && n != NULL)
|
|||
|
man->meta.date = mandoc_strdup("");
|
|||
|
- mandoc_msg(MANDOCERR_DATE_MISSING,
|
|||
|
- n ? n->line : nb->line,
|
|||
|
- n ? n->pos : nb->pos, "TH");
|
|||
|
- }
|
|||
|
+ else
|
|||
|
+ man->meta.date = mandoc_normdate(n, nb);
|
|||
|
|
|||
|
/* TITLE MSEC DATE ->OS<- VOL */
|
|||
|
|
|||
|
--- a/mandoc.1
|
|||
|
+++ b/mandoc.1
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
.\" $Id: mandoc.1,v 1.237 2019/02/23 18:53:54 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
|
|||
|
@@ -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
|
|||
|
@@ -1066,7 +1073,7 @@ macro lacks the mandatory section argume
|
|||
|
The section number in a
|
|||
|
.Ic \&Dt
|
|||
|
line is invalid, but still used.
|
|||
|
-.It Sy "missing date, using today's date"
|
|||
|
+.It Sy "missing date, using \(dq\(dq"
|
|||
|
.Pq mdoc, man
|
|||
|
The document was parsed as
|
|||
|
.Xr mdoc 7
|
|||
|
@@ -1699,9 +1706,12 @@ The meaning of blank input lines is only
|
|||
|
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 ,
|
|||
|
--- a/mandoc.c
|
|||
|
+++ b/mandoc.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: mandoc.c,v 1.114 2018/12/30 00:49:55 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2011-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2011-2015, 2017-2020 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
|
|||
|
@@ -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,46 +532,63 @@ time2a(time_t t)
|
|||
|
|
|||
|
fail:
|
|||
|
free(buf);
|
|||
|
- return NULL;
|
|||
|
+ return mandoc_strdup("");
|
|||
|
}
|
|||
|
|
|||
|
char *
|
|||
|
-mandoc_normdate(struct roff_man *man, char *in, int ln, int pos)
|
|||
|
+mandoc_normdate(struct roff_node *nch, struct roff_node *nbl)
|
|||
|
{
|
|||
|
char *cp;
|
|||
|
time_t t;
|
|||
|
|
|||
|
- /* No date specified: use today's date. */
|
|||
|
+ /* No date specified. */
|
|||
|
|
|||
|
- if (in == NULL || *in == '\0' || strcmp(in, "$" "Mdocdate$") == 0) {
|
|||
|
- mandoc_msg(MANDOCERR_DATE_MISSING, ln, pos, NULL);
|
|||
|
- return time2a(time(NULL));
|
|||
|
+ if (nch == NULL) {
|
|||
|
+ if (nbl == NULL)
|
|||
|
+ mandoc_msg(MANDOCERR_DATE_MISSING, 0, 0, NULL);
|
|||
|
+ else
|
|||
|
+ mandoc_msg(MANDOCERR_DATE_MISSING, nbl->line,
|
|||
|
+ nbl->pos, "%s", roff_name[nbl->tok]);
|
|||
|
+ return mandoc_strdup("");
|
|||
|
}
|
|||
|
+ if (*nch->string == '\0') {
|
|||
|
+ mandoc_msg(MANDOCERR_DATE_MISSING, nch->line,
|
|||
|
+ nch->pos, "%s", roff_name[nbl->tok]);
|
|||
|
+ return mandoc_strdup("");
|
|||
|
+ }
|
|||
|
+ if (strcmp(nch->string, "$" "Mdocdate$") == 0)
|
|||
|
+ return time2a(time(NULL));
|
|||
|
|
|||
|
/* Valid mdoc(7) date format. */
|
|||
|
|
|||
|
- if (a2time(&t, "$" "Mdocdate: %b %d %Y $", in) ||
|
|||
|
- a2time(&t, "%b %d, %Y", in)) {
|
|||
|
+ if (a2time(&t, "$" "Mdocdate: %b %d %Y $", nch->string) ||
|
|||
|
+ a2time(&t, "%b %d, %Y", nch->string)) {
|
|||
|
cp = time2a(t);
|
|||
|
if (t > time(NULL) + 86400)
|
|||
|
- mandoc_msg(MANDOCERR_DATE_FUTURE, ln, pos, "%s", cp);
|
|||
|
- else if (*in != '$' && strcmp(in, cp) != 0)
|
|||
|
- mandoc_msg(MANDOCERR_DATE_NORM, ln, pos, "%s", cp);
|
|||
|
+ mandoc_msg(MANDOCERR_DATE_FUTURE, nch->line,
|
|||
|
+ nch->pos, "%s %s", roff_name[nbl->tok], cp);
|
|||
|
+ else if (*nch->string != '$' &&
|
|||
|
+ strcmp(nch->string, cp) != 0)
|
|||
|
+ mandoc_msg(MANDOCERR_DATE_NORM, nch->line,
|
|||
|
+ nch->pos, "%s %s", roff_name[nbl->tok], cp);
|
|||
|
return cp;
|
|||
|
}
|
|||
|
|
|||
|
/* In man(7), do not warn about the legacy format. */
|
|||
|
|
|||
|
- if (a2time(&t, "%Y-%m-%d", in) == 0)
|
|||
|
- mandoc_msg(MANDOCERR_DATE_BAD, ln, pos, "%s", in);
|
|||
|
+ if (a2time(&t, "%Y-%m-%d", nch->string) == 0)
|
|||
|
+ mandoc_msg(MANDOCERR_DATE_BAD, nch->line, nch->pos,
|
|||
|
+ "%s %s", roff_name[nbl->tok], nch->string);
|
|||
|
else if (t > time(NULL) + 86400)
|
|||
|
- mandoc_msg(MANDOCERR_DATE_FUTURE, ln, pos, "%s", in);
|
|||
|
- else if (man->meta.macroset == MACROSET_MDOC)
|
|||
|
- mandoc_msg(MANDOCERR_DATE_LEGACY, ln, pos, "Dd %s", in);
|
|||
|
+ mandoc_msg(MANDOCERR_DATE_FUTURE, nch->line, nch->pos,
|
|||
|
+ "%s %s", roff_name[nbl->tok], nch->string);
|
|||
|
+ else if (nbl->tok == MDOC_Dd)
|
|||
|
+ mandoc_msg(MANDOCERR_DATE_LEGACY, nch->line, nch->pos,
|
|||
|
+ "Dd %s", nch->string);
|
|||
|
|
|||
|
/* Use any non-mdoc(7) date verbatim. */
|
|||
|
|
|||
|
- return mandoc_strdup(in);
|
|||
|
+ return mandoc_strdup(nch->string);
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
--- a/mandoc.css
|
|||
|
+++ b/mandoc.css
|
|||
|
@@ -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::befor
|
|||
|
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; }
|
|||
|
+}
|
|||
|
--- a/mandoc.h
|
|||
|
+++ b/mandoc.h
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: mandoc.h,v 1.262 2018/12/16 00:17:02 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2012-2020 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
|
|||
|
@@ -83,7 +83,7 @@ enum mandocerr {
|
|||
|
MANDOCERR_TH_NOTITLE, /* missing manual title, using "": [macro] */
|
|||
|
MANDOCERR_MSEC_MISSING, /* missing manual section, using "": macro */
|
|||
|
MANDOCERR_MSEC_BAD, /* unknown manual section: Dt ... section */
|
|||
|
- MANDOCERR_DATE_MISSING, /* missing date, using today's date */
|
|||
|
+ MANDOCERR_DATE_MISSING, /* missing date, using "": [macro] */
|
|||
|
MANDOCERR_DATE_BAD, /* cannot parse date, using it verbatim: date */
|
|||
|
MANDOCERR_DATE_FUTURE, /* date in the future, using it anyway: date */
|
|||
|
MANDOCERR_OS_MISSING, /* missing Os macro, using "" */
|
|||
|
@@ -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? */
|
|||
|
@@ -224,6 +223,7 @@ enum mandocerr {
|
|||
|
MANDOCERR_SHIFT, /* excessive shift: ..., but max is ... */
|
|||
|
MANDOCERR_SO_PATH, /* NOT IMPLEMENTED: .so with absolute path or ".." */
|
|||
|
MANDOCERR_SO_FAIL, /* .so request failed */
|
|||
|
+ MANDOCERR_TG_SPC, /* skipping tag containing whitespace: tag */
|
|||
|
MANDOCERR_ARG_SKIP, /* skipping all arguments: macro args */
|
|||
|
MANDOCERR_ARG_EXCESS, /* skipping excess arguments: macro ... args */
|
|||
|
MANDOCERR_DIVZERO, /* divide by zero */
|
|||
|
@@ -242,6 +242,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 +310,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);
|
|||
|
--- a/mandoc_char.7
|
|||
|
+++ b/mandoc_char.7
|
|||
|
@@ -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
|
|||
|
--- a/mandoc_headers.3
|
|||
|
+++ b/mandoc_headers.3
|
|||
|
@@ -1,3 +1,19 @@
|
|||
|
+.\" $Id$
|
|||
|
+.\"
|
|||
|
+.\" 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: December 30 2018 $
|
|||
|
.Dt MANDOC_HEADERS 3
|
|||
|
.Os
|
|||
|
@@ -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 t
|
|||
|
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,22 +621,26 @@ 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
|
|||
|
for
|
|||
|
-.Vt size_t .
|
|||
|
+.Vt size_t
|
|||
|
+and
|
|||
|
+.In limits.h
|
|||
|
+for
|
|||
|
+.Dv INT_MAX .
|
|||
|
.Pp
|
|||
|
Provides an interface to generate
|
|||
|
.Xr ctags 1
|
|||
|
@@ -631,7 +654,7 @@ Provides the top level steering function
|
|||
|
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 +694,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
|
|||
|
--- 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 $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2014,2015,2016,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
*
|
|||
|
* Permission to use, copy, modify, and distribute this software for any
|
|||
|
* purpose with or without fee is hereby granted, provided that the above
|
|||
|
@@ -29,8 +29,8 @@ static const enum mandocerr lowest_type[
|
|||
|
MANDOCERR_WARNING,
|
|||
|
MANDOCERR_ERROR,
|
|||
|
MANDOCERR_UNSUPP,
|
|||
|
- MANDOCERR_MAX,
|
|||
|
- MANDOCERR_MAX
|
|||
|
+ MANDOCERR_BADARG,
|
|||
|
+ MANDOCERR_SYSERR
|
|||
|
};
|
|||
|
|
|||
|
static const char *const level_name[MANDOCLEVEL_MAX] = {
|
|||
|
@@ -83,7 +83,7 @@ static const char *const type_message[MA
|
|||
|
"missing manual title, using \"\"",
|
|||
|
"missing manual section, using \"\"",
|
|||
|
"unknown manual section",
|
|||
|
- "missing date, using today's date",
|
|||
|
+ "missing date, using \"\"",
|
|||
|
"cannot parse date, using it verbatim",
|
|||
|
"date in the future, using it anyway",
|
|||
|
"missing Os macro, using \"\"",
|
|||
|
@@ -193,7 +193,6 @@ static const char *const type_message[MA
|
|||
|
"data block open at end of tbl",
|
|||
|
|
|||
|
/* related to document structure and macros */
|
|||
|
- NULL,
|
|||
|
"duplicate prologue macro",
|
|||
|
"skipping late title macro",
|
|||
|
"input stack limit exceeded, infinite loop?",
|
|||
|
@@ -224,6 +223,7 @@ static const char *const type_message[MA
|
|||
|
"excessive shift",
|
|||
|
"NOT IMPLEMENTED: .so with absolute path or \"..\"",
|
|||
|
".so request failed",
|
|||
|
+ "skipping tag containing whitespace",
|
|||
|
"skipping all arguments",
|
|||
|
"skipping excess arguments",
|
|||
|
"divide by zero",
|
|||
|
@@ -240,11 +240,40 @@ static const char *const type_message[MA
|
|||
|
"eqn delim option in tbl",
|
|||
|
"unsupported tbl layout modifier",
|
|||
|
"ignoring macro in table",
|
|||
|
+
|
|||
|
+ /* bad command line arguments */
|
|||
|
+ NULL,
|
|||
|
+ "bad command line argument",
|
|||
|
+ "duplicate command line argument",
|
|||
|
+ "option has a superfluous value",
|
|||
|
+ "missing option value",
|
|||
|
+ "bad option value",
|
|||
|
+ "duplicate option value",
|
|||
|
+ "no such tag",
|
|||
|
+
|
|||
|
+ /* system errors */
|
|||
|
+ NULL,
|
|||
|
+ "dup",
|
|||
|
+ "exec",
|
|||
|
+ "fdopen",
|
|||
|
+ "fflush",
|
|||
|
+ "fork",
|
|||
|
+ "fstat",
|
|||
|
+ "getline",
|
|||
|
+ "glob",
|
|||
|
+ "gzclose",
|
|||
|
+ "gzdopen",
|
|||
|
+ "mkstemp",
|
|||
|
+ "open",
|
|||
|
+ "pledge",
|
|||
|
+ "read",
|
|||
|
+ "wait",
|
|||
|
+ "write",
|
|||
|
};
|
|||
|
|
|||
|
static FILE *fileptr = NULL;
|
|||
|
static const char *filename = NULL;
|
|||
|
-static enum mandocerr min_type = MANDOCERR_MAX;
|
|||
|
+static enum mandocerr min_type = MANDOCERR_BADARG;
|
|||
|
static enum mandoclevel rc = MANDOCLEVEL_OK;
|
|||
|
|
|||
|
|
|||
|
@@ -297,10 +326,10 @@ mandoc_msg(enum mandocerr t, int line, i
|
|||
|
va_list ap;
|
|||
|
enum mandoclevel level;
|
|||
|
|
|||
|
- if (t < min_type && t != MANDOCERR_FILE)
|
|||
|
+ if (t < min_type)
|
|||
|
return;
|
|||
|
|
|||
|
- level = MANDOCLEVEL_UNSUPP;
|
|||
|
+ level = MANDOCLEVEL_SYSERR;
|
|||
|
while (t < lowest_type[level])
|
|||
|
level--;
|
|||
|
mandoc_msg_setrc(level);
|
|||
|
@@ -327,3 +356,12 @@ mandoc_msg(enum mandocerr t, int line, i
|
|||
|
}
|
|||
|
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]);
|
|||
|
+}
|
|||
|
--- a/mandoc_parse.h
|
|||
|
+++ b/mandoc_parse.h
|
|||
|
@@ -29,6 +29,7 @@
|
|||
|
#define MPARSE_UTF8 (1 << 4) /* accept UTF-8 input */
|
|||
|
#define MPARSE_LATIN1 (1 << 5) /* accept ISO-LATIN-1 input */
|
|||
|
#define MPARSE_VALIDATE (1 << 6) /* call validation functions */
|
|||
|
+#define MPARSE_COMMENT (1 << 7) /* save comments in the tree */
|
|||
|
|
|||
|
|
|||
|
struct roff_meta;
|
|||
|
--- a/mandocdb.c
|
|||
|
+++ b/mandocdb.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: mandocdb.c,v 1.262 2018/12/30 00:49:55 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2011-2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2011-2020 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
* Copyright (c) 2016 Ed Maste <emaste@freebsd.org>
|
|||
|
*
|
|||
|
* Permission to use, copy, modify, and distribute this software for any
|
|||
|
@@ -179,6 +179,7 @@ static int write_utf8; /* write UTF-8
|
|||
|
static int exitcode; /* to be returned by main */
|
|||
|
static enum op op; /* operational mode */
|
|||
|
static char basedir[PATH_MAX]; /* current base directory */
|
|||
|
+static size_t basedir_len; /* strlen(basedir) */
|
|||
|
static struct mpage *mpage_head; /* list of distinct manual pages */
|
|||
|
static struct ohash mpages; /* table of distinct manual pages */
|
|||
|
static struct ohash mlinks; /* table of directory entries */
|
|||
|
@@ -342,7 +343,7 @@ mandocdb(int argc, char *argv[])
|
|||
|
* clobber each other.
|
|||
|
*/
|
|||
|
#define CHECKOP(_op, _ch) do \
|
|||
|
- if (OP_DEFAULT != (_op)) { \
|
|||
|
+ if ((_op) != OP_DEFAULT) { \
|
|||
|
warnx("-%c: Conflicting option", (_ch)); \
|
|||
|
goto usage; \
|
|||
|
} while (/*CONSTCOND*/0)
|
|||
|
@@ -351,7 +352,7 @@ mandocdb(int argc, char *argv[])
|
|||
|
path_arg = NULL;
|
|||
|
op = OP_DEFAULT;
|
|||
|
|
|||
|
- while (-1 != (ch = getopt(argc, argv, "aC:Dd:npQT:tu:v")))
|
|||
|
+ while ((ch = getopt(argc, argv, "aC:Dd:npQT:tu:v")) != -1)
|
|||
|
switch (ch) {
|
|||
|
case 'a':
|
|||
|
use_all = 1;
|
|||
|
@@ -379,7 +380,7 @@ mandocdb(int argc, char *argv[])
|
|||
|
mparse_options |= MPARSE_QUICK;
|
|||
|
break;
|
|||
|
case 'T':
|
|||
|
- if (strcmp(optarg, "utf8")) {
|
|||
|
+ if (strcmp(optarg, "utf8") != 0) {
|
|||
|
warnx("-T%s: Unsupported output format",
|
|||
|
optarg);
|
|||
|
goto usage;
|
|||
|
@@ -416,7 +417,7 @@ mandocdb(int argc, char *argv[])
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
- if (OP_CONFFILE == op && argc > 0) {
|
|||
|
+ if (op == OP_CONFFILE && argc > 0) {
|
|||
|
warnx("-C: Too many arguments");
|
|||
|
goto usage;
|
|||
|
}
|
|||
|
@@ -427,13 +428,13 @@ mandocdb(int argc, char *argv[])
|
|||
|
mandoc_ohash_init(&mpages, 6, offsetof(struct mpage, inodev));
|
|||
|
mandoc_ohash_init(&mlinks, 6, offsetof(struct mlink, file));
|
|||
|
|
|||
|
- if (OP_UPDATE == op || OP_DELETE == op || OP_TEST == op) {
|
|||
|
+ if (op == OP_UPDATE || op == OP_DELETE || op == OP_TEST) {
|
|||
|
|
|||
|
/*
|
|||
|
* Most of these deal with a specific directory.
|
|||
|
* Jump into that directory first.
|
|||
|
*/
|
|||
|
- if (OP_TEST != op && 0 == set_basedir(path_arg, 1))
|
|||
|
+ if (op != OP_TEST && set_basedir(path_arg, 1) == 0)
|
|||
|
goto out;
|
|||
|
|
|||
|
dba = nodb ? dba_new(128) : dba_read(MANDOC_DB);
|
|||
|
@@ -454,11 +455,11 @@ mandocdb(int argc, char *argv[])
|
|||
|
" from scratch", strerror(errno));
|
|||
|
exitcode = (int)MANDOCLEVEL_OK;
|
|||
|
op = OP_DEFAULT;
|
|||
|
- if (0 == treescan())
|
|||
|
+ if (treescan() == 0)
|
|||
|
goto out;
|
|||
|
dba = dba_new(128);
|
|||
|
}
|
|||
|
- if (OP_DELETE != op)
|
|||
|
+ if (op != OP_DELETE)
|
|||
|
mpages_merge(dba, mp);
|
|||
|
if (nodb == 0)
|
|||
|
dbwrite(dba);
|
|||
|
@@ -492,7 +493,7 @@ mandocdb(int argc, char *argv[])
|
|||
|
sz = strlen(conf.manpath.paths[j]);
|
|||
|
if (sz && conf.manpath.paths[j][sz - 1] == '/')
|
|||
|
conf.manpath.paths[j][--sz] = '\0';
|
|||
|
- if (0 == sz)
|
|||
|
+ if (sz == 0)
|
|||
|
continue;
|
|||
|
|
|||
|
if (j) {
|
|||
|
@@ -502,9 +503,9 @@ mandocdb(int argc, char *argv[])
|
|||
|
offsetof(struct mlink, file));
|
|||
|
}
|
|||
|
|
|||
|
- if ( ! set_basedir(conf.manpath.paths[j], argc > 0))
|
|||
|
+ if (set_basedir(conf.manpath.paths[j], argc > 0) == 0)
|
|||
|
continue;
|
|||
|
- if (0 == treescan())
|
|||
|
+ if (treescan() == 0)
|
|||
|
continue;
|
|||
|
dba = dba_new(128);
|
|||
|
mpages_merge(dba, mp);
|
|||
|
@@ -608,9 +609,9 @@ treescan(void)
|
|||
|
say(path, "&realpath");
|
|||
|
continue;
|
|||
|
}
|
|||
|
- if (strstr(buf, basedir) != buf
|
|||
|
+ if (strncmp(buf, basedir, basedir_len) != 0
|
|||
|
#ifdef HOMEBREWDIR
|
|||
|
- && strstr(buf, HOMEBREWDIR) != buf
|
|||
|
+ && strncmp(buf, HOMEBREWDIR, strlen(HOMEBREWDIR))
|
|||
|
#endif
|
|||
|
) {
|
|||
|
if (warnings) say("",
|
|||
|
@@ -777,17 +778,17 @@ treescan(void)
|
|||
|
* See treescan() for the fts(3) version of this.
|
|||
|
*/
|
|||
|
static void
|
|||
|
-filescan(const char *file)
|
|||
|
+filescan(const char *infile)
|
|||
|
{
|
|||
|
- char buf[PATH_MAX];
|
|||
|
struct stat st;
|
|||
|
struct mlink *mlink;
|
|||
|
- char *p, *start;
|
|||
|
+ char *linkfile, *p, *realdir, *start, *usefile;
|
|||
|
+ size_t realdir_len;
|
|||
|
|
|||
|
assert(use_all);
|
|||
|
|
|||
|
- if (0 == strncmp(file, "./", 2))
|
|||
|
- file += 2;
|
|||
|
+ if (strncmp(infile, "./", 2) == 0)
|
|||
|
+ infile += 2;
|
|||
|
|
|||
|
/*
|
|||
|
* We have to do lstat(2) before realpath(3) loses
|
|||
|
@@ -796,13 +797,13 @@ filescan(const char *file)
|
|||
|
* we want to use the orginal file name, while for
|
|||
|
* regular files, we want to use the real path.
|
|||
|
*/
|
|||
|
- if (-1 == lstat(file, &st)) {
|
|||
|
+ if (lstat(infile, &st) == -1) {
|
|||
|
exitcode = (int)MANDOCLEVEL_BADARG;
|
|||
|
- say(file, "&lstat");
|
|||
|
+ say(infile, "&lstat");
|
|||
|
return;
|
|||
|
- } else if (0 == ((S_IFREG | S_IFLNK) & st.st_mode)) {
|
|||
|
+ } else if (S_ISREG(st.st_mode) == 0 && S_ISLNK(st.st_mode) == 0) {
|
|||
|
exitcode = (int)MANDOCLEVEL_BADARG;
|
|||
|
- say(file, "Not a regular file");
|
|||
|
+ say(infile, "Not a regular file");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
@@ -810,23 +811,24 @@ filescan(const char *file)
|
|||
|
* We have to resolve the file name to the real path
|
|||
|
* in any case for the base directory check.
|
|||
|
*/
|
|||
|
- if (NULL == realpath(file, buf)) {
|
|||
|
+ if ((usefile = realpath(infile, NULL)) == NULL) {
|
|||
|
exitcode = (int)MANDOCLEVEL_BADARG;
|
|||
|
- say(file, "&realpath");
|
|||
|
+ say(infile, "&realpath");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
- if (OP_TEST == op)
|
|||
|
- start = buf;
|
|||
|
- else if (strstr(buf, basedir) == buf)
|
|||
|
- start = buf + strlen(basedir);
|
|||
|
+ if (op == OP_TEST)
|
|||
|
+ start = usefile;
|
|||
|
+ else if (strncmp(usefile, basedir, basedir_len) == 0)
|
|||
|
+ start = usefile + basedir_len;
|
|||
|
#ifdef HOMEBREWDIR
|
|||
|
- else if (strstr(buf, HOMEBREWDIR) == buf)
|
|||
|
- start = buf;
|
|||
|
+ else if (strncmp(usefile, HOMEBREWDIR, strlen(HOMEBREWDIR)) == 0)
|
|||
|
+ start = usefile;
|
|||
|
#endif
|
|||
|
else {
|
|||
|
exitcode = (int)MANDOCLEVEL_BADARG;
|
|||
|
- say("", "%s: outside base directory", buf);
|
|||
|
+ say("", "%s: outside base directory", infile);
|
|||
|
+ free(usefile);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
@@ -834,25 +836,72 @@ filescan(const char *file)
|
|||
|
* Now we are sure the file is inside our tree.
|
|||
|
* If it is a symbolic link, ignore the real path
|
|||
|
* and use the original name.
|
|||
|
- * This implies passing stuff like "cat1/../man1/foo.1"
|
|||
|
- * on the command line won't work. So don't do that.
|
|||
|
- * Note the stat(2) can still fail if the link target
|
|||
|
- * doesn't exist.
|
|||
|
*/
|
|||
|
- if (S_IFLNK & st.st_mode) {
|
|||
|
- if (-1 == stat(buf, &st)) {
|
|||
|
+ do {
|
|||
|
+ if (S_ISLNK(st.st_mode) == 0)
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ /*
|
|||
|
+ * Some implementations of realpath(3) may succeed
|
|||
|
+ * even if the target of the link does not exist,
|
|||
|
+ * so check again for extra safety.
|
|||
|
+ */
|
|||
|
+ if (stat(usefile, &st) == -1) {
|
|||
|
exitcode = (int)MANDOCLEVEL_BADARG;
|
|||
|
- say(file, "&stat");
|
|||
|
+ say(infile, "&stat");
|
|||
|
+ free(usefile);
|
|||
|
return;
|
|||
|
}
|
|||
|
- if (strlcpy(buf, file, sizeof(buf)) >= sizeof(buf)) {
|
|||
|
- say(file, "Filename too long");
|
|||
|
- return;
|
|||
|
+ linkfile = mandoc_strdup(infile);
|
|||
|
+ if (op == OP_TEST) {
|
|||
|
+ free(usefile);
|
|||
|
+ start = usefile = linkfile;
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ if (strncmp(infile, basedir, basedir_len) == 0) {
|
|||
|
+ free(usefile);
|
|||
|
+ usefile = linkfile;
|
|||
|
+ start = usefile + basedir_len;
|
|||
|
+ break;
|
|||
|
}
|
|||
|
- start = buf;
|
|||
|
- if (OP_TEST != op && strstr(buf, basedir) == buf)
|
|||
|
- start += strlen(basedir);
|
|||
|
- }
|
|||
|
+
|
|||
|
+ /*
|
|||
|
+ * This symbolic link points into the basedir
|
|||
|
+ * from the outside. Let's see whether any of
|
|||
|
+ * the parent directories resolve to the basedir.
|
|||
|
+ */
|
|||
|
+ p = strchr(linkfile, '\0');
|
|||
|
+ do {
|
|||
|
+ while (*--p != '/')
|
|||
|
+ continue;
|
|||
|
+ *p = '\0';
|
|||
|
+ if ((realdir = realpath(linkfile, NULL)) == NULL) {
|
|||
|
+ exitcode = (int)MANDOCLEVEL_BADARG;
|
|||
|
+ say(infile, "&realpath");
|
|||
|
+ free(linkfile);
|
|||
|
+ free(usefile);
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
+ realdir_len = strlen(realdir) + 1;
|
|||
|
+ free(realdir);
|
|||
|
+ *p = '/';
|
|||
|
+ } while (realdir_len > basedir_len);
|
|||
|
+
|
|||
|
+ /*
|
|||
|
+ * If one of the directories resolves to the basedir,
|
|||
|
+ * use the rest of the original name.
|
|||
|
+ * Otherwise, the best we can do
|
|||
|
+ * is to use the filename pointed to.
|
|||
|
+ */
|
|||
|
+ if (realdir_len == basedir_len) {
|
|||
|
+ free(usefile);
|
|||
|
+ usefile = linkfile;
|
|||
|
+ start = p + 1;
|
|||
|
+ } else {
|
|||
|
+ free(linkfile);
|
|||
|
+ start = usefile + basedir_len;
|
|||
|
+ }
|
|||
|
+ } while (/* CONSTCOND */ 0);
|
|||
|
|
|||
|
mlink = mandoc_calloc(1, sizeof(struct mlink));
|
|||
|
mlink->dform = FORM_NONE;
|
|||
|
@@ -860,6 +909,7 @@ filescan(const char *file)
|
|||
|
sizeof(mlink->file)) {
|
|||
|
say(start, "Filename too long");
|
|||
|
free(mlink);
|
|||
|
+ free(usefile);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
@@ -868,13 +918,13 @@ filescan(const char *file)
|
|||
|
* but outside our tree, guess the base directory.
|
|||
|
*/
|
|||
|
|
|||
|
- if (op == OP_TEST || (start == buf && *start == '/')) {
|
|||
|
- if (strncmp(buf, "man/", 4) == 0)
|
|||
|
- start = buf + 4;
|
|||
|
- else if ((start = strstr(buf, "/man/")) != NULL)
|
|||
|
+ if (op == OP_TEST || (start == usefile && *start == '/')) {
|
|||
|
+ if (strncmp(usefile, "man/", 4) == 0)
|
|||
|
+ start = usefile + 4;
|
|||
|
+ else if ((start = strstr(usefile, "/man/")) != NULL)
|
|||
|
start += 5;
|
|||
|
else
|
|||
|
- start = buf;
|
|||
|
+ start = usefile;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
@@ -883,18 +933,18 @@ filescan(const char *file)
|
|||
|
* If we find one of these and what's underneath is a directory,
|
|||
|
* assume it's an architecture.
|
|||
|
*/
|
|||
|
- if (NULL != (p = strchr(start, '/'))) {
|
|||
|
+ if ((p = strchr(start, '/')) != NULL) {
|
|||
|
*p++ = '\0';
|
|||
|
- if (0 == strncmp(start, "man", 3)) {
|
|||
|
+ if (strncmp(start, "man", 3) == 0) {
|
|||
|
mlink->dform = FORM_SRC;
|
|||
|
mlink->dsec = start + 3;
|
|||
|
- } else if (0 == strncmp(start, "cat", 3)) {
|
|||
|
+ } else if (strncmp(start, "cat", 3) == 0) {
|
|||
|
mlink->dform = FORM_CAT;
|
|||
|
mlink->dsec = start + 3;
|
|||
|
}
|
|||
|
|
|||
|
start = p;
|
|||
|
- if (NULL != mlink->dsec && NULL != (p = strchr(start, '/'))) {
|
|||
|
+ if (mlink->dsec != NULL && (p = strchr(start, '/')) != NULL) {
|
|||
|
*p++ = '\0';
|
|||
|
mlink->arch = start;
|
|||
|
start = p;
|
|||
|
@@ -906,10 +956,10 @@ filescan(const char *file)
|
|||
|
* Suffix of `.0' indicates a catpage, `.1-9' is a manpage.
|
|||
|
*/
|
|||
|
p = strrchr(start, '\0');
|
|||
|
- while (p-- > start && '/' != *p && '.' != *p)
|
|||
|
- /* Loop. */ ;
|
|||
|
+ while (p-- > start && *p != '/' && *p != '.')
|
|||
|
+ continue;
|
|||
|
|
|||
|
- if ('.' == *p) {
|
|||
|
+ if (*p == '.') {
|
|||
|
*p++ = '\0';
|
|||
|
mlink->fsec = p;
|
|||
|
}
|
|||
|
@@ -919,11 +969,12 @@ filescan(const char *file)
|
|||
|
* Use the filename portion of the path.
|
|||
|
*/
|
|||
|
mlink->name = start;
|
|||
|
- if (NULL != (p = strrchr(start, '/'))) {
|
|||
|
+ if ((p = strrchr(start, '/')) != NULL) {
|
|||
|
mlink->name = p + 1;
|
|||
|
*p = '\0';
|
|||
|
}
|
|||
|
mlink_add(mlink, &st);
|
|||
|
+ free(usefile);
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
@@ -1186,9 +1237,11 @@ mpages_merge(struct dba *dba, struct mpa
|
|||
|
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 +1261,15 @@ mpages_merge(struct dba *dba, struct mpa
|
|||
|
}
|
|||
|
|
|||
|
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
|
|||
|
@@ -2245,7 +2301,6 @@ set_basedir(const char *targetdir, int r
|
|||
|
static char startdir[PATH_MAX];
|
|||
|
static int getcwd_status; /* 1 = ok, 2 = failure */
|
|||
|
static int chdir_status; /* 1 = changed directory */
|
|||
|
- char *cp;
|
|||
|
|
|||
|
/*
|
|||
|
* Remember the original working directory, if possible.
|
|||
|
@@ -2254,8 +2309,8 @@ set_basedir(const char *targetdir, int r
|
|||
|
* Do not error out if the current directory is not
|
|||
|
* searchable: Maybe it won't be needed after all.
|
|||
|
*/
|
|||
|
- if (0 == getcwd_status) {
|
|||
|
- if (NULL == getcwd(startdir, sizeof(startdir))) {
|
|||
|
+ if (getcwd_status == 0) {
|
|||
|
+ if (getcwd(startdir, sizeof(startdir)) == NULL) {
|
|||
|
getcwd_status = 2;
|
|||
|
(void)strlcpy(startdir, strerror(errno),
|
|||
|
sizeof(startdir));
|
|||
|
@@ -2268,19 +2323,20 @@ set_basedir(const char *targetdir, int r
|
|||
|
* Do not use it any longer, not even for messages.
|
|||
|
*/
|
|||
|
*basedir = '\0';
|
|||
|
+ basedir_len = 0;
|
|||
|
|
|||
|
/*
|
|||
|
* If and only if the directory was changed earlier and
|
|||
|
* the next directory to process is given as a relative path,
|
|||
|
* first go back, or bail out if that is impossible.
|
|||
|
*/
|
|||
|
- if (chdir_status && '/' != *targetdir) {
|
|||
|
- if (2 == getcwd_status) {
|
|||
|
+ if (chdir_status && *targetdir != '/') {
|
|||
|
+ if (getcwd_status == 2) {
|
|||
|
exitcode = (int)MANDOCLEVEL_SYSERR;
|
|||
|
say("", "getcwd: %s", startdir);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
- if (-1 == chdir(startdir)) {
|
|||
|
+ if (chdir(startdir) == -1) {
|
|||
|
exitcode = (int)MANDOCLEVEL_SYSERR;
|
|||
|
say("", "&chdir %s", startdir);
|
|||
|
return 0;
|
|||
|
@@ -2292,29 +2348,33 @@ set_basedir(const char *targetdir, int r
|
|||
|
* pathname and append a trailing slash, such that
|
|||
|
* we can reliably check whether files are inside.
|
|||
|
*/
|
|||
|
- if (NULL == realpath(targetdir, basedir)) {
|
|||
|
+ if (realpath(targetdir, basedir) == NULL) {
|
|||
|
if (report_baddir || errno != ENOENT) {
|
|||
|
exitcode = (int)MANDOCLEVEL_BADARG;
|
|||
|
say("", "&%s: realpath", targetdir);
|
|||
|
}
|
|||
|
+ *basedir = '\0';
|
|||
|
return 0;
|
|||
|
- } else if (-1 == chdir(basedir)) {
|
|||
|
+ } else if (chdir(basedir) == -1) {
|
|||
|
if (report_baddir || errno != ENOENT) {
|
|||
|
exitcode = (int)MANDOCLEVEL_BADARG;
|
|||
|
say("", "&chdir");
|
|||
|
}
|
|||
|
+ *basedir = '\0';
|
|||
|
return 0;
|
|||
|
}
|
|||
|
chdir_status = 1;
|
|||
|
- cp = strchr(basedir, '\0');
|
|||
|
- if ('/' != cp[-1]) {
|
|||
|
- if (cp - basedir >= PATH_MAX - 1) {
|
|||
|
+ basedir_len = strlen(basedir);
|
|||
|
+ if (basedir[basedir_len - 1] != '/') {
|
|||
|
+ if (basedir_len >= PATH_MAX - 1) {
|
|||
|
exitcode = (int)MANDOCLEVEL_SYSERR;
|
|||
|
say("", "Filename too long");
|
|||
|
+ *basedir = '\0';
|
|||
|
+ basedir_len = 0;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
- *cp++ = '/';
|
|||
|
- *cp = '\0';
|
|||
|
+ basedir[basedir_len++] = '/';
|
|||
|
+ basedir[basedir_len] = '\0';
|
|||
|
}
|
|||
|
return 1;
|
|||
|
}
|
|||
|
@@ -2325,15 +2385,15 @@ say(const char *file, const char *format
|
|||
|
va_list ap;
|
|||
|
int use_errno;
|
|||
|
|
|||
|
- if ('\0' != *basedir)
|
|||
|
+ if (*basedir != '\0')
|
|||
|
fprintf(stderr, "%s", basedir);
|
|||
|
- if ('\0' != *basedir && '\0' != *file)
|
|||
|
+ if (*basedir != '\0' && *file != '\0')
|
|||
|
fputc('/', stderr);
|
|||
|
- if ('\0' != *file)
|
|||
|
+ if (*file != '\0')
|
|||
|
fprintf(stderr, "%s", file);
|
|||
|
|
|||
|
use_errno = 1;
|
|||
|
- if (NULL != format) {
|
|||
|
+ if (format != NULL) {
|
|||
|
switch (*format) {
|
|||
|
case '&':
|
|||
|
format++;
|
|||
|
@@ -2346,15 +2406,15 @@ say(const char *file, const char *format
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
- if (NULL != format) {
|
|||
|
- if ('\0' != *basedir || '\0' != *file)
|
|||
|
+ if (format != NULL) {
|
|||
|
+ if (*basedir != '\0' || *file != '\0')
|
|||
|
fputs(": ", stderr);
|
|||
|
va_start(ap, format);
|
|||
|
vfprintf(stderr, format, ap);
|
|||
|
va_end(ap);
|
|||
|
}
|
|||
|
if (use_errno) {
|
|||
|
- if ('\0' != *basedir || '\0' != *file || NULL != format)
|
|||
|
+ if (*basedir != '\0' || *file != '\0' || format != NULL)
|
|||
|
fputs(": ", stderr);
|
|||
|
perror(NULL);
|
|||
|
} else
|
|||
|
--- a/manpath.c
|
|||
|
+++ b/manpath.c
|
|||
|
@@ -1,6 +1,6 @@
|
|||
|
/* $Id: manpath.c,v 1.37 2018/11/22 11:30:23 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, cons
|
|||
|
char *insert;
|
|||
|
|
|||
|
/* Always prepend -m. */
|
|||
|
- manpath_parseline(&conf->manpath, auxp, 1);
|
|||
|
+ manpath_parseline(&conf->manpath, auxp, 'm');
|
|||
|
|
|||
|
/* If -M is given, it overrides everything else. */
|
|||
|
if (NULL != defp) {
|
|||
|
- manpath_parseline(&conf->manpath, defp, 1);
|
|||
|
+ manpath_parseline(&conf->manpath, defp, 'M');
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
@@ -66,13 +65,13 @@ manconf_parse(struct manconf *conf, cons
|
|||
|
/* Prepend man.conf(5) to MANPATH. */
|
|||
|
if (':' == defp[0]) {
|
|||
|
manconf_file(conf, file);
|
|||
|
- manpath_parseline(&conf->manpath, defp, 0);
|
|||
|
+ manpath_parseline(&conf->manpath, defp, '\0');
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/* Append man.conf(5) to MANPATH. */
|
|||
|
if (':' == defp[strlen(defp) - 1]) {
|
|||
|
- manpath_parseline(&conf->manpath, defp, 0);
|
|||
|
+ manpath_parseline(&conf->manpath, defp, '\0');
|
|||
|
manconf_file(conf, file);
|
|||
|
return;
|
|||
|
}
|
|||
|
@@ -81,28 +80,28 @@ manconf_parse(struct manconf *conf, cons
|
|||
|
insert = strstr(defp, "::");
|
|||
|
if (NULL != insert) {
|
|||
|
*insert++ = '\0';
|
|||
|
- manpath_parseline(&conf->manpath, defp, 0);
|
|||
|
+ manpath_parseline(&conf->manpath, defp, '\0');
|
|||
|
manconf_file(conf, file);
|
|||
|
- manpath_parseline(&conf->manpath, insert + 1, 0);
|
|||
|
+ manpath_parseline(&conf->manpath, insert + 1, '\0');
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/* MANPATH overrides man.conf(5) completely. */
|
|||
|
- manpath_parseline(&conf->manpath, defp, 0);
|
|||
|
+ manpath_parseline(&conf->manpath, defp, '\0');
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
manpath_base(struct manpaths *dirs)
|
|||
|
{
|
|||
|
char path_base[] = MANPATH_BASE;
|
|||
|
- manpath_parseline(dirs, path_base, 0);
|
|||
|
+ manpath_parseline(dirs, path_base, '\0');
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Parse a FULL pathname from a colon-separated list of arrays.
|
|||
|
*/
|
|||
|
static void
|
|||
|
-manpath_parseline(struct manpaths *dirs, char *path, int complain)
|
|||
|
+manpath_parseline(struct manpaths *dirs, char *path, char option)
|
|||
|
{
|
|||
|
char *dir;
|
|||
|
|
|||
|
@@ -110,7 +109,7 @@ manpath_parseline(struct manpaths *dirs,
|
|||
|
return;
|
|||
|
|
|||
|
for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
|
|||
|
- manpath_add(dirs, dir, complain);
|
|||
|
+ manpath_add(dirs, dir, option);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
@@ -118,33 +117,32 @@ manpath_parseline(struct manpaths *dirs,
|
|||
|
* Grow the array one-by-one for simplicity's sake.
|
|||
|
*/
|
|||
|
static void
|
|||
|
-manpath_add(struct manpaths *dirs, const char *dir, int complain)
|
|||
|
+manpath_add(struct manpaths *dirs, const char *dir, char option)
|
|||
|
{
|
|||
|
char buf[PATH_MAX];
|
|||
|
struct stat sb;
|
|||
|
char *cp;
|
|||
|
size_t i;
|
|||
|
|
|||
|
- if (NULL == (cp = realpath(dir, buf))) {
|
|||
|
- if (complain)
|
|||
|
- warn("manpath: %s", dir);
|
|||
|
- return;
|
|||
|
- }
|
|||
|
+ if ((cp = realpath(dir, buf)) == NULL)
|
|||
|
+ goto fail;
|
|||
|
|
|||
|
for (i = 0; i < dirs->sz; i++)
|
|||
|
- if (0 == strcmp(dirs->paths[i], dir))
|
|||
|
+ if (strcmp(dirs->paths[i], dir) == 0)
|
|||
|
return;
|
|||
|
|
|||
|
- if (stat(cp, &sb) == -1) {
|
|||
|
- if (complain)
|
|||
|
- warn("manpath: %s", dir);
|
|||
|
- return;
|
|||
|
- }
|
|||
|
+ if (stat(cp, &sb) == -1)
|
|||
|
+ goto fail;
|
|||
|
|
|||
|
dirs->paths = mandoc_reallocarray(dirs->paths,
|
|||
|
- dirs->sz + 1, sizeof(char *));
|
|||
|
-
|
|||
|
+ dirs->sz + 1, sizeof(*dirs->paths));
|
|||
|
dirs->paths[dirs->sz++] = mandoc_strdup(cp);
|
|||
|
+ return;
|
|||
|
+
|
|||
|
+fail:
|
|||
|
+ if (option != '\0')
|
|||
|
+ mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0,
|
|||
|
+ "-%c %s: %s", option, dir, strerror(errno));
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
@@ -165,7 +163,7 @@ manconf_free(struct manconf *conf)
|
|||
|
static void
|
|||
|
manconf_file(struct manconf *conf, const char *file)
|
|||
|
{
|
|||
|
- const char *const toks[] = { "manpath", "output", "_whatdb" };
|
|||
|
+ const char *const toks[] = { "manpath", "output" };
|
|||
|
char manpath_default[] = MANPATH_DEFAULT;
|
|||
|
|
|||
|
FILE *stream;
|
|||
|
@@ -202,15 +200,8 @@ manconf_file(struct manconf *conf, const
|
|||
|
}
|
|||
|
|
|||
|
switch (tok) {
|
|||
|
- case 2: /* _whatdb */
|
|||
|
- while (ep > cp && ep[-1] != '/')
|
|||
|
- ep--;
|
|||
|
- if (ep == cp)
|
|||
|
- continue;
|
|||
|
- *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 +216,7 @@ manconf_file(struct manconf *conf, const
|
|||
|
|
|||
|
out:
|
|||
|
if (*manpath_default != '\0')
|
|||
|
- manpath_parseline(&conf->manpath, manpath_default, 0);
|
|||
|
+ manpath_parseline(&conf->manpath, manpath_default, '\0');
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
@@ -235,14 +226,15 @@ manconf_output(struct manoutput *conf, c
|
|||
|
"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 +246,11 @@ manconf_output(struct manoutput *conf, c
|
|||
|
}
|
|||
|
|
|||
|
if (tok < 6 && *cp == '\0') {
|
|||
|
- warnx("-O %s=?: Missing argument value", toks[tok]);
|
|||
|
+ mandoc_msg(MANDOCERR_BADVAL_MISS, 0, 0, "-O %s=?", toks[tok]);
|
|||
|
return -1;
|
|||
|
}
|
|||
|
- if (tok > 6 && *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 +291,8 @@ manconf_output(struct manoutput *conf, c
|
|||
|
conf->indent = strtonum(cp, 0, 1000, &errstr);
|
|||
|
if (errstr == NULL)
|
|||
|
return 0;
|
|||
|
- warnx("-O indent=%s is %s", cp, errstr);
|
|||
|
+ mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0,
|
|||
|
+ "-O indent=%s is %s", cp, errstr);
|
|||
|
return -1;
|
|||
|
case 5:
|
|||
|
if (conf->width) {
|
|||
|
@@ -309,7 +302,8 @@ manconf_output(struct manoutput *conf, c
|
|||
|
conf->width = strtonum(cp, 1, 1000, &errstr);
|
|||
|
if (errstr == NULL)
|
|||
|
return 0;
|
|||
|
- warnx("-O width=%s is %s", cp, errstr);
|
|||
|
+ mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0,
|
|||
|
+ "-O width=%s is %s", cp, errstr);
|
|||
|
return -1;
|
|||
|
case 6:
|
|||
|
if (conf->tag != NULL) {
|
|||
|
@@ -331,13 +325,16 @@ manconf_output(struct manoutput *conf, c
|
|||
|
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;
|
|||
|
}
|
|||
|
--- a/mansearch.c
|
|||
|
+++ b/mansearch.c
|
|||
|
@@ -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 oha
|
|||
|
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 v
|
|||
|
|
|||
|
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. */
|
|||
|
--- a/mansearch.h
|
|||
|
+++ b/mansearch.h
|
|||
|
@@ -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;
|
|||
|
--- a/mdoc.7
|
|||
|
+++ b/mdoc.7
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
.\" $Id: mdoc.7,v 1.276 2019/02/07 15:45:53 schwarze Exp $
|
|||
|
.\"
|
|||
|
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
-.\" Copyright (c) 2010, 2011, 2013-2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+.\" Copyright (c) 2010, 2011, 2013-2020 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
|
|||
|
@@ -449,6 +449,7 @@ in the alphabetical
|
|||
|
.It Ic \&Ss Ta subsection header (one line)
|
|||
|
.It Ic \&Sx Ta internal cross reference to a section or subsection
|
|||
|
.It Ic \&Xr Ta cross reference to another manual page: Ar name section
|
|||
|
+.It Ic \&Tg Ta tag the definition of a Ar term Pq <= 1 arguments
|
|||
|
.It Ic \&Pp Ta start a text paragraph (no arguments)
|
|||
|
.El
|
|||
|
.Ss Displays and lists
|
|||
|
@@ -596,6 +597,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 +1164,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 +1687,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
|
|||
|
@@ -2539,6 +2549,49 @@ Table cell separator in
|
|||
|
.Ic \&Bl Fl column
|
|||
|
lists; can only be used below
|
|||
|
.Ic \&It .
|
|||
|
+.It Ic \&Tg Op Ar term
|
|||
|
+Announce that the next input line starts a definition of the
|
|||
|
+.Ar term .
|
|||
|
+This macro must appear alone on its own input line.
|
|||
|
+The argument defaults to the first argument of the first macro
|
|||
|
+on the next line.
|
|||
|
+The argument may not contain whitespace characters, not even when it is quoted.
|
|||
|
+This macro is a
|
|||
|
+.Xr mandoc 1
|
|||
|
+extension and is typically ignored by other formatters.
|
|||
|
+.Pp
|
|||
|
+When viewing terminal output with
|
|||
|
+.Xr less 1 ,
|
|||
|
+the interactive
|
|||
|
+.Ic :t
|
|||
|
+command can be used to go to the definition of the
|
|||
|
+.Ar term
|
|||
|
+as described for the
|
|||
|
+.Ev MANPAGER
|
|||
|
+variable in
|
|||
|
+.Xr man 1 ;
|
|||
|
+when producing HTML output, a fragment identifier
|
|||
|
+.Pq Ic id No attribute
|
|||
|
+is generated, to be used for deep linking to this place of the document.
|
|||
|
+.Pp
|
|||
|
+In most cases, adding a
|
|||
|
+.Ic \&Tg
|
|||
|
+macro would be redundant because
|
|||
|
+.Xr mandoc 1
|
|||
|
+is able to automatically tag most definitions.
|
|||
|
+This macro is intended for cases where automatic tagging of a
|
|||
|
+.Ar term
|
|||
|
+is unsatisfactory, for example if a definition is not tagged
|
|||
|
+automatically (false negative) or if places are tagged that do
|
|||
|
+not define the
|
|||
|
+.Ar term
|
|||
|
+(false positives).
|
|||
|
+When there is at least one
|
|||
|
+.Ic \&Tg
|
|||
|
+macro for a
|
|||
|
+.Ar term ,
|
|||
|
+no other places are automatically marked as definitions of that
|
|||
|
+.Ar term .
|
|||
|
.It Ic \&Tn Ar word ...
|
|||
|
Supported only for compatibility, do not use this in new manuals.
|
|||
|
Even though the macro name
|
|||
|
@@ -2903,6 +2956,7 @@ then the macro accepts an arbitrary numb
|
|||
|
.It Ic \&St Ta \&No Ta Yes Ta 1
|
|||
|
.It Ic \&Sx Ta Yes Ta Yes Ta >0
|
|||
|
.It Ic \&Sy Ta Yes Ta Yes Ta >0
|
|||
|
+.It Ic \&Tg Ta \&No Ta \&No Ta <2
|
|||
|
.It Ic \&Tn Ta Yes Ta Yes Ta >0
|
|||
|
.It Ic \&Ud Ta \&No Ta \&No Ta 0
|
|||
|
.It Ic \&Ux Ta Yes Ta Yes Ta n
|
|||
|
@@ -2969,7 +3023,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 +3050,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
|
|||
|
--- 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 $ */
|
|||
|
/*
|
|||
|
* 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, in
|
|||
|
mandoc_msg(MANDOCERR_ARG_QUOTE, line, *pos, NULL);
|
|||
|
mdoc->flags &= ~MDOC_PHRASELIT;
|
|||
|
}
|
|||
|
+ mdoc->flags &= ~MDOC_PHRASEQL;
|
|||
|
return ARGS_EOLN;
|
|||
|
}
|
|||
|
|
|||
|
--- a/mdoc_html.c
|
|||
|
+++ b/mdoc_html.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: mdoc_html.c,v 1.328 2019/03/01 10:57:18 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2014-2020 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
|
|||
|
@@ -115,6 +115,7 @@ static int mdoc_ss_pre(MDOC_ARGS);
|
|||
|
static int mdoc_st_pre(MDOC_ARGS);
|
|||
|
static int mdoc_sx_pre(MDOC_ARGS);
|
|||
|
static int mdoc_sy_pre(MDOC_ARGS);
|
|||
|
+static int mdoc_tg_pre(MDOC_ARGS);
|
|||
|
static int mdoc_va_pre(MDOC_ARGS);
|
|||
|
static int mdoc_vt_pre(MDOC_ARGS);
|
|||
|
static int mdoc_xr_pre(MDOC_ARGS);
|
|||
|
@@ -241,6 +242,7 @@ static const struct mdoc_html_act mdoc_h
|
|||
|
{mdoc__x_pre, mdoc__x_post}, /* %Q */
|
|||
|
{mdoc__x_pre, mdoc__x_post}, /* %U */
|
|||
|
{NULL, NULL}, /* Ta */
|
|||
|
+ {mdoc_tg_pre, NULL}, /* Tg */
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
@@ -351,26 +353,34 @@ print_mdoc_node(MDOC_ARGS)
|
|||
|
if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
|
|||
|
return;
|
|||
|
|
|||
|
- html_fillmode(h, n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi);
|
|||
|
+ if (n->flags & NODE_NOFILL) {
|
|||
|
+ html_fillmode(h, ROFF_nf);
|
|||
|
+ if (n->flags & NODE_LINE)
|
|||
|
+ print_endline(h);
|
|||
|
+ } else
|
|||
|
+ html_fillmode(h, ROFF_fi);
|
|||
|
|
|||
|
child = 1;
|
|||
|
n->flags &= ~NODE_ENDED;
|
|||
|
switch (n->type) {
|
|||
|
case ROFFT_TEXT:
|
|||
|
+ if (n->flags & NODE_LINE) {
|
|||
|
+ switch (*n->string) {
|
|||
|
+ case '\0':
|
|||
|
+ h->col = 1;
|
|||
|
+ print_endline(h);
|
|||
|
+ return;
|
|||
|
+ case ' ':
|
|||
|
+ if ((h->flags & HTML_NONEWLINE) == 0 &&
|
|||
|
+ (n->flags & NODE_NOFILL) == 0)
|
|||
|
+ print_otag(h, TAG_BR, "");
|
|||
|
+ break;
|
|||
|
+ default:
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+ }
|
|||
|
t = h->tag;
|
|||
|
t->refcnt++;
|
|||
|
-
|
|||
|
- /* No tables in this mode... */
|
|||
|
- assert(NULL == h->tblt);
|
|||
|
-
|
|||
|
- /*
|
|||
|
- * Make sure that if we're in a literal mode already
|
|||
|
- * (i.e., within a <PRE>) don't print the newline.
|
|||
|
- */
|
|||
|
- if (*n->string == ' ' && n->flags & NODE_LINE &&
|
|||
|
- (h->flags & HTML_NONEWLINE) == 0 &&
|
|||
|
- (n->flags & NODE_NOFILL) == 0)
|
|||
|
- print_otag(h, TAG_BR, "");
|
|||
|
if (NODE_DELIMC & n->flags)
|
|||
|
h->flags |= HTML_NOSPACE;
|
|||
|
print_text(h, n->string);
|
|||
|
@@ -439,12 +449,6 @@ print_mdoc_node(MDOC_ARGS)
|
|||
|
n->body->flags |= NODE_ENDED;
|
|||
|
break;
|
|||
|
}
|
|||
|
-
|
|||
|
- if (n->flags & NODE_NOFILL &&
|
|||
|
- (n->next == NULL || n->next->flags & NODE_LINE)) {
|
|||
|
- h->col++;
|
|||
|
- print_endline(h);
|
|||
|
- }
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
@@ -653,7 +657,6 @@ mdoc_nd_pre(MDOC_ARGS)
|
|||
|
{
|
|||
|
switch (n->type) {
|
|||
|
case ROFFT_BLOCK:
|
|||
|
- html_close_paragraph(h);
|
|||
|
return 1;
|
|||
|
case ROFFT_HEAD:
|
|||
|
return 0;
|
|||
|
@@ -663,8 +666,7 @@ mdoc_nd_pre(MDOC_ARGS)
|
|||
|
abort();
|
|||
|
}
|
|||
|
print_text(h, "\\(em");
|
|||
|
- /* Cannot use TAG_SPAN because it may contain blocks. */
|
|||
|
- print_otag(h, TAG_DIV, "c", "Nd");
|
|||
|
+ print_otag(h, TAG_SPAN, "c", "Nd");
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
@@ -722,6 +724,16 @@ mdoc_xr_pre(MDOC_ARGS)
|
|||
|
}
|
|||
|
|
|||
|
static int
|
|||
|
+mdoc_tg_pre(MDOC_ARGS)
|
|||
|
+{
|
|||
|
+ char *id;
|
|||
|
+
|
|||
|
+ if ((id = html_make_id(n, 1)) != NULL)
|
|||
|
+ print_otag(h, TAG_MARK, "i", id);
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static int
|
|||
|
mdoc_ns_pre(MDOC_ARGS)
|
|||
|
{
|
|||
|
|
|||
|
@@ -1272,7 +1284,11 @@ mdoc_skip_pre(MDOC_ARGS)
|
|||
|
static int
|
|||
|
mdoc_pp_pre(MDOC_ARGS)
|
|||
|
{
|
|||
|
- if ((n->flags & NODE_NOFILL) == 0) {
|
|||
|
+ if (n->flags & NODE_NOFILL) {
|
|||
|
+ print_endline(h);
|
|||
|
+ h->col = 1;
|
|||
|
+ print_endline(h);
|
|||
|
+ } else {
|
|||
|
html_close_paragraph(h);
|
|||
|
print_otag(h, TAG_P, "c", "Pp");
|
|||
|
}
|
|||
|
@@ -1700,7 +1716,7 @@ mdoc_quote_pre(MDOC_ARGS)
|
|||
|
/*
|
|||
|
* Give up on semantic markup for now.
|
|||
|
* We cannot use TAG_SPAN because .Oo may contain blocks.
|
|||
|
- * We cannot use TAG_IDIV because we might be in a
|
|||
|
+ * We cannot use TAG_DIV because we might be in a
|
|||
|
* phrasing context (like .Dl or .Pp); we cannot
|
|||
|
* close out a .Pp at this point either because
|
|||
|
* that would break the line.
|
|||
|
@@ -1715,9 +1731,11 @@ mdoc_quote_pre(MDOC_ARGS)
|
|||
|
break;
|
|||
|
case MDOC_Do:
|
|||
|
case MDOC_Dq:
|
|||
|
+ print_text(h, "\\(lq");
|
|||
|
+ break;
|
|||
|
case MDOC_Qo:
|
|||
|
case MDOC_Qq:
|
|||
|
- print_text(h, "\\(lq");
|
|||
|
+ print_text(h, "\"");
|
|||
|
break;
|
|||
|
case MDOC_Po:
|
|||
|
case MDOC_Pq:
|
|||
|
@@ -1773,12 +1791,14 @@ mdoc_quote_post(MDOC_ARGS)
|
|||
|
else
|
|||
|
print_text(h, n->norm->Es->child->next->string);
|
|||
|
break;
|
|||
|
- case MDOC_Qo:
|
|||
|
- case MDOC_Qq:
|
|||
|
case MDOC_Do:
|
|||
|
case MDOC_Dq:
|
|||
|
print_text(h, "\\(rq");
|
|||
|
break;
|
|||
|
+ case MDOC_Qo:
|
|||
|
+ case MDOC_Qq:
|
|||
|
+ print_text(h, "\"");
|
|||
|
+ break;
|
|||
|
case MDOC_Po:
|
|||
|
case MDOC_Pq:
|
|||
|
print_text(h, ")");
|
|||
|
--- a/mdoc_macro.c
|
|||
|
+++ b/mdoc_macro.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: mdoc_macro.c,v 1.232 2019/01/07 07:26:29 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2010, 2012-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2010, 2012-2020 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
|
|||
|
@@ -61,7 +61,7 @@ static void rew_pending(struct roff_man
|
|||
|
const struct roff_node *);
|
|||
|
|
|||
|
static const struct mdoc_macro mdoc_macros[MDOC_MAX - MDOC_Dd] = {
|
|||
|
- { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
|
|||
|
+ { in_line_eoln, MDOC_PROLOGUE | MDOC_JOIN }, /* Dd */
|
|||
|
{ in_line_eoln, MDOC_PROLOGUE }, /* Dt */
|
|||
|
{ in_line_eoln, MDOC_PROLOGUE }, /* Os */
|
|||
|
{ blk_full, MDOC_PARSED | MDOC_JOIN }, /* Sh */
|
|||
|
@@ -200,6 +200,7 @@ static const struct mdoc_macro mdoc_macr
|
|||
|
{ in_line_eoln, MDOC_JOIN }, /* %Q */
|
|||
|
{ in_line_eoln, 0 }, /* %U */
|
|||
|
{ phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
|
|||
|
+ { in_line_eoln, 0 }, /* Tg */
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
--- a/mdoc_man.c
|
|||
|
+++ b/mdoc_man.c
|
|||
|
@@ -262,6 +262,7 @@ static const struct mdoc_man_act mdoc_ma
|
|||
|
{ NULL, NULL, post_percent, NULL, NULL }, /* %Q */
|
|||
|
{ NULL, NULL, post_percent, NULL, NULL }, /* %U */
|
|||
|
{ NULL, NULL, NULL, NULL, NULL }, /* Ta */
|
|||
|
+ { NULL, NULL, NULL, NULL, NULL }, /* Tg */
|
|||
|
};
|
|||
|
static const struct mdoc_man_act *mdoc_man_act(enum roff_tok);
|
|||
|
|
|||
|
--- a/mdoc_markdown.c
|
|||
|
+++ b/mdoc_markdown.c
|
|||
|
@@ -226,6 +226,7 @@ static const struct md_act md_acts[MDOC_
|
|||
|
{ NULL, NULL, md_post_pc, NULL, NULL }, /* %Q */
|
|||
|
{ NULL, md_pre_Lk, md_post_pc, NULL, NULL }, /* %U */
|
|||
|
{ NULL, NULL, NULL, NULL, NULL }, /* Ta */
|
|||
|
+ { NULL, NULL, NULL, NULL, NULL }, /* Tg */
|
|||
|
};
|
|||
|
static const struct md_act *md_act(enum roff_tok);
|
|||
|
|
|||
|
@@ -1290,7 +1291,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.
|
|||
|
--- a/mdoc_state.c
|
|||
|
+++ b/mdoc_state.c
|
|||
|
@@ -157,6 +157,7 @@ static const state_handler state_handler
|
|||
|
NULL, /* %Q */
|
|||
|
NULL, /* %U */
|
|||
|
NULL, /* Ta */
|
|||
|
+ NULL, /* Tg */
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
--- a/mdoc_term.c
|
|||
|
+++ b/mdoc_term.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: mdoc_term.c,v 1.372 2019/01/04 03:39:01 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2010, 2012-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2010, 2012-2020 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
|
|||
|
*
|
|||
|
* Permission to use, copy, modify, and distribute this software for any
|
|||
|
@@ -119,6 +119,7 @@ static int termp_pp_pre(DECL_ARGS);
|
|||
|
static int termp_ss_pre(DECL_ARGS);
|
|||
|
static int termp_sy_pre(DECL_ARGS);
|
|||
|
static int termp_tag_pre(DECL_ARGS);
|
|||
|
+static int termp_tg_pre(DECL_ARGS);
|
|||
|
static int termp_under_pre(DECL_ARGS);
|
|||
|
static int termp_vt_pre(DECL_ARGS);
|
|||
|
static int termp_xr_pre(DECL_ARGS);
|
|||
|
@@ -245,15 +246,16 @@ static const struct mdoc_term_act mdoc_t
|
|||
|
{ NULL, termp____post }, /* %Q */
|
|||
|
{ NULL, termp____post }, /* %U */
|
|||
|
{ NULL, NULL }, /* Ta */
|
|||
|
+ { termp_tg_pre, NULL }, /* Tg */
|
|||
|
};
|
|||
|
|
|||
|
-static int fn_prio;
|
|||
|
+static int fn_prio = TAG_STRONG;
|
|||
|
|
|||
|
|
|||
|
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 +267,20 @@ terminal_mdoc(void *arg, const struct ro
|
|||
|
|
|||
|
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 +358,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) {
|
|||
|
@@ -1287,7 +1294,7 @@ termp_sh_pre(DECL_ARGS)
|
|||
|
term_tab_set(p, ".5i");
|
|||
|
switch (n->sec) {
|
|||
|
case SEC_DESCRIPTION:
|
|||
|
- fn_prio = 0;
|
|||
|
+ fn_prio = TAG_STRONG;
|
|||
|
break;
|
|||
|
case SEC_AUTHORS:
|
|||
|
p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT);
|
|||
|
@@ -1376,7 +1383,7 @@ termp_fn_pre(DECL_ARGS)
|
|||
|
term_fontpop(p);
|
|||
|
|
|||
|
if (n->sec == SEC_DESCRIPTION || n->sec == SEC_CUSTOM)
|
|||
|
- tag_put(n->string, ++fn_prio, p->line);
|
|||
|
+ tag_put(n->string, fn_prio++, p->line);
|
|||
|
|
|||
|
if (pretty) {
|
|||
|
term_flushln(p);
|
|||
|
@@ -1607,7 +1614,7 @@ termp_in_post(DECL_ARGS)
|
|||
|
static int
|
|||
|
termp_pp_pre(DECL_ARGS)
|
|||
|
{
|
|||
|
- fn_prio = 0;
|
|||
|
+ fn_prio = TAG_STRONG;
|
|||
|
term_vspace(p);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
@@ -2032,7 +2039,7 @@ termp_em_pre(DECL_ARGS)
|
|||
|
{
|
|||
|
if (n->child != NULL &&
|
|||
|
n->child->type == ROFFT_TEXT)
|
|||
|
- tag_put(n->child->string, 0, p->line);
|
|||
|
+ tag_put(n->child->string, TAG_FALLBACK, p->line);
|
|||
|
term_fontpush(p, TERMFONT_UNDER);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
@@ -2042,7 +2049,7 @@ termp_sy_pre(DECL_ARGS)
|
|||
|
{
|
|||
|
if (n->child != NULL &&
|
|||
|
n->child->type == ROFFT_TEXT)
|
|||
|
- tag_put(n->child->string, 0, p->line);
|
|||
|
+ tag_put(n->child->string, TAG_FALLBACK, p->line);
|
|||
|
term_fontpush(p, TERMFONT_BOLD);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
@@ -2055,7 +2062,7 @@ termp_er_pre(DECL_ARGS)
|
|||
|
(n->parent->tok == MDOC_It ||
|
|||
|
(n->parent->tok == MDOC_Bq &&
|
|||
|
n->parent->parent->parent->tok == MDOC_It)))
|
|||
|
- tag_put(n->child->string, 1, p->line);
|
|||
|
+ tag_put(n->child->string, TAG_STRONG, p->line);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
@@ -2072,11 +2079,18 @@ termp_tag_pre(DECL_ARGS)
|
|||
|
(n->parent->tok == MDOC_Xo &&
|
|||
|
n->parent->parent->prev == NULL &&
|
|||
|
n->parent->parent->parent->tok == MDOC_It)))
|
|||
|
- tag_put(n->child->string, 1, p->line);
|
|||
|
+ tag_put(n->child->string, TAG_STRONG, p->line);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
static int
|
|||
|
+termp_tg_pre(DECL_ARGS)
|
|||
|
+{
|
|||
|
+ tag_put(n->child->string, TAG_MANUAL, p->line);
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static int
|
|||
|
termp_abort_pre(DECL_ARGS)
|
|||
|
{
|
|||
|
abort();
|
|||
|
--- a/mdoc_validate.c
|
|||
|
+++ b/mdoc_validate.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: mdoc_validate.c,v 1.371 2019/03/04 13:01:57 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2010-2020 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
|
|||
|
*
|
|||
|
* Permission to use, copy, modify, and distribute this software for any
|
|||
|
@@ -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);
|
|||
|
@@ -113,6 +113,7 @@ static void post_sm(POST_ARGS);
|
|||
|
static void post_st(POST_ARGS);
|
|||
|
static void post_std(POST_ARGS);
|
|||
|
static void post_sx(POST_ARGS);
|
|||
|
+static void post_tg(POST_ARGS);
|
|||
|
static void post_useless(POST_ARGS);
|
|||
|
static void post_xr(POST_ARGS);
|
|||
|
static void post_xx(POST_ARGS);
|
|||
|
@@ -238,6 +239,7 @@ static const v_post mdoc_valids[MDOC_MAX
|
|||
|
NULL, /* %Q */
|
|||
|
NULL, /* %U */
|
|||
|
NULL, /* Ta */
|
|||
|
+ post_tg, /* Tg */
|
|||
|
};
|
|||
|
|
|||
|
#define RSORD_MAX 14 /* Number of `Rs' blocks. */
|
|||
|
@@ -1090,6 +1092,41 @@ post_st(POST_ARGS)
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
+post_tg(POST_ARGS)
|
|||
|
+{
|
|||
|
+ struct roff_node *n, *nch;
|
|||
|
+ size_t len;
|
|||
|
+
|
|||
|
+ n = mdoc->last;
|
|||
|
+ nch = n->child;
|
|||
|
+ if (nch == NULL && n->next != NULL &&
|
|||
|
+ n->next->child->type == ROFFT_TEXT) {
|
|||
|
+ mdoc->next = ROFF_NEXT_CHILD;
|
|||
|
+ roff_word_alloc(mdoc, n->line, n->pos, n->next->child->string);
|
|||
|
+ nch = mdoc->last;
|
|||
|
+ nch->flags |= NODE_NOSRC;
|
|||
|
+ mdoc->last = n;
|
|||
|
+ }
|
|||
|
+ if (nch == NULL || *nch->string == '\0') {
|
|||
|
+ mandoc_msg(MANDOCERR_MACRO_EMPTY, n->line, n->pos, "Tg");
|
|||
|
+ roff_node_delete(mdoc, n);
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
+ len = strcspn(nch->string, " \t");
|
|||
|
+ if (nch->string[len] != '\0')
|
|||
|
+ mandoc_msg(MANDOCERR_TG_SPC, nch->line, nch->pos + len + 1,
|
|||
|
+ "Tg %s", nch->string);
|
|||
|
+ if (nch->next != NULL) {
|
|||
|
+ mandoc_msg(MANDOCERR_ARG_EXCESS, nch->next->line,
|
|||
|
+ nch->next->pos, "Tg ... %s", nch->next->string);
|
|||
|
+ while (nch->next != NULL)
|
|||
|
+ roff_node_delete(mdoc, nch->next);
|
|||
|
+ }
|
|||
|
+ if (nch->string[len] != '\0')
|
|||
|
+ roff_node_delete(mdoc, n);
|
|||
|
+}
|
|||
|
+
|
|||
|
+static void
|
|||
|
post_obsolete(POST_ARGS)
|
|||
|
{
|
|||
|
struct roff_node *n;
|
|||
|
@@ -1186,11 +1223,17 @@ post_fname(POST_ARGS)
|
|||
|
size_t pos;
|
|||
|
|
|||
|
n = mdoc->last->child;
|
|||
|
- pos = strcspn(n->string, "()");
|
|||
|
- cp = n->string + pos;
|
|||
|
- if ( ! (cp[0] == '\0' || (cp[0] == '(' && cp[1] == '*')))
|
|||
|
- mandoc_msg(MANDOCERR_FN_PAREN, n->line, n->pos + pos,
|
|||
|
- "%s", n->string);
|
|||
|
+ cp = n->string;
|
|||
|
+ if (*cp == '(') {
|
|||
|
+ if (cp[strlen(cp + 1)] == ')')
|
|||
|
+ return;
|
|||
|
+ pos = 0;
|
|||
|
+ } else {
|
|||
|
+ pos = strcspn(cp, "()");
|
|||
|
+ if (cp[pos] == '\0')
|
|||
|
+ return;
|
|||
|
+ }
|
|||
|
+ mandoc_msg(MANDOCERR_FN_PAREN, n->line, n->pos + pos, "%s", cp);
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
@@ -1748,7 +1791,7 @@ post_bl(POST_ARGS)
|
|||
|
while (nchild != NULL) {
|
|||
|
nnext = nchild->next;
|
|||
|
if (nchild->tok == MDOC_It ||
|
|||
|
- (nchild->tok == MDOC_Sm &&
|
|||
|
+ ((nchild->tok == MDOC_Sm || nchild->tok == MDOC_Tg) &&
|
|||
|
nnext != NULL && nnext->tok == MDOC_It)) {
|
|||
|
nchild = nnext;
|
|||
|
continue;
|
|||
|
@@ -1903,8 +1946,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(NULL, NULL);
|
|||
|
|
|||
|
if (mdoc->meta.title == NULL) {
|
|||
|
mandoc_msg(MANDOCERR_DT_NOTITLE, 0, 0, "EOF");
|
|||
|
@@ -2502,7 +2544,6 @@ static void
|
|||
|
post_dd(POST_ARGS)
|
|||
|
{
|
|||
|
struct roff_node *n;
|
|||
|
- char *datestr;
|
|||
|
|
|||
|
n = mdoc->last;
|
|||
|
n->flags |= NODE_NOPRT;
|
|||
|
@@ -2519,21 +2560,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);
|
|||
|
- }
|
|||
|
+ if (mdoc->quick && n != NULL)
|
|||
|
+ mdoc->meta.date = mandoc_strdup("");
|
|||
|
+ else
|
|||
|
+ mdoc->meta.date = mandoc_normdate(n->child, n);
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
--- a/out.c
|
|||
|
+++ b/out.c
|
|||
|
@@ -149,7 +149,7 @@ tblcalc(struct rofftbl *tbl, const struc
|
|||
|
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;
|
|||
|
@@ -209,13 +209,25 @@ tblcalc(struct rofftbl *tbl, const struc
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
- * Column spacings are needed for span width calculations,
|
|||
|
- * so set the default values now.
|
|||
|
+ * The minimum width of columns explicitly specified
|
|||
|
+ * in the layout is 1n.
|
|||
|
*/
|
|||
|
|
|||
|
- for (icol = 0; icol <= maxcol; icol++)
|
|||
|
- if (tbl->cols[icol].spacing == SIZE_MAX || icol == maxcol)
|
|||
|
- tbl->cols[icol].spacing = 3;
|
|||
|
+ if (maxcol < sp_first->opts->cols - 1)
|
|||
|
+ maxcol = sp_first->opts->cols - 1;
|
|||
|
+ for (icol = 0; icol <= maxcol; icol++) {
|
|||
|
+ col = tbl->cols + icol;
|
|||
|
+ if (col->width < 1)
|
|||
|
+ col->width = 1;
|
|||
|
+
|
|||
|
+ /*
|
|||
|
+ * Column spacings are needed for span width
|
|||
|
+ * calculations, so set the default values now.
|
|||
|
+ */
|
|||
|
+
|
|||
|
+ if (col->spacing == SIZE_MAX || icol == maxcol)
|
|||
|
+ col->spacing = 3;
|
|||
|
+ }
|
|||
|
|
|||
|
/*
|
|||
|
* Replace the minimum widths with the missing widths,
|
|||
|
--- a/read.c
|
|||
|
+++ b/read.c
|
|||
|
@@ -157,7 +157,7 @@ mparse_buf_r(struct mparse *curp, struct
|
|||
|
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
|
|||
|
/* 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
|
|||
|
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
|
|||
|
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
|
|||
|
* 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
|
|||
|
|
|||
|
*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
|
|||
|
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
|
|||
|
}
|
|||
|
|
|||
|
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 f
|
|||
|
mandoc_msg(MANDOCERR_ROFFLOOP, curp->line, 0, NULL);
|
|||
|
return;
|
|||
|
}
|
|||
|
- if (read_whole_file(curp, fd, &blk, &with_mmap) == 0)
|
|||
|
+ if (read_whole_file(curp, fd, &blk, &with_mmap) == -1)
|
|||
|
return;
|
|||
|
|
|||
|
/*
|
|||
|
--- a/regress/char/space/zerowidth.out_html
|
|||
|
+++ b/regress/char/space/zerowidth.out_html
|
|||
|
@@ -1,6 +1,4 @@
|
|||
|
-BEGINTEST
|
|||
|
zero width space \& between A and B: AB
|
|||
|
hyphenation allowed \% between A and B: AB
|
|||
|
half-narrow (1/12) space \^ between A and B: AB
|
|||
|
narrow space (1/6) \| between A and B: AB
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/char/unicode/ascii.out_html
|
|||
|
+++ b/regress/char/unicode/ascii.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST
|
|||
|
""" QUOTATION MARK
|
|||
|
### NUMBER SIGN
|
|||
|
$$$ DOLLAR SIGN
|
|||
|
@@ -19,4 +18,3 @@ ____ LOW LINE
|
|||
|
|||| VERTICAL LINE
|
|||
|
}}} RIGHT CURLY BRACKET
|
|||
|
~~~~ TILDE
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/char/unicode/invalid.out_html
|
|||
|
+++ b/regress/char/unicode/invalid.out_html
|
|||
|
@@ -1,8 +1,6 @@
|
|||
|
-BEGINTEST
|
|||
|
too short: >.<
|
|||
|
just right: >+<
|
|||
|
too long: >..<
|
|||
|
too large: >..<
|
|||
|
trailing garbage: ><
|
|||
|
not unicode: >_.↑.⇑<
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/char/unicode/latin1.out_html
|
|||
|
+++ b/regress/char/unicode/latin1.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST
|
|||
|
¡¡ INVERTED EXCLAMATION MARK
|
|||
|
¢¢ CENT SIGN
|
|||
|
££ POUND SIGN
|
|||
|
@@ -93,4 +92,3 @@ BEGINTEST
|
|||
|
ýý LATIN SMALL LETTER Y WITH ACUTE
|
|||
|
þþ LATIN SMALL LETTER THORN
|
|||
|
ÿÿ LATIN SMALL LETTER Y WITH DIAERESIS
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/char/unicode/latin1diff.out_html
|
|||
|
+++ b/regress/char/unicode/latin1diff.out_html
|
|||
|
@@ -1,3 +1 @@
|
|||
|
-BEGINTEST
|
|||
|
¯¯ MACRON
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/char/unicode/named.out_html
|
|||
|
+++ b/regress/char/unicode/named.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST
|
|||
|
ıı LATIN SMALL LETTER DOTLESS I
|
|||
|
IJIJ LATIN CAPITAL LIGATURE IJ
|
|||
|
ijij LATIN SMALL LIGATURE IJ
|
|||
|
@@ -167,4 +166,3 @@ BEGINTEST
|
|||
|
♦♦ BLACK DIAMOND SUIT
|
|||
|
⟨⟨ MATHEMATICAL LEFT ANGLE BRACKET
|
|||
|
⟩⟩ MATHEMATICAL RIGHT ANGLE BRACKET
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/char/unicode/namediff.out_html
|
|||
|
+++ b/regress/char/unicode/namediff.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST
|
|||
|
‾‾ OVERLINE
|
|||
|
ℏℏℏ PLANCK CONSTANT OVER TWO PI
|
|||
|
↕↕ UP DOWN ARROW
|
|||
|
@@ -22,4 +21,3 @@ BEGINTEST
|
|||
|
⎫⎫ RIGHT CURLY BRACKET UPPER HOOK
|
|||
|
⎬⎬ RIGHT CURLY BRACKET MIDDLE PIECE
|
|||
|
⎭⎭ RIGHT CURLY BRACKET LOWER HOOK
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/char/unicode/nogroff.out_html
|
|||
|
+++ b/regress/char/unicode/nogroff.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST
|
|||
|
�� <control> NULL
|
|||
|
�� <control> START OF HEADING
|
|||
|
�� <control> BELL
|
|||
|
@@ -34,4 +33,3 @@ BEGINTEST
|
|||
|
􏿽 <Plane 16 Private Use, Last>
|
|||
|
 <undefined>
|
|||
|
 <undefined>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/eqn/Makefile.inc
|
|||
|
+++ b/regress/eqn/Makefile.inc
|
|||
|
@@ -1,6 +1,4 @@
|
|||
|
-# $OpenBSD: Makefile.inc,v 1.2 2015/02/03 19:37:25 schwarze Exp $
|
|||
|
-
|
|||
|
-EQN = /usr/local/bin/eqn
|
|||
|
+# $OpenBSD: Makefile.inc,v 1.4 2020/01/08 10:17:15 schwarze Exp $
|
|||
|
|
|||
|
SKIP_GROFF ?= ${REGRESS_TARGETS}
|
|||
|
SKIP_TMAN ?= ALL
|
|||
|
--- a/regress/eqn/delim/Makefile
|
|||
|
+++ b/regress/eqn/delim/Makefile
|
|||
|
@@ -1,5 +1,8 @@
|
|||
|
-# $OpenBSD: Makefile,v 1.1.1.1 2015/01/01 12:53:46 schwarze Exp $
|
|||
|
+# $OpenBSD: Makefile,v 1.3 2020/01/08 12:09:14 schwarze Exp $
|
|||
|
|
|||
|
REGRESS_TARGETS = basic
|
|||
|
+UTF8_TARGETS = basic
|
|||
|
+GOPTS = -e
|
|||
|
+SKIP_GROFF =
|
|||
|
|
|||
|
.include <bsd.regress.mk>
|
|||
|
--- a/regress/eqn/delim/basic.in
|
|||
|
+++ b/regress/eqn/delim/basic.in
|
|||
|
@@ -8,15 +8,24 @@
|
|||
|
.Sh DESCRIPTION
|
|||
|
initial text
|
|||
|
.EQ
|
|||
|
-delim <>alpha
|
|||
|
+delim []alpha
|
|||
|
.EN
|
|||
|
-inline <beta>
|
|||
|
+inline [beta]
|
|||
|
.EQ
|
|||
|
delim offgamma
|
|||
|
.EN
|
|||
|
-inline <delta>
|
|||
|
+inline [delta]
|
|||
|
.EQ
|
|||
|
delim onepsilon
|
|||
|
.EN
|
|||
|
-inline <zeta>
|
|||
|
+inline [zeta]
|
|||
|
+.EQ
|
|||
|
+delim $$
|
|||
|
+delim off
|
|||
|
+.EN
|
|||
|
+inline $eta$
|
|||
|
+.EQ
|
|||
|
+delim on
|
|||
|
+.EN
|
|||
|
+inline $theta$
|
|||
|
final text
|
|||
|
--- a/regress/eqn/delim/basic.out_ascii
|
|||
|
+++ b/regress/eqn/delim/basic.out_ascii
|
|||
|
@@ -4,7 +4,7 @@ NNAAMMEE
|
|||
|
ddeelliimm--bbaassiicc - inline eqn delimiters
|
|||
|
|
|||
|
DDEESSCCRRIIPPTTIIOONN
|
|||
|
- initial text <alpha> inline <beta> <gamma> inline <delta> <epsilon>
|
|||
|
- inline <zeta> final text
|
|||
|
+ initial text <alpha> inline <beta> <gamma> inline [delta] <epsilon>
|
|||
|
+ inline <zeta> inline $eta$ inline <theta> final text
|
|||
|
|
|||
|
-OpenBSD July 4, 2017 OpenBSD
|
|||
|
+OpenBSD January 8, 2020 OpenBSD
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/eqn/delim/basic.out_utf8
|
|||
|
@@ -0,0 +1,10 @@
|
|||
|
+DELIM-BASIC(1) General Commands Manual DELIM-BASIC(1)
|
|||
|
+
|
|||
|
+NNAAMMEE
|
|||
|
+ ddeelliimm--bbaassiicc – inline eqn delimiters
|
|||
|
+
|
|||
|
+DDEESSCCRRIIPPTTIIOONN
|
|||
|
+ initial text α inline β γ inline [delta] ε inline ζ inline $eta$ inline θ
|
|||
|
+ final text
|
|||
|
+
|
|||
|
+OpenBSD January 8, 2020 OpenBSD
|
|||
|
--- a/regress/eqn/nullary/roman.out_html
|
|||
|
+++ b/regress/eqn/nullary/roman.out_html
|
|||
|
@@ -1,15 +1,5 @@
|
|||
|
<mrow><mrow><mi>unquoted
|
|||
|
-words:</mi></mrow><mi>sin</mi><mi>cos</mi><mi>tan</mi>
|
|||
|
-<mi>sec</mi><mi>csc</mi>
|
|||
|
-<mi>asin</mi><mi>acos</mi><mi>atan</mi><mi>asec</mi>
|
|||
|
-<mi>acsc</mi><mi>sinh</mi>
|
|||
|
-<mi>cosh</mi><mi>tanh</mi><mi>coth</mi><mi>arc</mi>
|
|||
|
-<mi>max</mi><mi>min</mi><mi>lim</mi><mi>log</mi><mi>ln</mi><mi>exp</mi><mi>Re</mi><mi>Im</mi><mi>and</mi><mi>if</mi><mi>for</mi><mi>det</mi><mo>—</mo><mrow><mi>quoted
|
|||
|
-words:</mi></mrow>
|
|||
|
-<mi fontstyle="italic">sin</mi><mi fontstyle="italic">cos</mi>
|
|||
|
-<mi fontstyle="italic">tan</mi><mi fontstyle="italic">sec</mi><mi fontstyle="italic">csc</mi><mi fontstyle="italic">asin</mi><mi fontstyle="italic">acos</mi><mi fontstyle="italic">atan</mi><mi fontstyle="italic">asec</mi><mi fontstyle="italic">acsc</mi><mi fontstyle="italic">sinh</mi><mi fontstyle="italic">cosh</mi><mi fontstyle="italic">tanh</mi><mi fontstyle="italic">coth</mi><mi fontstyle="italic">arc</mi><mi fontstyle="italic">max</mi><mi fontstyle="italic">min</mi><mi fontstyle="italic">lim</mi><mi fontstyle="italic">log</mi><mi fontstyle="italic">ln</mi><mi fontstyle="italic">exp</mi><mi fontstyle="italic">Re</mi><mi fontstyle="italic">Im</mi><mi fontstyle="italic">and</mi><mi fontstyle="italic">if</mi><mi fontstyle="italic">for</mi><mi fontstyle="italic">det</mi><mo>—</mo><mrow><mi>font
|
|||
|
-operations:</mi></mrow>
|
|||
|
-<mrow><mi>sin</mi></mrow><mrow><mi fontweight="bold">sin</mi></mrow><mo>—</mo><mrow><mi>superstring:</mi></mrow><mi fontstyle="italic">sinus</mi><mo>—</mo><mrow><mi>composite
|
|||
|
-word:</mi></mrow>
|
|||
|
-<mi>tan</mi><mo>=</mo><mi fontstyle="italic">sin</mi><mo>/</mo>
|
|||
|
-<mi fontstyle="italic">cos</mi></mrow>
|
|||
|
+words:</mi></mrow><mi>sin</mi><mi>cos</mi><mi>tan</mi><mi>sec</mi><mi>csc</mi><mi>asin</mi><mi>acos</mi><mi>atan</mi><mi>asec</mi><mi>acsc</mi><mi>sinh</mi><mi>cosh</mi><mi>tanh</mi><mi>coth</mi><mi>arc</mi><mi>max</mi><mi>min</mi><mi>lim</mi><mi>log</mi><mi>ln</mi><mi>exp</mi><mi>Re</mi><mi>Im</mi><mi>and</mi><mi>if</mi><mi>for</mi><mi>det</mi><mo>—</mo><mrow><mi>quoted
|
|||
|
+words:</mi></mrow><mi fontstyle="italic">sin</mi><mi fontstyle="italic">cos</mi><mi fontstyle="italic">tan</mi><mi fontstyle="italic">sec</mi><mi fontstyle="italic">csc</mi><mi fontstyle="italic">asin</mi><mi fontstyle="italic">acos</mi><mi fontstyle="italic">atan</mi><mi fontstyle="italic">asec</mi><mi fontstyle="italic">acsc</mi><mi fontstyle="italic">sinh</mi><mi fontstyle="italic">cosh</mi><mi fontstyle="italic">tanh</mi><mi fontstyle="italic">coth</mi><mi fontstyle="italic">arc</mi><mi fontstyle="italic">max</mi><mi fontstyle="italic">min</mi><mi fontstyle="italic">lim</mi><mi fontstyle="italic">log</mi><mi fontstyle="italic">ln</mi><mi fontstyle="italic">exp</mi><mi fontstyle="italic">Re</mi><mi fontstyle="italic">Im</mi><mi fontstyle="italic">and</mi><mi fontstyle="italic">if</mi><mi fontstyle="italic">for</mi><mi fontstyle="italic">det</mi><mo>—</mo><mrow><mi>font
|
|||
|
+operations:</mi></mrow><mrow><mi>sin</mi></mrow><mrow><mi fontweight="bold">sin</mi></mrow><mo>—</mo><mrow><mi>superstring:</mi></mrow><mi fontstyle="italic">sinus</mi><mo>—</mo><mrow><mi>composite
|
|||
|
+word:</mi></mrow><mi>tan</mi><mo>=</mo><mi fontstyle="italic">sin</mi><mo>/</mo><mi fontstyle="italic">cos</mi></mrow>
|
|||
|
--- a/regress/eqn/nullary/symbol.out_html
|
|||
|
+++ b/regress/eqn/nullary/symbol.out_html
|
|||
|
@@ -1,6 +1,4 @@
|
|||
|
<mrow><mrow><mi>unquoted
|
|||
|
words:</mi></mrow><mo>ε</mo><mo>′</mo><mo>—</mo><mrow><mi>quoted
|
|||
|
-words:</mi></mrow>
|
|||
|
-<mi fontstyle="italic">epsilon</mi><mi fontstyle="italic">prime</mi><mo>—</mo><mrow><mi>composite
|
|||
|
-word:</mi></mrow>
|
|||
|
-<mi fontstyle="italic">epsilon</mi><mo>-</mo><mi fontstyle="italic">prime</mi></mrow>
|
|||
|
+words:</mi></mrow><mi fontstyle="italic">epsilon</mi><mi fontstyle="italic">prime</mi><mo>—</mo><mrow><mi>composite
|
|||
|
+word:</mi></mrow><mi fontstyle="italic">epsilon</mi><mo>-</mo><mi fontstyle="italic">prime</mi></mrow>
|
|||
|
--- a/regress/man/HP/literal.out_html
|
|||
|
+++ b/regress/man/HP/literal.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST before hanged paragraph
|
|||
|
<p class="Pp HP">tag indented text</p>
|
|||
|
<p class="Pp">regular paragraph</p>
|
|||
|
<pre>
|
|||
|
@@ -17,4 +16,3 @@ paragraph
|
|||
|
</pre>
|
|||
|
regular text
|
|||
|
<br/>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/man/IP/literal.out_html
|
|||
|
+++ b/regress/man/IP/literal.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST before indentation
|
|||
|
<dl class="Bl-tag">
|
|||
|
<dt>tag</dt>
|
|||
|
<dd>indented regular text</dd>
|
|||
|
@@ -27,7 +26,7 @@ regular text
|
|||
|
<section class="Ss">
|
|||
|
<h2 class="Ss" id="literal_into_indented_paragraph"><a class="permalink" href="#literal_into_indented_paragraph">literal
|
|||
|
into indented paragraph</a></h2>
|
|||
|
-regular text
|
|||
|
+<p class="Pp">regular text</p>
|
|||
|
<pre>
|
|||
|
literal
|
|||
|
text
|
|||
|
@@ -47,7 +46,7 @@ text
|
|||
|
<section class="Ss">
|
|||
|
<h2 class="Ss" id="literal_out_of_indented_paragraph"><a class="permalink" href="#literal_out_of_indented_paragraph">literal
|
|||
|
out of indented paragraph</a></h2>
|
|||
|
-regular text
|
|||
|
+<p class="Pp">regular text</p>
|
|||
|
<dl class="Bl-tag">
|
|||
|
<dt>tag</dt>
|
|||
|
<dd>indented regular text
|
|||
|
@@ -65,4 +64,3 @@ paragraph
|
|||
|
</pre>
|
|||
|
regular text
|
|||
|
<br/>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/man/RS/literal.out_html
|
|||
|
+++ b/regress/man/RS/literal.out_html
|
|||
|
@@ -1,6 +1,5 @@
|
|||
|
-BEGINTEST
|
|||
|
-<br/>
|
|||
|
-initial regular text
|
|||
|
+ <br/>
|
|||
|
+ initial regular text</p>
|
|||
|
<pre>
|
|||
|
literal text
|
|||
|
before display
|
|||
|
@@ -15,6 +14,5 @@ This is a very long line that would wrap
|
|||
|
literal text
|
|||
|
after display
|
|||
|
</pre>
|
|||
|
-final regular text
|
|||
|
-<br/>
|
|||
|
-ENDTEST
|
|||
|
+<p class="Pp">final regular text
|
|||
|
+ <br/>
|
|||
|
--- a/regress/man/RS/paragraph.out_html
|
|||
|
+++ b/regress/man/RS/paragraph.out_html
|
|||
|
@@ -1,8 +1,6 @@
|
|||
|
-BEGINTEST before paragraph
|
|||
|
<p class="Pp">regular paragraph</p>
|
|||
|
<div class="Bd-indent">indented paragraph
|
|||
|
<p class="Pp">nested paragraph</p>
|
|||
|
</div>
|
|||
|
regular text after display
|
|||
|
<br/>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/man/SH/paragraph.out_html
|
|||
|
+++ b/regress/man/SH/paragraph.out_html
|
|||
|
@@ -1,10 +1,8 @@
|
|||
|
-BEGINTEST
|
|||
|
</section>
|
|||
|
<section class="Sh">
|
|||
|
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
|
|||
|
-This text immediately follows a section header.
|
|||
|
+<p class="Pp">This text immediately follows a section header.</p>
|
|||
|
<p class="Pp">This is a paragraph.</p>
|
|||
|
</section>
|
|||
|
<section class="Sh">
|
|||
|
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/man/SS/paragraph.out_html
|
|||
|
+++ b/regress/man/SS/paragraph.out_html
|
|||
|
@@ -1,11 +1,9 @@
|
|||
|
-BEGINTEST
|
|||
|
<section class="Ss">
|
|||
|
<h2 class="Ss" id="First_subsection"><a class="permalink" href="#First_subsection">First
|
|||
|
subsection</a></h2>
|
|||
|
-This text immediately follows a subsection header.
|
|||
|
+<p class="Pp">This text immediately follows a subsection header.</p>
|
|||
|
<p class="Pp">This is a paragraph.</p>
|
|||
|
</section>
|
|||
|
<section class="Ss">
|
|||
|
<h2 class="Ss" id="Second_subsection"><a class="permalink" href="#Second_subsection">Second
|
|||
|
subsection</a></h2>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/man/SY/literal.out_html
|
|||
|
+++ b/regress/man/SY/literal.out_html
|
|||
|
@@ -1,6 +1,5 @@
|
|||
|
-BEGINTEST
|
|||
|
-<br/>
|
|||
|
-initial regular text
|
|||
|
+ <br/>
|
|||
|
+ initial regular text</p>
|
|||
|
<table class="Nm">
|
|||
|
<tr>
|
|||
|
<td><code class="Nm">command</code></td>
|
|||
|
@@ -26,6 +25,5 @@ before display
|
|||
|
literal text
|
|||
|
after display
|
|||
|
</pre>
|
|||
|
-final regular text
|
|||
|
-<br/>
|
|||
|
-ENDTEST
|
|||
|
+<p class="Pp">final regular text
|
|||
|
+ <br/>
|
|||
|
--- a/regress/man/TH/baddate.out_lint
|
|||
|
+++ b/regress/man/TH/baddate.out_lint
|
|||
|
@@ -1 +1 @@
|
|||
|
-mandoc: baddate.in:2:18: WARNING: cannot parse date, using it verbatim: three bad words
|
|||
|
+mandoc: baddate.in:2:18: WARNING: cannot parse date, using it verbatim: TH three bad words
|
|||
|
--- a/regress/man/TH/emptydate.out_lint
|
|||
|
+++ b/regress/man/TH/emptydate.out_lint
|
|||
|
@@ -1 +1 @@
|
|||
|
-mandoc: emptydate.in:2:20: WARNING: missing date, using today's date: TH
|
|||
|
+mandoc: emptydate.in:2:20: WARNING: missing date, using "": TH
|
|||
|
--- a/regress/man/TH/longdate.out_lint
|
|||
|
+++ b/regress/man/TH/longdate.out_lint
|
|||
|
@@ -1 +1 @@
|
|||
|
-mandoc: longdate.in:2:19: WARNING: cannot parse date, using it verbatim: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012
|
|||
|
+mandoc: longdate.in:2:19: WARNING: cannot parse date, using it verbatim: TH 1234567890123456789012345678901234567890123456789012345678901234567890123456789012
|
|||
|
--- a/regress/man/TH/noTH.out_lint
|
|||
|
+++ b/regress/man/TH/noTH.out_lint
|
|||
|
@@ -1,2 +1,2 @@
|
|||
|
mandoc: noTH.in: WARNING: missing manual title, using ""
|
|||
|
-mandoc: noTH.in: WARNING: missing date, using today's date
|
|||
|
+mandoc: noTH.in: WARNING: missing date, using ""
|
|||
|
--- a/regress/man/TH/noarg.out_lint
|
|||
|
+++ b/regress/man/TH/noarg.out_lint
|
|||
|
@@ -1,3 +1,3 @@
|
|||
|
mandoc: noarg.in:2:2: WARNING: missing manual title, using "": TH
|
|||
|
mandoc: noarg.in:2:2: WARNING: missing manual section, using "": TH
|
|||
|
-mandoc: noarg.in:2:2: WARNING: missing date, using today's date: TH
|
|||
|
+mandoc: noarg.in:2:2: WARNING: missing date, using "": TH
|
|||
|
--- a/regress/man/TH/onearg.out_lint
|
|||
|
+++ b/regress/man/TH/onearg.out_lint
|
|||
|
@@ -1,2 +1,2 @@
|
|||
|
mandoc: onearg.in:2:2: WARNING: missing manual section, using "": TH TH-ONEARG
|
|||
|
-mandoc: onearg.in:2:2: WARNING: missing date, using today's date: TH
|
|||
|
+mandoc: onearg.in:2:2: WARNING: missing date, using "": TH
|
|||
|
--- a/regress/man/TH/twoargs.out_lint
|
|||
|
+++ b/regress/man/TH/twoargs.out_lint
|
|||
|
@@ -1,2 +1,2 @@
|
|||
|
mandoc: twoargs.in:2:2: WARNING: missing manual section, using "": TH TH-TWOARGS
|
|||
|
-mandoc: twoargs.in:2:2: WARNING: missing date, using today's date: TH
|
|||
|
+mandoc: twoargs.in:2:2: WARNING: missing date, using "": TH
|
|||
|
--- a/regress/man/TP/literal.out_html
|
|||
|
+++ b/regress/man/TP/literal.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST before indentation
|
|||
|
<dl class="Bl-tag">
|
|||
|
<dt>tag</dt>
|
|||
|
<dd>regular indented text</dd>
|
|||
|
@@ -24,4 +23,3 @@ paragraph
|
|||
|
</pre>
|
|||
|
regular text
|
|||
|
<br/>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/man/TS/Makefile
|
|||
|
+++ b/regress/man/TS/Makefile
|
|||
|
@@ -1,7 +1,8 @@
|
|||
|
-# $OpenBSD: Makefile,v 1.3 2015/01/30 21:28:21 schwarze Exp $
|
|||
|
+# $OpenBSD: Makefile,v 1.4 2020/01/08 10:17:15 schwarze Exp $
|
|||
|
|
|||
|
REGRESS_TARGETS = break vspace
|
|||
|
LINT_TARGETS = break
|
|||
|
+GOPTS = -t
|
|||
|
|
|||
|
# groff-1.22.3 defect:
|
|||
|
# - Starting a table in next-line scope confuses font handling,
|
|||
|
@@ -9,14 +10,4 @@ LINT_TARGETS = break
|
|||
|
|
|||
|
SKIP_GROFF = break
|
|||
|
|
|||
|
-
|
|||
|
-# OpenBSD only: maintainer targets
|
|||
|
-
|
|||
|
-TBL=/usr/local/bin/tbl
|
|||
|
-
|
|||
|
-.for t in ${REGRESS_TARGETS}
|
|||
|
-${t}.out_ascii: ${t}.in
|
|||
|
- ${TBL} ${.ALLSRC} | ${NROFF} ${NOPTS} -Tascii > ${.TARGET}
|
|||
|
-.endfor
|
|||
|
-
|
|||
|
.include <bsd.regress.mk>
|
|||
|
--- a/regress/mdoc/Bd/nf.out_html
|
|||
|
+++ b/regress/mdoc/Bd/nf.out_html
|
|||
|
@@ -1,9 +1,8 @@
|
|||
|
-BEGINTEST initial text
|
|||
|
<pre>
|
|||
|
after .nf
|
|||
|
request
|
|||
|
</pre>
|
|||
|
-after .fi request
|
|||
|
+<p class="Pp">after .fi request</p>
|
|||
|
<div class="Bd Pp">
|
|||
|
<pre>
|
|||
|
in unfilled
|
|||
|
@@ -19,4 +18,3 @@ in filled block
|
|||
|
</div>
|
|||
|
after end of filled block
|
|||
|
<br/>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/mdoc/Bd/paragraph.out_html
|
|||
|
+++ b/regress/mdoc/Bd/paragraph.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST initial text
|
|||
|
<p class="Pp">normal paragraph</p>
|
|||
|
<div class="Bd Pp">filled display
|
|||
|
<p class="Pp">paragraph in display</p>
|
|||
|
@@ -16,4 +15,3 @@ paragraph
|
|||
|
</div>
|
|||
|
again back to normal
|
|||
|
<br/>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/mdoc/Bf/paragraph.out_html
|
|||
|
+++ b/regress/mdoc/Bf/paragraph.out_html
|
|||
|
@@ -1,6 +1,4 @@
|
|||
|
-BEGINTEST
|
|||
|
<p class="Pp">normal text</p>
|
|||
|
<div class="Bf Li">literal text
|
|||
|
<p class="Pp">literal paragraph</p>
|
|||
|
</div>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/mdoc/Bl/column.in
|
|||
|
+++ b/regress/mdoc/Bl/column.in
|
|||
|
@@ -81,7 +81,8 @@
|
|||
|
.\" Mixed tab and Ta
|
|||
|
.Bl -column a b c d
|
|||
|
.It a b c d
|
|||
|
-.It a b c Ta d
|
|||
|
+.It "a b c" Ta
|
|||
|
+d
|
|||
|
.It a b Ta c d
|
|||
|
.It a b Ta c Ta d
|
|||
|
.It a Ta b c d
|
|||
|
--- a/regress/mdoc/Bl/column.out_ascii
|
|||
|
+++ b/regress/mdoc/Bl/column.out_ascii
|
|||
|
@@ -71,4 +71,4 @@ DDEESSCCRRIIPPTTIIOONN
|
|||
|
aa bb tab at eol
|
|||
|
aa bb cc dd
|
|||
|
|
|||
|
-OpenBSD July 4, 2017 OpenBSD
|
|||
|
+OpenBSD July 11, 2019 OpenBSD
|
|||
|
--- a/regress/mdoc/Bl/column.out_lint
|
|||
|
+++ b/regress/mdoc/Bl/column.out_lint
|
|||
|
@@ -4,4 +4,4 @@ mandoc: column.in:75:2: WARNING: skippin
|
|||
|
mandoc: column.in:77:2: WARNING: wrong number of cells: 2 columns, 4 cells
|
|||
|
mandoc: column.in:78:2: WARNING: wrong number of cells: 2 columns, 5 cells
|
|||
|
mandoc: column.in:79:2: WARNING: skipping empty macro: It
|
|||
|
-mandoc: column.in:107:18: WARNING: skipping -width argument: Bl -column
|
|||
|
+mandoc: column.in:108:18: WARNING: skipping -width argument: Bl -column
|
|||
|
--- a/regress/mdoc/Bl/column.out_markdown
|
|||
|
+++ b/regress/mdoc/Bl/column.out_markdown
|
|||
|
@@ -75,4 +75,4 @@ BL-COLUMN(1) - General Commands Manual
|
|||
|
|
|||
|
aa bb cc dd
|
|||
|
|
|||
|
-OpenBSD - July 4, 2017
|
|||
|
+OpenBSD - July 11, 2019
|
|||
|
--- a/regress/mdoc/D1/spacing.out_html
|
|||
|
+++ b/regress/mdoc/D1/spacing.out_html
|
|||
|
@@ -1,8 +1,6 @@
|
|||
|
-BEGINTEST
|
|||
|
<p class="Pp">preceding paragraph</p>
|
|||
|
<div class="Bd Bd-indent">spacing in and around one-line displays</div>
|
|||
|
empty display:
|
|||
|
<div class="Bd Bd-indent"></div>
|
|||
|
following text
|
|||
|
<br/>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/mdoc/Dd/Makefile
|
|||
|
+++ b/regress/mdoc/Dd/Makefile
|
|||
|
@@ -1,23 +1,15 @@
|
|||
|
-# $OpenBSD: Makefile,v 1.2 2014/11/21 01:52:45 schwarze Exp $
|
|||
|
+# $OpenBSD: Makefile,v 1.6 2020/01/19 16:16:33 schwarze Exp $
|
|||
|
|
|||
|
REGRESS_TARGETS = badarg dupe late long manarg noarg order
|
|||
|
LINT_TARGETS = badarg dupe late long manarg noarg order
|
|||
|
|
|||
|
-# noarg output contains the date when the file is formatted
|
|||
|
+# groff-1.22.4 prints footer fields of excessive length on top of
|
|||
|
+# each other rather than breaking the output line.
|
|||
|
|
|||
|
-SKIP_ASCII ?= noarg
|
|||
|
-SKIP_MARKDOWN ?= noarg
|
|||
|
-
|
|||
|
-# If groff finds exactly three arguments, it assumes they are month,
|
|||
|
-# day and year without further checking. If there are no arguments,
|
|||
|
-# groff uses the string "Epoch". Otherwise, it silently falls back
|
|||
|
-# to today's date.
|
|||
|
-# That is not at all sane behaviour, we are not going to imitate it.
|
|||
|
-
|
|||
|
-SKIP_GROFF = badarg long manarg noarg
|
|||
|
+SKIP_GROFF = long
|
|||
|
|
|||
|
# Autodetection fails for late .Dd, so specify -mdoc explicitly.
|
|||
|
|
|||
|
-MOPTS += -mdoc
|
|||
|
+MOPTS = -mdoc
|
|||
|
|
|||
|
.include <bsd.regress.mk>
|
|||
|
--- a/regress/mdoc/Dd/badarg.out_lint
|
|||
|
+++ b/regress/mdoc/Dd/badarg.out_lint
|
|||
|
@@ -1,2 +1,2 @@
|
|||
|
-mandoc: badarg.in:2:2: WARNING: cannot parse date, using it verbatim: bad date
|
|||
|
+mandoc: badarg.in:2:5: WARNING: cannot parse date, using it verbatim: Dd bad date
|
|||
|
mandoc: badarg.in:2:5: STYLE: Mdocdate missing: Dd bad date (OpenBSD)
|
|||
|
--- a/regress/mdoc/Dd/dupe.out_lint
|
|||
|
+++ b/regress/mdoc/Dd/dupe.out_lint
|
|||
|
@@ -1,3 +1,3 @@
|
|||
|
-mandoc: dupe.in:2:5: STYLE: Mdocdate missing: Dd August (OpenBSD)
|
|||
|
+mandoc: dupe.in:2:5: STYLE: Mdocdate missing: Dd August 1, 2014 (OpenBSD)
|
|||
|
mandoc: dupe.in:5:2: ERROR: duplicate prologue macro: Dd
|
|||
|
mandoc: dupe.in:11:2: ERROR: duplicate prologue macro: Dd
|
|||
|
--- a/regress/mdoc/Dd/long.out_lint
|
|||
|
+++ b/regress/mdoc/Dd/long.out_lint
|
|||
|
@@ -1,2 +1,2 @@
|
|||
|
-mandoc: long.in:2:2: WARNING: cannot parse date, using it verbatim: 1234567890123456789012345678901234567890123456789012345678901234567890123456789
|
|||
|
+mandoc: long.in:2:5: WARNING: cannot parse date, using it verbatim: Dd 1234567890123456789012345678901234567890123456789012345678901234567890123456789
|
|||
|
mandoc: long.in:2:5: STYLE: Mdocdate missing: Dd 1234567890123456789012345678901234567890123456789012345678901234567890123456789 (OpenBSD)
|
|||
|
--- a/regress/mdoc/Dd/manarg.out_lint
|
|||
|
+++ b/regress/mdoc/Dd/manarg.out_lint
|
|||
|
@@ -1,2 +1,2 @@
|
|||
|
-mandoc: manarg.in:2:2: STYLE: legacy man(7) date format: Dd 2014-08-07
|
|||
|
+mandoc: manarg.in:2:5: STYLE: legacy man(7) date format: Dd 2014-08-07
|
|||
|
mandoc: manarg.in:2:5: STYLE: Mdocdate missing: Dd 2014-08-07 (OpenBSD)
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/mdoc/Dd/noarg.out_ascii
|
|||
|
@@ -0,0 +1,9 @@
|
|||
|
+DD-NOARG(1) General Commands Manual DD-NOARG(1)
|
|||
|
+
|
|||
|
+NNAAMMEE
|
|||
|
+ DDdd--nnooaarrgg - date macro without an argument
|
|||
|
+
|
|||
|
+DDEESSCCRRIIPPTTIIOONN
|
|||
|
+ some text
|
|||
|
+
|
|||
|
+OpenBSD OpenBSD
|
|||
|
--- a/regress/mdoc/Dd/noarg.out_lint
|
|||
|
+++ b/regress/mdoc/Dd/noarg.out_lint
|
|||
|
@@ -1 +1 @@
|
|||
|
-mandoc: noarg.in:2:2: WARNING: missing date, using today's date
|
|||
|
+mandoc: noarg.in:2:2: WARNING: missing date, using "": Dd
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/mdoc/Dd/noarg.out_markdown
|
|||
|
@@ -0,0 +1,11 @@
|
|||
|
+DD-NOARG(1) - General Commands Manual
|
|||
|
+
|
|||
|
+# NAME
|
|||
|
+
|
|||
|
+**Dd-noarg** - date macro without an argument
|
|||
|
+
|
|||
|
+# DESCRIPTION
|
|||
|
+
|
|||
|
+some text
|
|||
|
+
|
|||
|
+OpenBSD -
|
|||
|
--- a/regress/mdoc/Dd/order.out_lint
|
|||
|
+++ b/regress/mdoc/Dd/order.out_lint
|
|||
|
@@ -1,2 +1,2 @@
|
|||
|
mandoc: order.in:3:2: WARNING: prologue macros out of order: Dd after Dt
|
|||
|
-mandoc: order.in:3:5: STYLE: Mdocdate missing: Dd August (OpenBSD)
|
|||
|
+mandoc: order.in:3:5: STYLE: Mdocdate missing: Dd August 5, 2014 (OpenBSD)
|
|||
|
--- a/regress/mdoc/Fo/warn.in
|
|||
|
+++ b/regress/mdoc/Fo/warn.in
|
|||
|
@@ -12,3 +12,17 @@
|
|||
|
.Fc
|
|||
|
.Ft double
|
|||
|
.Fn atan2 "double y, double x"
|
|||
|
+.Ft int
|
|||
|
+.Fn close) "int fd"
|
|||
|
+.Ft typedef void
|
|||
|
+.Fn (handler) int
|
|||
|
+.Ft typedef void
|
|||
|
+.Fn (*fp) int
|
|||
|
+.Ft int
|
|||
|
+.Fn (open "const char *path"
|
|||
|
+.Ft FILE *
|
|||
|
+.Fn (*popen "const char *cmd"
|
|||
|
+.Ft void
|
|||
|
+.Fn (trail)x void
|
|||
|
+.Ft void
|
|||
|
+.Fn *star void
|
|||
|
--- a/regress/mdoc/Fo/warn.out_ascii
|
|||
|
+++ b/regress/mdoc/Fo/warn.out_ascii
|
|||
|
@@ -10,4 +10,25 @@ SSYYNNOOPPSSIISS
|
|||
|
_d_o_u_b_l_e
|
|||
|
aattaann22(_d_o_u_b_l_e _y_, _d_o_u_b_l_e _x);
|
|||
|
|
|||
|
-OpenBSD July 4, 2017 OpenBSD
|
|||
|
+ _i_n_t
|
|||
|
+ cclloossee))(_i_n_t _f_d);
|
|||
|
+
|
|||
|
+ _t_y_p_e_d_e_f _v_o_i_d
|
|||
|
+ ((hhaannddlleerr))(_i_n_t);
|
|||
|
+
|
|||
|
+ _t_y_p_e_d_e_f _v_o_i_d
|
|||
|
+ ((**ffpp))(_i_n_t);
|
|||
|
+
|
|||
|
+ _i_n_t
|
|||
|
+ ((ooppeenn(_c_o_n_s_t _c_h_a_r _*_p_a_t_h);
|
|||
|
+
|
|||
|
+ _F_I_L_E _*
|
|||
|
+ ((**ppooppeenn(_c_o_n_s_t _c_h_a_r _*_c_m_d);
|
|||
|
+
|
|||
|
+ _v_o_i_d
|
|||
|
+ ((ttrraaiill))xx(_v_o_i_d);
|
|||
|
+
|
|||
|
+ _v_o_i_d
|
|||
|
+ **ssttaarr(_v_o_i_d);
|
|||
|
+
|
|||
|
+OpenBSD September 13, 2019 OpenBSD
|
|||
|
--- a/regress/mdoc/Fo/warn.out_lint
|
|||
|
+++ b/regress/mdoc/Fo/warn.out_lint
|
|||
|
@@ -1,2 +1,6 @@
|
|||
|
mandoc: warn.in:10:8: WARNING: parenthesis in function name: sin()
|
|||
|
mandoc: warn.in:14:19: WARNING: comma in function argument: double y, double x
|
|||
|
+mandoc: warn.in:16:10: WARNING: parenthesis in function name: close)
|
|||
|
+mandoc: warn.in:22:5: WARNING: parenthesis in function name: (open
|
|||
|
+mandoc: warn.in:24:5: WARNING: parenthesis in function name: (*popen
|
|||
|
+mandoc: warn.in:26:5: WARNING: parenthesis in function name: (trail)x
|
|||
|
--- a/regress/mdoc/Fo/warn.out_markdown
|
|||
|
+++ b/regress/mdoc/Fo/warn.out_markdown
|
|||
|
@@ -12,4 +12,25 @@ FO-WARN(1) - General Commands Manual
|
|||
|
*double*
|
|||
|
**atan2**(*double y, double x*);
|
|||
|
|
|||
|
-OpenBSD - July 4, 2017
|
|||
|
+*int*
|
|||
|
+**close)**(*int fd*);
|
|||
|
+
|
|||
|
+*typedef void*
|
|||
|
+**(handler)**(*int*);
|
|||
|
+
|
|||
|
+*typedef void*
|
|||
|
+**(\*fp)**(*int*);
|
|||
|
+
|
|||
|
+*int*
|
|||
|
+**(open**(*const char \*path*);
|
|||
|
+
|
|||
|
+*FILE \*‌*
|
|||
|
+**(\*popen**(*const char \*cmd*);
|
|||
|
+
|
|||
|
+*void*
|
|||
|
+**(trail)x**(*void*);
|
|||
|
+
|
|||
|
+*void*
|
|||
|
+**\*star**(*void*);
|
|||
|
+
|
|||
|
+OpenBSD - September 13, 2019
|
|||
|
--- a/regress/mdoc/Os/dupe.out_ascii
|
|||
|
+++ b/regress/mdoc/Os/dupe.out_ascii
|
|||
|
@@ -6,4 +6,4 @@ NNAAMMEE
|
|||
|
DDEESSCCRRIIPPTTIIOONN
|
|||
|
initial text final text
|
|||
|
|
|||
|
-OpenBSD July 4, 2017 OpenBSD
|
|||
|
+OpenBSD January 19, 2020 OpenBSD
|
|||
|
--- a/regress/mdoc/Os/dupe.out_lint
|
|||
|
+++ b/regress/mdoc/Os/dupe.out_lint
|
|||
|
@@ -1,9 +1,9 @@
|
|||
|
mandoc: dupe.in:3:5: STYLE: operating system explicitly specified: Os NetBSD (NetBSD)
|
|||
|
-mandoc: dupe.in:2:5: STYLE: Mdocdate found: Dd $Mdocdate: (NetBSD)
|
|||
|
+mandoc: dupe.in:2:5: STYLE: Mdocdate found: Dd $Mdocdate$ (NetBSD)
|
|||
|
mandoc: dupe.in:4:2: WARNING: prologue macros out of order: Dt after Os
|
|||
|
mandoc: dupe.in:5:2: ERROR: duplicate prologue macro: Os
|
|||
|
mandoc: dupe.in:5:5: STYLE: operating system explicitly specified: Os FreeBSD (NetBSD)
|
|||
|
-mandoc: dupe.in:2:5: STYLE: Mdocdate found: Dd $Mdocdate: (NetBSD)
|
|||
|
+mandoc: dupe.in:2:5: STYLE: Mdocdate found: Dd $Mdocdate$ (NetBSD)
|
|||
|
mandoc: dupe.in:11:2: ERROR: duplicate prologue macro: Os
|
|||
|
mandoc: dupe.in:11:5: STYLE: operating system explicitly specified: Os OpenBSD (NetBSD)
|
|||
|
mandoc: dupe.in: STYLE: RCS id missing: (NetBSD)
|
|||
|
--- a/regress/mdoc/Os/dupe.out_markdown
|
|||
|
+++ b/regress/mdoc/Os/dupe.out_markdown
|
|||
|
@@ -9,4 +9,4 @@ OS-DUPE(1) - General Commands Manual
|
|||
|
initial text
|
|||
|
final text
|
|||
|
|
|||
|
-OpenBSD - July 4, 2017
|
|||
|
+OpenBSD - January 19, 2020
|
|||
|
--- a/regress/mdoc/Rs/paragraph.out_html
|
|||
|
+++ b/regress/mdoc/Rs/paragraph.out_html
|
|||
|
@@ -1,18 +1,16 @@
|
|||
|
-BEGINTEST
|
|||
|
-<br/>
|
|||
|
-initial reference: <cite class="Rs"><span class="RsA">author name</span>,
|
|||
|
- <i class="RsB">book title</i>.</cite>
|
|||
|
+ <br/>
|
|||
|
+ initial reference: <cite class="Rs"><span class="RsA">author name</span>,
|
|||
|
+ <i class="RsB">book title</i>.</cite></p>
|
|||
|
<p class="Pp">in a paragraph: <cite class="Rs"><span class="RsA">another
|
|||
|
author</span>, <i class="RsB">another book</i>.</cite></p>
|
|||
|
</section>
|
|||
|
<section class="Sh">
|
|||
|
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
|
|||
|
ALSO</a></h1>
|
|||
|
-initial reference:
|
|||
|
+<p class="Pp">initial reference:</p>
|
|||
|
<p class="Pp"><cite class="Rs"><span class="RsA">author name</span>,
|
|||
|
<i class="RsB">book title</i>.</cite></p>
|
|||
|
<p class="Pp">in a paragraph:</p>
|
|||
|
<p class="Pp"><cite class="Rs"><span class="RsA">another author</span>,
|
|||
|
<i class="RsB">another book</i>.</cite></p>
|
|||
|
<pre>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/mdoc/Sh/paragraph.out_html
|
|||
|
+++ b/regress/mdoc/Sh/paragraph.out_html
|
|||
|
@@ -1,11 +1,9 @@
|
|||
|
-BEGINTEST
|
|||
|
<p class="Pp">descriptive text</p>
|
|||
|
<section class="Ss">
|
|||
|
<h2 class="Ss" id="Subsection"><a class="permalink" href="#Subsection">Subsection</a></h2>
|
|||
|
-initial subsection text
|
|||
|
+<p class="Pp">initial subsection text</p>
|
|||
|
<p class="Pp">subsection paragraph</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section class="Sh">
|
|||
|
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/regress.pl
|
|||
|
+++ b/regress/regress.pl
|
|||
|
@@ -86,8 +86,12 @@ sub syshtml ($@) {
|
|||
|
if (!$state && s/.*<math class="eqn">//) {
|
|||
|
$state = 'math';
|
|||
|
next unless length;
|
|||
|
- } elsif (/^BEGINTEST/) {
|
|||
|
+ } elsif (/BEGINTEST/) {
|
|||
|
$state = 'other';
|
|||
|
+ next;
|
|||
|
+ } elsif (/ENDTEST/) {
|
|||
|
+ $state = 0;
|
|||
|
+ next;
|
|||
|
}
|
|||
|
if ($state eq 'math') {
|
|||
|
s/^ *//;
|
|||
|
@@ -98,7 +102,6 @@ sub syshtml ($@) {
|
|||
|
}
|
|||
|
}
|
|||
|
print $outfd "$_\n" if $state;
|
|||
|
- $state = 0 if /^ENDTEST/;
|
|||
|
}
|
|||
|
close $outfd;
|
|||
|
close $infd;
|
|||
|
@@ -162,10 +165,9 @@ foreach my $module (qw(roff char mdoc ma
|
|||
|
my %subvars = (MOPTS => '');
|
|||
|
parse_makefile "$module/$subdir/Makefile", \%subvars;
|
|||
|
parse_makefile "$module/Makefile.inc", \%subvars;
|
|||
|
+ delete $subvars{GOPTS};
|
|||
|
delete $subvars{SKIP_GROFF};
|
|||
|
delete $subvars{SKIP_GROFF_ASCII};
|
|||
|
- delete $subvars{TBL};
|
|||
|
- delete $subvars{EQN};
|
|||
|
my @mandoc = ('../mandoc', split ' ', $subvars{MOPTS});
|
|||
|
delete $subvars{MOPTS};
|
|||
|
my @regress_testnames;
|
|||
|
@@ -424,7 +426,7 @@ if ($count_total == 1) {
|
|||
|
print "\n";
|
|||
|
} else {
|
|||
|
print "No tests were run.\n";
|
|||
|
-}
|
|||
|
+}
|
|||
|
if ($targets{clean}) {
|
|||
|
if ($count_rm) {
|
|||
|
print "Deleted $count_rm test output files.\n";
|
|||
|
--- a/regress/roff/de/Makefile
|
|||
|
+++ b/regress/roff/de/Makefile
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
-# $OpenBSD: Makefile,v 1.12 2019/02/06 20:54:28 schwarze Exp $
|
|||
|
+# $OpenBSD: Makefile,v 1.13 2019/04/21 23:45:50 schwarze Exp $
|
|||
|
|
|||
|
-REGRESS_TARGETS = append cond escname factorial indir infinite startde tab
|
|||
|
-REGRESS_TARGETS += TH Dd
|
|||
|
+REGRESS_TARGETS = append cond empty escname factorial
|
|||
|
+REGRESS_TARGETS += indir infinite startde tab TH Dd
|
|||
|
LINT_TARGETS = escname indir infinite
|
|||
|
|
|||
|
# groff-1.22.4 defect:
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/roff/de/empty.in
|
|||
|
@@ -0,0 +1,18 @@
|
|||
|
+.\" $OpenBSD: empty.in,v 1.1 2019/04/21 23:45:50 schwarze Exp $
|
|||
|
+.Dd $Mdocdate$
|
|||
|
+.Dt DE-EMPTY 1
|
|||
|
+.Os
|
|||
|
+.Sh NAME
|
|||
|
+.Nm de-empty
|
|||
|
+.Nd empty user-defined macro with arguments
|
|||
|
+.Sh DESCRIPTION
|
|||
|
+initial text
|
|||
|
+.de empty
|
|||
|
+..
|
|||
|
+.de real
|
|||
|
+arg=\\$1
|
|||
|
+.empty wrong
|
|||
|
+arg=\\$1
|
|||
|
+..
|
|||
|
+.real right
|
|||
|
+final text
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/roff/de/empty.out_ascii
|
|||
|
@@ -0,0 +1,9 @@
|
|||
|
+DE-EMPTY(1) General Commands Manual DE-EMPTY(1)
|
|||
|
+
|
|||
|
+NNAAMMEE
|
|||
|
+ ddee--eemmppttyy - empty user-defined macro with arguments
|
|||
|
+
|
|||
|
+DDEESSCCRRIIPPTTIIOONN
|
|||
|
+ initial text arg=right arg=right final text
|
|||
|
+
|
|||
|
+OpenBSD April 21, 2019 OpenBSD
|
|||
|
--- a/regress/roff/esc/f.out_html
|
|||
|
+++ b/regress/roff/esc/f.out_html
|
|||
|
@@ -1,6 +1,4 @@
|
|||
|
-BEGINTEST
|
|||
|
numbers: <b><i>bolditalic</i></b><b>bold</b><i>italic</i>roman
|
|||
|
letters: <b>bold</b><i>italic</i><b>back</b><b><i>bolditalic</i></b>roman
|
|||
|
multiletter: <b>bold</b>empty<i>italic</i>back<b><i>bolditalic</i></b>roman
|
|||
|
typewriter: <span class="Li">roman</span><b>bold</b><span class="Li">roman</span><i>italic</i>roman
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/roff/ft/badargs.out_html
|
|||
|
+++ b/regress/roff/ft/badargs.out_html
|
|||
|
@@ -1,9 +1,6 @@
|
|||
|
-BEGINTEST
|
|||
|
-<br/>
|
|||
|
-default font <i></i><i>italic</i> <b><i></i></b><b><i>bold italic</i></b>
|
|||
|
- <span class="Li"></span><span class="Li">typeqriter</span>
|
|||
|
- <span class="Li"></span> <span class="Li">roman</span> <b></b><b>bold</b>
|
|||
|
- <i></i> <i>italic</i> <b></b><b>bold</b> <b>still bold</b>
|
|||
|
- <i></i><i>italic</i> <i></i><i>back to bold</i> <i></i><i>back to italic</i>
|
|||
|
-<br/>
|
|||
|
-ENDTEST
|
|||
|
+ <br/>
|
|||
|
+ default font <i>italic</i> <b><i>bold italic</i></b>
|
|||
|
+ <span class="Li">typeqriter</span> <span class="Li">roman</span> <b>bold</b>
|
|||
|
+ <i>italic</i> <b>bold</b> <b>still bold</b> <i>italic</i> <i>back to
|
|||
|
+ bold</i> <i>back to italic</i>
|
|||
|
+ <br/>
|
|||
|
--- a/regress/roff/sp/fill-man.out_html
|
|||
|
+++ b/regress/roff/sp/fill-man.out_html
|
|||
|
@@ -1,4 +1,3 @@
|
|||
|
-BEGINTEST in fill mode:
|
|||
|
<p class="Pp">switch to no-fill mode:</p>
|
|||
|
<pre>
|
|||
|
in no-fill mode:
|
|||
|
@@ -6,4 +5,3 @@ in no-fill mode:
|
|||
|
back to
|
|||
|
fill mode:
|
|||
|
</pre>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/roff/string/dotT.out_html
|
|||
|
+++ b/regress/roff/string/dotT.out_html
|
|||
|
@@ -1,5 +1,3 @@
|
|||
|
-BEGINTEST
|
|||
|
<p class="Pp">We are using the html device.</p>
|
|||
|
<p class="Pp">The device name can be overridden.</p>
|
|||
|
<pre>
|
|||
|
-ENDTEST
|
|||
|
--- a/regress/roff/while/Makefile
|
|||
|
+++ b/regress/roff/while/Makefile
|
|||
|
@@ -1,6 +1,6 @@
|
|||
|
-# $OpenBSD: Makefile,v 1.1 2018/08/24 22:56:37 schwarze Exp $
|
|||
|
+# $OpenBSD: Makefile,v 1.2 2019/04/21 22:43:00 schwarze Exp $
|
|||
|
|
|||
|
-REGRESS_TARGETS = basic badargs into nesting outof
|
|||
|
+REGRESS_TARGETS = basic badargs break into nesting outof
|
|||
|
LINT_TARGETS = badargs into nesting outof
|
|||
|
|
|||
|
# mandoc defects:
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/roff/while/break.in
|
|||
|
@@ -0,0 +1,16 @@
|
|||
|
+.\" $OpenBSD: break.in,v 1.1 2019/04/21 22:43:00 schwarze Exp $
|
|||
|
+.Dd $Mdocdate$
|
|||
|
+.Dt WHILE-BREAK 1
|
|||
|
+.Os
|
|||
|
+.Sh NAME
|
|||
|
+.Nm while-break
|
|||
|
+.Nd break request inside a while loop
|
|||
|
+.Sh DESCRIPTION
|
|||
|
+initial text
|
|||
|
+.nr cnt 11 1
|
|||
|
+.while n \{\
|
|||
|
+\n-[cnt]
|
|||
|
+.if !\n[cnt] .break
|
|||
|
+\(en
|
|||
|
+.\}
|
|||
|
+final text
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/roff/while/break.out_ascii
|
|||
|
@@ -0,0 +1,9 @@
|
|||
|
+WHILE-BREAK(1) General Commands Manual WHILE-BREAK(1)
|
|||
|
+
|
|||
|
+NNAAMMEE
|
|||
|
+ wwhhiillee--bbrreeaakk - break request inside a while loop
|
|||
|
+
|
|||
|
+DDEESSCCRRIIPPTTIIOONN
|
|||
|
+ initial text 10 - 9 - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0 final text
|
|||
|
+
|
|||
|
+OpenBSD April 21, 2019 OpenBSD
|
|||
|
--- a/regress/tbl/Makefile.inc
|
|||
|
+++ b/regress/tbl/Makefile.inc
|
|||
|
@@ -1,16 +1,7 @@
|
|||
|
-# $OpenBSD: Makefile.inc,v 1.2 2015/02/03 19:37:25 schwarze Exp $
|
|||
|
-
|
|||
|
-TBL = /usr/local/bin/tbl
|
|||
|
+# $OpenBSD: Makefile.inc,v 1.4 2020/01/08 10:17:15 schwarze Exp $
|
|||
|
|
|||
|
SKIP_TMAN ?= ALL
|
|||
|
SKIP_MARKDOWN ?= ALL
|
|||
|
-
|
|||
|
-
|
|||
|
-# OpenBSD only: maintainer targets
|
|||
|
-
|
|||
|
-.for t in ${REGRESS_TARGETS}
|
|||
|
-${t}.out_ascii: ${t}.in
|
|||
|
- ${TBL} ${.ALLSRC} | ${NROFF} ${NOPTS} -Tascii > ${.TARGET}
|
|||
|
-.endfor
|
|||
|
+GOPTS = -t
|
|||
|
|
|||
|
.include "../Makefile.inc"
|
|||
|
--- a/regress/tbl/data/Makefile
|
|||
|
+++ b/regress/tbl/data/Makefile
|
|||
|
@@ -1,6 +1,7 @@
|
|||
|
-# $OpenBSD: Makefile,v 1.4 2017/07/04 20:59:17 schwarze Exp $
|
|||
|
+# $OpenBSD: Makefile,v 1.5 2019/07/18 14:38:47 schwarze Exp $
|
|||
|
|
|||
|
-REGRESS_TARGETS = blankline block_unclosed block_width block_wrap empty insert
|
|||
|
+REGRESS_TARGETS = blankline block_empty block_unclosed block_width
|
|||
|
+REGRESS_TARGETS += block_wrap empty insert
|
|||
|
LINT_TARGETS = block_unclosed empty insert
|
|||
|
|
|||
|
# groff-1.22.3 defect:
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/tbl/data/block_empty.in
|
|||
|
@@ -0,0 +1,19 @@
|
|||
|
+.\" $OpenBSD: block_empty.in,v 1.1 2019/07/18 14:38:47 schwarze Exp $
|
|||
|
+.TH TBL-DATA-BLOCK_EMPTY 1 "July 17, 2019"
|
|||
|
+.SH NAME
|
|||
|
+tbl-data-block_empty \- empty text block
|
|||
|
+.SH DESCRIPTION
|
|||
|
+normal text
|
|||
|
+.TS
|
|||
|
+|l|l|.
|
|||
|
+_
|
|||
|
+A test
|
|||
|
+_
|
|||
|
+table T{
|
|||
|
+T}
|
|||
|
+_
|
|||
|
+.TE
|
|||
|
+.SH AUTHORS
|
|||
|
+.MT rea@FreeBSD.org
|
|||
|
+Eygene Ryabinkin
|
|||
|
+.ME
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/tbl/data/block_empty.out_ascii
|
|||
|
@@ -0,0 +1,22 @@
|
|||
|
+TBL-DATA-BLOCK_EMPTY(1) General Commands Manual TBL-DATA-BLOCK_EMPTY(1)
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+NNAAMMEE
|
|||
|
+ tbl-data-block_empty - empty text block
|
|||
|
+
|
|||
|
+DDEESSCCRRIIPPTTIIOONN
|
|||
|
+ normal text
|
|||
|
+
|
|||
|
+ +------+------+
|
|||
|
+ |A | test |
|
|||
|
+ +------+------+
|
|||
|
+ |table | |
|
|||
|
+ +------+------+
|
|||
|
+
|
|||
|
+AAUUTTHHOORRSS
|
|||
|
+ Eygene Ryabinkin <rea@FreeBSD.org>
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+OpenBSD July 17, 2019 TBL-DATA-BLOCK_EMPTY(1)
|
|||
|
--- a/regress/tbl/layout/Makefile
|
|||
|
+++ b/regress/tbl/layout/Makefile
|
|||
|
@@ -1,8 +1,8 @@
|
|||
|
-# $OpenBSD: Makefile,v 1.2 2015/01/30 00:27:09 schwarze Exp $
|
|||
|
+# $OpenBSD: Makefile,v 1.6 2020/01/11 20:56:26 schwarze Exp $
|
|||
|
|
|||
|
-REGRESS_TARGETS = center complex empty emptyline
|
|||
|
-REGRESS_TARGETS += lines lines-nogroff numbers span
|
|||
|
-LINT_TARGETS = complex empty
|
|||
|
+REGRESS_TARGETS = badspan center complex empty emptycol emptyline
|
|||
|
+REGRESS_TARGETS += lines lines-nogroff numbers shortlines span
|
|||
|
+LINT_TARGETS = badspan complex empty
|
|||
|
|
|||
|
# groff-1.22.3 defects:
|
|||
|
# - When the layout is completely empty,
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/tbl/layout/badspan.in
|
|||
|
@@ -0,0 +1,13 @@
|
|||
|
+.\" $OpenBSD: badspan.in,v 1.1 2020/01/11 20:56:26 schwarze Exp $
|
|||
|
+.TH TBL-LAYOUT-BADSPAN 1 "January 11, 2020"
|
|||
|
+.SH NAME
|
|||
|
+tbl-layout-badspan \- invalid spanned cells
|
|||
|
+.SH DESCRIPTION
|
|||
|
+normal text
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+S L S S
|
|||
|
+L L L L L L.
|
|||
|
+span:end
|
|||
|
+1:2:3:4:5:6
|
|||
|
+.TE
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/tbl/layout/badspan.out_ascii
|
|||
|
@@ -0,0 +1,18 @@
|
|||
|
+TBL-LAYOUT-BADSPAN(1) General Commands Manual TBL-LAYOUT-BADSPAN(1)
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+NNAAMMEE
|
|||
|
+ tbl-layout-badspan - invalid spanned cells
|
|||
|
+
|
|||
|
+DDEESSCCRRIIPPTTIIOONN
|
|||
|
+ normal text
|
|||
|
+
|
|||
|
+ +--+-----------+-----+---+
|
|||
|
+ | | span | end | |
|
|||
|
+ +--+---+---+---+-----+---+
|
|||
|
+ |1 | 2 | 3 | 4 | 5 | 6 |
|
|||
|
+ +--+---+---+---+-----+---+
|
|||
|
+
|
|||
|
+
|
|||
|
+OpenBSD January 11, 2020 TBL-LAYOUT-BADSPAN(1)
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/tbl/layout/badspan.out_lint
|
|||
|
@@ -0,0 +1 @@
|
|||
|
+mandoc: badspan.in:9:1: WARNING: tbl line starts with span
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/tbl/layout/emptycol.in
|
|||
|
@@ -0,0 +1,49 @@
|
|||
|
+.\" $OpenBSD: emptycol.in,v 1.1 2019/12/31 22:49:17 schwarze Exp $
|
|||
|
+.TH TBL-LAYOUT-EMPTYCOL 1 "December 31, 2019"
|
|||
|
+.SH NAME
|
|||
|
+tbl-layout-emptycol \- empty columns in tables
|
|||
|
+.SH DESCRIPTION
|
|||
|
+missing final column:
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+L L L
|
|||
|
+L L.
|
|||
|
+1:2
|
|||
|
+a:b
|
|||
|
+.TE
|
|||
|
+.sp
|
|||
|
+empty final column:
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+L L L
|
|||
|
+L L.
|
|||
|
+1:2:
|
|||
|
+a:b
|
|||
|
+.TE
|
|||
|
+.sp
|
|||
|
+final column with zero-width content:
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+L L L
|
|||
|
+L L.
|
|||
|
+1:2:\&
|
|||
|
+a:b
|
|||
|
+.TE
|
|||
|
+.sp
|
|||
|
+empty middle column:
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+L L L
|
|||
|
+L.
|
|||
|
+1::3
|
|||
|
+a
|
|||
|
+.TE
|
|||
|
+.sp
|
|||
|
+span crossing empty middle column:
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+L L L
|
|||
|
+L S S.
|
|||
|
+1::3
|
|||
|
+span
|
|||
|
+.TE
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/tbl/layout/emptycol.out_ascii
|
|||
|
@@ -0,0 +1,46 @@
|
|||
|
+TBL-LAYOUT-EMPTYCOL(1) General Commands Manual TBL-LAYOUT-EMPTYCOL(1)
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+NNAAMMEE
|
|||
|
+ tbl-layout-emptycol - empty columns in tables
|
|||
|
+
|
|||
|
+DDEESSCCRRIIPPTTIIOONN
|
|||
|
+ missing final column:
|
|||
|
+
|
|||
|
+ +--+---+---+
|
|||
|
+ |1 | 2 | |
|
|||
|
+ +--+---+---+
|
|||
|
+ |a | b | |
|
|||
|
+ +--+---+---+
|
|||
|
+ empty final column:
|
|||
|
+
|
|||
|
+ +--+---+---+
|
|||
|
+ |1 | 2 | |
|
|||
|
+ +--+---+---+
|
|||
|
+ |a | b | |
|
|||
|
+ +--+---+---+
|
|||
|
+ final column with zero-width content:
|
|||
|
+
|
|||
|
+ +--+---+---+
|
|||
|
+ |1 | 2 | |
|
|||
|
+ +--+---+---+
|
|||
|
+ |a | b | |
|
|||
|
+ +--+---+---+
|
|||
|
+ empty middle column:
|
|||
|
+
|
|||
|
+ +--+---+---+
|
|||
|
+ |1 | | 3 |
|
|||
|
+ +--+---+---+
|
|||
|
+ |a | | |
|
|||
|
+ +--+---+---+
|
|||
|
+ span crossing empty middle column:
|
|||
|
+
|
|||
|
+ +--+---+---+
|
|||
|
+ |1 | | 3 |
|
|||
|
+ +--+---+---+
|
|||
|
+ |span |
|
|||
|
+ +----------+
|
|||
|
+
|
|||
|
+
|
|||
|
+OpenBSD December 31, 2019 TBL-LAYOUT-EMPTYCOL(1)
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/tbl/layout/shortlines.in
|
|||
|
@@ -0,0 +1,47 @@
|
|||
|
+.\" $OpenBSD: shortlines.in,v 1.2 2020/01/11 20:56:26 schwarze Exp $
|
|||
|
+.TH TBL-LAYOUT-SHORTLINES 1 "January 11, 2020"
|
|||
|
+.SH NAME
|
|||
|
+tbl-layout-shortlines \- table lines of different length
|
|||
|
+.SH DESCRIPTION
|
|||
|
+normal text
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+L L
|
|||
|
+L
|
|||
|
+L L.
|
|||
|
+left:right
|
|||
|
+short
|
|||
|
+left:right
|
|||
|
+.TE
|
|||
|
+.sp
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+L L
|
|||
|
+L
|
|||
|
+L
|
|||
|
+L L.
|
|||
|
+left:right
|
|||
|
+first short
|
|||
|
+second short
|
|||
|
+left:right
|
|||
|
+.TE
|
|||
|
+.sp
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+L L L
|
|||
|
+L L
|
|||
|
+L.
|
|||
|
+left:middle:right
|
|||
|
+short:line
|
|||
|
+very short
|
|||
|
+.TE
|
|||
|
+.sp
|
|||
|
+.TS
|
|||
|
+allbox tab(:);
|
|||
|
+L
|
|||
|
+L
|
|||
|
+L L L.
|
|||
|
+very short
|
|||
|
+short:line
|
|||
|
+left:middle:right
|
|||
|
+.TE
|
|||
|
--- /dev/null
|
|||
|
+++ b/regress/tbl/layout/shortlines.out_ascii
|
|||
|
@@ -0,0 +1,46 @@
|
|||
|
+TBL-LAYOUT-SHORTLINES(1) General Commands Manual TBL-LAYOUT-SHORTLINES(1)
|
|||
|
+
|
|||
|
+
|
|||
|
+
|
|||
|
+NNAAMMEE
|
|||
|
+ tbl-layout-shortlines - table lines of different length
|
|||
|
+
|
|||
|
+DDEESSCCRRIIPPTTIIOONN
|
|||
|
+ normal text
|
|||
|
+
|
|||
|
+ +------+-------+
|
|||
|
+ |left | right |
|
|||
|
+ +------+-------+
|
|||
|
+ |short | |
|
|||
|
+ +------+-------+
|
|||
|
+ |left | right |
|
|||
|
+ +------+-------+
|
|||
|
+
|
|||
|
+ +-------------+-------+
|
|||
|
+ |left | right |
|
|||
|
+ +-------------+-------+
|
|||
|
+ |first short | |
|
|||
|
+ +-------------+-------+
|
|||
|
+ |second short | |
|
|||
|
+ +-------------+-------+
|
|||
|
+ |left | right |
|
|||
|
+ +-------------+-------+
|
|||
|
+
|
|||
|
+ +-----------+--------+-------+
|
|||
|
+ |left | middle | right |
|
|||
|
+ +-----------+--------+-------+
|
|||
|
+ |short | line | |
|
|||
|
+ +-----------+--------+-------+
|
|||
|
+ |very short | | |
|
|||
|
+ +-----------+--------+-------+
|
|||
|
+
|
|||
|
+ +-----------+--------+-------+
|
|||
|
+ |very short | | |
|
|||
|
+ +-----------+--------+-------+
|
|||
|
+ |short | line | |
|
|||
|
+ +-----------+--------+-------+
|
|||
|
+ |left | middle | right |
|
|||
|
+ +-----------+--------+-------+
|
|||
|
+
|
|||
|
+
|
|||
|
+OpenBSD January 11, 2020 TBL-LAYOUT-SHORTLINES(1)
|
|||
|
--- a/roff.7
|
|||
|
+++ b/roff.7
|
|||
|
@@ -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 current
|
|||
|
.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
|
|||
|
--- a/roff.c
|
|||
|
+++ b/roff.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: roff.c,v 1.363 2019/02/06 21:11:43 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2010-2015, 2017-2020 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
|
|||
|
@@ -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);
|
|||
|
@@ -351,7 +355,7 @@ const char *__roff_name[MAN_MAX + 1] = {
|
|||
|
"Lk", "Mt", "Brq", "Bro",
|
|||
|
"Brc", "%C", "Es", "En",
|
|||
|
"Dx", "%Q", "%U", "Ta",
|
|||
|
- NULL,
|
|||
|
+ "Tg", NULL,
|
|||
|
"TH", "SH", "SS", "TP",
|
|||
|
"TQ",
|
|||
|
"LP", "PP", "P", "IP",
|
|||
|
@@ -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
|
|||
|
|
|||
|
/*
|
|||
|
* 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)
|
|||
|
@@ -767,6 +771,7 @@ void
|
|||
|
roff_reset(struct roff *r)
|
|||
|
{
|
|||
|
roff_free1(r);
|
|||
|
+ r->options |= MPARSE_COMMENT;
|
|||
|
r->format = r->options & (MPARSE_MDOC | MPARSE_MAN);
|
|||
|
r->control = '\0';
|
|||
|
r->escape = '\\';
|
|||
|
@@ -779,7 +784,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++)
|
|||
|
@@ -796,7 +801,7 @@ roff_alloc(int options)
|
|||
|
|
|||
|
r = mandoc_calloc(1, sizeof(struct roff));
|
|||
|
r->reqtab = roffhash_alloc(0, ROFF_RENAMED);
|
|||
|
- r->options = options;
|
|||
|
+ r->options = options | MPARSE_COMMENT;
|
|||
|
r->format = options & (MPARSE_MDOC | MPARSE_MAN);
|
|||
|
r->mstackpos = -1;
|
|||
|
r->rstackpos = -1;
|
|||
|
@@ -1242,7 +1247,7 @@ roff_expand(struct roff *r, struct buf *
|
|||
|
* in the syntax tree.
|
|||
|
*/
|
|||
|
|
|||
|
- if (newesc != ASCII_ESC && r->format == 0) {
|
|||
|
+ if (newesc != ASCII_ESC && r->options & MPARSE_COMMENT) {
|
|||
|
while (*ep == ' ' || *ep == '\t')
|
|||
|
ep--;
|
|||
|
ep[1] = '\0';
|
|||
|
@@ -1586,7 +1591,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. */
|
|||
|
@@ -1811,8 +1816,10 @@ roff_parseln(struct roff *r, int ln, str
|
|||
|
roff_addtbl(r->man, ln, r->tbl);
|
|||
|
return e;
|
|||
|
}
|
|||
|
- if ( ! ctl)
|
|||
|
+ if ( ! ctl) {
|
|||
|
+ r->options &= ~MPARSE_COMMENT;
|
|||
|
return roff_parsetext(r, buf, pos, offs) | e;
|
|||
|
+ }
|
|||
|
|
|||
|
/* Skip empty request lines. */
|
|||
|
|
|||
|
@@ -1835,6 +1842,7 @@ roff_parseln(struct roff *r, int ln, str
|
|||
|
|
|||
|
/* No scope is open. This is a new request or macro. */
|
|||
|
|
|||
|
+ r->options &= ~MPARSE_COMMENT;
|
|||
|
spos = pos;
|
|||
|
t = roff_parse(r, buf->buf, &pos, ln, ppos);
|
|||
|
|
|||
|
@@ -2002,6 +2010,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 +2028,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 +2252,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;
|
|||
|
@@ -2276,15 +2294,39 @@ roff_cond_sub(ROFF_ARGS)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
+ t = roff_parse(r, buf->buf, &pos, ln, ppos);
|
|||
|
+
|
|||
|
+ /* For now, let high level macros abort .ce mode. */
|
|||
|
+
|
|||
|
+ if (roffce_node != NULL &&
|
|||
|
+ (t == TOKEN_NONE || t == ROFF_Dd || t == ROFF_EQ ||
|
|||
|
+ t == ROFF_TH || t == ROFF_TS)) {
|
|||
|
+ r->man->last = roffce_node;
|
|||
|
+ r->man->next = ROFF_NEXT_SIBLING;
|
|||
|
+ roffce_lines = 0;
|
|||
|
+ roffce_node = NULL;
|
|||
|
+ }
|
|||
|
+
|
|||
|
/*
|
|||
|
* Fully handle known macros when they are structurally
|
|||
|
* required or when the conditional evaluated to true.
|
|||
|
*/
|
|||
|
|
|||
|
- 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 +3524,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 +3857,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 +3909,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;
|
|||
|
}
|
|||
|
|
|||
|
--- a/roff.h
|
|||
|
+++ b/roff.h
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: roff.h,v 1.69 2019/03/04 13:01:57 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2013-2015, 2017-2020 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
|
|||
|
@@ -437,6 +437,7 @@ enum roff_tok {
|
|||
|
MDOC__Q,
|
|||
|
MDOC__U,
|
|||
|
MDOC_Ta,
|
|||
|
+ MDOC_Tg,
|
|||
|
MDOC_MAX,
|
|||
|
MAN_TH,
|
|||
|
MAN_SH,
|
|||
|
--- a/roff_html.c
|
|||
|
+++ b/roff_html.c
|
|||
|
@@ -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
|
|||
|
--- a/tag.c
|
|||
|
+++ b/tag.c
|
|||
|
@@ -1,6 +1,6 @@
|
|||
|
/* $Id: tag.c,v 1.21 2018/11/22 11:30:23 schwarze Exp $ */
|
|||
|
/*
|
|||
|
- * Copyright (c) 2015, 2016, 2018 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2015,2016,2018,2019,2020 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,8 @@
|
|||
|
|
|||
|
#include <sys/types.h>
|
|||
|
|
|||
|
-#if HAVE_ERR
|
|||
|
-#include <err.h>
|
|||
|
-#endif
|
|||
|
+#include <assert.h>
|
|||
|
+#include <errno.h>
|
|||
|
#include <limits.h>
|
|||
|
#include <signal.h>
|
|||
|
#include <stddef.h>
|
|||
|
@@ -32,6 +31,7 @@
|
|||
|
|
|||
|
#include "mandoc_aux.h"
|
|||
|
#include "mandoc_ohash.h"
|
|||
|
+#include "mandoc.h"
|
|||
|
#include "tag.h"
|
|||
|
|
|||
|
struct tag_entry {
|
|||
|
@@ -54,7 +54,7 @@ static struct tag_files tag_files;
|
|||
|
* but for simplicity, create it anyway.
|
|||
|
*/
|
|||
|
struct tag_files *
|
|||
|
-tag_init(void)
|
|||
|
+tag_init(char *tagname)
|
|||
|
{
|
|||
|
struct sigaction sa;
|
|||
|
int ofd;
|
|||
|
@@ -62,6 +62,7 @@ tag_init(void)
|
|||
|
ofd = -1;
|
|||
|
tag_files.tfd = -1;
|
|||
|
tag_files.tcpgid = -1;
|
|||
|
+ tag_files.tagname = tagname;
|
|||
|
|
|||
|
/* Clean up when dying from a signal. */
|
|||
|
|
|||
|
@@ -83,8 +84,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 +95,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);
|
|||
|
|
|||
|
/*
|
|||
|
@@ -120,6 +131,7 @@ fail:
|
|||
|
*tag_files.tfn = '\0';
|
|||
|
tag_files.ofd = -1;
|
|||
|
tag_files.tfd = -1;
|
|||
|
+ tag_files.tagname = NULL;
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
@@ -135,6 +147,7 @@ tag_put(const char *s, int prio, size_t
|
|||
|
size_t len;
|
|||
|
unsigned int slot;
|
|||
|
|
|||
|
+ assert(prio <= TAG_FALLBACK);
|
|||
|
if (tag_files.tfd <= 0)
|
|||
|
return;
|
|||
|
|
|||
|
@@ -142,17 +155,17 @@ tag_put(const char *s, int prio, size_t
|
|||
|
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;
|
|||
|
|
|||
|
se = s + len;
|
|||
|
- if (*se != '\0')
|
|||
|
- prio = INT_MAX;
|
|||
|
+ if (*se != '\0' && prio < TAG_WEAK)
|
|||
|
+ prio = TAG_WEAK;
|
|||
|
|
|||
|
slot = ohash_qlookupi(&tag_data, s, &se);
|
|||
|
entry = ohash_find(&tag_data, slot);
|
|||
|
@@ -172,25 +185,25 @@ tag_put(const char *s, int prio, size_t
|
|||
|
|
|||
|
/*
|
|||
|
* Lower priority numbers take precedence,
|
|||
|
- * but 0 is special.
|
|||
|
- * A tag with priority 0 is only used
|
|||
|
+ * but TAG_FALLBACK is special.
|
|||
|
+ * A tag with priority TAG_FALLBACK is only used
|
|||
|
* if the tag occurs exactly once.
|
|||
|
*/
|
|||
|
|
|||
|
- if (prio == 0) {
|
|||
|
- if (entry->prio == 0)
|
|||
|
- entry->prio = -1;
|
|||
|
+ if (prio == TAG_FALLBACK) {
|
|||
|
+ if (entry->prio == TAG_FALLBACK)
|
|||
|
+ entry->prio = TAG_DELETE;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/* A better entry is already present, ignore the new one. */
|
|||
|
|
|||
|
- if (entry->prio > 0 && entry->prio < prio)
|
|||
|
+ if (entry->prio < prio)
|
|||
|
return;
|
|||
|
|
|||
|
/* The existing entry is worse, clear it. */
|
|||
|
|
|||
|
- if (entry->prio < 1 || entry->prio > prio)
|
|||
|
+ if (entry->prio > prio)
|
|||
|
entry->nlines = 0;
|
|||
|
}
|
|||
|
|
|||
|
@@ -216,21 +229,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 < TAG_DELETE) {
|
|||
|
+ 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 +260,10 @@ tag_write(void)
|
|||
|
else
|
|||
|
close(tag_files.tfd);
|
|||
|
tag_files.tfd = -1;
|
|||
|
+ if (empty) {
|
|||
|
+ unlink(tag_files.tfn);
|
|||
|
+ *tag_files.tfn = '\0';
|
|||
|
+ }
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
--- a/tag.h
|
|||
|
+++ b/tag.h
|
|||
|
@@ -1,6 +1,6 @@
|
|||
|
/* $Id: tag.h,v 1.8 2018/11/22 11:30:23 schwarze Exp $ */
|
|||
|
/*
|
|||
|
- * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2015, 2018, 2019, 2020 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,6 +15,17 @@
|
|||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
*/
|
|||
|
|
|||
|
+/*
|
|||
|
+ * Tagging priorities.
|
|||
|
+ * Lower numbers indicate higher importance.
|
|||
|
+ */
|
|||
|
+#define TAG_MANUAL 1 /* Set with a .Tg macro. */
|
|||
|
+#define TAG_STRONG 2 /* Good automatic tagging. */
|
|||
|
+#define TAG_WEAK (INT_MAX - 2) /* Dubious automatic tagging. */
|
|||
|
+#define TAG_FALLBACK (INT_MAX - 1) /* Tag only used if unique. */
|
|||
|
+#define TAG_DELETE (INT_MAX) /* Tag not used at all. */
|
|||
|
+
|
|||
|
+
|
|||
|
struct tag_files {
|
|||
|
char ofn[20];
|
|||
|
char tfn[20];
|
|||
|
@@ -26,7 +37,7 @@ struct tag_files {
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
-struct tag_files *tag_init(void);
|
|||
|
+struct tag_files *tag_init(char *);
|
|||
|
void tag_put(const char *, int, size_t);
|
|||
|
void tag_write(void);
|
|||
|
void tag_unlink(void);
|
|||
|
--- a/tbl_data.c
|
|||
|
+++ b/tbl_data.c
|
|||
|
@@ -21,6 +21,7 @@
|
|||
|
|
|||
|
#include <assert.h>
|
|||
|
#include <ctype.h>
|
|||
|
+#include <stdint.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
@@ -73,6 +74,7 @@ getdata(struct tbl_node *tbl, struct tbl
|
|||
|
if (dp->layout->last->col + 1 < dp->opts->cols) {
|
|||
|
cp = mandoc_calloc(1, sizeof(*cp));
|
|||
|
cp->pos = TBL_CELL_LEFT;
|
|||
|
+ cp->spacing = SIZE_MAX;
|
|||
|
dp->layout->last->next = cp;
|
|||
|
cp->col = dp->layout->last->col + 1;
|
|||
|
dp->layout->last = cp;
|
|||
|
--- a/tbl_html.c
|
|||
|
+++ b/tbl_html.c
|
|||
|
@@ -25,6 +25,7 @@
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
#include "mandoc.h"
|
|||
|
+#include "roff.h"
|
|||
|
#include "tbl.h"
|
|||
|
#include "out.h"
|
|||
|
#include "html.h"
|
|||
|
--- a/tbl_term.c
|
|||
|
+++ b/tbl_term.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: tbl_term.c,v 1.68 2019/02/09 21:02:47 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2011-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2011-2020 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
|
|||
|
@@ -46,7 +46,8 @@ static void tbl_fill_border(struct termp
|
|||
|
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
|
|||
|
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
|
|||
|
|
|||
|
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. */
|
|||
|
@@ -266,11 +267,11 @@ term_tbl(struct termp *tp, const struct
|
|||
|
hspans--;
|
|||
|
continue;
|
|||
|
}
|
|||
|
- if (dp == NULL)
|
|||
|
- continue;
|
|||
|
- hspans = dp->hspans;
|
|||
|
- if (ic || sp->layout->first->pos != TBL_CELL_SPAN)
|
|||
|
+ if (dp != NULL &&
|
|||
|
+ (ic || sp->layout->first->pos != TBL_CELL_SPAN)) {
|
|||
|
+ hspans = dp->hspans;
|
|||
|
dp = dp->next;
|
|||
|
+ }
|
|||
|
}
|
|||
|
|
|||
|
/* Set up a column for a right vertical frame. */
|
|||
|
@@ -301,11 +302,11 @@ term_tbl(struct termp *tp, const struct
|
|||
|
tp->tcol++;
|
|||
|
tp->col = 0;
|
|||
|
tbl_data(tp, sp->opts, cp, dp, tp->tbl.cols + ic);
|
|||
|
- if (dp == NULL)
|
|||
|
- continue;
|
|||
|
- hspans = dp->hspans;
|
|||
|
- if (cp->pos != TBL_CELL_SPAN)
|
|||
|
+ if (dp != NULL &&
|
|||
|
+ (ic || sp->layout->first->pos != TBL_CELL_SPAN)) {
|
|||
|
+ hspans = dp->hspans;
|
|||
|
dp = dp->next;
|
|||
|
+ }
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
@@ -342,7 +343,7 @@ term_tbl(struct termp *tp, const struct
|
|||
|
|
|||
|
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 :
|
|||
|
@@ -424,11 +425,10 @@ term_tbl(struct termp *tp, const struct
|
|||
|
cp = cp->next;
|
|||
|
continue;
|
|||
|
}
|
|||
|
- if (dp != NULL) {
|
|||
|
+ if (dp != NULL && (ic ||
|
|||
|
+ sp->layout->first->pos != TBL_CELL_SPAN)) {
|
|||
|
hspans = dp->hspans;
|
|||
|
- if (ic || sp->layout->first->pos
|
|||
|
- != TBL_CELL_SPAN)
|
|||
|
- dp = dp->next;
|
|||
|
+ dp = dp->next;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
@@ -557,12 +557,12 @@ term_tbl(struct termp *tp, const struct
|
|||
|
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 +571,7 @@ term_tbl(struct termp *tp, const struct
|
|||
|
} 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 +579,10 @@ term_tbl(struct termp *tp, const struct
|
|||
|
|
|||
|
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 +593,7 @@ tbl_hrule(struct termp *tp, const struct
|
|||
|
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 +602,11 @@ tbl_hrule(struct termp *tp, const struct
|
|||
|
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 +621,19 @@ tbl_hrule(struct termp *tp, const struct
|
|||
|
(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 +652,10 @@ tbl_hrule(struct termp *tp, const struct
|
|||
|
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 +665,9 @@ tbl_hrule(struct termp *tp, const struct
|
|||
|
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 +681,8 @@ tbl_hrule(struct termp *tp, const struct
|
|||
|
|
|||
|
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. */
|
|||
|
--- a/term.c
|
|||
|
+++ b/term.c
|
|||
|
@@ -281,6 +281,8 @@ term_fill(struct termp *p, size_t *nbr,
|
|||
|
case ASCII_BREAK:
|
|||
|
vn = vis;
|
|||
|
break;
|
|||
|
+ default:
|
|||
|
+ abort();
|
|||
|
}
|
|||
|
/* Can break at the end of a word. */
|
|||
|
if (breakline || vn > vtarget)
|
|||
|
--- a/tree.c
|
|||
|
+++ b/tree.c
|
|||
|
@@ -1,7 +1,7 @@
|
|||
|
/* $Id: tree.c,v 1.84 2019/01/01 05:56:34 schwarze Exp $ */
|
|||
|
/*
|
|||
|
* Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
|||
|
- * Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
|
|||
|
+ * Copyright (c) 2013-2015, 2017-2020 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
|
|||
|
@@ -34,6 +34,7 @@
|
|||
|
#include "main.h"
|
|||
|
|
|||
|
static void print_box(const struct eqn_box *, int);
|
|||
|
+static void print_cellt(enum tbl_cellt);
|
|||
|
static void print_man(const struct roff_node *, int);
|
|||
|
static void print_meta(const struct roff_meta *);
|
|||
|
static void print_mdoc(const struct roff_node *, int);
|
|||
|
@@ -374,11 +375,72 @@ print_box(const struct eqn_box *ep, int
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
+print_cellt(enum tbl_cellt pos)
|
|||
|
+{
|
|||
|
+ switch(pos) {
|
|||
|
+ case TBL_CELL_LEFT:
|
|||
|
+ putchar('L');
|
|||
|
+ break;
|
|||
|
+ case TBL_CELL_LONG:
|
|||
|
+ putchar('a');
|
|||
|
+ break;
|
|||
|
+ case TBL_CELL_CENTRE:
|
|||
|
+ putchar('c');
|
|||
|
+ break;
|
|||
|
+ case TBL_CELL_RIGHT:
|
|||
|
+ putchar('r');
|
|||
|
+ break;
|
|||
|
+ case TBL_CELL_NUMBER:
|
|||
|
+ putchar('n');
|
|||
|
+ break;
|
|||
|
+ case TBL_CELL_SPAN:
|
|||
|
+ putchar('s');
|
|||
|
+ break;
|
|||
|
+ case TBL_CELL_DOWN:
|
|||
|
+ putchar('^');
|
|||
|
+ break;
|
|||
|
+ case TBL_CELL_HORIZ:
|
|||
|
+ putchar('-');
|
|||
|
+ break;
|
|||
|
+ case TBL_CELL_DHORIZ:
|
|||
|
+ putchar('=');
|
|||
|
+ break;
|
|||
|
+ case TBL_CELL_MAX:
|
|||
|
+ putchar('#');
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+}
|
|||
|
+
|
|||
|
+static void
|
|||
|
print_span(const struct tbl_span *sp, int indent)
|
|||
|
{
|
|||
|
const struct tbl_dat *dp;
|
|||
|
+ const struct tbl_cell *cp;
|
|||
|
int i;
|
|||
|
|
|||
|
+ if (sp->prev == NULL) {
|
|||
|
+ for (i = 0; i < indent; i++)
|
|||
|
+ putchar(' ');
|
|||
|
+ printf("%d", sp->opts->cols);
|
|||
|
+ if (sp->opts->opts & TBL_OPT_CENTRE)
|
|||
|
+ fputs(" center", stdout);
|
|||
|
+ if (sp->opts->opts & TBL_OPT_EXPAND)
|
|||
|
+ fputs(" expand", stdout);
|
|||
|
+ if (sp->opts->opts & TBL_OPT_ALLBOX)
|
|||
|
+ fputs(" allbox", stdout);
|
|||
|
+ if (sp->opts->opts & TBL_OPT_BOX)
|
|||
|
+ fputs(" box", stdout);
|
|||
|
+ if (sp->opts->opts & TBL_OPT_DBOX)
|
|||
|
+ fputs(" doublebox", stdout);
|
|||
|
+ if (sp->opts->opts & TBL_OPT_NOKEEP)
|
|||
|
+ fputs(" nokeep", stdout);
|
|||
|
+ if (sp->opts->opts & TBL_OPT_NOSPACE)
|
|||
|
+ fputs(" nospaces", stdout);
|
|||
|
+ if (sp->opts->opts & TBL_OPT_NOWARN)
|
|||
|
+ fputs(" nowarn", stdout);
|
|||
|
+ printf(" (tbl options) %d:1\n", sp->line);
|
|||
|
+ }
|
|||
|
+
|
|||
|
for (i = 0; i < indent; i++)
|
|||
|
putchar(' ');
|
|||
|
|
|||
|
@@ -392,31 +454,52 @@ print_span(const struct tbl_span *sp, in
|
|||
|
putchar(' ');
|
|||
|
break;
|
|||
|
default:
|
|||
|
+ for (cp = sp->layout->first; cp != NULL; cp = cp->next)
|
|||
|
+ print_cellt(cp->pos);
|
|||
|
+ putchar(' ');
|
|||
|
for (dp = sp->first; dp; dp = dp->next) {
|
|||
|
+ if ((cp = dp->layout) == NULL)
|
|||
|
+ putchar('*');
|
|||
|
+ else {
|
|||
|
+ printf("%d", cp->col);
|
|||
|
+ print_cellt(dp->layout->pos);
|
|||
|
+ if (cp->flags & TBL_CELL_BOLD)
|
|||
|
+ putchar('b');
|
|||
|
+ if (cp->flags & TBL_CELL_ITALIC)
|
|||
|
+ putchar('i');
|
|||
|
+ if (cp->flags & TBL_CELL_TALIGN)
|
|||
|
+ putchar('t');
|
|||
|
+ if (cp->flags & TBL_CELL_UP)
|
|||
|
+ putchar('u');
|
|||
|
+ if (cp->flags & TBL_CELL_BALIGN)
|
|||
|
+ putchar('d');
|
|||
|
+ if (cp->flags & TBL_CELL_WIGN)
|
|||
|
+ putchar('z');
|
|||
|
+ if (cp->flags & TBL_CELL_EQUAL)
|
|||
|
+ putchar('e');
|
|||
|
+ if (cp->flags & TBL_CELL_WMAX)
|
|||
|
+ putchar('x');
|
|||
|
+ }
|
|||
|
switch (dp->pos) {
|
|||
|
case TBL_DATA_HORIZ:
|
|||
|
case TBL_DATA_NHORIZ:
|
|||
|
putchar('-');
|
|||
|
- putchar(' ');
|
|||
|
- continue;
|
|||
|
+ break;
|
|||
|
case TBL_DATA_DHORIZ:
|
|||
|
case TBL_DATA_NDHORIZ:
|
|||
|
putchar('=');
|
|||
|
- putchar(' ');
|
|||
|
- continue;
|
|||
|
+ break;
|
|||
|
default:
|
|||
|
+ putchar(dp->block ? '{' : '[');
|
|||
|
+ if (dp->string != NULL)
|
|||
|
+ fputs(dp->string, stdout);
|
|||
|
+ putchar(dp->block ? '}' : ']');
|
|||
|
break;
|
|||
|
}
|
|||
|
- printf("[\"%s\"", dp->string ? dp->string : "");
|
|||
|
if (dp->hspans)
|
|||
|
printf(">%d", dp->hspans);
|
|||
|
if (dp->vspans)
|
|||
|
printf("v%d", dp->vspans);
|
|||
|
- if (dp->layout == NULL)
|
|||
|
- putchar('*');
|
|||
|
- else if (dp->layout->pos == TBL_CELL_DOWN)
|
|||
|
- putchar('^');
|
|||
|
- putchar(']');
|
|||
|
putchar(' ');
|
|||
|
}
|
|||
|
break;
|