Import mandoc 1.4.1rc2

This commit is contained in:
Baptiste Daroussin 2017-02-19 17:41:20 +00:00
parent ef7476572c
commit 696a89ee8d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/mdocml/dist/; revision=313956
svn path=/vendor/mdocml/1.4.1rc2/; revision=313957; tag=vendor/mandoc/1.4.1rc2
56 changed files with 3501 additions and 585 deletions

51
INSTALL
View File

@ -1,4 +1,4 @@
$Id: INSTALL,v 1.17 2016/07/19 22:40:33 schwarze Exp $
$Id: INSTALL,v 1.18 2017/02/08 12:24:10 schwarze Exp $
About mdocml, the portable mandoc distribution
----------------------------------------------
@ -16,7 +16,7 @@ tech@ mailing list, too.
Enjoy using the mandoc toolset!
Ingo Schwarze, Karlsruhe, July 2016
Ingo Schwarze, Karlsruhe, February 2017
Installation
@ -31,15 +31,21 @@ Regarding how packages and ports are maintained for your operating
system, please consult your operating system documentation.
To install mandoc manually, the following steps are needed:
1. If you want to build the CGI program, man.cgi(8), too, run the
command "echo BUILD_CGI=1 > configure.local". Then run "cp
cgi.h.examples cgi.h" and edit cgi.h as desired.
1. If you want to build the CGI program, man.cgi(8), too,
run the command "echo BUILD_CGI=1 >> configure.local".
Then run "cp cgi.h.example cgi.h" and edit cgi.h as desired.
2. Define MANPATH_DEFAULT in configure.local
2. If you also want to build the new catman(8) utility, run the
command "echo BUILD_CATMAN=1 >> configure.local". Note that it
is unlikely to be a drop-in replacement providing the same
functionality as your system's "catman", if your operating
system contains one.
3. Define MANPATH_DEFAULT in configure.local
if /usr/share/man:/usr/X11R6/man:/usr/local/man is not appropriate
for your operating system.
3. Run "./configure".
4. Run "./configure".
This script attempts autoconfiguration of mandoc for your system.
Read both its standard output and the file "Makefile.local" it
generates. If anything looks wrong or different from what you
@ -49,27 +55,31 @@ result seems right to you.
On Solaris 10 and earlier, you may have to run "ksh ./configure"
because the native /bin/sh lacks some POSIX features.
4. Run "make".
5. Run "make".
Any POSIX-compatible make, in particular both BSD make and GNU make,
should work. If the build fails, look at "configure.local.example"
and go back to step 2.
5. Run "make -n install" and check whether everything will be
6. Run "make -n install" and check whether everything will be
installed to the intended places. Otherwise, put some *DIR or *NM*
variables into "configure.local" and go back to step 3.
variables into "configure.local" and go back to step 4.
6. Run "sudo make install". If you intend to build a binary
7. Optionally run the regression suite.
Basically, that amounts to "cd regress && ./regress.pl".
But you should probably look at "./mandoc -l regress/regress.pl.1"
first.
8. Run "sudo make install". If you intend to build a binary
package using some kind of fake root mechanism, you may need a
command like "make DESTDIR=... install". Read the *-install targets
in the "Makefile" to understand how DESTDIR is used.
7. Run the command "sudo
makewhatis" to build mandoc.db(5) databases in all the directory
trees configured in step 6. Whenever installing new manual pages,
re-run makewhatis(8) to update the databases, or apropos(1) will
not find the new pages.
9. Run the command "sudo makewhatis" to build mandoc.db(5) databases
in all the directory trees configured in step 6. Whenever installing
new manual pages, re-run makewhatis(8) to update the databases, or
apropos(1) will not find the new pages.
8. To set up a man.cgi(8) server, read its manual page.
10. To set up a man.cgi(8) server, read its manual page.
Note that some man(7) pages may contain low-level roff(7) markup
that mandoc does not yet understand. On some BSD systems using
@ -87,9 +97,10 @@ The following libraries are required:
2. The fts(3) directory traversion functions.
If your system does not have them, the bundled compatibility version
will be used, so you need not worry in that case. But be careful: the
glibc version of fts(3) is known to be broken on 32bit platforms,
see <https://sourceware.org/bugzilla/show_bug.cgi?id=15838>.
will be used, so you need not worry in that case. But be careful: old
glibc versions of fts(3) were known to be broken on 32bit platforms,
see <https://sourceware.org/bugzilla/show_bug.cgi?id=11460>.
That was presumably fixed in glibc-2.23.
If you run into that problem, set "HAVE_FTS=0" in configure.local.
3. Marc Espie's ohash(3) library.

View File

@ -1,4 +1,4 @@
$Id: LICENSE,v 1.13 2016/10/18 14:15:33 schwarze Exp $
$Id: LICENSE,v 1.14 2017/02/08 12:24:10 schwarze Exp $
With the exceptions noted below, all code and documentation
contained in the mdocml toolkit is protected by the Copyright
@ -10,6 +10,7 @@ Copyright (c) 2009, 2010, 2011, 2012 Joerg Sonnenberger <joerg@netbsd.org>
Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
Copyright (c) 2014 Baptiste Daroussin <bapt@freebsd.org>
Copyright (c) 2016 Ed Maste <emaste@freebsd.org>
Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
Copyright (c) 1998, 2004, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>

150
Makefile
View File

@ -1,7 +1,7 @@
# $Id: Makefile,v 1.493 2016/11/19 15:24:51 schwarze Exp $
# $Id: Makefile,v 1.504 2017/02/18 15:29:39 schwarze Exp $
#
# Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
# Copyright (c) 2011, 2013-2016 Ingo Schwarze <schwarze@openbsd.org>
# Copyright (c) 2011, 2013-2017 Ingo Schwarze <schwarze@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@ -15,11 +15,12 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
VERSION = 1.14.0
VERSION = 1.14.1
# === LIST OF FILES ====================================================
TESTSRCS = test-be32toh.c \
test-cmsg.c \
test-dirent-namlen.c \
test-EFTYPE.c \
test-err.c \
@ -30,10 +31,12 @@ TESTSRCS = test-be32toh.c \
test-mkdtemp.c \
test-nanosleep.c \
test-ntohl.c \
test-O_DIRECTORY.c \
test-ohash.c \
test-PATH_MAX.c \
test-pledge.c \
test-progname.c \
test-recvmsg.c \
test-reallocarray.c \
test-rewb-bsd.c \
test-rewb-sysv.c \
@ -49,6 +52,7 @@ TESTSRCS = test-be32toh.c \
test-wchar.c
SRCS = att.c \
catman.c \
cgi.c \
chars.c \
compat_err.c \
@ -89,6 +93,7 @@ SRCS = att.c \
mandoc.c \
mandoc_aux.c \
mandoc_ohash.c \
mandocd.c \
mandocdb.c \
manpage.c \
manpath.c \
@ -128,6 +133,7 @@ DISTFILES = INSTALL \
NEWS \
TODO \
apropos.1 \
catman.8 \
cgi.h.example \
compat_fts.h \
compat_ohash.h \
@ -156,6 +162,7 @@ DISTFILES = INSTALL \
man.cgi.8 \
man.conf.5 \
man.h \
man.options.1 \
manconf.h \
mandoc.1 \
mandoc.3 \
@ -169,6 +176,7 @@ DISTFILES = INSTALL \
mandoc_html.3 \
mandoc_malloc.3 \
mandoc_ohash.h \
mandocd.8 \
mansearch.3 \
mansearch.h \
mchars_alloc.3 \
@ -280,6 +288,12 @@ CGI_OBJS = $(MANDOC_HTML_OBJS) \
cgi.o \
out.o
MANDOCD_OBJS = $(MANDOC_HTML_OBJS) \
$(MANDOC_TERM_OBJS) \
mandocd.o \
out.o \
tag.o
MANPAGE_OBJS = $(DBM_OBJS) \
manpage.o \
manpath.o
@ -298,6 +312,7 @@ WWW_MANS = apropos.1.html \
man.1.html \
mandoc.1.html \
soelim.1.html \
man.cgi.3.html \
mandoc.3.html \
mandoc_escape.3.html \
mandoc_headers.3.html \
@ -311,11 +326,12 @@ WWW_MANS = apropos.1.html \
eqn.7.html \
man.7.html \
mandoc_char.7.html \
mandocd.8.html \
mdoc.7.html \
roff.7.html \
tbl.7.html \
catman.8.html \
makewhatis.8.html \
man.cgi.3.html \
man.cgi.8.html \
man.h.html \
manconf.h.html \
@ -334,11 +350,7 @@ include Makefile.local
# === DEPENDENCY HANDLING ==============================================
all: base-build $(BUILD_TARGETS) Makefile.local
base-build: mandoc demandoc soelim
cgi-build: man.cgi
all: mandoc demandoc soelim $(BUILD_TARGETS) Makefile.local
install: base-install $(INSTALL_TARGETS)
@ -360,13 +372,14 @@ clean:
rm -f libmandoc.a $(LIBMANDOC_OBJS) $(COMPAT_OBJS)
rm -f mandoc $(MAIN_OBJS)
rm -f man.cgi $(CGI_OBJS)
rm -f mandocd catman $(MANDOCD_OBJS)
rm -f manpage $(MANPAGE_OBJS)
rm -f demandoc $(DEMANDOC_OBJS)
rm -f soelim $(SOELIM_OBJS)
rm -f $(WWW_MANS) $(WWW_OBJS)
rm -rf *.dSYM
base-install: base-build
base-install: mandoc demandoc soelim
mkdir -p $(DESTDIR)$(BINDIR)
mkdir -p $(DESTDIR)$(SBINDIR)
mkdir -p $(DESTDIR)$(MANDIR)/man1
@ -375,29 +388,29 @@ base-install: base-build
mkdir -p $(DESTDIR)$(MANDIR)/man8
$(INSTALL_PROGRAM) mandoc demandoc $(DESTDIR)$(BINDIR)
$(INSTALL_PROGRAM) soelim $(DESTDIR)$(BINDIR)/$(BINM_SOELIM)
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_MAN)
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_APROPOS)
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_WHATIS)
ln -f $(DESTDIR)$(BINDIR)/mandoc \
$(LN) $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_MAN)
$(LN) $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_APROPOS)
$(LN) $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_WHATIS)
$(LN) $(DESTDIR)$(BINDIR)/mandoc \
$(DESTDIR)$(SBINDIR)/$(BINM_MAKEWHATIS)
$(INSTALL_MAN) mandoc.1 demandoc.1 $(DESTDIR)$(MANDIR)/man1
$(INSTALL_MAN) soelim.1 $(DESTDIR)$(MANDIR)/man1/$(BINM_SOELIM).1
$(INSTALL_MAN) man.1 $(DESTDIR)$(MANDIR)/man1/$(BINM_MAN).1
$(INSTALL_MAN) apropos.1 $(DESTDIR)$(MANDIR)/man1/$(BINM_APROPOS).1
ln -f $(DESTDIR)$(MANDIR)/man1/$(BINM_APROPOS).1 \
$(LN) $(DESTDIR)$(MANDIR)/man1/$(BINM_APROPOS).1 \
$(DESTDIR)$(MANDIR)/man1/$(BINM_WHATIS).1
$(INSTALL_MAN) man.conf.5 $(DESTDIR)$(MANDIR)/man5/${MANM_MANCONF}.5
$(INSTALL_MAN) man.conf.5 $(DESTDIR)$(MANDIR)/man5/$(MANM_MANCONF).5
$(INSTALL_MAN) mandoc.db.5 $(DESTDIR)$(MANDIR)/man5
$(INSTALL_MAN) man.7 $(DESTDIR)$(MANDIR)/man7/${MANM_MAN}.7
$(INSTALL_MAN) mdoc.7 $(DESTDIR)$(MANDIR)/man7/${MANM_MDOC}.7
$(INSTALL_MAN) roff.7 $(DESTDIR)$(MANDIR)/man7/${MANM_ROFF}.7
$(INSTALL_MAN) eqn.7 $(DESTDIR)$(MANDIR)/man7/${MANM_EQN}.7
$(INSTALL_MAN) tbl.7 $(DESTDIR)$(MANDIR)/man7/${MANM_TBL}.7
$(INSTALL_MAN) man.7 $(DESTDIR)$(MANDIR)/man7/$(MANM_MAN).7
$(INSTALL_MAN) mdoc.7 $(DESTDIR)$(MANDIR)/man7/$(MANM_MDOC).7
$(INSTALL_MAN) roff.7 $(DESTDIR)$(MANDIR)/man7/$(MANM_ROFF).7
$(INSTALL_MAN) eqn.7 $(DESTDIR)$(MANDIR)/man7/$(MANM_EQN).7
$(INSTALL_MAN) tbl.7 $(DESTDIR)$(MANDIR)/man7/$(MANM_TBL).7
$(INSTALL_MAN) mandoc_char.7 $(DESTDIR)$(MANDIR)/man7
$(INSTALL_MAN) makewhatis.8 \
$(DESTDIR)$(MANDIR)/man8/$(BINM_MAKEWHATIS).8
lib-install: base-build
lib-install: libmandoc.a
mkdir -p $(DESTDIR)$(LIBDIR)
mkdir -p $(DESTDIR)$(INCLUDEDIR)
mkdir -p $(DESTDIR)$(MANDIR)/man3
@ -407,13 +420,70 @@ lib-install: base-build
$(INSTALL_MAN) mandoc.3 mandoc_escape.3 mandoc_malloc.3 \
mansearch.3 mchars_alloc.3 tbl.3 $(DESTDIR)$(MANDIR)/man3
cgi-install: cgi-build
cgi-install: man.cgi
mkdir -p $(DESTDIR)$(CGIBINDIR)
mkdir -p $(DESTDIR)$(HTDOCDIR)
$(INSTALL_PROGRAM) man.cgi $(DESTDIR)$(CGIBINDIR)
$(INSTALL_DATA) mandoc.css $(DESTDIR)$(HTDOCDIR)
Makefile.local config.h: configure ${TESTSRCS}
catman-install: mandocd catman
mkdir -p $(DESTDIR)$(SBINDIR)
mkdir -p $(DESTDIR)$(MANDIR)/man8
$(INSTALL_PROGRAM) mandocd $(DESTDIR)$(SBINDIR)
$(INSTALL_PROGRAM) catman $(DESTDIR)$(SBINDIR)/$(BINM_CATMAN)
$(INSTALL_MAN) mandocd.8 $(DESTDIR)$(MANDIR)/man8
$(INSTALL_MAN) catman.8 $(DESTDIR)$(MANDIR)/man8/$(BINM_CATMAN).8
uninstall:
rm -f $(DESTDIR)$(BINDIR)/mandoc
rm -f $(DESTDIR)$(BINDIR)/demandoc
rm -f $(DESTDIR)$(BINDIR)/$(BINM_SOELIM)
rm -f $(DESTDIR)$(BINDIR)/$(BINM_MAN)
rm -f $(DESTDIR)$(BINDIR)/$(BINM_APROPOS)
rm -f $(DESTDIR)$(BINDIR)/$(BINM_WHATIS)
rm -f $(DESTDIR)$(SBINDIR)/$(BINM_MAKEWHATIS)
rm -f $(DESTDIR)$(MANDIR)/man1/mandoc.1
rm -f $(DESTDIR)$(MANDIR)/man1/demandoc.1
rm -f $(DESTDIR)$(MANDIR)/man1/$(BINM_SOELIM).1
rm -f $(DESTDIR)$(MANDIR)/man1/$(BINM_MAN).1
rm -f $(DESTDIR)$(MANDIR)/man1/$(BINM_APROPOS).1
rm -f $(DESTDIR)$(MANDIR)/man1/$(BINM_WHATIS).1
rm -f $(DESTDIR)$(MANDIR)/man5/$(MANM_MANCONF).5
rm -f $(DESTDIR)$(MANDIR)/man5/mandoc.db.5
rm -f $(DESTDIR)$(MANDIR)/man7/$(MANM_MAN).7
rm -f $(DESTDIR)$(MANDIR)/man7/$(MANM_MDOC).7
rm -f $(DESTDIR)$(MANDIR)/man7/$(MANM_ROFF).7
rm -f $(DESTDIR)$(MANDIR)/man7/$(MANM_EQN).7
rm -f $(DESTDIR)$(MANDIR)/man7/$(MANM_TBL).7
rm -f $(DESTDIR)$(MANDIR)/man7/mandoc_char.7
rm -f $(DESTDIR)$(MANDIR)/man8/$(BINM_MAKEWHATIS).8
rm -f $(DESTDIR)$(CGIBINDIR)/man.cgi
rm -f $(DESTDIR)$(HTDOCDIR)/mandoc.css
rm -f $(DESTDIR)$(SBINDIR)/mandocd
rm -f $(DESTDIR)$(SBINDIR)/$(BINM_CATMAN)
rm -f $(DESTDIR)$(MANDIR)/man8/mandocd.8
rm -f $(DESTDIR)$(MANDIR)/man8/$(BINM_CATMAN).8
rm -f $(DESTDIR)$(LIBDIR)/libmandoc.a
rm -f $(DESTDIR)$(MANDIR)/man3/mandoc.3
rm -f $(DESTDIR)$(MANDIR)/man3/mandoc_escape.3
rm -f $(DESTDIR)$(MANDIR)/man3/mandoc_malloc.3
rm -f $(DESTDIR)$(MANDIR)/man3/mansearch.3
rm -f $(DESTDIR)$(MANDIR)/man3/mchars_alloc.3
rm -f $(DESTDIR)$(MANDIR)/man3/tbl.3
rm -f $(DESTDIR)$(INCLUDEDIR)/man.h
rm -f $(DESTDIR)$(INCLUDEDIR)/mandoc.h
rm -f $(DESTDIR)$(INCLUDEDIR)/mandoc_aux.h
rm -f $(DESTDIR)$(INCLUDEDIR)/mdoc.h
rm -f $(DESTDIR)$(INCLUDEDIR)/roff.h
rmdir $(DESTDIR)$(INCLUDEDIR)
regress: all
cd regress && ./regress.pl
regress-clean:
cd regress && ./regress.pl . clean
Makefile.local config.h: configure $(TESTSRCS)
@echo "$@ is out of date; please run ./configure"
@exit 1
@ -429,6 +499,12 @@ manpage: $(MANPAGE_OBJS) libmandoc.a
man.cgi: $(CGI_OBJS) libmandoc.a
$(CC) $(STATIC) -o $@ $(LDFLAGS) $(CGI_OBJS) libmandoc.a $(LDADD)
mandocd: $(MANDOCD_OBJS) libmandoc.a
$(CC) -o $@ $(LDFLAGS) $(MANDOCD_OBJS) libmandoc.a $(LDADD)
catman: catman.o libmandoc.a
$(CC) -o $@ $(LDFLAGS) catman.o libmandoc.a $(LDADD)
demandoc: $(DEMANDOC_OBJS) libmandoc.a
$(CC) -o $@ $(LDFLAGS) $(DEMANDOC_OBJS) libmandoc.a $(LDADD)
@ -453,14 +529,40 @@ depend: config.h
Makefile.depend > Makefile.tmp
mv Makefile.tmp Makefile.depend
regress-distclean:
@find regress \
-name '.#*' -o \
-name '*.orig' -o \
-name '*.rej' -o \
-name '*.core' \
-exec rm -i {} \;
regress-distcheck:
@find regress ! -type d ! -type f
@find regress -type f \
! -path '*/CVS/*' \
! -name Makefile \
! -name Makefile.inc \
! -name '*.in' \
! -name '*.out_ascii' \
! -name '*.out_utf8' \
! -name '*.out_html' \
! -name '*.out_lint' \
! -path regress/regress.pl \
! -path regress/regress.pl.1
dist: mdocml.sha256
mdocml.sha256: mdocml.tar.gz
sha256 mdocml.tar.gz > $@
mdocml.tar.gz: $(DISTFILES)
ls regress/*/*/*.mandoc_* && exit 1 || true
mkdir -p .dist/mdocml-$(VERSION)/
$(INSTALL) -m 0644 $(DISTFILES) .dist/mdocml-$(VERSION)
cp -pR regress .dist/mdocml-$(VERSION)
find .dist/mdocml-$(VERSION)/regress \
-type d -name CVS -print0 | xargs -0 rm -rf
chmod 755 .dist/mdocml-$(VERSION)/configure
( cd .dist/ && tar zcf ../$@ mdocml-$(VERSION) )
rm -rf .dist/

View File

@ -1,4 +1,5 @@
att.o: att.c config.h roff.h mdoc.h libmdoc.h
catman.o: catman.c config.h compat_fts.h
cgi.o: cgi.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h main.h manconf.h mansearch.h cgi.h
chars.o: chars.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h libmandoc.h
compat_err.o: compat_err.c config.h
@ -39,6 +40,7 @@ man_validate.o: man_validate.c config.h mandoc_aux.h mandoc.h roff.h man.h libma
mandoc.o: mandoc.c config.h mandoc.h mandoc_aux.h libmandoc.h
mandoc_aux.o: mandoc_aux.c config.h mandoc.h mandoc_aux.h
mandoc_ohash.o: mandoc_ohash.c mandoc_aux.h mandoc_ohash.h compat_ohash.h
mandocd.o: mandocd.c config.h mandoc.h roff.h mdoc.h man.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 manconf.h mansearch.h dba_array.h dba.h
manpage.o: manpage.c config.h manconf.h mansearch.h
manpath.o: manpath.c config.h mandoc_aux.h manconf.h

128
NEWS
View File

@ -1,7 +1,131 @@
$Id: NEWS,v 1.12 2016/07/14 11:09:06 schwarze Exp $
$Id: NEWS,v 1.20 2017/02/16 14:38:12 schwarze Exp $
This file lists the most important changes in the mdocml.bsd.lv distribution.
Changes in version 1.14.1, released on February XXX, 2017
--- MAJOR NEW FEATURES ---
* apropos(1): Reimplement complete semantic search functionality
without the dependency on SQLite3, using only POSIX APIs.
This comes with a completely new mandoc.db(5) file format.
* man(1): Support more than one tag entry for the same search term,
plus some minor improvements to the less(1) :t support.
* -Thtml: Use real macro names for CSS classes.
Systematic cleanup of and many improvements to mandoc.css.
* -Thtml: Produce human readable HTML code by using indentation
and better line breaks. Improve various HTML elements,
and trim several useless ones.
* New catman(8) utility, still somewhat experimental.
* Now includes a portable version of the OpenBSD mandoc regression
suite, see regress/regress.pl.1 for details.
--- REMOVED FUNCTIONALITY ---
* Operating systems that don't provide mmap(3) are no longer supported.
* Drop support for manpath(1). Even if your system has manpath(1),
it is simpler to use MANPATH_DEFAULT in configure.local for
operating system defaults, man.conf(5) for machine-specific
modifications, and ${MANPATH}, -m, and -M for user preferences
than to bother with the complexity of manpath(1).
* makewhatis(8) -p: No longer warn about missing MLINKS since these
are no longer needed for anything.
--- MINOR NEW FEATURES ---
* mdoc(7): Warn about invalid punctuation and content below NAME.
* mdoc(7): Warn about .Xr lacking the second argument (section).
* mdoc(7): Warn about violations of the rule "new sentence, new line".
* roff(7): Warn about trailing whitespace at the end of comments.
* mdoc(7): Improve rendering of double quotes.
* mdoc(7): Always do text production in the validator, never in the
formatters. Cleaner, simpler, shorter, helps NetBSD apropos(1)
and also makes -Ttree output more useful.
* -Ttree: Show metadata and some additional node flags.
New -Onoval output option to show the unvalidated tree.
--- RELIABILITY BUGFIXES ---
* man(1): Make "man -l" work with standard input from a pipe or file,
as long as standard output is a terminal.
* man(7): Fix out of bounds read access if a text node immediately
preceded the first .SH header.
* mdoc(7): Fix out of bounds read access for .Bl without a type
but with a width.
* mdoc(7): Fix out of bounds read access for .Bl -column starting
with a tab character instead of a child .It macro.
* mdoc(7): Fix syntax tree corruption leading to segfaults caused
by stray block end macros in nested blocks of mismatching type.
* man(1): Fix NULL dereference when the first of multiple pages
shown was preformatted.
* mdoc(7): Fix syntax tree corruption leading to NULL dereference
caused by partial implicit macros inside .Bl -column table cells.
* mdoc(7): Fix syntax tree corruption leading to NULL dereference
for macro sequences like .Bl .Bl .It Bo .El .It.
* mdoc(7): Fix syntax tree corruption leading to NULL dereference
caused by .Ta following a nested .Bl -column breaking another block.
* mdoc(7): Fix syntax tree corruption sometimes leading to NULL
dereference caused by indirectly broken .Nd or .Nm blocks.
* mdoc(7) -Thtml: Fix a NULL dereference for .Bl -column with 0 columns.
* mdoc(7): Fix NULL dereference in some specific cases of a
block-end macro calling another block-end macro.
* mdoc(7): Fix NULL dereference if the only child of the head
of the first .Sh was an empty in-line macro.
* eqn(7): Fix NULL dereference in the terminal formatter
for empty matrices and empty square roots.
* mdoc(7): Fix an assertion failure for a .Bd without a type that
breaks another block.
* mdoc(7): Fix an assertion failure that happened for some .Bl -column
lists containing a column width of "-4n", "-3n", or "-2n".
* mdoc(7): Fix an assertion failure caused by .Bl -column without .It
but containing eqn(7) or tbl(7) code.
* roff(7): Fix an assertion failure caused by \z\[u00FF] with -Tps/-Tpdf.
* roff(7): Fix an assertion failures caused by whitespace inside \o''
(overstrike) sequences.
* -Thtml: Fix an assertion failure caused by -Oman or -Oincludes of
excessive length.
--- PORTABILITY IMPROVEMENTS ---
* man(1): Do not mix stdio narrow and wide stream orientation
on stdout, which could cause output corruption on glibc.
* mandoc(1): Autodetect a suitable locale for -Tutf8 mode.
* ./configure: Autodetect whether PATH_MAX and O_DIRECTORY are defined.
* ./configure: Autodetect if nanosleep(3) needs -lrt.
* ./configure: Provide an ${LN} configuration variable.
* ./configure: Put compiler arguments that may contain -l at the end.
--- MINOR BUGFIXES ---
* mdoc(7): Fix SYNOPSIS output if the first child of .Nm is a macro.
* mdoc(7) -Thtml: Improve formatting of .Bl -tag with short tags.
* man(7) -Thtml: Preserve whitespace in .nf (nofill) mode.
* mandoc(1): Error out on invalid output options on the command line.
--- STRUCTURAL CHANGES, no functional change ---
* Redesign part of the mandoc_html(3) interfaces, making them much
easier to use and reducing the amount of code by a few hundred lines.
--- THANKS TO ---
* Michael Stapelberg (Debian) for designing the new mandocd(8)
and parts of the new catman(8), and for a number of patches
and bug reports.
* Baptiste Daroussin (FreeBSD) for profiling the new makewhatis(8)
implementation and suggesting an algorithmic improvement which
more than doubled performance, and for a few bug reports.
* Ed Maste (FreeBSD) for an important patch improving reproducibility
of builds in makewhatis(8), and for a few bug reports.
* Theo Buehler (OpenBSD) for more than ten important bug reports,
most of them found by systematic afl(1) fuzzing.
* Benny Lofgren, David Dahlberg, and in particular Vadim Zhukov
for crucial help in getting .Bl -tag CSS formatting fixed.
* Svyatoslav Mishyn (Crux Linux) for an initial version of the
patch to autodetect a suitable locale for -Tutf8 mode.
* Jason McIntyre (OpenBSD) for multiple useful discussions
and a number of bug reports.
* Alexander Bluhm, Andrew Fresh, Antoine Jacoutot, Antony Bentley,
Christian Weisgerber, Jonathan Gray, Marc Espie, Martijn van Duren,
Stuart Henderson, Ted Unangst, Theo de Raadt (OpenBSD), Abhinav
Upadhyay, Christos Zoulas, Kamil Rytarowski, Sevan Janiyan,
Thomas Klausner (NetBSD), Aaron M. Ucko, Bdale Garbee, Reiner
Herrmann, Shane Kerr (Debian), Leah Neukirchen (Void Linux),
Daniel Sabogal (Alpine Linux), Yuri Pankov (illumos),
Carsten Kunze (Heirloom roff), Kristaps Dzonsons (bsd.lv),
Anton Lindqvist, Jan Stary, Jeremy A. Mates, Mark Patruck,
Pavan Maddamsetti, Sean Levy <attila@stalphonsos.com>, and
Tiago Silva for bug reports.
* Brent Cook, Marc Espie, Philip Guenther, Todd Miller (OpenBSD)
and Markus Waldeck for useful discussions.
* And as usual, OpenCSW for providing me with a Solaris 9/10/11
testing environment.
Changes in version 1.13.4, released on July 14, 2016
--- MAJOR NEW FEATURES ---
@ -109,7 +233,7 @@ Changes in version 1.13.4, released on July 14, 2016
again resulting in more than half a dozen important bug reports.
* Svyatoslav Mishyn (Crux Linux) for some patches, several bug
reports, and extensive release testing.
* Christian Neukirchen (void Linux) for a number of compatibility
* Leah Neukirchen (Void Linux) for a number of compatibility
patches and suggestions and several bug reports.
* Christos Zoulas (NetBSD) for a bug fix patch and some useful
suggestions for cleanup.

85
TODO
View File

@ -1,6 +1,6 @@
************************************************************************
* Official mandoc TODO.
* $Id: TODO,v 1.223 2017/01/17 15:32:43 schwarze Exp $
* $Id: TODO,v 1.234 2017/02/18 11:53:33 schwarze Exp $
************************************************************************
Many issues are annotated for difficulty as follows:
@ -193,10 +193,6 @@ are mere guesses, and some may be wrong.
uqs@ Thu, 2 Jun 2011 11:33:35 +0200
loc * exist ** algo *** size * imp **
--- missing man features -----------------------------------------------
- -T[x]html doesn't stipulate non-collapsing spaces in literal mode
--- missing tbl features -----------------------------------------------
- horizontal lines in the layout still consume data cells
@ -223,13 +219,16 @@ are mere guesses, and some may be wrong.
- support mdoc(7) and man(7) macros inside tbl(7) code;
probably requires the parser reorg and letting tbl(7)
use roff_node such that macro sets can mix;
informed by bapt@ that FreeBSD needs this.
informed by bapt@ that FreeBSD needs this: 3 Jan 2015 23:32:23 +0100
loc *** exist ** algo *** size ** imp ***
- look at the POSIX manuals in the books/man-pages-posix port,
they use some unsupported tbl(7) features.
loc * exist ** algo ** size ** imp ***
- look what Joerg Schilling manual pages use
Thu, 19 Mar 2015 18:31:48 +0100
- use Unicode U+2500 to U+256C for table borders
in tbl(7) -Tutf-8 output
suggested by bentley@ Tue, 14 Oct 2014 04:10:55 -0600
@ -263,15 +262,6 @@ are mere guesses, and some may be wrong.
even for apropos title line output; req by bapt@
loc * exist * algo * size * imp ***
- makewhatis(8) for preformatted pages:
parse the section number from the header line
and compare to the section number from the directory name
loc * exist * algo * size * imp **
- Does makewhatis(8) detect missing NAME sections, missing names,
and missing descriptions in all the file formats?
loc * exist * algo * size * imp ***
- clean up escape sequence handling, creating three classes:
(1) fully implemented, or parsed and ignored without loss of content
(2) unimplemented, potentially causing loss of content
@ -300,6 +290,8 @@ are mere guesses, and some may be wrong.
- look at AT&T DWB http://www2.research.att.com/sw/download
Carsten Kunze <carsten dot kunze at arcor dot de> has patches
Mon, 4 Aug 2014 17:01:28 +0200
ported version: https://github.com/n-t-roff/DWB3.3
Carsten Kunze Wed, 22 Apr 2015 11:21:43 +0200
- look at pages generated from reStructeredText, e.g. devel/mercurial hg(1)
These are a weird mixture of man(7) and custom autogenerated low-level
@ -334,6 +326,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 features of the Slackware man.conf(5) format
Carsten Kunze Wed, 11 Mar 2015 17:57:24 +0100
************************************************************************
* formatting issues: ugly output
************************************************************************
@ -394,7 +389,7 @@ are mere guesses, and some may be wrong.
reveals lots of bugs both in groff and mandoc...
reported by bentley@ Wed, 22 May 2013 23:49:30 -0600
--- PDF issues ---------------------------------------------------------
--- PostScript and PDF issues ------------------------------------------
- PDF output doesn't use a monospaced font for .Bd -literal
Example: "mandoc -Tpdf afterboot.8 > output.pdf && pdfviewer output.pdf".
@ -404,21 +399,11 @@ are mere guesses, and some may be wrong.
instructions from juanfra@ Wed, 11 Jun 2014 02:21:01 +0200
add a new <</Type /Font>> block to the PDF files with /BaseFont /Courier
and change the /Name from /F0 to the new font (/F5 (?)).
re-reported by tb@ Mon, 16 Mar 2015 16:47:21 +0100
loc * exist ** algo ** size * imp **
--- HTML issues --------------------------------------------------------
- <dl><dt><dd> formatting is ugly
hints are easy to find on the web, e.g.
http://stackoverflow.com/questions/1713048/
see also matthew@ Fri, 18 Jul 2014 19:25:12 -0700
loc * exist * algo ** size * imp ***
- In -man -Thtml, .nf does not preserve indentation.
It should either convert blanks to &nbsp;
or use <pre> rather than <div> (like .Bd -literal does).
Reported by afresh1@ 12 Apr 2016 14:35:45 -0700
- .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
@ -427,6 +412,9 @@ are mere guesses, and some may be wrong.
- jsg on icb, Nov 3, 2014:
try to guess Xr in man(7) for hyperlinking
and render them with <a class="Xr" href=...>
https://github.com/Debian/debiman/issues/15
loc * exist * algo ** size ** imp **
- The tables used to render the three-part page headers actually force
the width of the <body> to the max-width given for <html>.
@ -435,9 +423,6 @@ are mere guesses, and some may be wrong.
http://undeadly.org/cgi?action=article&sid=20140925064244&pid=1
loc * exist * algo ** size * imp ***
- consider whether <var> can be used for Ar Dv Er Ev Fa Va.
from bentley@ Wed, 13 Aug 2014 09:17:55 -0600
- generate <img> tags in HTML
idea from florian@ Tue, 7 Apr 2015 00:26:28 +0000
may be possible to implement with .Lk img://something.png alt_text
@ -454,6 +439,9 @@ are mere guesses, and some may be wrong.
Steffen Nurpmeso Sat, 08 Nov 2014 13:34:59 +0100
loc * exist ** algo ** size * imp **
- .Lk formatting for long links with line breaks
Franco Fichtner 8 Oct 2013 00:33:42 +0200
- In .Bl -enum -width 0n, groff continues one the same line after
the number, mandoc breaks the line.
mail to kristaps@ Mon, 20 Jul 2009 02:21:39 +0200
@ -498,6 +486,7 @@ are mere guesses, and some may be wrong.
The same applies to .Bl -column column widths;
reported again by Nicolas Joly Thu, 1 Mar 2012 13:41:26 +0100 via wiz@ 5 Mar
reported again by Franco Fichtner Fri, 27 Sep 2013 21:02:28 +0200
reported again by Bruce Evans Fri, 17 Feb 2017 21:22:44 +0100 via bapt@
loc *** exist *** algo *** size ** imp ***
An easy partial fix would be to just skip the first word if it starts
with a dot, including any following white space, when measuring.
@ -508,12 +497,6 @@ are mere guesses, and some may be wrong.
we want three blank lines, not two as in mandoc.
loc ** exist ** algo ** size * imp **
- Header lines of excessive length:
Port OpenBSD man_term.c rev. 1.25 to mdoc_term.c
and document it in mdoc(7) and man(7) COMPATIBILITY
found while talking to Chris Bennett
loc * exist * algo * size * imp *
- Sequences of multiple man(7) paragraphs (.PP, .IP) interspersed
with .ps and .nf/.fi produce execessive blank lines, see libJudy
and graphics/dcmtk. The parser reorg may help with this.
@ -535,21 +518,10 @@ are mere guesses, and some may be wrong.
to access the manpath and mandoc.db(3) after parsing.
asked for by jmc@ Fri, 4 Dec 2015 22:39:40 +0000
- Report errors in -O suboption parsing.
loc * exist * algo * size * imp **
- warn when .Sh or .Ss contain other macros
Steffen Nurpmeso, savannah.gnu.org/bugs/index.php?45034
loc * exist * algo * size * imp **
- check that MANDOCERR_BADTAB is thrown in the right cases,
i.e. when finding a literal tab character in fill mode,
and possibly change the wording of the warning message
to refer to fill mode, not literal mode
See the mail from Werner LEMBERG on the groff list,
Fri, 14 Feb 2014 18:54:42 +0100 (CET)
loc * exist ** algo ** size * imp **
- warn about attempts to call non-callable macros
Steffen Nurpmeso Tue, 11 Nov 2014 22:55:16 +0100
Note that formatting is inconsistent in groff.
@ -558,9 +530,6 @@ are mere guesses, and some may be wrong.
all over mdoc_macro.c and all subtly different.
loc ** exist ** algo ** size ** imp **
- warn about "new sentence, new line"
loc ** exist ** algo *** size * imp **
- mandoc_special does not really check the escape sequence,
but just the overall format
loc ** exist ** algo *** size ** imp **
@ -580,13 +549,6 @@ are mere guesses, and some may be wrong.
* documentation issues
************************************************************************
- mention hyphenation rules:
breaking at letter-letter in text mode (not macro args)
proper hyphenation is unimplemented
- talk about spacing around delimiters
to jmc@, kristaps@ Sat, 23 Apr 2011 17:41:27 +0200
- mark macros as: page structure domain, manual domain, general text domain
is this useful?
@ -606,14 +568,8 @@ Several areas can be cleaned up to make mandoc even faster. These are
- improve hashing mechanism for macros (quite important: performance)
- improve hashing mechanism for characters (not as important)
- the PDF file is HUGE: this can be reduced by using relative offsets
- instead of re-initialising the roff predefined-strings set before each
parse, create a read-only version the first time and copy it
loc * exist ** algo ** size * imp **
************************************************************************
* structural issues
************************************************************************
@ -648,9 +604,6 @@ Several areas can be cleaned up to make mandoc even faster. These are
output through libz.
- Sandbox (see OpenSSH).
- Enable caching support via HTTP 304 and If-Modified-Since.
- Allow for cgi.h to be overridden by CGI environment variables.
Otherwise, binary distributions will inherit the compile-time
behaviour, which is not optimal.
- Have Mac OSX systems automatically disable -static compilation of the
CGI: -static isn't supported.

View File

@ -1,4 +1,4 @@
.\" $Id: apropos.1,v 1.39 2015/04/03 08:46:17 schwarze Exp $
.\" $Id: apropos.1,v 1.40 2017/01/31 19:44:04 schwarze Exp $
.\"
.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: April 3 2015 $
.Dd $Mdocdate: January 31 2017 $
.Dt APROPOS 1
.Os
.Sh NAME
@ -468,6 +468,10 @@ and in
.Ox 5.6
for
.Nm whatis .
The options
.Fl acfhIKklOTWw
appeared in
.Ox 5.7 .
.Sh AUTHORS
.An -nosplit
.An Bill Joy

186
catman.8 Normal file
View File

@ -0,0 +1,186 @@
.\" $Id: catman.8,v 1.7 2017/02/06 19:04:21 schwarze Exp $
.\"
.\" Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: February 6 2017 $
.Dt CATMAN 8
.Os
.Sh NAME
.Nm catman
.Nd format all manual pages below a directory
.Sh SYNOPSIS
.Nm catman
.Op Fl I Cm os Ns = Ns Ar name
.Op Fl T Ar output
.Ar srcdir dstdir
.Sh DESCRIPTION
The
.Nm
utility assumes that all files below
.Ar srcdir
are manual pages in
.Xr mdoc 7
and
.Xr man 7
format and formats all of them, storing the formatted versions in
the same relative paths below
.Ar dstdir .
Subdirectories of
.Ar dstdir
are created as needed.
Existing files are not explicitly deleted, but possibly overwritten.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl I Cm os Ns = Ns Ar name
Override the default operating system
.Ar name
for the
.Xr mdoc 7
.Ic Os
and for the
.Xr man 7
.Ic TH
macro.
.It Fl T Ar output
Output format.
The
.Ar output
argument can be
.Cm ascii ,
.Cm utf8 ,
or
.Cm html ;
see
.Xr mandoc 1 .
In
.Cm html
output mode, the
.Cm fragment
output option is implied.
Other output options are not supported.
.El
.Sh IMPLEMENTATION NOTES
Since this version avoids
.Xr fork 2
and
.Xr exec 3
overhead and uses the much faster
.Sy mandoc
parsers and formatters rather than
.Sy groff ,
it may be about one order of magnitude faster than other
.Nm
implementations.
.Sh EXIT STATUS
.Ex -std
.Pp
Possible errors include:
.Bl -bullet
.It
missing, invalid, or excessive command line arguments
.It
failure to change the current working directory to
.Ar srcdir
.It
failure to open
.Ar dstdir
.It
communication failure with
.Xr mandocd 8
.It
resource exhaustion, for example file descriptor, process table,
or memory exhaustion
.El
.Pp
Except for memory exhaustion and similar system-level failures,
failures while trying to open, read, parse, or format individual
manual pages, to save individual formatted files to the file system,
or even to create directories do not cause
.Nm
to return an error exit status.
In such cases,
.Nm
will simply continue with the next file or subdirectory.
.Sh SEE ALSO
.Xr mandoc 1 ,
.Xr mandocd 8
.Sh HISTORY
A
.Nm
utility first appeared in
.Fx 1.0 .
Other, incompatible implementations appeared in
.Nx 1.0
and in
.Sy man-db No 2.2 .
.Pp
This version appeared in version 1.14.1 of the
.Sy mandoc
toolkit.
.Sh AUTHORS
.An -nosplit
The first
.Nm
implementation was a short shell script by
.An Christoph Robitschko
in July 1993.
.Pp
The
.Nx
implementations were written by
.An J. T. Conklin Aq Mt jtc@netbsd.org
in 1993,
.An Christian E. Hopps Aq Mt chopps@netbsd.org
in 1994,
and
.An Dante Profeta Aq Mt dante@netbsd.org
in 1999; the
.Sy man-db
implementation by
.An Graeme W. Wilford
in 1994; and the
.Fx
implementations by
.An Wolfram Schneider Aq Mt wosch@freebsd.org
in 1995 and
.An John Rochester Aq Mt john@jrochester.org
in 2002.
.Pp
The concept of the present version was designed and implemented by
.An Michael Stapelberg Aq Mt stapelberg@debian.org
in 2017.
Option and argument handling and directory iteration was added by
.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
.Sh CAVEATS
All versions of
.Nm
are incompatible with each other because each caters to the needs
of a specific operating system, for example regarding directory
structures and file naming conventions.
.Pp
This version is more flexible than the others in so far as it does
not assume any particular directory structure or naming convention.
That flexibility comes at the price of not being able to change the
names and relative paths of the source files when reusing them to
store the formatted files, of not supporting any configuration file
formats or environment variables, and of being unable to scan for
and remove junk files in
.Ar dstdir .
.Pp
Currently,
.Nm
always reformats each page, even if the formatted version is newer
than the source version.

260
catman.c Normal file
View File

@ -0,0 +1,260 @@
/* $Id: catman.c,v 1.21 2017/02/18 12:24:24 schwarze Exp $ */
/*
* Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
* Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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.
*/
#include "config.h"
#if HAVE_CMSG_XPG42
#define _XPG4_2
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <errno.h>
#include <fcntl.h>
#if HAVE_FTS
#include <fts.h>
#else
#include "compat_fts.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
int process_manpage(int, int, const char *);
int process_tree(int, int);
void run_mandocd(int, const char *, const char *)
__attribute__((__noreturn__));
ssize_t sock_fd_write(int, int, int, int);
void usage(void) __attribute__((__noreturn__));
void
run_mandocd(int sockfd, const char *outtype, const char* defos)
{
char sockfdstr[10];
if (snprintf(sockfdstr, sizeof(sockfdstr), "%d", sockfd) == -1)
err(1, "snprintf");
if (defos == NULL)
execlp("mandocd", "mandocd", "-T", outtype,
sockfdstr, (char *)NULL);
else
execlp("mandocd", "mandocd", "-T", outtype,
"-I", defos, sockfdstr, (char *)NULL);
err(1, "exec");
}
ssize_t
sock_fd_write(int fd, int fd0, int fd1, int fd2)
{
const struct timespec timeout = { 0, 10000000 }; /* 0.01 s */
struct msghdr msg;
struct iovec iov;
union {
struct cmsghdr cmsghdr;
char control[CMSG_SPACE(3 * sizeof(int))];
} cmsgu;
struct cmsghdr *cmsg;
int *walk;
ssize_t sz;
unsigned char dummy[1] = {'\0'};
iov.iov_base = dummy;
iov.iov_len = sizeof(dummy);
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmsgu.control;
msg.msg_controllen = sizeof(cmsgu.control);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(3 * sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
walk = (int *)CMSG_DATA(cmsg);
*(walk++) = fd0;
*(walk++) = fd1;
*(walk++) = fd2;
/*
* It appears that on some systems, sendmsg(3)
* may return EAGAIN even in blocking mode.
* Seen for example on Oracle Solaris 11.2.
* The sleeping time was chosen by experimentation,
* to neither cause more than a handful of retries
* in normal operation nor unnecessary delays.
*/
for (;;) {
if ((sz = sendmsg(fd, &msg, 0)) != -1 ||
errno != EAGAIN)
break;
nanosleep(&timeout, NULL);
}
return sz;
}
int
process_manpage(int srv_fd, int dstdir_fd, const char *path)
{
int in_fd, out_fd;
int irc;
if ((in_fd = open(path, O_RDONLY)) == -1) {
warn("open(%s)", path);
return 0;
}
if ((out_fd = openat(dstdir_fd, path,
O_WRONLY | O_NOFOLLOW | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) {
warn("openat(%s)", path);
close(in_fd);
return 0;
}
irc = sock_fd_write(srv_fd, in_fd, out_fd, STDERR_FILENO);
close(in_fd);
close(out_fd);
if (irc < 0) {
warn("sendmsg");
return -1;
}
return 0;
}
int
process_tree(int srv_fd, int dstdir_fd)
{
FTS *ftsp;
FTSENT *entry;
const char *argv[2];
const char *path;
argv[0] = ".";
argv[1] = (char *)NULL;
if ((ftsp = fts_open((char * const *)argv,
FTS_PHYSICAL | FTS_NOCHDIR, NULL)) == NULL) {
warn("fts_open");
return -1;
}
while ((entry = fts_read(ftsp)) != NULL) {
path = entry->fts_path + 2;
switch (entry->fts_info) {
case FTS_F:
if (process_manpage(srv_fd, dstdir_fd, path) == -1) {
fts_close(ftsp);
return -1;
}
break;
case FTS_D:
if (*path != '\0' &&
mkdirat(dstdir_fd, path, S_IRWXU | S_IRGRP |
S_IXGRP | S_IROTH | S_IXOTH) == -1 &&
errno != EEXIST) {
warn("mkdirat(%s)", path);
(void)fts_set(ftsp, entry, FTS_SKIP);
}
break;
case FTS_DP:
break;
default:
warnx("%s: not a regular file", path);
break;
}
}
fts_close(ftsp);
return 0;
}
int
main(int argc, char **argv)
{
const char *defos, *outtype;
int srv_fds[2];
int dstdir_fd;
int opt;
pid_t pid;
defos = NULL;
outtype = "ascii";
while ((opt = getopt(argc, argv, "I:T:")) != -1) {
switch (opt) {
case 'I':
defos = optarg;
break;
case 'T':
outtype = optarg;
break;
default:
usage();
}
}
if (argc > 0) {
argc -= optind;
argv += optind;
}
if (argc != 2)
usage();
if (socketpair(AF_LOCAL, SOCK_STREAM, AF_UNSPEC, srv_fds) == -1)
err(1, "socketpair");
pid = fork();
switch (pid) {
case -1:
err(1, "fork");
case 0:
close(srv_fds[0]);
run_mandocd(srv_fds[1], outtype, defos);
default:
break;
}
close(srv_fds[1]);
if ((dstdir_fd = open(argv[1], O_RDONLY | O_DIRECTORY)) == -1)
err(1, "open(%s)", argv[1]);
if (chdir(argv[0]) == -1)
err(1, "chdir(%s)", argv[0]);
return process_tree(srv_fds[0], dstdir_fd) == -1 ? 1 : 0;
}
void
usage(void)
{
fprintf(stderr, "usage: %s [-I os=name] [-T output] "
"srcdir dstdir\n", BINM_CATMAN);
exit(1);
}

8
cgi.c
View File

@ -1,4 +1,4 @@
/* $Id: cgi.c,v 1.144 2017/01/21 01:20:31 schwarze Exp $ */
/* $Id: cgi.c,v 1.147 2017/02/08 13:34:27 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@usta.de>
@ -21,7 +21,9 @@
#include <sys/time.h>
#include <ctype.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@ -113,7 +115,7 @@ static const char *const sec_names[] = {
static const int sec_MAX = sizeof(sec_names) / sizeof(char *);
static const char *const arch_names[] = {
"amd64", "alpha", "armv7",
"amd64", "alpha", "armv7", "arm64",
"hppa", "i386", "landisk",
"loongson", "luna88k", "macppc", "mips64",
"octeon", "sgi", "socppc", "sparc64",
@ -799,6 +801,7 @@ resp_format(const struct req *req, const char *file)
memset(&conf, 0, sizeof(conf));
conf.fragment = 1;
conf.style = mandoc_strdup(CSS_DIR "/mandoc.css");
usepath = strcmp(req->q.manpath, req->p[0]);
mandoc_asprintf(&conf.man, "/%s%s%%N.%%S",
usepath ? req->q.manpath : "", usepath ? "/" : "");
@ -826,6 +829,7 @@ resp_format(const struct req *req, const char *file)
mparse_free(mp);
mchars_free();
free(conf.man);
free(conf.style);
}
static void

View File

@ -1,4 +1,4 @@
/* $Id: chars.c,v 1.68 2015/10/13 22:59:54 schwarze Exp $ */
/* $Id: chars.c,v 1.69 2017/02/17 18:28:06 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -101,8 +101,8 @@ static struct ln lines[] = {
{ "bq", ",", 0x201a },
{ "lq", "\"", 0x201c },
{ "rq", "\"", 0x201d },
{ "Lq", "``", 0x201c },
{ "Rq", "''", 0x201d },
{ "Lq", "\"", 0x201c },
{ "Rq", "\"", 0x201d },
{ "oq", "`", 0x2018 },
{ "cq", "\'", 0x2019 },
{ "aq", "\'", 0x0027 },

View File

@ -6,7 +6,7 @@ int dummy;
#else
/* $Id: compat_fts.c,v 1.12 2016/10/18 23:58:12 schwarze Exp $ */
/* $Id: compat_fts.c,v 1.14 2017/02/18 12:24:24 schwarze Exp $ */
/* $OpenBSD: fts.c,v 1.56 2016/09/21 04:38:56 guenther Exp $ */
/*-
@ -63,15 +63,9 @@ static FTSENT *fts_sort(FTS *, FTSENT *, int);
static unsigned short fts_stat(FTS *, FTSENT *);
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
#ifndef O_DIRECTORY
#define O_DIRECTORY 0
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#define CLR(opt) (sp->fts_options &= ~(opt))
#define ISSET(opt) (sp->fts_options & (opt))
@ -84,7 +78,7 @@ fts_open(char * const *argv, int options,
FTS *sp;
FTSENT *p, *root;
int nitems;
FTSENT *parent, *tmp;
FTSENT *parent, *prev;
/* Options check. */
if (options & ~FTS_OPTIONMASK) {
@ -117,7 +111,7 @@ fts_open(char * const *argv, int options,
parent->fts_level = FTS_ROOTPARENTLEVEL;
/* Allocate/initialize root(s). */
for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
for (root = prev = NULL, nitems = 0; *argv; ++argv, ++nitems) {
if ((p = fts_alloc(sp, *argv, strlen(*argv))) == NULL)
goto mem3;
p->fts_level = FTS_ROOTLEVEL;
@ -139,11 +133,10 @@ fts_open(char * const *argv, int options,
} else {
p->fts_link = NULL;
if (root == NULL)
tmp = root = p;
else {
tmp->fts_link = p;
tmp = p;
}
root = p;
else
prev->fts_link = p;
prev = p;
}
}
if (compar && nitems > 1)

61
configure vendored
View File

@ -1,8 +1,8 @@
#!/bin/sh
#
# $Id: configure,v 1.55 2017/01/12 15:45:05 schwarze Exp $
# $Id: configure,v 1.61 2017/02/18 12:24:24 schwarze Exp $
#
# Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
# Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@ -33,6 +33,8 @@ echo "config.log: writing..."
# Initialize all variables here,
# such that nothing can leak in from the environment.
SOURCEDIR=`dirname "$0"`
MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man"
OSNAME=
UTF8_LOCALE=
@ -44,11 +46,15 @@ LDADD=
LDFLAGS=
LD_NANOSLEEP=
LD_OHASH=
LD_RECVMSG=
STATIC="-static"
BUILD_CGI=0
BUILD_CATMAN=0
INSTALL_LIBMANDOC=0
HAVE_CMSG=
HAVE_CMSG_XPG42=0
HAVE_DIRENT_NAMLEN=
HAVE_EFTYPE=
HAVE_ENDIAN=
@ -61,11 +67,13 @@ HAVE_ISBLANK=
HAVE_MKDTEMP=
HAVE_NANOSLEEP=
HAVE_NTOHL=
HAVE_O_DIRECTORY=
HAVE_OHASH=
HAVE_PATH_MAX=
HAVE_PLEDGE=
HAVE_PROGNAME=
HAVE_REALLOCARRAY=
HAVE_RECVMSG=
HAVE_REWB_BSD=
HAVE_REWB_SYSV=
HAVE_SANDBOX_INIT=
@ -93,6 +101,7 @@ HTDOCDIR=
CGIBINDIR=
BINM_APROPOS="apropos"
BINM_CATMAN="catman"
BINM_MAKEWHATIS="makewhatis"
BINM_MAN="man"
BINM_SOELIM="soelim"
@ -109,6 +118,7 @@ INSTALL_PROGRAM=
INSTALL_LIB=
INSTALL_MAN=
INSTALL_DATA=
LN="ln -f"
# --- manual settings from configure.local -----------------------------
@ -148,7 +158,8 @@ ${1}${3}: testing...
${COMP} -o test-${1} test-${1}.c ${3}
__HEREDOC__
if ${COMP} -o "test-${1}" "test-${1}.c" ${3} 1>&3 2>&3; then
if ${COMP} -o "test-${1}" "${SOURCEDIR}/test-${1}.c" ${3} 1>&3 2>&3
then
echo "${1}${3}: ${CC} succeeded" 1>&3
else
echo "${1}${3}: ${CC} failed with $?" 1>&3
@ -211,6 +222,7 @@ runtest getsubopt GETSUBOPT || true
runtest isblank ISBLANK || true
runtest mkdtemp MKDTEMP || true
runtest ntohl NTOHL || true
runtest O_DIRECTORY O_DIRECTORY || true
runtest PATH_MAX PATH_MAX || true
runtest pledge PLEDGE || true
runtest sandbox_init SANDBOX_INIT || true
@ -266,6 +278,36 @@ if [ "${HAVE_NANOSLEEP}" -eq 0 ]; then
exit 1
fi
if [ ${BUILD_CATMAN} -gt 0 ]; then
# --- recvmsg ---
if [ -n "${LD_RECVMSG}" ]; then
runtest recvmsg RECVMSG "${LD_RECVMSG}" || true
elif singletest recvmsg RECVMSG; then
:
elif runtest recvmsg RECVMSG "-lsocket"; then
LD_RECVMSG="-lsocket"
fi
if [ "${HAVE_RECVMSG}" -eq 0 ]; then
echo "FATAL: recvmsg: no" 1>&2
echo "FATAL: recvmsg: no" 1>&3
echo "Without recvmsg(2), you cannot BUILD_CATMAN." 1>&2
exit 1
fi
# --- cmsg ---
if singletest cmsg CMSG; then
:
elif runtest cmsg CMSG "-D_XPG4_2"; then
HAVE_CMSG_XPG42=1
fi
if [ "${HAVE_CMSG}" -eq 0 ]; then
echo "FATAL: cmsg: no" 1>&2
echo "FATAL: cmsg: no" 1>&3
echo "Without CMSG_FIRSTHDR(3), you cannot BUILD_CATMAN." 1>&2
exit 1
fi
fi
# --- ohash ---
if ismanual ohash OHASH "${HAVE_OHASH}"; then
:
@ -281,7 +323,7 @@ if [ "${HAVE_OHASH}" -eq 0 ]; then
fi
# --- LDADD ---
LDADD="${LDADD} ${LD_NANOSLEEP} ${LD_OHASH} -lz"
LDADD="${LDADD} ${LD_NANOSLEEP} ${LD_RECVMSG} ${LD_OHASH} -lz"
echo "LDADD=\"${LDADD}\"" 1>&2
echo "LDADD=\"${LDADD}\"" 1>&3
echo 1>&3
@ -318,6 +360,7 @@ echo "#define MANPATH_DEFAULT \"${MANPATH_DEFAULT}\""
[ -n "${UTF8_LOCALE}" ] && echo "#define UTF8_LOCALE \"${UTF8_LOCALE}\""
[ -n "${HOMEBREWDIR}" ] && echo "#define HOMEBREWDIR \"${HOMEBREWDIR}\""
[ ${HAVE_EFTYPE} -eq 0 ] && echo "#define EFTYPE EINVAL"
[ ${HAVE_O_DIRECTORY} -eq 0 ] && echo "#define O_DIRECTORY 0"
[ ${HAVE_PATH_MAX} -eq 0 ] && echo "#define PATH_MAX 4096"
if [ ${HAVE_ENDIAN} -eq 0 -a ${HAVE_SYS_ENDIAN} -eq 0 ]; then
echo "#define be32toh ntohl"
@ -325,6 +368,7 @@ if [ ${HAVE_ENDIAN} -eq 0 -a ${HAVE_SYS_ENDIAN} -eq 0 ]; then
fi
cat << __HEREDOC__
#define HAVE_CMSG_XPG42 ${HAVE_CMSG_XPG42}
#define HAVE_DIRENT_NAMLEN ${HAVE_DIRENT_NAMLEN}
#define HAVE_ENDIAN ${HAVE_ENDIAN}
#define HAVE_ERR ${HAVE_ERR}
@ -354,6 +398,7 @@ cat << __HEREDOC__
#define HAVE_OHASH ${HAVE_OHASH}
#define BINM_APROPOS "${BINM_APROPOS}"
#define BINM_CATMAN "${BINM_CATMAN}"
#define BINM_MAKEWHATIS "${BINM_MAKEWHATIS}"
#define BINM_MAN "${BINM_MAN}"
#define BINM_SOELIM "${BINM_SOELIM}"
@ -428,10 +473,14 @@ exec > Makefile.local
[ -z "${INSTALL_DATA}" ] && INSTALL_DATA="${INSTALL} -m 0444"
BUILD_TARGETS=
[ ${BUILD_CGI} -gt 0 ] && BUILD_TARGETS="cgi-build"
[ ${BUILD_CGI} -gt 0 ] && BUILD_TARGETS="man.cgi"
[ ${BUILD_CATMAN} -gt 0 ] && \
BUILD_TARGETS="${BUILD_TARGETS} mandocd catman"
INSTALL_TARGETS=
[ ${INSTALL_LIBMANDOC} -gt 0 ] && INSTALL_TARGETS="lib-install"
[ ${BUILD_CGI} -gt 0 ] && INSTALL_TARGETS="${INSTALL_TARGETS} cgi-install"
[ ${BUILD_CATMAN} -gt 0 ] && \
INSTALL_TARGETS="${INSTALL_TARGETS} catman-install"
cat << __HEREDOC__
BUILD_TARGETS = ${BUILD_TARGETS}
@ -451,6 +500,7 @@ WWWPREFIX = ${WWWPREFIX}
HTDOCDIR = ${HTDOCDIR}
CGIBINDIR = ${CGIBINDIR}
BINM_APROPOS = ${BINM_APROPOS}
BINM_CATMAN = ${BINM_CATMAN}
BINM_MAKEWHATIS = ${BINM_MAKEWHATIS}
BINM_MAN = ${BINM_MAN}
BINM_SOELIM = ${BINM_SOELIM}
@ -466,6 +516,7 @@ INSTALL_PROGRAM = ${INSTALL_PROGRAM}
INSTALL_LIB = ${INSTALL_LIB}
INSTALL_MAN = ${INSTALL_MAN}
INSTALL_DATA = ${INSTALL_DATA}
LN = ${LN}
__HEREDOC__
echo "Makefile.local: written" 1>&2

View File

@ -1,6 +1,6 @@
# $Id: configure.local.example,v 1.22 2016/11/19 15:24:51 schwarze Exp $
# $Id: configure.local.example,v 1.29 2017/02/18 12:24:24 schwarze Exp $
#
# Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
# Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@ -119,6 +119,15 @@ BINM_WHATIS=mwhatis # default is "whatis"
BINM_MAKEWHATIS=mandocdb # default is "makewhatis"
BINM_SOELIM=msoelim # default is "soelim"
# Some distributions do not want hardlinks
# between installed binary programs.
# Set the following variable to use symbolic links instead.
# It is also used for links between manual pages.
# It is only used by the install* targets.
# When using this, DESTDIR must be empty or an absolute path.
LN="ln -sf" # default is "ln -f"
# Before falling back to the bundled version of the ohash(3) hashing
# library, autoconfiguration tries the following linker flag to
# link against your system version. If you do have ohash(3) on
@ -140,6 +149,12 @@ CFLAGS="${CFLAGS} -I/usr/local/include"
LD_NANOSLEEP="-lrt"
# Some platforms may need an additional linker flag for recvmsg(2).
# If none is needed or it is -lsocket, it is autodetected.
# Otherwise, set the following variable.
LD_RECVMSG="-lsocket"
# Some platforms might need additional linker flags to link against
# libmandoc that are not autodetected, though no such cases are
# currently known.
@ -212,6 +227,20 @@ WWWPREFIX="/var/www"
HTDOCDIR="${WWWPREFIX}/htdocs"
CGIBINDIR="${WWWPREFIX}/cgi-bin"
# --- user settings related to catman ----------------------------------
# By default, building mandocd(8) and catman(8) is disabled.
# To enable it, use the following line.
# It does not work on SunOS 5.10 because there is no mkdirat(2)
# nor on SunOS 5.9 which also lacks CMSG_LEN(3) and CMSG_SPACE(3).
BUILD_CATMAN=1
# Install catman(8) with a different name.
# See BINM_MAN above for details of how this works.
BINM_CATMAN=mcatman # default is "catman"
# --- settings that rarely need to be touched --------------------------
# Do not set these variables unless you really need to.
@ -250,6 +279,7 @@ HAVE_GETSUBOPT=0
HAVE_ISBLANK=0
HAVE_MKDTEMP=0
HAVE_NTOHL=0
HAVE_O_DIRECTORY=0
HAVE_OHASH=0
HAVE_PATH_MAX=0
HAVE_PLEDGE=0

14
dba.c
View File

@ -1,4 +1,4 @@
/* $Id: dba.c,v 1.9 2017/01/15 15:28:55 schwarze Exp $ */
/* $Id: dba.c,v 1.10 2017/02/17 14:43:54 schwarze Exp $ */
/*
* Copyright (c) 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
*
@ -315,8 +315,8 @@ compare_names(const void *vp1, const void *vp2)
const char *cp1, *cp2;
int diff;
cp1 = *(char **)vp1;
cp2 = *(char **)vp2;
cp1 = *(const char * const *)vp1;
cp2 = *(const char * const *)vp2;
return (diff = *cp2 - *cp1) ? diff :
strcasecmp(cp1 + 1, cp2 + 1);
}
@ -326,8 +326,8 @@ compare_strings(const void *vp1, const void *vp2)
{
const char *cp1, *cp2;
cp1 = *(char **)vp1;
cp2 = *(char **)vp2;
cp1 = *(const char * const *)vp1;
cp2 = *(const char * const *)vp2;
return strcmp(cp1, cp2);
}
@ -502,7 +502,7 @@ compare_entries(const void *vp1, const void *vp2)
{
const struct macro_entry *ep1, *ep2;
ep1 = *(struct macro_entry **)vp1;
ep2 = *(struct macro_entry **)vp2;
ep1 = *(const struct macro_entry * const *)vp1;
ep2 = *(const struct macro_entry * const *)vp2;
return strcmp(ep1->value, ep2->value);
}

View File

@ -1,4 +1,4 @@
/* $Id: dbm_map.c,v 1.7 2016/10/22 10:09:27 schwarze Exp $ */
/* $Id: dbm_map.c,v 1.8 2017/02/17 14:43:54 schwarze Exp $ */
/*
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
*
@ -175,7 +175,7 @@ dbm_getint(int32_t offset)
int32_t
dbm_addr(const void *p)
{
return htobe32((char *)p - dbm_base);
return htobe32((const char *)p - dbm_base);
}
int

View File

@ -1,7 +1,7 @@
/* $Id: eqn_term.c,v 1.8 2015/01/01 15:36:08 schwarze Exp $ */
/* $Id: eqn_term.c,v 1.9 2017/02/12 14:19:01 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -68,8 +68,10 @@ eqn_box(struct termp *p, const struct eqn_box *bp)
if (bp->pos == EQNPOS_SQRT) {
term_word(p, "sqrt");
p->flags |= TERMP_NOSPACE;
eqn_box(p, bp->first);
if (bp->first != NULL) {
p->flags |= TERMP_NOSPACE;
eqn_box(p, bp->first);
}
} else if (bp->type == EQN_SUBEXPR) {
child = bp->first;
eqn_box(p, child);
@ -93,7 +95,8 @@ eqn_box(struct termp *p, const struct eqn_box *bp)
}
} else {
child = bp->first;
if (bp->type == EQN_MATRIX && child->type == EQN_LIST)
if (bp->type == EQN_MATRIX &&
child != NULL && child->type == EQN_LIST)
child = child->first;
while (child != NULL) {
eqn_box(p,

4
gmdiff
View File

@ -19,7 +19,7 @@ if [ `id -u` -eq 0 ]; then
fi
if [ $# -eq 0 ]; then
echo "usage: $0 -h manual_source_file ..."
echo "usage: $0 [-h] manual_source_file ..."
exit 1
fi
@ -33,7 +33,7 @@ else
EQN="eqn -Tascii"
ROFF="groff -ww -Tascii -P -c"
fi
MOPT="-Werror $MOPT"
MOPT="-Werror -Tascii $MOPT"
while [ -n "$1" ]; do
file=$1

112
html.c
View File

@ -1,4 +1,4 @@
/* $Id: html.c,v 1.200 2017/01/21 02:29:57 schwarze Exp $ */
/* $Id: html.c,v 1.207 2017/02/05 20:22:04 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -65,7 +65,7 @@ static const struct htmldata htmltags[TAG_MAX] = {
{"br", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL},
{"a", 0},
{"table", HTML_NLALL | HTML_INDENT},
{"tbody", HTML_NLALL | HTML_INDENT},
{"colgroup", HTML_NLALL | HTML_INDENT},
{"col", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL},
{"tr", HTML_NLALL | HTML_INDENT},
{"td", HTML_NLAROUND},
@ -76,6 +76,8 @@ static const struct htmldata htmltags[TAG_MAX] = {
{"dt", HTML_NLAROUND},
{"dd", HTML_NLAROUND | HTML_INDENT},
{"pre", HTML_NLALL | HTML_NOINDENT},
{"var", 0},
{"cite", 0},
{"b", 0},
{"i", 0},
{"code", 0},
@ -114,7 +116,6 @@ static const char *const roffscales[SCALE_MAX] = {
static void a2width(const char *, struct roffsu *);
static void print_byte(struct html *, char);
static void print_endline(struct html *);
static void print_endword(struct html *);
static void print_indent(struct html *);
static void print_word(struct html *, const char *);
@ -133,7 +134,7 @@ html_alloc(const struct manoutput *outopts)
h = mandoc_calloc(1, sizeof(struct html));
h->tags.head = NULL;
h->tag = NULL;
h->style = outopts->style;
h->base_man = outopts->man;
h->base_includes = outopts->includes;
@ -151,8 +152,8 @@ html_free(void *p)
h = (struct html *)p;
while ((tag = h->tags.head) != NULL) {
h->tags.head = tag->next;
while ((tag = h->tag) != NULL) {
h->tag = tag->next;
free(tag);
}
@ -450,19 +451,19 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
char numbuf[16];
struct tag *t;
const char *attr;
char *s;
char *arg1, *arg2;
double v;
int i, have_style, tflags;
tflags = htmltags[tag].flags;
/* Push this tags onto the stack of open scopes. */
/* Push this tag onto the stack of open scopes. */
if ((tflags & HTML_NOSTACK) == 0) {
t = mandoc_malloc(sizeof(struct tag));
t->tag = tag;
t->next = h->tags.head;
h->tags.head = t;
t->next = h->tag;
h->tag = t;
} else
t = NULL;
@ -495,12 +496,14 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
have_style = 0;
while (*fmt != '\0') {
if (*fmt == 's') {
print_word(h, " style=\"");
have_style = 1;
fmt++;
break;
}
s = va_arg(ap, char *);
/* Parse a non-style attribute and its arguments. */
arg1 = va_arg(ap, char *);
switch (*fmt++) {
case 'c':
attr = "class";
@ -512,23 +515,31 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
attr = "id";
break;
case '?':
attr = s;
s = va_arg(ap, char *);
attr = arg1;
arg1 = va_arg(ap, char *);
break;
default:
abort();
}
arg2 = NULL;
if (*fmt == 'M')
arg2 = va_arg(ap, char *);
if (arg1 == NULL)
continue;
/* Print the non-style attributes. */
print_byte(h, ' ');
print_word(h, attr);
print_byte(h, '=');
print_byte(h, '"');
switch (*fmt) {
case 'M':
print_href(h, s, va_arg(ap, char *), 1);
print_href(h, arg1, arg2, 1);
fmt++;
break;
case 'I':
print_href(h, s, NULL, 0);
print_href(h, arg1, NULL, 0);
fmt++;
break;
case 'R':
@ -536,7 +547,7 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
fmt++;
/* FALLTHROUGH */
default:
print_encode(h, s, NULL, 1);
print_encode(h, arg1, NULL, 1);
break;
}
print_byte(h, '"');
@ -544,30 +555,37 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
/* Print out styles. */
s = NULL;
su = &mysu;
while (*fmt != '\0') {
arg1 = NULL;
su = NULL;
/* First letter: input argument type. */
switch (*fmt++) {
case 'h':
i = va_arg(ap, int);
su = &mysu;
SCALE_HS_INIT(su, i);
break;
case 's':
s = va_arg(ap, char *);
arg1 = va_arg(ap, char *);
break;
case 'u':
su = va_arg(ap, struct roffsu *);
break;
case 'v':
i = va_arg(ap, int);
su = &mysu;
SCALE_VS_INIT(su, i);
break;
case 'w':
s = va_arg(ap, char *);
a2width(s, su);
case 'W':
if ((arg2 = va_arg(ap, char *)) == NULL)
break;
su = &mysu;
a2width(arg2, su);
if (fmt[-1] == 'W')
su->scale *= -1.0;
break;
default:
abort();
@ -598,33 +616,37 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
attr = "min-width";
break;
case '?':
print_word(h, s);
print_byte(h, ':');
print_byte(h, ' ');
print_word(h, va_arg(ap, char *));
print_byte(h, ';');
if (*fmt != '\0')
print_byte(h, ' ');
continue;
attr = arg1;
arg1 = va_arg(ap, char *);
break;
default:
abort();
}
v = su->scale;
if (su->unit == SCALE_MM && (v /= 100.0) == 0.0)
v = 1.0;
else if (su->unit == SCALE_BU)
v /= 24.0;
if (su == NULL && arg1 == NULL)
continue;
if (have_style == 1)
print_word(h, " style=\"");
else
print_byte(h, ' ');
print_word(h, attr);
print_byte(h, ':');
print_byte(h, ' ');
(void)snprintf(numbuf, sizeof(numbuf), "%.2f", v);
print_word(h, numbuf);
print_word(h, roffscales[su->unit]);
if (su != NULL) {
v = su->scale;
if (su->unit == SCALE_MM && (v /= 100.0) == 0.0)
v = 1.0;
else if (su->unit == SCALE_BU)
v /= 24.0;
(void)snprintf(numbuf, sizeof(numbuf), "%.2f", v);
print_word(h, numbuf);
print_word(h, roffscales[su->unit]);
} else
print_word(h, arg1);
print_byte(h, ';');
if (*fmt != '\0')
print_byte(h, ' ');
have_style = 2;
}
if (have_style)
if (have_style == 2)
print_byte(h, '"');
va_end(ap);
@ -679,7 +701,7 @@ print_ctag(struct html *h, struct tag *tag)
if (tflags & HTML_NLAFTER)
print_endline(h);
h->tags.head = tag->next;
h->tag = tag->next;
free(tag);
}
@ -740,7 +762,7 @@ print_tagq(struct html *h, const struct tag *until)
{
struct tag *tag;
while ((tag = h->tags.head) != NULL) {
while ((tag = h->tag) != NULL) {
print_ctag(h, tag);
if (until && tag == until)
return;
@ -752,7 +774,7 @@ print_stagq(struct html *h, const struct tag *suntil)
{
struct tag *tag;
while ((tag = h->tags.head) != NULL) {
while ((tag = h->tag) != NULL) {
if (suntil && tag == suntil)
return;
print_ctag(h, tag);
@ -809,7 +831,7 @@ print_byte(struct html *h, char c)
* If something was printed on the current output line, end it.
* Not to be called right after print_indent().
*/
static void
void
print_endline(struct html *h)
{
if (h->col == 0)

13
html.h
View File

@ -1,4 +1,4 @@
/* $Id: html.h,v 1.78 2017/01/19 16:59:30 schwarze Exp $ */
/* $Id: html.h,v 1.83 2017/02/05 20:22:04 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -30,7 +30,7 @@ enum htmltag {
TAG_BR,
TAG_A,
TAG_TABLE,
TAG_TBODY,
TAG_COLGROUP,
TAG_COL,
TAG_TR,
TAG_TD,
@ -41,6 +41,8 @@ enum htmltag {
TAG_DT,
TAG_DD,
TAG_PRE,
TAG_VAR,
TAG_CITE,
TAG_B,
TAG_I,
TAG_CODE,
@ -78,10 +80,6 @@ struct tag {
enum htmltag tag;
};
struct tagq {
struct tag *head;
};
struct html {
int flags;
#define HTML_NOSPACE (1 << 0) /* suppress next space */
@ -100,7 +98,7 @@ struct html {
size_t col; /* current output byte position */
size_t bufcol; /* current buf byte position */
char buf[80]; /* output buffer */
struct tagq tags; /* stack of open tags */
struct tag *tag; /* last open tag */
struct rofftbl tbl; /* current table */
struct tag *tblt; /* current open table scope */
char *base_man; /* base for manpage href */
@ -127,5 +125,6 @@ void print_tblclose(struct html *);
void print_tbl(struct html *, const struct tbl_span *);
void print_eqn(struct html *, const struct eqn *);
void print_paragraph(struct html *);
void print_endline(struct html *);
int html_strlen(const char *);

View File

@ -1,4 +1,4 @@
/* $Id: libmandoc.h,v 1.64 2016/07/19 13:36:13 schwarze Exp $ */
/* $Id: libmandoc.h,v 1.66 2017/02/18 13:43:52 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -43,7 +43,7 @@ void mandoc_msg(enum mandocerr, struct mparse *,
int, int, const char *);
void mandoc_vmsg(enum mandocerr, struct mparse *,
int, int, const char *, ...)
__attribute__((__format__ (printf, 5, 6)));
__attribute__((__format__ (__printf__, 5, 6)));
char *mandoc_getarg(struct mparse *, char **, int, int *);
char *mandoc_normdate(struct mparse *, char *, int, int);
int mandoc_eos(const char *, size_t);
@ -59,7 +59,7 @@ int man_parseln(struct roff_man *, int, char *, int);
void man_endparse(struct roff_man *);
int preconv_cue(const struct buf *, size_t);
int preconv_encode(struct buf *, size_t *,
int preconv_encode(const struct buf *, size_t *,
struct buf *, size_t *, int *);
void roff_free(struct roff *);

View File

@ -1,4 +1,4 @@
/* $Id: libmdoc.h,v 1.108 2015/11/07 14:01:16 schwarze Exp $ */
/* $Id: libmdoc.h,v 1.109 2017/02/16 03:00:23 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -70,7 +70,7 @@ struct roff_node *mdoc_block_alloc(struct roff_man *, int, int,
int, struct mdoc_arg *);
void mdoc_tail_alloc(struct roff_man *, int, int, int);
struct roff_node *mdoc_endbody_alloc(struct roff_man *, int, int, int,
struct roff_node *, enum mdoc_endbody);
struct roff_node *);
void mdoc_node_relink(struct roff_man *, struct roff_node *);
void mdoc_node_validate(struct roff_man *);
void mdoc_state(struct roff_man *, struct roff_node *);

43
main.c
View File

@ -1,4 +1,4 @@
/* $Id: main.c,v 1.279 2017/01/09 17:49:57 schwarze Exp $ */
/* $Id: main.c,v 1.283 2017/02/17 14:31:52 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -100,7 +100,7 @@ static void parse(struct curparse *, int, const char *);
static void passthrough(const char *, int, int);
static pid_t spawn_pager(struct tag_files *);
static int toptions(struct curparse *, char *);
static void usage(enum argmode) __attribute__((noreturn));
static void usage(enum argmode) __attribute__((__noreturn__));
static int woptions(struct curparse *, char *);
static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
@ -113,16 +113,14 @@ int
main(int argc, char *argv[])
{
struct manconf conf;
struct curparse curp;
struct mansearch search;
struct curparse curp;
struct tag_files *tag_files;
const char *progname;
char *auxpaths;
char *defos;
unsigned char *uc;
struct manpage *res, *resp;
char *conf_file, *defpaths;
const char *sec;
const char *progname, *sec, *thisarg;
char *conf_file, *defpaths, *auxpaths;
char *defos, *oarg;
unsigned char *uc;
size_t i, sz;
int prio, best_prio;
enum outmode outmode;
@ -168,6 +166,7 @@ main(int argc, char *argv[])
memset(&search, 0, sizeof(struct mansearch));
search.outkey = "Nd";
oarg = NULL;
if (strcmp(progname, BINM_MAN) == 0)
search.argmode = ARG_NAME;
@ -246,10 +245,7 @@ main(int argc, char *argv[])
auxpaths = optarg;
break;
case 'O':
search.outkey = optarg;
while (optarg != NULL)
manconf_output(&conf.output,
strsep(&optarg, ","));
oarg = optarg;
break;
case 'S':
search.arch = optarg;
@ -294,6 +290,21 @@ main(int argc, char *argv[])
}
}
if (oarg != NULL) {
if (outmode == OUTMODE_LST)
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;
}
}
}
if (outmode == OUTMODE_FLN ||
outmode == OUTMODE_LST ||
!isatty(STDOUT_FILENO))
@ -736,7 +747,8 @@ parse(struct curparse *curp, int fd, const char *file)
if (man == NULL)
return;
if (man->macroset == MACROSET_MDOC) {
mdoc_validate(man);
if (curp->outtype != OUTT_TREE || !curp->outopts->noval)
mdoc_validate(man);
switch (curp->outtype) {
case OUTT_HTML:
html_mdoc(curp->outdata, man);
@ -759,7 +771,8 @@ parse(struct curparse *curp, int fd, const char *file)
}
}
if (man->macroset == MACROSET_MAN) {
man_validate(man);
if (curp->outtype != OUTT_TREE || !curp->outopts->noval)
man_validate(man);
switch (curp->outtype) {
case OUTT_HTML:
html_man(curp->outdata, man);

22
man.1
View File

@ -1,4 +1,4 @@
.\" $Id: man.1,v 1.20 2017/01/06 01:34:57 schwarze Exp $
.\" $Id: man.1,v 1.21 2017/01/31 19:44:04 schwarze Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -31,7 +31,7 @@
.\"
.\" @(#)man.1 8.2 (Berkeley) 1/2/94
.\"
.Dd $Mdocdate: January 6 2017 $
.Dd $Mdocdate: January 31 2017 $
.Dt MAN 1
.Os
.Sh NAME
@ -427,9 +427,23 @@ in
.Fl C
in
.Nx 1.0 ;
and
.Fl s
and
.Fl S
in
.Ox 2.3 .
.Ox 2.3 ;
and
.Fl I ,
.Fl K ,
.Fl l ,
.Fl O ,
and
.Fl W
in
.Ox 5.7 .
The
.Fl T
option first appeared in
.At III
and was also added in
.Ox 5.7 .

1326
man.options.1 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $Id: man_html.c,v 1.129 2017/01/21 01:20:32 schwarze Exp $ */
/* $Id: man_html.c,v 1.133 2017/02/05 18:15:39 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -32,21 +32,14 @@
#include "html.h"
#include "main.h"
/* TODO: preserve ident widths. */
/* FIXME: have PD set the default vspace width. */
#define INDENT 5
#define MAN_ARGS const struct roff_meta *man, \
const struct roff_node *n, \
struct mhtml *mh, \
struct html *h
struct mhtml {
int fl;
#define MANH_LITERAL (1 << 0) /* literal context */
};
struct htmlman {
int (*pre)(MAN_ARGS);
int (*post)(MAN_ARGS);
@ -57,6 +50,7 @@ static void print_bvspace(struct html *,
static void print_man_head(MAN_ARGS);
static void print_man_nodelist(MAN_ARGS);
static void print_man_node(MAN_ARGS);
static int fillmode(struct html *, int);
static int a2width(const struct roff_node *,
struct roffsu *);
static int man_B_pre(MAN_ARGS);
@ -74,7 +68,6 @@ static int man_alt_pre(MAN_ARGS);
static int man_br_pre(MAN_ARGS);
static int man_ign_pre(MAN_ARGS);
static int man_in_pre(MAN_ARGS);
static int man_literal_pre(MAN_ARGS);
static void man_root_post(MAN_ARGS);
static void man_root_pre(MAN_ARGS);
@ -101,8 +94,8 @@ static const struct htmlman mans[MAN_MAX] = {
{ man_alt_pre, NULL }, /* IR */
{ man_alt_pre, NULL }, /* RI */
{ man_br_pre, NULL }, /* sp */
{ man_literal_pre, NULL }, /* nf */
{ man_literal_pre, NULL }, /* fi */
{ NULL, NULL }, /* nf */
{ NULL, NULL }, /* fi */
{ NULL, NULL }, /* RE */
{ man_RS_pre, NULL }, /* RS */
{ man_ign_pre, NULL }, /* DT */
@ -112,8 +105,8 @@ static const struct htmlman mans[MAN_MAX] = {
{ man_in_pre, NULL }, /* in */
{ man_ign_pre, NULL }, /* ft */
{ man_OP_pre, NULL }, /* OP */
{ man_literal_pre, NULL }, /* EX */
{ man_literal_pre, NULL }, /* EE */
{ NULL, NULL }, /* EX */
{ NULL, NULL }, /* EE */
{ man_UR_pre, NULL }, /* UR */
{ NULL, NULL }, /* UE */
{ man_ign_pre, NULL }, /* ll */
@ -146,27 +139,25 @@ print_bvspace(struct html *h, const struct roff_node *n)
void
html_man(void *arg, const struct roff_man *man)
{
struct mhtml mh;
struct html *h;
struct tag *t;
memset(&mh, 0, sizeof(mh));
h = (struct html *)arg;
if ((h->oflags & HTML_FRAGMENT) == 0) {
print_gen_decls(h);
print_otag(h, TAG_HTML, "");
t = print_otag(h, TAG_HEAD, "");
print_man_head(&man->meta, man->first, &mh, h);
print_man_head(&man->meta, man->first, h);
print_tagq(h, t);
print_otag(h, TAG_BODY, "");
}
man_root_pre(&man->meta, man->first, &mh, h);
man_root_pre(&man->meta, man->first, h);
t = print_otag(h, TAG_DIV, "c", "manual-text");
print_man_nodelist(&man->meta, man->first->child, &mh, h);
print_man_nodelist(&man->meta, man->first->child, h);
print_tagq(h, t);
man_root_post(&man->meta, man->first, &mh, h);
man_root_post(&man->meta, man->first, h);
print_tagq(h, NULL);
}
@ -187,7 +178,7 @@ print_man_nodelist(MAN_ARGS)
{
while (n != NULL) {
print_man_node(man, n, mh, h);
print_man_node(man, n, h);
n = n->next;
}
}
@ -195,25 +186,95 @@ print_man_nodelist(MAN_ARGS)
static void
print_man_node(MAN_ARGS)
{
int child;
struct tag *t;
static int want_fillmode = MAN_fi;
static int save_fillmode;
child = 1;
t = h->tags.head;
struct tag *t;
int child;
/*
* Handle fill mode switch requests up front,
* they would just cause trouble in the subsequent code.
*/
switch (n->tok) {
case MAN_nf:
case MAN_EX:
want_fillmode = MAN_nf;
return;
case MAN_fi:
case MAN_EE:
want_fillmode = MAN_fi;
if (fillmode(h, 0) == MAN_fi)
print_otag(h, TAG_BR, "");
return;
default:
break;
}
/* Set up fill mode for the upcoming node. */
switch (n->type) {
case ROFFT_TEXT:
if ('\0' == *n->string) {
print_paragraph(h);
return;
case ROFFT_BLOCK:
save_fillmode = 0;
/* Some block macros suspend or cancel .nf. */
switch (n->tok) {
case MAN_TP: /* Tagged paragraphs */
case MAN_IP: /* temporarily disable .nf */
case MAN_HP: /* for the head. */
save_fillmode = want_fillmode;
/* FALLTHROUGH */
case MAN_SH: /* Section headers */
case MAN_SS: /* permanently cancel .nf. */
want_fillmode = MAN_fi;
/* FALLTHROUGH */
case MAN_PP: /* These have no head. */
case MAN_LP: /* They will simply */
case MAN_P: /* reopen .nf in the body. */
case MAN_RS:
case MAN_UR:
fillmode(h, MAN_fi);
break;
default:
break;
}
if (n->flags & NODE_LINE && (*n->string == ' ' ||
(n->prev != NULL && mh->fl & MANH_LITERAL &&
! (h->flags & HTML_NONEWLINE))))
break;
case ROFFT_TBL:
fillmode(h, MAN_fi);
break;
case ROFFT_ELEM:
/*
* Some in-line macros produce tags and/or text
* in the handler, so they require fill mode to be
* configured up front just like for text nodes.
* For the others, keep the traditional approach
* of doing the same, for now.
*/
fillmode(h, want_fillmode);
break;
case ROFFT_TEXT:
if (fillmode(h, want_fillmode) == MAN_fi &&
want_fillmode == MAN_fi &&
n->flags & NODE_LINE && *n->string == ' ')
print_otag(h, TAG_BR, "");
print_text(h, n->string);
if (*n->string != '\0')
break;
print_paragraph(h);
return;
default:
break;
}
/* Produce output for this node. */
child = 1;
switch (n->type) {
case ROFFT_TEXT:
t = h->tag;
print_text(h, n->string);
break;
case ROFFT_EQN:
t = h->tag;
print_eqn(h, n->eqn);
break;
case ROFFT_TBL:
@ -239,29 +300,55 @@ print_man_node(MAN_ARGS)
* the "meta" table state. This will be reopened on the
* next table element.
*/
if (h->tblt) {
if (h->tblt)
print_tblclose(h);
t = h->tags.head;
}
t = h->tag;
if (mans[n->tok].pre)
child = (*mans[n->tok].pre)(man, n, mh, h);
child = (*mans[n->tok].pre)(man, n, h);
/* Some block macros resume .nf in the body. */
if (save_fillmode && n->type == ROFFT_BODY)
want_fillmode = save_fillmode;
break;
}
if (child && n->child)
print_man_nodelist(man, n->child, mh, h);
print_man_nodelist(man, n->child, h);
/* This will automatically close out any font scope. */
print_stagq(h, t);
switch (n->type) {
case ROFFT_EQN:
break;
default:
if (mans[n->tok].post)
(*mans[n->tok].post)(man, n, mh, h);
break;
if (fillmode(h, 0) == MAN_nf &&
n->next != NULL && n->next->flags & NODE_LINE)
print_endline(h);
}
/*
* MAN_nf switches to no-fill mode, MAN_fi to fill mode.
* Other arguments do not switch.
* The old mode is returned.
*/
static int
fillmode(struct html *h, int want)
{
struct tag *pre;
int had;
for (pre = h->tag; pre != NULL; pre = pre->next)
if (pre->tag == TAG_PRE)
break;
had = pre == NULL ? MAN_fi : MAN_nf;
if (want && want != had) {
if (want == MAN_nf)
print_otag(h, TAG_PRE, "");
else
print_tagq(h, pre);
}
return had;
}
static int
@ -287,7 +374,6 @@ man_root_pre(MAN_ARGS)
mandoc_asprintf(&title, "%s(%s)", man->title, man->msec);
t = print_otag(h, TAG_TABLE, "c", "head");
print_otag(h, TAG_TBODY, "");
tt = print_otag(h, TAG_TR, "");
print_otag(h, TAG_TD, "c", "head-ltitle");
@ -349,13 +435,8 @@ man_br_pre(MAN_ARGS)
static int
man_SH_pre(MAN_ARGS)
{
if (n->type == ROFFT_BLOCK) {
mh->fl &= ~MANH_LITERAL;
return 1;
} else if (n->type == ROFFT_BODY)
return 1;
print_otag(h, TAG_H1, "c", "Sh");
if (n->type == ROFFT_HEAD)
print_otag(h, TAG_H1, "c", "Sh");
return 1;
}
@ -363,17 +444,11 @@ static int
man_alt_pre(MAN_ARGS)
{
const struct roff_node *nn;
int i, savelit;
int i;
enum htmltag fp;
struct tag *t;
if ((savelit = mh->fl & MANH_LITERAL))
print_otag(h, TAG_BR, "");
mh->fl &= ~MANH_LITERAL;
for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
t = NULL;
switch (n->tok) {
case MAN_BI:
fp = i % 2 ? TAG_I : TAG_B;
@ -400,18 +475,14 @@ man_alt_pre(MAN_ARGS)
if (i)
h->flags |= HTML_NOSPACE;
if (TAG_MAX != fp)
if (fp != TAG_MAX)
t = print_otag(h, fp, "");
print_man_node(man, nn, mh, h);
print_text(h, nn->string);
if (t)
if (fp != TAG_MAX)
print_tagq(h, t);
}
if (savelit)
mh->fl |= MANH_LITERAL;
return 0;
}
@ -427,13 +498,8 @@ man_SM_pre(MAN_ARGS)
static int
man_SS_pre(MAN_ARGS)
{
if (n->type == ROFFT_BLOCK) {
mh->fl &= ~MANH_LITERAL;
return 1;
} else if (n->type == ROFFT_BODY)
return 1;
print_otag(h, TAG_H2, "c", "Ss");
if (n->type == ROFFT_HEAD)
print_otag(h, TAG_H2, "c", "Ss");
return 1;
}
@ -469,7 +535,7 @@ man_IP_pre(MAN_ARGS)
/* For IP, only print the first header element. */
if (MAN_IP == n->tok && n->child)
print_man_node(man, n->child, mh, h);
print_man_node(man, n->child, h);
/* For TP, only print next-line header elements. */
@ -478,7 +544,7 @@ man_IP_pre(MAN_ARGS)
while (NULL != nn && 0 == (NODE_LINE & nn->flags))
nn = nn->next;
while (NULL != nn) {
print_man_node(man, nn, mh, h);
print_man_node(man, nn, h);
nn = nn->next;
}
}
@ -551,19 +617,6 @@ man_I_pre(MAN_ARGS)
return 1;
}
static int
man_literal_pre(MAN_ARGS)
{
if (MAN_fi == n->tok || MAN_EE == n->tok) {
print_otag(h, TAG_BR, "");
mh->fl &= ~MANH_LITERAL;
} else
mh->fl |= MANH_LITERAL;
return 0;
}
static int
man_in_pre(MAN_ARGS)
{
@ -610,7 +663,7 @@ man_UR_pre(MAN_ARGS)
if (n->next->child != NULL)
n = n->next;
print_man_nodelist(man, n->child, mh, h);
print_man_nodelist(man, n->child, h);
return 0;
}

View File

@ -1,7 +1,7 @@
/* $Id: man_term.c,v 1.188 2017/01/10 13:47:00 schwarze Exp $ */
/* $Id: man_term.c,v 1.191 2017/02/15 14:10:08 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -143,6 +143,7 @@ terminal_man(void *arg, const struct roff_man *man)
struct termp *p;
struct roff_node *n;
struct mtermp mt;
size_t save_defindent;
p = (struct termp *)arg;
p->overstep = 0;
@ -170,6 +171,7 @@ terminal_man(void *arg, const struct roff_man *man)
n = n->next;
}
} else {
save_defindent = p->defindent;
if (p->defindent == 0)
p->defindent = 7;
term_begin(p, print_man_head, print_man_foot, &man->meta);
@ -177,6 +179,7 @@ terminal_man(void *arg, const struct roff_man *man)
if (n != NULL)
print_man_nodelist(p, &mt, n, &man->meta);
term_end(p);
p->defindent = save_defindent;
}
}
@ -819,7 +822,8 @@ pre_SH(DECL_ARGS)
do {
n = n->prev;
} while (n != NULL && termacts[n->tok].flags & MAN_NOTEXT);
} while (n != NULL && n->tok != TOKEN_NONE &&
termacts[n->tok].flags & MAN_NOTEXT);
if (n == NULL || (n->tok == MAN_SH && n->body->child == NULL))
break;

View File

@ -35,6 +35,7 @@ struct manoutput {
int fragment;
int mdoc;
int synopsisonly;
int noval;
};
struct manconf {
@ -44,5 +45,5 @@ struct manconf {
void manconf_parse(struct manconf *, const char *, char *, char *);
void manconf_output(struct manoutput *, const char *);
int manconf_output(struct manoutput *, const char *, int);
void manconf_free(struct manconf *);

View File

@ -1,4 +1,4 @@
.\" $Id: mandoc.1,v 1.171 2017/01/21 02:32:39 schwarze Exp $
.\" $Id: mandoc.1,v 1.174 2017/02/10 15:45:28 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2012, 2014-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: January 21 2017 $
.Dd $Mdocdate: February 10 2017 $
.Dt MANDOC 1
.Os
.Sh NAME
@ -538,6 +538,8 @@ A closing parenthesis if the node is a closing delimiter.
.It
A full stop if the node ends a sentence.
.It
BROKEN if the node is a block broken by another block.
.It
NOSRC if the node is not in the input file,
but automatically generated from macros.
.It
@ -545,6 +547,17 @@ NOPRT if the node is not supposed to generate output
for any output format.
.El
.El
.Pp
The following
.Fl O
argument is accepted:
.Bl -tag -width Ds
.It Cm noval
Skip validation and show the unvalidated syntax tree.
This can help to find out whether a given behaviour is caused by
the parser or by the validator.
Meta data is not available in this case.
.El
.Sh ENVIRONMENT
.Bl -tag -width MANPAGER
.It Ev MANPAGER
@ -1357,6 +1370,10 @@ it is hard to predict which tab stop position the tab will advance to.
Whitespace at the end of input lines is almost never semantically
significant \(em but in the odd case where it might be, it is
extremely confusing when reviewing and maintaining documents.
.It Sy "new sentence, new line"
.Pq mdoc
A new sentence starts in the middle of a text line.
Start it on a new input line to help formatters produce correct spacing.
.It Sy "bad comment style"
.Pq roff
Comment lines start with a dot, a backslash, and a double-quote character.
@ -1832,6 +1849,19 @@ as if they were a text line.
.Xr mdoc 7 ,
.Xr roff 7 ,
.Xr tbl 7
.Sh HISTORY
The
.Nm
utility first appeared in
.Ox 4.8 .
The option
.Fl I
appeared in
.Ox 5.2 ,
and
.Fl aCcfhKklMSsw
in
.Ox 5.7 .
.Sh AUTHORS
.An -nosplit
The

View File

@ -1,4 +1,4 @@
/* $Id: mandoc.css,v 1.13 2017/01/21 02:29:57 schwarze Exp $ */
/* $Id: mandoc.css,v 1.17 2017/02/05 21:00:43 schwarze Exp $ */
/*
* Standard style sheet for mandoc(1) -Thtml and man.cgi(8).
*/
@ -91,15 +91,25 @@ dd.It-inset { }
dl.Bl-ohang { }
dt.It-ohang { }
dd.It-ohang { margin-left: 0ex; }
dl.Bl-tag { }
dt.It-tag { }
dd.It-tag { }
dl.Bl-tag { margin-left: 8ex; }
dt.It-tag { float: left;
clear: both;
margin-top: 0ex;
margin-left: -8ex;
padding-right: 2ex;
vertical-align: top; }
dd.It-tag { width: 100%;
margin-top: 0ex;
margin-left: 0ex;
vertical-align: top;
overflow: auto; }
table.Bl-column { }
tr.It-column { }
td.It-column { margin-top: 1em; }
span.Rs { }
cite.Rs { font-style: normal;
font-weight: normal; }
span.RsA { }
i.RsB { font-weight: normal; }
span.RsC { }
@ -124,7 +134,8 @@ table.Nm { }
b.Nm { font-style: normal; }
b.Fl { font-style: normal; }
b.Cm { font-style: normal; }
i.Ar { font-weight: normal; }
var.Ar { font-style: italic;
font-weight: normal; }
span.Op { }
b.Ic { font-style: normal; }
code.Ev { font-style: normal;
@ -138,11 +149,15 @@ span.Lb { }
b.In { font-style: normal; }
a.In { }
b.Fd { font-style: normal; }
i.Ft { font-weight: normal; }
var.Ft { font-style: italic;
font-weight: normal; }
b.Fn { font-style: normal; }
i.Fa { font-weight: normal; }
i.Vt { font-weight: normal; }
i.Va { font-weight: normal; }
var.Fa { font-style: italic;
font-weight: normal; }
var.Vt { font-style: italic;
font-weight: normal; }
var.Va { font-style: italic;
font-weight: normal; }
code.Dv { font-style: normal;
font-weight: normal;
font-family: monospace; }
@ -158,6 +173,7 @@ a.Mt { }
b.Cd { font-style: normal; }
i.Ad { font-weight: normal; }
b.Ms { font-style: normal; }
span.St { }
a.Ux { }
/* Physical markup. */

View File

@ -1,4 +1,4 @@
/* $Id: mandoc.h,v 1.213 2017/01/09 01:37:03 schwarze Exp $ */
/* $Id: mandoc.h,v 1.214 2017/01/28 23:30:08 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -134,6 +134,7 @@ enum mandocerr {
MANDOCERR_FI_BLANK, /* blank line in fill mode, using .sp */
MANDOCERR_FI_TAB, /* tab in filled text */
MANDOCERR_SPACE_EOL, /* whitespace at end of input line */
MANDOCERR_EOS, /* new sentence, new line */
MANDOCERR_COMMENT_BAD, /* bad comment style */
MANDOCERR_ESC_BAD, /* invalid escape sequence: esc */
MANDOCERR_STR_UNDEF, /* undefined string, using "": name */

View File

@ -1,4 +1,4 @@
/* $Id: mandoc_aux.h,v 1.5 2016/07/19 13:36:13 schwarze Exp $ */
/* $Id: mandoc_aux.h,v 1.6 2017/02/17 14:31:52 schwarze Exp $ */
/*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@ -17,7 +17,7 @@
*/
int mandoc_asprintf(char **, const char *, ...)
__attribute__((__format__ (printf, 2, 3)));
__attribute__((__format__ (__printf__, 2, 3)));
void *mandoc_calloc(size_t, size_t);
void *mandoc_malloc(size_t);
void *mandoc_realloc(void *, size_t);

View File

@ -1,4 +1,4 @@
.\" $Id: mandoc_char.7,v 1.63 2015/09/02 15:38:35 schwarze Exp $
.\" $Id: mandoc_char.7,v 1.64 2017/02/05 21:41:21 schwarze Exp $
.\"
.\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 2 2015 $
.Dd $Mdocdate: February 5 2017 $
.Dt MANDOC_CHAR 7
.Os
.Sh NAME
@ -62,6 +62,30 @@ blue-eyed
lorry-driver
.Ed
.Pp
If a word on a text input line contains a hyphen, a formatter may decide
to insert an output line break after the hyphen if that helps filling
the current output line, but the whole word would overflow the line.
If it is important that the word is not broken across lines in this
way, a zero-width space
.Pq Sq \e&
can be inserted before or after the hyphen.
While
.Xr mandoc 1
never breaks the output line after hyphens adjacent to a zero-width
space, after any of the other dash- or hyphen-like characters
represented by escape sequences, or after hyphens inside words in
macro arguments, other software may not respect these rules and may
break the line even in such cases.
.Pp
Some
.Xr roff 7
implementations contains dictionaries allowing to break the line
at syllable boundaries even inside words that contain no hyphens.
Such automatic hyphenation is not supported by
.Xr mandoc 1 ,
which only breaks the line at whitespace, and inside words only
after existing hyphens.
.Pp
The mathematical minus sign is used for negative numbers or subtraction.
It should be written as
.Sq \e(mi :

View File

@ -1,4 +1,4 @@
.\" $Id: mandoc_html.3,v 1.3 2017/01/17 15:32:44 schwarze Exp $
.\" $Id: mandoc_html.3,v 1.5 2017/01/28 22:36:38 schwarze Exp $
.\"
.\" Copyright (c) 2014, 2017 Ingo Schwarze <schwarze@openbsd.org>
.\"
@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: January 17 2017 $
.Dd $Mdocdate: January 28 2017 $
.Dt MANDOC_HTML 3
.Os
.Sh NAME
@ -137,6 +137,9 @@ Most attributes require one
.Va char *
argument which becomes the value of the attribute.
The arguments have to be given in the same order as the attribute letters.
If an argument is
.Dv NULL ,
the respective attribute is not written.
.Bl -tag -width 1n -offset indent
.It Cm c
Print a
@ -175,13 +178,15 @@ Print an arbitrary attribute.
This format letter requires two
.Vt char *
arguments, the attribute name and the value.
The name must not be
.Dv NULL .
.It Cm s
Print a
.Cm style
attribute.
If present, it must be the last format letter.
In contrast to the other format letters, this one does not yet
print the value and does not require an argument.
print the value and does not take an argument.
Instead, the rest of the format string consists of pairs of
argument type letters and style name letters.
.El
@ -212,6 +217,13 @@ Requires one
argument, interpreted as an
.Xr mdoc 7 Ns -style
width specifier.
If the argument is
.Dv NULL ,
nothing is printed for this pair.
.It Cm W
Similar to
.Cm w ,
but makes the width negative by multiplying it with \(mi1.
.El
.Pp
Style name letters decide what to do with the preceding argument:
@ -251,6 +263,8 @@ requires two
.Vt char *
arguments.
The first is the style name, the second its value.
The style name must not be
.Dv NULL .
.El
.Pp
.Fn print_otag
@ -336,5 +350,6 @@ implementation of common mandoc utility functions
.An -nosplit
The mandoc HTML formatter was written by
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
This manual was written by
.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
It is maintained by
.An Ingo Schwarze Aq Mt schwarze@openbsd.org ,
who also wrote this manual.

198
mandocd.8 Normal file
View File

@ -0,0 +1,198 @@
.\" $Id: mandocd.8,v 1.1 2017/02/06 19:04:21 schwarze Exp $
.\"
.\" Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: February 6 2017 $
.Dt MANDOCD 8
.Os
.Sh NAME
.Nm mandocd
.Nd server process to format manual pages in batch mode
.Sh SYNOPSIS
.Nm mandocd
.Op Fl I Cm os Ns = Ns Ar name
.Op Fl T Ar output
.Ar socket_fd
.Sh DESCRIPTION
The
.Nm
utility formats many manual pages without requiring
.Xr fork 2
and
.Xr exec 3
overhead in between.
It does not require listing all the manuals to be formatted on the
command line, and it supports writing each formatted manual to its
own file descriptor.
.Pp
This server requires that a connected UNIX domain
.Xr socket 2
is already present at
.Xr exec 3
time.
Consequently, it cannot be started from the
.Xr sh 1
command line because the shell cannot supply such a socket.
Typically, the socket is created by the parent process using
.Xr socketpair 2
before calling
.Xr fork 2
and
.Xr exec 3
on
.Nm .
The parent process will pass the file descriptor number as an argument to
.Xr exec 3 ,
formatted as a decimal ASCII-encoded integer.
See
.Xr catman 8
for a typical implementation of a parent process.
.Pp
.Nm
loops reading one-byte messages with
.Xr recvmsg 2
from the file descriptor number
.Ar socket_fd .
It ignores the byte read and only uses the out-of-band auxiliary
.Vt struct cmsghdr
control data, typically supplied by the calling process using
.Xr CMSG_FIRSTHDR 3 .
The parent process is expected to pass three file descriptors
with each dummy byte.
The first one is used for
.Xr mdoc 7
or
.Xr man 7
input, the second one for formatted output, and the third one
for error output.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl I Cm os Ns = Ns Ar name
Override the default operating system
.Ar name
for the
.Xr mdoc 7
.Ic Os
and for the
.Xr man 7
.Ic TH
macro.
.It Fl T Ar output
Output format.
The
.Ar output
argument can be
.Cm ascii ,
.Cm utf8 ,
or
.Cm html ;
see
.Xr mandoc 1 .
In
.Cm html
output mode, the
.Cm fragment
output option is implied.
Other output options are not supported.
.El
.Pp
After exhausting one input file descriptor, all three file descriptors
are closed before reading the next dummy byte and control message.
.Pp
When a zero-byte message is read, when the
.Ar socket_fd
is closed by the parent process,
or when an error occurs,
.Nm
exits.
.Sh EXIT STATUS
.Ex -std
.Pp
A zero-byte message or a closed
.Ar socket_fd
is considered success.
Possible errors include:
.Bl -bullet
.It
missing, invalid, or excessive
.Xr exec 3
arguments
.It
.Xr recvmsg 2
failure, for example due to
.Er EMSGSIZE
.It
missing or unexpected control data, in particular a
.Fa cmsg_level
in the
.Vt struct cmsghdr
that differs from
.Dv SOL_SOCKET ,
a
.Fa cmsg_type
that differs from
.Dv SCM_RIGHTS ,
or a
.Fa cmsg_len
that is not three times the size of an
.Vt int
.It
invalid file descriptors passed in the
.Xr CMSG_DATA 3
.It
resource exhaustion, in particular
.Xr dup 2
or
.Xr malloc 3
failure
.El
.Pp
Except for memory exhaustion and similar system-level failures,
parsing and formatting errors do not cause
.Nm
to return an error exit status.
Even after severe parsing errors,
.Nm
will simply accept and process the next input file descriptor.
.Sh SEE ALSO
.Xr mandoc 1 ,
.Xr mandoc 3 ,
.Xr catman 8
.Sh HISTORY
The
.Nm
utility appeared in version 1.14.1 or the
.Sy mandoc
toolkit.
.Sh AUTHORS
.An -nosplit
The concept was designed and implemented by
.An Michael Stapelberg Aq Mt stapelberg@debian.org .
The
.Xr mandoc 3
glue needed to make it a stand-alone process was added by
.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
.Sh CAVEATS
If the parsed manual pages contain
.Xr roff 7
.Pf . Ic so
requests,
.Nm
needs to be started with the current working directory set to the
root of the manual page tree.
Avoid starting it in directories that contain secret files in any
subdirectories, in particular in the user starting it has read
access to these secret files.

285
mandocd.c Normal file
View File

@ -0,0 +1,285 @@
/* $Id: mandocd.c,v 1.5 2017/02/17 14:31:52 schwarze Exp $ */
/*
* Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
* Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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.
*/
#include "config.h"
#if HAVE_CMSG_XPG42
#define _XPG4_2
#endif
#include <sys/types.h>
#include <sys/socket.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mandoc.h"
#include "roff.h"
#include "mdoc.h"
#include "man.h"
#include "main.h"
#include "manconf.h"
enum outt {
OUTT_ASCII = 0,
OUTT_UTF8,
OUTT_HTML
};
static void process(struct mparse *, enum outt, void *);
static int read_fds(int, int *);
static void usage(void) __attribute__((__noreturn__));
#define NUM_FDS 3
static int
read_fds(int clientfd, int *fds)
{
struct msghdr msg;
struct iovec iov[1];
unsigned char dummy[1];
struct cmsghdr *cmsg;
int *walk;
int cnt;
/* Union used for alignment. */
union {
uint8_t controlbuf[CMSG_SPACE(NUM_FDS * sizeof(int))];
struct cmsghdr align;
} u;
memset(&msg, '\0', sizeof(msg));
msg.msg_control = u.controlbuf;
msg.msg_controllen = sizeof(u.controlbuf);
/*
* Read a dummy byte - sendmsg cannot send an empty message,
* even if we are only interested in the OOB data.
*/
iov[0].iov_base = dummy;
iov[0].iov_len = sizeof(dummy);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
switch (recvmsg(clientfd, &msg, 0)) {
case -1:
warn("recvmsg");
return -1;
case 0:
return 0;
default:
break;
}
if ((cmsg = CMSG_FIRSTHDR(&msg)) == NULL) {
warnx("CMSG_FIRSTHDR: missing control message");
return -1;
}
if (cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS ||
cmsg->cmsg_len != CMSG_LEN(NUM_FDS * sizeof(int))) {
warnx("CMSG_FIRSTHDR: invalid control message");
return -1;
}
walk = (int *)CMSG_DATA(cmsg);
for (cnt = 0; cnt < NUM_FDS; cnt++)
fds[cnt] = *walk++;
return 1;
}
int
main(int argc, char *argv[])
{
struct manoutput options;
struct mparse *parser;
void *formatter;
const char *defos;
const char *errstr;
int clientfd;
int old_stdin;
int old_stdout;
int old_stderr;
int fds[3];
int state, opt;
enum outt outtype;
defos = NULL;
outtype = OUTT_ASCII;
while ((opt = getopt(argc, argv, "I:T:")) != -1) {
switch (opt) {
case 'I':
if (strncmp(optarg, "os=", 3) == 0)
defos = optarg + 3;
else {
warnx("-I %s: Bad argument", optarg);
usage();
}
break;
case 'T':
if (strcmp(optarg, "ascii") == 0)
outtype = OUTT_ASCII;
else if (strcmp(optarg, "utf8") == 0)
outtype = OUTT_UTF8;
else if (strcmp(optarg, "html") == 0)
outtype = OUTT_HTML;
else {
warnx("-T %s: Bad argument", optarg);
usage();
}
break;
default:
usage();
}
}
if (argc > 0) {
argc -= optind;
argv += optind;
}
if (argc != 1)
usage();
errstr = NULL;
clientfd = strtonum(argv[0], 3, INT_MAX, &errstr);
if (errstr)
errx(1, "file descriptor %s %s", argv[1], errstr);
mchars_alloc();
parser = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1,
MANDOCLEVEL_BADARG, NULL, defos);
memset(&options, 0, sizeof(options));
switch (outtype) {
case OUTT_ASCII:
formatter = ascii_alloc(&options);
break;
case OUTT_UTF8:
formatter = utf8_alloc(&options);
break;
case OUTT_HTML:
options.fragment = 1;
formatter = html_alloc(&options);
break;
}
state = 1; /* work to do */
fflush(stdout);
fflush(stderr);
if ((old_stdin = dup(STDIN_FILENO)) == -1 ||
(old_stdout = dup(STDOUT_FILENO)) == -1 ||
(old_stderr = dup(STDERR_FILENO)) == -1) {
warn("dup");
state = -1; /* error */
}
while (state == 1 && (state = read_fds(clientfd, fds)) == 1) {
if (dup2(fds[0], STDIN_FILENO) == -1 ||
dup2(fds[1], STDOUT_FILENO) == -1 ||
dup2(fds[2], STDERR_FILENO) == -1) {
warn("dup2");
state = -1;
break;
}
close(fds[0]);
close(fds[1]);
close(fds[2]);
process(parser, outtype, formatter);
mparse_reset(parser);
fflush(stdout);
fflush(stderr);
/* Close file descriptors by restoring the old ones. */
if (dup2(old_stderr, STDERR_FILENO) == -1 ||
dup2(old_stdout, STDOUT_FILENO) == -1 ||
dup2(old_stdin, STDIN_FILENO) == -1) {
warn("dup2");
state = -1;
break;
}
}
close(clientfd);
switch (outtype) {
case OUTT_ASCII:
case OUTT_UTF8:
ascii_free(formatter);
break;
case OUTT_HTML:
html_free(formatter);
break;
}
mparse_free(parser);
mchars_free();
return state == -1 ? 1 : 0;
}
static void
process(struct mparse *parser, enum outt outtype, void *formatter)
{
struct roff_man *man;
mparse_readfd(parser, STDIN_FILENO, "<unixfd>");
mparse_result(parser, &man, NULL);
if (man == NULL)
return;
if (man->macroset == MACROSET_MDOC) {
mdoc_validate(man);
switch (outtype) {
case OUTT_ASCII:
case OUTT_UTF8:
terminal_mdoc(formatter, man);
break;
case OUTT_HTML:
html_mdoc(formatter, man);
break;
}
}
if (man->macroset == MACROSET_MAN) {
man_validate(man);
switch (outtype) {
case OUTT_ASCII:
case OUTT_UTF8:
terminal_man(formatter, man);
break;
case OUTT_HTML:
html_man(formatter, man);
break;
}
}
}
void
usage(void)
{
fprintf(stderr, "usage: mandocd [-I os=name] [-T output] socket_fd\n");
exit(1);
}

View File

@ -1,4 +1,4 @@
/* $Id: mandocdb.c,v 1.237 2017/01/11 17:39:53 schwarze Exp $ */
/* $Id: mandocdb.c,v 1.244 2017/02/17 14:45:55 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -162,7 +162,7 @@ static void putmdockey(const struct mpage *,
const struct roff_node *, uint64_t, int);
static int render_string(char **, size_t *);
static void say(const char *, const char *, ...)
__attribute__((__format__ (printf, 2, 3)));
__attribute__((__format__ (__printf__, 2, 3)));
static int set_basedir(const char *, int);
static int treescan(void);
static size_t utf8(unsigned int, char [7]);
@ -589,7 +589,7 @@ treescan(void)
const char *argv[2];
argv[0] = ".";
argv[1] = (char *)NULL;
argv[1] = NULL;
f = fts_open((char * const *)argv, FTS_PHYSICAL | FTS_NOCHDIR,
fts_compare);
@ -871,6 +871,20 @@ filescan(const char *file)
return;
}
/*
* In test mode or when the original name is absolute
* 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)
start += 5;
else
start = buf;
}
/*
* First try to guess our directory structure.
* If we find a separator, try to look for man* or cat*.
@ -1139,6 +1153,7 @@ mpages_merge(struct dba *dba, struct mparse *mp)
if (mlink->dform != FORM_CAT || mlink->fform != FORM_CAT) {
mparse_readfd(mp, fd, mlink->file);
close(fd);
fd = -1;
mparse_result(mp, &man, &sodest);
}
@ -1195,34 +1210,43 @@ mpages_merge(struct dba *dba, struct mparse *mp)
mpage->title = mandoc_strdup(man->meta.title);
} else if (man != NULL && man->macroset == MACROSET_MAN) {
man_validate(man);
mpage->form = FORM_SRC;
mpage->sec = mandoc_strdup(man->meta.msec);
mpage->arch = mandoc_strdup(mlink->arch);
mpage->title = mandoc_strdup(man->meta.title);
} else {
if (*man->meta.msec != '\0' ||
*man->meta.msec != '\0') {
mpage->form = FORM_SRC;
mpage->sec = mandoc_strdup(man->meta.msec);
mpage->arch = mandoc_strdup(mlink->arch);
mpage->title = mandoc_strdup(man->meta.title);
} else
man = NULL;
}
assert(mpage->desc == NULL);
if (man == NULL) {
mpage->form = FORM_CAT;
mpage->sec = mandoc_strdup(mlink->dsec);
mpage->arch = mandoc_strdup(mlink->arch);
mpage->title = mandoc_strdup(mlink->name);
parse_cat(mpage, fd);
} else if (man->macroset == MACROSET_MDOC)
parse_mdoc(mpage, &man->meta, man->first);
else
parse_man(mpage, &man->meta, man->first);
if (mpage->desc == NULL) {
mpage->desc = mandoc_strdup(mlink->name);
if (warnings)
say(mlink->file, "No one-line description, "
"using filename \"%s\"", mlink->name);
}
assert(mpage->desc == NULL);
if (man != NULL && man->macroset == MACROSET_MDOC)
parse_mdoc(mpage, &man->meta, man->first);
else if (man != NULL)
parse_man(mpage, &man->meta, man->first);
else
parse_cat(mpage, fd);
if (mpage->desc == NULL)
mpage->desc = mandoc_strdup(mpage->mlinks->name);
if (warnings && !use_all)
for (mlink = mpage->mlinks; mlink;
mlink = mlink->next)
for (mlink = mpage->mlinks;
mlink != NULL;
mlink = mlink->next) {
putkey(mpage, mlink->name, NAME_FILE);
if (warnings && !use_all)
mlink_check(mpage, mlink);
}
dbadd(dba, mpage);
mlink = mpage->mlinks;
nextpage:
ohash_delete(&strings);
@ -1234,29 +1258,48 @@ static void
parse_cat(struct mpage *mpage, int fd)
{
FILE *stream;
char *line, *p, *title;
struct mlink *mlink;
char *line, *p, *title, *sec;
size_t linesz, plen, titlesz;
ssize_t len;
int offs;
stream = (-1 == fd) ?
fopen(mpage->mlinks->file, "r") :
fdopen(fd, "r");
if (NULL == stream) {
if (-1 != fd)
mlink = mpage->mlinks;
stream = fd == -1 ? fopen(mlink->file, "r") : fdopen(fd, "r");
if (stream == NULL) {
if (fd != -1)
close(fd);
if (warnings)
say(mpage->mlinks->file, "&fopen");
say(mlink->file, "&fopen");
return;
}
line = NULL;
linesz = 0;
/* Parse the section number from the header line. */
while (getline(&line, &linesz, stream) != -1) {
if (*line == '\n')
continue;
if ((sec = strchr(line, '(')) == NULL)
break;
if ((p = strchr(++sec, ')')) == NULL)
break;
free(mpage->sec);
mpage->sec = mandoc_strndup(sec, p - sec);
if (warnings && *mlink->dsec != '\0' &&
strcasecmp(mpage->sec, mlink->dsec))
say(mlink->file,
"Section \"%s\" manual in %s directory",
mpage->sec, mlink->dsec);
break;
}
/* Skip to first blank line. */
while (getline(&line, &linesz, stream) != -1)
if (*line == '\n')
while (line == NULL || *line != '\n')
if (getline(&line, &linesz, stream) == -1)
break;
/*
@ -1302,8 +1345,7 @@ parse_cat(struct mpage *mpage, int fd)
if (NULL == title || '\0' == *title) {
if (warnings)
say(mpage->mlinks->file,
"Cannot find NAME section");
say(mlink->file, "Cannot find NAME section");
fclose(stream);
free(title);
return;
@ -1322,8 +1364,8 @@ parse_cat(struct mpage *mpage, int fd)
/* Skip to next word. */ ;
} else {
if (warnings)
say(mpage->mlinks->file,
"No dash in title line");
say(mlink->file, "No dash in title line, "
"reusing \"%s\" as one-line description", title);
p = title;
}

102
manpath.c
View File

@ -1,6 +1,6 @@
/* $Id: manpath.c,v 1.31 2016/07/19 22:40:33 schwarze Exp $ */
/* $Id: manpath.c,v 1.33 2017/02/10 15:45:28 schwarze Exp $ */
/*
* Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
@ -207,7 +207,7 @@ manconf_file(struct manconf *conf, const char *file)
*manpath_default = '\0';
break;
case 1: /* output */
manconf_output(&conf->output, cp);
manconf_output(&conf->output, cp, 1);
break;
default:
break;
@ -221,15 +221,17 @@ manconf_file(struct manconf *conf, const char *file)
manpath_parseline(&conf->manpath, manpath_default, 0);
}
void
manconf_output(struct manoutput *conf, const char *cp)
int
manconf_output(struct manoutput *conf, const char *cp, int fromfile)
{
const char *const toks[] = {
"includes", "man", "paper", "style",
"indent", "width", "fragment", "mdoc"
"indent", "width", "fragment", "mdoc", "noval"
};
size_t len, tok;
const char *errstr;
char *oldval;
size_t len, tok;
for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {
len = strlen(toks[tok]);
@ -244,41 +246,81 @@ manconf_output(struct manoutput *conf, const char *cp)
}
}
if (tok < 6 && *cp == '\0')
return;
if (tok < 6 && *cp == '\0') {
warnx("-O %s=?: Missing argument value", toks[tok]);
return -1;
}
if ((tok == 6 || tok == 7) && *cp != '\0') {
warnx("-O %s: Does not take a value: %s", toks[tok], cp);
return -1;
}
switch (tok) {
case 0:
if (conf->includes == NULL)
conf->includes = mandoc_strdup(cp);
break;
if (conf->includes != NULL) {
oldval = mandoc_strdup(conf->includes);
break;
}
conf->includes = mandoc_strdup(cp);
return 0;
case 1:
if (conf->man == NULL)
conf->man = mandoc_strdup(cp);
break;
if (conf->man != NULL) {
oldval = mandoc_strdup(conf->man);
break;
}
conf->man = mandoc_strdup(cp);
return 0;
case 2:
if (conf->paper == NULL)
conf->paper = mandoc_strdup(cp);
break;
if (conf->paper != NULL) {
oldval = mandoc_strdup(conf->paper);
break;
}
conf->paper = mandoc_strdup(cp);
return 0;
case 3:
if (conf->style == NULL)
conf->style = mandoc_strdup(cp);
break;
if (conf->style != NULL) {
oldval = mandoc_strdup(conf->style);
break;
}
conf->style = mandoc_strdup(cp);
return 0;
case 4:
if (conf->indent == 0)
conf->indent = strtonum(cp, 0, 1000, NULL);
break;
if (conf->indent) {
mandoc_asprintf(&oldval, "%zu", conf->indent);
break;
}
conf->indent = strtonum(cp, 0, 1000, &errstr);
if (errstr == NULL)
return 0;
warnx("-O indent=%s is %s", cp, errstr);
return -1;
case 5:
if (conf->width == 0)
conf->width = strtonum(cp, 58, 1000, NULL);
break;
if (conf->width) {
mandoc_asprintf(&oldval, "%zu", conf->width);
break;
}
conf->width = strtonum(cp, 58, 1000, &errstr);
if (errstr == NULL)
return 0;
warnx("-O width=%s is %s", cp, errstr);
return -1;
case 6:
conf->fragment = 1;
break;
return 0;
case 7:
conf->mdoc = 1;
break;
return 0;
case 8:
conf->noval = 1;
return 0;
default:
break;
if (fromfile)
warnx("-O %s: Bad argument", cp);
return -1;
}
if (fromfile == 0)
warnx("-O %s=%s: Option already set to %s",
toks[tok], cp, oldval);
free(oldval);
return -1;
}

14
mdoc.7
View File

@ -1,4 +1,4 @@
.\" $Id: mdoc.7,v 1.260 2017/01/09 14:10:53 schwarze Exp $
.\" $Id: mdoc.7,v 1.262 2017/02/16 14:38:12 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010, 2011, 2013-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: January 9 2017 $
.Dd $Mdocdate: February 16 2017 $
.Dt MDOC 7
.Os
.Sh NAME
@ -974,10 +974,8 @@ argument.
A columnated list.
The
.Fl width
argument has no effect; instead, each argument specifies the width
of one column, using either the scaling width syntax described in
.Xr roff 7
or the string length of the argument.
argument has no effect; instead, the string length of each argument
specifies the width of one column.
If the first line of the body of a
.Fl column
list is not an
@ -3064,6 +3062,8 @@ For many macros, when the leading arguments are opening delimiters,
these delimiters are put before the macro scope,
and when the trailing arguments are closing delimiters,
these delimiters are put after the macro scope.
Spacing is suppressed after opening delimiters
and before closing delimiters.
For example,
.Pp
.D1 Pf \. \&Aq "( [ word ] ) ."
@ -3120,7 +3120,7 @@ renders as:
.D1 Fl a ( b | c \*(Ba d ) e
.Pp
This applies to both opening and closing delimiters,
and also to the middle delimiter:
and also to the middle delimiter, which does not suppress spacing:
.Pp
.Bl -tag -width Ds -offset indent -compact
.It \&|

24
mdoc.c
View File

@ -1,7 +1,7 @@
/* $Id: mdoc.c,v 1.258 2017/01/10 13:47:00 schwarze Exp $ */
/* $Id: mdoc.c,v 1.260 2017/02/16 03:00:23 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2016 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -136,7 +136,7 @@ mdoc_tail_alloc(struct roff_man *mdoc, int line, int pos, int tok)
struct roff_node *
mdoc_endbody_alloc(struct roff_man *mdoc, int line, int pos, int tok,
struct roff_node *body, enum mdoc_endbody end)
struct roff_node *body)
{
struct roff_node *p;
@ -145,7 +145,7 @@ mdoc_endbody_alloc(struct roff_man *mdoc, int line, int pos, int tok,
p = roff_node_alloc(mdoc, line, pos, ROFFT_BODY, tok);
p->body = body;
p->norm = body->norm;
p->end = end;
p->end = ENDBODY_SPACE;
roff_node_append(mdoc, p);
mdoc->next = ROFF_NEXT_SIBLING;
return p;
@ -312,6 +312,22 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
if (mandoc_eos(buf+offs, (size_t)(end-buf-offs)))
mdoc->last->flags |= NODE_EOS;
for (c = buf + offs; c != NULL; c = strchr(c + 1, '.')) {
if (c - buf < offs + 2)
continue;
if (end - c < 4)
break;
if (isalpha((unsigned char)c[-2]) &&
isalpha((unsigned char)c[-1]) &&
c[1] == ' ' &&
isupper((unsigned char)(c[2] == ' ' ? c[3] : c[2])) &&
(c[-2] != 'n' || c[-1] != 'c') &&
(c[-2] != 'v' || c[-1] != 's'))
mandoc_msg(MANDOCERR_EOS, mdoc->parse,
line, (int)(c - buf), NULL);
}
return 1;
}

View File

@ -1,4 +1,4 @@
/* $Id: mdoc_html.c,v 1.260 2017/01/21 02:09:51 schwarze Exp $ */
/* $Id: mdoc_html.c,v 1.271 2017/02/16 03:00:23 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -110,6 +110,7 @@ static int mdoc_skip_pre(MDOC_ARGS);
static int mdoc_sm_pre(MDOC_ARGS);
static int mdoc_sp_pre(MDOC_ARGS);
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_va_pre(MDOC_ARGS);
@ -155,7 +156,7 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = {
{mdoc_ft_pre, NULL}, /* Ot */
{mdoc_pa_pre, NULL}, /* Pa */
{mdoc_ex_pre, NULL}, /* Rv */
{NULL, NULL}, /* St */
{mdoc_st_pre, NULL}, /* St */
{mdoc_va_pre, NULL}, /* Va */
{mdoc_vt_pre, NULL}, /* Vt */
{mdoc_xr_pre, NULL}, /* Xr */
@ -173,7 +174,7 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = {
{NULL, NULL}, /* Ac */
{mdoc_quote_pre, mdoc_quote_post}, /* Ao */
{mdoc_quote_pre, mdoc_quote_post}, /* Aq */
{NULL, NULL}, /* At */
{mdoc_xx_pre, NULL}, /* At */
{NULL, NULL}, /* Bc */
{mdoc_bf_pre, NULL}, /* Bf */
{mdoc_quote_pre, mdoc_quote_post}, /* Bo */
@ -349,7 +350,7 @@ print_mdoc_node(MDOC_ARGS)
return;
child = 1;
t = h->tags.head;
t = h->tag;
n->flags &= ~NODE_ENDED;
switch (n->type) {
@ -389,7 +390,7 @@ print_mdoc_node(MDOC_ARGS)
*/
if (h->tblt != NULL) {
print_tblclose(h);
t = h->tags.head;
t = h->tag;
}
assert(h->tblt == NULL);
if (mdocs[n->tok].pre && (n->end == ENDBODY_NOT || n->child))
@ -416,8 +417,6 @@ print_mdoc_node(MDOC_ARGS)
(*mdocs[n->tok].post)(meta, n, h);
if (n->end != ENDBODY_NOT)
n->body->flags |= NODE_ENDED;
if (n->end == ENDBODY_NOSPACE)
h->flags |= HTML_NOSPACE;
break;
}
}
@ -428,7 +427,6 @@ mdoc_root_post(MDOC_ARGS)
struct tag *t, *tt;
t = print_otag(h, TAG_TABLE, "c", "foot");
print_otag(h, TAG_TBODY, "");
tt = print_otag(h, TAG_TR, "");
print_otag(h, TAG_TD, "c", "foot-date");
@ -459,7 +457,6 @@ mdoc_root_pre(MDOC_ARGS)
meta->title, meta->msec);
t = print_otag(h, TAG_TABLE, "c", "head");
print_otag(h, TAG_TBODY, "");
tt = print_otag(h, TAG_TR, "");
print_otag(h, TAG_TD, "c", "head-ltitle");
@ -507,22 +504,18 @@ mdoc_sh_pre(MDOC_ARGS)
char *id;
switch (n->type) {
case ROFFT_BLOCK:
return 1;
case ROFFT_HEAD:
id = make_id(n);
print_otag(h, TAG_H1, "ci", "Sh", id);
free(id);
break;
case ROFFT_BODY:
if (n->sec == SEC_AUTHORS)
h->flags &= ~(HTML_SPLIT|HTML_NOSPLIT);
return 1;
break;
default:
break;
}
if ((id = make_id(n)) != NULL) {
print_otag(h, TAG_H1, "ci", "Sh", id);
free(id);
} else
print_otag(h, TAG_H1, "c", "Sh");
return 1;
}
@ -534,12 +527,9 @@ mdoc_ss_pre(MDOC_ARGS)
if (n->type != ROFFT_HEAD)
return 1;
if ((id = make_id(n)) != NULL) {
print_otag(h, TAG_H2, "ci", "Ss", id);
free(id);
} else
print_otag(h, TAG_H2, "c", "Ss");
id = make_id(n);
print_otag(h, TAG_H2, "ci", "Ss", id);
free(id);
return 1;
}
@ -581,6 +571,7 @@ mdoc_nd_pre(MDOC_ARGS)
static int
mdoc_nm_pre(MDOC_ARGS)
{
struct tag *t;
int len;
switch (n->type) {
@ -589,8 +580,6 @@ mdoc_nm_pre(MDOC_ARGS)
/* FALLTHROUGH */
case ROFFT_ELEM:
print_otag(h, TAG_B, "c", "Nm");
if (n->child == NULL && meta->name != NULL)
print_text(h, meta->name);
return 1;
case ROFFT_BODY:
print_otag(h, TAG_TD, "");
@ -609,9 +598,10 @@ mdoc_nm_pre(MDOC_ARGS)
if (len == 0 && meta->name != NULL)
len = html_strlen(meta->name);
t = print_otag(h, TAG_COLGROUP, "");
print_otag(h, TAG_COL, "shw", len);
print_otag(h, TAG_COL, "");
print_otag(h, TAG_TBODY, "");
print_tagq(h, t);
print_otag(h, TAG_TR, "");
return 1;
}
@ -656,7 +646,7 @@ mdoc_ns_pre(MDOC_ARGS)
static int
mdoc_ar_pre(MDOC_ARGS)
{
print_otag(h, TAG_I, "c", "Ar");
print_otag(h, TAG_VAR, "c", "Ar");
return 1;
}
@ -671,6 +661,7 @@ static int
mdoc_it_pre(MDOC_ARGS)
{
const struct roff_node *bl;
struct tag *t;
const char *cattr;
enum mdoc_list type;
@ -738,7 +729,6 @@ mdoc_it_pre(MDOC_ARGS)
case LIST_hang:
case LIST_inset:
case LIST_ohang:
case LIST_tag:
switch (n->type) {
case ROFFT_HEAD:
if (bl->norm->Bl.comp)
@ -749,11 +739,37 @@ mdoc_it_pre(MDOC_ARGS)
print_otag(h, TAG_B, "c", cattr);
break;
case ROFFT_BODY:
if (bl->norm->Bl.width == NULL)
print_otag(h, TAG_DD, "cswl", cattr,
bl->norm->Bl.width);
break;
default:
break;
}
break;
case LIST_tag:
switch (n->type) {
case ROFFT_HEAD:
if (h->style != NULL && !bl->norm->Bl.comp &&
(n->parent->prev == NULL ||
n->parent->prev->body->child != NULL)) {
t = print_otag(h, TAG_DT, "csWl",
cattr, bl->norm->Bl.width);
print_text(h, "\\ ");
print_tagq(h, t);
t = print_otag(h, TAG_DD, "c", cattr);
print_text(h, "\\ ");
print_tagq(h, t);
}
print_otag(h, TAG_DT, "csWl", cattr,
bl->norm->Bl.width);
break;
case ROFFT_BODY:
if (n->child == NULL) {
print_otag(h, TAG_DD, "css?", cattr,
"width", "auto");
print_text(h, "\\ ");
} else
print_otag(h, TAG_DD, "c", cattr);
else
print_otag(h, TAG_DD, "cswl", cattr,
bl->norm->Bl.width);
break;
default:
break;
@ -782,18 +798,20 @@ mdoc_it_pre(MDOC_ARGS)
static int
mdoc_bl_pre(MDOC_ARGS)
{
struct tag *t;
struct mdoc_bl *bl;
const char *cattr;
int i;
size_t i;
enum htmltag elemtype;
if (n->type == ROFFT_BODY) {
if (LIST_column == n->norm->Bl.type)
print_otag(h, TAG_TBODY, "");
return 1;
}
bl = &n->norm->Bl;
if (n->type == ROFFT_HEAD) {
if (LIST_column != n->norm->Bl.type)
switch (n->type) {
case ROFFT_BODY:
return 1;
case ROFFT_HEAD:
if (bl->type != LIST_column || bl->ncols == 0)
return 0;
/*
@ -803,14 +821,18 @@ mdoc_bl_pre(MDOC_ARGS)
* screen and we want to preserve that behaviour.
*/
for (i = 0; i < (int)n->norm->Bl.ncols - 1; i++)
print_otag(h, TAG_COL, "sww", n->norm->Bl.cols[i]);
print_otag(h, TAG_COL, "swW", n->norm->Bl.cols[i]);
t = print_otag(h, TAG_COLGROUP, "");
for (i = 0; i < bl->ncols - 1; i++)
print_otag(h, TAG_COL, "sww", bl->cols[i]);
print_otag(h, TAG_COL, "swW", bl->cols[i]);
print_tagq(h, t);
return 0;
default:
break;
}
switch (n->norm->Bl.type) {
switch (bl->type) {
case LIST_bullet:
elemtype = TAG_UL;
cattr = "Bl-bullet";
@ -845,9 +867,11 @@ mdoc_bl_pre(MDOC_ARGS)
cattr = "Bl-ohang";
break;
case LIST_tag:
elemtype = TAG_DL;
cattr = "Bl-tag";
break;
if (bl->offs)
print_otag(h, TAG_DIV, "cswl", cattr, bl->offs);
print_otag(h, TAG_DL, "cswl", cattr, bl->width);
return 1;
case LIST_column:
elemtype = TAG_TABLE;
cattr = "Bl-column";
@ -855,12 +879,7 @@ mdoc_bl_pre(MDOC_ARGS)
default:
abort();
}
if (n->norm->Bl.offs)
print_otag(h, elemtype, "cswl", cattr, n->norm->Bl.offs);
else
print_otag(h, elemtype, "c", cattr);
print_otag(h, elemtype, "cswl", cattr, bl->offs);
return 1;
}
@ -872,6 +891,13 @@ mdoc_ex_pre(MDOC_ARGS)
return 1;
}
static int
mdoc_st_pre(MDOC_ARGS)
{
print_otag(h, TAG_SPAN, "c", "St");
return 1;
}
static int
mdoc_em_pre(MDOC_ARGS)
{
@ -898,12 +924,9 @@ mdoc_sx_pre(MDOC_ARGS)
{
char *id;
if ((id = make_id(n)) != NULL) {
print_otag(h, TAG_A, "chR", "Sx", id);
free(id);
} else
print_otag(h, TAG_A, "c", "Sx");
id = make_id(n);
print_otag(h, TAG_A, "chR", "Sx", id);
free(id);
return 1;
}
@ -1069,12 +1092,12 @@ mdoc_fa_pre(MDOC_ARGS)
struct tag *t;
if (n->parent->tok != MDOC_Fo) {
print_otag(h, TAG_I, "c", "Fa");
print_otag(h, TAG_VAR, "c", "Fa");
return 1;
}
for (nn = n->child; nn; nn = nn->next) {
t = print_otag(h, TAG_I, "c", "Fa");
t = print_otag(h, TAG_VAR, "c", "Fa");
print_text(h, nn->string);
print_tagq(h, t);
if (nn->next) {
@ -1153,7 +1176,7 @@ mdoc_vt_pre(MDOC_ARGS)
} else if (n->type == ROFFT_HEAD)
return 0;
print_otag(h, TAG_I, "c", "Vt");
print_otag(h, TAG_VAR, "c", "Vt");
return 1;
}
@ -1161,7 +1184,7 @@ static int
mdoc_ft_pre(MDOC_ARGS)
{
synopsis_pre(h, n);
print_otag(h, TAG_I, "c", "Ft");
print_otag(h, TAG_VAR, "c", "Ft");
return 1;
}
@ -1182,7 +1205,7 @@ mdoc_fn_pre(MDOC_ARGS)
ep = strchr(sp, ' ');
if (NULL != ep) {
t = print_otag(h, TAG_I, "c", "Ft");
t = print_otag(h, TAG_VAR, "c", "Ft");
while (ep) {
sz = MIN((int)(ep - sp), BUFSIZ - 1);
@ -1208,10 +1231,10 @@ mdoc_fn_pre(MDOC_ARGS)
for (n = n->child->next; n; n = n->next) {
if (NODE_SYNPRETTY & n->flags)
t = print_otag(h, TAG_I, "css?", "Fa",
t = print_otag(h, TAG_VAR, "css?", "Fa",
"white-space", "nowrap");
else
t = print_otag(h, TAG_I, "c", "Fa");
t = print_otag(h, TAG_VAR, "c", "Fa");
print_text(h, n->string);
print_tagq(h, t);
if (n->next) {
@ -1419,7 +1442,7 @@ mdoc_ic_pre(MDOC_ARGS)
static int
mdoc_va_pre(MDOC_ARGS)
{
print_otag(h, TAG_I, "c", "Va");
print_otag(h, TAG_VAR, "c", "Va");
return 1;
}
@ -1450,7 +1473,7 @@ mdoc_bf_pre(MDOC_ARGS)
else if (FONT_Li == n->norm->Bf.font)
cattr = "Li";
else
cattr = "none";
cattr = "No";
/*
* We want this to be inline-formatted, but needs to be div to
@ -1493,7 +1516,7 @@ mdoc_rs_pre(MDOC_ARGS)
if (n->prev && SEC_SEE_ALSO == n->sec)
print_paragraph(h);
print_otag(h, TAG_SPAN, "c", "Rs");
print_otag(h, TAG_CITE, "c", "Rs");
return 1;
}

View File

@ -1,7 +1,7 @@
/* $Id: mdoc_macro.c,v 1.210 2017/01/10 13:47:00 schwarze Exp $ */
/* $Id: mdoc_macro.c,v 1.217 2017/02/16 09:47:31 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2016 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -50,6 +50,8 @@ static int find_pending(struct roff_man *, int, int, int,
struct roff_node *);
static int lookup(struct roff_man *, int, int, int, const char *);
static int macro_or_word(MACRO_PROT_ARGS, int);
static void break_intermediate(struct roff_node *,
struct roff_node *);
static int parse_rest(struct roff_man *, int, int, int *, char *);
static int rew_alt(int);
static void rew_elem(struct roff_man *, int);
@ -376,6 +378,20 @@ rew_elem(struct roff_man *mdoc, int tok)
rew_last(mdoc, n);
}
static void
break_intermediate(struct roff_node *n, struct roff_node *breaker)
{
if (n != breaker &&
n->type != ROFFT_BLOCK && n->type != ROFFT_HEAD &&
(n->type != ROFFT_BODY || n->end != ENDBODY_NOT))
n = n->parent;
while (n != breaker) {
if ( ! (n->flags & NODE_VALID))
n->flags |= NODE_BROKEN;
n = n->parent;
}
}
/*
* If there is an open sub-block of the target requiring
* explicit close-out, postpone closing out the target until
@ -388,26 +404,26 @@ find_pending(struct roff_man *mdoc, int tok, int line, int ppos,
struct roff_node *n;
int irc;
if (target->flags & NODE_VALID)
return 0;
irc = 0;
for (n = mdoc->last; n != NULL && n != target; n = n->parent) {
if (n->flags & NODE_ENDED) {
if ( ! (n->flags & NODE_VALID))
n->flags |= NODE_BROKEN;
if (n->flags & NODE_ENDED)
continue;
}
if (n->type == ROFFT_BLOCK &&
mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {
irc = 1;
n->flags = NODE_BROKEN;
break_intermediate(mdoc->last, target);
if (target->type == ROFFT_HEAD)
target->flags = NODE_ENDED;
target->flags |= NODE_ENDED;
else if ( ! (target->flags & NODE_ENDED)) {
mandoc_vmsg(MANDOCERR_BLK_NEST,
mdoc->parse, line, ppos,
"%s breaks %s", mdoc_macronames[tok],
mdoc_macronames[n->tok]);
mdoc_endbody_alloc(mdoc, line, ppos,
tok, target, ENDBODY_NOSPACE);
tok, target);
}
}
}
@ -568,30 +584,34 @@ blk_exp_close(MACRO_PROT_ARGS)
endbody = itblk = later = NULL;
for (n = mdoc->last; n; n = n->parent) {
if (n->flags & NODE_ENDED) {
if ( ! (n->flags & NODE_VALID))
n->flags |= NODE_BROKEN;
if (n->flags & NODE_ENDED)
continue;
}
/*
* Mismatching end macros can never break anything,
* SYNOPSIS name blocks can never be broken,
* Mismatching end macros can never break anything
* and we only care about the breaking of BLOCKs.
*/
if (body == NULL ||
n->tok == MDOC_Nm ||
n->type != ROFFT_BLOCK)
if (body == NULL || n->type != ROFFT_BLOCK)
continue;
/*
* SYNOPSIS name blocks can not be broken themselves,
* but they do get broken together with a broken child.
*/
if (n->tok == MDOC_Nm) {
if (later != NULL)
n->flags |= NODE_BROKEN | NODE_ENDED;
continue;
}
if (n->tok == MDOC_It) {
itblk = n;
continue;
}
if (atok == n->tok) {
assert(body);
/*
* Found the start of our own block.
@ -617,7 +637,7 @@ blk_exp_close(MACRO_PROT_ARGS)
mdoc_macronames[later->tok]);
endbody = mdoc_endbody_alloc(mdoc, line, ppos,
atok, body, ENDBODY_SPACE);
atok, body);
if (tok == MDOC_El)
itblk->flags |= NODE_ENDED | NODE_BROKEN;
@ -633,15 +653,22 @@ blk_exp_close(MACRO_PROT_ARGS)
break;
}
/* Explicit blocks close out description lines. */
/*
* Explicit blocks close out description lines, but
* even those can get broken together with a child.
*/
if (n->tok == MDOC_Nd) {
rew_last(mdoc, n);
if (later != NULL)
n->flags |= NODE_BROKEN | NODE_ENDED;
else
rew_last(mdoc, n);
continue;
}
/* Breaking an open sub block. */
break_intermediate(mdoc->last, body);
n->flags |= NODE_BROKEN;
if (later == NULL)
later = n;
@ -706,15 +733,14 @@ blk_exp_close(MACRO_PROT_ARGS)
}
if (n != NULL) {
pending = 0;
if (ntok != TOKEN_NONE && n->flags & NODE_BROKEN) {
target = n;
do
target = target->parent;
while ( ! (target->flags & NODE_ENDED));
pending = find_pending(mdoc, ntok, line, ppos,
target);
} else
pending = 0;
pending = find_pending(mdoc, ntok, line, ppos, target);
}
if ( ! pending)
rew_pending(mdoc, n);
}
@ -987,7 +1013,7 @@ blk_full(MACRO_PROT_ARGS)
/* Close out prior implicit scopes. */
rew_last(mdoc, n);
rew_pending(mdoc, n);
}
/* Skip items outside lists. */

View File

@ -1,4 +1,4 @@
/* $Id: mdoc_man.c,v 1.101 2017/01/11 17:39:53 schwarze Exp $ */
/* $Id: mdoc_man.c,v 1.104 2017/02/17 19:15:41 schwarze Exp $ */
/*
* Copyright (c) 2011-2017 Ingo Schwarze <schwarze@openbsd.org>
*
@ -639,9 +639,6 @@ print_node(DECL_ARGS)
if (ENDBODY_NOT != n->end)
n->body->flags |= NODE_ENDED;
if (ENDBODY_NOSPACE == n->end)
outflags &= ~(MMAN_spc | MMAN_nl);
}
static int
@ -720,8 +717,7 @@ pre__t(DECL_ARGS)
if (n->parent && MDOC_Rs == n->parent->tok &&
n->parent->norm->Rs.quote_T) {
print_word("");
putchar('\"');
print_word("\\(lq");
outflags &= ~MMAN_spc;
} else
font_push('I');
@ -735,8 +731,7 @@ post__t(DECL_ARGS)
if (n->parent && MDOC_Rs == n->parent->tok &&
n->parent->norm->Rs.quote_T) {
outflags &= ~MMAN_spc;
print_word("");
putchar('\"');
print_word("\\(rq");
} else
font_pop();
post_percent(meta, n);
@ -1518,7 +1513,7 @@ pre_nm(DECL_ARGS)
}
if (n->type != ROFFT_ELEM && n->type != ROFFT_HEAD)
return 1;
name = n->child ? n->child->string : meta->name;
name = n->child == NULL ? NULL : n->child->string;
if (NULL == name)
return 0;
if (n->type == ROFFT_HEAD) {
@ -1529,8 +1524,6 @@ pre_nm(DECL_ARGS)
outflags |= MMAN_nl;
}
font_push('B');
if (NULL == n->child)
print_word(meta->name);
return 1;
}
@ -1544,7 +1537,7 @@ post_nm(DECL_ARGS)
break;
case ROFFT_HEAD:
case ROFFT_ELEM:
if (n->child != NULL || meta->name != NULL)
if (n->child != NULL && n->child->string != NULL)
font_pop();
break;
default:

View File

@ -1,4 +1,4 @@
/* $Id: mdoc_term.c,v 1.341 2017/01/11 17:39:53 schwarze Exp $ */
/* $Id: mdoc_term.c,v 1.346 2017/02/17 19:15:41 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -258,6 +258,7 @@ terminal_mdoc(void *arg, const struct roff_man *mdoc)
{
struct roff_node *n;
struct termp *p;
size_t save_defindent;
p = (struct termp *)arg;
p->overstep = 0;
@ -278,6 +279,7 @@ terminal_mdoc(void *arg, const struct roff_man *mdoc)
n = n->next;
}
} else {
save_defindent = p->defindent;
if (p->defindent == 0)
p->defindent = 5;
term_begin(p, print_mdoc_head, print_mdoc_foot,
@ -290,6 +292,7 @@ terminal_mdoc(void *arg, const struct roff_man *mdoc)
print_mdoc_nodelist(p, NULL, &mdoc->meta, n);
}
term_end(p);
p->defindent = save_defindent;
}
}
@ -392,14 +395,6 @@ print_mdoc_node(DECL_ARGS)
*/
if (ENDBODY_NOT != n->end)
n->body->flags |= NODE_ENDED;
/*
* End of line terminating an implicit block
* while an explicit block is still open.
* Continue the explicit block without spacing.
*/
if (ENDBODY_NOSPACE == n->end)
p->flags |= TERMP_NOSPACE;
break;
}
@ -611,6 +606,7 @@ termp_ll_pre(DECL_ARGS)
static int
termp_it_pre(DECL_ARGS)
{
struct roffsu su;
char buf[24];
const struct roff_node *bl, *nn;
size_t ncols, dcol;
@ -688,9 +684,12 @@ termp_it_pre(DECL_ARGS)
for (i = 0, nn = n->prev;
nn->prev && i < (int)ncols;
nn = nn->prev, i++)
offset += dcol + a2width(p,
bl->norm->Bl.cols[i]);
nn = nn->prev, i++) {
SCALE_HS_INIT(&su,
term_strlen(p, bl->norm->Bl.cols[i]));
su.scale /= term_strlen(p, "0");
offset += term_hspan(p, &su) / 24 + dcol;
}
/*
* When exceeding the declared number of columns, leave
@ -705,7 +704,9 @@ termp_it_pre(DECL_ARGS)
* Use the declared column widths, extended as explained
* in the preceding paragraph.
*/
width = a2width(p, bl->norm->Bl.cols[i]) + dcol;
SCALE_HS_INIT(&su, term_strlen(p, bl->norm->Bl.cols[i]));
su.scale /= term_strlen(p, "0");
width = term_hspan(p, &su) / 24 + dcol;
break;
default:
if (NULL == bl->norm->Bl.width)
@ -993,7 +994,7 @@ termp_nm_pre(DECL_ARGS)
return 1;
}
if (NULL == n->child && NULL == meta->name)
if (n->child == NULL)
return 0;
if (n->type == ROFFT_HEAD)
@ -1017,8 +1018,6 @@ termp_nm_pre(DECL_ARGS)
}
term_fontpush(p, TERMFONT_BOLD);
if (NULL == n->child)
term_word(p, meta->name);
return 1;
}
@ -1715,6 +1714,8 @@ termp_quote_pre(DECL_ARGS)
case MDOC_Bq:
term_word(p, "[");
break;
case MDOC__T:
/* FALLTHROUGH */
case MDOC_Do:
case MDOC_Dq:
term_word(p, "\\(Lq");
@ -1729,7 +1730,6 @@ termp_quote_pre(DECL_ARGS)
case MDOC_Pq:
term_word(p, "(");
break;
case MDOC__T:
case MDOC_Qo:
case MDOC_Qq:
term_word(p, "\"");
@ -1772,6 +1772,8 @@ termp_quote_post(DECL_ARGS)
case MDOC_Bq:
term_word(p, "]");
break;
case MDOC__T:
/* FALLTHROUGH */
case MDOC_Do:
case MDOC_Dq:
term_word(p, "\\(Rq");
@ -1788,7 +1790,6 @@ termp_quote_post(DECL_ARGS)
case MDOC_Pq:
term_word(p, ")");
break;
case MDOC__T:
case MDOC_Qo:
case MDOC_Qq:
term_word(p, "\"");

View File

@ -1,4 +1,4 @@
/* $Id: mdoc_validate.c,v 1.317 2017/01/11 17:39:53 schwarze Exp $ */
/* $Id: mdoc_validate.c,v 1.318 2017/02/06 03:44:58 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -1013,6 +1013,16 @@ post_nm(POST_ARGS)
(mdoc->lastsec == SEC_NAME && n->child == NULL))
mandoc_msg(MANDOCERR_NM_NONAME, mdoc->parse,
n->line, n->pos, "Nm");
if ((n->type != ROFFT_ELEM && n->type != ROFFT_HEAD) ||
(n->child != NULL && n->child->type == ROFFT_TEXT) ||
mdoc->meta.name == NULL)
return;
mdoc->next = ROFF_NEXT_CHILD;
roff_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name);
mdoc->last->flags |= NODE_NOSRC;
mdoc->last = n;
}
static void

View File

@ -1,4 +1,4 @@
/* $Id: preconv.c,v 1.15 2015/10/06 18:32:19 schwarze Exp $ */
/* $Id: preconv.c,v 1.16 2017/02/18 13:43:52 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@ -26,14 +26,14 @@
#include "libmandoc.h"
int
preconv_encode(struct buf *ib, size_t *ii, struct buf *ob, size_t *oi,
preconv_encode(const struct buf *ib, size_t *ii, struct buf *ob, size_t *oi,
int *filenc)
{
unsigned char *cu;
int nby;
unsigned int accum;
const unsigned char *cu;
int nby;
unsigned int accum;
cu = (unsigned char *)ib->buf + *ii;
cu = (const unsigned char *)ib->buf + *ii;
assert(*cu & 0x80);
if ( ! (*filenc & MPARSE_UTF8))
@ -90,7 +90,7 @@ preconv_encode(struct buf *ib, size_t *ii, struct buf *ob, size_t *oi,
assert(accum < 0xd800 || accum > 0xdfff);
*oi += snprintf(ob->buf + *oi, 11, "\\[u%.4X]", accum);
*ii = (char *)cu - ib->buf;
*ii = (const char *)cu - ib->buf;
*filenc &= ~MPARSE_LATIN1;
return 1;

20
read.c
View File

@ -1,4 +1,4 @@
/* $Id: read.c,v 1.157 2017/01/09 01:37:03 schwarze Exp $ */
/* $Id: read.c,v 1.161 2017/02/18 17:29:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
@ -30,7 +30,6 @@
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -48,8 +47,8 @@
#define REPARSE_LIMIT 1000
struct mparse {
struct roff_man *man; /* man parser */
struct roff *roff; /* roff parser (!NULL) */
struct roff_man *man; /* man parser */
char *sodest; /* filename pointed to by .so */
const char *file; /* filename of current input file */
struct buf *primary; /* buffer currently being parsed */
@ -177,6 +176,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"blank line in fill mode, using .sp",
"tab in filled text",
"whitespace at end of input line",
"new sentence, new line",
"bad comment style",
"invalid escape sequence",
"undefined string, using \"\"",
@ -602,12 +602,11 @@ static int
read_whole_file(struct mparse *curp, const char *file, int fd,
struct buf *fb, int *with_mmap)
{
struct stat st;
gzFile gz;
size_t off;
ssize_t ssz;
struct stat st;
if (fstat(fd, &st) == -1)
err((int)MANDOCLEVEL_SYSERR, "%s", file);
@ -829,13 +828,15 @@ mparse_reset(struct mparse *curp)
{
roff_reset(curp->roff);
roff_man_reset(curp->man);
free(curp->sodest);
curp->sodest = NULL;
if (curp->secondary)
curp->secondary->sz = 0;
curp->file_status = MANDOCLEVEL_OK;
free(curp->sodest);
curp->sodest = NULL;
curp->gzip = 0;
}
void
@ -843,8 +844,7 @@ mparse_free(struct mparse *curp)
{
roff_man_free(curp->man);
if (curp->roff)
roff_free(curp->roff);
roff_free(curp->roff);
if (curp->secondary)
free(curp->secondary->buf);

16
roff.c
View File

@ -1,4 +1,4 @@
/* $Id: roff.c,v 1.288 2017/01/12 18:02:20 schwarze Exp $ */
/* $Id: roff.c,v 1.289 2017/02/17 03:03:03 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -1226,15 +1226,22 @@ deroff(char **dest, const struct roff_node *n)
/* Skip leading whitespace. */
for (cp = n->string; *cp != '\0'; cp++) {
if (cp[0] == '\\' && strchr(" %&0^|~", cp[1]) != NULL)
if (cp[0] == '\\' && cp[1] != '\0' &&
strchr(" %&0^|~", cp[1]) != NULL)
cp++;
else if ( ! isspace((unsigned char)*cp))
break;
}
/* Skip trailing backslash. */
sz = strlen(cp);
if (cp[sz - 1] == '\\')
sz--;
/* Skip trailing whitespace. */
for (sz = strlen(cp); sz; sz--)
for (; sz; sz--)
if ( ! isspace((unsigned char)cp[sz-1]))
break;
@ -3358,7 +3365,8 @@ roff_strdup(const struct roff *r, const char *p)
ssz = 0;
while ('\0' != *p) {
if ('\\' != *p && r->xtab && r->xtab[(int)*p].p) {
assert((unsigned int)*p < 128);
if ('\\' != *p && r->xtab && r->xtab[(unsigned int)*p].p) {
sz = r->xtab[(int)*p].sz;
res = mandoc_realloc(res, ssz + sz + 1);
memcpy(res + ssz, r->xtab[(int)*p].p, sz);

5
roff.h
View File

@ -1,4 +1,4 @@
/* $Id: roff.h,v 1.39 2017/01/10 13:47:00 schwarze Exp $ */
/* $Id: roff.h,v 1.40 2017/02/16 03:00:23 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -75,8 +75,7 @@ enum roff_next {
*/
enum mdoc_endbody {
ENDBODY_NOT = 0,
ENDBODY_SPACE, /* Is broken: append a space. */
ENDBODY_NOSPACE /* Is broken: don't append a space. */
ENDBODY_SPACE /* Is broken: append a space. */
};
struct roff_node {

4
tag.c
View File

@ -1,4 +1,4 @@
/* $Id: tag.c,v 1.17 2017/01/09 17:49:58 schwarze Exp $ */
/* $Id: tag.c,v 1.18 2017/02/17 14:31:52 schwarze Exp $ */
/*
* Copyright (c) 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
*
@ -38,7 +38,7 @@ struct tag_entry {
char s[];
};
static void tag_signal(int) __attribute__((noreturn));
static void tag_signal(int) __attribute__((__noreturn__));
static struct ohash tag_data;
static struct tag_files tag_files;

View File

@ -1,4 +1,4 @@
/* $Id: tbl_html.c,v 1.19 2017/01/17 01:47:51 schwarze Exp $ */
/* $Id: tbl_html.c,v 1.20 2017/02/05 18:15:39 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -50,6 +50,7 @@ html_tbl_strlen(const char *p, void *arg)
static void
html_tblopen(struct html *h, const struct tbl_span *sp)
{
struct tag *t;
int ic;
if (h->tbl.cols == NULL) {
@ -61,10 +62,10 @@ html_tblopen(struct html *h, const struct tbl_span *sp)
assert(NULL == h->tblt);
h->tblt = print_otag(h, TAG_TABLE, "c", "tbl");
t = print_otag(h, TAG_COLGROUP, "");
for (ic = 0; ic < sp->opts->cols; ic++)
print_otag(h, TAG_COL, "shw", h->tbl.cols[ic].width);
print_otag(h, TAG_TBODY, "");
print_tagq(h, t);
}
void

View File

@ -1,4 +1,4 @@
/* $Id: term_ps.c,v 1.82 2016/08/10 11:03:43 schwarze Exp $ */
/* $Id: term_ps.c,v 1.83 2017/02/17 14:31:52 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
@ -104,7 +104,7 @@ static void ps_pclose(struct termp *);
static void ps_plast(struct termp *);
static void ps_pletter(struct termp *, int);
static void ps_printf(struct termp *, const char *, ...)
__attribute__((__format__ (printf, 2, 3)));
__attribute__((__format__ (__printf__, 2, 3)));
static void ps_putchar(struct termp *, char);
static void ps_setfont(struct termp *, enum termfont);
static void ps_setwidth(struct termp *, int, int);

7
test-O_DIRECTORY.c Normal file
View File

@ -0,0 +1,7 @@
#include <fcntl.h>
int
main(void)
{
return open(".", O_RDONLY | O_DIRECTORY) == -1;
}

13
test-cmsg.c Normal file
View File

@ -0,0 +1,13 @@
#include <stddef.h>
#include <sys/socket.h>
int
main(void)
{
struct msghdr msg;
msg.msg_control = NULL;
msg.msg_controllen = 0;
return CMSG_FIRSTHDR(&msg) != NULL;
}

8
test-recvmsg.c Normal file
View File

@ -0,0 +1,8 @@
#include <sys/socket.h>
#include <stddef.h>
int
main(void)
{
return recvmsg(-1, NULL, 0) != -1;
}

4
tree.c
View File

@ -1,4 +1,4 @@
/* $Id: tree.c,v 1.72 2017/01/12 17:29:33 schwarze Exp $ */
/* $Id: tree.c,v 1.73 2017/02/10 15:45:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -192,6 +192,8 @@ print_mdoc(const struct roff_node *n, int indent)
putchar(')');
if (NODE_EOS & n->flags)
putchar('.');
if (NODE_BROKEN & n->flags)
printf(" BROKEN");
if (NODE_NOSRC & n->flags)
printf(" NOSRC");
if (NODE_NOPRT & n->flags)