aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2019-03-29 13:13:30 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2019-03-29 13:13:30 +0000
commit8f0c701250919da7f99273250017bf536dc73db9 (patch)
treea42cb3618557ec86ef8d8f1a7389e68912dbd2c0
parent1f1d4007ae66645e397e325b72643166dc3c1efe (diff)
downloadsrc-8f0c701250919da7f99273250017bf536dc73db9.tar.gz
src-8f0c701250919da7f99273250017bf536dc73db9.zip
Import mandoc 1.4.5vendor/mandoc/1.14.5
Notes
Notes: svn path=/vendor/mandoc/dist/; revision=345685 svn path=/vendor/mandoc/1.14.5/; revision=345686; tag=vendor/mandoc/1.14.5
-rw-r--r--INSTALL7
-rw-r--r--LICENSE11
-rw-r--r--Makefile60
-rw-r--r--Makefile.depend56
-rw-r--r--NEWS76
-rw-r--r--TODO124
-rw-r--r--apropos.161
-rw-r--r--arch.c54
-rw-r--r--att.c4
-rw-r--r--cgi.c156
-rw-r--r--chars.c37
-rwxr-xr-xconfigure142
-rw-r--r--configure.local.example18
-rw-r--r--dbm.c8
-rw-r--r--demandoc.c24
-rw-r--r--eqn.c93
-rw-r--r--eqn.h72
-rw-r--r--eqn_html.c3
-rw-r--r--eqn_parse.h48
-rw-r--r--eqn_term.c6
-rw-r--r--gmdiff4
-rw-r--r--html.c277
-rw-r--r--html.h19
-rw-r--r--lib.c5
-rw-r--r--lib.in3
-rw-r--r--libman.h22
-rw-r--r--libmandoc.h54
-rw-r--r--libmdoc.h16
-rw-r--r--main.c223
-rw-r--r--main.h24
-rw-r--r--man.125
-rw-r--r--man.7772
-rw-r--r--man.c170
-rw-r--r--man.conf.57
-rw-r--r--man.h3
-rw-r--r--man_html.c465
-rw-r--r--man_macro.c214
-rw-r--r--man_term.c323
-rw-r--r--man_validate.c211
-rw-r--r--manconf.h8
-rw-r--r--mandoc.1138
-rw-r--r--mandoc.3187
-rw-r--r--mandoc.c316
-rw-r--r--mandoc.css114
-rw-r--r--mandoc.h241
-rw-r--r--mandoc_char.724
-rw-r--r--mandoc_headers.3378
-rw-r--r--mandoc_html.317
-rw-r--r--mandoc_msg.c329
-rw-r--r--mandoc_parse.h43
-rw-r--r--mandocd.c33
-rw-r--r--mandocdb.c72
-rw-r--r--manpath.c24
-rw-r--r--mansearch.c18
-rw-r--r--mansearch.h3
-rw-r--r--mdoc.71523
-rw-r--r--mdoc.c59
-rw-r--r--mdoc.h5
-rw-r--r--mdoc_argv.c53
-rw-r--r--mdoc_html.c437
-rw-r--r--mdoc_macro.c272
-rw-r--r--mdoc_man.c111
-rw-r--r--mdoc_markdown.c64
-rw-r--r--mdoc_state.c60
-rw-r--r--mdoc_term.c149
-rw-r--r--mdoc_validate.c559
-rw-r--r--msec.c3
-rw-r--r--out.c334
-rw-r--r--out.h5
-rw-r--r--preconv.c5
-rw-r--r--read.c730
-rw-r--r--roff.7607
-rw-r--r--roff.c1299
-rw-r--r--roff.h86
-rw-r--r--roff_html.c51
-rw-r--r--roff_int.h58
-rw-r--r--roff_term.c48
-rw-r--r--roff_validate.c106
-rw-r--r--st.c54
-rw-r--r--st.in76
-rw-r--r--tag.c45
-rw-r--r--tag.h3
-rw-r--r--tbl.333
-rw-r--r--tbl.744
-rw-r--r--tbl.c76
-rw-r--r--tbl.h122
-rw-r--r--tbl_data.c113
-rw-r--r--tbl_html.c158
-rw-r--r--tbl_int.h47
-rw-r--r--tbl_layout.c34
-rw-r--r--tbl_opts.c22
-rw-r--r--tbl_parse.h30
-rw-r--r--tbl_term.c665
-rw-r--r--term.c489
-rw-r--r--term.h6
-rw-r--r--term_ascii.c13
-rw-r--r--term_tab.c2
-rw-r--r--test-getsubopt.c13
-rw-r--r--test-strcasestr.c4
-rw-r--r--test-stringlist.c3
-rw-r--r--test-strptime.c4
-rw-r--r--test-vasprintf.c6
-rw-r--r--test-wchar.c6
-rw-r--r--tree.c96
104 files changed, 8249 insertions, 6381 deletions
diff --git a/INSTALL b/INSTALL
index 558574b903de..3c09f3f214cb 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,4 +1,4 @@
-$Id: INSTALL,v 1.22 2018/07/31 15:34:00 schwarze Exp $
+$Id: INSTALL,v 1.23 2019/03/06 15:58:10 schwarze Exp $
About the portable mandoc distribution
--------------------------------------
@@ -18,7 +18,7 @@ tech@ mailing list, too.
Enjoy using the mandoc toolset!
-Ingo Schwarze, Karlsruhe, August 2018
+Ingo Schwarze, Karlsruhe, March 2019
Installation
@@ -67,7 +67,8 @@ variables into "configure.local" and go back to step 4.
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.
+first. In particular, regarding Solaris systems, look at the BUGS
+section of that manual page.
8. Run "sudo make install". If you intend to build a binary
package using some kind of fake root mechanism, you may need a
diff --git a/LICENSE b/LICENSE
index ec7fc029d82c..81eada0b3657 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,8 +1,8 @@
-$Id: LICENSE,v 1.19 2018/07/31 10:18:15 schwarze Exp $
+$Id: LICENSE,v 1.21 2018/11/26 17:11:11 schwarze Exp $
-With the exceptions noted below, all code and documentation
-contained in the mandoc toolkit is protected by the Copyright
-of the following developers:
+With the exceptions noted below, all non-trivial files contained
+in the mandoc toolkit are protected by the Copyright of the following
+developers:
Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -12,13 +12,14 @@ 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) 2017 Anthony Bentley <bentley@openbsd.org>
Copyright (c) 1998, 2004, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
Copyright (c) 2004 Ted Unangst <tedu@openbsd.org>
Copyright (c) 1994 Christos Zoulas <christos@netbsd.org>
Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
-See the individual source files for information about who contributed
+See the individual files for information about who contributed
to which file during which years.
diff --git a/Makefile b/Makefile
index 09738579f0d2..f4e29540df00 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
-# $Id: Makefile,v 1.519 2018/07/31 15:34:00 schwarze Exp $
+# $Id: Makefile,v 1.530 2019/03/06 16:08:41 schwarze Exp $
#
# Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
-# Copyright (c) 2011, 2013-2018 Ingo Schwarze <schwarze@openbsd.org>
+# Copyright (c) 2011, 2013-2019 Ingo Schwarze <schwarze@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -15,7 +15,7 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-VERSION = 1.14.4
+VERSION = 1.14.5
# === LIST OF FILES ====================================================
@@ -37,9 +37,9 @@ TESTSRCS = test-be32toh.c \
test-PATH_MAX.c \
test-pledge.c \
test-progname.c \
- test-recvmsg.c \
test-reallocarray.c \
test-recallocarray.c \
+ test-recvmsg.c \
test-rewb-bsd.c \
test-rewb-sysv.c \
test-sandbox_init.c \
@@ -54,7 +54,8 @@ TESTSRCS = test-be32toh.c \
test-vasprintf.c \
test-wchar.c
-SRCS = att.c \
+SRCS = arch.c \
+ att.c \
catman.c \
cgi.c \
chars.c \
@@ -96,6 +97,7 @@ SRCS = att.c \
man_validate.c \
mandoc.c \
mandoc_aux.c \
+ mandoc_msg.c \
mandoc_ohash.c \
mandoc_xr.c \
mandocd.c \
@@ -155,13 +157,14 @@ DISTFILES = INSTALL \
dbm_map.h \
demandoc.1 \
eqn.7 \
+ eqn.h \
+ eqn_parse.h \
gmdiff \
html.h \
lib.in \
libman.h \
libmandoc.h \
libmdoc.h \
- libroff.h \
main.h \
makewhatis.8 \
man.1 \
@@ -184,6 +187,7 @@ DISTFILES = INSTALL \
mandoc_html.3 \
mandoc_malloc.3 \
mandoc_ohash.h \
+ mandoc_parse.h \
mandoc_xr.h \
mandocd.8 \
mansearch.3 \
@@ -198,10 +202,12 @@ DISTFILES = INSTALL \
roff.h \
roff_int.h \
soelim.1 \
- st.in \
tag.h \
tbl.3 \
tbl.7 \
+ tbl.h \
+ tbl_int.h \
+ tbl_parse.h \
term.h \
$(SRCS) \
$(TESTSRCS)
@@ -230,9 +236,11 @@ LIBROFF_OBJS = eqn.o \
LIBMANDOC_OBJS = $(LIBMAN_OBJS) \
$(LIBMDOC_OBJS) \
$(LIBROFF_OBJS) \
+ arch.o \
chars.o \
mandoc.o \
mandoc_aux.o \
+ mandoc_msg.o \
mandoc_ohash.o \
mandoc_xr.o \
msec.o \
@@ -320,6 +328,7 @@ SOELIM_OBJS = soelim.o \
WWW_MANS = apropos.1.html \
demandoc.1.html \
man.1.html \
+ man.options.1.html \
mandoc.1.html \
soelim.1.html \
man.cgi.3.html \
@@ -336,20 +345,27 @@ 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.8.html \
+ mandocd.8.html
+
+WWW_INCS = eqn.h.html \
+ html.h.html \
man.h.html \
manconf.h.html \
mandoc.h.html \
mandoc_aux.h.html \
+ mandoc_parse.h.html \
mansearch.h.html \
mdoc.h.html \
- roff.h.html
+ roff.h.html \
+ tbl.h.html \
+ tbl_int.h.html \
+ tbl_parse.h.html
# === USER CONFIGURATION ===============================================
@@ -361,9 +377,9 @@ all: mandoc demandoc soelim $(BUILD_TARGETS) Makefile.local
install: base-install $(INSTALL_TARGETS)
-www: $(WWW_MANS)
+www: $(WWW_MANS) $(WWW_INCS)
-$(WWW_MANS): mandoc
+$(WWW_MANS) $(WWW_INCS): mandoc
.PHONY: base-install cgi-install install www-install
.PHONY: clean distclean depend
@@ -382,7 +398,7 @@ clean:
rm -f mandocd catman catman.o $(MANDOCD_OBJS)
rm -f demandoc $(DEMANDOC_OBJS)
rm -f soelim $(SOELIM_OBJS)
- rm -f $(WWW_MANS) mandoc.tar.gz mandoc.sha256
+ rm -f $(WWW_MANS) $(WWW_INCS) mandoc*.tar.gz mandoc*.sha256
rm -rf *.dSYM
base-install: mandoc demandoc soelim
@@ -420,8 +436,8 @@ lib-install: libmandoc.a
mkdir -p $(DESTDIR)$(INCLUDEDIR)
mkdir -p $(DESTDIR)$(MANDIR)/man3
$(INSTALL_LIB) libmandoc.a $(DESTDIR)$(LIBDIR)
- $(INSTALL_LIB) man.h mandoc.h mandoc_aux.h mdoc.h roff.h \
- $(DESTDIR)$(INCLUDEDIR)
+ $(INSTALL_LIB) eqn.h man.h mandoc.h mandoc_aux.h mandoc_parse.h \
+ mdoc.h roff.h tbl.h $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_MAN) mandoc.3 mandoc_escape.3 mandoc_malloc.3 \
mansearch.3 mchars_alloc.3 tbl.3 $(DESTDIR)$(MANDIR)/man3
@@ -475,11 +491,14 @@ uninstall:
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)/eqn.h
rm -f $(DESTDIR)$(INCLUDEDIR)/man.h
rm -f $(DESTDIR)$(INCLUDEDIR)/mandoc.h
rm -f $(DESTDIR)$(INCLUDEDIR)/mandoc_aux.h
+ rm -f $(DESTDIR)$(INCLUDEDIR)/mandoc_parse.h
rm -f $(DESTDIR)$(INCLUDEDIR)/mdoc.h
rm -f $(DESTDIR)$(INCLUDEDIR)/roff.h
+ rm -f $(DESTDIR)$(INCLUDEDIR)/tbl.h
[ ! -e $(DESTDIR)$(INCLUDEDIR) ] || rmdir $(DESTDIR)$(INCLUDEDIR)
regress: all
@@ -516,7 +535,9 @@ soelim: $(SOELIM_OBJS)
# --- maintainer targets ---
www-install: www
- $(INSTALL_DATA) $(WWW_MANS) mandoc.css $(HTDOCDIR)
+ $(INSTALL_DATA) mandoc.css $(HTDOCDIR)
+ $(INSTALL_DATA) $(WWW_MANS) $(HTDOCDIR)/man
+ $(INSTALL_DATA) $(WWW_INCS) $(HTDOCDIR)/includes
depend: config.h
mkdep -f Makefile.depend $(CFLAGS) $(SRCS)
@@ -564,6 +585,10 @@ mandoc-$(VERSION).tar.gz: $(DISTFILES)
( cd .dist/ && tar zcf ../$@ mandoc-$(VERSION) )
rm -rf .dist/
+dist-install: dist
+ $(INSTALL_DATA) mandoc-$(VERSION).tar.gz mandoc-$(VERSION).sha256 \
+ $(HTDOCDIR)/snapshots
+
# === SUFFIX RULES =====================================================
.SUFFIXES: .1 .3 .5 .7 .8 .h
@@ -573,5 +598,6 @@ mandoc-$(VERSION).tar.gz: $(DISTFILES)
highlight -I $< > $@
.1.1.html .3.3.html .5.5.html .7.7.html .8.8.html: mandoc
- ./mandoc -Thtml -Wall,stop \
- -Ostyle=mandoc.css,man=%N.%S.html,includes=%I.html $< > $@
+ mandoc -Thtml -Wwarning,stop \
+ -O 'style=/mandoc.css,man=/man/%N.%S.html;https://man.openbsd.org/%N.%S,includes=/includes/%I.html' \
+ $< > $@
diff --git a/Makefile.depend b/Makefile.depend
index da366a1cd596..a0898095ae7a 100644
--- a/Makefile.depend
+++ b/Makefile.depend
@@ -1,6 +1,7 @@
-att.o: att.c config.h mandoc.h roff.h mdoc.h libmdoc.h
+arch.o: arch.c config.h roff.h
+att.o: att.c config.h roff.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
+cgi.o: cgi.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h mandoc_parse.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
compat_fts.o: compat_fts.c config.h compat_fts.h
@@ -26,54 +27,55 @@ dba_read.o: dba_read.c mandoc_aux.h mansearch.h dba_array.h dba.h dbm.h
dba_write.o: dba_write.c config.h dba_write.h
dbm.o: dbm.c config.h mansearch.h dbm_map.h dbm.h
dbm_map.o: dbm_map.c config.h mansearch.h dbm_map.h dbm.h
-demandoc.o: demandoc.c config.h mandoc.h roff.h man.h mdoc.h
-eqn.o: eqn.c config.h mandoc_aux.h mandoc.h roff.h libmandoc.h libroff.h
-eqn_html.o: eqn_html.c config.h mandoc.h out.h html.h
-eqn_term.o: eqn_term.c config.h mandoc.h out.h term.h
+demandoc.o: demandoc.c config.h mandoc.h roff.h man.h mdoc.h mandoc_parse.h
+eqn.o: eqn.c config.h mandoc_aux.h mandoc.h roff.h eqn.h libmandoc.h eqn_parse.h
+eqn_html.o: eqn_html.c config.h mandoc.h eqn.h out.h html.h
+eqn_term.o: eqn_term.c config.h eqn.h out.h term.h
html.o: html.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h out.h html.h manconf.h main.h
-lib.o: lib.c config.h mandoc.h roff.h mdoc.h libmdoc.h lib.in
-main.o: main.c config.h mandoc_aux.h mandoc.h mandoc_xr.h roff.h mdoc.h man.h tag.h main.h manconf.h mansearch.h
+lib.o: lib.c config.h roff.h libmdoc.h lib.in
+main.o: main.c config.h mandoc_aux.h mandoc.h mandoc_xr.h roff.h mdoc.h man.h mandoc_parse.h tag.h main.h manconf.h mansearch.h
man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
man_html.o: man_html.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h html.h main.h
man_macro.o: man_macro.c config.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
-man_term.o: man_term.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h term.h main.h
+man_term.o: man_term.c config.h mandoc_aux.h roff.h man.h out.h term.h main.h
man_validate.o: man_validate.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
-mandoc.o: mandoc.c config.h mandoc_aux.h mandoc.h roff.h libmandoc.h
+mandoc.o: mandoc.c config.h mandoc_aux.h mandoc.h roff.h libmandoc.h roff_int.h
mandoc_aux.o: mandoc_aux.c config.h mandoc.h mandoc_aux.h
+mandoc_msg.o: mandoc_msg.c mandoc.h
mandoc_ohash.o: mandoc_ohash.c mandoc_aux.h mandoc_ohash.h compat_ohash.h
mandoc_xr.o: mandoc_xr.c mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc_xr.h
-mandocd.o: mandocd.c config.h mandoc.h roff.h mdoc.h man.h 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
+mandocd.o: mandocd.c config.h mandoc.h roff.h mdoc.h man.h mandoc_parse.h main.h manconf.h
+mandocdb.o: mandocdb.c config.h compat_fts.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h mdoc.h man.h mandoc_parse.h manconf.h mansearch.h dba_array.h dba.h
manpath.o: manpath.c config.h mandoc_aux.h manconf.h
-mansearch.o: mansearch.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h manconf.h mansearch.h dbm.h
+mansearch.o: mansearch.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h manconf.h mansearch.h dbm.h
mdoc.o: mdoc.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
mdoc_argv.o: mdoc_argv.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
mdoc_html.o: mdoc_html.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h out.h html.h main.h
mdoc_macro.o: mdoc_macro.c config.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
mdoc_man.o: mdoc_man.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h out.h main.h
mdoc_markdown.o: mdoc_markdown.c mandoc_aux.h mandoc.h roff.h mdoc.h main.h
-mdoc_state.o: mdoc_state.c mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h
-mdoc_term.o: mdoc_term.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h out.h term.h tag.h main.h
+mdoc_state.o: mdoc_state.c mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
+mdoc_term.o: mdoc_term.c config.h mandoc_aux.h roff.h mdoc.h out.h term.h tag.h main.h
mdoc_validate.o: mdoc_validate.c config.h mandoc_aux.h mandoc.h mandoc_xr.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
msec.o: msec.c config.h mandoc.h libmandoc.h msec.in
-out.o: out.c config.h mandoc_aux.h mandoc.h out.h
-preconv.o: preconv.c config.h mandoc.h libmandoc.h
-read.o: read.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h libmandoc.h
-roff.o: roff.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h roff.h libmandoc.h roff_int.h libroff.h predefs.in
+out.o: out.c config.h mandoc_aux.h tbl.h out.h
+preconv.o: preconv.c config.h mandoc.h roff.h mandoc_parse.h libmandoc.h
+read.o: read.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h mandoc_parse.h libmandoc.h roff_int.h
+roff.o: roff.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h mandoc_parse.h libmandoc.h roff_int.h tbl_parse.h eqn_parse.h predefs.in
roff_html.o: roff_html.c mandoc.h roff.h out.h html.h
roff_term.o: roff_term.c mandoc.h roff.h out.h term.h
roff_validate.o: roff_validate.c mandoc.h roff.h libmandoc.h roff_int.h
soelim.o: soelim.c config.h compat_stringlist.h
-st.o: st.c config.h mandoc.h roff.h mdoc.h libmdoc.h st.in
+st.o: st.c config.h mandoc.h roff.h libmdoc.h
tag.o: tag.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h tag.h
-tbl.o: tbl.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h
-tbl_data.o: tbl_data.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h
-tbl_html.o: tbl_html.c config.h mandoc.h out.h html.h
-tbl_layout.o: tbl_layout.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h
-tbl_opts.o: tbl_opts.c config.h mandoc.h libmandoc.h libroff.h
-tbl_term.o: tbl_term.c config.h mandoc.h out.h term.h
+tbl.o: tbl.c config.h mandoc_aux.h mandoc.h tbl.h libmandoc.h tbl_parse.h tbl_int.h
+tbl_data.o: tbl_data.c config.h mandoc_aux.h mandoc.h tbl.h libmandoc.h tbl_int.h
+tbl_html.o: tbl_html.c config.h mandoc.h tbl.h out.h html.h
+tbl_layout.o: tbl_layout.c config.h mandoc_aux.h mandoc.h tbl.h libmandoc.h tbl_int.h
+tbl_opts.o: tbl_opts.c config.h mandoc.h tbl.h libmandoc.h tbl_int.h
+tbl_term.o: tbl_term.c config.h mandoc.h tbl.h out.h term.h
term.o: term.c config.h mandoc.h mandoc_aux.h out.h term.h main.h
term_ascii.o: term_ascii.c config.h mandoc.h mandoc_aux.h out.h term.h manconf.h main.h
term_ps.o: term_ps.c config.h mandoc_aux.h out.h term.h manconf.h main.h
term_tab.o: term_tab.c mandoc_aux.h out.h term.h
-tree.o: tree.c config.h mandoc.h roff.h mdoc.h man.h main.h
+tree.o: tree.c config.h mandoc.h roff.h mdoc.h man.h tbl.h eqn.h main.h
diff --git a/NEWS b/NEWS
index 3bb5b4728b99..89eb3f6fb629 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,81 @@
-$Id: NEWS,v 1.32 2018/08/08 14:47:38 schwarze Exp $
+$Id: NEWS,v 1.34 2019/03/10 09:32:00 schwarze Exp $
This file lists the most important changes in the mandoc.bsd.lv distribution.
+Changes in version 1.14.5, released on March 10, 2019
+
+ --- MAJOR NEW FEATURES ---
+ * apropos(1): improve POSIX compliance by accepting case-insensitive
+ extended regular expressions by default
+ * new -O tag[=term] output option (open a page at the definition of a term)
+ * tbl(7) -T html: spanning and horizontal and vertical alignment of cells
+ * tbl(7) -T html: draw lines on the edges of table cells
+ * tbl(7) -T utf8: render lines with the Unicode box drawing characters
+ * mandoc is now able to handle the manual pages of the groff package.
+ --- MINOR NEW FEATURES ---
+ * -T html: new option -O toc (table of contents)
+ * -T html: second argument to -O man to support local and remote links
+ * mdoc(7) .Bd -centered now fills the text contained in it
+ * man-ext .SY and .YS macros (synopsis block)
+ * man-ext .TQ macro (tagged paragraph without vertical space before it)
+ * tbl(7) \& explicit alignment indicator
+ * roff(7) .shift, .while, and .return requests
+ * roff(7) .char request (output glyph definition)
+ * roff(7) .nop request (no operation)
+ * roff(7) .ft request: handle the CB, CI, and CR fonts
+ * roff(7) .if c conditional (character available)
+ * roff(7) \\$@ escape sequence (insert all macro arguments, quoted)
+ * roff(7) \*(.T predefined string (interpolate output device name)
+ * roff(7) \[charNNN] escape sequence (for printable ASCII characters)
+ * roff(7) \# escape sequence (line continuation with comment)
+ --- HTML OUTPUT SYNTAX CORRECTIONS ---
+ * Render .br and \p as <br/>, not as an empty <div>.
+ * Render .Pp and .PP as <p> and automatically close it when needed.
+ * Stop writing empty list elements for non-compact .Bl -tag lists.
+ * Do not put <p> inside <a> if .UR or .MT contain .PP.
+ * Implement tooltips purely in CSS rather than abusing title= attributes.
+ --- MINOR FUNCTIONAL IMPROVEMENTS ---
+ * many improvements to the handling of fill and no-fill mode
+ * tbl(7): better column widths in the presence of horizontal spans
+ * several minor improvements to escape sequence handling
+ * several minor improvements to manual font handling
+ * portability: autodetect need for _GNU_SOURCE or _OPENBSD_SOURCE
+ * portability: autodetect whether less(1) supports the -T option
+ * large numbers of bugfixes of diverse kinds
+ --- STRUCTURAL IMPROVEMENTS ---
+ * Disentangle eqn(7) and tbl(7) from other parser header files,
+ and clean up some parser data structures.
+ * Substantially simplify error and warning message infrastructure.
+ --- THANKS TO ---
+ * John Gardner for crucial help implementing tooltips in CSS.
+ * Alexander Bluhm, Raphael Graf, Ted Unangst (OpenBSD)
+ and Daniel Sabogal (Alpine Linux) for patches.
+ * Anthony Bentley and Jason McIntyre (OpenBSD) for documentation patches,
+ suggesting new features, bug reports, and useful discussions.
+ * Kyle Evans and Baptiste Daroussin (FreeBSD) for minor patches.
+ * Pali Rohar for suggesting multiple new features and for reporting
+ several bugs and missing features.
+ * Klemens Nanni (OpenBSD) for suggesting multiple new features.
+ * Kristaps Dzonsons (bsd.lv), Marc Espie (OpenBSD), Adam Kalisz,
+ and Laura Morales for suggesting new features.
+ * Wolfram Schneider and Yuri Pankov (FreeBSD) for reporting missing features.
+ * Edward Tomasz Napierala (FreeBSD) for suggesting a feature improvement.
+ * Thomas Klausner (NetBSD) and Sevan Janiyan (SmartOS)
+ for bug reports and release testing.
+ * Bryan Steele, Janne Johansson, Kurt Mosiejczuk, Mike Belopuhov, Theo
+ Buehler, Todd Miller (OpenBSD), Andreas Gustafsson, Christos Zoulas,
+ Robert Elz (NetBSD), Kurt Jaeger (FreeBSD), Fabio Scotoni, Kelvin
+ Sherlock, Mark Harris, Orestis Ioannou, Raf Czlonka, and Sean Farrell
+ for bug reports.
+ * Ulrich Spoerlein (FreeBSD), Leah Neukirchen (Void Linux),
+ Matej Cepl (openSUSE), and Jan Stary (MacOS X) for release testing.
+ * Brian Callahan and Stuart Henderson (OpenBSD) for help
+ with the OpenBSD groff port.
+ * Bertrand Garrigues, Branden Robinson, Ralph Corderoy, and Werner
+ Lemberg (GNU troff) for checking groff patches.
+ * Scott Cheloha, Theo de Raadt (OpenBSD)
+ and Natanael Copa (Alpine Linux) for useful discussions.
+
Changes in version 1.14.4, released on August 8, 2018
--- MAJOR NEW FEATURES ---
diff --git a/TODO b/TODO
index 6df63ea3c79b..063e2789d2c5 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,6 @@
************************************************************************
* Official mandoc TODO.
-* $Id: TODO,v 1.258 2018/08/06 14:16:30 schwarze Exp $
+* $Id: TODO,v 1.289 2019/03/04 13:01:57 schwarze Exp $
************************************************************************
Many issues are annotated for difficulty as follows:
@@ -38,18 +38,6 @@ are mere guesses, and some may be wrong.
--- missing roff features ----------------------------------------------
-- .nop prints its arguments as text,
- see groff(7) for an example
-
-- .ft CB selects constant-width bold font
- see groff_out(7) for examples
-
-- \*(.T prints the device being used,
- see groff_char(7) for an example
-
-- \[charNN], \[charNNN] prints a single-byte codepoint
- see groff_char(7) for examples
-
- .ad (adjust margins)
.ad l -- adjust left margin only (flush left)
.ad r -- adjust right margin only (flush right)
@@ -69,34 +57,11 @@ are mere guesses, and some may be wrong.
reported by brad@ Sat, 15 Jan 2011 15:45:23 -0500
loc *** exist *** algo *** size ** imp *
-- .while and .shift
- found by jca@ in ratpoison(1) Sun, 30 Jun 2013 12:01:09 +0200
- loc * exist ** algo ** size ** imp **
-
- \w'' improve width measurements
would not be very useful without an expression parser, see below
needed for Tcl_NewStringObj(3) via wiz@ Wed, 5 Mar 2014 22:27:43 +0100
loc ** exist *** algo *** size * imp ***
-- \\ in high-level macro arguments
- Currently, \\ is expanded in two situations:
- 1) macro and string definition (roff.c setstrn())
- 2) macro argument parsing (mandoc.c mandoc_getarg())
- For user defined macros, the second happens in time because of ROFF_REPARSE.
- But for standard high-level macros, it only happens after entering the
- high level parsers, which is too late because the code doesn't get
- back to roff.c roff_res() from that point. Because this requires
- distinguishing requests, user-defined macros and standard macros
- on the roff_res() level, it is hard to solve without the parser reorg.
- Found by naddy@ in devel/cutils cobfusc(1) Mon, 16 Feb 2015 19:10:52 +0100
- loc *** exist *** algo *** size ** imp *
-
-- check for missing roff escape sequences, implement those that are
- trivial even if not usually appearing in manual pages, gracefully
- ignore the non-trivial ones, document what they are supposed to do
- and what mandoc does instead
- loc * exist ** algo * size * imp *
-
--- missing mdoc features ----------------------------------------------
- .Bl -column .Xo support is missing
@@ -112,13 +77,6 @@ are mere guesses, and some may be wrong.
from jmc@ Wed, 14 Jul 2010 18:10:32 +0100
loc * exist *** algo *** size ** imp **
-- .Bd -centered implies -filled, not -unfilled, which is not
- easy to implement; it requires code similar to .ce, which
- we don't have either.
- Besides, groff has bug causing text right *before* .Bd -centered
- to be centered as well.
- loc *** exist *** algo ** size ** imp ** (parser reorg would help)
-
- .Bd -filled should not be the same as .Bd -ragged, but align both
the left and right margin. In groff, it is implemented in terms
of .ad b, which we don't have either. Found in cksum(1).
@@ -174,15 +132,6 @@ are mere guesses, and some may be wrong.
--- missing man features -----------------------------------------------
-- .SY and .YS,
- used by many groff manual pages
-
-- preserve punctuation following .ME,
- see ditroff(7) for an example
-
-- .TQ tagged paragraph continuation,
- see groff_diff(7) for examples
-
- groff_www(7) .MTO and .URL
These macros were used by the GNU grep(1) man page.
The groff_www(7) manual page itself uses them, too.
@@ -193,18 +142,10 @@ are mere guesses, and some may be wrong.
--- missing tbl features -----------------------------------------------
-- the "s" layout column specifier is used for placement of data
- into columns, but ignored during column width calculations
- synaptics(4) found by tedu@ Mon, 17 Aug 2015 21:17:42 -0400
- loc * exist ** algo *** size * imp **
-
- vertical centering in cells vertically spanned with ^
pali dot rohar at gmail dot com 16 Jul 2018 13:03:35 +0200
loc * exist *** algo *** size ** imp *
-- support .ds requests inside tbl(7) code,
- see tbl(1) for an example
-
- 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;
@@ -212,35 +153,24 @@ are mere guesses, and some may be wrong.
loc *** exist ** algo *** size ** imp ***
- look at the POSIX manuals in the books/man-pages-posix port,
- they use some unsupported tbl(7) features.
+ they use some unsupported tbl(7) features, mostly macros in tbl(7).
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
- loc * exist ** algo * size * imp **
-
-- implement horizontal and vertical alignment in HTML output
- pali dot rohar at gmail dot com 16 Jul 2018 13:03:35 +0200
- loc * exist * algo * size * imp ***
-
-- implement cell spanning in HTML output
- pali dot rohar at gmail dot com 16 Jul 2018 13:03:35 +0200
- loc * exist * algo ** size ** imp **
-
-- implement table borders in HTML output
- pali dot rohar at gmail dot com 16 Jul 2018 13:03:35 +0200
- loc * exist * algo ** size ** imp **
-
--- missing eqn features -----------------------------------------------
- In a matrix, break the output line after each matrix line.
- Found in the discussion at CDBUG 2015.
- Suggested by Avi Weinstock.
- loc * exist * algo * size * imp **
+ Found in the discussion at CDBUG 2015. Suggested by Avi Weinstock.
+ This may not be the ideal solution after all: eqn(7) matrices
+ are lists of columns, so Avi's proposal would show each *column*
+ on its own *line*, which is likely to cause confusion.
+ A better solution, but much harder to implement, would be to
+ actually show the coordinates of column vectors on different
+ terminal output lines, using the clumnated output facilities
+ developed for .Bl -tag, .Bl -column, and also used for tbl(7).
+ loc * exist * algo ** size ** imp **
- The "size" keyword is parsed, but ignored by the formatter.
loc * exist * algo * size * imp *
@@ -341,9 +271,6 @@ are mere guesses, and some may be wrong.
* formatting issues: ugly output
************************************************************************
-- .UR can nest inside .TP,
- see roff(7) for examples
-
- revisit empty in-line macros
look at the difference between "Em x Em ." and "Sq x Em ."
Carsten Kunze Fri, 12 Dec 2014 00:15:41 +0100
@@ -400,6 +327,8 @@ are mere guesses, and some may be wrong.
- a line starting with "\fB something" counts as starting with whitespace
and triggers a line break; found in audio/normalize-mp3(1)
+ This will become easier once escape sequences are represented
+ by syntax tree nodes.
loc ** exist * algo ** size * imp **
- formatting /usr/local/man/man1/latex2man.1 with groff and mandoc
@@ -421,17 +350,6 @@ are mere guesses, and some may be wrong.
--- HTML issues --------------------------------------------------------
-- wrap Sh and Ss content into <div>
- Laura Morales <lauretas at mail dot com> 21 Apr 2018 18:10:48 +0200
- (Evaluate whether this is really useful and has no adverse
- side effects before implementing; if it is possible,
- it does seem cleaner.)
- loc ** exist ** algo * size * imp ***
-
-- format ".IP *" etc. as <ul> rather than <dl>
- https://github.com/Debian/debiman/issues/67
- loc ** exist ** algo ** size * imp ***
-
- .Bf at the beginning of a paragraph inserts a bogus 1ex horizontal
space, see for example random(3). Introduced in
http://mdocml.bsd.lv/cgi-bin/cvsweb/mdoc_html.c.diff?r1=1.91&r2=1.92
@@ -558,18 +476,11 @@ are mere guesses, and some may be wrong.
all over mdoc_macro.c and all subtly different.
loc ** exist ** algo ** size ** imp **
-- style message about suspicious uses of - vs. \- vs. \(mi
- e.g. -1 is likely wrong (from the mdoclint TODO)
-
- warn about punctuation - e.g. ',' and ';' - at the beginning
of a text line, if it is likely intended to follow the preceding
output without intervening whitespace, in particular after a
macro line (from the mdoclint TODO)
-- mandoc_special does not really check the escape sequence,
- but just the overall format
- loc ** exist ** algo *** size ** imp **
-
- makewhatis -p complains about language subdirectories:
/usr/local/man//ru: Unknown directory part
@@ -578,9 +489,6 @@ are mere guesses, and some may be wrong.
* documentation issues
************************************************************************
-- dashes, hyphens, and minus signs in manual pages
- jmc@ Fri, 28 Mar 2014 07:19:27 +0000
-
- mark macros as: page structure domain, manual domain, general text domain
is this useful?
@@ -606,10 +514,6 @@ are mere guesses, and some may be wrong.
Found by Aaron M. Ucko in the GNU Hurd via Bdale Garbee,
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=829624
-- We use the input line number at several places to distinguish
- same-line from different-line input. That plainly doesn't work
- with user-defined macros, leading to random breakage.
-
- Is it possible to further simplify ENDBODY_SPACE?
- Find better ways to prevent endless loops
@@ -629,8 +533,6 @@ are mere guesses, and some may be wrong.
output through libz.
- Privilege separation (see OpenSSH).
- Enable caching support via HTTP 304 and If-Modified-Since.
- - Have Mac OSX systems automatically disable -static compilation of the
- CGI: -static isn't supported.
************************************************************************
* to improve in the groff_mdoc(7) macros
diff --git a/apropos.1 b/apropos.1
index c0895a87e4c3..01d2a6bfa4f4 100644
--- a/apropos.1
+++ b/apropos.1
@@ -1,7 +1,7 @@
-.\" $Id: apropos.1,v 1.47 2018/02/23 18:54:02 schwarze Exp $
+.\" $Id: apropos.1,v 1.49 2018/11/22 12:33:52 schwarze Exp $
.\"
.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2011, 2012, 2014, 2017 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2011,2012,2014,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: February 23 2018 $
+.Dd $Mdocdate: November 22 2018 $
.Dt APROPOS 1
.Os
.Sh NAME
@@ -51,8 +51,7 @@ searches for
.Xr makewhatis 8
databases in the default paths stipulated by
.Xr man 1
-and uses case-insensitive substring matching
-.Pq the Cm = No operator
+and uses case-insensitive extended regular expression matching
over manual names and descriptions
.Pq the Li \&Nm No and Li \&Nd No macro keys .
Multiple terms imply pairwise
@@ -93,7 +92,7 @@ format.
Search for all words in
.Ar expression
in manual page names only.
-The search is case insensitive and matches whole words only.
+The search is case-insensitive and matches whole words only.
In this mode, macro keys, comparison operators, and logical operators
are not available.
.It Fl k
@@ -123,7 +122,7 @@ Restrict the search to pages for the specified
.Xr machine 1
architecture.
.Ar arch
-is case insensitive.
+is case-insensitive.
By default, pages for all architectures are shown.
.It Fl s Ar section
Restrict the search to the specified section of the manual.
@@ -199,7 +198,7 @@ Operator
.Cm =
evaluates a substring, while
.Cm \(ti
-evaluates a regular expression.
+evaluates a case-sensitive extended regular expression.
.It Fl i Ar term
If
.Ar term
@@ -208,26 +207,10 @@ is evaluated case-insensitively.
Has no effect on substring terms.
.El
.Pp
-Results are sorted according to the following criteria:
-.Bl -enum
-.It
-The manpath directory tree the page is found in, according to the
-order specified with
-.Fl M ,
-.Fl m ,
-the
-.Ev MANPATH
-environment variable, the
-.Xr man.conf 5
-configuration file, or the default documented in
-.Xr man.conf 5 .
-.It
-The section number in ascending numerical order.
-.It
-The page name in ascending
+Results are sorted first according to the section number in ascending
+numerical order, then by the page name in ascending
.Xr ascii 7
alphabetical order, case-insensitive.
-.El
.Pp
Each output line is formatted as
.Pp
@@ -339,7 +322,7 @@ function arguments appearing on
.Ic \&Fn
lines
.It Li \&Fn
-fuction names marked up with
+function names marked up with
.Ic \&Fo
macros
.It Li \&In
@@ -407,7 +390,7 @@ Search for
.Qq .cf
as a substring of manual names and descriptions:
.Pp
-.Dl $ apropos .cf
+.Dl $ apropos =.cf
.Pp
Include matches for
.Qq .cnf
@@ -415,9 +398,9 @@ and
.Qq .conf
as well:
.Pp
-.Dl $ apropos .cf .cnf .conf
+.Dl $ apropos =.cf =.cnf =.conf
.Pp
-Search in names and descriptions using a regular expression:
+Search in names and descriptions using a case-sensitive regular expression:
.Pp
.Dl $ apropos \(aq\(tiset.?[ug]id\(aq
.Pp
@@ -448,6 +431,24 @@ The following two invocations are equivalent:
.Xr man 1 ,
.Xr re_format 7 ,
.Xr makewhatis 8
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification of
+.Xr man 1
+.Fl k .
+.Pp
+All options, the
+.Nm whatis
+command, support for logical operators, macro keys,
+substring matching, sorting of results, the environment variables
+.Ev MANPAGER
+and
+.Ev MANPATH ,
+the database format, and the configuration file
+are extensions to that specification.
.Sh HISTORY
Part of the functionality of
.Nm whatis
diff --git a/arch.c b/arch.c
new file mode 100644
index 000000000000..56b937ec8412
--- /dev/null
+++ b/arch.c
@@ -0,0 +1,54 @@
+/* $Id: arch.c,v 1.14 2019/03/04 13:01:57 schwarze Exp $ */
+/*
+ * Copyright (c) 2017, 2019 Ingo Schwarze <schwarze@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "config.h"
+
+#include <string.h>
+
+#include "roff.h"
+
+int
+arch_valid(const char *arch, enum mandoc_os os)
+{
+ const char *openbsd_arch[] = {
+ "alpha", "amd64", "arm64", "armv7", "hppa", "i386",
+ "landisk", "loongson", "luna88k", "macppc", "mips64",
+ "octeon", "sgi", "socppc", "sparc64", NULL
+ };
+ const char *netbsd_arch[] = {
+ "acorn26", "acorn32", "algor", "alpha", "amiga",
+ "arc", "atari",
+ "bebox", "cats", "cesfic", "cobalt", "dreamcast",
+ "emips", "evbarm", "evbmips", "evbppc", "evbsh3", "evbsh5",
+ "hp300", "hpcarm", "hpcmips", "hpcsh", "hppa",
+ "i386", "ibmnws", "luna68k",
+ "mac68k", "macppc", "mipsco", "mmeye", "mvme68k", "mvmeppc",
+ "netwinder", "news68k", "newsmips", "next68k",
+ "pc532", "playstation2", "pmax", "pmppc", "prep",
+ "sandpoint", "sbmips", "sgimips", "shark",
+ "sparc", "sparc64", "sun2", "sun3",
+ "vax", "walnut", "x68k", "x86", "x86_64", "xen", NULL
+ };
+ const char **arches[] = { NULL, netbsd_arch, openbsd_arch };
+ const char **arch_p;
+
+ if ((arch_p = arches[os]) == NULL)
+ return 1;
+ for (; *arch_p != NULL; arch_p++)
+ if (strcmp(*arch_p, arch) == 0)
+ return 1;
+ return 0;
+}
diff --git a/att.c b/att.c
index dd7f2a0d7711..5575bed54a4f 100644
--- a/att.c
+++ b/att.c
@@ -1,4 +1,4 @@
-/* $Id: att.c,v 1.16 2017/06/24 14:38:32 schwarze Exp $ */
+/* $Id: att.c,v 1.18 2018/12/13 11:55:46 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -19,9 +19,7 @@
#include <sys/types.h>
#include <string.h>
-#include "mandoc.h"
#include "roff.h"
-#include "mdoc.h"
#include "libmdoc.h"
#define LINE(x, y) \
diff --git a/cgi.c b/cgi.c
index 8098352d6140..0af0f1255d40 100644
--- a/cgi.c
+++ b/cgi.c
@@ -1,7 +1,7 @@
-/* $Id: cgi.c,v 1.158 2018/05/29 20:32:45 schwarze Exp $ */
+/* $Id: cgi.c,v 1.166 2019/03/06 12:32:41 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@usta.de>
+ * Copyright (c) 2014, 2015, 2016, 2017, 2018 Ingo Schwarze <schwarze@usta.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -38,6 +38,7 @@
#include "roff.h"
#include "mdoc.h"
#include "man.h"
+#include "mandoc_parse.h"
#include "main.h"
#include "manconf.h"
#include "mansearch.h"
@@ -69,6 +70,7 @@ enum focus {
static void html_print(const char *);
static void html_putchar(char);
static int http_decode(char *);
+static void http_encode(const char *p);
static void parse_manpath_conf(struct req *);
static void parse_path_info(struct req *req, const char *path);
static void parse_query_string(struct req *, const char *);
@@ -90,6 +92,7 @@ static void resp_format(const struct req *, const char *);
static void resp_searchform(const struct req *, enum focus);
static void resp_show(const struct req *, const char *);
static void set_query_attr(char **, char **);
+static int validate_arch(const char *);
static int validate_filename(const char *);
static int validate_manpath(const struct req *, const char *);
static int validate_urifrag(const char *);
@@ -316,6 +319,18 @@ http_decode(char *p)
}
static void
+http_encode(const char *p)
+{
+ for (; *p != '\0'; p++) {
+ if (isalnum((unsigned char)*p) == 0 &&
+ strchr("-._~", *p) == NULL)
+ printf("%%%2.2X", (unsigned char)*p);
+ else
+ putchar(*p);
+ }
+}
+
+static void
resp_begin_http(int code, const char *msg)
{
@@ -490,6 +505,18 @@ validate_manpath(const struct req *req, const char* manpath)
}
static int
+validate_arch(const char *arch)
+{
+ int i;
+
+ for (i = 0; i < arch_MAX; i++)
+ if (strcmp(arch, arch_names[i]) == 0)
+ return 1;
+
+ return 0;
+}
+
+static int
validate_filename(const char *file)
{
@@ -562,9 +589,11 @@ pg_redirect(const struct req *req, const char *name)
printf("%s/", req->q.manpath);
if (req->q.arch != NULL)
printf("%s/", req->q.arch);
- printf("%s", name);
- if (req->q.sec != NULL)
- printf(".%s", req->q.sec);
+ http_encode(name);
+ if (req->q.sec != NULL) {
+ putchar('.');
+ http_encode(req->q.sec);
+ }
printf("\r\nContent-Type: text/html; charset=utf-8\r\n\r\n");
}
@@ -820,7 +849,7 @@ resp_format(const struct req *req, const char *file)
{
struct manoutput conf;
struct mparse *mp;
- struct roff_man *man;
+ struct roff_meta *meta;
void *vp;
int fd;
int usepath;
@@ -831,37 +860,26 @@ resp_format(const struct req *req, const char *file)
}
mchars_alloc();
- mp = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1,
- MANDOCERR_MAX, NULL, MANDOC_OS_OTHER, req->q.manpath);
+ mp = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1 |
+ MPARSE_VALIDATE, MANDOC_OS_OTHER, req->q.manpath);
mparse_readfd(mp, fd, file);
close(fd);
+ meta = mparse_result(mp);
memset(&conf, 0, sizeof(conf));
conf.fragment = 1;
conf.style = mandoc_strdup(CSS_DIR "/mandoc.css");
+ conf.toc = 1;
usepath = strcmp(req->q.manpath, req->p[0]);
mandoc_asprintf(&conf.man, "/%s%s%s%s%%N.%%S",
scriptname, *scriptname == '\0' ? "" : "/",
usepath ? req->q.manpath : "", usepath ? "/" : "");
- mparse_result(mp, &man, NULL);
- if (man == NULL) {
- warnx("fatal mandoc error: %s/%s", req->q.manpath, file);
- pg_error_internal();
- mparse_free(mp);
- mchars_free();
- return;
- }
-
vp = html_alloc(&conf);
-
- if (man->macroset == MACROSET_MDOC) {
- mdoc_validate(man);
- html_mdoc(vp, man);
- } else {
- man_validate(man);
- html_man(vp, man);
- }
+ if (meta->macroset == MACROSET_MDOC)
+ html_mdoc(vp, meta);
+ else
+ html_man(vp, meta);
html_free(vp);
mparse_free(mp);
@@ -1089,7 +1107,7 @@ main(void)
return EXIT_FAILURE;
}
- if ( ! (NULL == req.q.arch || validate_urifrag(req.q.arch))) {
+ if (req.q.arch != NULL && validate_arch(req.q.arch) == 0) {
pg_error_badrequest(
"You specified an invalid architecture.");
return EXIT_FAILURE;
@@ -1115,80 +1133,74 @@ main(void)
}
/*
- * If PATH_INFO is not a file name, translate it to a query.
+ * Translate PATH_INFO to a query.
*/
static void
parse_path_info(struct req *req, const char *path)
{
- char *dir[4];
- int i;
+ const char *name, *sec, *end;
req->isquery = 0;
req->q.equal = 1;
- req->q.manpath = mandoc_strdup(path);
+ req->q.manpath = NULL;
req->q.arch = NULL;
/* Mandatory manual page name. */
- if ((req->q.query = strrchr(req->q.manpath, '/')) == NULL) {
- req->q.query = req->q.manpath;
- req->q.manpath = NULL;
- } else
- *req->q.query++ = '\0';
+ if ((name = strrchr(path, '/')) == NULL)
+ name = path;
+ else
+ name++;
/* Optional trailing section. */
- if ((req->q.sec = strrchr(req->q.query, '.')) != NULL) {
- if(isdigit((unsigned char)req->q.sec[1])) {
- *req->q.sec++ = '\0';
- req->q.sec = mandoc_strdup(req->q.sec);
- } else
- req->q.sec = NULL;
+ sec = strrchr(name, '.');
+ if (sec != NULL && isdigit((unsigned char)*++sec)) {
+ req->q.query = mandoc_strndup(name, sec - name - 1);
+ req->q.sec = mandoc_strdup(sec);
+ } else {
+ req->q.query = mandoc_strdup(name);
+ req->q.sec = NULL;
}
/* Handle the case of name[.section] only. */
- if (req->q.manpath == NULL)
+ if (name == path)
return;
- req->q.query = mandoc_strdup(req->q.query);
-
- /* Split directory components. */
- dir[i = 0] = req->q.manpath;
- while ((dir[i + 1] = strchr(dir[i], '/')) != NULL) {
- if (++i == 3) {
- pg_error_badrequest(
- "You specified too many directory components.");
- exit(EXIT_FAILURE);
- }
- *dir[i]++ = '\0';
- }
/* Optional manpath. */
- if ((i = validate_manpath(req, req->q.manpath)) == 0)
+ end = strchr(path, '/');
+ req->q.manpath = mandoc_strndup(path, end - path);
+ if (validate_manpath(req, req->q.manpath)) {
+ path = end + 1;
+ if (name == path)
+ return;
+ } else {
+ free(req->q.manpath);
req->q.manpath = NULL;
- else if (dir[1] == NULL)
- return;
+ }
/* Optional section. */
- if (strncmp(dir[i], "man", 3) == 0) {
+ if (strncmp(path, "man", 3) == 0 || strncmp(path, "cat", 3) == 0) {
+ path += 3;
+ end = strchr(path, '/');
free(req->q.sec);
- req->q.sec = mandoc_strdup(dir[i++] + 3);
+ req->q.sec = mandoc_strndup(path, end - path);
+ path = end + 1;
+ if (name == path)
+ return;
}
- if (dir[i] == NULL) {
- if (req->q.manpath == NULL)
- free(dir[0]);
- return;
+
+ /* Optional architecture. */
+ end = strchr(path, '/');
+ if (end + 1 != name) {
+ pg_error_badrequest(
+ "You specified too many directory components.");
+ exit(EXIT_FAILURE);
}
- if (dir[i + 1] != NULL) {
+ req->q.arch = mandoc_strndup(path, end - path);
+ if (validate_arch(req->q.arch) == 0) {
pg_error_badrequest(
"You specified an invalid directory component.");
exit(EXIT_FAILURE);
}
-
- /* Optional architecture. */
- if (i) {
- req->q.arch = mandoc_strdup(dir[i]);
- if (req->q.manpath == NULL)
- free(dir[0]);
- } else
- req->q.arch = dir[0];
}
/*
diff --git a/chars.c b/chars.c
index fb9ded8baef6..24166dbd9f8f 100644
--- a/chars.c
+++ b/chars.c
@@ -1,7 +1,7 @@
-/* $Id: chars.c,v 1.73 2017/08/23 13:01:29 schwarze Exp $ */
+/* $Id: chars.c,v 1.78 2018/12/15 19:30:26 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011,2014,2015,2017,2018 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
@@ -23,6 +23,7 @@
#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -47,20 +48,13 @@ static struct ln lines[] = {
{ " ", ascii_nbrsp, 0x00a0 },
{ "~", ascii_nbrsp, 0x00a0 },
{ "0", " ", 0x2002 },
- { "|", "", 0 },
- { "^", "", 0 },
- { "&", "", 0 },
- { "%", "", 0 },
{ ":", ascii_break, 0 },
- /* XXX The following three do not really belong here. */
- { "t", "", 0 },
- { "c", "", 0 },
- { "}", "", 0 },
/* Lines. */
{ "ba", "|", 0x007c },
{ "br", "|", 0x2502 },
{ "ul", "_", 0x005f },
+ { "_", "_", 0x005f },
{ "ru", "_", 0x005f },
{ "rn", "-", 0x203e },
{ "bb", "|", 0x00a6 },
@@ -82,10 +76,10 @@ static struct ln lines[] = {
{ "sh", "#", 0x0023 },
{ "CR", "<cr>", 0x21b5 },
{ "OK", "\\/", 0x2713 },
- { "CL", "<club>", 0x2663 },
- { "SP", "<spade>", 0x2660 },
- { "HE", "<heart>", 0x2665 },
- { "DI", "<diamond>", 0x2666 },
+ { "CL", "C", 0x2663 },
+ { "SP", "S", 0x2660 },
+ { "HE", "H", 0x2665 },
+ { "DI", "D", 0x2666 },
/* Legal symbols. */
{ "co", "(C)", 0x00a9 },
@@ -240,7 +234,7 @@ static struct ln lines[] = {
{ "Ah", "<Aleph>", 0x2135 },
{ "Im", "<Im>", 0x2111 },
{ "Re", "<Re>", 0x211c },
- { "wp", "P", 0x2118 },
+ { "wp", "p", 0x2118 },
{ "pd", "<del>", 0x2202 },
{ "-h", "/h", 0x210f },
{ "hbar", "/h", 0x210f },
@@ -287,6 +281,7 @@ static struct ln lines[] = {
{ "ho", ",", 0x02db },
{ "ha", "^", 0x005e },
{ "ti", "~", 0x007e },
+ { "u02DC", "~", 0x02dc },
/* Accented letters. */
{ "'A", "'\bA", 0x00c1 },
@@ -294,11 +289,13 @@ static struct ln lines[] = {
{ "'I", "'\bI", 0x00cd },
{ "'O", "'\bO", 0x00d3 },
{ "'U", "'\bU", 0x00da },
+ { "'Y", "'\bY", 0x00dd },
{ "'a", "'\ba", 0x00e1 },
{ "'e", "'\be", 0x00e9 },
{ "'i", "'\bi", 0x00ed },
{ "'o", "'\bo", 0x00f3 },
{ "'u", "'\bu", 0x00fa },
+ { "'y", "'\by", 0x00fd },
{ "`A", "`\bA", 0x00c0 },
{ "`E", "`\bE", 0x00c8 },
{ "`I", "`\bI", 0x00cc },
@@ -359,7 +356,7 @@ static struct ln lines[] = {
{ "Eu", "EUR", 0x20ac },
{ "eu", "EUR", 0x20ac },
{ "Ye", "=\bY", 0x00a5 },
- { "Po", "GBP", 0x00a3 },
+ { "Po", "-\bL", 0x00a3 },
{ "Cs", "o\bx", 0x00a4 },
{ "Fn", ",\bf", 0x0192 },
@@ -460,7 +457,7 @@ mchars_spec2cp(const char *p, size_t sz)
end = p + sz;
ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end));
- return ln != NULL ? ln->unicode : sz == 1 ? (unsigned char)*p : -1;
+ return ln != NULL ? ln->unicode : -1;
}
int
@@ -490,10 +487,8 @@ mchars_spec2str(const char *p, size_t sz, size_t *rsz)
end = p + sz;
ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end));
- if (ln == NULL) {
- *rsz = 1;
- return sz == 1 ? p : NULL;
- }
+ if (ln == NULL)
+ return NULL;
*rsz = strlen(ln->ascii);
return ln->ascii;
diff --git a/configure b/configure
index 1ccc37dc0cdc..5507de7021b8 100755
--- a/configure
+++ b/configure
@@ -1,8 +1,8 @@
#!/bin/sh
#
-# $Id: configure,v 1.66 2018/07/31 15:34:00 schwarze Exp $
+# $Id: configure,v 1.70 2019/03/06 16:04:31 schwarze Exp $
#
-# Copyright (c) 2014,2015,2016,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
+# Copyright (c) 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -37,6 +37,7 @@ SOURCEDIR=`dirname "$0"`
MANPATH_BASE="/usr/share/man:/usr/X11R6/man"
MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man"
+OSENUM=
OSNAME=
UTF8_LOCALE=
@@ -64,6 +65,7 @@ HAVE_FTS_COMPARE_CONST=
HAVE_GETLINE=
HAVE_GETSUBOPT=
HAVE_ISBLANK=
+HAVE_LESS_T=
HAVE_MKDTEMP=
HAVE_NANOSLEEP=
HAVE_NTOHL=
@@ -90,6 +92,9 @@ HAVE_SYS_ENDIAN=
HAVE_VASPRINTF=
HAVE_WCHAR=
+NEED_GNU_SOURCE=0
+NEED_OPENBSD_SOURCE=0
+
PREFIX="/usr/local"
BINDIR=
SBINDIR=
@@ -154,31 +159,34 @@ ismanual() {
# In case of failure, do not decide anything yet.
# Arguments: test file name, test var name, additional CFLAGS
singletest() {
+ n=${1}${3}${4}
cat 1>&3 << __HEREDOC__
-testing ${1}${3} ...
-${COMP} -o test-${1} test-${1}.c ${3}
+testing ${n} ...
+${COMP} -o test-${1} test-${1}.c ${3} ${4}
__HEREDOC__
- if ${COMP} -o "test-${1}" "${SOURCEDIR}/test-${1}.c" ${3} 1>&3 2>&3
+ if ${COMP} -o "test-${1}" "${SOURCEDIR}/test-${1}.c" ${3} ${4} 1>&3 2>&3
then
- echo "partial result of ${1}${3}: ${CC} succeeded" 1>&3
+ echo "partial result of ${n}: ${CC} succeeded" 1>&3
else
- echo "result of ${1}${3}: ${CC} failed with exit status $?" 1>&3
- echo "result of compiling ${1}${3}: no" 1>&3
+ echo "result of ${n}: ${CC} failed with exit status $?" 1>&3
+ echo "result of compiling ${n}: no" 1>&3
echo 1>&3
return 1
fi
if ./test-${1} 1>&3 2>&3; then
- echo "tested ${1}${3}: yes" 1>&2
- echo "result of running ${1}${3}: yes" 1>&3
+ echo "tested ${n}: yes" 1>&2
+ echo "result of running ${n}: yes" 1>&3
echo 1>&3
eval HAVE_${2}=1
+ [ "X$3" = "X-D_GNU_SOURCE" ] && NEED_GNU_SOURCE=1
+ [ "X$3" = "X-D_OPENBSD_SOURCE" ] && NEED_OPENBSD_SOURCE=1
rm "test-${1}"
return 0
else
- echo "result of ${1}${3}: execution failed with exit status $?" 1>&3
- echo "result of running ${1}${3}: no" 1>&3
+ echo "result of ${n}: execution failed with exit status $?" 1>&3
+ echo "result of running ${n}: no" 1>&3
echo 1>&3
rm "test-${1}"
return 1
@@ -191,8 +199,8 @@ __HEREDOC__
runtest() {
eval _manual=\${HAVE_${2}}
ismanual "${1}" "${2}" "${_manual}" && return 0
- singletest "${1}" "${2}" "${3}" && return 0
- echo "tested ${1}${3}: no" 1>&2
+ singletest "${1}" "${2}" "${3}" "${4}" && return 0
+ echo "tested ${1}${3}${4}: no" 1>&2
eval HAVE_${2}=0
return 1
}
@@ -213,28 +221,52 @@ get_locale() {
return 0;
}
+# --- operating system -------------------------------------------------
+
+if [ -n "${OSENUM}" ]; then
+ echo "OSENUM specified manually: ${OSENUM}" 1>&2
+ echo "OSENUM specified manually: ${OSENUM}" 1>&3
+else
+ OSDETECT=`uname`
+ if [ "X${OSDETECT}" = "XNetBSD" ]; then
+ OSENUM=MANDOC_OS_NETBSD
+ elif [ "X${OSDETECT}" = "XOpenBSD" ]; then
+ OSENUM=MANDOC_OS_OPENBSD
+ else
+ OSENUM=MANDOC_OS_OTHER
+ fi
+ echo "tested operating system: ${OSDETECT} -> OSENUM=${OSENUM}" 1>&2
+ echo "tested operating system: ${OSDETECT} -> OSENUM=${OSENUM}" 1>&3
+ unset OSDETECT
+fi
+echo 1>&3
+
# --- compiler options -------------------------------------------------
+DEFCFLAGS="-g -W -Wall -Wmissing-prototypes -Wstrict-prototypes -Wwrite-strings -Wno-unused-parameter"
+
if [ -n "${CFLAGS}" ]; then
- COMP="${CC} ${CFLAGS}"
- echo "selected CFLAGS=\"${CFLAGS}\" (manual)" 1>&2
- echo "selected CFLAGS=\"${CFLAGS}\" (manual)" 1>&3
- echo 1>&3
-else
- CFLAGS="-g -W -Wall -Wmissing-prototypes -Wstrict-prototypes"
- CFLAGS="${CFLAGS} -Wwrite-strings -Wno-unused-parameter"
COMP="${CC} ${CFLAGS} -Wno-unused -Werror"
- echo -n "tested ${CC} -W: " 1>&2
- echo -n "testing ${CC} -W: " 1>&3
- runtest noop WFLAG || true
- if [ "${HAVE_WFLAG}" -eq 0 ]; then
- CFLAGS="-g"
- COMP="${CC} ${CFLAGS}"
- fi
- echo "selected CFLAGS=\"${CFLAGS}\"" 1>&2
- echo "selected CFLAGS=\"${CFLAGS}\"" 1>&3
- echo 1>&3
+else
+ COMP="${CC} ${DEFCFLAGS} -Wno-unused -Werror"
fi
+echo -n "tested ${CC} -W: " 1>&2
+echo -n "testing ${CC} -W: " 1>&3
+runtest noop WFLAG || true
+
+if [ -n "${CFLAGS}" ]; then
+ echo "CFLAGS specified manually:" 1>&3
+elif [ ${HAVE_WFLAG} -eq 0 ]; then
+ CFLAGS="-g"
+else
+ CFLAGS="${DEFCFLAGS}"
+fi
+echo "selected CFLAGS=\"${CFLAGS}\"" 1>&2
+echo "selected CFLAGS=\"${CFLAGS}\"" 1>&3
+echo 1>&3
+
+COMP="${CC} ${CFLAGS}"
+[ ${HAVE_WFLAG} -eq 0 ] || COMP="${COMP} -Wno-unused -Werror"
if [ -n "${STATIC}" ]; then
echo "selected STATIC=\"${STATIC}\" (manual)" 1>&2
@@ -257,7 +289,8 @@ runtest be32toh SYS_ENDIAN -DSYS_ENDIAN || true
runtest EFTYPE EFTYPE || true
runtest err ERR || true
runtest getline GETLINE || true
-runtest getsubopt GETSUBOPT || true
+singletest getsubopt GETSUBOPT || \
+ runtest getsubopt GETSUBOPT -D_GNU_SOURCE || true
runtest isblank ISBLANK || true
runtest mkdtemp MKDTEMP || true
runtest ntohl NTOHL || true
@@ -266,19 +299,25 @@ runtest PATH_MAX PATH_MAX || true
runtest pledge PLEDGE || true
runtest sandbox_init SANDBOX_INIT || true
runtest progname PROGNAME || true
-runtest reallocarray REALLOCARRAY || true
-runtest recallocarray RECALLOCARRAY || true
+singletest reallocarray REALLOCARRAY || \
+ runtest reallocarray REALLOCARRAY -D_OPENBSD_SOURCE || true
+singletest recallocarray RECALLOCARRAY || \
+ runtest recallocarray RECALLOCARRAY -D_OPENBSD_SOURCE || true
runtest rewb-bsd REWB_BSD || true
runtest rewb-sysv REWB_SYSV || true
-runtest strcasestr STRCASESTR || true
+singletest strcasestr STRCASESTR || \
+ runtest strcasestr STRCASESTR -D_GNU_SOURCE || true
runtest stringlist STRINGLIST || true
runtest strlcat STRLCAT || true
runtest strlcpy STRLCPY || true
runtest strndup STRNDUP || true
-runtest strptime STRPTIME || true
+singletest strptime STRPTIME || \
+ runtest strptime STRPTIME -D_GNU_SOURCE || true
runtest strsep STRSEP || true
-runtest strtonum STRTONUM || true
-runtest vasprintf VASPRINTF || true
+singletest strtonum STRTONUM || \
+ runtest strtonum STRTONUM -D_OPENBSD_SOURCE || true
+singletest vasprintf VASPRINTF || \
+ runtest vasprintf VASPRINTF -D_GNU_SOURCE || true
if [ ${HAVE_ENDIAN} -eq 0 -a \
${HAVE_SYS_ENDIAN} -eq 0 -a \
@@ -296,9 +335,25 @@ else
runtest fts FTS || true
fi
+if ismanual "less -T" LESS_T ${HAVE_LESS_T}; then
+ :
+elif less -ET /dev/null test-noop.c 1>/dev/null 2>&3; then
+ HAVE_LESS_T=1
+ echo "tested less -T: yes" 1>&2
+ echo "tested less -T: yes" 1>&3
+ echo 1>&3
+else
+ HAVE_LESS_T=0
+ echo "tested less -T: no" 1>&2
+ echo "tested less -T: no" 1>&3
+ echo 1>&3
+fi
+
# --- wide character and locale support ---
if get_locale; then
- runtest wchar WCHAR -DUTF8_LOCALE=\"${UTF8_LOCALE}\" || true
+ singletest wchar WCHAR -DUTF8_LOCALE=\"${UTF8_LOCALE}\" || \
+ runtest wchar WCHAR -D_GNU_SOURCE \
+ -DUTF8_LOCALE=\"${UTF8_LOCALE}\" || true
else
HAVE_WCHAR=0
echo "tested wchar: no (no UTF8_LOCALE)" 1>&2
@@ -383,12 +438,11 @@ cat << __HEREDOC__
#define __attribute__(x)
#endif
-#if defined(__linux__) || defined(__MINT__)
-#define _GNU_SOURCE /* See test-*.c what needs this. */
-#endif
-
__HEREDOC__
+[ ${NEED_GNU_SOURCE} -eq 0 ] || echo "#define _GNU_SOURCE"
+[ ${NEED_OPENBSD_SOURCE} -eq 0 ] || echo "#define _OPENBSD_SOURCE"
+
[ ${HAVE_GETLINE} -eq 0 -o \
${HAVE_REALLOCARRAY} -eq 0 -o ${HAVE_RECALLOCARRAY} -eq 0 -o \
${HAVE_STRLCAT} -eq 0 -o ${HAVE_STRLCPY} -eq 0 -o \
@@ -401,6 +455,7 @@ echo
echo "#define MAN_CONF_FILE \"/etc/${MANM_MANCONF}\""
echo "#define MANPATH_BASE \"${MANPATH_BASE}\""
echo "#define MANPATH_DEFAULT \"${MANPATH_DEFAULT}\""
+echo "#define OSENUM ${OSENUM}"
[ -n "${OSNAME}" ] && echo "#define OSNAME \"${OSNAME}\""
[ -n "${UTF8_LOCALE}" ] && echo "#define UTF8_LOCALE \"${UTF8_LOCALE}\""
[ -n "${HOMEBREWDIR}" ] && echo "#define HOMEBREWDIR \"${HOMEBREWDIR}\""
@@ -422,6 +477,7 @@ cat << __HEREDOC__
#define HAVE_GETLINE ${HAVE_GETLINE}
#define HAVE_GETSUBOPT ${HAVE_GETSUBOPT}
#define HAVE_ISBLANK ${HAVE_ISBLANK}
+#define HAVE_LESS_T ${HAVE_LESS_T}
#define HAVE_MKDTEMP ${HAVE_MKDTEMP}
#define HAVE_NTOHL ${HAVE_NTOHL}
#define HAVE_PLEDGE ${HAVE_PLEDGE}
diff --git a/configure.local.example b/configure.local.example
index 82fc2a2c28e5..4a456aade7c3 100644
--- a/configure.local.example
+++ b/configure.local.example
@@ -1,6 +1,6 @@
-# $Id: configure.local.example,v 1.34 2018/07/31 15:34:00 schwarze Exp $
+# $Id: configure.local.example,v 1.36 2019/03/06 10:18:58 schwarze Exp $
#
-# Copyright (c) 2014,2015,2016,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
+# Copyright (c) 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -67,6 +67,17 @@ MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man"
MANPATH_BASE="/usr/share/man:/usr/X11R6/man"
+# When man(1) is called with the -S option and no manual page is
+# found matching the requested name and the requested architecture,
+# it tries to figure out whether the requested architecture is valid
+# for the present operating system. Normally, ./configure detects
+# the operating system using uname(1). If that fails or is not
+# desired, either of the following lines can be used:
+
+OSENUM=MANDOC_OS_NETBSD
+OSENUM=MANDOC_OS_OPENBSD
+OSENUM=MANDOC_OS_OTHER
+
# In manual pages written in the mdoc(7) language, the operating system
# version is displayed in the page footer line. If an operating system
# is specified as an argument to the .Os macro, that is always used.
@@ -77,7 +88,7 @@ MANPATH_BASE="/usr/share/man:/usr/X11R6/man"
# If you do not want uname(3) to be called but instead want a fixed
# string to be used, use the following line:
-OSNAME="OpenBSD 6.3"
+OSNAME="OpenBSD 6.5"
# The following installation directories are used.
# It is possible to set only one or a few of these variables,
@@ -293,6 +304,7 @@ HAVE_FTS_COMPARE_CONST=0 # Setting this implies HAVE_FTS=1.
HAVE_GETLINE=0
HAVE_GETSUBOPT=0
HAVE_ISBLANK=0
+HAVE_LESS_T=0
HAVE_MKDTEMP=0
HAVE_NTOHL=0
HAVE_O_DIRECTORY=0
diff --git a/dbm.c b/dbm.c
index 4aedf66d136f..f6b1259ef5ad 100644
--- a/dbm.c
+++ b/dbm.c
@@ -1,4 +1,4 @@
-/* $Id: dbm.c,v 1.5 2016/10/18 22:27:25 schwarze Exp $ */
+/* $Id: dbm.c,v 1.6 2018/11/19 19:22:07 schwarze Exp $ */
/*
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -151,17 +151,17 @@ dbm_page_get(int32_t ip)
assert(ip < npages);
res.name = dbm_get(pages[ip].name);
if (res.name == NULL)
- res.name = "(NULL)";
+ res.name = "(NULL)\0";
res.sect = dbm_get(pages[ip].sect);
if (res.sect == NULL)
- res.sect = "(NULL)";
+ res.sect = "(NULL)\0";
res.arch = pages[ip].arch ? dbm_get(pages[ip].arch) : NULL;
res.desc = dbm_get(pages[ip].desc);
if (res.desc == NULL)
res.desc = "(NULL)";
res.file = dbm_get(pages[ip].file);
if (res.file == NULL)
- res.file = " (NULL)";
+ res.file = " (NULL)\0";
res.addr = dbm_addr(pages + ip);
return &res;
}
diff --git a/demandoc.c b/demandoc.c
index 8b202ab023a0..57d0cc5f4120 100644
--- a/demandoc.c
+++ b/demandoc.c
@@ -1,4 +1,4 @@
-/* $Id: demandoc.c,v 1.29 2017/06/24 14:38:32 schwarze Exp $ */
+/* $Id: demandoc.c,v 1.33 2019/03/03 11:01:15 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -29,6 +29,7 @@
#include "roff.h"
#include "man.h"
#include "mdoc.h"
+#include "mandoc_parse.h"
static void pline(int, int *, int *, int);
static void pman(const struct roff_node *, int *, int *, int);
@@ -78,8 +79,8 @@ main(int argc, char *argv[])
argv += optind;
mchars_alloc();
- mp = mparse_alloc(MPARSE_SO, MANDOCERR_MAX, NULL,
- MANDOC_OS_OTHER, NULL);
+ mp = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1 |
+ MPARSE_VALIDATE, MANDOC_OS_OTHER, NULL);
assert(mp);
if (argc < 1)
@@ -109,24 +110,19 @@ usage(void)
static void
pmandoc(struct mparse *mp, int fd, const char *fn, int list)
{
- struct roff_man *man;
+ struct roff_meta *meta;
int line, col;
mparse_readfd(mp, fd, fn);
close(fd);
- mparse_result(mp, &man, NULL);
+ meta = mparse_result(mp);
line = 1;
col = 0;
- if (man == NULL)
- return;
- if (man->macroset == MACROSET_MDOC) {
- mdoc_validate(man);
- pmdoc(man->first->child, &line, &col, list);
- } else {
- man_validate(man);
- pman(man->first->child, &line, &col, list);
- }
+ if (meta->macroset == MACROSET_MDOC)
+ pmdoc(meta->first->child, &line, &col, list);
+ else
+ pman(meta->first->child, &line, &col, list);
if ( ! list)
putchar('\n');
diff --git a/eqn.c b/eqn.c
index 01601a713734..3d63382ab31b 100644
--- a/eqn.c
+++ b/eqn.c
@@ -1,7 +1,7 @@
-/* $Id: eqn.c,v 1.78 2017/07/15 16:26:17 schwarze Exp $ */
+/* $Id: eqn.c,v 1.83 2018/12/14 06:33:14 schwarze Exp $ */
/*
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2015, 2017, 2018 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
@@ -30,8 +30,9 @@
#include "mandoc_aux.h"
#include "mandoc.h"
#include "roff.h"
+#include "eqn.h"
#include "libmandoc.h"
-#include "libroff.h"
+#include "eqn_parse.h"
#define EQN_NEST_MAX 128 /* maximum nesting of defines */
#define STRNEQ(p1, sz1, p2, sz2) \
@@ -284,6 +285,13 @@ enum parse_mode {
MODE_TOK
};
+struct eqn_def {
+ char *key;
+ size_t keysz;
+ char *val;
+ size_t valsz;
+};
+
static struct eqn_box *eqn_box_alloc(struct eqn_node *, struct eqn_box *);
static struct eqn_box *eqn_box_makebinary(struct eqn_node *,
struct eqn_box *);
@@ -295,12 +303,11 @@ static void eqn_undef(struct eqn_node *);
struct eqn_node *
-eqn_alloc(struct mparse *parse)
+eqn_alloc(void)
{
struct eqn_node *ep;
ep = mandoc_calloc(1, sizeof(*ep));
- ep->parse = parse;
ep->gsize = EQN_DEFSIZE;
return ep;
}
@@ -399,7 +406,7 @@ eqn_next(struct eqn_node *ep, enum parse_mode mode)
ep->end = strchr(ep->start + 1, *ep->start);
ep->start++; /* Skip opening quote. */
if (ep->end == NULL) {
- mandoc_msg(MANDOCERR_ARG_QUOTE, ep->parse,
+ mandoc_msg(MANDOCERR_ARG_QUOTE,
ep->node->line, ep->node->pos, NULL);
ep->end = strchr(ep->start, '\0');
}
@@ -420,7 +427,7 @@ eqn_next(struct eqn_node *ep, enum parse_mode mode)
if ((def = eqn_def_find(ep)) == NULL)
break;
if (++lim > EQN_NEST_MAX) {
- mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse,
+ mandoc_msg(MANDOCERR_ROFFLOOP,
ep->node->line, ep->node->pos, NULL);
return EQN_TOK_EOF;
}
@@ -468,6 +475,8 @@ eqn_next(struct eqn_node *ep, enum parse_mode mode)
void
eqn_box_free(struct eqn_box *bp)
{
+ if (bp == NULL)
+ return;
if (bp->first)
eqn_box_free(bp->first);
@@ -482,6 +491,16 @@ eqn_box_free(struct eqn_box *bp)
free(bp);
}
+struct eqn_box *
+eqn_box_new(void)
+{
+ struct eqn_box *bp;
+
+ bp = mandoc_calloc(1, sizeof(*bp));
+ bp->expectargs = UINT_MAX;
+ return bp;
+}
+
/*
* Allocate a box as the last child of the parent node.
*/
@@ -490,10 +509,9 @@ eqn_box_alloc(struct eqn_node *ep, struct eqn_box *parent)
{
struct eqn_box *bp;
- bp = mandoc_calloc(1, sizeof(struct eqn_box));
+ bp = eqn_box_new();
bp->parent = parent;
bp->parent->args++;
- bp->expectargs = UINT_MAX;
bp->font = bp->parent->font;
bp->size = ep->gsize;
@@ -542,7 +560,7 @@ static void
eqn_delim(struct eqn_node *ep)
{
if (ep->end[0] == '\0' || ep->end[1] == '\0') {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "delim");
if (ep->end[0] != '\0')
ep->end++;
@@ -569,7 +587,7 @@ eqn_undef(struct eqn_node *ep)
struct eqn_def *def;
if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF) {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "undef");
return;
}
@@ -588,7 +606,7 @@ eqn_def(struct eqn_node *ep)
int i;
if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF) {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "define");
return;
}
@@ -617,7 +635,7 @@ eqn_def(struct eqn_node *ep)
}
if (eqn_next(ep, MODE_QUOTED) == EQN_TOK_EOF) {
- mandoc_vmsg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "define %s", def->key);
free(def->key);
free(def->val);
@@ -666,7 +684,7 @@ next_tok:
case EQN_TOK_TDEFINE:
if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF ||
eqn_next(ep, MODE_QUOTED) == EQN_TOK_EOF)
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "tdefine");
break;
case EQN_TOK_DELIM:
@@ -674,8 +692,8 @@ next_tok:
break;
case EQN_TOK_GFONT:
if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF)
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
case EQN_TOK_MARK:
case EQN_TOK_LINEUP:
@@ -690,8 +708,8 @@ next_tok:
case EQN_TOK_DOT:
case EQN_TOK_DOTDOT:
if (parent->last == NULL) {
- mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_EQN_NOBOX, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
cur = eqn_box_alloc(ep, parent);
cur->type = EQN_TEXT;
cur->text = mandoc_strdup("");
@@ -735,8 +753,8 @@ next_tok:
case EQN_TOK_DOWN:
case EQN_TOK_UP:
if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF)
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
case EQN_TOK_FAT:
case EQN_TOK_ROMAN:
@@ -773,14 +791,14 @@ next_tok:
case EQN_TOK_GSIZE:
/* Accept two values: integral size and a single. */
if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
size = mandoc_strntoi(ep->start, ep->toksz, 10);
if (-1 == size) {
- mandoc_msg(MANDOCERR_IT_NONUM, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_IT_NONUM, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
if (EQN_TOK_GSIZE == tok) {
@@ -804,8 +822,8 @@ next_tok:
* and keep on reading.
*/
if (parent->last == NULL) {
- mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_EQN_NOBOX, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
cur = eqn_box_alloc(ep, parent);
cur->type = EQN_TEXT;
cur->text = mandoc_strdup("");
@@ -871,8 +889,8 @@ next_tok:
* rebalance and continue reading.
*/
if (parent->last == NULL) {
- mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_EQN_NOBOX, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
cur = eqn_box_alloc(ep, parent);
cur->type = EQN_TEXT;
cur->text = mandoc_strdup("");
@@ -898,16 +916,16 @@ next_tok:
cur->left != NULL))
break;
if (cur == NULL) {
- mandoc_msg(MANDOCERR_BLK_NOTOPEN, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_BLK_NOTOPEN, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
parent = cur;
if (EQN_TOK_RIGHT == tok) {
if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {
mandoc_msg(MANDOCERR_REQ_EMPTY,
- ep->parse, ep->node->line,
- ep->node->pos, eqn_toks[tok]);
+ ep->node->line, ep->node->pos,
+ "%s", eqn_toks[tok]);
break;
}
/* Handling depends on right/left. */
@@ -941,8 +959,8 @@ next_tok:
parent = parent->parent;
if (EQN_TOK_LEFT == tok &&
eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
parent = eqn_box_alloc(ep, parent);
@@ -975,8 +993,8 @@ next_tok:
if (cur->type == EQN_PILE)
break;
if (cur == NULL) {
- mandoc_msg(MANDOCERR_IT_STRAY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_IT_STRAY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
parent = eqn_box_alloc(ep, cur);
@@ -1092,6 +1110,9 @@ eqn_free(struct eqn_node *p)
{
int i;
+ if (p == NULL)
+ return;
+
for (i = 0; i < (int)p->defsz; i++) {
free(p->defs[i].key);
free(p->defs[i].val);
diff --git a/eqn.h b/eqn.h
new file mode 100644
index 000000000000..c7c7aa15a7c6
--- /dev/null
+++ b/eqn.h
@@ -0,0 +1,72 @@
+/* $Id: eqn.h,v 1.1 2018/12/13 05:23:38 schwarze Exp $ */
+/*
+ * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
+ *
+ * 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.
+ *
+ * Public data types for eqn(7) syntax trees.
+ */
+
+enum eqn_boxt {
+ EQN_TEXT, /* Text, e.g. number, variable, operator, ... */
+ EQN_SUBEXPR, /* Nested eqn(7) subexpression. */
+ EQN_LIST, /* List, for example in braces. */
+ EQN_PILE, /* Vertical pile. */
+ EQN_MATRIX /* List of columns. */
+};
+
+enum eqn_fontt {
+ EQNFONT_NONE = 0,
+ EQNFONT_ROMAN,
+ EQNFONT_BOLD,
+ EQNFONT_FAT,
+ EQNFONT_ITALIC,
+ EQNFONT__MAX
+};
+
+enum eqn_post {
+ EQNPOS_NONE = 0,
+ EQNPOS_SUP,
+ EQNPOS_SUBSUP,
+ EQNPOS_SUB,
+ EQNPOS_TO,
+ EQNPOS_FROM,
+ EQNPOS_FROMTO,
+ EQNPOS_OVER,
+ EQNPOS_SQRT,
+ EQNPOS__MAX
+};
+
+ /*
+ * A "box" is a parsed mathematical expression as defined by the eqn.7
+ * grammar.
+ */
+struct eqn_box {
+ struct eqn_box *parent;
+ struct eqn_box *prev;
+ struct eqn_box *next;
+ struct eqn_box *first; /* First child node. */
+ struct eqn_box *last; /* Last child node. */
+ char *text; /* Text (or NULL). */
+ char *left; /* Left-hand fence. */
+ char *right; /* Right-hand fence. */
+ char *top; /* Symbol above. */
+ char *bottom; /* Symbol below. */
+ size_t expectargs; /* Maximal number of arguments. */
+ size_t args; /* Actual number of arguments. */
+ int size; /* Font size. */
+#define EQN_DEFSIZE INT_MIN
+ enum eqn_boxt type; /* Type of node. */
+ enum eqn_fontt font; /* Font in this box. */
+ enum eqn_post pos; /* Position of the next box. */
+};
diff --git a/eqn_html.c b/eqn_html.c
index 51f144234275..1fe41ecbfac5 100644
--- a/eqn_html.c
+++ b/eqn_html.c
@@ -1,4 +1,4 @@
-/* $Id: eqn_html.c,v 1.17 2017/07/14 13:32:35 schwarze Exp $ */
+/* $Id: eqn_html.c,v 1.18 2018/12/13 05:23:38 schwarze Exp $ */
/*
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -26,6 +26,7 @@
#include <string.h>
#include "mandoc.h"
+#include "eqn.h"
#include "out.h"
#include "html.h"
diff --git a/eqn_parse.h b/eqn_parse.h
new file mode 100644
index 000000000000..a2a4e6fd7d37
--- /dev/null
+++ b/eqn_parse.h
@@ -0,0 +1,48 @@
+/* $Id: eqn_parse.h,v 1.3 2018/12/14 06:33:14 schwarze Exp $ */
+/*
+ * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2014, 2017, 2018 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.
+ *
+ * External interface of the eqn(7) parser.
+ * For use in the roff(7) and eqn(7) parsers only.
+ */
+
+struct roff_node;
+struct eqn_box;
+struct eqn_def;
+
+struct eqn_node {
+ struct roff_node *node; /* Syntax tree of this equation. */
+ struct eqn_def *defs; /* Array of definitions. */
+ char *data; /* Source code of this equation. */
+ char *start; /* First byte of the current token. */
+ char *end; /* First byte of the next token. */
+ size_t defsz; /* Number of definitions. */
+ size_t sz; /* Length of the source code. */
+ size_t toksz; /* Length of the current token. */
+ int gsize; /* Default point size. */
+ int delim; /* In-line delimiters enabled. */
+ char odelim; /* In-line opening delimiter. */
+ char cdelim; /* In-line closing delimiter. */
+};
+
+
+struct eqn_node *eqn_alloc(void);
+struct eqn_box *eqn_box_new(void);
+void eqn_box_free(struct eqn_box *);
+void eqn_free(struct eqn_node *);
+void eqn_parse(struct eqn_node *);
+void eqn_read(struct eqn_node *, const char *);
+void eqn_reset(struct eqn_node *);
diff --git a/eqn_term.c b/eqn_term.c
index 669c3c56cff7..3e27233b30f9 100644
--- a/eqn_term.c
+++ b/eqn_term.c
@@ -1,4 +1,4 @@
-/* $Id: eqn_term.c,v 1.17 2017/08/23 21:56:20 schwarze Exp $ */
+/* $Id: eqn_term.c,v 1.19 2018/12/13 05:23:38 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -25,7 +25,7 @@
#include <stdlib.h>
#include <string.h>
-#include "mandoc.h"
+#include "eqn.h"
#include "out.h"
#include "term.h"
@@ -106,7 +106,7 @@ eqn_box(struct termp *p, const struct eqn_box *bp)
/* Special box types. */
if (bp->pos == EQNPOS_SQRT) {
- term_word(p, "sqrt");
+ term_word(p, "\\(sr");
if (bp->first != NULL) {
p->flags |= TERMP_NOSPACE;
eqn_box(p, bp->first);
diff --git a/gmdiff b/gmdiff
index 65cf353daa0c..69431f703aaf 100644
--- a/gmdiff
+++ b/gmdiff
@@ -36,7 +36,7 @@ elif [ "X$1" = "X-u" ]; then
MOPT="-Ios=OpenBSD -Wall -Tutf8 $MOPT"
COLPIPE="cat"
else
- ROFF="groff -et -ww -mtty-char -Tascii -P -c"
+ ROFF="groff -ket -ww -mtty-char -Tascii -P -c"
MOPT="-Ios=OpenBSD -Wall -Tascii $MOPT"
COLPIPE="cat"
fi
@@ -51,7 +51,7 @@ while [ -n "$1" ]; do
for i in roff mandoc; do
[ -s /tmp/$i.err ] && echo "$i errors:" && cat /tmp/$i.err
done
- diff -au /tmp/roff.out /tmp/mandoc.out 2>&1
+ diff -au $DIFFOPT /tmp/roff.out /tmp/mandoc.out 2>&1
done
exit 0
diff --git a/html.c b/html.c
index 70935dcd57e4..1302972a4e13 100644
--- a/html.c
+++ b/html.c
@@ -1,7 +1,7 @@
-/* $Id: html.c,v 1.238 2018/06/25 16:54:59 schwarze Exp $ */
+/* $Id: html.c,v 1.254 2019/03/03 13:02:11 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,6 +18,7 @@
#include "config.h"
#include <sys/types.h>
+#include <sys/stat.h>
#include <assert.h>
#include <ctype.h>
@@ -62,6 +63,7 @@ static const struct htmldata htmltags[TAG_MAX] = {
{"title", HTML_NLAROUND},
{"div", HTML_NLAROUND},
{"div", 0},
+ {"section", HTML_NLALL},
{"h1", HTML_NLAROUND},
{"h2", HTML_NLAROUND},
{"span", 0},
@@ -77,6 +79,7 @@ static const struct htmldata htmltags[TAG_MAX] = {
{"dl", HTML_NLALL | HTML_INDENT},
{"dt", HTML_NLAROUND},
{"dd", HTML_NLAROUND | HTML_INDENT},
+ {"p", HTML_NLAROUND | HTML_INDENT},
{"pre", HTML_NLALL | HTML_NOINDENT},
{"var", 0},
{"cite", 0},
@@ -107,6 +110,7 @@ static const struct htmldata htmltags[TAG_MAX] = {
/* Avoid duplicate HTML id= attributes. */
static struct ohash id_unique;
+static void html_reset_internal(struct html *);
static void print_byte(struct html *, char);
static void print_endword(struct html *);
static void print_indent(struct html *);
@@ -116,7 +120,6 @@ static void print_ctag(struct html *, struct tag *);
static int print_escape(struct html *, char);
static int print_encode(struct html *, const char *, const char *, int);
static void print_href(struct html *, const char *, const char *, int);
-static void print_metaf(struct html *, enum mandoc_esc);
void *
@@ -128,31 +131,32 @@ html_alloc(const struct manoutput *outopts)
h->tag = NULL;
h->style = outopts->style;
- h->base_man = outopts->man;
+ if ((h->base_man1 = outopts->man) == NULL)
+ h->base_man2 = NULL;
+ else if ((h->base_man2 = strchr(h->base_man1, ';')) != NULL)
+ *h->base_man2++ = '\0';
h->base_includes = outopts->includes;
if (outopts->fragment)
h->oflags |= HTML_FRAGMENT;
+ if (outopts->toc)
+ h->oflags |= HTML_TOC;
mandoc_ohash_init(&id_unique, 4, 0);
return h;
}
-void
-html_free(void *p)
+static void
+html_reset_internal(struct html *h)
{
struct tag *tag;
- struct html *h;
char *cp;
unsigned int slot;
- h = (struct html *)p;
while ((tag = h->tag) != NULL) {
h->tag = tag->next;
free(tag);
}
- free(h);
-
cp = ohash_first(&id_unique, &slot);
while (cp != NULL) {
free(cp);
@@ -162,6 +166,20 @@ html_free(void *p)
}
void
+html_reset(void *p)
+{
+ html_reset_internal(p);
+ mandoc_ohash_init(&id_unique, 4, 0);
+}
+
+void
+html_free(void *p)
+{
+ html_reset_internal(p);
+ free(p);
+}
+
+void
print_gen_head(struct html *h)
{
struct tag *t;
@@ -204,7 +222,7 @@ print_gen_head(struct html *h)
print_tagq(h, t);
}
-static void
+void
print_metaf(struct html *h, enum mandoc_esc deco)
{
enum htmlfont font;
@@ -222,12 +240,15 @@ print_metaf(struct html *h, enum mandoc_esc deco)
case ESCAPE_FONTBI:
font = HTMLFONT_BI;
break;
+ case ESCAPE_FONTCW:
+ font = HTMLFONT_CW;
+ break;
case ESCAPE_FONT:
case ESCAPE_FONTROMAN:
font = HTMLFONT_NONE;
break;
default:
- abort();
+ return;
}
if (h->metaf) {
@@ -249,11 +270,69 @@ print_metaf(struct html *h, enum mandoc_esc deco)
h->metaf = print_otag(h, TAG_B, "");
print_otag(h, TAG_I, "");
break;
+ case HTMLFONT_CW:
+ h->metaf = print_otag(h, TAG_SPAN, "c", "Li");
+ break;
default:
break;
}
}
+void
+html_close_paragraph(struct html *h)
+{
+ struct tag *t;
+
+ for (t = h->tag; t != NULL && t->closed == 0; t = t->next) {
+ switch(t->tag) {
+ case TAG_P:
+ case TAG_PRE:
+ print_tagq(h, t);
+ break;
+ case TAG_A:
+ print_tagq(h, t);
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+}
+
+/*
+ * ROFF_nf switches to no-fill mode, ROFF_fi to fill mode.
+ * TOKEN_NONE does not switch. The old mode is returned.
+ */
+enum roff_tok
+html_fillmode(struct html *h, enum roff_tok want)
+{
+ struct tag *t;
+ enum roff_tok had;
+
+ for (t = h->tag; t != NULL; t = t->next)
+ if (t->tag == TAG_PRE)
+ break;
+
+ had = t == NULL ? ROFF_fi : ROFF_nf;
+
+ if (want != had) {
+ switch (want) {
+ case ROFF_fi:
+ print_tagq(h, t);
+ break;
+ case ROFF_nf:
+ html_close_paragraph(h);
+ print_otag(h, TAG_PRE, "");
+ break;
+ case TOKEN_NONE:
+ break;
+ default:
+ abort();
+ }
+ }
+ return had;
+}
+
char *
html_make_id(const struct roff_node *n, int unique)
{
@@ -345,7 +424,6 @@ static int
print_encode(struct html *h, const char *p, const char *pend, int norecurse)
{
char numbuf[16];
- struct tag *t;
const char *seq;
size_t sz;
int c, len, breakline, nospace;
@@ -371,9 +449,7 @@ print_encode(struct html *h, const char *p, const char *pend, int norecurse)
if (breakline &&
(p >= pend || *p == ' ' || *p == ASCII_NBRSP)) {
- t = print_otag(h, TAG_DIV, "");
- print_text(h, "\\~");
- print_tagq(h, t);
+ print_otag(h, TAG_BR, "");
breakline = 0;
while (p < pend && (*p == ' ' || *p == ASCII_NBRSP))
p++;
@@ -393,22 +469,25 @@ print_encode(struct html *h, const char *p, const char *pend, int norecurse)
continue;
esc = mandoc_escape(&p, &seq, &len);
- if (ESCAPE_ERROR == esc)
- break;
-
switch (esc) {
case ESCAPE_FONT:
case ESCAPE_FONTPREV:
case ESCAPE_FONTBOLD:
case ESCAPE_FONTITALIC:
case ESCAPE_FONTBI:
+ case ESCAPE_FONTCW:
case ESCAPE_FONTROMAN:
- if (0 == norecurse)
+ if (0 == norecurse) {
+ h->flags |= HTML_NOSPACE;
print_metaf(h, esc);
+ h->flags &= ~HTML_NOSPACE;
+ }
continue;
case ESCAPE_SKIPCHAR:
h->flags |= HTML_SKIPCHAR;
continue;
+ case ESCAPE_ERROR:
+ continue;
default:
break;
}
@@ -433,6 +512,12 @@ print_encode(struct html *h, const char *p, const char *pend, int norecurse)
if (c <= 0)
continue;
break;
+ case ESCAPE_UNDEF:
+ c = *seq;
+ break;
+ case ESCAPE_DEVICE:
+ print_word(h, "html");
+ continue;
case ESCAPE_BREAK:
breakline = 1;
continue;
@@ -464,9 +549,21 @@ print_encode(struct html *h, const char *p, const char *pend, int norecurse)
static void
print_href(struct html *h, const char *name, const char *sec, int man)
{
+ struct stat sb;
const char *p, *pp;
+ char *filename;
+
+ if (man) {
+ pp = h->base_man1;
+ if (h->base_man2 != NULL) {
+ mandoc_asprintf(&filename, "%s.%s", name, sec);
+ if (stat(filename, &sb) == -1)
+ pp = h->base_man2;
+ free(filename);
+ }
+ } else
+ pp = h->base_includes;
- pp = man ? h->base_man : h->base_includes;
while ((p = strchr(pp, '%')) != NULL) {
print_encode(h, pp, p, 1);
if (man && p[1] == 'S') {
@@ -492,7 +589,7 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
struct tag *t;
const char *attr;
char *arg1, *arg2;
- int tflags;
+ int style_written, tflags;
tflags = htmltags[tag].flags;
@@ -502,6 +599,8 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
t = mandoc_malloc(sizeof(struct tag));
t->tag = tag;
t->next = h->tag;
+ t->refcnt = 0;
+ t->closed = 0;
h->tag = t;
} else
t = NULL;
@@ -532,7 +631,7 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
va_start(ap, fmt);
- while (*fmt != '\0') {
+ while (*fmt != '\0' && *fmt != 's') {
/* Parse attributes and arguments. */
@@ -548,10 +647,6 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
case 'i':
attr = "id";
break;
- case 's':
- attr = "style";
- arg2 = va_arg(ap, char *);
- break;
case '?':
attr = arg1;
arg1 = va_arg(ap, char *);
@@ -584,26 +679,33 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
print_encode(h, arg1, NULL, 1);
fmt++;
break;
- case 'T':
- print_encode(h, arg1, NULL, 1);
- print_word(h, "\" title=\"");
- print_encode(h, arg1, NULL, 1);
- fmt++;
- break;
default:
- if (arg2 == NULL)
- print_encode(h, arg1, NULL, 1);
- else {
- print_word(h, arg1);
- print_byte(h, ':');
- print_byte(h, ' ');
- print_word(h, arg2);
- print_byte(h, ';');
- }
+ print_encode(h, arg1, NULL, 1);
break;
}
print_byte(h, '"');
}
+
+ style_written = 0;
+ while (*fmt++ == 's') {
+ arg1 = va_arg(ap, char *);
+ arg2 = va_arg(ap, char *);
+ if (arg2 == NULL)
+ continue;
+ print_byte(h, ' ');
+ if (style_written == 0) {
+ print_word(h, "style=\"");
+ style_written = 1;
+ }
+ print_word(h, arg1);
+ print_byte(h, ':');
+ print_byte(h, ' ');
+ print_word(h, arg2);
+ print_byte(h, ';');
+ }
+ if (style_written)
+ print_byte(h, '"');
+
va_end(ap);
/* Accommodate for "well-formed" singleton escaping. */
@@ -631,33 +733,32 @@ print_ctag(struct html *h, struct tag *tag)
{
int tflags;
- /*
- * Remember to close out and nullify the current
- * meta-font and table, if applicable.
- */
- if (tag == h->metaf)
- h->metaf = NULL;
- if (tag == h->tblt)
- h->tblt = NULL;
-
- tflags = htmltags[tag->tag].flags;
-
- if (tflags & HTML_INDENT)
- h->indent--;
- if (tflags & HTML_NOINDENT)
- h->noindent--;
- if (tflags & HTML_NLEND)
- print_endline(h);
- print_indent(h);
- print_byte(h, '<');
- print_byte(h, '/');
- print_word(h, htmltags[tag->tag].name);
- print_byte(h, '>');
- if (tflags & HTML_NLAFTER)
- print_endline(h);
-
- h->tag = tag->next;
- free(tag);
+ if (tag->closed == 0) {
+ tag->closed = 1;
+ if (tag == h->metaf)
+ h->metaf = NULL;
+ if (tag == h->tblt)
+ h->tblt = NULL;
+
+ tflags = htmltags[tag->tag].flags;
+ if (tflags & HTML_INDENT)
+ h->indent--;
+ if (tflags & HTML_NOINDENT)
+ h->noindent--;
+ if (tflags & HTML_NLEND)
+ print_endline(h);
+ print_indent(h);
+ print_byte(h, '<');
+ print_byte(h, '/');
+ print_word(h, htmltags[tag->tag].name);
+ print_byte(h, '>');
+ if (tflags & HTML_NLAFTER)
+ print_endline(h);
+ }
+ if (tag->refcnt == 0) {
+ h->tag = tag->next;
+ free(tag);
+ }
}
void
@@ -717,6 +818,9 @@ print_text(struct html *h, const char *word)
h->metaf = print_otag(h, TAG_B, "");
print_otag(h, TAG_I, "");
break;
+ case HTMLFONT_CW:
+ h->metaf = print_otag(h, TAG_SPAN, "c", "Li");
+ break;
default:
print_indent(h);
break;
@@ -741,36 +845,33 @@ print_text(struct html *h, const char *word)
void
print_tagq(struct html *h, const struct tag *until)
{
- struct tag *tag;
+ struct tag *this, *next;
- while ((tag = h->tag) != NULL) {
- print_ctag(h, tag);
- if (until && tag == until)
- return;
+ for (this = h->tag; this != NULL; this = next) {
+ next = this == until ? NULL : this->next;
+ print_ctag(h, this);
}
}
+/*
+ * Close out all open elements up to but excluding suntil.
+ * Note that a paragraph just inside stays open together with it
+ * because paragraphs include subsequent phrasing content.
+ */
void
print_stagq(struct html *h, const struct tag *suntil)
{
- struct tag *tag;
+ struct tag *this, *next;
- while ((tag = h->tag) != NULL) {
- if (suntil && tag == suntil)
- return;
- print_ctag(h, tag);
+ for (this = h->tag; this != NULL; this = next) {
+ next = this->next;
+ if (this == suntil || (next == suntil &&
+ (this->tag == TAG_P || this->tag == TAG_PRE)))
+ break;
+ print_ctag(h, this);
}
}
-void
-print_paragraph(struct html *h)
-{
- struct tag *t;
-
- t = print_otag(h, TAG_DIV, "c", "Pp");
- print_tagq(h, t);
-}
-
/***********************************************************************
* Low level output functions.
diff --git a/html.h b/html.h
index 6d44a47383a7..a6bf89119057 100644
--- a/html.h
+++ b/html.h
@@ -1,7 +1,7 @@
-/* $Id: html.h,v 1.92 2018/06/25 16:54:59 schwarze Exp $ */
+/* $Id: html.h,v 1.102 2019/03/01 10:57:18 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2017, 2018, 2019 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -24,6 +24,7 @@ enum htmltag {
TAG_TITLE,
TAG_DIV,
TAG_IDIV,
+ TAG_SECTION,
TAG_H1,
TAG_H2,
TAG_SPAN,
@@ -39,6 +40,7 @@ enum htmltag {
TAG_DL,
TAG_DT,
TAG_DD,
+ TAG_P,
TAG_PRE,
TAG_VAR,
TAG_CITE,
@@ -72,11 +74,14 @@ enum htmlfont {
HTMLFONT_BOLD,
HTMLFONT_ITALIC,
HTMLFONT_BI,
+ HTMLFONT_CW,
HTMLFONT_MAX
};
struct tag {
struct tag *next;
+ int refcnt;
+ int closed;
enum htmltag tag;
};
@@ -87,12 +92,12 @@ struct html {
#define HTML_KEEP (1 << 2)
#define HTML_PREKEEP (1 << 3)
#define HTML_NONOSPACE (1 << 4) /* never add spaces */
-#define HTML_LITERAL (1 << 5) /* literal (e.g., <PRE>) context */
#define HTML_SKIPCHAR (1 << 6) /* skip the next character */
#define HTML_NOSPLIT (1 << 7) /* do not break line before .An */
#define HTML_SPLIT (1 << 8) /* break line before .An */
#define HTML_NONEWLINE (1 << 9) /* No line break in nofill mode. */
#define HTML_BUFFER (1 << 10) /* Collect a word to see if it fits. */
+#define HTML_TOCDONE (1 << 11) /* The TOC was already written. */
size_t indent; /* current output indentation level */
int noindent; /* indent disabled by <pre> */
size_t col; /* current output byte position */
@@ -101,7 +106,8 @@ struct html {
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 */
+ char *base_man1; /* bases for manpage href */
+ char *base_man2;
char *base_includes; /* base for include href */
char *style; /* style-sheet URI */
struct tag *metaf; /* current open font scope */
@@ -109,6 +115,7 @@ struct html {
enum htmlfont metac; /* current font mode */
int oflags; /* output options */
#define HTML_FRAGMENT (1 << 0) /* don't emit HTML/HEAD/BODY */
+#define HTML_TOC (1 << 1) /* emit a table of contents */
};
@@ -121,6 +128,7 @@ void roff_html_pre(struct html *, const struct roff_node *);
void print_gen_comment(struct html *, struct roff_node *);
void print_gen_decls(struct html *);
void print_gen_head(struct html *);
+void print_metaf(struct html *, enum mandoc_esc);
struct tag *print_otag(struct html *, enum htmltag, const char *, ...);
void print_tagq(struct html *, const struct tag *);
void print_stagq(struct html *, const struct tag *);
@@ -128,7 +136,8 @@ void print_text(struct html *, const char *);
void print_tblclose(struct html *);
void print_tbl(struct html *, const struct tbl_span *);
void print_eqn(struct html *, const struct eqn_box *);
-void print_paragraph(struct html *);
void print_endline(struct html *);
+void html_close_paragraph(struct html *);
+enum roff_tok html_fillmode(struct html *, enum roff_tok);
char *html_make_id(const struct roff_node *, int);
diff --git a/lib.c b/lib.c
index 0474924d735a..e377c1bced75 100644
--- a/lib.c
+++ b/lib.c
@@ -1,4 +1,4 @@
-/* $Id: lib.c,v 1.14 2017/06/24 14:38:32 schwarze Exp $ */
+/* $Id: lib.c,v 1.15 2018/12/13 11:55:46 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -17,12 +17,9 @@
#include "config.h"
#include <sys/types.h>
-
#include <string.h>
-#include "mandoc.h"
#include "roff.h"
-#include "mdoc.h"
#include "libmdoc.h"
#define LINE(x, y) \
diff --git a/lib.in b/lib.in
index 2e217ee77da4..b8dd87eb99f8 100644
--- a/lib.in
+++ b/lib.in
@@ -1,4 +1,4 @@
-/* $Id: lib.in,v 1.20 2017/08/20 02:30:27 schwarze Exp $ */
+/* $Id: lib.in,v 1.21 2019/03/04 17:35:21 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2009, 2012 Joerg Sonnenberger <joerg@netbsd.org>
@@ -29,6 +29,7 @@ LINE("libalias", "Packet Aliasing Library (libalias, \\-lalias)")
LINE("libarchive", "Streaming Archive Library (libarchive, \\-larchive)")
LINE("libarm", "ARM Architecture Library (libarm, \\-larm)")
LINE("libarm32", "ARM32 Architecture Library (libarm32, \\-larm32)")
+LINE("libbe", "Boot Environment Library (libbe, \\-lbe)")
LINE("libbluetooth", "Bluetooth Library (libbluetooth, \\-lbluetooth)")
LINE("libbsdxml", "eXpat XML parser library (libbsdxml, \\-lbsdxml)")
LINE("libbsm", "Basic Security Module Library (libbsm, \\-lbsm)")
diff --git a/libman.h b/libman.h
index 312093dd018c..ac960a685889 100644
--- a/libman.h
+++ b/libman.h
@@ -1,7 +1,7 @@
-/* $Id: libman.h,v 1.81 2017/04/29 12:45:41 schwarze Exp $ */
+/* $Id: libman.h,v 1.86 2018/12/31 10:04:39 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2015, 2018 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
@@ -16,6 +16,9 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+struct roff_node;
+struct roff_man;
+
#define MACRO_PROT_ARGS struct roff_man *man, \
enum roff_tok tok, \
int line, \
@@ -26,15 +29,14 @@
struct man_macro {
void (*fp)(MACRO_PROT_ARGS);
int flags;
-#define MAN_SCOPED (1 << 0) /* Optional next-line scope. */
-#define MAN_NSCOPED (1 << 1) /* Allowed in next-line element scope. */
-#define MAN_BSCOPE (1 << 2) /* Break next-line block scope. */
-#define MAN_JOIN (1 << 3) /* Join arguments together. */
+#define MAN_BSCOPED (1 << 0) /* Optional next-line block scope. */
+#define MAN_ESCOPED (1 << 1) /* Optional next-line element scope. */
+#define MAN_NSCOPED (1 << 2) /* Allowed in next-line element scope. */
+#define MAN_XSCOPE (1 << 3) /* Exit next-line block scope. */
+#define MAN_JOIN (1 << 4) /* Join arguments together. */
};
-extern const struct man_macro *const man_macros;
-
+const struct man_macro *man_macro(enum roff_tok);
-void man_node_validate(struct roff_man *);
-void man_state(struct roff_man *, struct roff_node *);
+void man_descope(struct roff_man *, int, int, char *);
void man_unscope(struct roff_man *, const struct roff_node *);
diff --git a/libmandoc.h b/libmandoc.h
index 9cc8cce4ecca..ff6f4692f062 100644
--- a/libmandoc.h
+++ b/libmandoc.h
@@ -1,7 +1,7 @@
-/* $Id: libmandoc.h,v 1.71 2018/04/09 22:27:04 schwarze Exp $ */
+/* $Id: libmandoc.h,v 1.77 2018/12/21 17:15:18 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013,2014,2015,2017,2018 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
@@ -16,31 +16,38 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-enum rofferr {
- ROFF_CONT, /* continue processing line */
- ROFF_RERUN, /* re-run roff interpreter with offset */
- ROFF_APPEND, /* re-run main parser, appending next line */
- ROFF_REPARSE, /* re-run main parser on the result */
- ROFF_SO, /* include another file */
- ROFF_IGN, /* ignore current line */
-};
+/*
+ * Return codes passed from the roff parser to the main parser.
+ */
+
+/* Main instruction: what to do with the returned line. */
+#define ROFF_IGN 0x000 /* Don't do anything with it. */
+#define ROFF_CONT 0x001 /* Give it to the high-level parser. */
+#define ROFF_RERUN 0x002 /* Re-run the roff parser with an offset. */
+#define ROFF_REPARSE 0x004 /* Recursively run the main parser on it. */
+#define ROFF_SO 0x008 /* Include the named file. */
+#define ROFF_MASK 0x00f /* Only one of these bits should be set. */
+
+/* Options for further parsing, to be OR'ed with the above. */
+#define ROFF_APPEND 0x010 /* Append the next line to this one. */
+#define ROFF_USERCALL 0x020 /* Start execution of a new macro. */
+#define ROFF_USERRET 0x040 /* Abort execution of the current macro. */
+#define ROFF_WHILE 0x100 /* Start a new .while loop. */
+#define ROFF_LOOPCONT 0x200 /* Iterate the current .while loop. */
+#define ROFF_LOOPEXIT 0x400 /* Exit the current .while loop. */
+#define ROFF_LOOPMASK 0xf00
+
struct buf {
- char *buf;
- size_t sz;
+ char *buf;
+ size_t sz;
+ struct buf *next;
};
-struct mparse;
struct roff;
struct roff_man;
-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)));
-char *mandoc_getarg(struct mparse *, char **, int, int *);
char *mandoc_normdate(struct roff_man *, char *, int, int);
int mandoc_eos(const char *, size_t);
int mandoc_strntoi(const char *, size_t, int);
@@ -57,17 +64,18 @@ int preconv_encode(const struct buf *, size_t *,
struct buf *, size_t *, int *);
void roff_free(struct roff *);
-struct roff *roff_alloc(struct mparse *, int);
+struct roff *roff_alloc(int);
void roff_reset(struct roff *);
void roff_man_free(struct roff_man *);
-struct roff_man *roff_man_alloc(struct roff *, struct mparse *,
- const char *, int);
+struct roff_man *roff_man_alloc(struct roff *, const char *, int);
void roff_man_reset(struct roff_man *);
-enum rofferr roff_parseln(struct roff *, int, struct buf *, int *);
+int roff_parseln(struct roff *, int, struct buf *, int *);
+void roff_userret(struct roff *);
void roff_endparse(struct roff *);
void roff_setreg(struct roff *, const char *, int, char sign);
int roff_getreg(struct roff *, const char *);
char *roff_strdup(const struct roff *, const char *);
+char *roff_getarg(struct roff *, char **, int, int *);
int roff_getcontrol(const struct roff *,
const char *, int *);
int roff_getformat(const struct roff *);
diff --git a/libmdoc.h b/libmdoc.h
index 57dff61b4aa3..ff29625194dc 100644
--- a/libmdoc.h
+++ b/libmdoc.h
@@ -1,7 +1,7 @@
-/* $Id: libmdoc.h,v 1.112 2017/05/30 16:22:03 schwarze Exp $ */
+/* $Id: libmdoc.h,v 1.117 2018/12/31 04:55:46 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013,2014,2015,2017,2018 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
@@ -16,6 +16,10 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+struct roff_node;
+struct roff_man;
+struct mdoc_arg;
+
#define MACRO_PROT_ARGS struct roff_man *mdoc, \
enum roff_tok tok, \
int line, \
@@ -38,6 +42,7 @@ enum margserr {
ARGS_ERROR,
ARGS_EOLN, /* end-of-line */
ARGS_WORD, /* normal word */
+ ARGS_ALLOC, /* normal word from roff_getarg() */
ARGS_PUNCT, /* series of punctuation */
ARGS_PHRASE /* Bl -column phrase */
};
@@ -59,10 +64,8 @@ enum mdelim {
DELIM_MAX
};
-extern const struct mdoc_macro *const mdoc_macros;
-
+const struct mdoc_macro *mdoc_macro(enum roff_tok);
-void mdoc_macro(MACRO_PROT_ARGS);
void mdoc_elem_alloc(struct roff_man *, int, int,
enum roff_tok, struct mdoc_arg *);
struct roff_node *mdoc_block_alloc(struct roff_man *, int, int,
@@ -71,10 +74,7 @@ void mdoc_tail_alloc(struct roff_man *, int, int,
enum roff_tok);
struct roff_node *mdoc_endbody_alloc(struct roff_man *, int, int,
enum roff_tok, 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 *);
-void mdoc_state_reset(struct roff_man *);
const char *mdoc_a2arch(const char *);
const char *mdoc_a2att(const char *);
const char *mdoc_a2lib(const char *);
diff --git a/main.c b/main.c
index 600bc9bb4bef..b91c15860ab1 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,7 @@
-/* $Id: main.c,v 1.306 2018/05/14 14:10:23 schwarze Exp $ */
+/* $Id: main.c,v 1.322 2019/03/06 10:18:58 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2012, 2014-2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2012, 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h> /* MACHINE */
-#include <sys/termios.h>
#include <sys/wait.h>
#include <assert.h>
@@ -40,6 +39,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
#include <time.h>
#include <unistd.h>
@@ -49,6 +49,7 @@
#include "roff.h"
#include "mdoc.h"
#include "man.h"
+#include "mandoc_parse.h"
#include "tag.h"
#include "main.h"
#include "manconf.h"
@@ -81,7 +82,6 @@ struct curparse {
void *outdata; /* data for output */
char *os_s; /* operating system for display */
int wstop; /* stop after a file with a warning */
- enum mandocerr mmin; /* ignore messages below this */
enum mandoc_os os_e; /* check base system conventions */
enum outt outtype; /* which output to use */
};
@@ -89,7 +89,7 @@ struct curparse {
int mandocdb(int, char *[]);
-static void check_xr(const char *);
+static void check_xr(void);
static int fs_lookup(const struct manpaths *,
size_t ipath, const char *,
const char *, const char *,
@@ -99,8 +99,6 @@ static int fs_search(const struct mansearch *,
struct manpage **, size_t *);
static int koptions(int *, char *);
static void moptions(int *, char *);
-static void mmsg(enum mandocerr, enum mandoclevel,
- const char *, int, int, const char *);
static void outdata_alloc(struct curparse *);
static void parse(struct curparse *, int, const char *);
static void passthrough(const char *, int, int);
@@ -112,8 +110,6 @@ static int woptions(struct curparse *, char *);
static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
static char help_arg[] = "help";
static char *help_argv[] = {help_arg, NULL};
-static enum mandoclevel rc;
-static FILE *mmsg_stream;
int
@@ -127,7 +123,7 @@ main(int argc, char *argv[])
struct manpage *res, *resp;
const char *progname, *sec, *thisarg;
char *conf_file, *defpaths, *auxpaths;
- char *oarg;
+ char *oarg, *tagarg;
unsigned char *uc;
size_t i, sz;
int prio, best_prio;
@@ -152,6 +148,7 @@ main(int argc, char *argv[])
setprogname(progname);
#endif
+ mandoc_msg_setoutfile(stderr);
if (strncmp(progname, "mandocdb", 8) == 0 ||
strcmp(progname, BINM_MAKEWHATIS) == 0)
return mandocdb(argc, argv);
@@ -191,10 +188,8 @@ main(int argc, char *argv[])
memset(&curp, 0, sizeof(struct curparse));
curp.outtype = OUTT_LOCALE;
- curp.mmin = MANDOCERR_MAX;
curp.outopts = &conf.output;
options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1;
- mmsg_stream = stderr;
use_pager = 1;
tag_files = NULL;
@@ -314,6 +309,9 @@ main(int argc, char *argv[])
}
}
+ if (curp.outtype != OUTT_TREE || !curp.outopts->noval)
+ options |= MPARSE_VALIDATE;
+
if (outmode == OUTMODE_FLN ||
outmode == OUTMODE_LST ||
!isatty(STDOUT_FILENO))
@@ -371,7 +369,16 @@ main(int argc, char *argv[])
#endif
}
- rc = MANDOCLEVEL_OK;
+ /*
+ * Use the first argument for -O tag in addition to
+ * using it as a search term for man(1) or apropos(1).
+ */
+
+ if (conf.output.tag != NULL && *conf.output.tag == '\0') {
+ tagarg = argc > 0 && search.argmode == ARG_EXPR ?
+ strchr(*argv, '=') : NULL;
+ conf.output.tag = tagarg == NULL ? *argv : tagarg + 1;
+ }
/* man(1), whatis(1), apropos(1) */
@@ -405,7 +412,6 @@ main(int argc, char *argv[])
res[sz].names = NULL;
res[sz].output = NULL;
res[sz].ipath = SIZE_MAX;
- res[sz].bits = 0;
res[sz].sec = 10;
res[sz].form = FORM_SRC;
sz++;
@@ -415,7 +421,7 @@ main(int argc, char *argv[])
if (sz == 0) {
if (search.argmode != ARG_NAME)
warnx("nothing appropriate");
- rc = MANDOCLEVEL_BADARG;
+ mandoc_msg_setrc(MANDOCLEVEL_BADARG);
goto out;
}
@@ -483,19 +489,17 @@ main(int argc, char *argv[])
moptions(&options, auxpaths);
mchars_alloc();
- curp.mp = mparse_alloc(options, curp.mmin, mmsg,
- curp.os_e, curp.os_s);
-
- /*
- * Conditionally start up the lookaside buffer before parsing.
- */
- if (OUTT_MAN == curp.outtype)
- mparse_keep(curp.mp);
+ curp.mp = mparse_alloc(options, curp.os_e, curp.os_s);
if (argc < 1) {
- if (use_pager)
+ if (use_pager) {
tag_files = tag_init();
- parse(&curp, STDIN_FILENO, "<stdin>");
+ tag_files->tagname = conf.output.tag;
+ }
+ thisarg = "<stdin>";
+ mandoc_msg_setinfilename(thisarg);
+ parse(&curp, STDIN_FILENO, thisarg);
+ mandoc_msg_setinfilename(NULL);
}
/*
@@ -519,22 +523,25 @@ main(int argc, char *argv[])
(void)chdir(conf.manpath.paths[resp->ipath]);
else if (startdir != -1)
(void)fchdir(startdir);
- }
+ thisarg = resp->file;
+ } else
+ thisarg = *argv;
- fd = mparse_open(curp.mp, resp != NULL ? resp->file : *argv);
+ fd = mparse_open(curp.mp, thisarg);
if (fd != -1) {
if (use_pager) {
- tag_files = tag_init();
use_pager = 0;
+ tag_files = tag_init();
+ tag_files->tagname = conf.output.tag;
}
- if (resp == NULL)
- parse(&curp, fd, *argv);
- else if (resp->form == FORM_SRC)
- parse(&curp, fd, resp->file);
+ mandoc_msg_setinfilename(thisarg);
+ if (resp == NULL || resp->form == FORM_SRC)
+ parse(&curp, fd, thisarg);
else
passthrough(resp->file, fd,
conf.output.synopsisonly);
+ mandoc_msg_setinfilename(NULL);
if (ferror(stdout)) {
if (tag_files != NULL) {
@@ -543,7 +550,7 @@ main(int argc, char *argv[])
tag_files = NULL;
} else
warn("stdout");
- rc = MANDOCLEVEL_SYSERR;
+ mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
break;
}
@@ -552,10 +559,11 @@ main(int argc, char *argv[])
outdata_alloc(&curp);
terminal_sepline(curp.outdata);
}
- } else if (rc < MANDOCLEVEL_ERROR)
- rc = MANDOCLEVEL_ERROR;
+ } else
+ mandoc_msg(MANDOCERR_FILE, 0, 0,
+ "%s: %s", thisarg, strerror(errno));
- if (MANDOCLEVEL_OK != rc && curp.wstop)
+ if (curp.wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
break;
if (resp != NULL)
@@ -646,7 +654,7 @@ out:
if (pid == -1) {
warn("wait");
- rc = MANDOCLEVEL_SYSERR;
+ mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
break;
}
if (!WIFSTOPPED(status))
@@ -656,8 +664,7 @@ out:
}
tag_unlink();
}
-
- return (int)rc;
+ return (int)mandoc_msg_getrc();
}
static void
@@ -755,7 +762,6 @@ found:
page->names = NULL;
page->output = NULL;
page->ipath = ipath;
- page->bits = NAME_FILE & NAME_MASK;
page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10;
page->form = form;
return 1;
@@ -790,8 +796,18 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
return 1;
}
if (res != NULL && *ressz == lastsz &&
- strchr(*argv, '/') == NULL)
- warnx("No entry for %s in the manual.", *argv);
+ strchr(*argv, '/') == NULL) {
+ if (cfg->arch != NULL &&
+ arch_valid(cfg->arch, OSENUM) == 0)
+ warnx("Unknown architecture \"%s\".",
+ cfg->arch);
+ else if (cfg->sec == NULL)
+ warnx("No entry for %s in the manual.",
+ *argv);
+ else
+ warnx("No entry for %s in section %s "
+ "of the manual.", *argv, cfg->sec);
+ }
lastsz = *ressz;
argv++;
argc--;
@@ -802,101 +818,92 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
static void
parse(struct curparse *curp, int fd, const char *file)
{
- enum mandoclevel rctmp;
- struct roff_man *man;
+ struct roff_meta *meta;
/* Begin by parsing the file itself. */
assert(file);
assert(fd >= 0);
- rctmp = mparse_readfd(curp->mp, fd, file);
+ mparse_readfd(curp->mp, fd, file);
if (fd != STDIN_FILENO)
close(fd);
- if (rc < rctmp)
- rc = rctmp;
/*
* With -Wstop and warnings or errors of at least the requested
* level, do not produce output.
*/
- if (rctmp != MANDOCLEVEL_OK && curp->wstop)
+ if (curp->wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
return;
if (curp->outdata == NULL)
outdata_alloc(curp);
+ else if (curp->outtype == OUTT_HTML)
+ html_reset(curp);
- mparse_result(curp->mp, &man, NULL);
+ mandoc_xr_reset();
+ meta = mparse_result(curp->mp);
/* Execute the out device, if it exists. */
- if (man == NULL)
- return;
- mandoc_xr_reset();
- if (man->macroset == MACROSET_MDOC) {
- if (curp->outtype != OUTT_TREE || !curp->outopts->noval)
- mdoc_validate(man);
+ if (meta->macroset == MACROSET_MDOC) {
switch (curp->outtype) {
case OUTT_HTML:
- html_mdoc(curp->outdata, man);
+ html_mdoc(curp->outdata, meta);
break;
case OUTT_TREE:
- tree_mdoc(curp->outdata, man);
+ tree_mdoc(curp->outdata, meta);
break;
case OUTT_MAN:
- man_mdoc(curp->outdata, man);
+ man_mdoc(curp->outdata, meta);
break;
case OUTT_PDF:
case OUTT_ASCII:
case OUTT_UTF8:
case OUTT_LOCALE:
case OUTT_PS:
- terminal_mdoc(curp->outdata, man);
+ terminal_mdoc(curp->outdata, meta);
break;
case OUTT_MARKDOWN:
- markdown_mdoc(curp->outdata, man);
+ markdown_mdoc(curp->outdata, meta);
break;
default:
break;
}
}
- if (man->macroset == MACROSET_MAN) {
- if (curp->outtype != OUTT_TREE || !curp->outopts->noval)
- man_validate(man);
+ if (meta->macroset == MACROSET_MAN) {
switch (curp->outtype) {
case OUTT_HTML:
- html_man(curp->outdata, man);
+ html_man(curp->outdata, meta);
break;
case OUTT_TREE:
- tree_man(curp->outdata, man);
+ tree_man(curp->outdata, meta);
break;
case OUTT_MAN:
- man_man(curp->outdata, man);
+ mparse_copy(curp->mp);
break;
case OUTT_PDF:
case OUTT_ASCII:
case OUTT_UTF8:
case OUTT_LOCALE:
case OUTT_PS:
- terminal_man(curp->outdata, man);
+ terminal_man(curp->outdata, meta);
break;
default:
break;
}
}
- if (curp->mmin < MANDOCERR_STYLE)
- check_xr(file);
- mparse_updaterc(curp->mp, &rc);
+ if (mandoc_msg_getmin() < MANDOCERR_STYLE)
+ check_xr();
}
static void
-check_xr(const char *file)
+check_xr(void)
{
static struct manpaths paths;
struct mansearch search;
struct mandoc_xr *xr;
- char *cp;
size_t sz;
if (paths.sz == 0)
@@ -915,13 +922,12 @@ check_xr(const char *file)
if (fs_search(&search, &paths, 1, &xr->name, NULL, &sz))
continue;
if (xr->count == 1)
- mandoc_asprintf(&cp, "Xr %s %s", xr->name, xr->sec);
+ mandoc_msg(MANDOCERR_XR_BAD, xr->line,
+ xr->pos + 1, "Xr %s %s", xr->name, xr->sec);
else
- mandoc_asprintf(&cp, "Xr %s %s (%d times)",
+ mandoc_msg(MANDOCERR_XR_BAD, xr->line,
+ xr->pos + 1, "Xr %s %s (%d times)",
xr->name, xr->sec, xr->count);
- mmsg(MANDOCERR_XR_BAD, MANDOCLEVEL_STYLE,
- file, xr->line, xr->pos + 1, cp);
- free(cp);
}
}
@@ -1020,8 +1026,7 @@ done:
fail:
free(line);
warn("%s: SYSERR: %s", file, syscall);
- if (rc < MANDOCLEVEL_SYSERR)
- rc = MANDOCLEVEL_SYSERR;
+ mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
}
static int
@@ -1063,8 +1068,8 @@ toptions(struct curparse *curp, char *arg)
curp->outtype = OUTT_ASCII;
else if (0 == strcmp(arg, "lint")) {
curp->outtype = OUTT_LINT;
- curp->mmin = MANDOCERR_BASE;
- mmsg_stream = stdout;
+ mandoc_msg_setoutfile(stdout);
+ mandoc_msg_setmin(MANDOCERR_BASE);
} else if (0 == strcmp(arg, "tree"))
curp->outtype = OUTT_TREE;
else if (0 == strcmp(arg, "man"))
@@ -1115,29 +1120,29 @@ woptions(struct curparse *curp, char *arg)
break;
case 1:
case 2:
- curp->mmin = MANDOCERR_BASE;
+ mandoc_msg_setmin(MANDOCERR_BASE);
break;
case 3:
- curp->mmin = MANDOCERR_STYLE;
+ mandoc_msg_setmin(MANDOCERR_STYLE);
break;
case 4:
- curp->mmin = MANDOCERR_WARNING;
+ mandoc_msg_setmin(MANDOCERR_WARNING);
break;
case 5:
- curp->mmin = MANDOCERR_ERROR;
+ mandoc_msg_setmin(MANDOCERR_ERROR);
break;
case 6:
- curp->mmin = MANDOCERR_UNSUPP;
+ mandoc_msg_setmin(MANDOCERR_UNSUPP);
break;
case 7:
- curp->mmin = MANDOCERR_MAX;
+ mandoc_msg_setmin(MANDOCERR_MAX);
break;
case 8:
- curp->mmin = MANDOCERR_BASE;
+ mandoc_msg_setmin(MANDOCERR_BASE);
curp->os_e = MANDOC_OS_OPENBSD;
break;
case 9:
- curp->mmin = MANDOCERR_BASE;
+ mandoc_msg_setmin(MANDOCERR_BASE);
curp->os_e = MANDOC_OS_NETBSD;
break;
default:
@@ -1148,29 +1153,6 @@ woptions(struct curparse *curp, char *arg)
return 1;
}
-static void
-mmsg(enum mandocerr t, enum mandoclevel lvl,
- const char *file, int line, int col, const char *msg)
-{
- const char *mparse_msg;
-
- fprintf(mmsg_stream, "%s: %s:", getprogname(),
- file == NULL ? "<stdin>" : file);
-
- if (line)
- fprintf(mmsg_stream, "%d:%d:", line, col + 1);
-
- fprintf(mmsg_stream, " %s", mparse_strlevel(lvl));
-
- if ((mparse_msg = mparse_strerror(t)) != NULL)
- fprintf(mmsg_stream, ": %s", mparse_msg);
-
- if (msg)
- fprintf(mmsg_stream, ": %s", msg);
-
- fputc('\n', mmsg_stream);
-}
-
static pid_t
spawn_pager(struct tag_files *tag_files)
{
@@ -1179,8 +1161,10 @@ spawn_pager(struct tag_files *tag_files)
char *argv[MAX_PAGER_ARGS];
const char *pager;
char *cp;
+#if HAVE_LESS_T
size_t cmdlen;
- int argc;
+#endif
+ int argc, use_ofn;
pid_t pager_pid;
pager = getenv("MANPAGER");
@@ -1196,7 +1180,7 @@ spawn_pager(struct tag_files *tag_files)
*/
argc = 0;
- while (argc + 4 < MAX_PAGER_ARGS) {
+ while (argc + 5 < MAX_PAGER_ARGS) {
argv[argc++] = cp;
cp = strchr(cp, ' ');
if (cp == NULL)
@@ -1210,14 +1194,23 @@ spawn_pager(struct tag_files *tag_files)
/* For less(1), use the tag file. */
+ use_ofn = 1;
+#if HAVE_LESS_T
if ((cmdlen = strlen(argv[0])) >= 4) {
cp = argv[0] + cmdlen - 4;
if (strcmp(cp, "less") == 0) {
argv[argc++] = mandoc_strdup("-T");
argv[argc++] = tag_files->tfn;
+ if (tag_files->tagname != NULL) {
+ argv[argc++] = mandoc_strdup("-t");
+ argv[argc++] = tag_files->tagname;
+ use_ofn = 0;
+ }
}
}
- argv[argc++] = tag_files->ofn;
+#endif
+ if (use_ofn)
+ argv[argc++] = tag_files->ofn;
argv[argc] = NULL;
switch (pager_pid = fork()) {
diff --git a/main.h b/main.h
index f9b8f135f885..19a630cde8b6 100644
--- a/main.h
+++ b/main.h
@@ -1,7 +1,7 @@
-/* $Id: main.h,v 1.27 2017/03/03 14:23:23 schwarze Exp $ */
+/* $Id: main.h,v 1.30 2019/03/03 13:02:11 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2015, 2019 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -16,7 +16,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-struct roff_man;
+struct roff_meta;
struct manoutput;
/*
@@ -27,15 +27,15 @@ struct manoutput;
*/
void *html_alloc(const struct manoutput *);
-void html_mdoc(void *, const struct roff_man *);
-void html_man(void *, const struct roff_man *);
+void html_mdoc(void *, const struct roff_meta *);
+void html_man(void *, const struct roff_meta *);
+void html_reset(void *);
void html_free(void *);
-void tree_mdoc(void *, const struct roff_man *);
-void tree_man(void *, const struct roff_man *);
+void tree_mdoc(void *, const struct roff_meta *);
+void tree_man(void *, const struct roff_meta *);
-void man_mdoc(void *, const struct roff_man *);
-void man_man(void *, const struct roff_man *);
+void man_mdoc(void *, const struct roff_meta *);
void *locale_alloc(const struct manoutput *);
void *utf8_alloc(const struct manoutput *);
@@ -46,8 +46,8 @@ void *pdf_alloc(const struct manoutput *);
void *ps_alloc(const struct manoutput *);
void pspdf_free(void *);
-void terminal_mdoc(void *, const struct roff_man *);
-void terminal_man(void *, const struct roff_man *);
+void terminal_mdoc(void *, const struct roff_meta *);
+void terminal_man(void *, const struct roff_meta *);
void terminal_sepline(void *);
-void markdown_mdoc(void *, const struct roff_man *);
+void markdown_mdoc(void *, const struct roff_meta *);
diff --git a/man.1 b/man.1
index cf03693ee981..0d2976bab795 100644
--- a/man.1
+++ b/man.1
@@ -1,9 +1,9 @@
-.\" $Id: man.1,v 1.33 2018/04/19 23:41:16 schwarze Exp $
+.\" $Id: man.1,v 1.35 2019/03/09 15:55:01 schwarze Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\" Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
-.\" Copyright (c) 2010, 2011, 2014-2017 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2010, 2011, 2014-2018 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -31,7 +31,7 @@
.\"
.\" @(#)man.1 8.2 (Berkeley) 1/2/94
.\"
-.Dd $Mdocdate: April 19 2018 $
+.Dd $Mdocdate: March 9 2019 $
.Dt MAN 1
.Os
.Sh NAME
@@ -218,12 +218,24 @@ Guidelines for writing
man pages can be found in
.Xr mdoc 7 .
.Pp
+The
+.Xr mandoc.db 5
+database is used for looking up manual page entries.
+In cases where the database is absent, outdated, or corrupt,
+.Nm
+falls back to looking for files called
+.Ar name . Ns Ar section .
If both a formatted and an unformatted version of the same manual page,
for example
.Pa cat1/foo.0
and
.Pa man1/foo.1 ,
exist in the same directory, only the unformatted version is used.
+The database is kept up to date with
+.Xr makewhatis 8 ,
+which is run by the
+.Xr weekly 8
+maintenance script.
.Sh ENVIRONMENT
.Bl -tag -width MANPATHX
.It Ev MACHINE
@@ -266,6 +278,13 @@ and
can be used to move to the next and to the previous place providing
information about the term last searched for with
.Ic :t .
+The
+.Fl O Cm tag Ns Op = Ns Ar term
+option documented in the
+.Xr mandoc 1
+manual opens a manual page at the definition of a specific
+.Ar term
+rather than at the beginning.
.It Ev MANPATH
The standard search path used by
.Nm
diff --git a/man.7 b/man.7
index d418b9ee76ca..7706b5ca23df 100644
--- a/man.7
+++ b/man.7
@@ -1,7 +1,8 @@
-.\" $Id: man.7,v 1.137 2018/04/05 22:12:33 schwarze Exp $
+.\" $Id: man.7,v 1.143 2019/03/02 22:04:40 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2011-2015,2017,2018,2019 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2017 Anthony Bentley <bentley@openbsd.org>
.\" Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
@@ -16,31 +17,20 @@
.\" 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 5 2018 $
+.Dd $Mdocdate: March 2 2019 $
.Dt MAN 7
.Os
.Sh NAME
.Nm man
.Nd legacy formatting language for manual pages
.Sh DESCRIPTION
-Traditionally, the
+The
.Nm man
-language has been used to write
-.Ux
-manuals for the
-.Xr man 1
-utility.
-It supports limited control of presentational details like fonts,
-indentation and spacing.
-This reference document describes the structure of manual pages
-and the syntax and usage of the man language.
-.Pp
-.Bf -emphasis
-Do not use
-.Nm
-to write your manuals:
-.Ef
-It lacks support for semantic markup.
+language was the standard formatting language for
+.At
+manual pages from 1979 to 1989.
+Do not use it to write new manual pages: it is a purely presentational
+language and lacks support for semantic markup.
Use the
.Xr mdoc 7
language, instead.
@@ -53,7 +43,7 @@ are called
.Dq macro lines .
The first word is the macro name.
It usually consists of two capital letters.
-For a list of available macros, see
+For a list of portable macros, see
.Sx MACRO OVERVIEW .
The words following the macro name are arguments to the macro.
.Pp
@@ -78,226 +68,68 @@ sections in the
.Xr roff 7
manual for details, in particular regarding
comments, escape sequences, whitespace, and quoting.
-.Sh MANUAL STRUCTURE
-Each
-.Nm
-document must contain the
-.Sx \&TH
-macro describing the document's section and title.
-It may occur anywhere in the document, although conventionally it
-appears as the first macro.
-.Pp
-Beyond
-.Sx \&TH ,
-at least one macro or text line must appear in the document.
.Pp
-The following is a well-formed skeleton
+Each
.Nm
-file for a utility
-.Qq progname :
+document starts with the
+.Ic TH
+macro specifying the document's name and section, followed by the
+.Sx NAME
+section formatted as follows:
.Bd -literal -offset indent
-\&.TH PROGNAME 1 2009-10-10
+\&.TH PROGNAME 1 1979-01-10
\&.SH NAME
\efBprogname\efR \e(en one line about what it does
-\&.\e\(dq .SH LIBRARY
-\&.\e\(dq For sections 2, 3, and 9 only.
-\&.\e\(dq Not used in OpenBSD.
-\&.SH SYNOPSIS
-\efBprogname\efR [\efB\e-options\efR] \efIfile ...\efR
-\&.SH DESCRIPTION
-The \efBfoo\efR utility processes files ...
-\&.\e\(dq .Sh CONTEXT
-\&.\e\(dq For section 9 functions only.
-\&.\e\(dq .SH IMPLEMENTATION NOTES
-\&.\e\(dq Not used in OpenBSD.
-\&.\e\(dq .SH RETURN VALUES
-\&.\e\(dq For sections 2, 3, and 9 function return values only.
-\&.\e\(dq .SH ENVIRONMENT
-\&.\e\(dq For sections 1, 6, 7, and 8 only.
-\&.\e\(dq .SH FILES
-\&.\e\(dq .SH EXIT STATUS
-\&.\e\(dq For sections 1, 6, and 8 only.
-\&.\e\(dq .SH EXAMPLES
-\&.\e\(dq .SH DIAGNOSTICS
-\&.\e\(dq For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only.
-\&.\e\(dq .SH ERRORS
-\&.\e\(dq For sections 2, 3, 4, and 9 errno settings only.
-\&.\e\(dq .SH SEE ALSO
-\&.\e\(dq .BR foobar ( 1 )
-\&.\e\(dq .SH STANDARDS
-\&.\e\(dq .SH HISTORY
-\&.\e\(dq .SH AUTHORS
-\&.\e\(dq .SH CAVEATS
-\&.\e\(dq .SH BUGS
-\&.\e\(dq .SH SECURITY CONSIDERATIONS
-\&.\e\(dq Not used in OpenBSD.
.Ed
-.Pp
-The sections in a
-.Nm
-document are conventionally ordered as they appear above.
-Sections should be composed as follows:
-.Bl -ohang -offset indent
-.It Em NAME
-The name(s) and a short description of the documented material.
-The syntax for this is generally as follows:
-.Pp
-.D1 \efBname\efR \e(en description
-.It Em LIBRARY
-The name of the library containing the documented material, which is
-assumed to be a function in a section 2 or 3 manual.
-For functions in the C library, this may be as follows:
-.Pp
-.D1 Standard C Library (libc, -lc)
-.It Em SYNOPSIS
-Documents the utility invocation syntax, function call syntax, or device
-configuration.
-.Pp
-For the first, utilities (sections 1, 6, and 8), this is
-generally structured as follows:
-.Pp
-.D1 \efBname\efR [-\efBab\efR] [-\efBc\efR\efIarg\efR] \efBpath\efR...
-.Pp
-For the second, function calls (sections 2, 3, 9):
-.Pp
-.D1 \&.B char *name(char *\efIarg\efR);
-.Pp
-And for the third, configurations (section 4):
-.Pp
-.D1 \&.B name* at cardbus ? function ?
-.Pp
-Manuals not in these sections generally don't need a
-.Em SYNOPSIS .
-.It Em DESCRIPTION
-This expands upon the brief, one-line description in
-.Em NAME .
-It usually contains a break-down of the options (if documenting a
-command).
-.It Em CONTEXT
-This section lists the contexts in which functions can be called in section 9.
-The contexts are autoconf, process, or interrupt.
-.It Em IMPLEMENTATION NOTES
-Implementation-specific notes should be kept here.
-This is useful when implementing standard functions that may have side
-effects or notable algorithmic implications.
-.It Em RETURN VALUES
-This section documents the return values of functions in sections 2, 3, and 9.
-.It Em ENVIRONMENT
-Documents any usages of environment variables, e.g.,
-.Xr environ 7 .
-.It Em FILES
-Documents files used.
-It's helpful to document both the file name and a short description of how
-the file is used (created, modified, etc.).
-.It Em EXIT STATUS
-This section documents the command exit status for
-section 1, 6, and 8 utilities.
-Historically, this information was described in
-.Em DIAGNOSTICS ,
-a practise that is now discouraged.
-.It Em EXAMPLES
-Example usages.
-This often contains snippets of well-formed,
-well-tested invocations.
-Make sure that examples work properly!
-.It Em DIAGNOSTICS
-Documents error conditions.
-In section 4 and 9 manuals, these are usually messages
-printed by the kernel to the console and to the kernel log.
-In section 1, 6, 7, and 8, these are usually messages
-printed by userland programs to the standard error output.
-.Pp
-Historically, this section was used in place of
-.Em EXIT STATUS
-for manuals in sections 1, 6, and 8; however, this practise is
-discouraged.
-.It Em ERRORS
-Documents
-.Xr errno 2
-settings in sections 2, 3, 4, and 9.
-.It Em SEE ALSO
-References other manuals with related topics.
-This section should exist for most manuals.
-.Pp
-.D1 \&.BR bar \&( 1 \&),
-.Pp
-Cross-references should conventionally be ordered
-first by section, then alphabetically.
-.It Em STANDARDS
-References any standards implemented or used, such as
-.Pp
-.D1 IEEE Std 1003.2 (\e(lqPOSIX.2\e(rq)
-.Pp
-If not adhering to any standards, the
-.Em HISTORY
-section should be used.
-.It Em HISTORY
-A brief history of the subject, including where support first appeared.
-.It Em AUTHORS
-Credits to the person or persons who wrote the code and/or documentation.
-Authors should generally be noted by both name and email address.
-.It Em CAVEATS
-Common misuses and misunderstandings should be explained
-in this section.
-.It Em BUGS
-Known bugs, limitations, and work-arounds should be described
-in this section.
-.It Em SECURITY CONSIDERATIONS
-Documents any security precautions that operators should consider.
-.El
.Sh MACRO OVERVIEW
This overview is sorted such that macros of similar purpose are listed
-together, to help find the best macro for any given purpose.
-Deprecated macros are not included in the overview, but can be found
-in the alphabetical reference below.
+together.
+Deprecated and non-portable macros are not included in the overview,
+but can be found in the alphabetical reference below.
.Ss Page header and footer meta-data
-.Bl -column "PP, LP, P" description
-.It Sx TH Ta set the title: Ar title section date Op Ar source Op Ar volume
-.It Sx AT Ta display AT&T UNIX version in the page footer (<= 1 argument)
-.It Sx UC Ta display BSD version in the page footer (<= 1 argument)
+.Bl -column "RS, RE" description
+.It Ic TH Ta set the title: Ar name section date Op Ar source Op Ar volume
+.It Ic AT Ta display AT&T UNIX version in the page footer (<= 1 argument)
+.It Ic UC Ta display BSD version in the page footer (<= 1 argument)
.El
.Ss Sections and paragraphs
-.Bl -column "PP, LP, P" description
-.It Sx SH Ta section header (one line)
-.It Sx SS Ta subsection header (one line)
-.It Sx PP , LP , P Ta start an undecorated paragraph (no arguments)
-.It Sx RS , RE Ta reset the left margin: Op Ar width
-.It Sx IP Ta indented paragraph: Op Ar head Op Ar width
-.It Sx TP Ta tagged paragraph: Op Ar width
-.It Sx HP Ta hanged paragraph: Op Ar width
-.It Sx PD Ta set vertical paragraph distance: Op Ar height
-.It Sx fi , nf Ta fill mode and no-fill mode (no arguments)
-.It Sx in Ta additional indent: Op Ar width
+.Bl -column "RS, RE" description
+.It Ic SH Ta section header (one line)
+.It Ic SS Ta subsection header (one line)
+.It Ic PP Ta start an undecorated paragraph (no arguments)
+.It Ic RS , RE Ta reset the left margin: Op Ar width
+.It Ic IP Ta indented paragraph: Op Ar head Op Ar width
+.It Ic TP Ta tagged paragraph: Op Ar width
+.It Ic PD Ta set vertical paragraph distance: Op Ar height
+.It Ic in Ta additional indent: Op Ar width
.El
.Ss Physical markup
-.Bl -column "PP, LP, P" description
-.It Sx B Ta boldface font
-.It Sx I Ta italic font
-.It Sx SB Ta small boldface font
-.It Sx SM Ta small roman font
-.It Sx BI Ta alternate between boldface and italic fonts
-.It Sx BR Ta alternate between boldface and roman fonts
-.It Sx IB Ta alternate between italic and boldface fonts
-.It Sx IR Ta alternate between italic and roman fonts
-.It Sx RB Ta alternate between roman and boldface fonts
-.It Sx RI Ta alternate between roman and italic fonts
+.Bl -column "RS, RE" description
+.It Ic B Ta boldface font
+.It Ic I Ta italic font
+.It Ic SB Ta small boldface font
+.It Ic SM Ta small roman font
+.It Ic BI Ta alternate between boldface and italic fonts
+.It Ic BR Ta alternate between boldface and roman fonts
+.It Ic IB Ta alternate between italic and boldface fonts
+.It Ic IR Ta alternate between italic and roman fonts
+.It Ic RB Ta alternate between roman and boldface fonts
+.It Ic RI Ta alternate between roman and italic fonts
.El
.Sh MACRO REFERENCE
This section is a canonical reference to all macros, arranged
alphabetically.
For the scoping of individual macros, see
.Sx MACRO SYNTAX .
-.Ss \&AT
+.Bl -tag -width 3n
+.It Ic AT
Sets the volume for the footer for compatibility with man pages from
.At
releases.
The optional arguments specify which release it is from.
-.Ss \&B
+.It Ic B
Text is rendered in bold face.
-.Pp
-See also
-.Sx \&I .
-.Ss \&BI
+.It Ic BI
Text is rendered alternately in bold face and italic.
Thus,
.Sq .BI this word and that
@@ -312,106 +144,66 @@ and
render in italics.
Whitespace between arguments is omitted in output.
.Pp
-Examples:
+Example:
.Pp
.Dl \&.BI bold italic bold italic
-.Pp
-The output of this example will be emboldened
-.Dq bold
-and italicised
-.Dq italic ,
-with spaces stripped between arguments.
-.Pp
-See also
-.Sx \&IB ,
-.Sx \&BR ,
-.Sx \&RB ,
-.Sx \&RI ,
-and
-.Sx \&IR .
-.Ss \&BR
+.It Ic BR
Text is rendered alternately in bold face and roman (the default font).
Whitespace between arguments is omitted in output.
-.Pp
-See
-.Sx \&BI
-for an equivalent example.
-.Pp
See also
-.Sx \&BI ,
-.Sx \&IB ,
-.Sx \&RB ,
-.Sx \&RI ,
-and
-.Sx \&IR .
-.Ss \&DT
+.Ic BI .
+.It Ic DT
Restore the default tabulator positions.
They are at intervals of 0.5 inches.
This has no effect unless the tabulator positions were changed with the
.Xr roff 7
-.Ic \&ta
+.Ic ta
request.
-.Ss \&EE
-This is a non-standard GNU extension, included only for compatibility.
+.It Ic EE
+This is a non-standard GNU extension.
In
.Xr mandoc 1 ,
-it does the same as
-.Sx \&fi .
-.Ss \&EX
-This is a non-standard GNU extension, included only for compatibility.
+it does the same as the
+.Xr roff 7
+.Ic fi
+request (switch to fill mode).
+.It Ic EX
+This is a non-standard GNU extension.
In
.Xr mandoc 1 ,
-it does the same as
-.Sx \&nf .
-.Ss \&HP
+it does the same as the
+.Xr roff 7
+.Ic nf
+request (switch to no-fill mode).
+.It Ic HP
Begin a paragraph whose initial output line is left-justified, but
subsequent output lines are indented, with the following syntax:
-.Bd -filled -offset indent
-.Pf \. Sx \&HP
-.Op Ar width
-.Ed
+.Pp
+.D1 Pf . Ic HP Op Ar width
.Pp
The
.Ar width
argument is a
.Xr roff 7
scaling width.
-If specified, it's saved for later paragraph left-margins; if unspecified, the
-saved or default width is used.
-.Pp
-See also
-.Sx \&IP ,
-.Sx \&LP ,
-.Sx \&P ,
-.Sx \&PP ,
-and
-.Sx \&TP .
-.Ss \&I
+If specified, it's saved for later paragraph left margins;
+if unspecified, the saved or default width is used.
+.Pp
+This macro is portable, but deprecated
+because it has no good representation in HTML output,
+usually ending up indistinguishable from
+.Ic PP .
+.It Ic I
Text is rendered in italics.
-.Pp
-See also
-.Sx \&B .
-.Ss \&IB
+.It Ic IB
Text is rendered alternately in italics and bold face.
Whitespace between arguments is omitted in output.
-.Pp
-See
-.Sx \&BI
-for an equivalent example.
-.Pp
See also
-.Sx \&BI ,
-.Sx \&BR ,
-.Sx \&RB ,
-.Sx \&RI ,
-and
-.Sx \&IR .
-.Ss \&IP
+.Ic BI .
+.It Ic IP
Begin an indented paragraph with the following syntax:
-.Bd -filled -offset indent
-.Pf \. Sx \&IP
-.Op Ar head Op Ar width
-.Ed
+.Pp
+.D1 Pf . Ic IP Op Ar head Op Ar width
.Pp
The
.Ar width
@@ -425,89 +217,48 @@ The
.Ar head
argument is used as a leading term, flushed to the left margin.
This is useful for bulleted paragraphs and so on.
-.Pp
-See also
-.Sx \&HP ,
-.Sx \&LP ,
-.Sx \&P ,
-.Sx \&PP ,
-and
-.Sx \&TP .
-.Ss \&IR
+.It Ic IR
Text is rendered alternately in italics and roman (the default font).
Whitespace between arguments is omitted in output.
-.Pp
-See
-.Sx \&BI
-for an equivalent example.
-.Pp
See also
-.Sx \&BI ,
-.Sx \&IB ,
-.Sx \&BR ,
-.Sx \&RB ,
-and
-.Sx \&RI .
-.Ss \&LP
-Begin an undecorated paragraph.
-The scope of a paragraph is closed by a subsequent paragraph,
-sub-section, section, or end of file.
-The saved paragraph left-margin width is reset to the default.
-.Pp
-See also
-.Sx \&HP ,
-.Sx \&IP ,
-.Sx \&P ,
-.Sx \&PP ,
-and
-.Sx \&TP .
-.Ss \&ME
-End a mailto block.
-This is a non-standard GNU extension, included only for compatibility.
-See
-.Sx \&MT .
-.Ss \&MT
+.Ic BI .
+.It Ic LP
+A synonym for
+.Ic PP .
+.It Ic ME
+End a mailto block started with
+.Ic MT .
+This is a non-standard GNU extension.
+.It Ic MT
Begin a mailto block.
-This is a non-standard GNU extension, included only for compatibility.
+This is a non-standard GNU extension.
It has the following syntax:
-.Bd -literal -offset indent
-.Pf \. Sx \&MT Ar address
+.Bd -unfilled -offset indent
+.Pf . Ic MT Ar address
link description to be shown
-.Pf \. Sx ME
+.Pf . Ic ME
.Ed
-.Ss \&OP
+.It Ic OP
Optional command-line argument.
-This is a non-standard GNU extension, included only for compatibility.
+This is a non-standard GNU extension.
It has the following syntax:
-.Bd -filled -offset indent
-.Pf \. Sx \&OP
-.Ar key Op Ar value
-.Ed
+.Pp
+.D1 Pf . Ic OP Ar key Op Ar value
.Pp
The
.Ar key
is usually a command-line flag and
.Ar value
its argument.
-.Ss \&P
-Synonym for
-.Sx \&LP .
-.Pp
-See also
-.Sx \&HP ,
-.Sx \&IP ,
-.Sx \&LP ,
-.Sx \&PP ,
-and
-.Sx \&TP .
-.Ss \&PD
+.It Ic P
+A synonym for
+.Ic PP .
+.It Ic PD
Specify the vertical space to be inserted before each new paragraph.
.br
The syntax is as follows:
-.Bd -filled -offset indent
-.Pf \. Sx \&PD
-.Op Ar height
-.Ed
+.Pp
+.D1 Pf . Ic PD Op Ar height
.Pp
The
.Ar height
@@ -521,89 +272,60 @@ If the unit is omitted,
is assumed.
.Pp
This macro affects the spacing before any subsequent instances of
-.Sx \&HP ,
-.Sx \&IP ,
-.Sx \&LP ,
-.Sx \&P ,
-.Sx \&PP ,
-.Sx \&SH ,
-.Sx \&SS ,
+.Ic HP ,
+.Ic IP ,
+.Ic LP ,
+.Ic P ,
+.Ic PP ,
+.Ic SH ,
+.Ic SS ,
+.Ic SY ,
and
-.Sx \&TP .
-.Ss \&PP
-Synonym for
-.Sx \&LP .
-.Pp
-See also
-.Sx \&HP ,
-.Sx \&IP ,
-.Sx \&LP ,
-.Sx \&P ,
-and
-.Sx \&TP .
-.Ss \&RB
+.Ic TP .
+.It Ic PP
+Begin an undecorated paragraph.
+The scope of a paragraph is closed by a subsequent paragraph,
+sub-section, section, or end of file.
+The saved paragraph left-margin width is reset to the default.
+.It Ic RB
Text is rendered alternately in roman (the default font) and bold face.
Whitespace between arguments is omitted in output.
-.Pp
-See
-.Sx \&BI
-for an equivalent example.
-.Pp
See also
-.Sx \&BI ,
-.Sx \&IB ,
-.Sx \&BR ,
-.Sx \&RI ,
-and
-.Sx \&IR .
-.Ss \&RE
+.Ic BI .
+.It Ic RE
Explicitly close out the scope of a prior
-.Sx \&RS .
+.Ic RS .
The default left margin is restored to the state before that
-.Sx \&RS
+.Ic RS
invocation.
.Pp
The syntax is as follows:
-.Bd -filled -offset indent
-.Pf \. Sx \&RE
-.Op Ar level
-.Ed
+.Pp
+.D1 Pf . Ic RE Op Ar level
.Pp
Without an argument, the most recent
-.Sx \&RS
+.Ic RS
block is closed out.
If
.Ar level
is 1, all open
-.Sx \&RS
+.Ic RS
blocks are closed out.
Otherwise,
.Ar level No \(mi 1
nested
-.Sx \&RS
+.Ic RS
blocks remain open.
-.Ss \&RI
+.It Ic RI
Text is rendered alternately in roman (the default font) and italics.
Whitespace between arguments is omitted in output.
-.Pp
-See
-.Sx \&BI
-for an equivalent example.
-.Pp
See also
-.Sx \&BI ,
-.Sx \&IB ,
-.Sx \&BR ,
-.Sx \&RB ,
-and
-.Sx \&IR .
-.Ss \&RS
+.Ic BI .
+.It Ic RS
Temporarily reset the default left margin.
This has the following syntax:
-.Bd -filled -offset indent
-.Pf \. Sx \&RS
-.Op Ar width
-.Ed
+.Pp
+.D1 Pf . Ic RS Op Ar width
.Pp
The
.Ar width
@@ -613,35 +335,47 @@ scaling width.
If not specified, the saved or default width is used.
.Pp
See also
-.Sx \&RE .
-.Ss \&SB
+.Ic RE .
+.It Ic SB
Text is rendered in small size (one point smaller than the default font)
bold face.
-.Ss \&SH
+.It Ic SH
Begin a section.
The scope of a section is only closed by another section or the end of
file.
The paragraph left-margin width is reset to the default.
-.Ss \&SM
+.It Ic SM
Text is rendered in small size (one point smaller than the default
font).
-.Ss \&SS
+.It Ic SS
Begin a sub-section.
The scope of a sub-section is closed by a subsequent sub-section,
section, or end of file.
The paragraph left-margin width is reset to the default.
-.Ss \&TH
-Sets the title of the manual page for use in the page header
-and footer with the following syntax:
-.Bd -filled -offset indent
-.Pf \. Sx \&TH
-.Ar title section date
-.Op Ar source Op Ar volume
+.It Ic SY
+Begin a synopsis block with the following syntax:
+.Bd -unfilled -offset indent
+.Pf . Ic SY Ar command
+.Ar arguments
+.Pf . Ic YS
.Ed
.Pp
+This is a non-standard GNU extension
+and very rarely used even in GNU manual pages.
+Formatting is similar to
+.Ic IP .
+.It Ic TH
+Set the name of the manual page for use in the page header
+and footer with the following syntax:
+.Pp
+.D1 Pf . Ic TH Ar name section date Op Ar source Op Ar volume
+.Pp
Conventionally, the document
-.Ar title
+.Ar name
is given in all caps.
+The
+.Ar section
+is usually a single digit, in a few cases followed by a letter.
The recommended
.Ar date
format is
@@ -661,21 +395,22 @@ uses its
argument.
The
.Ar volume
-string replaces the default rendered volume, which is dictated by the
-manual section.
+string replaces the default volume title of the
+.Ar section .
.Pp
Examples:
.Pp
.Dl \&.TH CVS 5 "1992-02-12" GNU
-.Ss \&TP
+.It Ic TP
Begin a paragraph where the head, if exceeding the indentation width, is
-followed by a newline; if not, the body follows on the same line after a
-buffer to the indentation width.
+followed by a newline; if not, the body follows on the same line after
+advancing to the indentation width.
Subsequent output lines are indented.
The syntax is as follows:
-.Bd -filled -offset indent
-.Pf \. Sx \&TP
-.Op Ar width
+.Bd -unfilled -offset indent
+.Pf . Ic TP Op Ar width
+.Ar head No \e" one line
+.Ar body
.Ed
.Pp
The
@@ -685,55 +420,45 @@ argument is a
scaling width.
If specified, it's saved for later paragraph left-margins; if
unspecified, the saved or default width is used.
-.Pp
-See also
-.Sx \&HP ,
-.Sx \&IP ,
-.Sx \&LP ,
-.Sx \&P ,
-and
-.Sx \&PP .
-.Ss \&UC
+.It Ic TQ
+Like
+.Ic TP ,
+except that no vertical spacing is inserted before the paragraph.
+This is a non-standard GNU extension
+and very rarely used even in GNU manual pages.
+.It Ic UC
Sets the volume for the footer for compatibility with man pages from
.Bx
releases.
The optional first argument specifies which release it is from.
-.Ss \&UE
-End a uniform resource identifier block.
-This is a non-standard GNU extension, included only for compatibility.
-See
-.Sx \&UE .
-.Ss \&UR
+.It Ic UE
+End a uniform resource identifier block started with
+.Ic UR .
+This is a non-standard GNU extension.
+.It Ic UR
Begin a uniform resource identifier block.
-This is a non-standard GNU extension, included only for compatibility.
+This is a non-standard GNU extension.
It has the following syntax:
-.Bd -literal -offset indent
-.Pf \. Sx \&UR Ar uri
+.Bd -unfilled -offset indent
+.Pf . Ic UR Ar uri
link description to be shown
-.Pf \. Sx UE
+.Pf . Ic UE
.Ed
-.Ss \&fi
-End literal mode begun by
-.Sx \&nf .
-.Ss \&in
+.It Ic YS
+End a synopsis block started with
+.Ic SY .
+This is a non-standard GNU extension.
+.It Ic in
Indent relative to the current indentation:
.Pp
-.D1 Pf \. Sx \&in Op Ar width
+.D1 Pf . Ic in Op Ar width
.Pp
If
.Ar width
is signed, the new offset is relative.
Otherwise, it is absolute.
This value is reset upon the next paragraph, section, or sub-section.
-.Ss \&nf
-Begin literal mode: all subsequent free-form lines have their end of
-line boundaries preserved.
-May be ended by
-.Sx \&fi .
-Literal mode is implicitly ended by
-.Sx \&SH
-or
-.Sx \&SS .
+.El
.Sh MACRO SYNTAX
The
.Nm
@@ -754,7 +479,7 @@ foo
.Ed
.Pp
is equivalent to
-.Sq \&.I foo .
+.Sq .I foo .
If next-line macros are invoked consecutively, only the last is used.
If a next-line macro is followed by a non-next-line macro, an error is
raised.
@@ -766,36 +491,26 @@ The syntax is as follows:
.Ed
.Bl -column "MacroX" "ArgumentsX" "ScopeXXXXX" "CompatX" -offset indent
.It Em Macro Ta Em Arguments Ta Em Scope Ta Em Notes
-.It Sx \&AT Ta <=1 Ta current Ta \&
-.It Sx \&B Ta n Ta next-line Ta \&
-.It Sx \&BI Ta n Ta current Ta \&
-.It Sx \&BR Ta n Ta current Ta \&
-.It Sx \&DT Ta 0 Ta current Ta \&
-.It Sx \&EE Ta 0 Ta current Ta compat
-.It Sx \&EX Ta 0 Ta current Ta compat
-.It Sx \&I Ta n Ta next-line Ta \&
-.It Sx \&IB Ta n Ta current Ta \&
-.It Sx \&IR Ta n Ta current Ta \&
-.It Sx \&OP Ta 0, 1 Ta current Ta compat
-.It Sx \&PD Ta 1 Ta current Ta \&
-.It Sx \&RB Ta n Ta current Ta \&
-.It Sx \&RI Ta n Ta current Ta \&
-.It Sx \&SB Ta n Ta next-line Ta \&
-.It Sx \&SM Ta n Ta next-line Ta \&
-.It Sx \&TH Ta >1, <6 Ta current Ta \&
-.It Sx \&UC Ta <=1 Ta current Ta \&
-.It Sx \&fi Ta 0 Ta current Ta compat
-.It Sx \&in Ta 1 Ta current Ta compat
-.It Sx \&nf Ta 0 Ta current Ta compat
+.It Ic AT Ta <=1 Ta current Ta \&
+.It Ic B Ta n Ta next-line Ta \&
+.It Ic BI Ta n Ta current Ta \&
+.It Ic BR Ta n Ta current Ta \&
+.It Ic DT Ta 0 Ta current Ta \&
+.It Ic EE Ta 0 Ta current Ta GNU
+.It Ic EX Ta 0 Ta current Ta GNU
+.It Ic I Ta n Ta next-line Ta \&
+.It Ic IB Ta n Ta current Ta \&
+.It Ic IR Ta n Ta current Ta \&
+.It Ic OP Ta >=1 Ta current Ta GNU
+.It Ic PD Ta 1 Ta current Ta \&
+.It Ic RB Ta n Ta current Ta \&
+.It Ic RI Ta n Ta current Ta \&
+.It Ic SB Ta n Ta next-line Ta \&
+.It Ic SM Ta n Ta next-line Ta \&
+.It Ic TH Ta >1, <6 Ta current Ta \&
+.It Ic UC Ta <=1 Ta current Ta \&
+.It Ic in Ta 1 Ta current Ta Xr roff 7
.El
-.Pp
-Macros marked as
-.Qq compat
-are included for compatibility with the significant corpus of existing
-manuals that mix dialects of roff.
-These macros should not be used for portable
-.Nm
-manuals.
.Ss Block Macros
Block macros comprise a head and body.
As with in-line macros, the head is scoped to the current line and, in
@@ -812,19 +527,19 @@ The syntax is as follows:
.Pp
The closure of body scope may be to the section, where a macro is closed
by
-.Sx \&SH ;
+.Ic SH ;
sub-section, closed by a section or
-.Sx \&SS ;
-part, closed by a section, sub-section, or
-.Sx \&RE ;
-or paragraph, closed by a section, sub-section, part,
-.Sx \&HP ,
-.Sx \&IP ,
-.Sx \&LP ,
-.Sx \&P ,
-.Sx \&PP ,
+.Ic SS ;
+or paragraph, closed by a section, sub-section,
+.Ic HP ,
+.Ic IP ,
+.Ic LP ,
+.Ic P ,
+.Ic PP ,
+.Ic RE ,
+.Ic SY ,
or
-.Sx \&TP .
+.Ic TP .
No closure refers to an explicit block closing macro.
.Pp
As a rule, block macros may not be nested; thus, calling a block macro
@@ -832,25 +547,25 @@ while another block macro scope is open, and the open scope is not
implicitly closed, is syntactically incorrect.
.Bl -column "MacroX" "ArgumentsX" "Head ScopeX" "sub-sectionX" "compatX" -offset indent
.It Em Macro Ta Em Arguments Ta Em Head Scope Ta Em Body Scope Ta Em Notes
-.It Sx \&HP Ta <2 Ta current Ta paragraph Ta \&
-.It Sx \&IP Ta <3 Ta current Ta paragraph Ta \&
-.It Sx \&LP Ta 0 Ta current Ta paragraph Ta \&
-.It Sx \&P Ta 0 Ta current Ta paragraph Ta \&
-.It Sx \&PP Ta 0 Ta current Ta paragraph Ta \&
-.It Sx \&RE Ta 0 Ta current Ta none Ta compat
-.It Sx \&RS Ta 1 Ta current Ta part Ta compat
-.It Sx \&SH Ta >0 Ta next-line Ta section Ta \&
-.It Sx \&SS Ta >0 Ta next-line Ta sub-section Ta \&
-.It Sx \&TP Ta n Ta next-line Ta paragraph Ta \&
-.It Sx \&UE Ta 0 Ta current Ta none Ta compat
-.It Sx \&UR Ta 1 Ta current Ta part Ta compat
+.It Ic HP Ta <2 Ta current Ta paragraph Ta \&
+.It Ic IP Ta <3 Ta current Ta paragraph Ta \&
+.It Ic LP Ta 0 Ta current Ta paragraph Ta \&
+.It Ic ME Ta 0 Ta none Ta none Ta GNU
+.It Ic MT Ta 1 Ta current Ta to \&ME Ta GNU
+.It Ic P Ta 0 Ta current Ta paragraph Ta \&
+.It Ic PP Ta 0 Ta current Ta paragraph Ta \&
+.It Ic RE Ta <=1 Ta current Ta none Ta \&
+.It Ic RS Ta 1 Ta current Ta to \&RE Ta \&
+.It Ic SH Ta >0 Ta next-line Ta section Ta \&
+.It Ic SS Ta >0 Ta next-line Ta sub-section Ta \&
+.It Ic SY Ta 1 Ta current Ta to \&YS Ta GNU
+.It Ic TP Ta n Ta next-line Ta paragraph Ta \&
+.It Ic TQ Ta n Ta next-line Ta paragraph Ta GNU
+.It Ic UE Ta 0 Ta current Ta none Ta GNU
+.It Ic UR Ta 1 Ta current Ta part Ta GNU
+.It Ic YS Ta 0 Ta none Ta none Ta GNU
.El
.Pp
-Macros marked
-.Qq compat
-are as mentioned in
-.Sx Line Macros .
-.Pp
If a block macro is next-line scoped, it may only be followed by in-line
macros for decorating text.
.Ss Font handling
@@ -866,7 +581,7 @@ In text lines, the effect of manual font selection by escape sequences
only lasts until the next macro invocation; in macro lines, it only lasts
until the end of the macro scope.
Note that macros like
-.Sx \&BR
+.Ic BR
open and close a font scope for each argument.
.Sh SEE ALSO
.Xr man 1 ,
@@ -895,8 +610,3 @@ This
.Nm
reference was written by
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
-.Sh CAVEATS
-Do not use this language.
-Use
-.Xr mdoc 7 ,
-instead.
diff --git a/man.c b/man.c
index 7a2bcc968818..f0e4002b2a2c 100644
--- a/man.c
+++ b/man.c
@@ -1,7 +1,7 @@
-/* $Id: man.c,v 1.176 2017/06/28 12:52:45 schwarze Exp $ */
+/* $Id: man.c,v 1.187 2019/01/05 00:36:50 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Joerg Sonnenberger <joerg@netbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -35,7 +35,7 @@
#include "roff_int.h"
#include "libman.h"
-static void man_descope(struct roff_man *, int, int);
+static char *man_hasc(char *);
static int man_ptext(struct roff_man *, int, char *, int);
static int man_pmacro(struct roff_man *, int, char *, int);
@@ -52,38 +52,62 @@ man_parseln(struct roff_man *man, int ln, char *buf, int offs)
man_ptext(man, ln, buf, offs);
}
-static void
-man_descope(struct roff_man *man, int line, int offs)
+/*
+ * If the string ends with \c, return a pointer to the backslash.
+ * Otherwise, return NULL.
+ */
+static char *
+man_hasc(char *start)
{
+ char *cp, *ep;
+
+ ep = strchr(start, '\0') - 2;
+ if (ep < start || ep[0] != '\\' || ep[1] != 'c')
+ return NULL;
+ for (cp = ep; cp > start; cp--)
+ if (cp[-1] != '\\')
+ break;
+ return (ep - cp) % 2 ? NULL : ep;
+}
+
+void
+man_descope(struct roff_man *man, int line, int offs, char *start)
+{
+ /* Trailing \c keeps next-line scope open. */
+
+ if (start != NULL && man_hasc(start) != NULL)
+ return;
+
/*
* Co-ordinate what happens with having a next-line scope open:
- * first close out the element scope (if applicable), then close
- * out the block scope (also if applicable).
+ * first close out the element scopes (if applicable),
+ * then close out the block scope (also if applicable).
*/
if (man->flags & MAN_ELINE) {
+ while (man->last->parent->type != ROFFT_ROOT &&
+ man_macro(man->last->parent->tok)->flags & MAN_ESCOPED)
+ man_unscope(man, man->last->parent);
man->flags &= ~MAN_ELINE;
- man_unscope(man, man->last->parent);
}
if ( ! (man->flags & MAN_BLINE))
return;
- man->flags &= ~MAN_BLINE;
man_unscope(man, man->last->parent);
roff_body_alloc(man, line, offs, man->last->tok);
+ man->flags &= ~(MAN_BLINE | ROFF_NONOFILL);
}
static int
man_ptext(struct roff_man *man, int line, char *buf, int offs)
{
int i;
- const char *cp, *sp;
char *ep;
- /* Literal free-form text whitespace is preserved. */
+ /* In no-fill mode, whitespace is preserved on text lines. */
- if (man->flags & MAN_LITERAL) {
+ if (man->flags & ROFF_NOFILL) {
roff_word_alloc(man, line, offs, buf + offs);
- man_descope(man, line, offs);
+ man_descope(man, line, offs, buf + offs);
return 1;
}
@@ -98,26 +122,15 @@ man_ptext(struct roff_man *man, int line, char *buf, int offs)
if (buf[i] == '\0') {
if (man->flags & (MAN_ELINE | MAN_BLINE)) {
- mandoc_msg(MANDOCERR_BLK_BLANK, man->parse,
- line, 0, NULL);
+ mandoc_msg(MANDOCERR_BLK_BLANK, line, 0, NULL);
return 1;
}
if (man->last->tok == MAN_SH || man->last->tok == MAN_SS)
return 1;
- switch (man->last->type) {
- case ROFFT_TEXT:
- sp = man->last->string;
- cp = ep = strchr(sp, '\0') - 2;
- if (cp < sp || cp[0] != '\\' || cp[1] != 'c')
- break;
- while (cp > sp && cp[-1] == '\\')
- cp--;
- if ((ep - cp) % 2)
- break;
+ if (man->last->type == ROFFT_TEXT &&
+ ((ep = man_hasc(man->last->string)) != NULL)) {
*ep = '\0';
return 1;
- default:
- break;
}
roff_elem_alloc(man, line, offs, ROFF_sp);
man->next = ROFF_NEXT_SIBLING;
@@ -134,8 +147,7 @@ man_ptext(struct roff_man *man, int line, char *buf, int offs)
if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
if (i > 1 && '\\' != buf[i - 2])
- mandoc_msg(MANDOCERR_SPACE_EOL, man->parse,
- line, i - 1, NULL);
+ mandoc_msg(MANDOCERR_SPACE_EOL, line, i - 1, NULL);
for (--i; i && ' ' == buf[i]; i--)
/* Spin back to non-space. */ ;
@@ -157,7 +169,7 @@ man_ptext(struct roff_man *man, int line, char *buf, int offs)
if (mandoc_eos(buf, (size_t)i))
man->last->flags |= NODE_EOS;
- man_descope(man, line, offs);
+ man_descope(man, line, offs, buf + offs);
return 1;
}
@@ -180,8 +192,7 @@ man_pmacro(struct roff_man *man, int ln, char *buf, int offs)
if (sz > 0 && sz < 4)
tok = roffhash_find(man->manmac, buf + ppos, sz);
if (tok == TOKEN_NONE) {
- mandoc_msg(MANDOCERR_MACRO, man->parse,
- ln, ppos, buf + ppos - 1);
+ mandoc_msg(MANDOCERR_MACRO, ln, ppos, "%s", buf + ppos - 1);
return 1;
}
@@ -211,8 +222,7 @@ man_pmacro(struct roff_man *man, int ln, char *buf, int offs)
*/
if (buf[offs] == '\0' && buf[offs - 1] == ' ')
- mandoc_msg(MANDOCERR_SPACE_EOL, man->parse,
- ln, offs - 1, NULL);
+ mandoc_msg(MANDOCERR_SPACE_EOL, ln, offs - 1, NULL);
/*
* Some macros break next-line scopes; otherwise, remember
@@ -230,16 +240,12 @@ man_pmacro(struct roff_man *man, int ln, char *buf, int offs)
* page, that's very likely what the author intended.
*/
- if (bline) {
- cp = strchr(buf + offs, '\0') - 2;
- if (cp >= buf && cp[0] == '\\' && cp[1] == 'c')
- bline = 0;
- }
+ if (bline && man_hasc(buf + offs))
+ bline = 0;
/* Call to handler... */
- assert(man_macros[tok].fp);
- (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf);
+ (*man_macro(tok)->fp)(man, tok, ln, ppos, &offs, buf);
/* In quick mode (for mandocdb), abort after the NAME section. */
@@ -256,15 +262,15 @@ man_pmacro(struct roff_man *man, int ln, char *buf, int offs)
* unless the next-line scope is allowed to continue.
*/
- if ( ! bline || man->flags & MAN_ELINE ||
- man_macros[tok].flags & MAN_NSCOPED)
+ if (bline == 0 ||
+ (man->flags & MAN_BLINE) == 0 ||
+ man->flags & MAN_ELINE ||
+ man_macro(tok)->flags & MAN_NSCOPED)
return 1;
- assert(man->flags & MAN_BLINE);
- man->flags &= ~MAN_BLINE;
-
man_unscope(man, man->last->parent);
roff_body_alloc(man, ln, ppos, man->last->tok);
+ man->flags &= ~(MAN_BLINE | ROFF_NONOFILL);
return 1;
}
@@ -280,17 +286,17 @@ man_breakscope(struct roff_man *man, int tok)
*/
if (man->flags & MAN_ELINE && (tok < MAN_TH ||
- ! (man_macros[tok].flags & MAN_NSCOPED))) {
+ (man_macro(tok)->flags & MAN_NSCOPED) == 0)) {
n = man->last;
if (n->type == ROFFT_TEXT)
n = n->parent;
if (n->tok < MAN_TH ||
- man_macros[n->tok].flags & MAN_NSCOPED)
+ (man_macro(n->tok)->flags & (MAN_NSCOPED | MAN_ESCOPED))
+ == MAN_NSCOPED)
n = n->parent;
- mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
- n->line, n->pos, "%s breaks %s",
- roff_name[tok], roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_BLK_LINE, n->line, n->pos,
+ "%s breaks %s", roff_name[tok], roff_name[n->tok]);
roff_node_delete(man, n);
man->flags &= ~MAN_ELINE;
@@ -302,12 +308,12 @@ man_breakscope(struct roff_man *man, int tok)
*/
if (man->flags & MAN_BLINE &&
- (tok == MAN_nf || tok == MAN_fi) &&
+ (tok == ROFF_nf || tok == ROFF_fi) &&
(man->last->tok == MAN_SH || man->last->tok == MAN_SS)) {
n = man->last;
man_unscope(man, n);
roff_body_alloc(man, n->line, n->pos, n->tok);
- man->flags &= ~MAN_BLINE;
+ man->flags &= ~(MAN_BLINE | ROFF_NONOFILL);
}
/*
@@ -316,68 +322,24 @@ man_breakscope(struct roff_man *man, int tok)
* Delete the block that is being broken.
*/
- if (man->flags & MAN_BLINE && (tok < MAN_TH ||
- man_macros[tok].flags & MAN_BSCOPE)) {
+ if (man->flags & MAN_BLINE && tok != ROFF_nf && tok != ROFF_fi &&
+ (tok < MAN_TH || man_macro(tok)->flags & MAN_XSCOPE)) {
n = man->last;
if (n->type == ROFFT_TEXT)
n = n->parent;
if (n->tok < MAN_TH ||
- (man_macros[n->tok].flags & MAN_BSCOPE) == 0)
+ (man_macro(n->tok)->flags & MAN_XSCOPE) == 0)
n = n->parent;
assert(n->type == ROFFT_HEAD);
n = n->parent;
assert(n->type == ROFFT_BLOCK);
- assert(man_macros[n->tok].flags & MAN_SCOPED);
+ assert(man_macro(n->tok)->flags & MAN_BSCOPED);
- mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
- n->line, n->pos, "%s breaks %s",
- roff_name[tok], roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_BLK_LINE, n->line, n->pos,
+ "%s breaks %s", roff_name[tok], roff_name[n->tok]);
roff_node_delete(man, n);
- man->flags &= ~MAN_BLINE;
+ man->flags &= ~(MAN_BLINE | ROFF_NONOFILL);
}
}
-
-const struct mparse *
-man_mparse(const struct roff_man *man)
-{
-
- assert(man && man->parse);
- return man->parse;
-}
-
-void
-man_state(struct roff_man *man, struct roff_node *n)
-{
-
- switch(n->tok) {
- case MAN_nf:
- case MAN_EX:
- if (man->flags & MAN_LITERAL && ! (n->flags & NODE_VALID))
- mandoc_msg(MANDOCERR_NF_SKIP, man->parse,
- n->line, n->pos, "nf");
- man->flags |= MAN_LITERAL;
- break;
- case MAN_fi:
- case MAN_EE:
- if ( ! (man->flags & MAN_LITERAL) &&
- ! (n->flags & NODE_VALID))
- mandoc_msg(MANDOCERR_FI_SKIP, man->parse,
- n->line, n->pos, "fi");
- man->flags &= ~MAN_LITERAL;
- break;
- default:
- break;
- }
- man->last->flags |= NODE_VALID;
-}
-
-void
-man_validate(struct roff_man *man)
-{
-
- man->last = man->first;
- man_node_validate(man);
- man->flags &= ~MAN_LITERAL;
-}
diff --git a/man.conf.5 b/man.conf.5
index be0998087d17..0ffe868ad764 100644
--- a/man.conf.5
+++ b/man.conf.5
@@ -1,6 +1,6 @@
-.\" $Id: man.conf.5,v 1.5 2017/08/22 18:17:52 schwarze Exp $
+.\" $Id: man.conf.5,v 1.6 2018/10/02 14:56:47 schwarze Exp $
.\"
-.\" Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 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
@@ -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: August 22 2017 $
+.Dd $Mdocdate: October 2 2018 $
.Dt MAN.CONF 5
.Os
.Sh NAME
@@ -98,6 +98,7 @@ manual.
.It Ic man Ta string Ta Cm html Ta path for \&Xr links
.It Ic paper Ta string Ta Cm ps , pdf Ta paper size
.It Ic style Ta string Ta Cm html Ta CSS file
+.It Ic toc Ta none Ta Cm html Ta print table of contents
.It Ic width Ta integer Ta Cm ascii , utf8 Ta right margin
.El
.It Ic _whatdb Ar path Ns Cm /whatis.db
diff --git a/man.h b/man.h
index d671f9a9e41e..ed4375c0c0dc 100644
--- a/man.h
+++ b/man.h
@@ -1,4 +1,4 @@
-/* $Id: man.h,v 1.78 2017/04/24 23:06:18 schwarze Exp $ */
+/* $Id: man.h,v 1.79 2018/08/23 19:33:27 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -18,5 +18,4 @@
struct roff_man;
-const struct mparse *man_mparse(const struct roff_man *);
void man_validate(struct roff_man *);
diff --git a/man_html.c b/man_html.c
index ae5dac1ad938..994a208aa0ee 100644
--- a/man_html.c
+++ b/man_html.c
@@ -1,7 +1,7 @@
-/* $Id: man_html.c,v 1.153 2018/07/27 17:49:31 schwarze Exp $ */
+/* $Id: man_html.c,v 1.173 2019/03/02 16:30:53 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,26 +33,22 @@
#include "html.h"
#include "main.h"
-/* FIXME: have PD set the default vspace width. */
-
#define MAN_ARGS const struct roff_meta *man, \
const struct roff_node *n, \
struct html *h
-struct htmlman {
+struct man_html_act {
int (*pre)(MAN_ARGS);
int (*post)(MAN_ARGS);
};
-static void print_bvspace(struct html *,
- const struct roff_node *);
static void print_man_head(const struct roff_meta *,
struct html *);
static void print_man_nodelist(MAN_ARGS);
static void print_man_node(MAN_ARGS);
-static int fillmode(struct html *, int);
+static char list_continues(const struct roff_node *,
+ const struct roff_node *);
static int man_B_pre(MAN_ARGS);
-static int man_HP_pre(MAN_ARGS);
static int man_IP_pre(MAN_ARGS);
static int man_I_pre(MAN_ARGS);
static int man_OP_pre(MAN_ARGS);
@@ -60,8 +56,9 @@ static int man_PP_pre(MAN_ARGS);
static int man_RS_pre(MAN_ARGS);
static int man_SH_pre(MAN_ARGS);
static int man_SM_pre(MAN_ARGS);
-static int man_SS_pre(MAN_ARGS);
+static int man_SY_pre(MAN_ARGS);
static int man_UR_pre(MAN_ARGS);
+static int man_abort_pre(MAN_ARGS);
static int man_alt_pre(MAN_ARGS);
static int man_ign_pre(MAN_ARGS);
static int man_in_pre(MAN_ARGS);
@@ -70,16 +67,17 @@ static void man_root_post(const struct roff_meta *,
static void man_root_pre(const struct roff_meta *,
struct html *);
-static const struct htmlman __mans[MAN_MAX - MAN_TH] = {
+static const struct man_html_act man_html_acts[MAN_MAX - MAN_TH] = {
{ NULL, NULL }, /* TH */
{ man_SH_pre, NULL }, /* SH */
- { man_SS_pre, NULL }, /* SS */
+ { man_SH_pre, NULL }, /* SS */
{ man_IP_pre, NULL }, /* TP */
- { man_PP_pre, NULL }, /* LP */
+ { man_IP_pre, NULL }, /* TQ */
+ { man_abort_pre, NULL }, /* LP */
{ man_PP_pre, NULL }, /* PP */
- { man_PP_pre, NULL }, /* P */
+ { man_abort_pre, NULL }, /* P */
{ man_IP_pre, NULL }, /* IP */
- { man_HP_pre, NULL }, /* HP */
+ { man_PP_pre, NULL }, /* HP */
{ man_SM_pre, NULL }, /* SM */
{ man_SM_pre, NULL }, /* SB */
{ man_alt_pre, NULL }, /* BI */
@@ -91,8 +89,6 @@ static const struct htmlman __mans[MAN_MAX - MAN_TH] = {
{ man_I_pre, NULL }, /* I */
{ man_alt_pre, NULL }, /* IR */
{ man_alt_pre, NULL }, /* RI */
- { NULL, NULL }, /* nf */
- { NULL, NULL }, /* fi */
{ NULL, NULL }, /* RE */
{ man_RS_pre, NULL }, /* RS */
{ man_ign_pre, NULL }, /* DT */
@@ -100,6 +96,8 @@ static const struct htmlman __mans[MAN_MAX - MAN_TH] = {
{ man_ign_pre, NULL }, /* PD */
{ man_ign_pre, NULL }, /* AT */
{ man_in_pre, NULL }, /* in */
+ { man_SY_pre, NULL }, /* SY */
+ { NULL, NULL }, /* YS */
{ man_OP_pre, NULL }, /* OP */
{ NULL, NULL }, /* EX */
{ NULL, NULL }, /* EE */
@@ -108,34 +106,10 @@ static const struct htmlman __mans[MAN_MAX - MAN_TH] = {
{ man_UR_pre, NULL }, /* MT */
{ NULL, NULL }, /* ME */
};
-static const struct htmlman *const mans = __mans - MAN_TH;
-
-
-/*
- * Printing leading vertical space before a block.
- * This is used for the paragraph macros.
- * The rules are pretty simple, since there's very little nesting going
- * on here. Basically, if we're the first within another block (SS/SH),
- * then don't emit vertical space. If we are (RS), then do. If not the
- * first, print it.
- */
-static void
-print_bvspace(struct html *h, const struct roff_node *n)
-{
- if (n->body && n->body->child)
- if (n->body->child->type == ROFFT_TBL)
- return;
-
- if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS)
- if (NULL == n->prev)
- return;
-
- print_paragraph(h);
-}
void
-html_man(void *arg, const struct roff_man *man)
+html_man(void *arg, const struct roff_meta *man)
{
struct html *h;
struct roff_node *n;
@@ -147,19 +121,19 @@ html_man(void *arg, const struct roff_man *man)
if ((h->oflags & HTML_FRAGMENT) == 0) {
print_gen_decls(h);
print_otag(h, TAG_HTML, "");
- if (n->type == ROFFT_COMMENT)
+ if (n != NULL && n->type == ROFFT_COMMENT)
print_gen_comment(h, n);
t = print_otag(h, TAG_HEAD, "");
- print_man_head(&man->meta, h);
+ print_man_head(man, h);
print_tagq(h, t);
print_otag(h, TAG_BODY, "");
}
- man_root_pre(&man->meta, h);
+ man_root_pre(man, h);
t = print_otag(h, TAG_DIV, "c", "manual-text");
- print_man_nodelist(&man->meta, n, h);
+ print_man_nodelist(man, n, h);
print_tagq(h, t);
- man_root_post(&man->meta, h);
+ man_root_post(man, h);
print_tagq(h, NULL);
}
@@ -178,7 +152,6 @@ print_man_head(const struct roff_meta *man, struct html *h)
static void
print_man_nodelist(MAN_ARGS)
{
-
while (n != NULL) {
print_man_node(man, n, h);
n = n->next;
@@ -188,99 +161,33 @@ print_man_nodelist(MAN_ARGS)
static void
print_man_node(MAN_ARGS)
{
- static int want_fillmode = MAN_fi;
- static int save_fillmode;
-
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;
+ if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
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_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:
- case MAN_MT:
- fillmode(h, MAN_fi);
- break;
- default:
- break;
- }
- 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 == ' ' &&
- (h->flags & HTML_NONEWLINE) == 0)
- print_otag(h, TAG_BR, "");
- if (*n->string != '\0')
- break;
- print_paragraph(h);
- return;
- case ROFFT_COMMENT:
- return;
- default:
- break;
- }
-
- /* Produce output for this node. */
+ html_fillmode(h, n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi);
child = 1;
switch (n->type) {
case ROFFT_TEXT:
+ if (*n->string == '\0') {
+ print_endline(h);
+ return;
+ }
+ if (*n->string == ' ' && n->flags & NODE_LINE &&
+ (h->flags & HTML_NONEWLINE) == 0)
+ print_endline(h);
+ else if (n->flags & NODE_DELIMC)
+ h->flags |= HTML_NOSPACE;
t = h->tag;
+ t->refcnt++;
print_text(h, n->string);
break;
case ROFFT_EQN:
t = h->tag;
+ t->refcnt++;
print_eqn(h, n->eqn);
break;
case ROFFT_TBL:
@@ -306,62 +213,51 @@ print_man_node(MAN_ARGS)
* the "meta" table state. This will be reopened on the
* next table element.
*/
- if (h->tblt)
+ if (h->tblt != NULL)
print_tblclose(h);
-
t = h->tag;
+ t->refcnt++;
if (n->tok < ROFF_MAX) {
roff_html_pre(h, n);
- child = 0;
- break;
+ t->refcnt--;
+ print_stagq(h, t);
+ return;
}
-
assert(n->tok >= MAN_TH && n->tok < MAN_MAX);
- if (mans[n->tok].pre)
- 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;
-
+ if (man_html_acts[n->tok - MAN_TH].pre != NULL)
+ child = (*man_html_acts[n->tok - MAN_TH].pre)(man,
+ n, h);
break;
}
- if (child && n->child)
+ if (child && n->child != NULL)
print_man_nodelist(man, n->child, h);
/* This will automatically close out any font scope. */
- print_stagq(h, t);
+ t->refcnt--;
+ if (n->type == ROFFT_BLOCK &&
+ (n->tok == MAN_IP || n->tok == MAN_TP || n->tok == MAN_TQ)) {
+ t = h->tag;
+ while (t->tag != TAG_DL && t->tag != TAG_UL)
+ t = t->next;
+ /*
+ * Close the list if no further item of the same type
+ * follows; otherwise, close the item only.
+ */
+ if (list_continues(n, n->next) == '\0') {
+ print_tagq(h, t);
+ t = NULL;
+ }
+ }
+ if (t != NULL)
+ print_stagq(h, t);
- if (fillmode(h, 0) == MAN_nf &&
- n->next != NULL && n->next->flags & NODE_LINE)
+ if (n->flags & NODE_NOFILL && n->tok != MAN_YS &&
+ (n->next != NULL && n->next->flags & NODE_LINE)) {
+ /* In .nf = <pre>, print even empty lines. */
+ h->col++;
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 void
@@ -382,7 +278,7 @@ man_root_pre(const struct roff_meta *man, struct html *h)
print_stagq(h, tt);
print_otag(h, TAG_TD, "c", "head-vol");
- if (NULL != man->vol)
+ if (man->vol != NULL)
print_text(h, man->vol);
print_stagq(h, tt);
@@ -405,7 +301,7 @@ man_root_post(const struct roff_meta *man, struct html *h)
print_stagq(h, tt);
print_otag(h, TAG_TD, "c", "foot-os");
- if (man->os)
+ if (man->os != NULL)
print_text(h, man->os);
print_tagq(h, t);
}
@@ -413,13 +309,32 @@ man_root_post(const struct roff_meta *man, struct html *h)
static int
man_SH_pre(MAN_ARGS)
{
- char *id;
-
- if (n->type == ROFFT_HEAD) {
+ const char *class;
+ char *id;
+ enum htmltag tag;
+
+ if (n->tok == MAN_SH) {
+ tag = TAG_H1;
+ class = "Sh";
+ } else {
+ tag = TAG_H2;
+ class = "Ss";
+ }
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
+ print_otag(h, TAG_SECTION, "c", class);
+ break;
+ case ROFFT_HEAD:
id = html_make_id(n, 1);
- print_otag(h, TAG_H1, "cTi", "Sh", id);
+ print_otag(h, tag, "ci", class, id);
if (id != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
+ break;
+ case ROFFT_BODY:
+ break;
+ default:
+ abort();
}
return 1;
}
@@ -428,11 +343,11 @@ static int
man_alt_pre(MAN_ARGS)
{
const struct roff_node *nn;
+ struct tag *t;
int i;
enum htmltag fp;
- struct tag *t;
- for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
+ for (i = 0, nn = n->child; nn != NULL; nn = nn->next, i++) {
switch (n->tok) {
case MAN_BI:
fp = i % 2 ? TAG_I : TAG_B;
@@ -474,88 +389,135 @@ static int
man_SM_pre(MAN_ARGS)
{
print_otag(h, TAG_SMALL, "");
- if (MAN_SB == n->tok)
+ if (n->tok == MAN_SB)
print_otag(h, TAG_B, "");
return 1;
}
static int
-man_SS_pre(MAN_ARGS)
+man_PP_pre(MAN_ARGS)
{
- char *id;
-
- if (n->type == ROFFT_HEAD) {
- id = html_make_id(n, 1);
- print_otag(h, TAG_H2, "cTi", "Ss", id);
- if (id != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
+ break;
+ case ROFFT_HEAD:
+ return 0;
+ case ROFFT_BODY:
+ if (n->child != NULL &&
+ (n->child->flags & NODE_NOFILL) == 0)
+ print_otag(h, TAG_P, "c",
+ n->tok == MAN_PP ? "Pp" : "Pp HP");
+ break;
+ default:
+ abort();
}
return 1;
}
-static int
-man_PP_pre(MAN_ARGS)
+static char
+list_continues(const struct roff_node *n1, const struct roff_node *n2)
{
-
- if (n->type == ROFFT_HEAD)
- return 0;
- else if (n->type == ROFFT_BLOCK)
- print_bvspace(h, n);
-
- return 1;
+ const char *s1, *s2;
+ char c1, c2;
+
+ if (n1 == NULL || n1->type != ROFFT_BLOCK ||
+ n2 == NULL || n2->type != ROFFT_BLOCK)
+ return '\0';
+ if ((n1->tok == MAN_TP || n1->tok == MAN_TQ) &&
+ (n2->tok == MAN_TP || n2->tok == MAN_TQ))
+ return ' ';
+ if (n1->tok != MAN_IP || n2->tok != MAN_IP)
+ return '\0';
+ n1 = n1->head->child;
+ n2 = n2->head->child;
+ s1 = n1 == NULL ? "" : n1->string;
+ s2 = n2 == NULL ? "" : n2->string;
+ c1 = strcmp(s1, "*") == 0 ? '*' :
+ strcmp(s1, "\\-") == 0 ? '-' :
+ strcmp(s1, "\\(bu") == 0 ? 'b' : ' ';
+ c2 = strcmp(s2, "*") == 0 ? '*' :
+ strcmp(s2, "\\-") == 0 ? '-' :
+ strcmp(s2, "\\(bu") == 0 ? 'b' : ' ';
+ return c1 != c2 ? '\0' : c1 == 'b' ? '*' : c1;
}
static int
man_IP_pre(MAN_ARGS)
{
const struct roff_node *nn;
+ const char *list_class;
+ enum htmltag list_elem, body_elem;
+ char list_type;
+
+ nn = n->type == ROFFT_BLOCK ? n : n->parent;
+ if ((list_type = list_continues(nn->prev, nn)) == '\0') {
+ /* Start a new list. */
+ if ((list_type = list_continues(nn, nn->next)) == '\0')
+ list_type = ' ';
+ switch (list_type) {
+ case ' ':
+ list_class = "Bl-tag";
+ list_elem = TAG_DL;
+ break;
+ case '*':
+ list_class = "Bl-bullet";
+ list_elem = TAG_UL;
+ break;
+ case '-':
+ list_class = "Bl-dash";
+ list_elem = TAG_UL;
+ break;
+ default:
+ abort();
+ }
+ } else {
+ /* Continue a list that was started earlier. */
+ list_class = NULL;
+ list_elem = TAG_MAX;
+ }
+ body_elem = list_type == ' ' ? TAG_DD : TAG_LI;
- if (n->type == ROFFT_BODY) {
- print_otag(h, TAG_DD, "");
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
+ if (list_elem != TAG_MAX)
+ print_otag(h, list_elem, "c", list_class);
return 1;
- } else if (n->type != ROFFT_HEAD) {
- print_otag(h, TAG_DL, "c", "Bl-tag");
+ case ROFFT_HEAD:
+ if (body_elem == TAG_LI)
+ return 0;
+ print_otag(h, TAG_DT, "");
+ break;
+ case ROFFT_BODY:
+ print_otag(h, body_elem, "");
return 1;
+ default:
+ abort();
}
- /* FIXME: width specification. */
-
- print_otag(h, TAG_DT, "");
-
- /* For IP, only print the first header element. */
-
- if (MAN_IP == n->tok && n->child)
- print_man_node(man, n->child, h);
-
- /* For TP, only print next-line header elements. */
-
- if (MAN_TP == n->tok) {
+ switch(n->tok) {
+ case MAN_IP: /* Only print the first header element. */
+ if (n->child != NULL)
+ print_man_node(man, n->child, h);
+ break;
+ case MAN_TP: /* Only print next-line header elements. */
+ case MAN_TQ:
nn = n->child;
- while (NULL != nn && 0 == (NODE_LINE & nn->flags))
+ while (nn != NULL && (NODE_LINE & nn->flags) == 0)
nn = nn->next;
- while (NULL != nn) {
+ while (nn != NULL) {
print_man_node(man, nn, h);
nn = nn->next;
}
+ break;
+ default:
+ abort();
}
-
return 0;
}
static int
-man_HP_pre(MAN_ARGS)
-{
- if (n->type == ROFFT_HEAD)
- return 0;
-
- if (n->type == ROFFT_BLOCK) {
- print_bvspace(h, n);
- print_otag(h, TAG_DIV, "c", "HP");
- }
- return 1;
-}
-
-static int
man_OP_pre(MAN_ARGS)
{
struct tag *tt;
@@ -564,14 +526,14 @@ man_OP_pre(MAN_ARGS)
h->flags |= HTML_NOSPACE;
tt = print_otag(h, TAG_SPAN, "c", "Op");
- if (NULL != (n = n->child)) {
+ if ((n = n->child) != NULL) {
print_otag(h, TAG_B, "");
print_text(h, n->string);
}
print_stagq(h, tt);
- if (NULL != n && NULL != n->next) {
+ if (n != NULL && n->next != NULL) {
print_otag(h, TAG_I, "");
print_text(h, n->next->string);
}
@@ -606,17 +568,46 @@ man_in_pre(MAN_ARGS)
static int
man_ign_pre(MAN_ARGS)
{
-
return 0;
}
static int
man_RS_pre(MAN_ARGS)
{
- if (n->type == ROFFT_HEAD)
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
+ break;
+ case ROFFT_HEAD:
return 0;
- if (n->type == ROFFT_BLOCK)
+ case ROFFT_BODY:
print_otag(h, TAG_DIV, "c", "Bd-indent");
+ break;
+ default:
+ abort();
+ }
+ return 1;
+}
+
+static int
+man_SY_pre(MAN_ARGS)
+{
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
+ print_otag(h, TAG_TABLE, "c", "Nm");
+ print_otag(h, TAG_TR, "");
+ break;
+ case ROFFT_HEAD:
+ print_otag(h, TAG_TD, "");
+ print_otag(h, TAG_CODE, "c", "Nm");
+ break;
+ case ROFFT_BODY:
+ print_otag(h, TAG_TD, "");
+ break;
+ default:
+ abort();
+ }
return 1;
}
@@ -624,16 +615,17 @@ static int
man_UR_pre(MAN_ARGS)
{
char *cp;
+
n = n->child;
assert(n->type == ROFFT_HEAD);
if (n->child != NULL) {
assert(n->child->type == ROFFT_TEXT);
if (n->tok == MAN_MT) {
mandoc_asprintf(&cp, "mailto:%s", n->child->string);
- print_otag(h, TAG_A, "cTh", "Mt", cp);
+ print_otag(h, TAG_A, "ch", "Mt", cp);
free(cp);
} else
- print_otag(h, TAG_A, "cTh", "Lk", n->child->string);
+ print_otag(h, TAG_A, "ch", "Lk", n->child->string);
}
assert(n->next->type == ROFFT_BODY);
@@ -641,6 +633,11 @@ man_UR_pre(MAN_ARGS)
n = n->next;
print_man_nodelist(man, n->child, h);
-
return 0;
}
+
+static int
+man_abort_pre(MAN_ARGS)
+{
+ abort();
+}
diff --git a/man_macro.c b/man_macro.c
index aa8b200196a6..d195576dee28 100644
--- a/man_macro.c
+++ b/man_macro.c
@@ -1,7 +1,7 @@
-/* $Id: man_macro.c,v 1.123 2017/06/25 11:45:37 schwarze Exp $ */
+/* $Id: man_macro.c,v 1.144 2019/01/05 18:59:46 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -22,6 +22,7 @@
#include <assert.h>
#include <ctype.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -40,47 +41,54 @@ static int man_args(struct roff_man *, int,
int *, char *, char **);
static void rew_scope(struct roff_man *, enum roff_tok);
-const struct man_macro __man_macros[MAN_MAX - MAN_TH] = {
- { in_line_eoln, MAN_BSCOPE }, /* TH */
- { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */
- { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */
- { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* TP */
- { blk_imp, MAN_BSCOPE }, /* LP */
- { blk_imp, MAN_BSCOPE }, /* PP */
- { blk_imp, MAN_BSCOPE }, /* P */
- { blk_imp, MAN_BSCOPE }, /* IP */
- { blk_imp, MAN_BSCOPE }, /* HP */
- { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* SM */
- { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* SB */
+static const struct man_macro man_macros[MAN_MAX - MAN_TH] = {
+ { in_line_eoln, MAN_XSCOPE }, /* TH */
+ { blk_imp, MAN_XSCOPE | MAN_BSCOPED }, /* SH */
+ { blk_imp, MAN_XSCOPE | MAN_BSCOPED }, /* SS */
+ { blk_imp, MAN_XSCOPE | MAN_BSCOPED }, /* TP */
+ { blk_imp, MAN_XSCOPE | MAN_BSCOPED }, /* TQ */
+ { blk_imp, MAN_XSCOPE }, /* LP */
+ { blk_imp, MAN_XSCOPE }, /* PP */
+ { blk_imp, MAN_XSCOPE }, /* P */
+ { blk_imp, MAN_XSCOPE }, /* IP */
+ { blk_imp, MAN_XSCOPE }, /* HP */
+ { in_line_eoln, MAN_NSCOPED | MAN_ESCOPED | MAN_JOIN }, /* SM */
+ { in_line_eoln, MAN_NSCOPED | MAN_ESCOPED | MAN_JOIN }, /* SB */
{ in_line_eoln, 0 }, /* BI */
{ in_line_eoln, 0 }, /* IB */
{ in_line_eoln, 0 }, /* BR */
{ in_line_eoln, 0 }, /* RB */
- { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* R */
- { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* B */
- { in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* I */
+ { in_line_eoln, MAN_NSCOPED | MAN_ESCOPED | MAN_JOIN }, /* R */
+ { in_line_eoln, MAN_NSCOPED | MAN_ESCOPED | MAN_JOIN }, /* B */
+ { in_line_eoln, MAN_NSCOPED | MAN_ESCOPED | MAN_JOIN }, /* I */
{ in_line_eoln, 0 }, /* IR */
{ in_line_eoln, 0 }, /* RI */
- { in_line_eoln, MAN_NSCOPED }, /* nf */
- { in_line_eoln, MAN_NSCOPED }, /* fi */
- { blk_close, MAN_BSCOPE }, /* RE */
- { blk_exp, MAN_BSCOPE }, /* RS */
+ { blk_close, MAN_XSCOPE }, /* RE */
+ { blk_exp, MAN_XSCOPE }, /* RS */
{ in_line_eoln, 0 }, /* DT */
{ in_line_eoln, 0 }, /* UC */
{ in_line_eoln, MAN_NSCOPED }, /* PD */
{ in_line_eoln, 0 }, /* AT */
{ in_line_eoln, MAN_NSCOPED }, /* in */
+ { blk_imp, MAN_XSCOPE }, /* SY */
+ { blk_close, MAN_XSCOPE }, /* YS */
{ in_line_eoln, 0 }, /* OP */
- { in_line_eoln, MAN_BSCOPE }, /* EX */
- { in_line_eoln, MAN_BSCOPE }, /* EE */
- { blk_exp, MAN_BSCOPE }, /* UR */
- { blk_close, MAN_BSCOPE }, /* UE */
- { blk_exp, MAN_BSCOPE }, /* MT */
- { blk_close, MAN_BSCOPE }, /* ME */
+ { in_line_eoln, MAN_XSCOPE }, /* EX */
+ { in_line_eoln, MAN_XSCOPE }, /* EE */
+ { blk_exp, MAN_XSCOPE }, /* UR */
+ { blk_close, MAN_XSCOPE }, /* UE */
+ { blk_exp, MAN_XSCOPE }, /* MT */
+ { blk_close, MAN_XSCOPE }, /* ME */
};
-const struct man_macro *const man_macros = __man_macros - MAN_TH;
+const struct man_macro *
+man_macro(enum roff_tok tok)
+{
+ assert(tok >= MAN_TH && tok <= MAN_MAX);
+ return man_macros + (tok - MAN_TH);
+}
+
void
man_unscope(struct roff_man *man, const struct roff_node *to)
{
@@ -94,9 +102,10 @@ man_unscope(struct roff_man *man, const struct roff_node *to)
if (to == NULL && ! (n->flags & NODE_VALID)) {
if (man->flags & (MAN_BLINE | MAN_ELINE) &&
- man_macros[n->tok].flags & MAN_SCOPED) {
- mandoc_vmsg(MANDOCERR_BLK_LINE,
- man->parse, n->line, n->pos,
+ man_macro(n->tok)->flags &
+ (MAN_BSCOPED | MAN_NSCOPED)) {
+ mandoc_msg(MANDOCERR_BLK_LINE,
+ n->line, n->pos,
"EOF breaks %s", roff_name[n->tok]);
if (man->flags & MAN_ELINE)
man->flags &= ~MAN_ELINE;
@@ -111,9 +120,9 @@ man_unscope(struct roff_man *man, const struct roff_node *to)
continue;
}
if (n->type == ROFFT_BLOCK &&
- man_macros[n->tok].fp == blk_exp)
+ man_macro(n->tok)->fp == blk_exp)
mandoc_msg(MANDOCERR_BLK_NOEND,
- man->parse, n->line, n->pos,
+ n->line, n->pos, "%s",
roff_name[n->tok]);
}
@@ -175,7 +184,7 @@ rew_scope(struct roff_man *man, enum roff_tok tok)
}
if (tok != MAN_SH && (n->tok == MAN_SH ||
(tok != MAN_SS && (n->tok == MAN_SS ||
- man_macros[n->tok].fp == blk_exp))))
+ man_macro(n->tok)->fp == blk_exp))))
return;
man_unscope(man, n);
n = man->last;
@@ -189,33 +198,39 @@ rew_scope(struct roff_man *man, enum roff_tok tok)
void
blk_close(MACRO_PROT_ARGS)
{
- enum roff_tok ntok;
+ enum roff_tok ctok, ntok;
const struct roff_node *nn;
- char *p;
- int nrew, target;
+ char *p, *ep;
+ int cline, cpos, la, nrew, target;
nrew = 1;
switch (tok) {
case MAN_RE:
ntok = MAN_RS;
+ la = *pos;
if ( ! man_args(man, line, pos, buf, &p))
break;
for (nn = man->last->parent; nn; nn = nn->parent)
if (nn->tok == ntok && nn->type == ROFFT_BLOCK)
nrew++;
- target = strtol(p, &p, 10);
- if (*p != '\0')
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse,
- line, p - buf, "RE ... %s", p);
+ target = strtol(p, &ep, 10);
+ if (*ep != '\0')
+ mandoc_msg(MANDOCERR_ARG_EXCESS, line,
+ la + (buf[la] == '"') + (int)(ep - p),
+ "RE ... %s", ep);
+ free(p);
if (target == 0)
target = 1;
nrew -= target;
if (nrew < 1) {
- mandoc_vmsg(MANDOCERR_RE_NOTOPEN, man->parse,
+ mandoc_msg(MANDOCERR_RE_NOTOPEN,
line, ppos, "RE %d", target);
return;
}
break;
+ case MAN_YS:
+ ntok = MAN_SY;
+ break;
case MAN_UE:
ntok = MAN_UR;
break;
@@ -231,25 +246,47 @@ blk_close(MACRO_PROT_ARGS)
break;
if (nn == NULL) {
- mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse,
- line, ppos, roff_name[tok]);
+ mandoc_msg(MANDOCERR_BLK_NOTOPEN,
+ line, ppos, "%s", roff_name[tok]);
rew_scope(man, MAN_PP);
- } else {
- line = man->last->line;
- ppos = man->last->pos;
- ntok = man->last->tok;
- man_unscope(man, nn);
+ if (tok == MAN_RE) {
+ roff_elem_alloc(man, line, ppos, ROFF_br);
+ man->last->flags |= NODE_LINE |
+ NODE_VALID | NODE_ENDED;
+ man->next = ROFF_NEXT_SIBLING;
+ }
+ return;
+ }
- if (tok == MAN_RE && nn->head->aux > 0)
- roff_setreg(man->roff, "an-margin",
- nn->head->aux, '-');
+ cline = man->last->line;
+ cpos = man->last->pos;
+ ctok = man->last->tok;
+ man_unscope(man, nn);
- /* Move a trailing paragraph behind the block. */
+ if (tok == MAN_RE && nn->head->aux > 0)
+ roff_setreg(man->roff, "an-margin", nn->head->aux, '-');
- if (ntok == MAN_LP || ntok == MAN_PP || ntok == MAN_P) {
- *pos = strlen(buf);
- blk_imp(man, ntok, line, ppos, pos, buf);
- }
+ /* Trailing text. */
+
+ if (buf[*pos] != '\0') {
+ roff_word_alloc(man, line, ppos, buf + *pos);
+ man->last->flags |= NODE_DELIMC;
+ if (mandoc_eos(man->last->string, strlen(man->last->string)))
+ man->last->flags |= NODE_EOS;
+ }
+
+ /* Move a trailing paragraph behind the block. */
+
+ if (ctok == MAN_LP || ctok == MAN_PP || ctok == MAN_P) {
+ *pos = strlen(buf);
+ blk_imp(man, ctok, cline, cpos, pos, buf);
+ }
+
+ /* Synopsis blocks need an explicit end marker for spacing. */
+
+ if (tok == MAN_YS && man->last == nn) {
+ roff_elem_alloc(man, line, ppos, tok);
+ man_unscope(man, man->last);
}
}
@@ -260,7 +297,10 @@ blk_exp(MACRO_PROT_ARGS)
char *p;
int la;
- rew_scope(man, tok);
+ if (tok == MAN_RS) {
+ rew_scope(man, tok);
+ man->flags |= ROFF_NONOFILL;
+ }
roff_block_alloc(man, line, ppos, tok);
head = roff_head_alloc(man, line, ppos, tok);
@@ -275,14 +315,16 @@ blk_exp(MACRO_PROT_ARGS)
roff_setreg(man->roff, "an-margin",
head->aux, '+');
}
+ free(p);
}
if (buf[*pos] != '\0')
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse, line,
- *pos, "%s ... %s", roff_name[tok], buf + *pos);
+ mandoc_msg(MANDOCERR_ARG_EXCESS, line, *pos,
+ "%s ... %s", roff_name[tok], buf + *pos);
man_unscope(man, head);
roff_body_alloc(man, line, ppos, tok);
+ man->flags &= ~ROFF_NONOFILL;
}
/*
@@ -299,9 +341,10 @@ blk_imp(MACRO_PROT_ARGS)
struct roff_node *n;
rew_scope(man, tok);
- n = roff_block_alloc(man, line, ppos, tok);
- if (n->tok == MAN_SH || n->tok == MAN_SS)
- man->flags &= ~MAN_LITERAL;
+ man->flags |= ROFF_NONOFILL;
+ if (tok == MAN_SH || tok == MAN_SS)
+ man->flags &= ~ROFF_NOFILL;
+ roff_block_alloc(man, line, ppos, tok);
n = roff_head_alloc(man, line, ppos, tok);
/* Add line arguments. */
@@ -311,16 +354,17 @@ blk_imp(MACRO_PROT_ARGS)
if ( ! man_args(man, line, pos, buf, &p))
break;
roff_word_alloc(man, line, la, p);
+ free(p);
}
/*
* For macros having optional next-line scope,
* keep the head open if there were no arguments.
- * For `TP', always keep the head open.
+ * For `TP' and `TQ', always keep the head open.
*/
- if (man_macros[tok].flags & MAN_SCOPED &&
- (tok == MAN_TP || n == man->last)) {
+ if (man_macro(tok)->flags & MAN_BSCOPED &&
+ (tok == MAN_TP || tok == MAN_TQ || n == man->last)) {
man->flags |= MAN_BLINE;
return;
}
@@ -329,6 +373,7 @@ blk_imp(MACRO_PROT_ARGS)
man_unscope(man, n);
roff_body_alloc(man, line, ppos, tok);
+ man->flags &= ~ROFF_NONOFILL;
}
void
@@ -341,27 +386,26 @@ in_line_eoln(MACRO_PROT_ARGS)
roff_elem_alloc(man, line, ppos, tok);
n = man->last;
+ if (tok == MAN_EX)
+ man->flags |= ROFF_NOFILL;
+ else if (tok == MAN_EE)
+ man->flags &= ~ROFF_NOFILL;
+
for (;;) {
- if (buf[*pos] != '\0' && (tok == MAN_fi || tok == MAN_nf)) {
- mandoc_vmsg(MANDOCERR_ARG_SKIP,
- man->parse, line, *pos, "%s %s",
- roff_name[tok], buf + *pos);
- break;
- }
if (buf[*pos] != '\0' && man->last != n && tok == MAN_PD) {
- mandoc_vmsg(MANDOCERR_ARG_EXCESS,
- man->parse, line, *pos, "%s ... %s",
- roff_name[tok], buf + *pos);
+ mandoc_msg(MANDOCERR_ARG_EXCESS, line, *pos,
+ "%s ... %s", roff_name[tok], buf + *pos);
break;
}
la = *pos;
if ( ! man_args(man, line, pos, buf, &p))
break;
- if (man_macros[tok].flags & MAN_JOIN &&
+ if (man_macro(tok)->flags & MAN_JOIN &&
man->last->type == ROFFT_TEXT)
roff_word_append(man, p);
else
roff_word_alloc(man, line, la, p);
+ free(p);
}
/*
@@ -374,13 +418,12 @@ in_line_eoln(MACRO_PROT_ARGS)
man->last->flags |= NODE_EOS;
/*
- * If no arguments are specified and this is MAN_SCOPED (i.e.,
+ * If no arguments are specified and this is MAN_ESCOPED (i.e.,
* next-line scoped), then set our mode to indicate that we're
* waiting for terms to load into our context.
*/
- if (n == man->last && man_macros[tok].flags & MAN_SCOPED) {
- assert( ! (man_macros[tok].flags & MAN_NSCOPED));
+ if (n == man->last && man_macro(tok)->flags & MAN_ESCOPED) {
man->flags |= MAN_ELINE;
return;
}
@@ -391,18 +434,21 @@ in_line_eoln(MACRO_PROT_ARGS)
/* Rewind our element scope. */
for ( ; man->last; man->last = man->last->parent) {
- man_state(man, man->last);
+ man->last->flags |= NODE_VALID;
if (man->last == n)
break;
}
+
+ /* Rewind next-line scoped ancestors, if any. */
+
+ if (man_macro(tok)->flags & MAN_ESCOPED)
+ man_descope(man, line, ppos, NULL);
}
void
man_endparse(struct roff_man *man)
{
-
- man_unscope(man, man->first);
- man->flags &= ~MAN_LITERAL;
+ man_unscope(man, man->meta.first);
}
static int
@@ -417,6 +463,6 @@ man_args(struct roff_man *man, int line, int *pos, char *buf, char **v)
if ('\0' == *start)
return 0;
- *v = mandoc_getarg(man->parse, v, line, pos);
+ *v = roff_getarg(man->roff, v, line, pos);
return 1;
}
diff --git a/man_term.c b/man_term.c
index b5723ccf8383..d867762dcace 100644
--- a/man_term.c
+++ b/man_term.c
@@ -1,7 +1,7 @@
-/* $Id: man_term.c,v 1.211 2018/06/10 15:12:35 schwarze Exp $ */
+/* $Id: man_term.c,v 1.228 2019/01/05 21:18:26 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,7 +27,6 @@
#include <string.h>
#include "mandoc_aux.h"
-#include "mandoc.h"
#include "roff.h"
#include "man.h"
#include "out.h"
@@ -37,8 +36,6 @@
#define MAXMARGINS 64 /* maximum number of indented scopes */
struct mtermp {
- int fl;
-#define MANT_LITERAL (1 << 0)
int lmargin[MAXMARGINS]; /* margins (incl. vis. page) */
int lmargincur; /* index of current margin */
int lmarginsz; /* actual number of nested margins */
@@ -51,7 +48,7 @@ struct mtermp {
struct roff_node *n, \
const struct roff_meta *meta
-struct termact {
+struct man_term_act {
int (*pre)(DECL_ARGS);
void (*post)(DECL_ARGS);
int flags;
@@ -78,8 +75,10 @@ static int pre_PP(DECL_ARGS);
static int pre_RS(DECL_ARGS);
static int pre_SH(DECL_ARGS);
static int pre_SS(DECL_ARGS);
+static int pre_SY(DECL_ARGS);
static int pre_TP(DECL_ARGS);
static int pre_UR(DECL_ARGS);
+static int pre_abort(DECL_ARGS);
static int pre_alternate(DECL_ARGS);
static int pre_ign(DECL_ARGS);
static int pre_in(DECL_ARGS);
@@ -89,18 +88,19 @@ static void post_IP(DECL_ARGS);
static void post_HP(DECL_ARGS);
static void post_RS(DECL_ARGS);
static void post_SH(DECL_ARGS);
-static void post_SS(DECL_ARGS);
+static void post_SY(DECL_ARGS);
static void post_TP(DECL_ARGS);
static void post_UR(DECL_ARGS);
-static const struct termact __termacts[MAN_MAX - MAN_TH] = {
+static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = {
{ NULL, NULL, 0 }, /* TH */
{ pre_SH, post_SH, 0 }, /* SH */
- { pre_SS, post_SS, 0 }, /* SS */
+ { pre_SS, post_SH, 0 }, /* SS */
{ pre_TP, post_TP, 0 }, /* TP */
- { pre_PP, NULL, 0 }, /* LP */
+ { pre_TP, post_TP, 0 }, /* TQ */
+ { pre_abort, NULL, 0 }, /* LP */
{ pre_PP, NULL, 0 }, /* PP */
- { pre_PP, NULL, 0 }, /* P */
+ { pre_abort, NULL, 0 }, /* P */
{ pre_IP, post_IP, 0 }, /* IP */
{ pre_HP, post_HP, 0 }, /* HP */
{ NULL, NULL, 0 }, /* SM */
@@ -114,8 +114,6 @@ static const struct termact __termacts[MAN_MAX - MAN_TH] = {
{ pre_I, NULL, 0 }, /* I */
{ pre_alternate, NULL, 0 }, /* IR */
{ pre_alternate, NULL, 0 }, /* RI */
- { pre_literal, NULL, 0 }, /* nf */
- { pre_literal, NULL, 0 }, /* fi */
{ NULL, NULL, 0 }, /* RE */
{ pre_RS, post_RS, 0 }, /* RS */
{ pre_DT, NULL, 0 }, /* DT */
@@ -123,6 +121,8 @@ static const struct termact __termacts[MAN_MAX - MAN_TH] = {
{ pre_PD, NULL, MAN_NOTEXT }, /* PD */
{ pre_ign, NULL, 0 }, /* AT */
{ pre_in, NULL, MAN_NOTEXT }, /* in */
+ { pre_SY, post_SY, 0 }, /* SY */
+ { NULL, NULL, 0 }, /* YS */
{ pre_OP, NULL, 0 }, /* OP */
{ pre_literal, NULL, 0 }, /* EX */
{ pre_literal, NULL, 0 }, /* EE */
@@ -131,15 +131,22 @@ static const struct termact __termacts[MAN_MAX - MAN_TH] = {
{ pre_UR, post_UR, 0 }, /* MT */
{ NULL, NULL, 0 }, /* ME */
};
-static const struct termact *termacts = __termacts - MAN_TH;
+static const struct man_term_act *man_term_act(enum roff_tok);
+static const struct man_term_act *
+man_term_act(enum roff_tok tok)
+{
+ assert(tok >= MAN_TH && tok <= MAN_MAX);
+ return man_term_acts + (tok - MAN_TH);
+}
+
void
-terminal_man(void *arg, const struct roff_man *man)
+terminal_man(void *arg, const struct roff_meta *man)
{
+ struct mtermp mt;
struct termp *p;
struct roff_node *n;
- struct mtermp mt;
size_t save_defindent;
p = (struct termp *)arg;
@@ -151,7 +158,7 @@ terminal_man(void *arg, const struct roff_man *man)
term_tab_set(p, "T");
term_tab_set(p, ".5i");
- memset(&mt, 0, sizeof(struct mtermp));
+ memset(&mt, 0, sizeof(mt));
mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
mt.offset = term_len(p, p->defindent);
mt.pardist = 1;
@@ -164,18 +171,17 @@ terminal_man(void *arg, const struct roff_man *man)
!strcmp(n->child->child->string, "SYNOPSIS")) {
if (n->child->next->child != NULL)
print_man_nodelist(p, &mt,
- n->child->next->child,
- &man->meta);
+ n->child->next->child, man);
term_newln(p);
break;
}
n = n->next;
}
} else {
- term_begin(p, print_man_head, print_man_foot, &man->meta);
+ term_begin(p, print_man_head, print_man_foot, man);
p->flags |= TERMP_NOSPACE;
if (n != NULL)
- print_man_nodelist(p, &mt, n, &man->meta);
+ print_man_nodelist(p, &mt, n, man);
term_end(p);
}
p->defindent = save_defindent;
@@ -196,12 +202,12 @@ print_bvspace(struct termp *p, const struct roff_node *n, int pardist)
term_newln(p);
- if (n->body && n->body->child)
+ if (n->body != NULL && n->body->child != NULL)
if (n->body->child->type == ROFFT_TBL)
return;
if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS)
- if (NULL == n->prev)
+ if (n->prev == NULL)
return;
for (i = 0; i < pardist; i++)
@@ -210,16 +216,20 @@ print_bvspace(struct termp *p, const struct roff_node *n, int pardist)
static int
-pre_ign(DECL_ARGS)
+pre_abort(DECL_ARGS)
{
+ abort();
+}
+static int
+pre_ign(DECL_ARGS)
+{
return 0;
}
static int
pre_I(DECL_ARGS)
{
-
term_fontrepl(p, TERMFONT_UNDER);
return 1;
}
@@ -227,14 +237,8 @@ pre_I(DECL_ARGS)
static int
pre_literal(DECL_ARGS)
{
-
term_newln(p);
- if (n->tok == MAN_nf || n->tok == MAN_EX)
- mt->fl |= MANT_LITERAL;
- else
- mt->fl &= ~MANT_LITERAL;
-
/*
* Unlike .IP and .TP, .HP does not have a HEAD.
* So in case a second call to term_flushln() is needed,
@@ -247,7 +251,6 @@ pre_literal(DECL_ARGS)
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
p->flags |= TERMP_NOSPACE;
}
-
return 0;
}
@@ -272,7 +275,7 @@ pre_alternate(DECL_ARGS)
{
enum termfont font[2];
struct roff_node *nn;
- int savelit, i;
+ int i;
switch (n->tok) {
case MAN_RB:
@@ -302,29 +305,21 @@ pre_alternate(DECL_ARGS)
default:
abort();
}
-
- savelit = MANT_LITERAL & mt->fl;
- mt->fl &= ~MANT_LITERAL;
-
- for (i = 0, nn = n->child; nn; nn = nn->next, i = 1 - i) {
+ for (i = 0, nn = n->child; nn != NULL; nn = nn->next, i = 1 - i) {
term_fontrepl(p, font[i]);
- if (savelit && NULL == nn->next)
- mt->fl |= MANT_LITERAL;
assert(nn->type == ROFFT_TEXT);
term_word(p, nn->string);
if (nn->flags & NODE_EOS)
p->flags |= TERMP_SENTENCE;
- if (nn->next)
+ if (nn->next != NULL)
p->flags |= TERMP_NOSPACE;
}
-
return 0;
}
static int
pre_B(DECL_ARGS)
{
-
term_fontrepl(p, TERMFONT_BOLD);
return 1;
}
@@ -332,20 +327,19 @@ pre_B(DECL_ARGS)
static int
pre_OP(DECL_ARGS)
{
-
term_word(p, "[");
- p->flags |= TERMP_NOSPACE;
+ p->flags |= TERMP_KEEP | TERMP_NOSPACE;
- if (NULL != (n = n->child)) {
+ if ((n = n->child) != NULL) {
term_fontrepl(p, TERMFONT_BOLD);
term_word(p, n->string);
}
- if (NULL != n && NULL != n->next) {
+ if (n != NULL && n->next != NULL) {
term_fontrepl(p, TERMFONT_UNDER);
term_word(p, n->next->string);
}
-
term_fontrepl(p, TERMFONT_NONE);
+ p->flags &= ~TERMP_KEEP;
p->flags |= TERMP_NOSPACE;
term_word(p, "]");
return 0;
@@ -369,9 +363,9 @@ pre_in(DECL_ARGS)
cp = n->child->string;
less = 0;
- if ('-' == *cp)
+ if (*cp == '-')
less = -1;
- else if ('+' == *cp)
+ else if (*cp == '+')
less = 1;
else
cp--;
@@ -413,13 +407,18 @@ pre_HP(DECL_ARGS)
case ROFFT_BLOCK:
print_bvspace(p, n, mt->pardist);
return 1;
+ case ROFFT_HEAD:
+ return 0;
case ROFFT_BODY:
break;
default:
- return 0;
+ abort();
}
- if ( ! (MANT_LITERAL & mt->fl)) {
+ if (n->child == NULL)
+ return 0;
+
+ if ((n->child->flags & NODE_NOFILL) == 0) {
p->flags |= TERMP_NOBREAK | TERMP_BRIND;
p->trailspace = 2;
}
@@ -445,8 +444,10 @@ pre_HP(DECL_ARGS)
static void
post_HP(DECL_ARGS)
{
-
switch (n->type) {
+ case ROFFT_BLOCK:
+ case ROFFT_HEAD:
+ break;
case ROFFT_BODY:
term_newln(p);
@@ -466,25 +467,27 @@ post_HP(DECL_ARGS)
p->tcol->rmargin = p->maxrmargin;
break;
default:
- break;
+ abort();
}
}
static int
pre_PP(DECL_ARGS)
{
-
switch (n->type) {
case ROFFT_BLOCK:
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
print_bvspace(p, n, mt->pardist);
break;
- default:
+ case ROFFT_HEAD:
+ return 0;
+ case ROFFT_BODY:
p->tcol->offset = mt->offset;
break;
+ default:
+ abort();
}
-
- return n->type != ROFFT_HEAD;
+ return 1;
}
static int
@@ -492,21 +495,21 @@ pre_IP(DECL_ARGS)
{
struct roffsu su;
const struct roff_node *nn;
- int len, savelit;
+ int len;
switch (n->type) {
- case ROFFT_BODY:
- p->flags |= TERMP_NOSPACE;
- break;
+ case ROFFT_BLOCK:
+ print_bvspace(p, n, mt->pardist);
+ return 1;
case ROFFT_HEAD:
p->flags |= TERMP_NOBREAK;
p->trailspace = 1;
break;
- case ROFFT_BLOCK:
- print_bvspace(p, n, mt->pardist);
- /* FALLTHROUGH */
+ case ROFFT_BODY:
+ p->flags |= TERMP_NOSPACE;
+ break;
default:
- return 1;
+ abort();
}
/* Calculate the offset from the optional second argument. */
@@ -526,33 +529,25 @@ pre_IP(DECL_ARGS)
case ROFFT_HEAD:
p->tcol->offset = mt->offset;
p->tcol->rmargin = mt->offset + len;
-
- savelit = MANT_LITERAL & mt->fl;
- mt->fl &= ~MANT_LITERAL;
-
- if (n->child)
+ if (n->child != NULL)
print_man_node(p, mt, n->child, meta);
-
- if (savelit)
- mt->fl |= MANT_LITERAL;
-
return 0;
case ROFFT_BODY:
p->tcol->offset = mt->offset + len;
p->tcol->rmargin = p->maxrmargin;
break;
default:
- break;
+ abort();
}
-
return 1;
}
static void
post_IP(DECL_ARGS)
{
-
switch (n->type) {
+ case ROFFT_BLOCK:
+ break;
case ROFFT_HEAD:
term_flushln(p);
p->flags &= ~TERMP_NOBREAK;
@@ -564,7 +559,7 @@ post_IP(DECL_ARGS)
p->tcol->offset = mt->offset;
break;
default:
- break;
+ abort();
}
}
@@ -573,9 +568,13 @@ pre_TP(DECL_ARGS)
{
struct roffsu su;
struct roff_node *nn;
- int len, savelit;
+ int len;
switch (n->type) {
+ case ROFFT_BLOCK:
+ if (n->tok == MAN_TP)
+ print_bvspace(p, n, mt->pardist);
+ return 1;
case ROFFT_HEAD:
p->flags |= TERMP_NOBREAK | TERMP_BRTRSP;
p->trailspace = 1;
@@ -583,11 +582,8 @@ pre_TP(DECL_ARGS)
case ROFFT_BODY:
p->flags |= TERMP_NOSPACE;
break;
- case ROFFT_BLOCK:
- print_bvspace(p, n, mt->pardist);
- /* FALLTHROUGH */
default:
- return 1;
+ abort();
}
/* Calculate offset. */
@@ -609,21 +605,15 @@ pre_TP(DECL_ARGS)
p->tcol->offset = mt->offset;
p->tcol->rmargin = mt->offset + len;
- savelit = MANT_LITERAL & mt->fl;
- mt->fl &= ~MANT_LITERAL;
-
/* Don't print same-line elements. */
nn = n->child;
- while (NULL != nn && 0 == (NODE_LINE & nn->flags))
+ while (nn != NULL && (nn->flags & NODE_LINE) == 0)
nn = nn->next;
- while (NULL != nn) {
+ while (nn != NULL) {
print_man_node(p, mt, nn, meta);
nn = nn->next;
}
-
- if (savelit)
- mt->fl |= MANT_LITERAL;
return 0;
case ROFFT_BODY:
p->tcol->offset = mt->offset + len;
@@ -632,17 +622,17 @@ pre_TP(DECL_ARGS)
p->flags &= ~(TERMP_NOBREAK | TERMP_BRTRSP);
break;
default:
- break;
+ abort();
}
-
return 1;
}
static void
post_TP(DECL_ARGS)
{
-
switch (n->type) {
+ case ROFFT_BLOCK:
+ break;
case ROFFT_HEAD:
term_flushln(p);
break;
@@ -651,7 +641,7 @@ post_TP(DECL_ARGS)
p->tcol->offset = mt->offset;
break;
default:
- break;
+ abort();
}
}
@@ -662,7 +652,6 @@ pre_SS(DECL_ARGS)
switch (n->type) {
case ROFFT_BLOCK:
- mt->fl &= ~MANT_LITERAL;
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
mt->offset = term_len(p, p->defindent);
@@ -674,7 +663,7 @@ pre_SS(DECL_ARGS)
do {
n = n->prev;
} while (n != NULL && n->tok >= MAN_TH &&
- termacts[n->tok].flags & MAN_NOTEXT);
+ man_term_act(n->tok)->flags & MAN_NOTEXT);
if (n == NULL || n->type == ROFFT_COMMENT ||
(n->tok == MAN_SS && n->body->child == NULL))
break;
@@ -698,26 +687,9 @@ pre_SS(DECL_ARGS)
default:
break;
}
-
return 1;
}
-static void
-post_SS(DECL_ARGS)
-{
-
- switch (n->type) {
- case ROFFT_HEAD:
- term_newln(p);
- break;
- case ROFFT_BODY:
- term_newln(p);
- break;
- default:
- break;
- }
-}
-
static int
pre_SH(DECL_ARGS)
{
@@ -725,7 +697,6 @@ pre_SH(DECL_ARGS)
switch (n->type) {
case ROFFT_BLOCK:
- mt->fl &= ~MANT_LITERAL;
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
mt->offset = term_len(p, p->defindent);
@@ -737,7 +708,7 @@ pre_SH(DECL_ARGS)
do {
n = n->prev;
} while (n != NULL && n->tok >= MAN_TH &&
- termacts[n->tok].flags & MAN_NOTEXT);
+ man_term_act(n->tok)->flags & MAN_NOTEXT);
if (n == NULL || n->type == ROFFT_COMMENT ||
(n->tok == MAN_SH && n->body->child == NULL))
break;
@@ -759,25 +730,23 @@ pre_SH(DECL_ARGS)
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
break;
default:
- break;
+ abort();
}
-
return 1;
}
static void
post_SH(DECL_ARGS)
{
-
switch (n->type) {
- case ROFFT_HEAD:
- term_newln(p);
+ case ROFFT_BLOCK:
break;
+ case ROFFT_HEAD:
case ROFFT_BODY:
term_newln(p);
break;
default:
- break;
+ abort();
}
}
@@ -792,8 +761,10 @@ pre_RS(DECL_ARGS)
return 1;
case ROFFT_HEAD:
return 0;
- default:
+ case ROFFT_BODY:
break;
+ default:
+ abort();
}
n = n->parent->head;
@@ -821,42 +792,99 @@ pre_RS(DECL_ARGS)
static void
post_RS(DECL_ARGS)
{
-
switch (n->type) {
case ROFFT_BLOCK:
- return;
case ROFFT_HEAD:
return;
- default:
- term_newln(p);
+ case ROFFT_BODY:
break;
+ default:
+ abort();
}
-
+ term_newln(p);
mt->offset -= n->parent->head->aux;
p->tcol->offset = mt->offset;
-
if (--mt->lmarginsz < MAXMARGINS)
mt->lmargincur = mt->lmarginsz;
}
static int
-pre_UR(DECL_ARGS)
+pre_SY(DECL_ARGS)
+{
+ const struct roff_node *nn;
+ int len;
+
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ if (n->prev == NULL || n->prev->tok != MAN_SY)
+ print_bvspace(p, n, mt->pardist);
+ return 1;
+ case ROFFT_HEAD:
+ case ROFFT_BODY:
+ break;
+ default:
+ abort();
+ }
+
+ nn = n->parent->head->child;
+ len = nn == NULL ? 1 : term_strlen(p, nn->string) + 1;
+
+ switch (n->type) {
+ case ROFFT_HEAD:
+ p->tcol->offset = mt->offset;
+ p->tcol->rmargin = mt->offset + len;
+ if (n->next->child == NULL ||
+ (n->next->child->flags & NODE_NOFILL) == 0)
+ p->flags |= TERMP_NOBREAK;
+ term_fontrepl(p, TERMFONT_BOLD);
+ break;
+ case ROFFT_BODY:
+ mt->lmargin[mt->lmargincur] = len;
+ p->tcol->offset = mt->offset + len;
+ p->tcol->rmargin = p->maxrmargin;
+ p->flags |= TERMP_NOSPACE;
+ break;
+ default:
+ abort();
+ }
+ return 1;
+}
+
+static void
+post_SY(DECL_ARGS)
{
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ break;
+ case ROFFT_HEAD:
+ term_flushln(p);
+ p->flags &= ~TERMP_NOBREAK;
+ break;
+ case ROFFT_BODY:
+ term_newln(p);
+ p->tcol->offset = mt->offset;
+ break;
+ default:
+ abort();
+ }
+}
+static int
+pre_UR(DECL_ARGS)
+{
return n->type != ROFFT_HEAD;
}
static void
post_UR(DECL_ARGS)
{
-
if (n->type != ROFFT_BLOCK)
return;
term_word(p, "<");
p->flags |= TERMP_NOSPACE;
- if (NULL != n->child->child)
+ if (n->child->child != NULL)
print_man_node(p, mt, n->child->child, meta);
p->flags |= TERMP_NOSPACE;
@@ -866,7 +894,8 @@ post_UR(DECL_ARGS)
static void
print_man_node(DECL_ARGS)
{
- int c;
+ const struct man_term_act *act;
+ int c;
switch (n->type) {
case ROFFT_TEXT:
@@ -884,6 +913,8 @@ print_man_node(DECL_ARGS)
} else if (*n->string == ' ' && n->flags & NODE_LINE &&
(p->flags & TERMP_NONEWLINE) == 0)
term_newln(p);
+ else if (n->flags & NODE_DELIMC)
+ p->flags |= TERMP_NOSPACE;
term_word(p, n->string);
goto out;
@@ -910,20 +941,20 @@ print_man_node(DECL_ARGS)
return;
}
- assert(n->tok >= MAN_TH && n->tok <= MAN_MAX);
- if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
+ act = man_term_act(n->tok);
+ if ((act->flags & MAN_NOTEXT) == 0 && n->tok != MAN_SM)
term_fontrepl(p, TERMFONT_NONE);
c = 1;
- if (termacts[n->tok].pre)
- c = (*termacts[n->tok].pre)(p, mt, n, meta);
+ if (act->pre != NULL)
+ c = (*act->pre)(p, mt, n, meta);
- if (c && n->child)
+ if (c && n->child != NULL)
print_man_nodelist(p, mt, n->child, meta);
- if (termacts[n->tok].post)
- (*termacts[n->tok].post)(p, mt, n, meta);
- if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
+ if (act->post != NULL)
+ (*act->post)(p, mt, n, meta);
+ if ((act->flags & MAN_NOTEXT) == 0 && n->tok != MAN_SM)
term_fontrepl(p, TERMFONT_NONE);
out:
@@ -934,7 +965,7 @@ out:
* -man doesn't have nested macros, we don't need to be
* more specific than this.
*/
- if (mt->fl & MANT_LITERAL &&
+ if (n->flags & NODE_NOFILL &&
! (p->flags & (TERMP_NOBREAK | TERMP_NONEWLINE)) &&
(n->next == NULL || n->next->flags & NODE_LINE)) {
p->flags |= TERMP_BRNEVER | TERMP_NOSPACE;
@@ -949,15 +980,13 @@ out:
p->tcol->rmargin = p->maxrmargin;
}
}
- if (NODE_EOS & n->flags)
+ if (n->flags & NODE_EOS)
p->flags |= TERMP_SENTENCE;
}
-
static void
print_man_nodelist(DECL_ARGS)
{
-
while (n != NULL) {
print_man_node(p, mt, n, meta);
n = n->next;
@@ -992,7 +1021,7 @@ print_man_foot(struct termp *p, const struct roff_meta *meta)
}
mandoc_asprintf(&title, "%s(%s)",
meta->title, meta->msec);
- } else if (meta->os) {
+ } else if (meta->os != NULL) {
title = mandoc_strdup(meta->os);
} else {
title = mandoc_strdup("");
diff --git a/man_validate.c b/man_validate.c
index d6c51af5255c..4bfaf764e6c8 100644
--- a/man_validate.c
+++ b/man_validate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id: man_validate.c,v 1.146 2018/12/31 10:04:39 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -24,6 +24,7 @@
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -40,28 +41,32 @@
typedef void (*v_check)(CHKARGS);
+static void check_abort(CHKARGS);
static void check_par(CHKARGS);
static void check_part(CHKARGS);
static void check_root(CHKARGS);
static void check_text(CHKARGS);
static void post_AT(CHKARGS);
+static void post_EE(CHKARGS);
+static void post_EX(CHKARGS);
static void post_IP(CHKARGS);
static void post_OP(CHKARGS);
+static void post_SH(CHKARGS);
static void post_TH(CHKARGS);
static void post_UC(CHKARGS);
static void post_UR(CHKARGS);
static void post_in(CHKARGS);
-static void post_vs(CHKARGS);
-static const v_check __man_valids[MAN_MAX - MAN_TH] = {
+static const v_check man_valids[MAN_MAX - MAN_TH] = {
post_TH, /* TH */
- NULL, /* SH */
- NULL, /* SS */
+ post_SH, /* SH */
+ post_SH, /* SS */
NULL, /* TP */
- check_par, /* LP */
+ NULL, /* TQ */
+ check_abort,/* LP */
check_par, /* PP */
- check_par, /* P */
+ check_abort,/* P */
post_IP, /* IP */
NULL, /* HP */
NULL, /* SM */
@@ -75,8 +80,6 @@ static const v_check __man_valids[MAN_MAX - MAN_TH] = {
NULL, /* I */
NULL, /* IR */
NULL, /* RI */
- NULL, /* nf */
- NULL, /* fi */
NULL, /* RE */
check_part, /* RS */
NULL, /* DT */
@@ -84,33 +87,56 @@ static const v_check __man_valids[MAN_MAX - MAN_TH] = {
NULL, /* PD */
post_AT, /* AT */
post_in, /* in */
+ NULL, /* SY */
+ NULL, /* YS */
post_OP, /* OP */
- NULL, /* EX */
- NULL, /* EE */
+ post_EX, /* EX */
+ post_EE, /* EE */
post_UR, /* UR */
NULL, /* UE */
post_UR, /* MT */
NULL, /* ME */
};
-static const v_check *man_valids = __man_valids - MAN_TH;
+/* Validate the subtree rooted at man->last. */
void
-man_node_validate(struct roff_man *man)
+man_validate(struct roff_man *man)
{
struct roff_node *n;
const v_check *cp;
+ /*
+ * Translate obsolete macros such that later code
+ * does not need to look for them.
+ */
+
n = man->last;
+ switch (n->tok) {
+ case MAN_LP:
+ case MAN_P:
+ n->tok = MAN_PP;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Iterate over all children, recursing into each one
+ * in turn, depth-first.
+ */
+
man->last = man->last->child;
while (man->last != NULL) {
- man_node_validate(man);
+ man_validate(man);
if (man->last == n)
man->last = man->last->child;
else
man->last = man->last->next;
}
+ /* Finally validate the macro itself. */
+
man->last = n;
man->next = ROFF_NEXT_SIBLING;
switch (n->type) {
@@ -126,23 +152,15 @@ man_node_validate(struct roff_man *man)
break;
default:
if (n->tok < ROFF_MAX) {
- switch (n->tok) {
- case ROFF_br:
- case ROFF_sp:
- post_vs(man, n);
- break;
- default:
- roff_validate(man);
- break;
- }
+ roff_validate(man);
break;
}
assert(n->tok >= MAN_TH && n->tok < MAN_MAX);
- cp = man_valids + n->tok;
+ cp = man_valids + (n->tok - MAN_TH);
if (*cp)
(*cp)(man, n);
if (man->last == n)
- man_state(man, n);
+ n->flags |= NODE_VALID;
break;
}
}
@@ -153,14 +171,12 @@ check_root(CHKARGS)
assert((man->flags & (MAN_BLINE | MAN_ELINE)) == 0);
if (n->last == NULL || n->last->type == ROFFT_COMMENT)
- mandoc_msg(MANDOCERR_DOC_EMPTY, man->parse,
- n->line, n->pos, NULL);
+ mandoc_msg(MANDOCERR_DOC_EMPTY, n->line, n->pos, NULL);
else
man->meta.hasbody = 1;
if (NULL == man->meta.title) {
- mandoc_msg(MANDOCERR_TH_NOTITLE, man->parse,
- n->line, n->pos, NULL);
+ mandoc_msg(MANDOCERR_TH_NOTITLE, n->line, n->pos, NULL);
/*
* If a title hasn't been set, do so now (by
@@ -175,23 +191,43 @@ check_root(CHKARGS)
if (man->meta.os_e &&
(man->meta.rcsids & (1 << man->meta.os_e)) == 0)
- mandoc_msg(MANDOCERR_RCS_MISSING, man->parse, 0, 0,
+ mandoc_msg(MANDOCERR_RCS_MISSING, 0, 0,
man->meta.os_e == MANDOC_OS_OPENBSD ?
"(OpenBSD)" : "(NetBSD)");
}
static void
+check_abort(CHKARGS)
+{
+ abort();
+}
+
+static void
check_text(CHKARGS)
{
char *cp, *p;
- if (MAN_LITERAL & man->flags)
+ if (n->flags & NODE_NOFILL)
return;
cp = n->string;
for (p = cp; NULL != (p = strchr(p, '\t')); p++)
- mandoc_msg(MANDOCERR_FI_TAB, man->parse,
- n->line, n->pos + (p - cp), NULL);
+ mandoc_msg(MANDOCERR_FI_TAB,
+ n->line, n->pos + (int)(p - cp), NULL);
+}
+
+static void
+post_EE(CHKARGS)
+{
+ if ((n->flags & NODE_NOFILL) == 0)
+ mandoc_msg(MANDOCERR_FI_SKIP, n->line, n->pos, "EE");
+}
+
+static void
+post_EX(CHKARGS)
+{
+ if (n->flags & NODE_NOFILL)
+ mandoc_msg(MANDOCERR_NF_SKIP, n->line, n->pos, "EX");
}
static void
@@ -199,21 +235,55 @@ post_OP(CHKARGS)
{
if (n->child == NULL)
- mandoc_msg(MANDOCERR_OP_EMPTY, man->parse,
- n->line, n->pos, "OP");
+ mandoc_msg(MANDOCERR_OP_EMPTY, n->line, n->pos, "OP");
else if (n->child->next != NULL && n->child->next->next != NULL) {
n = n->child->next->next;
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse,
+ mandoc_msg(MANDOCERR_ARG_EXCESS,
n->line, n->pos, "OP ... %s", n->string);
}
}
static void
+post_SH(CHKARGS)
+{
+ struct roff_node *nc;
+
+ if (n->type != ROFFT_BODY || (nc = n->child) == NULL)
+ return;
+
+ if (nc->tok == MAN_PP && nc->body->child != NULL) {
+ while (nc->body->last != NULL) {
+ man->next = ROFF_NEXT_CHILD;
+ roff_node_relink(man, nc->body->last);
+ man->last = n;
+ }
+ }
+
+ if (nc->tok == MAN_PP || nc->tok == ROFF_sp || nc->tok == ROFF_br) {
+ mandoc_msg(MANDOCERR_PAR_SKIP, nc->line, nc->pos,
+ "%s after %s", roff_name[nc->tok], roff_name[n->tok]);
+ roff_node_delete(man, nc);
+ }
+
+ /*
+ * Trailing PP is empty, so it is deleted by check_par().
+ * Trailing sp is significant.
+ */
+
+ if ((nc = n->last) != NULL && nc->tok == ROFF_br) {
+ mandoc_msg(MANDOCERR_PAR_SKIP,
+ nc->line, nc->pos, "%s at the end of %s",
+ roff_name[nc->tok], roff_name[n->tok]);
+ roff_node_delete(man, nc);
+ }
+}
+
+static void
post_UR(CHKARGS)
{
if (n->type == ROFFT_HEAD && n->child == NULL)
- mandoc_msg(MANDOCERR_UR_NOHEAD, man->parse,
- n->line, n->pos, roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_UR_NOHEAD, n->line, n->pos,
+ "%s", roff_name[n->tok]);
check_part(man, n);
}
@@ -222,8 +292,8 @@ check_part(CHKARGS)
{
if (n->type == ROFFT_BODY && n->child == NULL)
- mandoc_msg(MANDOCERR_BLK_EMPTY, man->parse,
- n->line, n->pos, roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_BLK_EMPTY, n->line, n->pos,
+ "%s", roff_name[n->tok]);
}
static void
@@ -236,15 +306,22 @@ check_par(CHKARGS)
roff_node_delete(man, n);
break;
case ROFFT_BODY:
+ if (n->child != NULL &&
+ (n->child->tok == ROFF_sp || n->child->tok == ROFF_br)) {
+ mandoc_msg(MANDOCERR_PAR_SKIP,
+ n->child->line, n->child->pos,
+ "%s after %s", roff_name[n->child->tok],
+ roff_name[n->tok]);
+ roff_node_delete(man, n->child);
+ }
if (n->child == NULL)
- mandoc_vmsg(MANDOCERR_PAR_SKIP,
- man->parse, n->line, n->pos,
+ mandoc_msg(MANDOCERR_PAR_SKIP, n->line, n->pos,
"%s empty", roff_name[n->tok]);
break;
case ROFFT_HEAD:
if (n->child != NULL)
- mandoc_vmsg(MANDOCERR_ARG_SKIP,
- man->parse, n->line, n->pos, "%s %s%s",
+ mandoc_msg(MANDOCERR_ARG_SKIP,
+ n->line, n->pos, "%s %s%s",
roff_name[n->tok], n->child->string,
n->child->next != NULL ? " ..." : "");
break;
@@ -264,8 +341,7 @@ post_IP(CHKARGS)
break;
case ROFFT_BODY:
if (n->parent->head->child == NULL && n->child == NULL)
- mandoc_vmsg(MANDOCERR_PAR_SKIP,
- man->parse, n->line, n->pos,
+ mandoc_msg(MANDOCERR_PAR_SKIP, n->line, n->pos,
"%s empty", roff_name[n->tok]);
break;
default:
@@ -298,9 +374,8 @@ post_TH(CHKARGS)
/* Only warn about this once... */
if (isalpha((unsigned char)*p) &&
! isupper((unsigned char)*p)) {
- mandoc_vmsg(MANDOCERR_TITLE_CASE,
- man->parse, n->line,
- n->pos + (p - n->string),
+ mandoc_msg(MANDOCERR_TITLE_CASE, n->line,
+ n->pos + (int)(p - n->string),
"TH %s", n->string);
break;
}
@@ -308,8 +383,7 @@ post_TH(CHKARGS)
man->meta.title = mandoc_strdup(n->string);
} else {
man->meta.title = mandoc_strdup("");
- mandoc_msg(MANDOCERR_TH_NOTITLE, man->parse,
- nb->line, nb->pos, "TH");
+ mandoc_msg(MANDOCERR_TH_NOTITLE, nb->line, nb->pos, "TH");
}
/* TITLE ->MSEC<- DATE OS VOL */
@@ -320,7 +394,7 @@ post_TH(CHKARGS)
man->meta.msec = mandoc_strdup(n->string);
else {
man->meta.msec = mandoc_strdup("");
- mandoc_vmsg(MANDOCERR_MSEC_MISSING, man->parse,
+ mandoc_msg(MANDOCERR_MSEC_MISSING,
nb->line, nb->pos, "TH %s", man->meta.title);
}
@@ -334,7 +408,7 @@ post_TH(CHKARGS)
mandoc_normdate(man, n->string, n->line, n->pos);
} else {
man->meta.date = mandoc_strdup("");
- mandoc_msg(MANDOCERR_DATE_MISSING, man->parse,
+ mandoc_msg(MANDOCERR_DATE_MISSING,
n ? n->line : nb->line,
n ? n->pos : nb->pos, "TH");
}
@@ -362,7 +436,7 @@ post_TH(CHKARGS)
man->meta.vol = mandoc_strdup(p);
if (n != NULL && (n = n->next) != NULL)
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse,
+ mandoc_msg(MANDOCERR_ARG_EXCESS,
n->line, n->pos, "TH ... %s", n->string);
/*
@@ -463,32 +537,3 @@ post_in(CHKARGS)
free(n->child->string);
n->child->string = s;
}
-
-static void
-post_vs(CHKARGS)
-{
-
- if (NULL != n->prev)
- return;
-
- switch (n->parent->tok) {
- case MAN_SH:
- case MAN_SS:
- case MAN_PP:
- case MAN_LP:
- case MAN_P:
- mandoc_vmsg(MANDOCERR_PAR_SKIP, man->parse, n->line, n->pos,
- "%s after %s", roff_name[n->tok],
- roff_name[n->parent->tok]);
- /* FALLTHROUGH */
- case TOKEN_NONE:
- /*
- * Don't warn about this because it occurs in pod2man
- * and would cause considerable (unfixable) warnage.
- */
- roff_node_delete(man, n);
- break;
- default:
- break;
- }
-}
diff --git a/manconf.h b/manconf.h
index b4cd31646c91..bb3761998c88 100644
--- a/manconf.h
+++ b/manconf.h
@@ -1,6 +1,6 @@
-/* $Id: manconf.h,v 1.5 2017/07/01 09:47:30 schwarze Exp $ */
+/* $Id: manconf.h,v 1.7 2018/11/22 11:30:23 schwarze Exp $ */
/*
- * Copyright (c) 2011, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -30,12 +30,14 @@ struct manoutput {
char *man;
char *paper;
char *style;
+ char *tag;
size_t indent;
size_t width;
int fragment;
int mdoc;
- int synopsisonly;
int noval;
+ int synopsisonly;
+ int toc;
};
struct manconf {
diff --git a/mandoc.1 b/mandoc.1
index 76b3cda5a704..79f6e8500d5c 100644
--- a/mandoc.1
+++ b/mandoc.1
@@ -1,4 +1,4 @@
-.\" $Id: mandoc.1,v 1.226 2018/07/28 18:34:15 schwarze Exp $
+.\" $Id: mandoc.1,v 1.237 2019/02/23 18:53:54 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2012, 2014-2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -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: July 28 2018 $
+.Dd $Mdocdate: February 23 2019 $
.Dt MANDOC 1
.Os
.Sh NAME
@@ -256,10 +256,28 @@ where
is the back-space character number 8.
Emboldened characters are rendered as
.Sq c Ns \e[bs] Ns c .
+This markup is typically converted to appropriate terminal sequences by
+the pager or
+.Xr ul 1 .
+To remove the markup, pipe the output to
+.Xr col 1
+.Fl b
+instead.
.Pp
The special characters documented in
.Xr mandoc_char 7
are rendered best-effort in an ASCII equivalent.
+In particular, opening and closing
+.Sq single quotes
+are represented as characters number 0x60 and 0x27, respectively,
+which agrees with all ASCII standards from 1965 to the latest
+revision (2012) and which matches the traditional way in which
+.Xr roff 7
+formatters represent single quotes in ASCII output.
+This correct ASCII rendering may look strange with modern
+Unicode-compatible fonts because contrary to ASCII, Unicode uses
+the code point U+0060 for the grave accent only, never for an opening
+quote.
.Pp
The following
.Fl O
@@ -290,6 +308,26 @@ One useful application is for checking that
output formats in the same way as the
.Xr mdoc 7
source it was generated from.
+.It Cm tag Ns Op = Ns Ar term
+If the formatted manual page is opened in a pager,
+go to the definition of the
+.Ar term
+rather than showing the manual page from the beginning.
+If no
+.Ar term
+is specified, reuse the first command line argument that is not a
+.Ar section
+number.
+If that argument is in
+.Xr apropos 1
+.Ar key Ns = Ns Ar val
+format, only the
+.Ar val
+is used rather than the argument as a whole.
+This is useful for commands like
+.Ql man -akO tag Ic=ulimit
+to search for a keyword and jump right to its definition
+in the matching manual pages.
.It Cm width Ns = Ns Ar width
The output width is set to
.Ar width
@@ -308,9 +346,9 @@ Equations rendered from
.Xr eqn 7
blocks use MathML.
.Pp
-The
-.Pa mandoc.css
-file documents style-sheet classes available for customising output.
+The file
+.Pa /usr/share/misc/mandoc.css
+documents style-sheet classes available for customising output.
If a style-sheet is not specified with
.Fl O Cm style ,
.Fl T Cm html
@@ -345,7 +383,7 @@ Instances of
are replaced with the include filename.
The default is not to present a
hyperlink.
-.It Cm man Ns = Ns Ar fmt
+.It Cm man Ns = Ns Ar fmt Ns Op ; Ns Ar fmt
The string
.Ar fmt ,
for example,
@@ -361,12 +399,19 @@ are replaced with the linked manual's name and section, respectively.
If no section is included, section 1 is assumed.
The default is not to
present a hyperlink.
+If two formats are given and a file
+.Ar %N.%S
+exists in the current directory, the first format is used;
+otherwise, the second format is used.
.It Cm style Ns = Ns Ar style.css
The file
.Ar style.css
is used for an external style-sheet.
This must be a valid absolute or
relative URI.
+.It Cm toc
+If an input file contains at least two non-standard sections,
+print a table of contents near the beginning of the output.
.El
.Ss Locale Output
By default,
@@ -667,10 +712,10 @@ To page manuals to the terminal:
.Dl $ mandoc -l mandoc.1 man.1 apropos.1 makewhatis.8
.Pp
To produce HTML manuals with
-.Pa mandoc.css
+.Pa /usr/share/misc/mandoc.css
as the style-sheet:
.Pp
-.Dl $ mandoc \-T html -O style=mandoc.css mdoc.7 \*(Gt mdoc.7.html
+.Dl $ mandoc \-T html -O style=/usr/share/misc/mandoc.css mdoc.7 > mdoc.7.html
.Pp
To check over a large set of manuals:
.Pp
@@ -678,7 +723,7 @@ To check over a large set of manuals:
.Pp
To produce a series of PostScript manuals for A4 paper:
.Pp
-.Dl $ mandoc \-T ps \-O paper=a4 mdoc.7 man.7 \*(Gt manuals.ps
+.Dl $ mandoc \-T ps \-O paper=a4 mdoc.7 man.7 > manuals.ps
.Pp
Convert a modern
.Xr mdoc 7
@@ -688,20 +733,36 @@ format, for use on systems lacking an
.Xr mdoc 7
parser:
.Pp
-.Dl $ mandoc \-T man foo.mdoc \*(Gt foo.man
+.Dl $ mandoc \-T man foo.mdoc > foo.man
.Sh DIAGNOSTICS
Messages displayed by
.Nm
follow this format:
.Bd -ragged -offset indent
.Nm :
-.Ar file : Ns Ar line : Ns Ar column : level : message : macro args
+.Ar file : Ns Ar line : Ns Ar column : level : message : macro arguments
.Pq Ar os
.Ed
.Pp
-Line and column numbers start at 1.
+The first three fields identify the
+.Ar file
+name,
+.Ar line
+number, and
+.Ar column
+number of the input file where the message was triggered.
+The line and column numbers start at 1.
Both are omitted for messages referring to an input file as a whole.
-Macro names and arguments are omitted where meaningless.
+All
+.Ar level
+and
+.Ar message
+strings are explained below.
+The name of the
+.Ar macro
+triggering the message and its
+.Ar arguments
+are omitted where meaningless.
The
.Ar os
operating system specifier is omitted for messages that are relevant
@@ -1606,6 +1667,12 @@ or
.Cm off .
The invalid argument is moved out of the macro, which leaves the macro
empty, causing it to toggle the spacing mode.
+.It Sy "argument contains two font escapes"
+.Pq roff
+The second argument of a
+.Ic char
+request contains more than one font escape sequence.
+A wrong font may remain active after using the character.
.It Sy "unknown font, skipping request"
.Pq man , tbl
A
@@ -1651,7 +1718,8 @@ Start it on a new input line to help formatters produce correct spacing.
.It Sy "invalid escape sequence"
.Pq roff
An escape sequence has an invalid opening argument delimiter, lacks the
-closing argument delimiter, or the argument has too few characters.
+closing argument delimiter, the argument is of an invalid form, or it is
+a character escape sequence with an invalid name.
If the argument is incomplete,
.Ic \e*
and
@@ -1664,6 +1732,12 @@ and
.Ic \ew
to the length of the incomplete argument.
All other invalid escape sequences are ignored.
+.It Sy "undefined escape, printing literally"
+.Pq roff
+In an escape sequence, the first character
+right after the leading backslash is invalid.
+That character is printed literally,
+which is equivalent to ignoring the backslash.
.It Sy "undefined string, using \(dq\(dq"
.Pq roff
If a string is used without being defined before,
@@ -1807,6 +1881,13 @@ or
macro.
It may be mistyped or unsupported.
The request or macro is discarded including its arguments.
+.It Sy "skipping request outside macro"
+.Pq roff
+A
+.Ic shift
+or
+.Ic return
+request occurs outside any macro definition and has no effect.
.It Sy "skipping insecure request"
.Pq roff
An input file attempted to run a shell command
@@ -1916,6 +1997,14 @@ When parsing for a request or a user-defined macro name to be called,
only the escape sequence is discarded.
The characters preceding it are used as the request or macro name,
the characters following it are used as the arguments to the request or macro.
+.It Sy "using macro argument outside macro"
+.Pq roff
+The escape sequence \e$ occurs outside any macro definition
+and expands to the empty string.
+.It Sy "argument number is not numeric"
+.Pq roff
+The argument of the escape sequence \e$ is not a digit;
+the escape sequence expands to the empty string.
.It Sy "NOT IMPLEMENTED: Bd -file"
.Pq mdoc
For security reasons, the
@@ -1944,6 +2033,13 @@ macro fails to specify the list type.
The argument of a
.Ic \&ce
request is not a number.
+.It Sy "argument is not a character"
+.Pq roff
+The first argument of a
+.Ic char
+request is neither a single ASCII character
+nor a single character escape sequence.
+The request is ignored including all its arguments.
.It Sy "missing manual name, using \(dq\(dq"
.Pq mdoc
The first call to
@@ -1978,6 +2074,13 @@ or
.Ic \&gsize
statement has a non-numeric or negative argument or no argument at all.
The invalid request or statement is ignored.
+.It Sy "excessive shift"
+.Pq roff
+The argument of a
+.Ic shift
+request is larger than the number of arguments of the macro that is
+currently being executed.
+All macro arguments are deleted and \en(.$ is set to zero.
.It Sy "NOT IMPLEMENTED: .so with absolute path or \(dq..\(dq"
.Pq roff
For security reasons,
@@ -2100,6 +2203,13 @@ implementations but not by
.Nm
was found in an input file.
It is replaced by a question mark.
+.It Sy "unsupported escape sequence"
+.Pq roff
+An input file contains an escape sequence supported by GNU troff
+or Heirloom troff but not by
+.Nm ,
+and it is likely that this will cause information loss
+or considerable misformatting.
.It Sy "unsupported roff request"
.Pq roff
An input file contains a
diff --git a/mandoc.3 b/mandoc.3
index 6914a76808f7..4ecfbdebd8c2 100644
--- a/mandoc.3
+++ b/mandoc.3
@@ -1,4 +1,4 @@
-.\" $Id: mandoc.3,v 1.41 2017/07/04 23:40:01 schwarze Exp $
+.\" $Id: mandoc.3,v 1.44 2018/12/30 00:49:55 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,30 +15,23 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: July 4 2017 $
+.Dd $Mdocdate: December 30 2018 $
.Dt MANDOC 3
.Os
.Sh NAME
.Nm mandoc ,
.Nm deroff ,
-.Nm mandocmsg ,
-.Nm man_mparse ,
-.Nm man_validate ,
-.Nm mdoc_validate ,
.Nm mparse_alloc ,
+.Nm mparse_copy ,
.Nm mparse_free ,
-.Nm mparse_getkeep ,
-.Nm mparse_keep ,
.Nm mparse_open ,
.Nm mparse_readfd ,
.Nm mparse_reset ,
-.Nm mparse_result ,
-.Nm mparse_strerror ,
-.Nm mparse_strlevel ,
-.Nm mparse_updaterc
+.Nm mparse_result
.Nd mandoc macro compiler library
.Sh SYNOPSIS
.In sys/types.h
+.In stdio.h
.In mandoc.h
.Pp
.Fd "#define ASCII_NBRSP"
@@ -47,38 +40,23 @@
.Ft struct mparse *
.Fo mparse_alloc
.Fa "int options"
-.Fa "enum mandocerr mmin"
-.Fa "mandocmsg mmsg"
.Fa "enum mandoc_os oe_e"
.Fa "char *os_s"
.Fc
.Ft void
-.Fo (*mandocmsg)
-.Fa "enum mandocerr errtype"
-.Fa "enum mandoclevel level"
-.Fa "const char *file"
-.Fa "int line"
-.Fa "int col"
-.Fa "const char *msg"
-.Fc
-.Ft void
.Fo mparse_free
.Fa "struct mparse *parse"
.Fc
-.Ft const char *
-.Fo mparse_getkeep
-.Fa "const struct mparse *parse"
-.Fc
.Ft void
-.Fo mparse_keep
-.Fa "struct mparse *parse"
+.Fo mparse_copy
+.Fa "const struct mparse *parse"
.Fc
.Ft int
.Fo mparse_open
.Fa "struct mparse *parse"
.Fa "const char *fname"
.Fc
-.Ft "enum mandoclevel"
+.Ft void
.Fo mparse_readfd
.Fa "struct mparse *parse"
.Fa "int fd"
@@ -88,24 +66,9 @@
.Fo mparse_reset
.Fa "struct mparse *parse"
.Fc
-.Ft void
+.Ft struct roff_meta *
.Fo mparse_result
.Fa "struct mparse *parse"
-.Fa "struct roff_man **man"
-.Fa "char **sodest"
-.Fc
-.Ft "const char *"
-.Fo mparse_strerror
-.Fa "enum mandocerr"
-.Fc
-.Ft "const char *"
-.Fo mparse_strlevel
-.Fa "enum mandoclevel"
-.Fc
-.Ft void
-.Fo mparse_updaterc
-.Fa "struct mparse *parse"
-.Fa "enum mandoclevel *rc"
.Fc
.In roff.h
.Ft void
@@ -118,22 +81,10 @@
.In mdoc.h
.Vt extern const char * const * mdoc_argnames;
.Vt extern const char * const * mdoc_macronames;
-.Ft void
-.Fo mdoc_validate
-.Fa "struct roff_man *mdoc"
-.Fc
.In sys/types.h
.In mandoc.h
.In man.h
.Vt extern const char * const * man_macronames;
-.Ft "const struct mparse *"
-.Fo man_mparse
-.Fa "const struct roff_man *man"
-.Fc
-.Ft void
-.Fo man_validate
-.Fa "struct roff_man *man"
-.Fc
.Sh DESCRIPTION
The
.Nm mandoc
@@ -174,27 +125,13 @@ close it with
retrieve the syntax tree with
.Fn mparse_result ;
.It
-depending on whether the
-.Fa macroset
-member of the returned
-.Vt struct roff_man
-is
-.Dv MACROSET_MDOC
-or
-.Dv MACROSET_MAN ,
-validate it with
-.Fn mdoc_validate
-or
-.Fn man_validate ,
-respectively;
-.It
if information about the validity of the input is needed, fetch it with
.Fn mparse_updaterc ;
.It
iterate over parse nodes with starting from the
.Fa first
member of the returned
-.Vt struct roff_man ;
+.Vt struct roff_meta ;
.It
free all allocated memory with
.Fn mparse_free
@@ -232,9 +169,6 @@ and freed with
This may be used across parsed input if
.Fn mparse_reset
is called between parses.
-.It Vt "mandocmsg"
-A prototype for a function to handle error and warning
-messages emitted by the parser.
.El
.Ss Functions
.Bl -ohang
@@ -245,35 +179,11 @@ including text contained in its child nodes.
To be used on children of the
.Fa first
member of
-.Vt struct roff_man .
+.Vt struct roff_meta .
When it is no longer needed, the pointer returned from
.Fn deroff
can be passed to
.Xr free 3 .
-.It Fn man_mparse
-Get the parser used for the current output.
-Declared in
-.In man.h ,
-implemented in
-.Pa man.c .
-.It Fn man_validate
-Validate the
-.Dv MACROSET_MAN
-parse tree obtained with
-.Fn mparse_result .
-Declared in
-.In man.h ,
-implemented in
-.Pa man.c .
-.It Fn mdoc_validate
-Validate the
-.Dv MACROSET_MDOC
-parse tree obtained with
-.Fn mparse_result .
-Declared in
-.In mdoc.h ,
-implemented in
-.Pa mdoc.c .
.It Fn mparse_alloc
Allocate a parser.
The arguments have the following effect:
@@ -295,8 +205,8 @@ file inclusion requests are always honoured.
Otherwise, if the request is the only content in an input file,
only the file name is remembered, to be returned in the
.Fa sodest
-argument of
-.Fn mparse_result .
+field of
+.Vt struct roff_meta .
.Pp
When the
.Dv MPARSE_QUICK
@@ -305,24 +215,14 @@ This is for example useful in
.Xr makewhatis 8
.Fl Q
to quickly build minimal databases.
-.It Ar mmin
-Can be set to
-.Dv MANDOCERR_BASE ,
-.Dv MANDOCERR_STYLE ,
-.Dv MANDOCERR_WARNING ,
-.Dv MANDOCERR_ERROR ,
-.Dv MANDOCERR_UNSUPP ,
-or
-.Dv MANDOCERR_MAX .
-Messages below the selected level will be suppressed.
-.It Ar mmsg
-A callback function to handle errors and warnings.
-See
-.Pa main.c
-for an example.
-If printing of error messages is not desired,
-.Dv NULL
-may be passed.
+.Pp
+When the
+.Dv MARSE_VALIDATE
+bit is set,
+.Fn mparse_result
+runs the validation functions before returning the syntax tree.
+This is almost always required, except in certain debugging scenarios,
+for example to dump unvalidated syntax trees.
.It Ar os_e
Operating system to check base system conventions for.
If
@@ -361,19 +261,9 @@ Declared in
.In mandoc.h ,
implemented in
.Pa read.c .
-.It Fn mparse_getkeep
-Acquire the keep buffer.
-Must follow a call of
-.Fn mparse_keep .
-Declared in
-.In mandoc.h ,
-implemented in
-.Pa read.c .
-.It Fn mparse_keep
-Instruct the parser to retain a copy of its parsed input.
-This can be acquired with subsequent
-.Fn mparse_getkeep
-calls.
+.It Fn mparse_copy
+Dump a copy of the input to the standard output; used for
+.Fl man T Ns Cm man .
Declared in
.In mandoc.h ,
implemented in
@@ -421,35 +311,6 @@ implemented in
.Pa read.c .
.It Fn mparse_result
Obtain the result of a parse.
-One of the two pointers will be filled in.
-Declared in
-.In mandoc.h ,
-implemented in
-.Pa read.c .
-.It Fn mparse_strerror
-Return a statically-allocated string representation of an error code.
-Declared in
-.In mandoc.h ,
-implemented in
-.Pa read.c .
-.It Fn mparse_strlevel
-Return a statically-allocated string representation of a level code.
-Declared in
-.In mandoc.h ,
-implemented in
-.Pa read.c .
-.It Fn mparse_updaterc
-If the highest warning or error level that occurred during the current
-.Fa parse
-is higher than
-.Pf * Fa rc ,
-update
-.Pf * Fa rc
-accordingly.
-This is useful after calling
-.Fn mdoc_validate
-or
-.Fn man_validate .
Declared in
.In mandoc.h ,
implemented in
diff --git a/mandoc.c b/mandoc.c
index 1279b52ed50f..fb9395a585db 100644
--- a/mandoc.c
+++ b/mandoc.c
@@ -1,4 +1,4 @@
-/* $Id: mandoc.c,v 1.104 2018/07/28 18:34:15 schwarze Exp $ */
+/* $Id: mandoc.c,v 1.114 2018/12/30 00:49:55 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -32,16 +32,70 @@
#include "mandoc.h"
#include "roff.h"
#include "libmandoc.h"
+#include "roff_int.h"
static int a2time(time_t *, const char *, const char *);
static char *time2a(time_t);
enum mandoc_esc
+mandoc_font(const char *cp, int sz)
+{
+ switch (sz) {
+ case 0:
+ return ESCAPE_FONTPREV;
+ case 1:
+ switch (cp[0]) {
+ case 'B':
+ case '3':
+ return ESCAPE_FONTBOLD;
+ case 'I':
+ case '2':
+ return ESCAPE_FONTITALIC;
+ case 'P':
+ return ESCAPE_FONTPREV;
+ case 'R':
+ case '1':
+ return ESCAPE_FONTROMAN;
+ case '4':
+ return ESCAPE_FONTBI;
+ default:
+ return ESCAPE_ERROR;
+ }
+ case 2:
+ switch (cp[0]) {
+ case 'B':
+ switch (cp[1]) {
+ case 'I':
+ return ESCAPE_FONTBI;
+ default:
+ return ESCAPE_ERROR;
+ }
+ case 'C':
+ switch (cp[1]) {
+ case 'B':
+ return ESCAPE_FONTBOLD;
+ case 'I':
+ return ESCAPE_FONTITALIC;
+ case 'R':
+ case 'W':
+ return ESCAPE_FONTCW;
+ default:
+ return ESCAPE_ERROR;
+ }
+ default:
+ return ESCAPE_ERROR;
+ }
+ default:
+ return ESCAPE_ERROR;
+ }
+}
+
+enum mandoc_esc
mandoc_escape(const char **end, const char **start, int *sz)
{
const char *local_start;
- int local_sz;
+ int local_sz, c, i;
char term;
enum mandoc_esc gly;
@@ -56,6 +110,14 @@ mandoc_escape(const char **end, const char **start, int *sz)
sz = &local_sz;
/*
+ * Treat "\E" just like "\";
+ * it only makes a difference in copy mode.
+ */
+
+ if (**end == 'E')
+ ++*end;
+
+ /*
* Beyond the backslash, at least one input character
* is part of the escape sequence. With one exception
* (see below), that character won't be returned.
@@ -77,6 +139,10 @@ mandoc_escape(const char **end, const char **start, int *sz)
*sz = 2;
break;
case '[':
+ if (**start == ' ') {
+ ++*end;
+ return ESCAPE_ERROR;
+ }
gly = ESCAPE_SPECIAL;
term = ']';
break;
@@ -91,11 +157,26 @@ mandoc_escape(const char **end, const char **start, int *sz)
/*
* Escapes taking no arguments at all.
*/
- case 'd':
- case 'u':
+ case '!':
+ case '?':
+ return ESCAPE_UNSUPP;
+ case '%':
+ case '&':
+ case ')':
case ',':
case '/':
+ case '^':
+ case 'a':
+ case 'd':
+ case 'r':
+ case 't':
+ case 'u':
+ case '{':
+ case '|':
+ case '}':
return ESCAPE_IGNORE;
+ case 'c':
+ return ESCAPE_NOSPACE;
case 'p':
return ESCAPE_BREAK;
@@ -113,32 +194,57 @@ mandoc_escape(const char **end, const char **start, int *sz)
* 'X' is the trigger. These have opaque sub-strings.
*/
case 'F':
+ case 'f':
case 'g':
case 'k':
case 'M':
case 'm':
case 'n':
+ case 'O':
case 'V':
case 'Y':
- gly = ESCAPE_IGNORE;
- /* FALLTHROUGH */
- case 'f':
- if (ESCAPE_ERROR == gly)
- gly = ESCAPE_FONT;
+ gly = (*start)[-1] == 'f' ? ESCAPE_FONT : ESCAPE_IGNORE;
switch (**start) {
case '(':
+ if ((*start)[-1] == 'O')
+ gly = ESCAPE_ERROR;
*start = ++*end;
*sz = 2;
break;
case '[':
+ if ((*start)[-1] == 'O')
+ gly = (*start)[1] == '5' ?
+ ESCAPE_UNSUPP : ESCAPE_ERROR;
*start = ++*end;
term = ']';
break;
default:
+ if ((*start)[-1] == 'O') {
+ switch (**start) {
+ case '0':
+ gly = ESCAPE_UNSUPP;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ break;
+ default:
+ gly = ESCAPE_ERROR;
+ break;
+ }
+ }
*sz = 1;
break;
}
break;
+ case '*':
+ if (strncmp(*start, "(.T", 3) != 0)
+ abort();
+ gly = ESCAPE_DEVICE;
+ *start = ++*end;
+ *sz = 2;
+ break;
/*
* These escapes are of the form \X'Y', where 'X' is the trigger
@@ -250,18 +356,29 @@ mandoc_escape(const char **end, const char **start, int *sz)
break;
/*
- * Anything else is assumed to be a glyph.
- * In this case, pass back the character after the backslash.
+ * Several special characters can be encoded as
+ * one-byte escape sequences without using \[].
*/
- default:
+ case ' ':
+ case '\'':
+ case '-':
+ case '.':
+ case '0':
+ case ':':
+ case '_':
+ case '`':
+ case 'e':
+ case '~':
gly = ESCAPE_SPECIAL;
+ /* FALLTHROUGH */
+ default:
+ if (gly == ESCAPE_ERROR)
+ gly = ESCAPE_UNDEF;
*start = --*end;
*sz = 1;
break;
}
- assert(ESCAPE_ERROR != gly);
-
/*
* Read up to the terminating character,
* paying attention to nested escapes.
@@ -284,6 +401,15 @@ mandoc_escape(const char **end, const char **start, int *sz)
}
}
*sz = (*end)++ - *start;
+
+ /*
+ * The file chars.c only provides one common list
+ * of character names, but \[-] == \- is the only
+ * one of the characters with one-byte names that
+ * allows enclosing the name in brackets.
+ */
+ if (gly == ESCAPE_SPECIAL && *sz == 1 && **start != '-')
+ return ESCAPE_ERROR;
} else {
assert(*sz > 0);
if ((size_t)*sz > strlen(*start))
@@ -295,43 +421,25 @@ mandoc_escape(const char **end, const char **start, int *sz)
switch (gly) {
case ESCAPE_FONT:
- if (2 == *sz) {
- if ('C' == **start) {
- /*
- * Treat constant-width font modes
- * just like regular font modes.
- */
- (*start)++;
- (*sz)--;
- } else {
- if ('B' == (*start)[0] && 'I' == (*start)[1])
- gly = ESCAPE_FONTBI;
+ gly = mandoc_font(*start, *sz);
+ break;
+ case ESCAPE_SPECIAL:
+ if (**start == 'c') {
+ if (*sz < 6 || *sz > 7 ||
+ strncmp(*start, "char", 4) != 0 ||
+ (int)strspn(*start + 4, "0123456789") + 4 < *sz)
break;
- }
- } else if (1 != *sz)
- break;
-
- switch (**start) {
- case '3':
- case 'B':
- gly = ESCAPE_FONTBOLD;
- break;
- case '2':
- case 'I':
- gly = ESCAPE_FONTITALIC;
- break;
- case 'P':
- gly = ESCAPE_FONTPREV;
- break;
- case '1':
- case 'R':
- gly = ESCAPE_FONTROMAN;
+ c = 0;
+ for (i = 4; i < *sz; i++)
+ c = 10 * c + ((*start)[i] - '0');
+ if (c < 0x21 || (c > 0x7e && c < 0xa0) || c > 0xff)
+ break;
+ *start += 4;
+ *sz -= 4;
+ gly = ESCAPE_NUMBERED;
break;
}
- break;
- case ESCAPE_SPECIAL:
- if (1 == *sz && 'c' == **start)
- gly = ESCAPE_NOSPACE;
+
/*
* Unicode escapes are defined in groff as \[u0000]
* to \[u10FFFF], where the contained value must be
@@ -358,101 +466,6 @@ mandoc_escape(const char **end, const char **start, int *sz)
return gly;
}
-/*
- * Parse a quoted or unquoted roff-style request or macro argument.
- * Return a pointer to the parsed argument, which is either the original
- * pointer or advanced by one byte in case the argument is quoted.
- * NUL-terminate the argument in place.
- * Collapse pairs of quotes inside quoted arguments.
- * Advance the argument pointer to the next argument,
- * or to the NUL byte terminating the argument line.
- */
-char *
-mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
-{
- char *start, *cp;
- int quoted, pairs, white;
-
- /* Quoting can only start with a new word. */
- start = *cpp;
- quoted = 0;
- if ('"' == *start) {
- quoted = 1;
- start++;
- }
-
- pairs = 0;
- white = 0;
- for (cp = start; '\0' != *cp; cp++) {
-
- /*
- * Move the following text left
- * after quoted quotes and after "\\" and "\t".
- */
- if (pairs)
- cp[-pairs] = cp[0];
-
- if ('\\' == cp[0]) {
- /*
- * In copy mode, translate double to single
- * backslashes and backslash-t to literal tabs.
- */
- switch (cp[1]) {
- case 't':
- cp[0] = '\t';
- /* FALLTHROUGH */
- case '\\':
- pairs++;
- cp++;
- break;
- case ' ':
- /* Skip escaped blanks. */
- if (0 == quoted)
- cp++;
- break;
- default:
- break;
- }
- } else if (0 == quoted) {
- if (' ' == cp[0]) {
- /* Unescaped blanks end unquoted args. */
- white = 1;
- break;
- }
- } else if ('"' == cp[0]) {
- if ('"' == cp[1]) {
- /* Quoted quotes collapse. */
- pairs++;
- cp++;
- } else {
- /* Unquoted quotes end quoted args. */
- quoted = 2;
- break;
- }
- }
- }
-
- /* Quoted argument without a closing quote. */
- if (1 == quoted)
- mandoc_msg(MANDOCERR_ARG_QUOTE, parse, ln, *pos, NULL);
-
- /* NUL-terminate this argument and move to the next one. */
- if (pairs)
- cp[-pairs] = '\0';
- if ('\0' != *cp) {
- *cp++ = '\0';
- while (' ' == *cp)
- cp++;
- }
- *pos += (int)(cp - start) + (quoted ? 1 : 0);
- *cpp = cp;
-
- if ('\0' == *cp && (white || ' ' == cp[-1]))
- mandoc_msg(MANDOCERR_SPACE_EOL, parse, ln, *pos, NULL);
-
- return start;
-}
-
static int
a2time(time_t *t, const char *fmt, const char *p)
{
@@ -529,7 +542,7 @@ mandoc_normdate(struct roff_man *man, char *in, int ln, int pos)
/* No date specified: use today's date. */
if (in == NULL || *in == '\0' || strcmp(in, "$" "Mdocdate$") == 0) {
- mandoc_msg(MANDOCERR_DATE_MISSING, man->parse, ln, pos, NULL);
+ mandoc_msg(MANDOCERR_DATE_MISSING, ln, pos, NULL);
return time2a(time(NULL));
}
@@ -539,23 +552,20 @@ mandoc_normdate(struct roff_man *man, char *in, int ln, int pos)
a2time(&t, "%b %d, %Y", in)) {
cp = time2a(t);
if (t > time(NULL) + 86400)
- mandoc_msg(MANDOCERR_DATE_FUTURE, man->parse,
- ln, pos, cp);
+ mandoc_msg(MANDOCERR_DATE_FUTURE, ln, pos, "%s", cp);
else if (*in != '$' && strcmp(in, cp) != 0)
- mandoc_msg(MANDOCERR_DATE_NORM, man->parse,
- ln, pos, cp);
+ mandoc_msg(MANDOCERR_DATE_NORM, ln, pos, "%s", cp);
return cp;
}
/* In man(7), do not warn about the legacy format. */
if (a2time(&t, "%Y-%m-%d", in) == 0)
- mandoc_msg(MANDOCERR_DATE_BAD, man->parse, ln, pos, in);
+ mandoc_msg(MANDOCERR_DATE_BAD, ln, pos, "%s", in);
else if (t > time(NULL) + 86400)
- mandoc_msg(MANDOCERR_DATE_FUTURE, man->parse, ln, pos, in);
- else if (man->macroset == MACROSET_MDOC)
- mandoc_vmsg(MANDOCERR_DATE_LEGACY, man->parse,
- ln, pos, "Dd %s", in);
+ mandoc_msg(MANDOCERR_DATE_FUTURE, ln, pos, "%s", in);
+ else if (man->meta.macroset == MACROSET_MDOC)
+ mandoc_msg(MANDOCERR_DATE_LEGACY, ln, pos, "Dd %s", in);
/* Use any non-mdoc(7) date verbatim. */
diff --git a/mandoc.css b/mandoc.css
index c93bc22a2d14..085f5c08b26d 100644
--- a/mandoc.css
+++ b/mandoc.css
@@ -1,6 +1,11 @@
-/* $Id: mandoc.css,v 1.36 2018/07/23 22:51:26 schwarze Exp $ */
+/* $Id: mandoc.css,v 1.45 2019/03/01 10:57:18 schwarze Exp $ */
/*
* Standard style sheet for mandoc(1) -Thtml and man.cgi(8).
+ *
+ * Written by Ingo Schwarze <schwarze@openbsd.org>.
+ * I place this file into the public domain.
+ * Permission to use, copy, modify, and distribute it for any purpose
+ * with or without fee is hereby granted, without any conditions.
*/
/* Global defaults. */
@@ -8,8 +13,16 @@
html { max-width: 65em; }
body { font-family: Helvetica,Arial,sans-serif; }
table { margin-top: 0em;
- margin-bottom: 0em; }
-td { vertical-align: top; }
+ margin-bottom: 0em;
+ border-collapse: collapse; }
+/* Some browsers set border-color in a browser style for tbody,
+ * but not for table, resulting in inconsistent border styling. */
+tbody { border-color: inherit; }
+tr { border-color: inherit; }
+td { vertical-align: top;
+ padding-left: 0.2em;
+ padding-right: 0.2em;
+ border-color: inherit; }
ul, ol, dl { margin-top: 0em;
margin-bottom: 0em; }
li, dt { margin-top: 1em; }
@@ -52,12 +65,14 @@ td.foot-os { text-align: right; }
.manual-text {
margin-left: 3.8em; }
-.Nd { display: inline; }
-.Sh { margin-top: 1.2em;
+.Nd { }
+section.Sh { }
+h1.Sh { margin-top: 1.2em;
margin-bottom: 0.6em;
margin-left: -3.2em;
font-size: 110%; }
-.Ss { margin-top: 1.2em;
+section.Ss { }
+h2.Ss { margin-top: 1.2em;
margin-bottom: 0.6em;
margin-left: -1.2em;
font-size: 105%; }
@@ -106,20 +121,25 @@ td.foot-os { text-align: right; }
.Bl-ohang > dt { }
.Bl-ohang > dd {
margin-left: 0em; }
-.Bl-tag { margin-left: 5.5em; }
+.Bl-tag { margin-top: 0.6em;
+ margin-left: 5.5em; }
.Bl-tag > dt {
float: left;
margin-top: 0em;
margin-left: -5.5em;
- padding-right: 1.2em;
+ padding-right: 0.5em;
vertical-align: top; }
.Bl-tag > dd {
clear: right;
width: 100%;
margin-top: 0em;
margin-left: 0em;
+ margin-bottom: 0.6em;
vertical-align: top;
overflow: auto; }
+.Bl-compact { margin-top: 0em; }
+.Bl-compact > dd {
+ margin-bottom: 0em; }
.Bl-compact > dt {
margin-top: 0em; }
@@ -151,7 +171,7 @@ td.foot-os { text-align: right; }
.RsV { }
.eqn { }
-.tbl { }
+.tbl td { vertical-align: middle; }
.HP { margin-left: 3.8em;
text-indent: -3.8em; }
@@ -236,12 +256,86 @@ a.In { }
font-weight: normal;
font-family: monospace; }
+/* Tooltip support. */
+
+h1.Sh, h2.Ss { position: relative; }
+.An, .Ar, .Cd, .Cm, .Dv, .Em, .Er, .Ev, .Fa, .Fd, .Fl, .Fn, .Ft,
+.Ic, code.In, .Lb, .Lk, .Ms, .Mt, .Nd, code.Nm, .Pa, .Rs,
+.St, .Sx, .Sy, .Va, .Vt, .Xr {
+ display: inline-block;
+ position: relative; }
+
+.An::before { content: "An"; }
+.Ar::before { content: "Ar"; }
+.Cd::before { content: "Cd"; }
+.Cm::before { content: "Cm"; }
+.Dv::before { content: "Dv"; }
+.Em::before { content: "Em"; }
+.Er::before { content: "Er"; }
+.Ev::before { content: "Ev"; }
+.Fa::before { content: "Fa"; }
+.Fd::before { content: "Fd"; }
+.Fl::before { content: "Fl"; }
+.Fn::before { content: "Fn"; }
+.Ft::before { content: "Ft"; }
+.Ic::before { content: "Ic"; }
+code.In::before { content: "In"; }
+.Lb::before { content: "Lb"; }
+.Lk::before { content: "Lk"; }
+.Ms::before { content: "Ms"; }
+.Mt::before { content: "Mt"; }
+.Nd::before { content: "Nd"; }
+code.Nm::before { content: "Nm"; }
+.Pa::before { content: "Pa"; }
+.Rs::before { content: "Rs"; }
+h1.Sh::before { content: "Sh"; }
+h2.Ss::before { content: "Ss"; }
+.St::before { content: "St"; }
+.Sx::before { content: "Sx"; }
+.Sy::before { content: "Sy"; }
+.Va::before { content: "Va"; }
+.Vt::before { content: "Vt"; }
+.Xr::before { content: "Xr"; }
+
+.An::before, .Ar::before, .Cd::before, .Cm::before,
+.Dv::before, .Em::before, .Er::before, .Ev::before,
+.Fa::before, .Fd::before, .Fl::before, .Fn::before, .Ft::before,
+.Ic::before, code.In::before, .Lb::before, .Lk::before,
+.Ms::before, .Mt::before, .Nd::before, code.Nm::before,
+.Pa::before, .Rs::before,
+h1.Sh::before, h2.Ss::before, .St::before, .Sx::before, .Sy::before,
+.Va::before, .Vt::before, .Xr::before {
+ opacity: 0;
+ transition: .15s ease opacity;
+ pointer-events: none;
+ position: absolute;
+ bottom: 100%;
+ box-shadow: 0 0 .35em #000;
+ padding: .15em .25em;
+ white-space: nowrap;
+ font-family: Helvetica,Arial,sans-serif;
+ font-style: normal;
+ font-weight: bold;
+ color: black;
+ background: #fff; }
+.An:hover::before, .Ar:hover::before, .Cd:hover::before, .Cm:hover::before,
+.Dv:hover::before, .Em:hover::before, .Er:hover::before, .Ev:hover::before,
+.Fa:hover::before, .Fd:hover::before, .Fl:hover::before, .Fn:hover::before,
+.Ft:hover::before, .Ic:hover::before, code.In:hover::before,
+.Lb:hover::before, .Lk:hover::before, .Ms:hover::before, .Mt:hover::before,
+.Nd:hover::before, code.Nm:hover::before, .Pa:hover::before,
+.Rs:hover::before, h1.Sh:hover::before, h2.Ss:hover::before, .St:hover::before,
+.Sx:hover::before, .Sy:hover::before, .Va:hover::before, .Vt:hover::before,
+.Xr:hover::before {
+ opacity: 1;
+ pointer-events: inherit; }
+
/* Overrides to avoid excessive margins on small devices. */
@media (max-width: 37.5em) {
.manual-text {
margin-left: 0.5em; }
-.Sh, .Ss { margin-left: 0em; }
+h1.Sh, h2.Ss { margin-left: 0em; }
.Bd-indent { margin-left: 2em; }
.Bl-hang > dd {
margin-left: 2em; }
diff --git a/mandoc.h b/mandoc.h
index dbc266cc3b06..a44b192e0f4f 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -1,7 +1,7 @@
-/* $Id: mandoc.h,v 1.248 2018/07/28 18:34:15 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.262 2018/12/16 00:17:02 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012-2018 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
@@ -14,6 +14,8 @@
* 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.
+ *
+ * Error handling, escape sequence, and character utilities.
*/
#define ASCII_NBRSP 31 /* non-breaking space */
@@ -158,6 +160,7 @@ enum mandocerr {
MANDOCERR_LB_BAD, /* unknown library name: Lb ... */
MANDOCERR_RS_BAD, /* invalid content in Rs block: macro */
MANDOCERR_SM_BAD, /* invalid Boolean argument: macro arg */
+ MANDOCERR_CHAR_FONT, /* argument contains two font escapes */
MANDOCERR_FT_BAD, /* unknown font, skipping request: ft font */
MANDOCERR_TR_ODD, /* odd number of characters in request: tr char */
@@ -166,6 +169,7 @@ enum mandocerr {
MANDOCERR_FI_TAB, /* tab in filled text */
MANDOCERR_EOS, /* new sentence, new line */
MANDOCERR_ESC_BAD, /* invalid escape sequence: esc */
+ MANDOCERR_ESC_UNDEF, /* undefined escape, printing literally: char */
MANDOCERR_STR_UNDEF, /* undefined string, using "": name */
/* related to tables */
@@ -195,6 +199,7 @@ enum mandocerr {
MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
MANDOCERR_CHAR_BAD, /* skipping bad character: number */
MANDOCERR_MACRO, /* skipping unknown macro: macro */
+ MANDOCERR_REQ_NOMAC, /* skipping request outside macro: ... */
MANDOCERR_REQ_INSEC, /* skipping insecure request: request */
MANDOCERR_IT_STRAY, /* skipping item outside list: It ... */
MANDOCERR_TA_STRAY, /* skipping column outside column list: Ta */
@@ -205,14 +210,18 @@ enum mandocerr {
/* related to request and macro arguments */
MANDOCERR_NAMESC, /* escaped character not allowed in a name: name */
+ MANDOCERR_ARG_UNDEF, /* using macro argument outside macro */
+ MANDOCERR_ARG_NONUM, /* argument number is not numeric */
MANDOCERR_BD_FILE, /* NOT IMPLEMENTED: Bd -file */
MANDOCERR_BD_NOARG, /* skipping display without arguments: Bd */
MANDOCERR_BL_NOTYPE, /* missing list type, using -item: Bl */
MANDOCERR_CE_NONUM, /* argument is not numeric, using 1: ce ... */
+ MANDOCERR_CHAR_ARG, /* argument is not a character: char ... */
MANDOCERR_NM_NONAME, /* missing manual name, using "": Nm */
MANDOCERR_OS_UNAME, /* uname(3) system call failed, using UNKNOWN */
MANDOCERR_ST_BAD, /* unknown standard specifier: St standard */
MANDOCERR_IT_NONUM, /* skipping request without numeric argument */
+ MANDOCERR_SHIFT, /* excessive shift: ..., but max is ... */
MANDOCERR_SO_PATH, /* NOT IMPLEMENTED: .so with absolute path or ".." */
MANDOCERR_SO_FAIL, /* .so request failed */
MANDOCERR_ARG_SKIP, /* skipping all arguments: macro args */
@@ -223,7 +232,12 @@ enum mandocerr {
MANDOCERR_TOOLARGE, /* input too large */
MANDOCERR_CHAR_UNSUPP, /* unsupported control character: number */
+ MANDOCERR_ESC_UNSUPP, /* unsupported escape sequence: escape */
MANDOCERR_REQ_UNSUPP, /* unsupported roff request: request */
+ MANDOCERR_WHILE_NEST, /* nested .while loops */
+ MANDOCERR_WHILE_OUTOF, /* end of scope with open .while loop */
+ MANDOCERR_WHILE_INTO, /* end of .while loop in inner scope */
+ MANDOCERR_WHILE_FAIL, /* cannot continue this .while loop */
MANDOCERR_TBLOPT_EQN, /* eqn delim option in tbl: arg */
MANDOCERR_TBLLAYOUT_MOD, /* unsupported tbl layout modifier: m */
MANDOCERR_TBLMACRO, /* ignoring macro in table: macro */
@@ -231,206 +245,22 @@ enum mandocerr {
MANDOCERR_MAX
};
-struct tbl_opts {
- char tab; /* cell-separator */
- char decimal; /* decimal point */
- int opts;
-#define TBL_OPT_CENTRE (1 << 0)
-#define TBL_OPT_EXPAND (1 << 1)
-#define TBL_OPT_BOX (1 << 2)
-#define TBL_OPT_DBOX (1 << 3)
-#define TBL_OPT_ALLBOX (1 << 4)
-#define TBL_OPT_NOKEEP (1 << 5)
-#define TBL_OPT_NOSPACE (1 << 6)
-#define TBL_OPT_NOWARN (1 << 7)
- int cols; /* number of columns */
- int lvert; /* width of left vertical line */
- int rvert; /* width of right vertical line */
-};
-
-enum tbl_cellt {
- TBL_CELL_CENTRE, /* c, C */
- TBL_CELL_RIGHT, /* r, R */
- TBL_CELL_LEFT, /* l, L */
- TBL_CELL_NUMBER, /* n, N */
- TBL_CELL_SPAN, /* s, S */
- TBL_CELL_LONG, /* a, A */
- TBL_CELL_DOWN, /* ^ */
- TBL_CELL_HORIZ, /* _, - */
- TBL_CELL_DHORIZ, /* = */
- TBL_CELL_MAX
-};
-
-/*
- * A cell in a layout row.
- */
-struct tbl_cell {
- struct tbl_cell *next;
- char *wstr; /* min width represented as a string */
- size_t width; /* minimum column width */
- size_t spacing; /* to the right of the column */
- int vert; /* width of subsequent vertical line */
- int col; /* column number, starting from 0 */
- int flags;
-#define TBL_CELL_TALIGN (1 << 0) /* t, T */
-#define TBL_CELL_BALIGN (1 << 1) /* d, D */
-#define TBL_CELL_BOLD (1 << 2) /* fB, B, b */
-#define TBL_CELL_ITALIC (1 << 3) /* fI, I, i */
-#define TBL_CELL_EQUAL (1 << 4) /* e, E */
-#define TBL_CELL_UP (1 << 5) /* u, U */
-#define TBL_CELL_WIGN (1 << 6) /* z, Z */
-#define TBL_CELL_WMAX (1 << 7) /* x, X */
- enum tbl_cellt pos;
-};
-
-/*
- * A layout row.
- */
-struct tbl_row {
- struct tbl_row *next;
- struct tbl_cell *first;
- struct tbl_cell *last;
- int vert; /* width of left vertical line */
-};
-
-enum tbl_datt {
- TBL_DATA_NONE, /* has no data */
- TBL_DATA_DATA, /* consists of data/string */
- TBL_DATA_HORIZ, /* horizontal line */
- TBL_DATA_DHORIZ, /* double-horizontal line */
- TBL_DATA_NHORIZ, /* squeezed horizontal line */
- TBL_DATA_NDHORIZ /* squeezed double-horizontal line */
-};
-
-/*
- * A cell within a row of data. The "string" field contains the actual
- * string value that's in the cell. The rest is layout.
- */
-struct tbl_dat {
- struct tbl_cell *layout; /* layout cell */
- struct tbl_dat *next;
- char *string; /* data (NULL if not TBL_DATA_DATA) */
- int spans; /* how many spans follow */
- int block; /* T{ text block T} */
- enum tbl_datt pos;
-};
-
-enum tbl_spant {
- TBL_SPAN_DATA, /* span consists of data */
- TBL_SPAN_HORIZ, /* span is horizontal line */
- TBL_SPAN_DHORIZ /* span is double horizontal line */
-};
-
-/*
- * A row of data in a table.
- */
-struct tbl_span {
- struct tbl_opts *opts;
- struct tbl_row *layout; /* layout row */
- struct tbl_dat *first;
- struct tbl_dat *last;
- struct tbl_span *prev;
- struct tbl_span *next;
- int line; /* parse line */
- enum tbl_spant pos;
-};
-
-enum eqn_boxt {
- EQN_TEXT, /* text (number, variable, whatever) */
- EQN_SUBEXPR, /* nested `eqn' subexpression */
- EQN_LIST, /* list (braces, etc.) */
- EQN_PILE, /* vertical pile */
- EQN_MATRIX /* pile of piles */
-};
-
-enum eqn_fontt {
- EQNFONT_NONE = 0,
- EQNFONT_ROMAN,
- EQNFONT_BOLD,
- EQNFONT_FAT,
- EQNFONT_ITALIC,
- EQNFONT__MAX
-};
-
-enum eqn_post {
- EQNPOS_NONE = 0,
- EQNPOS_SUP,
- EQNPOS_SUBSUP,
- EQNPOS_SUB,
- EQNPOS_TO,
- EQNPOS_FROM,
- EQNPOS_FROMTO,
- EQNPOS_OVER,
- EQNPOS_SQRT,
- EQNPOS__MAX
-};
-
-enum eqn_pilet {
- EQNPILE_NONE = 0,
- EQNPILE_PILE,
- EQNPILE_CPILE,
- EQNPILE_RPILE,
- EQNPILE_LPILE,
- EQNPILE_COL,
- EQNPILE_CCOL,
- EQNPILE_RCOL,
- EQNPILE_LCOL,
- EQNPILE__MAX
-};
-
- /*
- * A "box" is a parsed mathematical expression as defined by the eqn.7
- * grammar.
- */
-struct eqn_box {
- int size; /* font size of expression */
-#define EQN_DEFSIZE INT_MIN
- enum eqn_boxt type; /* type of node */
- struct eqn_box *first; /* first child node */
- struct eqn_box *last; /* last child node */
- struct eqn_box *next; /* node sibling */
- struct eqn_box *prev; /* node sibling */
- struct eqn_box *parent; /* node sibling */
- char *text; /* text (or NULL) */
- char *left; /* fence left-hand */
- char *right; /* fence right-hand */
- char *top; /* expression over-symbol */
- char *bottom; /* expression under-symbol */
- size_t args; /* arguments in parent */
- size_t expectargs; /* max arguments in parent */
- enum eqn_post pos; /* position of next box */
- enum eqn_fontt font; /* font of box */
- enum eqn_pilet pile; /* equation piling */
-};
-
-/*
- * Parse options.
- */
-#define MPARSE_MDOC 1 /* assume -mdoc */
-#define MPARSE_MAN 2 /* assume -man */
-#define MPARSE_SO 4 /* honour .so requests */
-#define MPARSE_QUICK 8 /* abort the parse early */
-#define MPARSE_UTF8 16 /* accept UTF-8 input */
-#define MPARSE_LATIN1 32 /* accept ISO-LATIN-1 input */
-
-enum mandoc_os {
- MANDOC_OS_OTHER = 0,
- MANDOC_OS_NETBSD,
- MANDOC_OS_OPENBSD
-};
-
enum mandoc_esc {
ESCAPE_ERROR = 0, /* bail! unparsable escape */
+ ESCAPE_UNSUPP, /* unsupported escape; ignore it */
ESCAPE_IGNORE, /* escape to be ignored */
+ ESCAPE_UNDEF, /* undefined escape; print literal character */
ESCAPE_SPECIAL, /* a regular special character */
ESCAPE_FONT, /* a generic font mode */
ESCAPE_FONTBOLD, /* bold font mode */
ESCAPE_FONTITALIC, /* italic font mode */
ESCAPE_FONTBI, /* bold italic font mode */
ESCAPE_FONTROMAN, /* roman font mode */
+ ESCAPE_FONTCW, /* constant width font mode */
ESCAPE_FONTPREV, /* previous font mode */
ESCAPE_NUMBERED, /* a numbered glyph */
ESCAPE_UNICODE, /* a unicode codepoint */
+ ESCAPE_DEVICE, /* print the output device name */
ESCAPE_BREAK, /* break the output line */
ESCAPE_NOSPACE, /* suppress space if the last on a line */
ESCAPE_HORIZ, /* horizontal movement */
@@ -439,14 +269,18 @@ enum mandoc_esc {
ESCAPE_OVERSTRIKE /* overstrike all chars in the argument */
};
-typedef void (*mandocmsg)(enum mandocerr, enum mandoclevel,
- const char *, int, int, const char *);
-
-
-struct mparse;
-struct roff_man;
+enum mandoc_esc mandoc_font(const char *, int sz);
enum mandoc_esc mandoc_escape(const char **, const char **, int *);
+void mandoc_msg_setoutfile(FILE *);
+const char *mandoc_msg_getinfilename(void);
+void mandoc_msg_setinfilename(const char *);
+enum mandocerr mandoc_msg_getmin(void);
+void mandoc_msg_setmin(enum mandocerr);
+enum mandoclevel mandoc_msg_getrc(void);
+void mandoc_msg_setrc(enum mandoclevel);
+void mandoc_msg(enum mandocerr, int, int, const char *, ...)
+ __attribute__((__format__ (__printf__, 4, 5)));
void mchars_alloc(void);
void mchars_free(void);
int mchars_num2char(const char *, size_t);
@@ -454,18 +288,3 @@ const char *mchars_uc2str(int);
int mchars_num2uc(const char *, size_t);
int mchars_spec2cp(const char *, size_t);
const char *mchars_spec2str(const char *, size_t, size_t *);
-struct mparse *mparse_alloc(int, enum mandocerr, mandocmsg,
- enum mandoc_os, const char *);
-void mparse_free(struct mparse *);
-void mparse_keep(struct mparse *);
-int mparse_open(struct mparse *, const char *);
-enum mandoclevel mparse_readfd(struct mparse *, int, const char *);
-enum mandoclevel mparse_readmem(struct mparse *, void *, size_t,
- const char *);
-void mparse_reset(struct mparse *);
-void mparse_result(struct mparse *,
- struct roff_man **, char **);
-const char *mparse_getkeep(const struct mparse *);
-const char *mparse_strerror(enum mandocerr);
-const char *mparse_strlevel(enum mandoclevel);
-void mparse_updaterc(struct mparse *, enum mandoclevel *);
diff --git a/mandoc_char.7 b/mandoc_char.7
index f63cdaea8fcc..578f37f180c0 100644
--- a/mandoc_char.7
+++ b/mandoc_char.7
@@ -1,8 +1,8 @@
-.\" $Id: mandoc_char.7,v 1.72 2018/08/08 14:30:48 schwarze Exp $
+.\" $Id: mandoc_char.7,v 1.75 2018/12/15 19:30:26 schwarze Exp $
.\"
.\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2011, 2013, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2011,2013,2015,2017,2018 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
@@ -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: August 8 2018 $
+.Dd $Mdocdate: December 15 2018 $
.Dt MANDOC_CHAR 7
.Os
.Sh NAME
@@ -266,11 +266,13 @@ Spacing:
.It Em Input Ta Em Description
.It Sq \e\ \& Ta unpaddable non-breaking space
.It \e\(ti Ta paddable non-breaking space
-.It \e0 Ta unpaddable, breaking digit-width space
+.It \e0 Ta digit-width space allowing line break
.It \e| Ta one-sixth \e(em narrow space, zero width in nroff mode
.It \e^ Ta one-twelfth \e(em half-narrow space, zero width in nroff
-.It \e& Ta zero-width space
+.It \e& Ta zero-width non-breaking space
+.It \e) Ta zero-width space transparent to end-of-sentence detection
.It \e% Ta zero-width space allowing hyphenation
+.It \e: Ta zero-width space allowing line break
.El
.Pp
Lines:
@@ -543,11 +545,13 @@ Accented letters:
.It \e(\(aqI Ta \('I Ta acute I
.It \e(\(aqO Ta \('O Ta acute O
.It \e(\(aqU Ta \('U Ta acute U
+.It \e(\(aqY Ta \('Y Ta acute Y
.It \e(\(aqa Ta \('a Ta acute a
.It \e(\(aqe Ta \('e Ta acute e
.It \e(\(aqi Ta \('i Ta acute i
.It \e(\(aqo Ta \('o Ta acute o
.It \e(\(aqu Ta \('u Ta acute u
+.It \e(\(aqy Ta \('y Ta acute y
.It \e(\(gaA Ta \(`A Ta grave A
.It \e(\(gaE Ta \(`E Ta grave E
.It \e(\(gaI Ta \(`I Ta grave I
@@ -761,14 +765,16 @@ For backward compatibility with existing manuals,
.Xr mandoc 1
also supports the
.Pp
-.Dl \eN\(aq Ns Ar number Ns \(aq
+.Dl \eN\(aq Ns Ar number Ns \(aq and \e[ Ns Cm char Ns Ar number ]
.Pp
-escape sequence, inserting the character
+escape sequences, inserting the character
.Ar number
from the current character set into the output.
Of course, this is inherently non-portable and is already marked
-as deprecated in the Heirloom roff manual.
-For example, do not use \eN\(aq34\(aq, use \e(dq, or even the plain
+as deprecated in the Heirloom roff manual;
+on top of that, the second form is a GNU extension.
+For example, do not use \eN\(aq34\(aq or \e[char34], use \e(dq,
+or even the plain
.Sq \(dq
character where possible.
.Sh COMPATIBILITY
diff --git a/mandoc_headers.3 b/mandoc_headers.3
index 4a05d49678fd..321384739116 100644
--- a/mandoc_headers.3
+++ b/mandoc_headers.3
@@ -1,4 +1,4 @@
-.Dd $Mdocdate: July 8 2017 $
+.Dd $Mdocdate: December 30 2018 $
.Dt MANDOC_HEADERS 3
.Os
.Sh NAME
@@ -25,13 +25,13 @@ separate from each other:
.Pp
.Bl -dash -offset indent -compact
.It
-.Xr mdoc 7
+.Xr roff 7
parser
.It
-.Xr man 7
+.Xr mdoc 7
parser
.It
-.Xr roff 7
+.Xr man 7
parser
.It
.Xr tbl 7
@@ -45,6 +45,8 @@ terminal formatters
HTML formatters
.It
search tools
+.It
+main programs
.El
.Pp
Note that mere usage of an opaque struct type does
@@ -56,14 +58,18 @@ any other mandoc header.
These headers should be included before any other mandoc headers.
.Bl -tag -width Ds
.It Qq Pa mandoc_aux.h
+Memory allocation utility functions; can be used everywhere.
+.Pp
Requires
.In sys/types.h
for
.Vt size_t .
.Pp
-Provides the utility functions documented in
+Provides the functions documented in
.Xr mandoc_malloc 3 .
.It Qq Pa mandoc_ohash.h
+Hashing utility functions; can be used everywhere.
+.Pp
Requires
.In stddef.h
for
@@ -78,51 +84,130 @@ Includes
and provides
.Fn mandoc_ohash_init .
.It Qq Pa mandoc.h
+Error handling, escape sequence, and character utilities;
+can be used everywhere.
+.Pp
Requires
.In sys/types.h
for
-.Vt size_t .
+.Vt size_t
+and
+.In stdio.h
+for
+.Vt FILE .
.Pp
Provides
.Vt enum mandoc_esc ,
.Vt enum mandocerr ,
.Vt enum mandoclevel ,
+the function
+.Xr mandoc_escape 3 ,
+the functions described in
+.Xr mchars_alloc 3 ,
+and the
+.Fn mandoc_msg*
+functions.
+.It Qq Pa roff.h
+Common data types for all syntax trees and related functions;
+can be used everywhere.
+.Pp
+Provides
.Vt enum mandoc_os ,
+.Vt enum mdoc_endbody ,
+.Vt enum roff_macroset ,
+.Vt enum roff_sec ,
+.Vt enum roff_tok ,
+.Vt enum roff_type ,
+.Vt struct roff_man ,
+.Vt struct roff_meta ,
+.Vt struct roff_node ,
+the constant array
+.Va roff_name
+and the function
+.Fn deroff .
+.Pp
+Uses pointers to the types
+.Vt struct ohash
+from
+.Pa mandoc_ohash.h ,
+.Vt struct mdoc_arg
+and
+.Vt union mdoc_data
+from
+.Pa mdoc.h ,
+.Vt struct tbl_span
+from
+.Pa tbl.h ,
+and
+.Vt struct eqn_box
+from
+.Pa eqn.h
+as opaque struct members.
+.It Qq Pa tbl.h
+Data structures for the
+.Xr tbl 7
+parse tree; can be used everywhere.
+.Pp
+Requires
+.In sys/types.h
+for
+.Vt size_t .
+.Pp
+Provides
.Vt enum tbl_cellt ,
.Vt enum tbl_datt ,
.Vt enum tbl_spant ,
-.Vt enum eqn_boxt ,
-.Vt enum eqn_fontt ,
-.Vt enum eqn_pilet ,
-.Vt enum eqn_post ,
.Vt struct tbl_opts ,
.Vt struct tbl_cell ,
.Vt struct tbl_row ,
.Vt struct tbl_dat ,
-.Vt struct tbl_span ,
-.Vt struct eqn_box ,
-the function prototype typedef
-.Fn mandocmsg ,
-the function
-.Xr mandoc_escape 3 ,
-the functions described in
-.Xr mchars_alloc 3 ,
-and the functions
-.Fn mparse_*
-described in
-.Xr mandoc 3 .
+and
+.Vt struct tbl_span .
+.It Qq Pa eqn.h
+Data structures for the
+.Xr eqn 7
+parse tree; can be used everywhere.
+.Pp
+Requires
+.In sys/types.h
+for
+.Vt size_t .
+.Pp
+Provides
+.Vt enum eqn_boxt ,
+.Vt enum eqn_fontt ,
+.Vt enum eqn_post ,
+and
+.Vt struct eqn_box .
+.It Qq Pa mandoc_parse.h
+Top level parser interface, for use in the main program
+and in the main parser, but not in formatters.
+.Pp
+Requires
+.Pa mandoc.h
+for
+.Vt enum mandocerr
+and
+.Vt enum mandoclevel
+and
+.Pa roff.h
+for
+.Vt enum mandoc_os .
.Pp
Uses the opaque type
.Vt struct mparse
from
.Pa read.c
for function prototypes.
-Uses the type
-.Vt struct roff_man
+Uses
+.Vt struct roff_meta
from
.Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa mandoc_xr.h
+Cross reference validation; intended for use in the main program
+and in parsers, but not in formatters.
+.Pp
Provides
.Vt struct mandoc_xr
and the functions
@@ -131,43 +216,6 @@ and the functions
.Fn mandoc_xr_get ,
and
.Fn mandoc_xr_free .
-.It Qq Pa roff.h
-Requires
-.Qq Pa mandoc_ohash.h
-for
-.Vt struct ohash
-and
-.Qq Pa mandoc.h
-for
-.Vt enum mandoc_os .
-.Pp
-Provides
-.Vt enum mdoc_endbody ,
-.Vt enum roff_macroset ,
-.Vt enum roff_next ,
-.Vt enum roff_sec ,
-.Vt enum roff_tok ,
-.Vt enum roff_type ,
-.Vt struct roff_man ,
-.Vt struct roff_meta ,
-.Vt struct roff_node ,
-the constant array
-.Va roff_name
-and the functions
-.Fn deroff ,
-.Fn roffhash_alloc ,
-.Fn roffhash_find ,
-.Fn roffhash_free ,
-and
-.Fn roff_validate .
-.Pp
-Uses pointers to the types
-.Vt struct mdoc_arg
-and
-.Vt union mdoc_data
-from
-.Pa mdoc.h
-as opaque struct members.
.El
.Pp
The following two require
@@ -200,27 +248,24 @@ and the functions
described in
.Xr mandoc 3 .
.Pp
-Uses the type
-.Vt struct roff_man
+Uses the types
+.Vt struct roff_node
from
.Pa roff.h
-as an opaque type for function prototypes.
+and
+.Vt struct roff_man
+from
+.Pa roff_int.h
+as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
-.Pa libman.h
-or
-.Pa libroff.h .
+internals of different parsers.
.It Qq Pa man.h
Provides the functions
.Fn man_*
described in
.Xr mandoc 3 .
.Pp
-Uses the opaque type
-.Vt struct mparse
-from
-.Pa read.c
-for function prototypes.
Uses the type
.Vt struct roff_man
from
@@ -228,12 +273,10 @@ from
as an opaque type for function prototypes.
.Pp
When this header is included, the same file should not include
-.Pa libmdoc.h
-or
-.Pa libroff.h .
+internals of different parsers.
.El
.Ss Parser internals
-The following headers require inclusion of a parser interface header
+Most of the following headers require inclusion of a parser interface header
before they can be included.
All parser interface headers should precede all parser internal headers.
When any parser internal headers are included, the same file should
@@ -250,16 +293,11 @@ for
.Vt enum mandocerr .
.Pp
Provides
-.Vt enum rofferr ,
.Vt struct buf ,
utility functions needed by multiple parsers,
and the top-level functions to call the parsers.
.Pp
-Uses the opaque types
-.Vt struct mparse
-from
-.Pa read.c
-and
+Uses the opaque type
.Vt struct roff
from
.Pa roff.c
@@ -270,14 +308,28 @@ from
.Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa roff_int.h
+Parser internals shared by multiple parsers.
+Can be used in all parsers, but not in main programs or formatters.
+.Pp
Requires
.Qq Pa roff.h
for
-.Vt enum roff_type .
+.Vt enum roff_type
+and
+.Vt enum roff_tok .
.Pp
-Provides functions named
+Provides
+.Vt enum roff_next ,
+.Vt struct roff_man ,
+functions named
.Fn roff_*
-to handle roff nodes and the two special functions
+to handle roff nodes,
+.Fn roffhash_alloc ,
+.Fn roffhash_find ,
+.Fn roffhash_free ,
+and
+.Fn roff_validate ,
+and the two special functions
.Fn man_breakscope
and
.Fn mdoc_argv_free
@@ -285,11 +337,17 @@ because the latter two are needed by
.Qq Pa roff.c .
.Pp
Uses the types
-.Vt struct roff_man
-and
+.Vt struct ohash
+from
+.Pa mandoc_ohash.h ,
.Vt struct roff_node
+and
+.Vt struct roff_meta
from
-.Pa roff.h
+.Pa roff.h ,
+.Vt struct roff
+from
+.Pa roff.c ,
and
.Vt struct mdoc_arg
from
@@ -301,11 +359,7 @@ Requires
for
.Vt enum roff_tok
and
-.Qq Pa mdoc.h
-for
-.Vt enum mdoc_*
-and
-.Vt struct mdoc_* .
+.Vt enum roff_sec .
.Pp
Provides
.Vt enum margserr ,
@@ -315,23 +369,21 @@ and many functions internal to the
.Xr mdoc 7
parser.
.Pp
-Uses the opaque type
-.Vt struct mparse
-from
-.Pa read.c .
Uses the types
+.Vt struct roff_node
+from
+.Pa roff.h ,
.Vt struct roff_man
+from
+.Pa roff_int.h ,
and
-.Vt struct roff_node
+.Vt struct mdoc_arg
from
-.Pa roff.h
+.Pa mdoc.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
-.Pa man.h ,
-.Pa libman.h ,
-or
-.Pa libroff.h .
+interfaces of different parsers.
.It Qq Pa libman.h
Requires
.Qq Pa roff.h
@@ -345,52 +397,109 @@ and some functions internal to the
parser.
.Pp
Uses the types
-.Vt struct roff_man
-and
.Vt struct roff_node
from
.Pa roff.h
+and
+.Vt struct roff_man
+from
+.Pa roff_int.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
-.Pa mdoc.h ,
-.Pa libmdoc.h ,
-or
-.Pa libroff.h .
-.It Qq Pa libroff.h
+interfaces of different parsers.
+.It Qq Pa eqn_parse.h
+External interface of the
+.Xr eqn 7
+parser, for use in the
+.Xr roff 7
+and
+.Xr eqn 7
+parsers only.
+.Pp
Requires
.In sys/types.h
for
-.Vt size_t
+.Vt size_t .
+.Pp
+Provides
+.Vt struct eqn_node
+and the functions
+.Fn eqn_alloc ,
+.Fn eqn_box_new ,
+.Fn eqn_box_free ,
+.Fn eqn_free ,
+.Fn eqn_parse ,
+.Fn eqn_read ,
and
-.Qq Pa mandoc.h
-for
-.Vt struct tbl_*
+.Fn eqn_reset .
+.Pp
+Uses the type
+.Vt struct eqn_box
+from
+.Pa mandoc.h
+as an opaque type for function prototypes.
+Uses the types
+.Vt struct roff_node
+from
+.Pa roff.h
and
-.Vt struct eqn_box .
+.Vt struct eqn_def
+from
+.Pa eqn.c
+as opaque struct members.
.Pp
-Provides
-.Vt enum tbl_part ,
-.Vt struct tbl_node ,
-.Vt struct eqn_def ,
-.Vt struct eqn_node ,
-and many functions internal to the
+When this header is included, the same file should not include
+internals of different parsers.
+.It Qq Pa tbl_parse.h
+External interface of the
.Xr tbl 7
+parser, for use in the
+.Xr roff 7
and
-.Xr eqn 7
-parsers.
+.Xr tbl 7
+parsers only.
.Pp
-Uses the opaque type
-.Vt struct mparse
+Provides the functions documented in
+.Xr tbl 3 .
+.Pp
+Uses the types
+.Vt struct tbl_span
+from
+.Pa tbl.h
+and
+.Vt struct tbl_node
from
-.Pa read.c .
+.Pa tbl_int.h
+as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
-.Pa man.h ,
-.Pa mdoc.h ,
-.Pa libman.h ,
-or
-.Pa libmdoc.h .
+internals of different parsers.
+.It Qq Pa tbl_int.h
+Internal interfaces of the
+.Xr tbl 7
+parser, for use inside the
+.Xr tbl 7
+parser only.
+.Pp
+Requires
+.Qq Pa tbl.h
+for
+.Vt struct tbl_opts .
+.Pp
+Provides
+.Vt enum tbl_part ,
+.Vt struct tbl_node ,
+and the functions
+.Fn tbl_option ,
+.Fn tbl_layout ,
+.Fn tbl_data ,
+.Fn tbl_cdata ,
+and
+.Fn tbl_reset .
+.Pp
+When this header is included, the same file should not include
+interfaces of different parsers.
.El
.Ss Formatter interface
These headers should be included after any parser interface headers.
@@ -466,7 +575,10 @@ or
Requires
.In sys/types.h
for
-.Vt size_t
+.Vt size_t ,
+.Pa mandoc.h
+for
+.Vt enum mandoc_esc ,
and
.Qq Pa out.h
for
@@ -517,7 +629,7 @@ functionality mentioned in
Provides the top level steering functions for all formatters.
.Pp
Uses the type
-.Vt struct roff_man
+.Vt struct roff_meta
from
.Pa roff.h
as an opaque type for function prototypes.
diff --git a/mandoc_html.3 b/mandoc_html.3
index 5bd9446da824..32407574a814 100644
--- a/mandoc_html.3
+++ b/mandoc_html.3
@@ -1,4 +1,4 @@
-.\" $Id: mandoc_html.3,v 1.17 2018/06/25 16:54:59 schwarze Exp $
+.\" $Id: mandoc_html.3,v 1.19 2019/01/11 12:56:43 schwarze Exp $
.\"
.\" Copyright (c) 2014, 2017, 2018 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: June 25 2018 $
+.Dd $Mdocdate: January 11 2019 $
.Dt MANDOC_HTML 3
.Os
.Sh NAME
@@ -167,11 +167,6 @@ the respective attribute is not written.
Print a
.Cm class
attribute.
-This attribute letter can optionally be followed by the modifier letter
-.Cm T .
-In that case, a
-.Cm title
-attribute with the same value is also printed.
.It Cm h
Print a
.Cm href
@@ -216,6 +211,14 @@ It requires two
.Va char *
arguments.
The first is the name of the style property, the second its value.
+The name must not be
+.Dv NULL .
+The
+.Cm s
+.Ar fmt
+letter can be repeated, each repetition requiring an additional pair of
+.Va char *
+arguments.
.El
.Pp
.Fn print_otag
diff --git a/mandoc_msg.c b/mandoc_msg.c
new file mode 100644
index 000000000000..ff4d80313c2c
--- /dev/null
+++ b/mandoc_msg.c
@@ -0,0 +1,329 @@
+/* $Id: mandoc_msg.c,v 1.6 2019/03/06 15:55:38 schwarze Exp $ */
+/*
+ * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2014,2015,2016,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
+ *
+ * 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"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mandoc.h"
+
+static const enum mandocerr lowest_type[MANDOCLEVEL_MAX] = {
+ MANDOCERR_OK,
+ MANDOCERR_OK,
+ MANDOCERR_WARNING,
+ MANDOCERR_ERROR,
+ MANDOCERR_UNSUPP,
+ MANDOCERR_MAX,
+ MANDOCERR_MAX
+};
+
+static const char *const level_name[MANDOCLEVEL_MAX] = {
+ "SUCCESS",
+ "STYLE",
+ "WARNING",
+ "ERROR",
+ "UNSUPP",
+ "BADARG",
+ "SYSERR"
+};
+
+static const char *const type_message[MANDOCERR_MAX] = {
+ "ok",
+
+ "base system convention",
+
+ "Mdocdate found",
+ "Mdocdate missing",
+ "unknown architecture",
+ "operating system explicitly specified",
+ "RCS id missing",
+ "referenced manual not found",
+
+ "generic style suggestion",
+
+ "legacy man(7) date format",
+ "normalizing date format to",
+ "lower case character in document title",
+ "duplicate RCS id",
+ "possible typo in section name",
+ "unterminated quoted argument",
+ "useless macro",
+ "consider using OS macro",
+ "errnos out of order",
+ "duplicate errno",
+ "trailing delimiter",
+ "no blank before trailing delimiter",
+ "fill mode already enabled, skipping",
+ "fill mode already disabled, skipping",
+ "verbatim \"--\", maybe consider using \\(em",
+ "function name without markup",
+ "whitespace at end of input line",
+ "bad comment style",
+
+ "generic warning",
+
+ /* related to the prologue */
+ "missing manual title, using UNTITLED",
+ "missing manual title, using \"\"",
+ "missing manual section, using \"\"",
+ "unknown manual section",
+ "missing date, using today's date",
+ "cannot parse date, using it verbatim",
+ "date in the future, using it anyway",
+ "missing Os macro, using \"\"",
+ "late prologue macro",
+ "prologue macros out of order",
+
+ /* related to document structure */
+ ".so is fragile, better use ln(1)",
+ "no document body",
+ "content before first section header",
+ "first section is not \"NAME\"",
+ "NAME section without Nm before Nd",
+ "NAME section without description",
+ "description not at the end of NAME",
+ "bad NAME section content",
+ "missing comma before name",
+ "missing description line, using \"\"",
+ "description line outside NAME section",
+ "sections out of conventional order",
+ "duplicate section title",
+ "unexpected section",
+ "cross reference to self",
+ "unusual Xr order",
+ "unusual Xr punctuation",
+ "AUTHORS section without An macro",
+
+ /* related to macros and nesting */
+ "obsolete macro",
+ "macro neither callable nor escaped",
+ "skipping paragraph macro",
+ "moving paragraph macro out of list",
+ "skipping no-space macro",
+ "blocks badly nested",
+ "nested displays are not portable",
+ "moving content out of list",
+ "first macro on line",
+ "line scope broken",
+ "skipping blank line in line scope",
+
+ /* related to missing macro arguments */
+ "skipping empty request",
+ "conditional request controls empty scope",
+ "skipping empty macro",
+ "empty block",
+ "empty argument, using 0n",
+ "missing display type, using -ragged",
+ "list type is not the first argument",
+ "missing -width in -tag list, using 6n",
+ "missing utility name, using \"\"",
+ "missing function name, using \"\"",
+ "empty head in list item",
+ "empty list item",
+ "missing argument, using next line",
+ "missing font type, using \\fR",
+ "unknown font type, using \\fR",
+ "nothing follows prefix",
+ "empty reference block",
+ "missing section argument",
+ "missing -std argument, adding it",
+ "missing option string, using \"\"",
+ "missing resource identifier, using \"\"",
+ "missing eqn box, using \"\"",
+
+ /* related to bad macro arguments */
+ "duplicate argument",
+ "skipping duplicate argument",
+ "skipping duplicate display type",
+ "skipping duplicate list type",
+ "skipping -width argument",
+ "wrong number of cells",
+ "unknown AT&T UNIX version",
+ "comma in function argument",
+ "parenthesis in function name",
+ "unknown library name",
+ "invalid content in Rs block",
+ "invalid Boolean argument",
+ "argument contains two font escapes",
+ "unknown font, skipping request",
+ "odd number of characters in request",
+
+ /* related to plain text */
+ "blank line in fill mode, using .sp",
+ "tab in filled text",
+ "new sentence, new line",
+ "invalid escape sequence",
+ "undefined escape, printing literally",
+ "undefined string, using \"\"",
+
+ /* related to tables */
+ "tbl line starts with span",
+ "tbl column starts with span",
+ "skipping vertical bar in tbl layout",
+
+ "generic error",
+
+ /* related to tables */
+ "non-alphabetic character in tbl options",
+ "skipping unknown tbl option",
+ "missing tbl option argument",
+ "wrong tbl option argument size",
+ "empty tbl layout",
+ "invalid character in tbl layout",
+ "unmatched parenthesis in tbl layout",
+ "tbl without any data cells",
+ "ignoring data in spanned tbl cell",
+ "ignoring extra tbl data cells",
+ "data block open at end of tbl",
+
+ /* related to document structure and macros */
+ NULL,
+ "duplicate prologue macro",
+ "skipping late title macro",
+ "input stack limit exceeded, infinite loop?",
+ "skipping bad character",
+ "skipping unknown macro",
+ "ignoring request outside macro",
+ "skipping insecure request",
+ "skipping item outside list",
+ "skipping column outside column list",
+ "skipping end of block that is not open",
+ "fewer RS blocks open, skipping",
+ "inserting missing end of block",
+ "appending missing end of block",
+
+ /* related to request and macro arguments */
+ "escaped character not allowed in a name",
+ "using macro argument outside macro",
+ "argument number is not numeric",
+ "NOT IMPLEMENTED: Bd -file",
+ "skipping display without arguments",
+ "missing list type, using -item",
+ "argument is not numeric, using 1",
+ "argument is not a character",
+ "missing manual name, using \"\"",
+ "uname(3) system call failed, using UNKNOWN",
+ "unknown standard specifier",
+ "skipping request without numeric argument",
+ "excessive shift",
+ "NOT IMPLEMENTED: .so with absolute path or \"..\"",
+ ".so request failed",
+ "skipping all arguments",
+ "skipping excess arguments",
+ "divide by zero",
+
+ "unsupported feature",
+ "input too large",
+ "unsupported control character",
+ "unsupported escape sequence",
+ "unsupported roff request",
+ "nested .while loops",
+ "end of scope with open .while loop",
+ "end of .while loop in inner scope",
+ "cannot continue this .while loop",
+ "eqn delim option in tbl",
+ "unsupported tbl layout modifier",
+ "ignoring macro in table",
+};
+
+static FILE *fileptr = NULL;
+static const char *filename = NULL;
+static enum mandocerr min_type = MANDOCERR_MAX;
+static enum mandoclevel rc = MANDOCLEVEL_OK;
+
+
+void
+mandoc_msg_setoutfile(FILE *fp)
+{
+ fileptr = fp;
+}
+
+const char *
+mandoc_msg_getinfilename(void)
+{
+ return filename;
+}
+
+void
+mandoc_msg_setinfilename(const char *fn)
+{
+ filename = fn;
+}
+
+enum mandocerr
+mandoc_msg_getmin(void)
+{
+ return min_type;
+}
+
+void
+mandoc_msg_setmin(enum mandocerr t)
+{
+ min_type = t;
+}
+
+enum mandoclevel
+mandoc_msg_getrc(void)
+{
+ return rc;
+}
+
+void
+mandoc_msg_setrc(enum mandoclevel level)
+{
+ if (rc < level)
+ rc = level;
+}
+
+void
+mandoc_msg(enum mandocerr t, int line, int col, const char *fmt, ...)
+{
+ va_list ap;
+ enum mandoclevel level;
+
+ if (t < min_type && t != MANDOCERR_FILE)
+ return;
+
+ level = MANDOCLEVEL_UNSUPP;
+ while (t < lowest_type[level])
+ level--;
+ mandoc_msg_setrc(level);
+
+ if (fileptr == NULL)
+ return;
+
+ fprintf(fileptr, "%s:", getprogname());
+ if (filename != NULL)
+ fprintf(fileptr, " %s:", filename);
+
+ if (line > 0)
+ fprintf(fileptr, "%d:%d:", line, col + 1);
+
+ fprintf(fileptr, " %s", level_name[level]);
+ if (type_message[t] != NULL)
+ fprintf(fileptr, ": %s", type_message[t]);
+
+ if (fmt != NULL) {
+ fprintf(fileptr, ": ");
+ va_start(ap, fmt);
+ vfprintf(fileptr, fmt, ap);
+ va_end(ap);
+ }
+ fputc('\n', fileptr);
+}
diff --git a/mandoc_parse.h b/mandoc_parse.h
new file mode 100644
index 000000000000..61341f0d7f39
--- /dev/null
+++ b/mandoc_parse.h
@@ -0,0 +1,43 @@
+/* $Id: mandoc_parse.h,v 1.4 2018/12/30 00:49:55 schwarze Exp $ */
+/*
+ * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2014,2015,2016,2017,2018 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.
+ *
+ * Top level parser interface. For use in the main program
+ * and in the main parser, but not in formatters.
+ */
+
+/*
+ * Parse options.
+ */
+#define MPARSE_MDOC (1 << 0) /* assume -mdoc */
+#define MPARSE_MAN (1 << 1) /* assume -man */
+#define MPARSE_SO (1 << 2) /* honour .so requests */
+#define MPARSE_QUICK (1 << 3) /* abort the parse early */
+#define MPARSE_UTF8 (1 << 4) /* accept UTF-8 input */
+#define MPARSE_LATIN1 (1 << 5) /* accept ISO-LATIN-1 input */
+#define MPARSE_VALIDATE (1 << 6) /* call validation functions */
+
+
+struct roff_meta;
+struct mparse;
+
+struct mparse *mparse_alloc(int, enum mandoc_os, const char *);
+void mparse_copy(const struct mparse *);
+void mparse_free(struct mparse *);
+int mparse_open(struct mparse *, const char *);
+void mparse_readfd(struct mparse *, int, const char *);
+void mparse_reset(struct mparse *);
+struct roff_meta *mparse_result(struct mparse *);
diff --git a/mandocd.c b/mandocd.c
index 9aba9cc1d94c..1a597b3867bc 100644
--- a/mandocd.c
+++ b/mandocd.c
@@ -1,7 +1,7 @@
-/* $Id: mandocd.c,v 1.6 2017/06/24 14:38:32 schwarze Exp $ */
+/* $Id: mandocd.c,v 1.11 2019/03/03 13:02:11 schwarze Exp $ */
/*
* Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
- * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2017, 2019 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -38,6 +38,7 @@
#include "roff.h"
#include "mdoc.h"
#include "man.h"
+#include "mandoc_parse.h"
#include "main.h"
#include "manconf.h"
@@ -170,8 +171,8 @@ main(int argc, char *argv[])
errx(1, "file descriptor %s %s", argv[1], errstr);
mchars_alloc();
- parser = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1,
- MANDOCERR_MAX, NULL, MANDOC_OS_OTHER, defos);
+ parser = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1 |
+ MPARSE_VALIDATE, MANDOC_OS_OTHER, defos);
memset(&options, 0, sizeof(options));
switch (outtype) {
@@ -212,6 +213,8 @@ main(int argc, char *argv[])
process(parser, outtype, formatter);
mparse_reset(parser);
+ if (outtype == OUTT_HTML)
+ html_reset(formatter);
fflush(stdout);
fflush(stderr);
@@ -243,35 +246,29 @@ main(int argc, char *argv[])
static void
process(struct mparse *parser, enum outt outtype, void *formatter)
{
- struct roff_man *man;
+ struct roff_meta *meta;
mparse_readfd(parser, STDIN_FILENO, "<unixfd>");
- mparse_result(parser, &man, NULL);
-
- if (man == NULL)
- return;
-
- if (man->macroset == MACROSET_MDOC) {
- mdoc_validate(man);
+ meta = mparse_result(parser);
+ if (meta->macroset == MACROSET_MDOC) {
switch (outtype) {
case OUTT_ASCII:
case OUTT_UTF8:
- terminal_mdoc(formatter, man);
+ terminal_mdoc(formatter, meta);
break;
case OUTT_HTML:
- html_mdoc(formatter, man);
+ html_mdoc(formatter, meta);
break;
}
}
- if (man->macroset == MACROSET_MAN) {
- man_validate(man);
+ if (meta->macroset == MACROSET_MAN) {
switch (outtype) {
case OUTT_ASCII:
case OUTT_UTF8:
- terminal_man(formatter, man);
+ terminal_man(formatter, meta);
break;
case OUTT_HTML:
- html_man(formatter, man);
+ html_man(formatter, meta);
break;
}
}
diff --git a/mandocdb.c b/mandocdb.c
index 86dbce2d9fe6..222350c987b6 100644
--- a/mandocdb.c
+++ b/mandocdb.c
@@ -1,7 +1,7 @@
-/* $Id: mandocdb.c,v 1.258 2018/02/23 18:25:57 schwarze Exp $ */
+/* $Id: mandocdb.c,v 1.262 2018/12/30 00:49:55 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011-2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011-2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2016 Ed Maste <emaste@freebsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -52,6 +52,7 @@
#include "roff.h"
#include "mdoc.h"
#include "man.h"
+#include "mandoc_parse.h"
#include "manconf.h"
#include "mansearch.h"
#include "dba_array.h"
@@ -185,7 +186,7 @@ static struct ohash names; /* table of all names */
static struct ohash strings; /* table of all strings */
static uint64_t name_mask;
-static const struct mdoc_handler __mdocs[MDOC_MAX - MDOC_Dd] = {
+static const struct mdoc_handler mdoc_handlers[MDOC_MAX - MDOC_Dd] = {
{ NULL, 0, NODE_NOPRT }, /* Dd */
{ NULL, 0, NODE_NOPRT }, /* Dt */
{ NULL, 0, NODE_NOPRT }, /* Os */
@@ -307,7 +308,6 @@ static const struct mdoc_handler __mdocs[MDOC_MAX - MDOC_Dd] = {
{ NULL, 0, 0 }, /* %U */
{ NULL, 0, 0 }, /* Ta */
};
-static const struct mdoc_handler *const mdocs = __mdocs - MDOC_Dd;
int
@@ -347,6 +347,7 @@ mandocdb(int argc, char *argv[])
goto usage; \
} while (/*CONSTCOND*/0)
+ mparse_options = MPARSE_VALIDATE;
path_arg = NULL;
op = OP_DEFAULT;
@@ -422,8 +423,7 @@ mandocdb(int argc, char *argv[])
exitcode = (int)MANDOCLEVEL_OK;
mchars_alloc();
- mp = mparse_alloc(mparse_options, MANDOCERR_MAX, NULL,
- MANDOC_OS_OTHER, NULL);
+ mp = mparse_alloc(mparse_options, MANDOC_OS_OTHER, NULL);
mandoc_ohash_init(&mpages, 6, offsetof(struct mpage, inodev));
mandoc_ohash_init(&mlinks, 6, offsetof(struct mlink, file));
@@ -1116,8 +1116,7 @@ mpages_merge(struct dba *dba, struct mparse *mp)
{
struct mpage *mpage, *mpage_dest;
struct mlink *mlink, *mlink_dest;
- struct roff_man *man;
- char *sodest;
+ struct roff_meta *meta;
char *cp;
int fd;
@@ -1130,8 +1129,7 @@ mpages_merge(struct dba *dba, struct mparse *mp)
mandoc_ohash_init(&names, 4, offsetof(struct str, key));
mandoc_ohash_init(&strings, 6, offsetof(struct str, key));
mparse_reset(mp);
- man = NULL;
- sodest = NULL;
+ meta = NULL;
if ((fd = mparse_open(mp, mlink->file)) == -1) {
say(mlink->file, "&open");
@@ -1146,14 +1144,14 @@ mpages_merge(struct dba *dba, struct mparse *mp)
mparse_readfd(mp, fd, mlink->file);
close(fd);
fd = -1;
- mparse_result(mp, &man, &sodest);
+ meta = mparse_result(mp);
}
- if (sodest != NULL) {
+ if (meta != NULL && meta->sodest != NULL) {
mlink_dest = ohash_find(&mlinks,
- ohash_qlookup(&mlinks, sodest));
+ ohash_qlookup(&mlinks, meta->sodest));
if (mlink_dest == NULL) {
- mandoc_asprintf(&cp, "%s.gz", sodest);
+ mandoc_asprintf(&cp, "%s.gz", meta->sodest);
mlink_dest = ohash_find(&mlinks,
ohash_qlookup(&mlinks, cp));
free(cp);
@@ -1190,39 +1188,36 @@ mpages_merge(struct dba *dba, struct mparse *mp)
mpage->mlinks = NULL;
}
goto nextpage;
- } else if (man != NULL && man->macroset == MACROSET_MDOC) {
- mdoc_validate(man);
+ } else if (meta != NULL && meta->macroset == MACROSET_MDOC) {
mpage->form = FORM_SRC;
- mpage->sec = man->meta.msec;
+ mpage->sec = meta->msec;
mpage->sec = mandoc_strdup(
mpage->sec == NULL ? "" : mpage->sec);
- mpage->arch = man->meta.arch;
+ mpage->arch = meta->arch;
mpage->arch = mandoc_strdup(
mpage->arch == NULL ? "" : mpage->arch);
- mpage->title = mandoc_strdup(man->meta.title);
- } else if (man != NULL && man->macroset == MACROSET_MAN) {
- man_validate(man);
- if (*man->meta.msec != '\0' ||
- *man->meta.title != '\0') {
+ mpage->title = mandoc_strdup(meta->title);
+ } else if (meta != NULL && meta->macroset == MACROSET_MAN) {
+ if (*meta->msec != '\0' || *meta->title != '\0') {
mpage->form = FORM_SRC;
- mpage->sec = mandoc_strdup(man->meta.msec);
+ mpage->sec = mandoc_strdup(meta->msec);
mpage->arch = mandoc_strdup(mlink->arch);
- mpage->title = mandoc_strdup(man->meta.title);
+ mpage->title = mandoc_strdup(meta->title);
} else
- man = NULL;
+ meta = NULL;
}
assert(mpage->desc == NULL);
- if (man == NULL) {
+ if (meta == 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 if (meta->macroset == MACROSET_MDOC)
+ parse_mdoc(mpage, meta, meta->first);
else
- parse_man(mpage, &man->meta, man->first);
+ parse_man(mpage, meta, meta->first);
if (mpage->desc == NULL) {
mpage->desc = mandoc_strdup(mlink->name);
if (warnings)
@@ -1546,25 +1541,28 @@ static void
parse_mdoc(struct mpage *mpage, const struct roff_meta *meta,
const struct roff_node *n)
{
+ const struct mdoc_handler *handler;
for (n = n->child; n != NULL; n = n->next) {
- if (n->tok == TOKEN_NONE ||
- n->tok < ROFF_MAX ||
- n->flags & mdocs[n->tok].taboo)
+ if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX)
continue;
assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
+ handler = mdoc_handlers + (n->tok - MDOC_Dd);
+ if (n->flags & handler->taboo)
+ continue;
+
switch (n->type) {
case ROFFT_ELEM:
case ROFFT_BLOCK:
case ROFFT_HEAD:
case ROFFT_BODY:
case ROFFT_TAIL:
- if (mdocs[n->tok].fp != NULL &&
- (*mdocs[n->tok].fp)(mpage, meta, n) == 0)
+ if (handler->fp != NULL &&
+ (*handler->fp)(mpage, meta, n) == 0)
break;
- if (mdocs[n->tok].mask)
+ if (handler->mask)
putmdockey(mpage, n->child,
- mdocs[n->tok].mask, mdocs[n->tok].taboo);
+ handler->mask, handler->taboo);
break;
default:
continue;
diff --git a/manpath.c b/manpath.c
index 54f7a6b110ad..74f38a95db9e 100644
--- a/manpath.c
+++ b/manpath.c
@@ -1,6 +1,6 @@
-/* $Id: manpath.c,v 1.35 2017/07/01 09:47:30 schwarze Exp $ */
+/* $Id: manpath.c,v 1.37 2018/11/22 11:30:23 schwarze Exp $ */
/*
- * Copyright (c) 2011, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -232,8 +232,8 @@ int
manconf_output(struct manoutput *conf, const char *cp, int fromfile)
{
const char *const toks[] = {
- "includes", "man", "paper", "style",
- "indent", "width", "fragment", "mdoc", "noval"
+ "includes", "man", "paper", "style", "indent", "width",
+ "tag", "fragment", "mdoc", "noval", "toc"
};
const char *errstr;
@@ -257,7 +257,7 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
warnx("-O %s=?: Missing argument value", toks[tok]);
return -1;
}
- if ((tok == 6 || tok == 7) && *cp != '\0') {
+ if (tok > 6 && *cp != '\0') {
warnx("-O %s: Does not take a value: %s", toks[tok], cp);
return -1;
}
@@ -312,14 +312,24 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
warnx("-O width=%s is %s", cp, errstr);
return -1;
case 6:
- conf->fragment = 1;
+ if (conf->tag != NULL) {
+ oldval = mandoc_strdup(conf->tag);
+ break;
+ }
+ conf->tag = mandoc_strdup(cp);
return 0;
case 7:
- conf->mdoc = 1;
+ conf->fragment = 1;
return 0;
case 8:
+ conf->mdoc = 1;
+ return 0;
+ case 9:
conf->noval = 1;
return 0;
+ case 10:
+ conf->toc = 1;
+ return 0;
default:
if (fromfile)
warnx("-O %s: Bad argument", cp);
diff --git a/mansearch.c b/mansearch.c
index 784c17bee714..0c457f95d109 100644
--- a/mansearch.c
+++ b/mansearch.c
@@ -1,7 +1,7 @@
-/* $Id: mansearch.c,v 1.77 2017/08/22 17:50:11 schwarze Exp $ */
+/* $Id: mansearch.c,v 1.80 2018/12/13 11:55:46 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013-2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013-2018 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
@@ -36,7 +36,6 @@
#include <string.h>
#include <unistd.h>
-#include "mandoc.h"
#include "mandoc_aux.h"
#include "mandoc_ohash.h"
#include "manconf.h"
@@ -201,7 +200,6 @@ mansearch(const struct mansearch *search,
mpage->names = buildnames(page);
mpage->output = buildoutput(outkey, page);
mpage->ipath = i;
- mpage->bits = rp->bits;
mpage->sec = *page->sect - '0';
if (mpage->sec < 0 || mpage->sec > 9)
mpage->sec = 10;
@@ -296,10 +294,8 @@ manmerge_term(struct expr *e, struct ohash *htab)
break;
slot = ohash_lookup_memory(htab,
(char *)&res, sizeof(res.page), res.page);
- if ((rp = ohash_find(htab, slot)) != NULL) {
- rp->bits |= res.bits;
+ if ((rp = ohash_find(htab, slot)) != NULL)
continue;
- }
rp = mandoc_malloc(sizeof(*rp));
*rp = res;
ohash_insert(htab, slot, rp);
@@ -412,8 +408,7 @@ manpage_compare(const void *vp1, const void *vp2)
mp1 = vp1;
mp2 = vp2;
- if ((diff = mp2->bits - mp1->bits) ||
- (diff = mp1->sec - mp2->sec))
+ if ((diff = mp1->sec - mp2->sec))
return diff;
/* Fall back to alphabetic ordering of names. */
@@ -774,8 +769,9 @@ exprterm(const struct mansearch *search, int argc, char *argv[], int *argi)
cs = 0;
} else if ((val = strpbrk(argv[*argi], "=~")) == NULL) {
e->bits = TYPE_Nm | TYPE_Nd;
- e->match.type = DBM_SUB;
- e->match.str = argv[*argi];
+ e->match.type = DBM_REGEX;
+ val = argv[*argi];
+ cs = 0;
} else {
if (val == argv[*argi])
e->bits = TYPE_Nm | TYPE_Nd;
diff --git a/mansearch.h b/mansearch.h
index cc4f364f6932..355873f83e09 100644
--- a/mansearch.h
+++ b/mansearch.h
@@ -1,4 +1,4 @@
-/* $Id: mansearch.h,v 1.28 2017/04/17 20:05:08 schwarze Exp $ */
+/* $Id: mansearch.h,v 1.29 2018/11/22 12:01:46 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -93,7 +93,6 @@ struct manpage {
char *names; /* a list of names with sections */
char *output; /* user-defined additional output */
size_t ipath; /* number of the manpath */
- uint64_t bits; /* name type mask */
int sec; /* section number, 10 means invalid */
enum form form;
};
diff --git a/mdoc.7 b/mdoc.7
index 5c07434cd80e..0624ce788cd2 100644
--- a/mdoc.7
+++ b/mdoc.7
@@ -1,4 +1,4 @@
-.\" $Id: mdoc.7,v 1.271 2018/07/28 18:34:15 schwarze Exp $
+.\" $Id: mdoc.7,v 1.276 2019/02/07 15:45:53 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010, 2011, 2013-2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -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: July 28 2018 $
+.Dd $Mdocdate: February 7 2019 $
.Dt MDOC 7
.Os
.Sh NAME
@@ -94,18 +94,18 @@ document consists of a document prologue followed by one or more
sections.
.Pp
The prologue, which consists of the
-.Sx \&Dd ,
-.Sx \&Dt ,
+.Ic \&Dd ,
+.Ic \&Dt ,
and
-.Sx \&Os
+.Ic \&Os
macros in that order, is required for every document.
.Pp
The first section (sections are denoted by
-.Sx \&Sh )
+.Ic \&Sh )
must be the NAME section, consisting of at least one
-.Sx \&Nm
+.Ic \&Nm
followed by
-.Sx \&Nd .
+.Ic \&Nd .
.Pp
Following that, convention dictates specifying at least the
.Em SYNOPSIS
@@ -182,15 +182,15 @@ Multiple
names should be separated by commas.
.Pp
The
-.Sx \&Nm
+.Ic \&Nm
macro(s) must precede the
-.Sx \&Nd
+.Ic \&Nd
macro.
.Pp
See
-.Sx \&Nm
+.Ic \&Nm
and
-.Sx \&Nd .
+.Ic \&Nd .
.It Em LIBRARY
The name of the library containing the documented material, which is
assumed to be a function in a section 2, 3, or 9 manual.
@@ -200,7 +200,7 @@ The syntax for this is as follows:
.Ed
.Pp
See
-.Sx \&Lb .
+.Ic \&Lb .
.It Em SYNOPSIS
Documents the utility invocation syntax, function call syntax, or device
configuration.
@@ -231,11 +231,11 @@ For the second, function calls (sections 2, 3, 9):
.Ed
.Pp
Ordering of
-.Sx \&In ,
-.Sx \&Vt ,
-.Sx \&Fn ,
+.Ic \&In ,
+.Ic \&Vt ,
+.Ic \&Fn ,
and
-.Sx \&Fo
+.Ic \&Fo
macros should follow C header-file conventions.
.Pp
And for the third, configurations (section 4):
@@ -250,40 +250,40 @@ Manuals not in these sections generally don't need a
Some macros are displayed differently in the
.Em SYNOPSIS
section, particularly
-.Sx \&Nm ,
-.Sx \&Cd ,
-.Sx \&Fd ,
-.Sx \&Fn ,
-.Sx \&Fo ,
-.Sx \&In ,
-.Sx \&Vt ,
+.Ic \&Nm ,
+.Ic \&Cd ,
+.Ic \&Fd ,
+.Ic \&Fn ,
+.Ic \&Fo ,
+.Ic \&In ,
+.Ic \&Vt ,
and
-.Sx \&Ft .
+.Ic \&Ft .
All of these macros are output on their own line.
If two such dissimilar macros are pairwise invoked (except for
-.Sx \&Ft
+.Ic \&Ft
before
-.Sx \&Fo
+.Ic \&Fo
or
-.Sx \&Fn ) ,
+.Ic \&Fn ) ,
they are separated by a vertical space, unless in the case of
-.Sx \&Fo ,
-.Sx \&Fn ,
+.Ic \&Fo ,
+.Ic \&Fn ,
and
-.Sx \&Ft ,
+.Ic \&Ft ,
which are always separated by vertical space.
.Pp
When text and macros following an
-.Sx \&Nm
+.Ic \&Nm
macro starting an input line span multiple output lines,
all output lines but the first will be indented to align
with the text immediately following the
-.Sx \&Nm
+.Ic \&Nm
macro, up to the next
-.Sx \&Nm ,
-.Sx \&Sh ,
+.Ic \&Nm ,
+.Ic \&Sh ,
or
-.Sx \&Ss
+.Ic \&Ss
macro or the end of an enclosing block, whichever comes first.
.It Em DESCRIPTION
This begins with an expansion of the brief, one line description in
@@ -315,12 +315,12 @@ Since the
.Em DESCRIPTION
section usually contains most of the text of a manual, longer manuals
often use the
-.Sx \&Ss
+.Ic \&Ss
macro to form subsections.
In very long manuals, the
.Em DESCRIPTION
may be split into multiple sections, each started by an
-.Sx \&Sh
+.Ic \&Sh
macro followed by a non-standard section name, and each having
several subsections, like in the present
.Nm
@@ -337,7 +337,7 @@ This section documents the
return values of functions in sections 2, 3, and 9.
.Pp
See
-.Sx \&Rv .
+.Ic \&Rv .
.It Em ENVIRONMENT
Lists the environment variables used by the utility,
and explains the syntax and semantics of their values.
@@ -346,14 +346,14 @@ The
manual provides examples of typical content and formatting.
.Pp
See
-.Sx \&Ev .
+.Ic \&Ev .
.It Em FILES
Documents files used.
It's helpful to document both the file name and a short description of how
the file is used (created, modified, etc.).
.Pp
See
-.Sx \&Pa .
+.Ic \&Pa .
.It Em EXIT STATUS
This section documents the
command exit status for section 1, 6, and 8 utilities.
@@ -362,7 +362,7 @@ Historically, this information was described in
a practise that is now discouraged.
.Pp
See
-.Sx \&Ex .
+.Ic \&Ex .
.It Em EXAMPLES
Example usages.
This often contains snippets of well-formed, well-tested invocations.
@@ -380,7 +380,7 @@ for manuals in sections 1, 6, and 8; however, this practise is
discouraged.
.Pp
See
-.Sx \&Bl
+.Ic \&Bl
.Fl diag .
.It Em ERRORS
Documents
@@ -388,7 +388,7 @@ Documents
settings in sections 2, 3, 4, and 9.
.Pp
See
-.Sx \&Er .
+.Ic \&Er .
.It Em SEE ALSO
References other manuals with related topics.
This section should exist for most manuals.
@@ -400,9 +400,9 @@ for example authoritative books or journal articles, may also be
provided in this section.
.Pp
See
-.Sx \&Rs
+.Ic \&Rs
and
-.Sx \&Xr .
+.Ic \&Xr .
.It Em STANDARDS
References any standards implemented or used.
If not adhering to any standards, the
@@ -410,7 +410,7 @@ If not adhering to any standards, the
section should be used instead.
.Pp
See
-.Sx \&St .
+.Ic \&St .
.It Em HISTORY
A brief history of the subject, including where it was first implemented,
and when it was ported to or reimplemented for the operating system at hand.
@@ -419,7 +419,7 @@ Credits to the person or persons who wrote the code and/or documentation.
Authors should generally be noted by both name and email address.
.Pp
See
-.Sx \&An .
+.Ic \&An .
.It Em CAVEATS
Common misuses and misunderstandings should be explained
in this section.
@@ -437,208 +437,201 @@ in the alphabetical
.Sx MACRO REFERENCE .
.Ss Document preamble and NAME section macros
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&Dd Ta document date: Cm $\&Mdocdate$ | Ar month day , year
-.It Sx \&Dt Ta document title: Ar TITLE section Op Ar arch
-.It Sx \&Os Ta operating system version: Op Ar system Op Ar version
-.It Sx \&Nm Ta document name (one argument)
-.It Sx \&Nd Ta document description (one line)
+.It Ic \&Dd Ta document date: Cm $\&Mdocdate$ | Ar month day , year
+.It Ic \&Dt Ta document title: Ar TITLE section Op Ar arch
+.It Ic \&Os Ta operating system version: Op Ar system Op Ar version
+.It Ic \&Nm Ta document name (one argument)
+.It Ic \&Nd Ta document description (one line)
.El
.Ss Sections and cross references
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&Sh Ta section header (one line)
-.It Sx \&Ss Ta subsection header (one line)
-.It Sx \&Sx Ta internal cross reference to a section or subsection
-.It Sx \&Xr Ta cross reference to another manual page: Ar name section
-.It Sx \&Pp , \&Lp Ta start a text paragraph (no arguments)
+.It Ic \&Sh Ta section header (one line)
+.It Ic \&Ss Ta subsection header (one line)
+.It Ic \&Sx Ta internal cross reference to a section or subsection
+.It Ic \&Xr Ta cross reference to another manual page: Ar name section
+.It Ic \&Pp Ta start a text paragraph (no arguments)
.El
.Ss Displays and lists
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&Bd , \&Ed Ta display block:
+.It Ic \&Bd , \&Ed Ta display block:
.Fl Ar type
.Op Fl offset Ar width
.Op Fl compact
-.It Sx \&D1 Ta indented display (one line)
-.It Sx \&Dl Ta indented literal display (one line)
-.It Sx \&Ql Ta in-line literal display: Ql text
-.It Sx \&Bl , \&El Ta list block:
+.It Ic \&D1 Ta indented display (one line)
+.It Ic \&Dl Ta indented literal display (one line)
+.It Ic \&Ql Ta in-line literal display: Ql text
+.It Ic \&Bl , \&El Ta list block:
.Fl Ar type
.Op Fl width Ar val
.Op Fl offset Ar val
.Op Fl compact
-.It Sx \&It Ta list item (syntax depends on Fl Ar type )
-.It Sx \&Ta Ta table cell separator in Sx \&Bl Fl column No lists
-.It Sx \&Rs , \&%* , \&Re Ta bibliographic block (references)
+.It Ic \&It Ta list item (syntax depends on Fl Ar type )
+.It Ic \&Ta Ta table cell separator in Ic \&Bl Fl column No lists
+.It Ic \&Rs , \&%* , \&Re Ta bibliographic block (references)
.El
.Ss Spacing control
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&Pf Ta prefix, no following horizontal space (one argument)
-.It Sx \&Ns Ta roman font, no preceding horizontal space (no arguments)
-.It Sx \&Ap Ta apostrophe without surrounding whitespace (no arguments)
-.It Sx \&Sm Ta switch horizontal spacing mode: Op Cm on | off
-.It Sx \&Bk , \&Ek Ta keep block: Fl words
+.It Ic \&Pf Ta prefix, no following horizontal space (one argument)
+.It Ic \&Ns Ta roman font, no preceding horizontal space (no arguments)
+.It Ic \&Ap Ta apostrophe without surrounding whitespace (no arguments)
+.It Ic \&Sm Ta switch horizontal spacing mode: Op Cm on | off
+.It Ic \&Bk , \&Ek Ta keep block: Fl words
.El
.Ss Semantic markup for command line utilities
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&Nm Ta start a SYNOPSIS block with the name of a utility
-.It Sx \&Fl Ta command line options (flags) (>=0 arguments)
-.It Sx \&Cm Ta command modifier (>0 arguments)
-.It Sx \&Ar Ta command arguments (>=0 arguments)
-.It Sx \&Op , \&Oo , \&Oc Ta optional syntax elements (enclosure)
-.It Sx \&Ic Ta internal or interactive command (>0 arguments)
-.It Sx \&Ev Ta environmental variable (>0 arguments)
-.It Sx \&Pa Ta file system path (>=0 arguments)
+.It Ic \&Nm Ta start a SYNOPSIS block with the name of a utility
+.It Ic \&Fl Ta command line options (flags) (>=0 arguments)
+.It Ic \&Cm Ta command modifier (>0 arguments)
+.It Ic \&Ar Ta command arguments (>=0 arguments)
+.It Ic \&Op , \&Oo , \&Oc Ta optional syntax elements (enclosure)
+.It Ic \&Ic Ta internal or interactive command (>0 arguments)
+.It Ic \&Ev Ta environmental variable (>0 arguments)
+.It Ic \&Pa Ta file system path (>=0 arguments)
.El
.Ss Semantic markup for function libraries
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&Lb Ta function library (one argument)
-.It Sx \&In Ta include file (one argument)
-.It Sx \&Fd Ta other preprocessor directive (>0 arguments)
-.It Sx \&Ft Ta function type (>0 arguments)
-.It Sx \&Fo , \&Fc Ta function block: Ar funcname
-.It Sx \&Fn Ta function name:
-.Op Ar functype
-.Ar funcname
-.Oo
-.Op Ar argtype
-.Ar argname
-.Oc
-.It Sx \&Fa Ta function argument (>0 arguments)
-.It Sx \&Vt Ta variable type (>0 arguments)
-.It Sx \&Va Ta variable name (>0 arguments)
-.It Sx \&Dv Ta defined variable or preprocessor constant (>0 arguments)
-.It Sx \&Er Ta error constant (>0 arguments)
-.It Sx \&Ev Ta environmental variable (>0 arguments)
+.It Ic \&Lb Ta function library (one argument)
+.It Ic \&In Ta include file (one argument)
+.It Ic \&Fd Ta other preprocessor directive (>0 arguments)
+.It Ic \&Ft Ta function type (>0 arguments)
+.It Ic \&Fo , \&Fc Ta function block: Ar funcname
+.It Ic \&Fn Ta function name: Ar funcname Op Ar argument ...
+.It Ic \&Fa Ta function argument (>0 arguments)
+.It Ic \&Vt Ta variable type (>0 arguments)
+.It Ic \&Va Ta variable name (>0 arguments)
+.It Ic \&Dv Ta defined variable or preprocessor constant (>0 arguments)
+.It Ic \&Er Ta error constant (>0 arguments)
+.It Ic \&Ev Ta environmental variable (>0 arguments)
.El
.Ss Various semantic markup
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&An Ta author name (>0 arguments)
-.It Sx \&Lk Ta hyperlink: Ar uri Op Ar name
-.It Sx \&Mt Ta Do mailto Dc hyperlink: Ar address
-.It Sx \&Cd Ta kernel configuration declaration (>0 arguments)
-.It Sx \&Ad Ta memory address (>0 arguments)
-.It Sx \&Ms Ta mathematical symbol (>0 arguments)
+.It Ic \&An Ta author name (>0 arguments)
+.It Ic \&Lk Ta hyperlink: Ar uri Op Ar display_name
+.It Ic \&Mt Ta Do mailto Dc hyperlink: Ar localpart Ns @ Ns Ar domain
+.It Ic \&Cd Ta kernel configuration declaration (>0 arguments)
+.It Ic \&Ad Ta memory address (>0 arguments)
+.It Ic \&Ms Ta mathematical symbol (>0 arguments)
.El
.Ss Physical markup
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&Em Ta italic font or underline (emphasis) (>0 arguments)
-.It Sx \&Sy Ta boldface font (symbolic) (>0 arguments)
-.It Sx \&Li Ta typewriter font (literal) (>0 arguments)
-.It Sx \&No Ta return to roman font (normal) (no arguments)
-.It Sx \&Bf , \&Ef Ta font block:
-.Op Fl Ar type | Cm \&Em | \&Li | \&Sy
+.It Ic \&Em Ta italic font or underline (emphasis) (>0 arguments)
+.It Ic \&Sy Ta boldface font (symbolic) (>0 arguments)
+.It Ic \&No Ta return to roman font (normal) (>0 arguments)
+.It Ic \&Bf , \&Ef Ta font block: Fl Ar type | Cm \&Em | \&Li | \&Sy
.El
.Ss Physical enclosures
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&Dq , \&Do , \&Dc Ta enclose in typographic double quotes: Dq text
-.It Sx \&Qq , \&Qo , \&Qc Ta enclose in typewriter double quotes: Qq text
-.It Sx \&Sq , \&So , \&Sc Ta enclose in single quotes: Sq text
-.It Sx \&Pq , \&Po , \&Pc Ta enclose in parentheses: Pq text
-.It Sx \&Bq , \&Bo , \&Bc Ta enclose in square brackets: Bq text
-.It Sx \&Brq , \&Bro , \&Brc Ta enclose in curly braces: Brq text
-.It Sx \&Aq , \&Ao , \&Ac Ta enclose in angle brackets: Aq text
-.It Sx \&Eo , \&Ec Ta generic enclosure
+.It Ic \&Dq , \&Do , \&Dc Ta enclose in typographic double quotes: Dq text
+.It Ic \&Qq , \&Qo , \&Qc Ta enclose in typewriter double quotes: Qq text
+.It Ic \&Sq , \&So , \&Sc Ta enclose in single quotes: Sq text
+.It Ic \&Pq , \&Po , \&Pc Ta enclose in parentheses: Pq text
+.It Ic \&Bq , \&Bo , \&Bc Ta enclose in square brackets: Bq text
+.It Ic \&Brq , \&Bro , \&Brc Ta enclose in curly braces: Brq text
+.It Ic \&Aq , \&Ao , \&Ac Ta enclose in angle brackets: Aq text
+.It Ic \&Eo , \&Ec Ta generic enclosure
.El
.Ss Text production
.Bl -column "Brq, Bro, Brc" description
-.It Sx \&Ex Fl std Ta standard command exit values: Op Ar utility ...
-.It Sx \&Rv Fl std Ta standard function return values: Op Ar function ...
-.It Sx \&St Ta reference to a standards document (one argument)
-.It Sx \&At Ta At
-.It Sx \&Bx Ta Bx
-.It Sx \&Bsx Ta Bsx
-.It Sx \&Nx Ta Nx
-.It Sx \&Fx Ta Fx
-.It Sx \&Ox Ta Ox
-.It Sx \&Dx Ta Dx
+.It Ic \&Ex Fl std Ta standard command exit values: Op Ar utility ...
+.It Ic \&Rv Fl std Ta standard function return values: Op Ar function ...
+.It Ic \&St Ta reference to a standards document (one argument)
+.It Ic \&At Ta At
+.It Ic \&Bx Ta Bx
+.It Ic \&Bsx Ta Bsx
+.It Ic \&Nx Ta Nx
+.It Ic \&Fx Ta Fx
+.It Ic \&Ox Ta Ox
+.It Ic \&Dx Ta Dx
.El
.Sh MACRO REFERENCE
This section is a canonical reference of all macros, arranged
alphabetically.
For the scoping of individual macros, see
.Sx MACRO SYNTAX .
-.Ss \&%A
+.Bl -tag -width 3n
+.It Ic \&%A Ar first_name ... last_name
Author name of an
-.Sx \&Rs
+.Ic \&Rs
block.
Multiple authors should each be accorded their own
-.Sx \%%A
+.Ic \%%A
line.
Author names should be ordered with full or abbreviated forename(s)
first, then full surname.
-.Ss \&%B
+.It Ic \&%B Ar title
Book title of an
-.Sx \&Rs
+.Ic \&Rs
block.
This macro may also be used in a non-bibliographic context when
referring to book titles.
-.Ss \&%C
+.It Ic \&%C Ar location
Publication city or location of an
-.Sx \&Rs
+.Ic \&Rs
block.
-.Ss \&%D
+.It Ic \&%D Oo Ar month day , Oc Ar year
Publication date of an
-.Sx \&Rs
+.Ic \&Rs
block.
-Recommended formats of arguments are
-.Ar month day , year
-or just
+Provide the full English name of the
+.Ar month
+and all four digits of the
.Ar year .
-.Ss \&%I
+.It Ic \&%I Ar name
Publisher or issuer name of an
-.Sx \&Rs
+.Ic \&Rs
block.
-.Ss \&%J
+.It Ic \&%J Ar name
Journal name of an
-.Sx \&Rs
+.Ic \&Rs
block.
-.Ss \&%N
+.It Ic \&%N Ar number
Issue number (usually for journals) of an
-.Sx \&Rs
+.Ic \&Rs
block.
-.Ss \&%O
+.It Ic \&%O Ar line
Optional information of an
-.Sx \&Rs
+.Ic \&Rs
block.
-.Ss \&%P
+.It Ic \&%P Ar number
Book or journal page number of an
-.Sx \&Rs
+.Ic \&Rs
block.
-.Ss \&%Q
+.It Ic \&%Q Ar name
Institutional author (school, government, etc.) of an
-.Sx \&Rs
+.Ic \&Rs
block.
Multiple institutional authors should each be accorded their own
-.Sx \&%Q
+.Ic \&%Q
line.
-.Ss \&%R
+.It Ic \&%R Ar name
Technical report name of an
-.Sx \&Rs
+.Ic \&Rs
block.
-.Ss \&%T
+.It Ic \&%T Ar title
Article title of an
-.Sx \&Rs
+.Ic \&Rs
block.
This macro may also be used in a non-bibliographical context when
referring to article titles.
-.Ss \&%U
+.It Ic \&%U Ar protocol Ns :// Ns Ar path
URI of reference document.
-.Ss \&%V
+.It Ic \&%V Ar number
Volume number of an
-.Sx \&Rs
+.Ic \&Rs
block.
-.Ss \&Ac
+.It Ic \&Ac
Close an
-.Sx \&Ao
+.Ic \&Ao
block.
Does not have any tail arguments.
-.Ss \&Ad
+.It Ic \&Ad Ar address
Memory address.
Do not use this for postal addresses.
.Pp
Examples:
.Dl \&.Ad [0,$]
.Dl \&.Ad 0x00000000
-.Ss \&An
+.It Ic \&An Fl split | nosplit | Ar first_name ... last_name
Author name.
Can be used both for the authors of the program, function, or driver
documented in the manual, or for the authors of the manual itself.
@@ -647,7 +640,7 @@ Requires either the name of an author or one of the following arguments:
.Bl -tag -width "-nosplitX" -offset indent -compact
.It Fl split
Start a new output line before each subsequent invocation of
-.Sx \&An .
+.Ic \&An .
.It Fl nosplit
The opposite of
.Fl split .
@@ -671,25 +664,25 @@ for all other author listings.
Examples:
.Dl \&.An -nosplit
.Dl \&.An Kristaps Dzonsons \&Aq \&Mt kristaps@bsd.lv
-.Ss \&Ao
+.It Ic \&Ao Ar block
Begin a block enclosed by angle brackets.
Does not have any head arguments.
This macro is almost never useful.
See
-.Sx \&Aq
+.Ic \&Aq
for more details.
-.Ss \&Ap
+.It Ic \&Ap
Inserts an apostrophe without any surrounding whitespace.
This is generally used as a grammatical device when referring to the verb
form of a function.
.Pp
Examples:
.Dl \&.Fn execve \&Ap d
-.Ss \&Aq
-Encloses its arguments in angle brackets.
+.It Ic \&Aq Ar line
+Enclose the rest of the input line in angle brackets.
The only important use case is for email addresses.
See
-.Sx \&Mt
+.Ic \&Mt
for an example.
.Pp
Occasionally, it is used for names of characters and keys, for example:
@@ -700,19 +693,19 @@ key to ...
.Ed
.Pp
For URIs, use
-.Sx \&Lk
+.Ic \&Lk
instead, and
-.Sx \&In
+.Ic \&In
for
.Dq #include
directives.
Never wrap
-.Sx \&Ar
+.Ic \&Ar
in
-.Sx \&Aq .
+.Ic \&Aq .
.Pp
Since
-.Sx \&Aq
+.Ic \&Aq
usually renders with non-ASCII characters in non-ASCII output modes,
do not use it where the ASCII characters
.Sq <
@@ -721,15 +714,15 @@ and
are required as syntax elements.
Instead, use these characters directly in such cases, combining them
with the macros
-.Sx \&Pf ,
-.Sx \&Ns ,
+.Ic \&Pf ,
+.Ic \&Ns ,
or
-.Sx \&Eo
+.Ic \&Eo
as needed.
.Pp
See also
-.Sx \&Ao .
-.Ss \&Ar
+.Ic \&Ao .
+.It Ic \&Ar Op Ar placeholder ...
Command arguments.
If an argument is not provided, the string
.Dq file ...\&
@@ -741,13 +734,13 @@ Examples:
.Dl ".Ar arg1 , arg2 ."
.Pp
The arguments to the
-.Sx \&Ar
+.Ic \&Ar
macro are names and placeholders for command arguments;
for fixed strings to be passed verbatim as arguments, use
-.Sx \&Fl
+.Ic \&Fl
or
-.Sx \&Cm .
-.Ss \&At
+.Ic \&Cm .
+.It Ic \&At Op Ar version
Formats an
.At
version.
@@ -772,28 +765,20 @@ Examples:
.Dl \&.At V.1
.Pp
See also
-.Sx \&Bsx ,
-.Sx \&Bx ,
-.Sx \&Dx ,
-.Sx \&Fx ,
-.Sx \&Nx ,
+.Ic \&Bsx ,
+.Ic \&Bx ,
+.Ic \&Dx ,
+.Ic \&Fx ,
+.Ic \&Nx ,
and
-.Sx \&Ox .
-.Ss \&Bc
+.Ic \&Ox .
+.It Ic \&Bc
Close a
-.Sx \&Bo
+.Ic \&Bo
block.
Does not have any tail arguments.
-.Ss \&Bd
+.It Ic \&Bd Fl Ns Ar type Oo Fl offset Ar width Oc Op Fl compact
Begin a display block.
-Its syntax is as follows:
-.Bd -ragged -offset indent
-.Pf \. Sx \&Bd
-.Fl Ns Ar type
-.Op Fl offset Ar width
-.Op Fl compact
-.Ed
-.Pp
Display blocks are used to select a different indentation and
justification than the one used by the surrounding text.
They may contain both macro lines and text lines.
@@ -879,20 +864,11 @@ Examples:
.Ed
.Pp
See also
-.Sx \&D1
+.Ic \&D1
and
-.Sx \&Dl .
-.Ss \&Bf
+.Ic \&Dl .
+.It Ic \&Bf Fl emphasis | literal | symbolic | Cm \&Em | \&Li | \&Sy
Change the font mode for a scoped block of text.
-Its syntax is as follows:
-.Bd -ragged -offset indent
-.Pf \. Sx \&Bf
-.Oo
-.Fl emphasis | literal | symbolic |
-.Cm \&Em | \&Li | \&Sy
-.Oc
-.Ed
-.Pp
The
.Fl emphasis
and
@@ -908,30 +884,27 @@ and
Without an argument, this macro does nothing.
The font mode continues until broken by a new font mode in a nested
scope or
-.Sx \&Ef
+.Ic \&Ef
is encountered.
.Pp
See also
-.Sx \&Li ,
-.Sx \&Ef ,
-.Sx \&Em ,
+.Ic \&Li ,
+.Ic \&Ef ,
+.Ic \&Em ,
and
-.Sx \&Sy .
-.Ss \&Bk
+.Ic \&Sy .
+.It Ic \&Bk Fl words
For each macro, keep its output together on the same output line,
until the end of the macro or the end of the input line is reached,
whichever comes first.
Line breaks in text lines are unaffected.
-The syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Bk Fl words
.Pp
The
.Fl words
argument is required; additional arguments are ignored.
.Pp
The following example will not break within each
-.Sx \&Op
+.Ic \&Op
macro line:
.Bd -literal -offset indent
\&.Bk \-words
@@ -942,20 +915,18 @@ macro line:
.Pp
Be careful in using over-long lines within a keep block!
Doing so will clobber the right margin.
-.Ss \&Bl
-Begin a list.
-Lists consist of items specified using the
-.Sx \&It
-macro, containing a head or a body or both.
-The list syntax is as follows:
-.Bd -ragged -offset indent
-.Pf \. Sx \&Bl
+.It Xo
+.Ic \&Bl
.Fl Ns Ar type
.Op Fl width Ar val
.Op Fl offset Ar val
.Op Fl compact
-.Op HEAD ...
-.Ed
+.Op Ar col ...
+.Xc
+Begin a list.
+Lists consist of items specified using the
+.Ic \&It
+macro, containing a head or a body or both.
.Pp
The list
.Ar type
@@ -965,7 +936,7 @@ The
and
.Fl offset
arguments accept macro names as described for
-.Sx \&Bd
+.Ic \&Bd
.Fl offset ,
scaling widths as described in
.Xr roff 7 ,
@@ -1001,14 +972,14 @@ specifies the width of one column.
If the first line of the body of a
.Fl column
list is not an
-.Sx \&It
+.Ic \&It
macro line,
-.Sx \&It
+.Ic \&It
contexts spanning one input line each are implied until an
-.Sx \&It
+.Ic \&It
macro line is encountered, at which point items start being interpreted as
described in the
-.Sx \&It
+.Ic \&It
documentation.
.It Fl dash
Like
@@ -1071,10 +1042,10 @@ and
lists may not be portable.
.Pp
See also
-.Sx \&El
+.Ic \&El
and
-.Sx \&It .
-.Ss \&Bo
+.Ic \&It .
+.It Ic \&Bo Ar block
Begin a block enclosed by square brackets.
Does not have any head arguments.
.Pp
@@ -1085,8 +1056,8 @@ Examples:
.Ed
.Pp
See also
-.Sx \&Bq .
-.Ss \&Bq
+.Ic \&Bq .
+.It Ic \&Bq Ar line
Encloses its arguments in square brackets.
.Pp
Examples:
@@ -1095,19 +1066,19 @@ Examples:
.Em Remarks :
this macro is sometimes abused to emulate optional arguments for
commands; the correct macros to use for this purpose are
-.Sx \&Op ,
-.Sx \&Oo ,
+.Ic \&Op ,
+.Ic \&Oo ,
and
-.Sx \&Oc .
+.Ic \&Oc .
.Pp
See also
-.Sx \&Bo .
-.Ss \&Brc
+.Ic \&Bo .
+.It Ic \&Brc
Close a
-.Sx \&Bro
+.Ic \&Bro
block.
Does not have any tail arguments.
-.Ss \&Bro
+.It Ic \&Bro Ar block
Begin a block enclosed by curly braces.
Does not have any head arguments.
.Pp
@@ -1118,16 +1089,16 @@ Examples:
.Ed
.Pp
See also
-.Sx \&Brq .
-.Ss \&Brq
+.Ic \&Brq .
+.It Ic \&Brq Ar line
Encloses its arguments in curly braces.
.Pp
Examples:
.Dl \&.Brq 1 , ... , \&Va n
.Pp
See also
-.Sx \&Bro .
-.Ss \&Bsx
+.Ic \&Bro .
+.It Ic \&Bsx Op Ar version
Format the
.Bsx
version provided as an argument, or a default value if
@@ -1138,18 +1109,18 @@ Examples:
.Dl \&.Bsx
.Pp
See also
-.Sx \&At ,
-.Sx \&Bx ,
-.Sx \&Dx ,
-.Sx \&Fx ,
-.Sx \&Nx ,
+.Ic \&At ,
+.Ic \&Bx ,
+.Ic \&Dx ,
+.Ic \&Fx ,
+.Ic \&Nx ,
and
-.Sx \&Ox .
-.Ss \&Bt
+.Ic \&Ox .
+.It Ic \&Bt
Supported only for compatibility, do not use this in new manuals.
Prints
.Dq is currently in beta test.
-.Ss \&Bx
+.It Ic \&Bx Op Ar version Op Ar variant
Format the
.Bx
version provided as an argument, or a default value if no
@@ -1161,14 +1132,14 @@ Examples:
.Dl \&.Bx
.Pp
See also
-.Sx \&At ,
-.Sx \&Bsx ,
-.Sx \&Dx ,
-.Sx \&Fx ,
-.Sx \&Nx ,
+.Ic \&At ,
+.Ic \&Bsx ,
+.Ic \&Dx ,
+.Ic \&Fx ,
+.Ic \&Nx ,
and
-.Sx \&Ox .
-.Ss \&Cd
+.Ic \&Ox .
+.It Ic \&Cd Ar line
Kernel configuration declaration.
This denotes strings accepted by
.Xr config 8 .
@@ -1180,13 +1151,13 @@ Examples:
.Em Remarks :
this macro is commonly abused by using quoted literals to retain
whitespace and align consecutive
-.Sx \&Cd
+.Ic \&Cd
declarations.
This practise is discouraged.
-.Ss \&Cm
+.It Ic \&Cm Ar keyword ...
Command modifiers.
Typically used for fixed strings passed as arguments, unless
-.Sx \&Fl
+.Ic \&Fl
is more appropriate.
Also useful when specifying configuration options or keys.
.Pp
@@ -1196,7 +1167,7 @@ Examples:
.Dl ".Nm dd Cm if= Ns Ar file1 Cm of= Ns Ar file2"
.Dl ".Cm IdentityFile Pa ~/.ssh/id_rsa"
.Dl ".Cm LogLevel Dv DEBUG"
-.Ss \&D1
+.It Ic \&D1 Ar line
One-line indented display.
This is formatted by the default rules and is useful for simple indented
statements.
@@ -1206,29 +1177,26 @@ Examples:
.Dl \&.D1 \&Fl abcdefgh
.Pp
See also
-.Sx \&Bd
+.Ic \&Bd
and
-.Sx \&Dl .
-.Ss \&Db
+.Ic \&Dl .
+.It Ic \&Db
This macro is obsolete.
No replacement is needed.
It is ignored by
.Xr mandoc 1
and groff including its arguments.
It was formerly used to toggle a debugging mode.
-.Ss \&Dc
+.It Ic \&Dc
Close a
-.Sx \&Do
+.Ic \&Do
block.
Does not have any tail arguments.
-.Ss \&Dd
+.It Ic \&Dd Cm $\&Mdocdate$ | Ar month day , year
Document date for display in the page footer.
This is the mandatory first macro of any
.Nm
manual.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Dd Ar month day , year
.Pp
The
.Ar month
@@ -1268,10 +1236,10 @@ Examples:
.Dl \&.Dd July 2, 2018
.Pp
See also
-.Sx \&Dt
+.Ic \&Dt
and
-.Sx \&Os .
-.Ss \&Dl
+.Ic \&Os .
+.It Ic \&Dl Ar line
One-line indented display.
This is formatted as literal text and is useful for commands and
invocations.
@@ -1281,12 +1249,11 @@ Examples:
.Dl \&.Dl % mandoc mdoc.7 \e(ba less
.Pp
See also
-.Sx \&Ql ,
-.Sx \&Bd
-.Fl literal ,
+.Ic \&Ql ,
+.Ic \&Bd Fl literal ,
and
-.Sx \&D1 .
-.Ss \&Do
+.Ic \&D1 .
+.It Ic \&Do Ar block
Begin a block enclosed by double quotes.
Does not have any head arguments.
.Pp
@@ -1299,8 +1266,8 @@ April is the cruellest month
.Ed
.Pp
See also
-.Sx \&Dq .
-.Ss \&Dq
+.Ic \&Dq .
+.It Ic \&Dq Ar line
Encloses its arguments in
.Dq typographic
double-quotes.
@@ -1312,22 +1279,15 @@ Examples:
.Ed
.Pp
See also
-.Sx \&Qq ,
-.Sx \&Sq ,
+.Ic \&Qq ,
+.Ic \&Sq ,
and
-.Sx \&Do .
-.Ss \&Dt
+.Ic \&Do .
+.It Ic \&Dt Ar TITLE section Op Ar arch
Document title for display in the page header.
This is the mandatory second macro of any
.Nm
file.
-Its syntax is as follows:
-.Bd -ragged -offset indent
-.Pf \. Sx \&Dt
-.Ar TITLE
-.Ar section
-.Op Ar arch
-.Ed
.Pp
Its arguments are as follows:
.Bl -tag -width section -offset 2n
@@ -1379,10 +1339,10 @@ Examples:
.Dl \&.Dt FOO 9 i386
.Pp
See also
-.Sx \&Dd
+.Ic \&Dd
and
-.Sx \&Os .
-.Ss \&Dv
+.Ic \&Os .
+.It Ic \&Dv Ar identifier ...
Defined variables such as preprocessor constants, constant symbols,
enumeration values, and so on.
.Pp
@@ -1392,16 +1352,16 @@ Examples:
.Dl \&.Dv STDOUT_FILENO
.Pp
See also
-.Sx \&Er
+.Ic \&Er
and
-.Sx \&Ev
+.Ic \&Ev
for special-purpose constants,
-.Sx \&Va
+.Ic \&Va
for variable symbols, and
-.Sx \&Fd
+.Ic \&Fd
for listing preprocessor variable definitions in the
.Em SYNOPSIS .
-.Ss \&Dx
+.It Ic \&Dx Op Ar version
Format the
.Dx
version provided as an argument, or a default
@@ -1412,55 +1372,49 @@ Examples:
.Dl \&.Dx
.Pp
See also
-.Sx \&At ,
-.Sx \&Bsx ,
-.Sx \&Bx ,
-.Sx \&Fx ,
-.Sx \&Nx ,
+.Ic \&At ,
+.Ic \&Bsx ,
+.Ic \&Bx ,
+.Ic \&Fx ,
+.Ic \&Nx ,
and
-.Sx \&Ox .
-.Ss \&Ec
+.Ic \&Ox .
+.It Ic \&Ec Op Ar closing_delimiter
Close a scope started by
-.Sx \&Eo .
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Ec Op Ar TERM
+.Ic \&Eo .
.Pp
The
-.Ar TERM
+.Ar closing_delimiter
argument is used as the enclosure tail, for example, specifying \e(rq
will emulate
-.Sx \&Dc .
-.Ss \&Ed
+.Ic \&Dc .
+.It Ic \&Ed
End a display context started by
-.Sx \&Bd .
-.Ss \&Ef
+.Ic \&Bd .
+.It Ic \&Ef
End a font mode context started by
-.Sx \&Bf .
-.Ss \&Ek
+.Ic \&Bf .
+.It Ic \&Ek
End a keep context started by
-.Sx \&Bk .
-.Ss \&El
+.Ic \&Bk .
+.It Ic \&El
End a list context started by
-.Sx \&Bl .
-.Pp
+.Ic \&Bl .
See also
-.Sx \&Bl
-and
-.Sx \&It .
-.Ss \&Em
+.Ic \&It .
+.It Ic \&Em Ar word ...
Request an italic font.
If the output device does not provide that, underline.
.Pp
This is most often used for stress emphasis (not to be confused with
importance, see
-.Sx \&Sy ) .
+.Ic \&Sy ) .
In the rare cases where none of the semantic markup macros fit,
it can also be used for technical terms and placeholders, except
that for syntax elements,
-.Sx \&Sy
+.Ic \&Sy
and
-.Sx \&Ar
+.Ic \&Ar
are preferred, respectively.
.Pp
Examples:
@@ -1474,32 +1428,27 @@ to save the pattern space for subsequent retrieval.
.Ed
.Pp
See also
-.Sx \&Bf ,
-.Sx \&Li ,
-.Sx \&No ,
+.Ic \&No ,
+.Ic \&Ql ,
and
-.Sx \&Sy .
-.Ss \&En
+.Ic \&Sy .
+.It Ic \&En Ar word ...
This macro is obsolete.
Use
-.Sx \&Eo
+.Ic \&Eo
or any of the other enclosure macros.
.Pp
It encloses its argument in the delimiters specified by the last
-.Sx \&Es
+.Ic \&Es
macro.
-.Ss \&Eo
+.It Ic \&Eo Op Ar opening_delimiter
An arbitrary enclosure.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Eo Op Ar TERM
-.Pp
The
-.Ar TERM
+.Ar opening_delimiter
argument is used as the enclosure head, for example, specifying \e(lq
will emulate
-.Sx \&Do .
-.Ss \&Er
+.Ic \&Do .
+.It Ic \&Er Ar identifier ...
Error constants for definitions of the
.Va errno
libc global variable.
@@ -1510,18 +1459,18 @@ Examples:
.Dl \&.Er ENOENT
.Pp
See also
-.Sx \&Dv
+.Ic \&Dv
for general constants.
-.Ss \&Es
+.It Ic \&Es Ar opening_delimiter closing_delimiter
This macro is obsolete.
Use
-.Sx \&Eo
+.Ic \&Eo
or any of the other enclosure macros.
.Pp
It takes two arguments, defining the delimiters to be used by subsequent
-.Sx \&En
+.Ic \&En
macros.
-.Ss \&Ev
+.It Ic \&Ev Ar identifier ...
Environmental variables such as those specified in
.Xr environ 7 .
.Pp
@@ -1530,38 +1479,26 @@ Examples:
.Dl \&.Ev PATH
.Pp
See also
-.Sx \&Dv
+.Ic \&Dv
for general constants.
-.Ss \&Ex
+.It Ic \&Ex Fl std Op Ar utility ...
Insert a standard sentence regarding command exit values of 0 on success
and >0 on failure.
This is most often used in section 1, 6, and 8 manual pages.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Ex Fl std Op Ar utility ...
.Pp
If
.Ar utility
is not specified, the document's name set by
-.Sx \&Nm
+.Ic \&Nm
is used.
Multiple
.Ar utility
arguments are treated as separate utilities.
.Pp
See also
-.Sx \&Rv .
-.Ss \&Fa
+.Ic \&Rv .
+.It Ic \&Fa Ar argument ...
Function argument or parameter.
-Its syntax is as follows:
-.Bd -ragged -offset indent
-.Pf \. Sx \&Fa
-.Qo
-.Op Ar argtype
-.Op Ar argname
-.Qc Ar \&...
-.Ed
-.Pp
Each argument may be a name and a type (recommended for the
.Em SYNOPSIS
section), a name alone (for function invocations),
@@ -1569,22 +1506,22 @@ or a type alone (for function prototypes).
If both a type and a name are given or if the type consists of multiple
words, all words belonging to the same function argument have to be
given in a single argument to the
-.Sx \&Fa
+.Ic \&Fa
macro.
.Pp
This macro is also used to specify the field name of a structure.
.Pp
Most often, the
-.Sx \&Fa
+.Ic \&Fa
macro is used in the
.Em SYNOPSIS
within
-.Sx \&Fo
+.Ic \&Fo
blocks when documenting multi-line function prototypes.
If invoked with multiple arguments, the arguments are separated by a
comma.
Furthermore, if the following macro is another
-.Sx \&Fa ,
+.Ic \&Fa ,
the last argument will also have a trailing comma.
.Pp
Examples:
@@ -1593,23 +1530,16 @@ Examples:
.Dl \&.Fa \(dqchar *\(dq size_t
.Pp
See also
-.Sx \&Fo .
-.Ss \&Fc
+.Ic \&Fo .
+.It Ic \&Fc
End a function context started by
-.Sx \&Fo .
-.Ss \&Fd
+.Ic \&Fo .
+.It Ic \&Fd Pf # Ar directive Op Ar argument ...
Preprocessor directive, in particular for listing it in the
.Em SYNOPSIS .
Historically, it was also used to document include files.
The latter usage has been deprecated in favour of
-.Sx \&In .
-.Pp
-Its syntax is as follows:
-.Bd -ragged -offset indent
-.Pf \. Sx \&Fd
-.Li # Ns Ar directive
-.Op Ar argument ...
-.Ed
+.Ic \&In .
.Pp
Examples:
.Dl \&.Fd #define sa_handler __sigaction_u.__sa_handler
@@ -1621,10 +1551,10 @@ Examples:
.Pp
See also
.Sx MANUAL STRUCTURE ,
-.Sx \&In ,
+.Ic \&In ,
and
-.Sx \&Dv .
-.Ss \&Fl
+.Ic \&Dv .
+.It Ic \&Fl Op Ar word ...
Command-line flag or option.
Used when listing arguments to command-line utilities.
Prints a fixed-width hyphen
@@ -1642,16 +1572,9 @@ Examples:
.Dl ".Fl o Fl"
.Pp
See also
-.Sx \&Cm .
-.Ss \&Fn
+.Ic \&Cm .
+.It Ic \&Fn Ar funcname Op Ar argument ...
A function name.
-Its syntax is as follows:
-.Bd -ragged -offset indent
-.Pf . Sx \&Fn
-.Op Ar functype
-.Ar funcname
-.Op Oo Ar argtype Oc Ar argname
-.Ed
.Pp
Function arguments are surrounded in parenthesis and
are delimited by commas.
@@ -1665,62 +1588,55 @@ Examples:
.Dl \&.Fn \(dqint funcname\(dq \(dqint arg0\(dq \(dqint arg1\(dq
.Dl \&.Fn funcname \(dqint arg0\(dq
.Dl \&.Fn funcname arg0
-.Pp
-.Bd -literal -offset indent -compact
+.Bd -literal -offset indent
\&.Ft functype
\&.Fn funcname
.Ed
.Pp
When referring to a function documented in another manual page, use
-.Sx \&Xr
+.Ic \&Xr
instead.
See also
.Sx MANUAL STRUCTURE ,
-.Sx \&Fo ,
+.Ic \&Fo ,
and
-.Sx \&Ft .
-.Ss \&Fo
+.Ic \&Ft .
+.It Ic \&Fo Ar funcname
Begin a function block.
This is a multi-line version of
-.Sx \&Fn .
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Fo Ar funcname
+.Ic \&Fn .
.Pp
Invocations usually occur in the following context:
.Bd -ragged -offset indent
-.Pf \. Sx \&Ft Ar functype
+.Pf \. Ic \&Ft Ar functype
.br
-.Pf \. Sx \&Fo Ar funcname
+.Pf \. Ic \&Fo Ar funcname
.br
-.Pf \. Sx \&Fa Qq Ar argtype Ar argname
+.Pf \. Ic \&Fa Qq Ar argtype Ar argname
.br
\&.\.\.
.br
-.Pf \. Sx \&Fc
+.Pf \. Ic \&Fc
.Ed
.Pp
A
-.Sx \&Fo
+.Ic \&Fo
scope is closed by
-.Sx \&Fc .
+.Ic \&Fc .
.Pp
See also
.Sx MANUAL STRUCTURE ,
-.Sx \&Fa ,
-.Sx \&Fc ,
+.Ic \&Fa ,
+.Ic \&Fc ,
and
-.Sx \&Ft .
-.Ss \&Fr
+.Ic \&Ft .
+.It Ic \&Fr Ar number
This macro is obsolete.
No replacement markup is needed.
.Pp
It was used to show numerical function return values in an italic font.
-.Ss \&Ft
+.It Ic \&Ft Ar functype
A function type.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Ft Ar functype
.Pp
In the
.Em SYNOPSIS
@@ -1735,10 +1651,10 @@ Examples:
.Pp
See also
.Sx MANUAL STRUCTURE ,
-.Sx \&Fn ,
+.Ic \&Fn ,
and
-.Sx \&Fo .
-.Ss \&Fx
+.Ic \&Fo .
+.It Ic \&Fx Op Ar version
Format the
.Fx
version provided as an argument, or a default value
@@ -1749,25 +1665,21 @@ Examples:
.Dl \&.Fx
.Pp
See also
-.Sx \&At ,
-.Sx \&Bsx ,
-.Sx \&Bx ,
-.Sx \&Dx ,
-.Sx \&Nx ,
+.Ic \&At ,
+.Ic \&Bsx ,
+.Ic \&Bx ,
+.Ic \&Dx ,
+.Ic \&Nx ,
and
-.Sx \&Ox .
-.Ss \&Hf
+.Ic \&Ox .
+.It Ic \&Hf Ar filename
This macro is not implemented in
.Xr mandoc 1 .
-.Pp
It was used to include the contents of a (header) file literally.
-The syntax was:
-.Pp
-.Dl Pf . Sx \&Hf Ar filename
-.Ss \&Ic
+.It Ic \&Ic Ar keyword ...
Designate an internal or interactive command.
This is similar to
-.Sx \&Cm
+.Ic \&Cm
but used for instructions rather than values.
.Pp
Examples:
@@ -1776,13 +1688,14 @@ Examples:
.Dl \&.Ic alias
.Pp
Note that using
-.Sx \&Bd Fl literal
+.Ic \&Ql ,
+.Ic \&Dl ,
or
-.Sx \&D1
-is preferred for displaying code; the
-.Sx \&Ic
-macro is used when referring to specific instructions.
-.Ss \&In
+.Ic \&Bd Fl literal
+is preferred for displaying code samples; the
+.Ic \&Ic
+macro is used when referring to an individual command name.
+.It Ic \&In Ar filename
The name of an include file.
This macro is most often used in section 2, 3, and 9 manual pages.
.Pp
@@ -1801,7 +1714,7 @@ Examples:
.Pp
See also
.Sx MANUAL STRUCTURE .
-.Ss \&It
+.It Ic \&It Op Ar head
A list item.
The syntax of this macro depends on the list type.
.Pp
@@ -1814,7 +1727,7 @@ and
.Fl diag
have the following syntax:
.Pp
-.D1 Pf \. Sx \&It Ar args
+.D1 Pf \. Ic \&It Ar args
.Pp
Lists of type
.Fl bullet ,
@@ -1825,20 +1738,20 @@ and
.Fl item
have the following syntax:
.Pp
-.D1 Pf \. Sx \&It
+.D1 Pf \. Ic \&It
.Pp
with subsequent lines interpreted within the scope of the
-.Sx \&It
+.Ic \&It
until either a closing
-.Sx \&El
+.Ic \&El
or another
-.Sx \&It .
+.Ic \&It .
.Pp
The
.Fl tag
list has the following syntax:
.Pp
-.D1 Pf \. Sx \&It Op Cm args
+.D1 Pf \. Ic \&It Op Cm args
.Pp
Subsequent lines are interpreted as with
.Fl bullet
@@ -1851,13 +1764,13 @@ The
list is the most complicated.
Its syntax is as follows:
.Pp
-.D1 Pf \. Sx \&It Ar cell Op Sx \&Ta Ar cell ...
-.D1 Pf \. Sx \&It Ar cell Op <TAB> Ar cell ...
+.D1 Pf \. Ic \&It Ar cell Op Ic \&Ta Ar cell ...
+.D1 Pf \. Ic \&It Ar cell Op <TAB> Ar cell ...
.Pp
The arguments consist of one or more lines of text and macros
representing a complete table line.
Cells within the line are delimited by the special
-.Sx \&Ta
+.Ic \&Ta
block macro or by literal tab characters.
.Pp
Using literal tabs is strongly discouraged because they are very
@@ -1871,16 +1784,16 @@ that word is never interpreted as a macro call, but always output
literally.
.Pp
The tab cell delimiter may only be used within the
-.Sx \&It
+.Ic \&It
line itself; on following lines, only the
-.Sx \&Ta
+.Ic \&Ta
macro can be used to delimit cells, and portability requires that
-.Sx \&Ta
+.Ic \&Ta
is called by other macros: some parsers do not recognize it when
it appears as the first macro on a line.
.Pp
Note that quoted strings may span tab-delimited cells on an
-.Sx \&It
+.Ic \&It
line.
For example,
.Pp
@@ -1890,19 +1803,16 @@ will preserve the whitespace before both commas,
but not the whitespace before the semicolon.
.Pp
See also
-.Sx \&Bl .
-.Ss \&Lb
+.Ic \&Bl .
+.It Ic \&Lb Cm lib Ns Ar name
Specify a library.
-The syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Lb Ar library
.Pp
The
-.Ar library
+.Ar name
parameter may be a system library, such as
-.Cm libz
+.Cm z
or
-.Cm libpam ,
+.Cm pam ,
in which case a small library description is printed next to the linker
invocation; or a custom library, in which case the library name is
printed in quotes.
@@ -1914,71 +1824,56 @@ section as described in
Examples:
.Dl \&.Lb libz
.Dl \&.Lb libmandoc
-.Ss \&Li
-Denotes text that should be in a
-.Li literal
-font mode.
-Note that this is a presentation term and should not be used for
-stylistically decorating technical terms.
-.Pp
-On terminal output devices, this is often indistinguishable from
-normal text.
-.Pp
-See also
-.Sx \&Bf ,
-.Sx \&Em ,
-.Sx \&No ,
-and
-.Sx \&Sy .
-.Ss \&Lk
+.It Ic \&Li Ar word ...
+Request a typewriter (literal) font.
+Deprecated because on terminal output devices, this is usually
+indistinguishable from normal text.
+For literal displays, use
+.Ic \&Ql Pq in-line ,
+.Ic \&Dl Pq single line ,
+or
+.Ic \&Bd Fl literal Pq multi-line
+instead.
+.It Ic \&Lk Ar uri Op Ar display_name
Format a hyperlink.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Lk Ar uri Op Ar name
.Pp
Examples:
.Dl \&.Lk http://bsd.lv \(dqThe BSD.lv Project\(dq
.Dl \&.Lk http://bsd.lv
.Pp
See also
-.Sx \&Mt .
-.Ss \&Lp
-Synonym for
-.Sx \&Pp .
-.Ss \&Ms
+.Ic \&Mt .
+.It Ic \&Lp
+Deprecated synonym for
+.Ic \&Pp .
+.It Ic \&Ms Ar name
Display a mathematical symbol.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Ms Ar symbol
.Pp
Examples:
.Dl \&.Ms sigma
.Dl \&.Ms aleph
-.Ss \&Mt
+.It Ic \&Mt Ar localpart Ns @ Ns Ar domain
Format a
.Dq mailto:
hyperlink.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Mt Ar address
.Pp
Examples:
.Dl \&.Mt discuss@manpages.bsd.lv
.Dl \&.An Kristaps Dzonsons \&Aq \&Mt kristaps@bsd.lv
-.Ss \&Nd
+.It Ic \&Nd Ar line
A one line description of the manual's content.
This is the mandatory last macro of the
.Em NAME
section and not appropriate for other sections.
.Pp
Examples:
-.Dl Pf . Sx \&Nd mdoc language reference
-.Dl Pf . Sx \&Nd format and display UNIX manuals
+.Dl Pf . Ic \&Nd mdoc language reference
+.Dl Pf . Ic \&Nd format and display UNIX manuals
.Pp
The
-.Sx \&Nd
+.Ic \&Nd
macro technically accepts child macros and terminates with a subsequent
-.Sx \&Sh
+.Ic \&Sh
invocation.
Do not assume this behaviour: some
.Xr whatis 1
@@ -1986,13 +1881,13 @@ database generators are not smart enough to parse more than the line
arguments and will display macros verbatim.
.Pp
See also
-.Sx \&Nm .
-.Ss \&Nm
+.Ic \&Nm .
+.It Ic \&Nm Op Ar name
The name of the manual page, or \(em in particular in section 1, 6,
and 8 pages \(em of an additional command or feature documented in
the manual page.
When first invoked, the
-.Sx \&Nm
+.Ic \&Nm
macro expects a single argument, the name of the manual page.
Usually, the first invocation happens in the
.Em NAME
@@ -2000,7 +1895,7 @@ section of the page.
The specified name will be remembered and used whenever the macro is
called again without arguments later in the page.
The
-.Sx \&Nm
+.Ic \&Nm
macro uses
.Sx Block full-implicit
semantics when invoked as the first macro on an input line in the
@@ -2020,41 +1915,40 @@ Examples:
In the
.Em SYNOPSIS
of section 2, 3 and 9 manual pages, use the
-.Sx \&Fn
+.Ic \&Fn
macro rather than
-.Sx \&Nm
+.Ic \&Nm
to mark up the name of the manual page.
-.Ss \&No
+.It Ic \&No Ar word ...
Normal text.
Closes the scope of any preceding in-line macro.
When used after physical formatting macros like
-.Sx \&Em
+.Ic \&Em
or
-.Sx \&Sy ,
+.Ic \&Sy ,
switches back to the standard font face and weight.
Can also be used to embed plain text strings in macro lines
using semantic annotation macros.
.Pp
Examples:
.Dl ".Em italic , Sy bold , No and roman"
-.Pp
-.Bd -literal -offset indent -compact
+.Bd -literal -offset indent
\&.Sm off
\&.Cm :C No / Ar pattern No / Ar replacement No /
\&.Sm on
.Ed
.Pp
See also
-.Sx \&Em ,
-.Sx \&Li ,
+.Ic \&Em ,
+.Ic \&Ql ,
and
-.Sx \&Sy .
-.Ss \&Ns
+.Ic \&Sy .
+.It Ic \&Ns
Suppress a space between the output of the preceding macro
and the following text or macro.
Following invocation, input is interpreted as normal text
just like after an
-.Sx \&No
+.Ic \&No
macro.
.Pp
This has no effect when invoked at the start of a macro line.
@@ -2065,10 +1959,10 @@ Examples:
.Dl ".Fl o Ns Ar output"
.Pp
See also
-.Sx \&No
+.Ic \&No
and
-.Sx \&Sm .
-.Ss \&Nx
+.Ic \&Sm .
+.It Ic \&Nx Op Ar version
Format the
.Nx
version provided as an argument, or a default value if
@@ -2079,20 +1973,20 @@ Examples:
.Dl \&.Nx
.Pp
See also
-.Sx \&At ,
-.Sx \&Bsx ,
-.Sx \&Bx ,
-.Sx \&Dx ,
-.Sx \&Fx ,
+.Ic \&At ,
+.Ic \&Bsx ,
+.Ic \&Bx ,
+.Ic \&Dx ,
+.Ic \&Fx ,
and
-.Sx \&Ox .
-.Ss \&Oc
+.Ic \&Ox .
+.It Ic \&Oc
Close multi-line
-.Sx \&Oo
+.Ic \&Oo
context.
-.Ss \&Oo
+.It Ic \&Oo Ar block
Multi-line version of
-.Sx \&Op .
+.Ic \&Op .
.Pp
Examples:
.Bd -literal -offset indent -compact
@@ -2100,7 +1994,7 @@ Examples:
\&.Op Fl flag Ns Ar value
\&.Oc
.Ed
-.Ss \&Op
+.It Ic \&Op Ar line
Optional part of a command line.
Prints the argument(s) in brackets.
This is most often used in the
@@ -2112,16 +2006,13 @@ Examples:
.Dl \&.Op \&Ar a | b
.Pp
See also
-.Sx \&Oo .
-.Ss \&Os
+.Ic \&Oo .
+.It Ic \&Os Op Ar system Op Ar version
Operating system version for display in the page footer.
This is the mandatory third macro of
any
.Nm
file.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Os Op Ar system Op Ar version
.Pp
The optional
.Ar system
@@ -2143,13 +2034,13 @@ Examples:
.Dl \&.Os BSD 4.3
.Pp
See also
-.Sx \&Dd
+.Ic \&Dd
and
-.Sx \&Dt .
-.Ss \&Ot
+.Ic \&Dt .
+.It Ic \&Ot Ar functype
This macro is obsolete.
Use
-.Sx \&Ft
+.Ic \&Ft
instead; with
.Xr mandoc 1 ,
both have the same effect.
@@ -2158,7 +2049,7 @@ Historical
.Nm
packages described it as
.Dq "old function type (FORTRAN)" .
-.Ss \&Ox
+.It Ic \&Ox Op Ar version
Format the
.Ox
version provided as an argument, or a default value
@@ -2169,14 +2060,14 @@ Examples:
.Dl \&.Ox
.Pp
See also
-.Sx \&At ,
-.Sx \&Bsx ,
-.Sx \&Bx ,
-.Sx \&Dx ,
-.Sx \&Fx ,
+.Ic \&At ,
+.Ic \&Bsx ,
+.Ic \&Bx ,
+.Ic \&Dx ,
+.Ic \&Fx ,
and
-.Sx \&Nx .
-.Ss \&Pa
+.Ic \&Nx .
+.It Ic \&Pa Ar name ...
An absolute or relative file system path, or a file or directory name.
If an argument is not provided, the character
.Sq \(ti
@@ -2187,19 +2078,15 @@ Examples:
.Dl \&.Pa /usr/share/man/man7/mdoc.7
.Pp
See also
-.Sx \&Lk .
-.Ss \&Pc
+.Ic \&Lk .
+.It Ic \&Pc
Close parenthesised context opened by
-.Sx \&Po .
-.Ss \&Pf
+.Ic \&Po .
+.It Ic \&Pf Ar prefix macro Op Ar argument ...
Removes the space between its argument and the following macro.
-Its syntax is as follows:
-.Pp
-.D1 .Pf Ar prefix macro arguments ...
-.Pp
-This is equivalent to:
+It is equivalent to:
.Pp
-.D1 .No \e& Ns Ar prefix No \&Ns Ar macro arguments ...
+.D1 Ic \&No Pf \e& Ar prefix Ic \&Ns Ar macro Op Ar argument ...
.Pp
The
.Ar prefix
@@ -2212,93 +2099,87 @@ Examples:
.Dl ".Pf 0x Ar hex_digits"
.Pp
See also
-.Sx \&Ns
+.Ic \&Ns
and
-.Sx \&Sm .
-.Ss \&Po
+.Ic \&Sm .
+.It Ic \&Po Ar block
Multi-line version of
-.Sx \&Pq .
-.Ss \&Pp
+.Ic \&Pq .
+.It Ic \&Pp
Break a paragraph.
This will assert vertical space between prior and subsequent macros
and/or text.
.Pp
Paragraph breaks are not needed before or after
-.Sx \&Sh
+.Ic \&Sh
or
-.Sx \&Ss
+.Ic \&Ss
macros or before displays
-.Pq Sx \&Bd
+.Pq Ic \&Bd Ar line
or lists
-.Pq Sx \&Bl
+.Pq Ic \&Bl
unless the
.Fl compact
flag is given.
-.Ss \&Pq
+.It Ic \&Pq Ar line
Parenthesised enclosure.
.Pp
See also
-.Sx \&Po .
-.Ss \&Qc
+.Ic \&Po .
+.It Ic \&Qc
Close quoted context opened by
-.Sx \&Qo .
-.Ss \&Ql
+.Ic \&Qo .
+.It Ic \&Ql Ar line
In-line literal display.
-This can for example be used for complete command invocations and
-for multi-word code fragments when more specific markup is not
-appropriate and an indented display is not desired.
-While
-.Xr mandoc 1
-always encloses the arguments in single quotes, other formatters
-usually omit the quotes on non-terminal output devices when the
-arguments have three or more characters.
+This can be used for complete command invocations and for multi-word
+code examples when an indented display is not desired.
.Pp
See also
-.Sx \&Dl
+.Ic \&Dl
and
-.Sx \&Bd
+.Ic \&Bd
.Fl literal .
-.Ss \&Qo
+.It Ic \&Qo Ar block
Multi-line version of
-.Sx \&Qq .
-.Ss \&Qq
+.Ic \&Qq .
+.It Ic \&Qq Ar line
Encloses its arguments in
.Qq typewriter
double-quotes.
Consider using
-.Sx \&Dq .
+.Ic \&Dq .
.Pp
See also
-.Sx \&Dq ,
-.Sx \&Sq ,
+.Ic \&Dq ,
+.Ic \&Sq ,
and
-.Sx \&Qo .
-.Ss \&Re
+.Ic \&Qo .
+.It Ic \&Re
Close an
-.Sx \&Rs
+.Ic \&Rs
block.
Does not have any tail arguments.
-.Ss \&Rs
+.It Ic \&Rs
Begin a bibliographic
.Pq Dq reference
block.
Does not have any head arguments.
The block macro may only contain
-.Sx \&%A ,
-.Sx \&%B ,
-.Sx \&%C ,
-.Sx \&%D ,
-.Sx \&%I ,
-.Sx \&%J ,
-.Sx \&%N ,
-.Sx \&%O ,
-.Sx \&%P ,
-.Sx \&%Q ,
-.Sx \&%R ,
-.Sx \&%T ,
-.Sx \&%U ,
+.Ic \&%A ,
+.Ic \&%B ,
+.Ic \&%C ,
+.Ic \&%D ,
+.Ic \&%I ,
+.Ic \&%J ,
+.Ic \&%N ,
+.Ic \&%O ,
+.Ic \&%P ,
+.Ic \&%Q ,
+.Ic \&%R ,
+.Ic \&%T ,
+.Ic \&%U ,
and
-.Sx \&%V
+.Ic \&%V
child macros (at least one must be specified).
.Pp
Examples:
@@ -2314,34 +2195,31 @@ Examples:
.Ed
.Pp
If an
-.Sx \&Rs
+.Ic \&Rs
block is used within a SEE ALSO section, a vertical space is asserted
before the rendered output, else the block continues on the current
line.
-.Ss \&Rv
+.It Ic \&Rv Fl std Op Ar function ...
Insert a standard sentence regarding a function call's return value of 0
on success and \-1 on error, with the
.Va errno
libc global variable set on error.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Rv Fl std Op Ar function ...
.Pp
If
.Ar function
is not specified, the document's name set by
-.Sx \&Nm
+.Ic \&Nm
is used.
Multiple
.Ar function
arguments are treated as separate functions.
.Pp
See also
-.Sx \&Ex .
-.Ss \&Sc
+.Ic \&Ex .
+.It Ic \&Sc
Close single-quoted context opened by
-.Sx \&So .
-.Ss \&Sh
+.Ic \&So .
+.It Ic \&Sh Ar TITLE LINE
Begin a new section.
For a list of conventional manual sections, see
.Sx MANUAL STRUCTURE .
@@ -2349,21 +2227,18 @@ These sections should be used unless it's absolutely necessary that
custom sections be used.
.Pp
Section names should be unique so that they may be keyed by
-.Sx \&Sx .
+.Ic \&Sx .
Although this macro is parsed, it should not consist of child node or it
may not be linked with
-.Sx \&Sx .
+.Ic \&Sx .
.Pp
See also
-.Sx \&Pp ,
-.Sx \&Ss ,
+.Ic \&Pp ,
+.Ic \&Ss ,
and
-.Sx \&Sx .
-.Ss \&Sm
+.Ic \&Sx .
+.It Ic \&Sm Op Cm on | off
Switches the spacing mode for output generated from macros.
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Sm Op Cm on | off
.Pp
By default, spacing is
.Cm on .
@@ -2374,26 +2249,26 @@ output generated from adjacent macros, but text lines
still get normal spacing between words and sentences.
.Pp
When called without an argument, the
-.Sx \&Sm
+.Ic \&Sm
macro toggles the spacing mode.
Using this is not recommended because it makes the code harder to read.
-.Ss \&So
+.It Ic \&So Ar block
Multi-line version of
-.Sx \&Sq .
-.Ss \&Sq
+.Ic \&Sq .
+.It Ic \&Sq Ar line
Encloses its arguments in
.Sq typewriter
single-quotes.
.Pp
See also
-.Sx \&Dq ,
-.Sx \&Qq ,
+.Ic \&Dq ,
+.Ic \&Qq ,
and
-.Sx \&So .
-.Ss \&Ss
+.Ic \&So .
+.It Ic \&Ss Ar Title line
Begin a new subsection.
Unlike with
-.Sx \&Sh ,
+.Ic \&Sh ,
there is no convention for the naming of subsections.
Except
.Em DESCRIPTION ,
@@ -2402,17 +2277,17 @@ the conventional sections described in
rarely have subsections.
.Pp
Sub-section names should be unique so that they may be keyed by
-.Sx \&Sx .
+.Ic \&Sx .
Although this macro is parsed, it should not consist of child node or it
may not be linked with
-.Sx \&Sx .
+.Ic \&Sx .
.Pp
See also
-.Sx \&Pp ,
-.Sx \&Sh ,
+.Ic \&Pp ,
+.Ic \&Sh ,
and
-.Sx \&Sx .
-.Ss \&St
+.Ic \&Sx .
+.It Ic \&St Fl Ns Ar abbreviation
Replace an abbreviation for a standard with the full form.
The following standards are recognised.
Where multiple lines are given without a blank line in between,
@@ -2622,7 +2497,7 @@ Ethernet local area networks.
.St -ieee1275-94
.El
.El
-.Ss \&Sx
+.It Ic \&Sx Ar Title line
Reference a section or subsection in the same manual page.
The referenced section or subsection name must be identical to the
enclosed argument, including whitespace.
@@ -2631,15 +2506,15 @@ Examples:
.Dl \&.Sx MANUAL STRUCTURE
.Pp
See also
-.Sx \&Sh
+.Ic \&Sh
and
-.Sx \&Ss .
-.Ss \&Sy
+.Ic \&Ss .
+.It Ic \&Sy Ar word ...
Request a boldface font.
.Pp
This is most often used to indicate importance or seriousness (not to be
confused with stress emphasis, see
-.Sx \&Em ) .
+.Ic \&Em ) .
When none of the semantic macros fit, it is also adequate for syntax
elements that have to be given or that appear verbatim.
.Pp
@@ -2655,31 +2530,30 @@ program.
.Ed
.Pp
See also
-.Sx \&Bf ,
-.Sx \&Em ,
-.Sx \&Li ,
+.Ic \&Em ,
+.Ic \&No ,
and
-.Sx \&No .
-.Ss \&Ta
+.Ic \&Ql .
+.It Ic \&Ta
Table cell separator in
-.Sx \&Bl Fl column
+.Ic \&Bl Fl column
lists; can only be used below
-.Sx \&It .
-.Ss \&Tn
+.Ic \&It .
+.It Ic \&Tn Ar word ...
Supported only for compatibility, do not use this in new manuals.
Even though the macro name
.Pq Dq tradename
suggests a semantic function, historic usage is inconsistent, mostly
using it as a presentation-level macro to request a small caps font.
-.Ss \&Ud
+.It Ic \&Ud
Supported only for compatibility, do not use this in new manuals.
Prints out
.Dq currently under development.
-.Ss \&Ux
+.It Ic \&Ux
Supported only for compatibility, do not use this in new manuals.
Prints out
.Dq Ux .
-.Ss \&Va
+.It Ic \&Va Oo Ar type Oc Ar identifier ...
A variable name.
.Pp
Examples:
@@ -2687,13 +2561,13 @@ Examples:
.Dl \&.Va const char *bar ;
.Pp
For function arguments and parameters, use
-.Sx \&Fa
+.Ic \&Fa
instead.
For declarations of global variables in the
.Em SYNOPSIS
section, use
-.Sx \&Vt .
-.Ss \&Vt
+.Ic \&Vt .
+.It Ic \&Vt Ar type Op Ar identifier
A variable type.
.Pp
This is also used for indicating global variables in the
@@ -2715,33 +2589,30 @@ Examples:
.Dl \&.Vt extern const char * const sys_signame[] \&;
.Pp
For parameters in function prototypes, use
-.Sx \&Fa
+.Ic \&Fa
instead, for function return types
-.Sx \&Ft ,
+.Ic \&Ft ,
and for variable names outside the
.Em SYNOPSIS
section
-.Sx \&Va ,
+.Ic \&Va ,
even when including a type with the name.
See also
.Sx MANUAL STRUCTURE .
-.Ss \&Xc
+.It Ic \&Xc
Close a scope opened by
-.Sx \&Xo .
-.Ss \&Xo
+.Ic \&Xo .
+.It Ic \&Xo Ar block
Extend the header of an
-.Sx \&It
+.Ic \&It
macro or the body of a partial-implicit block macro
beyond the end of the input line.
This macro originally existed to work around the 9-argument limit
of historic
.Xr roff 7 .
-.Ss \&Xr
+.It Ic \&Xr Ar name section
Link to another manual
.Pq Qq cross-reference .
-Its syntax is as follows:
-.Pp
-.D1 Pf \. Sx \&Xr Ar name section
.Pp
Cross reference the
.Ar name
@@ -2753,6 +2624,7 @@ Examples:
.Dl \&.Xr mandoc 1
.Dl \&.Xr mandoc 1 \&;
.Dl \&.Xr mandoc 1 \&Ns s behaviour
+.El
.Sh MACRO SYNTAX
The syntax of a macro depends on its classification.
In this section,
@@ -2800,10 +2672,10 @@ column, if applicable, describes closure rules.
.Ss Block full-explicit
Multi-line scope closed by an explicit closing macro.
All macros contains bodies; only
-.Sx \&Bf
+.Ic \s&Bf
and
.Pq optionally
-.Sx \&Bl
+.Ic \&Bl
contain a head.
.Bd -literal -offset indent
\&.Yo \(lB\-arg \(lBparm...\(rB\(rB \(lBhead...\(rB
@@ -2812,20 +2684,20 @@ contain a head.
.Ed
.Bl -column "MacroX" "CallableX" "ParsedX" "closed by XXX" -offset indent
.It Em Macro Ta Em Callable Ta Em Parsed Ta Em Scope
-.It Sx \&Bd Ta \&No Ta \&No Ta closed by Sx \&Ed
-.It Sx \&Bf Ta \&No Ta \&No Ta closed by Sx \&Ef
-.It Sx \&Bk Ta \&No Ta \&No Ta closed by Sx \&Ek
-.It Sx \&Bl Ta \&No Ta \&No Ta closed by Sx \&El
-.It Sx \&Ed Ta \&No Ta \&No Ta opened by Sx \&Bd
-.It Sx \&Ef Ta \&No Ta \&No Ta opened by Sx \&Bf
-.It Sx \&Ek Ta \&No Ta \&No Ta opened by Sx \&Bk
-.It Sx \&El Ta \&No Ta \&No Ta opened by Sx \&Bl
+.It Ic \&Bd Ta \&No Ta \&No Ta closed by Ic \&Ed
+.It Ic \&Bf Ta \&No Ta \&No Ta closed by Ic \&Ef
+.It Ic \&Bk Ta \&No Ta \&No Ta closed by Ic \&Ek
+.It Ic \&Bl Ta \&No Ta \&No Ta closed by Ic \&El
+.It Ic \&Ed Ta \&No Ta \&No Ta opened by Ic \&Bd
+.It Ic \&Ef Ta \&No Ta \&No Ta opened by Ic \&Bf
+.It Ic \&Ek Ta \&No Ta \&No Ta opened by Ic \&Bk
+.It Ic \&El Ta \&No Ta \&No Ta opened by Ic \&Bl
.El
.Ss Block full-implicit
Multi-line scope closed by end-of-file or implicitly by another macro.
All macros have bodies; some
.Po
-.Sx \&It Fl bullet ,
+.Ic \&It Fl bullet ,
.Fl hyphen ,
.Fl dash ,
.Fl enum ,
@@ -2833,9 +2705,9 @@ All macros have bodies; some
.Pc
don't have heads; only one
.Po
-.Sx \&It
+.Ic \&It
in
-.Sx \&Bl Fl column
+.Ic \&Bl Fl column
.Pc
has multiple heads.
.Bd -literal -offset indent
@@ -2844,15 +2716,15 @@ has multiple heads.
.Ed
.Bl -column "MacroX" "CallableX" "ParsedX" "closed by XXXXXXXXXXX" -offset indent
.It Em Macro Ta Em Callable Ta Em Parsed Ta Em Scope
-.It Sx \&It Ta \&No Ta Yes Ta closed by Sx \&It , Sx \&El
-.It Sx \&Nd Ta \&No Ta \&No Ta closed by Sx \&Sh
-.It Sx \&Nm Ta \&No Ta Yes Ta closed by Sx \&Nm , Sx \&Sh , Sx \&Ss
-.It Sx \&Sh Ta \&No Ta Yes Ta closed by Sx \&Sh
-.It Sx \&Ss Ta \&No Ta Yes Ta closed by Sx \&Sh , Sx \&Ss
+.It Ic \&It Ta \&No Ta Yes Ta closed by Ic \&It , Ic \&El
+.It Ic \&Nd Ta \&No Ta \&No Ta closed by Ic \&Sh
+.It Ic \&Nm Ta \&No Ta Yes Ta closed by Ic \&Nm , Ic \&Sh , Ic \&Ss
+.It Ic \&Sh Ta \&No Ta Yes Ta closed by Ic \&Sh
+.It Ic \&Ss Ta \&No Ta Yes Ta closed by Ic \&Sh , Ic \&Ss
.El
.Pp
Note that the
-.Sx \&Nm
+.Ic \&Nm
macro is a
.Sx Block full-implicit
macro only when invoked as the first macro
@@ -2864,11 +2736,11 @@ section line, else it is
Like block full-explicit, but also with single-line scope.
Each has at least a body and, in limited circumstances, a head
.Po
-.Sx \&Fo ,
-.Sx \&Eo
+.Ic \&Fo ,
+.Ic \&Eo
.Pc
and/or tail
-.Pq Sx \&Ec .
+.Pq Ic \&Ec .
.Bd -literal -offset indent
\&.Yo \(lB\-arg \(lBparm...\(rB\(rB \(lBhead...\(rB
\(lBbody...\(rB
@@ -2879,30 +2751,30 @@ and/or tail
.Ed
.Bl -column "MacroX" "CallableX" "ParsedX" "closed by XXXX" -offset indent
.It Em Macro Ta Em Callable Ta Em Parsed Ta Em Scope
-.It Sx \&Ac Ta Yes Ta Yes Ta opened by Sx \&Ao
-.It Sx \&Ao Ta Yes Ta Yes Ta closed by Sx \&Ac
-.It Sx \&Bc Ta Yes Ta Yes Ta closed by Sx \&Bo
-.It Sx \&Bo Ta Yes Ta Yes Ta opened by Sx \&Bc
-.It Sx \&Brc Ta Yes Ta Yes Ta opened by Sx \&Bro
-.It Sx \&Bro Ta Yes Ta Yes Ta closed by Sx \&Brc
-.It Sx \&Dc Ta Yes Ta Yes Ta opened by Sx \&Do
-.It Sx \&Do Ta Yes Ta Yes Ta closed by Sx \&Dc
-.It Sx \&Ec Ta Yes Ta Yes Ta opened by Sx \&Eo
-.It Sx \&Eo Ta Yes Ta Yes Ta closed by Sx \&Ec
-.It Sx \&Fc Ta Yes Ta Yes Ta opened by Sx \&Fo
-.It Sx \&Fo Ta \&No Ta \&No Ta closed by Sx \&Fc
-.It Sx \&Oc Ta Yes Ta Yes Ta closed by Sx \&Oo
-.It Sx \&Oo Ta Yes Ta Yes Ta opened by Sx \&Oc
-.It Sx \&Pc Ta Yes Ta Yes Ta closed by Sx \&Po
-.It Sx \&Po Ta Yes Ta Yes Ta opened by Sx \&Pc
-.It Sx \&Qc Ta Yes Ta Yes Ta opened by Sx \&Oo
-.It Sx \&Qo Ta Yes Ta Yes Ta closed by Sx \&Oc
-.It Sx \&Re Ta \&No Ta \&No Ta opened by Sx \&Rs
-.It Sx \&Rs Ta \&No Ta \&No Ta closed by Sx \&Re
-.It Sx \&Sc Ta Yes Ta Yes Ta opened by Sx \&So
-.It Sx \&So Ta Yes Ta Yes Ta closed by Sx \&Sc
-.It Sx \&Xc Ta Yes Ta Yes Ta opened by Sx \&Xo
-.It Sx \&Xo Ta Yes Ta Yes Ta closed by Sx \&Xc
+.It Ic \&Ac Ta Yes Ta Yes Ta opened by Ic \&Ao
+.It Ic \&Ao Ta Yes Ta Yes Ta closed by Ic \&Ac
+.It Ic \&Bc Ta Yes Ta Yes Ta closed by Ic \&Bo
+.It Ic \&Bo Ta Yes Ta Yes Ta opened by Ic \&Bc
+.It Ic \&Brc Ta Yes Ta Yes Ta opened by Ic \&Bro
+.It Ic \&Bro Ta Yes Ta Yes Ta closed by Ic \&Brc
+.It Ic \&Dc Ta Yes Ta Yes Ta opened by Ic \&Do
+.It Ic \&Do Ta Yes Ta Yes Ta closed by Ic \&Dc
+.It Ic \&Ec Ta Yes Ta Yes Ta opened by Ic \&Eo
+.It Ic \&Eo Ta Yes Ta Yes Ta closed by Ic \&Ec
+.It Ic \&Fc Ta Yes Ta Yes Ta opened by Ic \&Fo
+.It Ic \&Fo Ta \&No Ta \&No Ta closed by Ic \&Fc
+.It Ic \&Oc Ta Yes Ta Yes Ta closed by Ic \&Oo
+.It Ic \&Oo Ta Yes Ta Yes Ta opened by Ic \&Oc
+.It Ic \&Pc Ta Yes Ta Yes Ta closed by Ic \&Po
+.It Ic \&Po Ta Yes Ta Yes Ta opened by Ic \&Pc
+.It Ic \&Qc Ta Yes Ta Yes Ta opened by Ic \&Oo
+.It Ic \&Qo Ta Yes Ta Yes Ta closed by Ic \&Oc
+.It Ic \&Re Ta \&No Ta \&No Ta opened by Ic \&Rs
+.It Ic \&Rs Ta \&No Ta \&No Ta closed by Ic \&Re
+.It Ic \&Sc Ta Yes Ta Yes Ta opened by Ic \&So
+.It Ic \&So Ta Yes Ta Yes Ta closed by Ic \&Sc
+.It Ic \&Xc Ta Yes Ta Yes Ta opened by Ic \&Xo
+.It Ic \&Xo Ta Yes Ta Yes Ta closed by Ic \&Xc
.El
.Ss Block partial-implicit
Like block full-implicit, but with single-line scope closed by the
@@ -2912,23 +2784,23 @@ end of the line.
.Ed
.Bl -column "MacroX" "CallableX" "ParsedX" -offset indent
.It Em Macro Ta Em Callable Ta Em Parsed
-.It Sx \&Aq Ta Yes Ta Yes
-.It Sx \&Bq Ta Yes Ta Yes
-.It Sx \&Brq Ta Yes Ta Yes
-.It Sx \&D1 Ta \&No Ta \&Yes
-.It Sx \&Dl Ta \&No Ta Yes
-.It Sx \&Dq Ta Yes Ta Yes
-.It Sx \&En Ta Yes Ta Yes
-.It Sx \&Op Ta Yes Ta Yes
-.It Sx \&Pq Ta Yes Ta Yes
-.It Sx \&Ql Ta Yes Ta Yes
-.It Sx \&Qq Ta Yes Ta Yes
-.It Sx \&Sq Ta Yes Ta Yes
-.It Sx \&Vt Ta Yes Ta Yes
+.It Ic \&Aq Ta Yes Ta Yes
+.It Ic \&Bq Ta Yes Ta Yes
+.It Ic \&Brq Ta Yes Ta Yes
+.It Ic \&D1 Ta \&No Ta \&Yes
+.It Ic \&Dl Ta \&No Ta Yes
+.It Ic \&Dq Ta Yes Ta Yes
+.It Ic \&En Ta Yes Ta Yes
+.It Ic \&Op Ta Yes Ta Yes
+.It Ic \&Pq Ta Yes Ta Yes
+.It Ic \&Ql Ta Yes Ta Yes
+.It Ic \&Qq Ta Yes Ta Yes
+.It Ic \&Sq Ta Yes Ta Yes
+.It Ic \&Vt Ta Yes Ta Yes
.El
.Pp
Note that the
-.Sx \&Vt
+.Ic \&Vt
macro is a
.Sx Block partial-implicit
only when invoked as the first macro
@@ -2938,17 +2810,17 @@ section line, else it is
.Sx In-line .
.Ss Special block macro
The
-.Sx \&Ta
+.Ic \&Ta
macro can only be used below
-.Sx \&It
+.Ic \&It
in
-.Sx \&Bl Fl column
+.Ic \&Bl Fl column
lists.
It delimits blocks representing table cells;
these blocks have bodies, but no heads.
.Bl -column "MacroX" "CallableX" "ParsedX" "closed by XXXX" -offset indent
.It Em Macro Ta Em Callable Ta Em Parsed Ta Em Scope
-.It Sx \&Ta Ta Yes Ta Yes Ta closed by Sx \&Ta , Sx \&It
+.It Ic \&Ta Ta Yes Ta Yes Ta closed by Ic \&Ta , Ic \&It
.El
.Ss In-line
Closed by the end of the line, fixed argument lengths,
@@ -2966,77 +2838,77 @@ then the macro accepts an arbitrary number of arguments.
.Ed
.Bl -column "MacroX" "CallableX" "ParsedX" "Arguments" -offset indent
.It Em Macro Ta Em Callable Ta Em Parsed Ta Em Arguments
-.It Sx \&%A Ta \&No Ta \&No Ta >0
-.It Sx \&%B Ta \&No Ta \&No Ta >0
-.It Sx \&%C Ta \&No Ta \&No Ta >0
-.It Sx \&%D Ta \&No Ta \&No Ta >0
-.It Sx \&%I Ta \&No Ta \&No Ta >0
-.It Sx \&%J Ta \&No Ta \&No Ta >0
-.It Sx \&%N Ta \&No Ta \&No Ta >0
-.It Sx \&%O Ta \&No Ta \&No Ta >0
-.It Sx \&%P Ta \&No Ta \&No Ta >0
-.It Sx \&%Q Ta \&No Ta \&No Ta >0
-.It Sx \&%R Ta \&No Ta \&No Ta >0
-.It Sx \&%T Ta \&No Ta \&No Ta >0
-.It Sx \&%U Ta \&No Ta \&No Ta >0
-.It Sx \&%V Ta \&No Ta \&No Ta >0
-.It Sx \&Ad Ta Yes Ta Yes Ta >0
-.It Sx \&An Ta Yes Ta Yes Ta >0
-.It Sx \&Ap Ta Yes Ta Yes Ta 0
-.It Sx \&Ar Ta Yes Ta Yes Ta n
-.It Sx \&At Ta Yes Ta Yes Ta 1
-.It Sx \&Bsx Ta Yes Ta Yes Ta n
-.It Sx \&Bt Ta \&No Ta \&No Ta 0
-.It Sx \&Bx Ta Yes Ta Yes Ta n
-.It Sx \&Cd Ta Yes Ta Yes Ta >0
-.It Sx \&Cm Ta Yes Ta Yes Ta >0
-.It Sx \&Db Ta \&No Ta \&No Ta 1
-.It Sx \&Dd Ta \&No Ta \&No Ta n
-.It Sx \&Dt Ta \&No Ta \&No Ta n
-.It Sx \&Dv Ta Yes Ta Yes Ta >0
-.It Sx \&Dx Ta Yes Ta Yes Ta n
-.It Sx \&Em Ta Yes Ta Yes Ta >0
-.It Sx \&Er Ta Yes Ta Yes Ta >0
-.It Sx \&Es Ta Yes Ta Yes Ta 2
-.It Sx \&Ev Ta Yes Ta Yes Ta >0
-.It Sx \&Ex Ta \&No Ta \&No Ta n
-.It Sx \&Fa Ta Yes Ta Yes Ta >0
-.It Sx \&Fd Ta \&No Ta \&No Ta >0
-.It Sx \&Fl Ta Yes Ta Yes Ta n
-.It Sx \&Fn Ta Yes Ta Yes Ta >0
-.It Sx \&Fr Ta Yes Ta Yes Ta >0
-.It Sx \&Ft Ta Yes Ta Yes Ta >0
-.It Sx \&Fx Ta Yes Ta Yes Ta n
-.It Sx \&Hf Ta \&No Ta \&No Ta n
-.It Sx \&Ic Ta Yes Ta Yes Ta >0
-.It Sx \&In Ta \&No Ta \&No Ta 1
-.It Sx \&Lb Ta \&No Ta \&No Ta 1
-.It Sx \&Li Ta Yes Ta Yes Ta >0
-.It Sx \&Lk Ta Yes Ta Yes Ta >0
-.It Sx \&Lp Ta \&No Ta \&No Ta 0
-.It Sx \&Ms Ta Yes Ta Yes Ta >0
-.It Sx \&Mt Ta Yes Ta Yes Ta >0
-.It Sx \&Nm Ta Yes Ta Yes Ta n
-.It Sx \&No Ta Yes Ta Yes Ta 0
-.It Sx \&Ns Ta Yes Ta Yes Ta 0
-.It Sx \&Nx Ta Yes Ta Yes Ta n
-.It Sx \&Os Ta \&No Ta \&No Ta n
-.It Sx \&Ot Ta Yes Ta Yes Ta >0
-.It Sx \&Ox Ta Yes Ta Yes Ta n
-.It Sx \&Pa Ta Yes Ta Yes Ta n
-.It Sx \&Pf Ta Yes Ta Yes Ta 1
-.It Sx \&Pp Ta \&No Ta \&No Ta 0
-.It Sx \&Rv Ta \&No Ta \&No Ta n
-.It Sx \&Sm Ta \&No Ta \&No Ta <2
-.It Sx \&St Ta \&No Ta Yes Ta 1
-.It Sx \&Sx Ta Yes Ta Yes Ta >0
-.It Sx \&Sy Ta Yes Ta Yes Ta >0
-.It Sx \&Tn Ta Yes Ta Yes Ta >0
-.It Sx \&Ud Ta \&No Ta \&No Ta 0
-.It Sx \&Ux Ta Yes Ta Yes Ta n
-.It Sx \&Va Ta Yes Ta Yes Ta n
-.It Sx \&Vt Ta Yes Ta Yes Ta >0
-.It Sx \&Xr Ta Yes Ta Yes Ta 2
+.It Ic \&%A Ta \&No Ta \&No Ta >0
+.It Ic \&%B Ta \&No Ta \&No Ta >0
+.It Ic \&%C Ta \&No Ta \&No Ta >0
+.It Ic \&%D Ta \&No Ta \&No Ta >0
+.It Ic \&%I Ta \&No Ta \&No Ta >0
+.It Ic \&%J Ta \&No Ta \&No Ta >0
+.It Ic \&%N Ta \&No Ta \&No Ta >0
+.It Ic \&%O Ta \&No Ta \&No Ta >0
+.It Ic \&%P Ta \&No Ta \&No Ta >0
+.It Ic \&%Q Ta \&No Ta \&No Ta >0
+.It Ic \&%R Ta \&No Ta \&No Ta >0
+.It Ic \&%T Ta \&No Ta \&No Ta >0
+.It Ic \&%U Ta \&No Ta \&No Ta >0
+.It Ic \&%V Ta \&No Ta \&No Ta >0
+.It Ic \&Ad Ta Yes Ta Yes Ta >0
+.It Ic \&An Ta Yes Ta Yes Ta >0
+.It Ic \&Ap Ta Yes Ta Yes Ta 0
+.It Ic \&Ar Ta Yes Ta Yes Ta n
+.It Ic \&At Ta Yes Ta Yes Ta 1
+.It Ic \&Bsx Ta Yes Ta Yes Ta n
+.It Ic \&Bt Ta \&No Ta \&No Ta 0
+.It Ic \&Bx Ta Yes Ta Yes Ta n
+.It Ic \&Cd Ta Yes Ta Yes Ta >0
+.It Ic \&Cm Ta Yes Ta Yes Ta >0
+.It Ic \&Db Ta \&No Ta \&No Ta 1
+.It Ic \&Dd Ta \&No Ta \&No Ta n
+.It Ic \&Dt Ta \&No Ta \&No Ta n
+.It Ic \&Dv Ta Yes Ta Yes Ta >0
+.It Ic \&Dx Ta Yes Ta Yes Ta n
+.It Ic \&Em Ta Yes Ta Yes Ta >0
+.It Ic \&Er Ta Yes Ta Yes Ta >0
+.It Ic \&Es Ta Yes Ta Yes Ta 2
+.It Ic \&Ev Ta Yes Ta Yes Ta >0
+.It Ic \&Ex Ta \&No Ta \&No Ta n
+.It Ic \&Fa Ta Yes Ta Yes Ta >0
+.It Ic \&Fd Ta \&No Ta \&No Ta >0
+.It Ic \&Fl Ta Yes Ta Yes Ta n
+.It Ic \&Fn Ta Yes Ta Yes Ta >0
+.It Ic \&Fr Ta Yes Ta Yes Ta >0
+.It Ic \&Ft Ta Yes Ta Yes Ta >0
+.It Ic \&Fx Ta Yes Ta Yes Ta n
+.It Ic \&Hf Ta \&No Ta \&No Ta n
+.It Ic \&Ic Ta Yes Ta Yes Ta >0
+.It Ic \&In Ta \&No Ta \&No Ta 1
+.It Ic \&Lb Ta \&No Ta \&No Ta 1
+.It Ic \&Li Ta Yes Ta Yes Ta >0
+.It Ic \&Lk Ta Yes Ta Yes Ta >0
+.It Ic \&Lp Ta \&No Ta \&No Ta 0
+.It Ic \&Ms Ta Yes Ta Yes Ta >0
+.It Ic \&Mt Ta Yes Ta Yes Ta >0
+.It Ic \&Nm Ta Yes Ta Yes Ta n
+.It Ic \&No Ta Yes Ta Yes Ta >0
+.It Ic \&Ns Ta Yes Ta Yes Ta 0
+.It Ic \&Nx Ta Yes Ta Yes Ta n
+.It Ic \&Os Ta \&No Ta \&No Ta n
+.It Ic \&Ot Ta Yes Ta Yes Ta >0
+.It Ic \&Ox Ta Yes Ta Yes Ta n
+.It Ic \&Pa Ta Yes Ta Yes Ta n
+.It Ic \&Pf Ta Yes Ta Yes Ta 1
+.It Ic \&Pp Ta \&No Ta \&No Ta 0
+.It Ic \&Rv Ta \&No Ta \&No Ta n
+.It Ic \&Sm Ta \&No Ta \&No Ta <2
+.It Ic \&St Ta \&No Ta Yes Ta 1
+.It Ic \&Sx Ta Yes Ta Yes Ta >0
+.It Ic \&Sy Ta Yes Ta Yes Ta >0
+.It Ic \&Tn Ta Yes Ta Yes Ta >0
+.It Ic \&Ud Ta \&No Ta \&No Ta 0
+.It Ic \&Ux Ta Yes Ta Yes Ta n
+.It Ic \&Va Ta Yes Ta Yes Ta n
+.It Ic \&Vt Ta Yes Ta Yes Ta >0
+.It Ic \&Xr Ta Yes Ta Yes Ta 2
.El
.Ss Delimiters
When a macro argument consists of one single input character
@@ -3151,7 +3023,7 @@ The following problematic behaviour is found in groff:
.Pp
.Bl -dash -compact
.It
-.Sx \&Dd
+.Ic \&Dd
with non-standard arguments behaves very strangely.
When there are three arguments, they are printed verbatim.
Any other number of arguments is replaced by the current date,
@@ -3159,17 +3031,17 @@ but without any arguments the string
.Dq Epoch
is printed.
.It
-.Sx \&Lk
+.Ic \&Lk
only accepts a single link-name argument; the remainder is misformatted.
.It
-.Sx \&Pa
+.Ic \&Pa
does not format its arguments when used in the FILES section under
certain list types.
.It
-.Sx \&Ta
+.Ic \&Ta
can only be called by other macros, but not at the beginning of a line.
.It
-.Sx \&%C
+.Ic \&%C
is not implemented (up to and including groff-1.22.2).
.It
.Sq \ef
@@ -3188,23 +3060,22 @@ The following features are unimplemented in mandoc:
.Pp
.Bl -dash -compact
.It
-.Sx \&Bd
-.Fl file Ar file
+.Ic \&Bd Fl file Ar file
is unsupported for security reasons.
.It
-.Sx \&Bd
+.Ic \&Bd
.Fl filled
does not adjust the right margin, but is an alias for
-.Sx \&Bd
+.Ic \&Bd
.Fl ragged .
.It
-.Sx \&Bd
+.Ic \&Bd
.Fl literal
does not use a literal font, but is an alias for
-.Sx \&Bd
+.Ic \&Bd
.Fl unfilled .
.It
-.Sx \&Bd
+.Ic \&Bd
.Fl offset Cm center
and
.Fl offset Cm right
diff --git a/mdoc.c b/mdoc.c
index 71803531ddfb..bb3ec58bd0f7 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc.c,v 1.268 2017/08/11 16:56:21 schwarze Exp $ */
+/* $Id: mdoc.c,v 1.274 2018/12/31 07:46:07 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012-2018 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
@@ -80,13 +80,6 @@ mdoc_parseln(struct roff_man *mdoc, int ln, char *buf, int offs)
}
void
-mdoc_macro(MACRO_PROT_ARGS)
-{
- assert(tok >= MDOC_Dd && tok < MDOC_MAX);
- (*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf);
-}
-
-void
mdoc_tail_alloc(struct roff_man *mdoc, int line, int pos, enum roff_tok tok)
{
struct roff_node *p;
@@ -162,15 +155,6 @@ mdoc_elem_alloc(struct roff_man *mdoc, int line, int pos,
mdoc->next = ROFF_NEXT_CHILD;
}
-void
-mdoc_node_relink(struct roff_man *mdoc, struct roff_node *p)
-{
-
- roff_node_unlink(mdoc, p);
- p->prev = p->next = NULL;
- roff_node_append(mdoc, p);
-}
-
/*
* Parse free-form text, that is, a line that does not begin with the
* control character.
@@ -196,7 +180,8 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
(n->parent != NULL && n->parent->tok == MDOC_Bl &&
n->parent->norm->Bl.type == LIST_column)) {
mdoc->flags |= MDOC_FREECOL;
- mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
+ (*mdoc_macro(MDOC_It)->fp)(mdoc, MDOC_It,
+ line, offs, &offs, buf);
return 1;
}
@@ -225,7 +210,7 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
* Strip trailing tabs in literal context only;
* outside, they affect the next line.
*/
- if (MDOC_LITERAL & mdoc->flags)
+ if (mdoc->flags & ROFF_NOFILL)
continue;
break;
case '\\':
@@ -242,8 +227,7 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
*end = '\0';
if (ws)
- mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse,
- line, (int)(ws-buf), NULL);
+ mandoc_msg(MANDOCERR_SPACE_EOL, line, (int)(ws - buf), NULL);
/*
* Blank lines are allowed in no-fill mode
@@ -251,7 +235,7 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
* but add a single vertical space elsewhere.
*/
- if (buf[offs] == '\0' && ! (mdoc->flags & MDOC_LITERAL)) {
+ if (buf[offs] == '\0' && (mdoc->flags & ROFF_NOFILL) == 0) {
switch (mdoc->last->type) {
case ROFFT_TEXT:
sp = mdoc->last->string;
@@ -267,8 +251,7 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
default:
break;
}
- mandoc_msg(MANDOCERR_FI_BLANK, mdoc->parse,
- line, (int)(c - buf), NULL);
+ mandoc_msg(MANDOCERR_FI_BLANK, line, (int)(c - buf), NULL);
roff_elem_alloc(mdoc, line, offs, ROFF_sp);
mdoc->last->flags |= NODE_VALID | NODE_ENDED;
mdoc->next = ROFF_NEXT_SIBLING;
@@ -277,7 +260,7 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
roff_word_alloc(mdoc, line, offs, buf+offs);
- if (mdoc->flags & MDOC_LITERAL)
+ if (mdoc->flags & ROFF_NOFILL)
return 1;
/*
@@ -308,8 +291,7 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
if (*c == ' ')
c++;
if (isupper((unsigned char)(*c)))
- mandoc_msg(MANDOCERR_EOS, mdoc->parse,
- line, (int)(c - buf), NULL);
+ mandoc_msg(MANDOCERR_EOS, line, (int)(c - buf), NULL);
}
return 1;
@@ -337,8 +319,7 @@ mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs)
if (sz == 2 || sz == 3)
tok = roffhash_find(mdoc->mdocmac, buf + sv, sz);
if (tok == TOKEN_NONE) {
- mandoc_msg(MANDOCERR_MACRO, mdoc->parse,
- ln, sv, buf + sv - 1);
+ mandoc_msg(MANDOCERR_MACRO, ln, sv, "%s", buf + sv - 1);
return 1;
}
@@ -368,8 +349,7 @@ mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs)
*/
if ('\0' == buf[offs] && ' ' == buf[offs - 1])
- mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse,
- ln, offs - 1, NULL);
+ mandoc_msg(MANDOCERR_SPACE_EOL, ln, offs - 1, NULL);
/*
* If an initial macro or a list invocation, divert directly
@@ -378,7 +358,7 @@ mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs)
n = mdoc->last;
if (n == NULL || tok == MDOC_It || tok == MDOC_El) {
- mdoc_macro(mdoc, tok, ln, sv, &offs, buf);
+ (*mdoc_macro(tok)->fp)(mdoc, tok, ln, sv, &offs, buf);
return 1;
}
@@ -394,13 +374,13 @@ mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs)
(n->parent != NULL && n->parent->tok == MDOC_Bl &&
n->parent->norm->Bl.type == LIST_column)) {
mdoc->flags |= MDOC_FREECOL;
- mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
+ (*mdoc_macro(MDOC_It)->fp)(mdoc, MDOC_It, ln, sv, &sv, buf);
return 1;
}
/* Normal processing of a macro. */
- mdoc_macro(mdoc, tok, ln, sv, &offs, buf);
+ (*mdoc_macro(tok)->fp)(mdoc, tok, ln, sv, &offs, buf);
/* In quick mode (for mandocdb), abort after the NAME section. */
@@ -448,12 +428,3 @@ mdoc_isdelim(const char *p)
return DELIM_NONE;
}
-
-void
-mdoc_validate(struct roff_man *mdoc)
-{
-
- mdoc->last = mdoc->first;
- mdoc_node_validate(mdoc);
- mdoc_state_reset(mdoc);
-}
diff --git a/mdoc.h b/mdoc.h
index 1628e0c80c94..2f32fa4962fe 100644
--- a/mdoc.h
+++ b/mdoc.h
@@ -1,4 +1,4 @@
-/* $Id: mdoc.h,v 1.145 2017/04/24 23:06:18 schwarze Exp $ */
+/* $Id: mdoc.h,v 1.146 2018/12/30 00:49:55 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -16,6 +16,9 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+struct roff_node;
+struct roff_man;
+
enum mdocargt {
MDOC_Split, /* -split */
MDOC_Nosplit, /* -nospli */
diff --git a/mdoc_argv.c b/mdoc_argv.c
index db4c63f0d6d2..f4ce4a8730f3 100644
--- a/mdoc_argv.c
+++ b/mdoc_argv.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc_argv.c,v 1.115 2017/05/30 16:22:03 schwarze Exp $ */
+/* $Id: mdoc_argv.c,v 1.119 2018/12/21 17:15:19 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012, 2014-2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012, 2014-2018 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
@@ -144,7 +144,7 @@ static const enum mdocargt args_Bl[] = {
MDOC_ARG_MAX
};
-static const struct mdocarg __mdocargs[MDOC_MAX - MDOC_Dd] = {
+static const struct mdocarg mdocargs[MDOC_MAX - MDOC_Dd] = {
{ ARGSFL_NONE, NULL }, /* Dd */
{ ARGSFL_NONE, NULL }, /* Dt */
{ ARGSFL_NONE, NULL }, /* Os */
@@ -266,7 +266,6 @@ static const struct mdocarg __mdocargs[MDOC_MAX - MDOC_Dd] = {
{ ARGSFL_NONE, NULL }, /* %U */
{ ARGSFL_NONE, NULL }, /* Ta */
};
-static const struct mdocarg *const mdocargs = __mdocargs - MDOC_Dd;
/*
@@ -290,7 +289,7 @@ mdoc_argv(struct roff_man *mdoc, int line, enum roff_tok tok,
/* Which flags does this macro support? */
assert(tok >= MDOC_Dd && tok < MDOC_MAX);
- argtable = mdocargs[tok].argvs;
+ argtable = mdocargs[tok - MDOC_Dd].argvs;
if (argtable == NULL)
return;
@@ -368,7 +367,7 @@ mdoc_argv(struct roff_man *mdoc, int line, enum roff_tok tok,
/* Prepare for parsing the next flag. */
*pos = ipos;
- argtable = mdocargs[tok].argvs;
+ argtable = mdocargs[tok - MDOC_Dd].argvs;
}
}
@@ -417,12 +416,9 @@ mdoc_args(struct roff_man *mdoc, int line, int *pos,
char *buf, enum roff_tok tok, char **v)
{
struct roff_node *n;
- char *v_local;
enum argsflag fl;
- if (v == NULL)
- v = &v_local;
- fl = tok == TOKEN_NONE ? ARGSFL_NONE : mdocargs[tok].flags;
+ fl = tok == TOKEN_NONE ? ARGSFL_NONE : mdocargs[tok - MDOC_Dd].flags;
/*
* We know that we're in an `It', so it's reasonable to expect
@@ -449,18 +445,20 @@ args(struct roff_man *mdoc, int line, int *pos,
char *buf, enum argsflag fl, char **v)
{
char *p;
+ char *v_local;
int pairs;
if (buf[*pos] == '\0') {
if (mdoc->flags & MDOC_PHRASELIT &&
! (mdoc->flags & MDOC_PHRASE)) {
- mandoc_msg(MANDOCERR_ARG_QUOTE,
- mdoc->parse, line, *pos, NULL);
+ mandoc_msg(MANDOCERR_ARG_QUOTE, line, *pos, NULL);
mdoc->flags &= ~MDOC_PHRASELIT;
}
return ARGS_EOLN;
}
+ if (v == NULL)
+ v = &v_local;
*v = buf + *pos;
if (fl == ARGSFL_DELIM && args_checkpunct(buf, *pos))
@@ -506,7 +504,7 @@ args(struct roff_man *mdoc, int line, int *pos,
p = strchr(*v, '\0');
if (p[-1] == ' ')
mandoc_msg(MANDOCERR_SPACE_EOL,
- mdoc->parse, line, *pos, NULL);
+ line, *pos, NULL);
*pos += (int)(p - *v);
}
@@ -527,13 +525,12 @@ args(struct roff_man *mdoc, int line, int *pos,
* Whitespace is NOT involved in literal termination.
*/
- if (mdoc->flags & MDOC_PHRASELIT || buf[*pos] == '\"') {
- if ( ! (mdoc->flags & MDOC_PHRASELIT))
+ if (mdoc->flags & MDOC_PHRASELIT ||
+ (mdoc->flags & MDOC_PHRASE && buf[*pos] == '\"')) {
+ if ((mdoc->flags & MDOC_PHRASELIT) == 0) {
*v = &buf[++(*pos)];
-
- if (mdoc->flags & MDOC_PHRASE)
mdoc->flags |= MDOC_PHRASELIT;
-
+ }
pairs = 0;
for ( ; buf[*pos]; (*pos)++) {
/* Move following text left after quoted quotes. */
@@ -554,7 +551,7 @@ args(struct roff_man *mdoc, int line, int *pos,
if (buf[*pos] == '\0') {
if ( ! (mdoc->flags & MDOC_PHRASE))
mandoc_msg(MANDOCERR_ARG_QUOTE,
- mdoc->parse, line, *pos, NULL);
+ line, *pos, NULL);
return ARGS_WORD;
}
@@ -568,14 +565,15 @@ args(struct roff_man *mdoc, int line, int *pos,
(*pos)++;
if ('\0' == buf[*pos])
- mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse,
- line, *pos, NULL);
+ mandoc_msg(MANDOCERR_SPACE_EOL, line, *pos, NULL);
return ARGS_WORD;
}
p = &buf[*pos];
- *v = mandoc_getarg(mdoc->parse, &p, line, pos);
+ *v = roff_getarg(mdoc->roff, &p, line, pos);
+ if (v == &v_local)
+ free(*v);
/*
* After parsing the last word in this phrase,
@@ -586,7 +584,7 @@ args(struct roff_man *mdoc, int line, int *pos,
mdoc->flags &= ~MDOC_PHRASEQL;
mdoc->flags |= MDOC_PHRASEQF;
}
- return ARGS_WORD;
+ return ARGS_ALLOC;
}
/*
@@ -657,7 +655,9 @@ argv_multi(struct roff_man *mdoc, int line,
v->value = mandoc_reallocarray(v->value,
v->sz + MULTI_STEP, sizeof(char *));
- v->value[(int)v->sz] = mandoc_strdup(p);
+ if (ac != ARGS_ALLOC)
+ p = mandoc_strdup(p);
+ v->value[(int)v->sz] = p;
}
}
@@ -672,7 +672,10 @@ argv_single(struct roff_man *mdoc, int line,
if (ac == ARGS_EOLN)
return;
+ if (ac != ARGS_ALLOC)
+ p = mandoc_strdup(p);
+
v->sz = 1;
v->value = mandoc_malloc(sizeof(char *));
- v->value[0] = mandoc_strdup(p);
+ v->value[0] = p;
}
diff --git a/mdoc_html.c b/mdoc_html.c
index f50de8a77af0..87bf42a72ba0 100644
--- a/mdoc_html.c
+++ b/mdoc_html.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc_html.c,v 1.310 2018/07/27 17:49:31 schwarze Exp $ */
+/* $Id: mdoc_html.c,v 1.328 2019/03/01 10:57:18 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014,2015,2016,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -42,7 +42,7 @@
#define MIN(a,b) ((/*CONSTCOND*/(a)<(b))?(a):(b))
#endif
-struct htmlmdoc {
+struct mdoc_html_act {
int (*pre)(MDOC_ARGS);
void (*post)(MDOC_ARGS);
};
@@ -62,6 +62,7 @@ static int mdoc_root_pre(const struct roff_meta *,
static void mdoc__x_post(MDOC_ARGS);
static int mdoc__x_pre(MDOC_ARGS);
+static int mdoc_abort_pre(MDOC_ARGS);
static int mdoc_ad_pre(MDOC_ARGS);
static int mdoc_an_pre(MDOC_ARGS);
static int mdoc_ap_pre(MDOC_ARGS);
@@ -119,7 +120,7 @@ static int mdoc_vt_pre(MDOC_ARGS);
static int mdoc_xr_pre(MDOC_ARGS);
static int mdoc_xx_pre(MDOC_ARGS);
-static const struct htmlmdoc __mdocs[MDOC_MAX - MDOC_Dd] = {
+static const struct mdoc_html_act mdoc_html_acts[MDOC_MAX - MDOC_Dd] = {
{NULL, NULL}, /* Dd */
{NULL, NULL}, /* Dt */
{NULL, NULL}, /* Os */
@@ -154,7 +155,7 @@ static const struct htmlmdoc __mdocs[MDOC_MAX - MDOC_Dd] = {
{mdoc_nd_pre, NULL}, /* Nd */
{mdoc_nm_pre, NULL}, /* Nm */
{mdoc_quote_pre, mdoc_quote_post}, /* Op */
- {mdoc_ft_pre, NULL}, /* Ot */
+ {mdoc_abort_pre, NULL}, /* Ot */
{mdoc_pa_pre, NULL}, /* Pa */
{mdoc_ex_pre, NULL}, /* Rv */
{mdoc_st_pre, NULL}, /* St */
@@ -227,7 +228,7 @@ static const struct htmlmdoc __mdocs[MDOC_MAX - MDOC_Dd] = {
{mdoc_em_pre, NULL}, /* Fr */
{NULL, NULL}, /* Ud */
{mdoc_lb_pre, NULL}, /* Lb */
- {mdoc_pp_pre, NULL}, /* Lp */
+ {mdoc_abort_pre, NULL}, /* Lp */
{mdoc_lk_pre, NULL}, /* Lk */
{mdoc_mt_pre, NULL}, /* Mt */
{mdoc_quote_pre, mdoc_quote_post}, /* Brq */
@@ -241,7 +242,6 @@ static const struct htmlmdoc __mdocs[MDOC_MAX - MDOC_Dd] = {
{mdoc__x_pre, mdoc__x_post}, /* %U */
{NULL, NULL}, /* Ta */
};
-static const struct htmlmdoc *const mdocs = __mdocs - MDOC_Dd;
/*
@@ -268,22 +268,21 @@ synopsis_pre(struct html *h, const struct roff_node *n)
case MDOC_Fo:
case MDOC_In:
case MDOC_Vt:
- print_paragraph(h);
break;
case MDOC_Ft:
- if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
- print_paragraph(h);
+ if (n->tok != MDOC_Fn && n->tok != MDOC_Fo)
break;
- }
/* FALLTHROUGH */
default:
print_otag(h, TAG_BR, "");
- break;
+ return;
}
+ html_close_paragraph(h);
+ print_otag(h, TAG_P, "c", "Pp");
}
void
-html_mdoc(void *arg, const struct roff_man *mdoc)
+html_mdoc(void *arg, const struct roff_meta *mdoc)
{
struct html *h;
struct roff_node *n;
@@ -295,19 +294,19 @@ html_mdoc(void *arg, const struct roff_man *mdoc)
if ((h->oflags & HTML_FRAGMENT) == 0) {
print_gen_decls(h);
print_otag(h, TAG_HTML, "");
- if (n->type == ROFFT_COMMENT)
+ if (n != NULL && n->type == ROFFT_COMMENT)
print_gen_comment(h, n);
t = print_otag(h, TAG_HEAD, "");
- print_mdoc_head(&mdoc->meta, h);
+ print_mdoc_head(mdoc, h);
print_tagq(h, t);
print_otag(h, TAG_BODY, "");
}
- mdoc_root_pre(&mdoc->meta, h);
+ mdoc_root_pre(mdoc, h);
t = print_otag(h, TAG_DIV, "c", "manual-text");
- print_mdoc_nodelist(&mdoc->meta, n, h);
+ print_mdoc_nodelist(mdoc, n, h);
print_tagq(h, t);
- mdoc_root_post(&mdoc->meta, h);
+ mdoc_root_post(mdoc, h);
print_tagq(h, NULL);
}
@@ -346,18 +345,21 @@ print_mdoc_nodelist(MDOC_ARGS)
static void
print_mdoc_node(MDOC_ARGS)
{
- int child;
struct tag *t;
+ int child;
if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
return;
+ html_fillmode(h, n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi);
+
child = 1;
- t = h->tag;
n->flags &= ~NODE_ENDED;
-
switch (n->type) {
case ROFFT_TEXT:
+ t = h->tag;
+ t->refcnt++;
+
/* No tables in this mode... */
assert(NULL == h->tblt);
@@ -366,15 +368,18 @@ print_mdoc_node(MDOC_ARGS)
* (i.e., within a <PRE>) don't print the newline.
*/
if (*n->string == ' ' && n->flags & NODE_LINE &&
- (h->flags & (HTML_LITERAL | HTML_NONEWLINE)) == 0)
+ (h->flags & HTML_NONEWLINE) == 0 &&
+ (n->flags & NODE_NOFILL) == 0)
print_otag(h, TAG_BR, "");
if (NODE_DELIMC & n->flags)
h->flags |= HTML_NOSPACE;
print_text(h, n->string);
if (NODE_DELIMO & n->flags)
h->flags |= HTML_NOSPACE;
- return;
+ break;
case ROFFT_EQN:
+ t = h->tag;
+ t->refcnt++;
print_eqn(h, n->eqn);
break;
case ROFFT_TBL:
@@ -391,20 +396,22 @@ print_mdoc_node(MDOC_ARGS)
* the "meta" table state. This will be reopened on the
* next table element.
*/
- if (h->tblt != NULL) {
+ if (h->tblt != NULL)
print_tblclose(h);
- t = h->tag;
- }
assert(h->tblt == NULL);
+ t = h->tag;
+ t->refcnt++;
if (n->tok < ROFF_MAX) {
roff_html_pre(h, n);
- child = 0;
- break;
+ t->refcnt--;
+ print_stagq(h, t);
+ return;
}
assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
- if (mdocs[n->tok].pre != NULL &&
+ if (mdoc_html_acts[n->tok - MDOC_Dd].pre != NULL &&
(n->end == ENDBODY_NOT || n->child != NULL))
- child = (*mdocs[n->tok].pre)(meta, n, h);
+ child = (*mdoc_html_acts[n->tok - MDOC_Dd].pre)(meta,
+ n, h);
break;
}
@@ -413,24 +420,31 @@ print_mdoc_node(MDOC_ARGS)
h->flags |= HTML_PREKEEP;
}
- if (child && n->child)
+ if (child && n->child != NULL)
print_mdoc_nodelist(meta, n->child, h);
+ t->refcnt--;
print_stagq(h, t);
switch (n->type) {
+ case ROFFT_TEXT:
case ROFFT_EQN:
break;
default:
- if (n->tok < ROFF_MAX ||
- mdocs[n->tok].post == NULL ||
+ if (mdoc_html_acts[n->tok - MDOC_Dd].post == NULL ||
n->flags & NODE_ENDED)
break;
- (*mdocs[n->tok].post)(meta, n, h);
+ (*mdoc_html_acts[n->tok - MDOC_Dd].post)(meta, n, h);
if (n->end != ENDBODY_NOT)
n->body->flags |= NODE_ENDED;
break;
}
+
+ if (n->flags & NODE_NOFILL &&
+ (n->next == NULL || n->next->flags & NODE_LINE)) {
+ h->col++;
+ print_endline(h);
+ }
}
static void
@@ -507,12 +521,65 @@ cond_id(const struct roff_node *n)
static int
mdoc_sh_pre(MDOC_ARGS)
{
- char *id;
+ struct roff_node *sn, *subn;
+ struct tag *t, *tsec, *tsub;
+ char *id;
+ int sc;
switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
+ if ((h->oflags & HTML_TOC) == 0 ||
+ h->flags & HTML_TOCDONE ||
+ n->sec <= SEC_SYNOPSIS) {
+ print_otag(h, TAG_SECTION, "c", "Sh");
+ break;
+ }
+ h->flags |= HTML_TOCDONE;
+ sc = 0;
+ for (sn = n->next; sn != NULL; sn = sn->next)
+ if (sn->sec == SEC_CUSTOM)
+ if (++sc == 2)
+ break;
+ if (sc < 2)
+ break;
+ t = print_otag(h, TAG_H1, "c", "Sh");
+ print_text(h, "TABLE OF CONTENTS");
+ print_tagq(h, t);
+ t = print_otag(h, TAG_UL, "c", "Bl-compact");
+ for (sn = n; sn != NULL; sn = sn->next) {
+ tsec = print_otag(h, TAG_LI, "");
+ id = html_make_id(sn->head, 0);
+ tsub = print_otag(h, TAG_A, "hR", id);
+ free(id);
+ print_mdoc_nodelist(meta, sn->head->child, h);
+ print_tagq(h, tsub);
+ tsub = NULL;
+ for (subn = sn->body->child; subn != NULL;
+ subn = subn->next) {
+ if (subn->tok != MDOC_Ss)
+ continue;
+ id = html_make_id(subn->head, 0);
+ if (id == NULL)
+ continue;
+ if (tsub == NULL)
+ print_otag(h, TAG_UL,
+ "c", "Bl-compact");
+ tsub = print_otag(h, TAG_LI, "");
+ print_otag(h, TAG_A, "hR", id);
+ free(id);
+ print_mdoc_nodelist(meta,
+ subn->head->child, h);
+ print_tagq(h, tsub);
+ }
+ print_tagq(h, tsec);
+ }
+ print_tagq(h, t);
+ print_otag(h, TAG_SECTION, "c", "Sh");
+ break;
case ROFFT_HEAD:
id = html_make_id(n, 1);
- print_otag(h, TAG_H1, "cTi", "Sh", id);
+ print_otag(h, TAG_H1, "ci", "Sh", id);
if (id != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
break;
@@ -531,11 +598,21 @@ mdoc_ss_pre(MDOC_ARGS)
{
char *id;
- if (n->type != ROFFT_HEAD)
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
+ print_otag(h, TAG_SECTION, "c", "Ss");
return 1;
+ case ROFFT_HEAD:
+ break;
+ case ROFFT_BODY:
+ return 1;
+ default:
+ abort();
+ }
id = html_make_id(n, 1);
- print_otag(h, TAG_H2, "cTi", "Ss", id);
+ print_otag(h, TAG_H2, "ci", "Ss", id);
if (id != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
return 1;
@@ -548,7 +625,7 @@ mdoc_fl_pre(MDOC_ARGS)
if ((id = cond_id(n)) != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "cTi", "Fl", id);
+ print_otag(h, TAG_CODE, "ci", "Fl", id);
print_text(h, "\\-");
if (!(n->child == NULL &&
@@ -567,19 +644,27 @@ mdoc_cm_pre(MDOC_ARGS)
if ((id = cond_id(n)) != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "cTi", "Cm", id);
+ print_otag(h, TAG_CODE, "ci", "Cm", id);
return 1;
}
static int
mdoc_nd_pre(MDOC_ARGS)
{
- if (n->type != ROFFT_BODY)
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
return 1;
-
+ case ROFFT_HEAD:
+ return 0;
+ case ROFFT_BODY:
+ break;
+ default:
+ abort();
+ }
print_text(h, "\\(em");
/* Cannot use TAG_SPAN because it may contain blocks. */
- print_otag(h, TAG_DIV, "cT", "Nd");
+ print_otag(h, TAG_DIV, "c", "Nd");
return 1;
}
@@ -587,18 +672,21 @@ static int
mdoc_nm_pre(MDOC_ARGS)
{
switch (n->type) {
+ case ROFFT_BLOCK:
+ break;
case ROFFT_HEAD:
print_otag(h, TAG_TD, "");
/* FALLTHROUGH */
case ROFFT_ELEM:
- print_otag(h, TAG_CODE, "cT", "Nm");
+ print_otag(h, TAG_CODE, "c", "Nm");
return 1;
case ROFFT_BODY:
print_otag(h, TAG_TD, "");
return 1;
default:
- break;
+ abort();
}
+ html_close_paragraph(h);
synopsis_pre(h, n);
print_otag(h, TAG_TABLE, "c", "Nm");
print_otag(h, TAG_TR, "");
@@ -611,12 +699,12 @@ mdoc_xr_pre(MDOC_ARGS)
if (NULL == n->child)
return 0;
- if (h->base_man)
- print_otag(h, TAG_A, "cThM", "Xr",
+ if (h->base_man1)
+ print_otag(h, TAG_A, "chM", "Xr",
n->child->string, n->child->next == NULL ?
NULL : n->child->next->string);
else
- print_otag(h, TAG_A, "cT", "Xr");
+ print_otag(h, TAG_A, "c", "Xr");
n = n->child;
print_text(h, n->string);
@@ -645,7 +733,7 @@ mdoc_ns_pre(MDOC_ARGS)
static int
mdoc_ar_pre(MDOC_ARGS)
{
- print_otag(h, TAG_VAR, "cT", "Ar");
+ print_otag(h, TAG_VAR, "c", "Ar");
return 1;
}
@@ -660,7 +748,6 @@ static int
mdoc_it_pre(MDOC_ARGS)
{
const struct roff_node *bl;
- struct tag *t;
enum mdoc_list type;
bl = n->parent;
@@ -702,17 +789,6 @@ mdoc_it_pre(MDOC_ARGS)
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 == NULL ||
- n->parent->prev->body->child != NULL)) {
- t = print_otag(h, TAG_DT, "");
- print_text(h, "\\ ");
- print_tagq(h, t);
- t = print_otag(h, TAG_DD, "");
- print_text(h, "\\ ");
- print_tagq(h, t);
- }
print_otag(h, TAG_DT, "");
break;
case ROFFT_BODY:
@@ -746,17 +822,20 @@ mdoc_it_pre(MDOC_ARGS)
static int
mdoc_bl_pre(MDOC_ARGS)
{
- char cattr[28];
+ char cattr[32];
struct mdoc_bl *bl;
enum htmltag elemtype;
switch (n->type) {
- case ROFFT_BODY:
- return 1;
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
+ break;
case ROFFT_HEAD:
return 0;
+ case ROFFT_BODY:
+ return 1;
default:
- break;
+ abort();
}
bl = &n->norm->Bl;
@@ -826,28 +905,34 @@ mdoc_ex_pre(MDOC_ARGS)
static int
mdoc_st_pre(MDOC_ARGS)
{
- print_otag(h, TAG_SPAN, "cT", "St");
+ print_otag(h, TAG_SPAN, "c", "St");
return 1;
}
static int
mdoc_em_pre(MDOC_ARGS)
{
- print_otag(h, TAG_I, "cT", "Em");
+ print_otag(h, TAG_I, "c", "Em");
return 1;
}
static int
mdoc_d1_pre(MDOC_ARGS)
{
- if (n->type != ROFFT_BLOCK)
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
+ break;
+ case ROFFT_HEAD:
+ return 0;
+ case ROFFT_BODY:
return 1;
-
+ default:
+ abort();
+ }
print_otag(h, TAG_DIV, "c", "Bd Bd-indent");
-
if (n->tok == MDOC_Dl)
print_otag(h, TAG_CODE, "c", "Li");
-
return 1;
}
@@ -857,7 +942,7 @@ mdoc_sx_pre(MDOC_ARGS)
char *id;
id = html_make_id(n, 0);
- print_otag(h, TAG_A, "cThR", "Sx", id);
+ print_otag(h, TAG_A, "chR", "Sx", id);
free(id);
return 1;
}
@@ -865,86 +950,51 @@ mdoc_sx_pre(MDOC_ARGS)
static int
mdoc_bd_pre(MDOC_ARGS)
{
- int comp, sv;
+ char buf[16];
struct roff_node *nn;
+ int comp;
- if (n->type == ROFFT_HEAD)
- return 0;
-
- if (n->type == ROFFT_BLOCK) {
- comp = n->norm->Bd.comp;
- for (nn = n; nn && ! comp; nn = nn->parent) {
- if (nn->type != ROFFT_BLOCK)
- continue;
- if (MDOC_Ss == nn->tok || MDOC_Sh == nn->tok)
- comp = 1;
- if (nn->prev)
- break;
- }
- if ( ! comp)
- print_paragraph(h);
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
return 1;
+ case ROFFT_HEAD:
+ return 0;
+ case ROFFT_BODY:
+ break;
+ default:
+ abort();
}
- /* Handle the -offset argument. */
-
- if (n->norm->Bd.offs == NULL ||
- ! strcmp(n->norm->Bd.offs, "left"))
- print_otag(h, TAG_DIV, "c", "Bd");
- else
- print_otag(h, TAG_DIV, "c", "Bd Bd-indent");
-
- if (n->norm->Bd.type != DISP_unfilled &&
- n->norm->Bd.type != DISP_literal)
- return 1;
-
- print_otag(h, TAG_PRE, "c", "Li");
+ /* Handle preceding whitespace. */
- /* This can be recursive: save & set our literal state. */
-
- sv = h->flags & HTML_LITERAL;
- h->flags |= HTML_LITERAL;
-
- for (nn = n->child; nn; nn = nn->next) {
- print_mdoc_node(meta, nn, h);
- /*
- * If the printed node flushes its own line, then we
- * needn't do it here as well. This is hacky, but the
- * notion of selective eoln whitespace is pretty dumb
- * anyway, so don't sweat it.
- */
- switch (nn->tok) {
- case ROFF_br:
- case ROFF_sp:
- case MDOC_Sm:
- case MDOC_Bl:
- case MDOC_D1:
- case MDOC_Dl:
- case MDOC_Lp:
- case MDOC_Pp:
+ comp = n->norm->Bd.comp;
+ for (nn = n; nn != NULL && comp == 0; nn = nn->parent) {
+ if (nn->type != ROFFT_BLOCK)
continue;
- default:
+ if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss)
+ comp = 1;
+ if (nn->prev != NULL)
break;
- }
- if (h->flags & HTML_NONEWLINE ||
- (nn->next && ! (nn->next->flags & NODE_LINE)))
- continue;
- else if (nn->next)
- print_text(h, "\n");
-
- h->flags |= HTML_NOSPACE;
}
+ (void)strlcpy(buf, "Bd", sizeof(buf));
+ if (comp == 0)
+ (void)strlcat(buf, " Pp", sizeof(buf));
- if (0 == sv)
- h->flags &= ~HTML_LITERAL;
+ /* Handle the -offset argument. */
- return 0;
+ if (n->norm->Bd.offs != NULL &&
+ strcmp(n->norm->Bd.offs, "left") != 0)
+ (void)strlcat(buf, " Bd-indent", sizeof(buf));
+
+ print_otag(h, TAG_DIV, "c", buf);
+ return 1;
}
static int
mdoc_pa_pre(MDOC_ARGS)
{
- print_otag(h, TAG_SPAN, "cT", "Pa");
+ print_otag(h, TAG_SPAN, "c", "Pa");
return 1;
}
@@ -975,7 +1025,7 @@ mdoc_an_pre(MDOC_ARGS)
if (n->sec == SEC_AUTHORS && ! (h->flags & HTML_NOSPLIT))
h->flags |= HTML_SPLIT;
- print_otag(h, TAG_SPAN, "cT", "An");
+ print_otag(h, TAG_SPAN, "c", "An");
return 1;
}
@@ -983,7 +1033,7 @@ static int
mdoc_cd_pre(MDOC_ARGS)
{
synopsis_pre(h, n);
- print_otag(h, TAG_CODE, "cT", "Cd");
+ print_otag(h, TAG_CODE, "c", "Cd");
return 1;
}
@@ -994,7 +1044,7 @@ mdoc_dv_pre(MDOC_ARGS)
if ((id = cond_id(n)) != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "cTi", "Dv", id);
+ print_otag(h, TAG_CODE, "ci", "Dv", id);
return 1;
}
@@ -1005,7 +1055,7 @@ mdoc_ev_pre(MDOC_ARGS)
if ((id = cond_id(n)) != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "cTi", "Ev", id);
+ print_otag(h, TAG_CODE, "ci", "Ev", id);
return 1;
}
@@ -1022,7 +1072,7 @@ mdoc_er_pre(MDOC_ARGS)
if (id != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "cTi", "Er", id);
+ print_otag(h, TAG_CODE, "ci", "Er", id);
return 1;
}
@@ -1033,12 +1083,12 @@ mdoc_fa_pre(MDOC_ARGS)
struct tag *t;
if (n->parent->tok != MDOC_Fo) {
- print_otag(h, TAG_VAR, "cT", "Fa");
+ print_otag(h, TAG_VAR, "c", "Fa");
return 1;
}
for (nn = n->child; nn; nn = nn->next) {
- t = print_otag(h, TAG_VAR, "cT", "Fa");
+ t = print_otag(h, TAG_VAR, "c", "Fa");
print_text(h, nn->string);
print_tagq(h, t);
if (nn->next) {
@@ -1069,11 +1119,11 @@ mdoc_fd_pre(MDOC_ARGS)
assert(n->type == ROFFT_TEXT);
if (strcmp(n->string, "#include")) {
- print_otag(h, TAG_CODE, "cT", "Fd");
+ print_otag(h, TAG_CODE, "c", "Fd");
return 1;
}
- print_otag(h, TAG_CODE, "cT", "In");
+ print_otag(h, TAG_CODE, "c", "In");
print_text(h, n->string);
if (NULL != (n = n->next)) {
@@ -1087,10 +1137,10 @@ mdoc_fd_pre(MDOC_ARGS)
cp = strchr(buf, '\0') - 1;
if (cp >= buf && (*cp == '>' || *cp == '"'))
*cp = '\0';
- t = print_otag(h, TAG_A, "cThI", "In", buf);
+ t = print_otag(h, TAG_A, "chI", "In", buf);
free(buf);
} else
- t = print_otag(h, TAG_A, "cT", "In");
+ t = print_otag(h, TAG_A, "c", "In");
print_text(h, n->string);
print_tagq(h, t);
@@ -1117,7 +1167,7 @@ mdoc_vt_pre(MDOC_ARGS)
} else if (n->type == ROFFT_HEAD)
return 0;
- print_otag(h, TAG_VAR, "cT", "Vt");
+ print_otag(h, TAG_VAR, "c", "Vt");
return 1;
}
@@ -1125,7 +1175,7 @@ static int
mdoc_ft_pre(MDOC_ARGS)
{
synopsis_pre(h, n);
- print_otag(h, TAG_VAR, "cT", "Ft");
+ print_otag(h, TAG_VAR, "c", "Ft");
return 1;
}
@@ -1146,7 +1196,7 @@ mdoc_fn_pre(MDOC_ARGS)
ep = strchr(sp, ' ');
if (NULL != ep) {
- t = print_otag(h, TAG_VAR, "cT", "Ft");
+ t = print_otag(h, TAG_VAR, "c", "Ft");
while (ep) {
sz = MIN((int)(ep - sp), BUFSIZ - 1);
@@ -1159,7 +1209,7 @@ mdoc_fn_pre(MDOC_ARGS)
print_tagq(h, t);
}
- t = print_otag(h, TAG_CODE, "cT", "Fn");
+ t = print_otag(h, TAG_CODE, "c", "Fn");
if (sp)
print_text(h, sp);
@@ -1172,10 +1222,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_VAR, "cTs", "Fa",
+ t = print_otag(h, TAG_VAR, "cs", "Fa",
"white-space", "nowrap");
else
- t = print_otag(h, TAG_VAR, "cT", "Fa");
+ t = print_otag(h, TAG_VAR, "c", "Fa");
print_text(h, n->string);
print_tagq(h, t);
if (n->next) {
@@ -1222,8 +1272,10 @@ mdoc_skip_pre(MDOC_ARGS)
static int
mdoc_pp_pre(MDOC_ARGS)
{
-
- print_paragraph(h);
+ if ((n->flags & NODE_NOFILL) == 0) {
+ html_close_paragraph(h);
+ print_otag(h, TAG_P, "c", "Pp");
+ }
return 0;
}
@@ -1246,7 +1298,7 @@ mdoc_lk_pre(MDOC_ARGS)
descr = link->next;
if (descr == punct)
descr = link; /* no text */
- t = print_otag(h, TAG_A, "cTh", "Lk", link->string);
+ t = print_otag(h, TAG_A, "ch", "Lk", link->string);
do {
if (descr->flags & (NODE_DELIMC | NODE_DELIMO))
h->flags |= HTML_NOSPACE;
@@ -1274,7 +1326,7 @@ mdoc_mt_pre(MDOC_ARGS)
assert(n->type == ROFFT_TEXT);
mandoc_asprintf(&cp, "mailto:%s", n->string);
- t = print_otag(h, TAG_A, "cTh", "Mt", cp);
+ t = print_otag(h, TAG_A, "ch", "Mt", cp);
print_text(h, n->string);
print_tagq(h, t);
free(cp);
@@ -1302,7 +1354,7 @@ mdoc_fo_pre(MDOC_ARGS)
return 0;
assert(n->child->string);
- t = print_otag(h, TAG_CODE, "cT", "Fn");
+ t = print_otag(h, TAG_CODE, "c", "Fn");
print_text(h, n->child->string);
print_tagq(h, t);
return 0;
@@ -1326,7 +1378,7 @@ mdoc_in_pre(MDOC_ARGS)
struct tag *t;
synopsis_pre(h, n);
- print_otag(h, TAG_CODE, "cT", "In");
+ print_otag(h, TAG_CODE, "c", "In");
/*
* The first argument of the `In' gets special treatment as
@@ -1345,9 +1397,9 @@ mdoc_in_pre(MDOC_ARGS)
assert(n->type == ROFFT_TEXT);
if (h->base_includes)
- t = print_otag(h, TAG_A, "cThI", "In", n->string);
+ t = print_otag(h, TAG_A, "chI", "In", n->string);
else
- t = print_otag(h, TAG_A, "cT", "In");
+ t = print_otag(h, TAG_A, "c", "In");
print_text(h, n->string);
print_tagq(h, t);
@@ -1372,14 +1424,14 @@ mdoc_ic_pre(MDOC_ARGS)
if ((id = cond_id(n)) != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "cTi", "Ic", id);
+ print_otag(h, TAG_CODE, "ci", "Ic", id);
return 1;
}
static int
mdoc_va_pre(MDOC_ARGS)
{
- print_otag(h, TAG_VAR, "cT", "Va");
+ print_otag(h, TAG_VAR, "c", "Va");
return 1;
}
@@ -1398,10 +1450,17 @@ mdoc_bf_pre(MDOC_ARGS)
{
const char *cattr;
- if (n->type == ROFFT_HEAD)
- return 0;
- else if (n->type != ROFFT_BODY)
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ html_close_paragraph(h);
return 1;
+ case ROFFT_HEAD:
+ return 0;
+ case ROFFT_BODY:
+ break;
+ default:
+ abort();
+ }
if (FONT_Em == n->norm->Bf.font)
cattr = "Bf Em";
@@ -1424,7 +1483,7 @@ mdoc_ms_pre(MDOC_ARGS)
if ((id = cond_id(n)) != NULL)
print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_SPAN, "cTi", "Ms", id);
+ print_otag(h, TAG_SPAN, "ci", "Ms", id);
return 1;
}
@@ -1447,13 +1506,21 @@ mdoc_pf_post(MDOC_ARGS)
static int
mdoc_rs_pre(MDOC_ARGS)
{
- if (n->type != ROFFT_BLOCK)
- return 1;
-
- if (n->prev && SEC_SEE_ALSO == n->sec)
- print_paragraph(h);
-
- print_otag(h, TAG_CITE, "cT", "Rs");
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ if (n->sec == SEC_SEE_ALSO)
+ html_close_paragraph(h);
+ break;
+ case ROFFT_HEAD:
+ return 0;
+ case ROFFT_BODY:
+ if (n->sec == SEC_SEE_ALSO)
+ print_otag(h, TAG_P, "c", "Pp");
+ print_otag(h, TAG_CITE, "c", "Rs");
+ break;
+ default:
+ abort();
+ }
return 1;
}
@@ -1482,7 +1549,7 @@ mdoc_li_pre(MDOC_ARGS)
static int
mdoc_sy_pre(MDOC_ARGS)
{
- print_otag(h, TAG_B, "cT", "Sy");
+ print_otag(h, TAG_B, "c", "Sy");
return 1;
}
@@ -1492,7 +1559,7 @@ mdoc_lb_pre(MDOC_ARGS)
if (SEC_LIBRARY == n->sec && NODE_LINE & n->flags && n->prev)
print_otag(h, TAG_BR, "");
- print_otag(h, TAG_SPAN, "cT", "Lb");
+ print_otag(h, TAG_SPAN, "c", "Lb");
return 1;
}
@@ -1630,9 +1697,15 @@ mdoc_quote_pre(MDOC_ARGS)
case MDOC_Oo:
case MDOC_Op:
print_text(h, "\\(lB");
- h->flags |= HTML_NOSPACE;
- /* Cannot use TAG_SPAN because it may contain blocks. */
- print_otag(h, TAG_IDIV, "c", "Op");
+ /*
+ * Give up on semantic markup for now.
+ * We cannot use TAG_SPAN because .Oo may contain blocks.
+ * We cannot use TAG_IDIV because we might be in a
+ * phrasing context (like .Dl or .Pp); we cannot
+ * close out a .Pp at this point either because
+ * that would break the line.
+ */
+ /* XXX print_otag(h, TAG_???, "c", "Op"); */
break;
case MDOC_En:
if (NULL == n->norm->Es ||
@@ -1760,3 +1833,9 @@ mdoc_eo_post(MDOC_ARGS)
else if ( ! tail)
h->flags &= ~HTML_NOSPACE;
}
+
+static int
+mdoc_abort_pre(MDOC_ARGS)
+{
+ abort();
+}
diff --git a/mdoc_macro.c b/mdoc_macro.c
index b463d03e225c..3422945814f0 100644
--- a/mdoc_macro.c
+++ b/mdoc_macro.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc_macro.c,v 1.224 2017/05/30 16:22:03 schwarze Exp $ */
+/* $Id: mdoc_macro.c,v 1.232 2019/01/07 07:26:29 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012-2019 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -49,7 +49,7 @@ static void dword(struct roff_man *, int, int, const char *,
static int find_pending(struct roff_man *, enum roff_tok,
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 int macro_or_word(MACRO_PROT_ARGS, char *, int);
static void break_intermediate(struct roff_node *,
struct roff_node *);
static int parse_rest(struct roff_man *, enum roff_tok,
@@ -60,7 +60,7 @@ static void rew_last(struct roff_man *, const struct roff_node *);
static void rew_pending(struct roff_man *,
const struct roff_node *);
-const struct mdoc_macro __mdoc_macros[MDOC_MAX - MDOC_Dd] = {
+static const struct mdoc_macro mdoc_macros[MDOC_MAX - MDOC_Dd] = {
{ in_line_eoln, MDOC_PROLOGUE }, /* Dd */
{ in_line_eoln, MDOC_PROLOGUE }, /* Dt */
{ in_line_eoln, MDOC_PROLOGUE }, /* Os */
@@ -201,9 +201,15 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX - MDOC_Dd] = {
{ in_line_eoln, 0 }, /* %U */
{ phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
};
-const struct mdoc_macro *const mdoc_macros = __mdoc_macros - MDOC_Dd;
+const struct mdoc_macro *
+mdoc_macro(enum roff_tok tok)
+{
+ assert(tok >= MDOC_Dd && tok < MDOC_MAX);
+ return mdoc_macros + (tok - MDOC_Dd);
+}
+
/*
* This is called at the end of parsing. It must traverse up the tree,
* closing out open [implicit] scopes. Obviously, open explicit scopes
@@ -221,14 +227,13 @@ mdoc_endparse(struct roff_man *mdoc)
for ( ; n; n = n->parent)
if (n->type == ROFFT_BLOCK &&
- mdoc_macros[n->tok].flags & MDOC_EXPLICIT)
- mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse,
- n->line, n->pos, roff_name[n->tok]);
+ mdoc_macro(n->tok)->flags & MDOC_EXPLICIT)
+ mandoc_msg(MANDOCERR_BLK_NOEND,
+ n->line, n->pos, "%s", roff_name[n->tok]);
/* Rewind to the first. */
- rew_last(mdoc, mdoc->first);
- mdoc_state_reset(mdoc);
+ rew_last(mdoc, mdoc->meta.first);
}
/*
@@ -244,13 +249,12 @@ lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p)
mdoc->flags &= ~MDOC_PHRASEQF;
return TOKEN_NONE;
}
- if (from == TOKEN_NONE || mdoc_macros[from].flags & MDOC_PARSED) {
+ if (from == TOKEN_NONE || mdoc_macro(from)->flags & MDOC_PARSED) {
res = roffhash_find(mdoc->mdocmac, p, 0);
if (res != TOKEN_NONE) {
- if (mdoc_macros[res].flags & MDOC_CALLABLE)
+ if (mdoc_macro(res)->flags & MDOC_CALLABLE)
return res;
- mandoc_msg(MANDOCERR_MACRO_CALL,
- mdoc->parse, line, ppos, p);
+ mandoc_msg(MANDOCERR_MACRO_CALL, line, ppos, "%s", p);
}
}
return TOKEN_NONE;
@@ -291,6 +295,8 @@ rew_pending(struct roff_man *mdoc, const struct roff_node *n)
case ROFFT_HEAD:
roff_body_alloc(mdoc, n->line, n->pos,
n->tok);
+ if (n->tok == MDOC_Ss)
+ mdoc->flags &= ~ROFF_NONOFILL;
break;
case ROFFT_BLOCK:
break;
@@ -409,16 +415,15 @@ find_pending(struct roff_man *mdoc, enum roff_tok tok, int line, int ppos,
if (n->flags & NODE_ENDED)
continue;
if (n->type == ROFFT_BLOCK &&
- mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {
+ mdoc_macro(n->tok)->flags & MDOC_EXPLICIT) {
irc = 1;
break_intermediate(mdoc->last, target);
if (target->type == ROFFT_HEAD)
target->flags |= NODE_ENDED;
else if ( ! (target->flags & NODE_ENDED)) {
- mandoc_vmsg(MANDOCERR_BLK_NEST,
- mdoc->parse, line, ppos,
- "%s breaks %s", roff_name[tok],
- roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_BLK_NEST,
+ line, ppos, "%s breaks %s",
+ roff_name[tok], roff_name[n->tok]);
mdoc_endbody_alloc(mdoc, line, ppos,
tok, target);
}
@@ -470,14 +475,15 @@ append_delims(struct roff_man *mdoc, int line, int *pos, char *buf)
{
char *p;
int la;
+ enum margserr ac;
if (buf[*pos] == '\0')
return;
for (;;) {
la = *pos;
- if (mdoc_args(mdoc, line, pos, buf, TOKEN_NONE, &p) ==
- ARGS_EOLN)
+ ac = mdoc_args(mdoc, line, pos, buf, TOKEN_NONE, &p);
+ if (ac == ARGS_EOLN)
break;
dword(mdoc, line, la, p, DELIM_MAX, 1);
@@ -495,6 +501,8 @@ append_delims(struct roff_man *mdoc, int line, int *pos, char *buf)
if (mandoc_eos(p, strlen(p)))
mdoc->last->flags |= NODE_EOS;
+ if (ac == ARGS_ALLOC)
+ free(p);
}
}
@@ -504,27 +512,23 @@ append_delims(struct roff_man *mdoc, int line, int *pos, char *buf)
* Otherwise, allocate it and return 0.
*/
static int
-macro_or_word(MACRO_PROT_ARGS, int parsed)
+macro_or_word(MACRO_PROT_ARGS, char *p, int parsed)
{
- char *p;
int ntok;
- p = buf + ppos;
- ntok = TOKEN_NONE;
- if (*p == '"')
- p++;
- else if (parsed && ! (mdoc->flags & MDOC_PHRASELIT))
- ntok = lookup(mdoc, tok, line, ppos, p);
+ ntok = buf[ppos] == '"' || parsed == 0 ||
+ mdoc->flags & MDOC_PHRASELIT ? TOKEN_NONE :
+ lookup(mdoc, tok, line, ppos, p);
if (ntok == TOKEN_NONE) {
dword(mdoc, line, ppos, p, DELIM_MAX, tok == TOKEN_NONE ||
- mdoc_macros[tok].flags & MDOC_JOIN);
+ mdoc_macro(tok)->flags & MDOC_JOIN);
return 0;
} else {
if (tok != TOKEN_NONE &&
- mdoc_macros[tok].fp == in_line_eoln)
+ mdoc_macro(tok)->fp == in_line_eoln)
rew_elem(mdoc, tok);
- mdoc_macro(mdoc, ntok, line, ppos, pos, buf);
+ (*mdoc_macro(ntok)->fp)(mdoc, ntok, line, ppos, pos, buf);
if (tok == TOKEN_NONE)
append_delims(mdoc, line, pos, buf);
return 1;
@@ -629,7 +633,7 @@ blk_exp_close(MACRO_PROT_ARGS)
* the scope - of the current block ends.
*/
- mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse,
+ mandoc_msg(MANDOCERR_BLK_NEST,
line, ppos, "%s breaks %s",
roff_name[atok], roff_name[later->tok]);
@@ -672,8 +676,8 @@ blk_exp_close(MACRO_PROT_ARGS)
}
if (body == NULL) {
- mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse,
- line, ppos, roff_name[tok]);
+ mandoc_msg(MANDOCERR_BLK_NOTOPEN, line, ppos,
+ "%s", roff_name[tok]);
if (maxargs && endbody == NULL) {
/*
* Stray .Ec without previous .Eo:
@@ -688,14 +692,25 @@ blk_exp_close(MACRO_PROT_ARGS)
mdoc_tail_alloc(mdoc, line, ppos, atok);
}
- if ( ! (mdoc_macros[tok].flags & MDOC_PARSED)) {
+ if ((mdoc_macro(tok)->flags & MDOC_PARSED) == 0) {
if (buf[*pos] != '\0')
- mandoc_vmsg(MANDOCERR_ARG_SKIP,
- mdoc->parse, line, ppos,
- "%s %s", roff_name[tok],
- buf + *pos);
+ mandoc_msg(MANDOCERR_ARG_SKIP, line, ppos,
+ "%s %s", roff_name[tok], buf + *pos);
if (endbody == NULL && n != NULL)
rew_pending(mdoc, n);
+
+ /*
+ * Restore the fill mode that was set before the display.
+ * This needs to be done here rather than during validation
+ * such that subsequent nodes get the right flags.
+ */
+
+ if (tok == MDOC_Ed && body != NULL) {
+ if (body->flags & NODE_NOFILL)
+ mdoc->flags |= ROFF_NOFILL;
+ else
+ mdoc->flags &= ~ROFF_NOFILL;
+ }
return;
}
@@ -717,14 +732,18 @@ blk_exp_close(MACRO_PROT_ARGS)
if (ntok == TOKEN_NONE) {
dword(mdoc, line, lastarg, p, DELIM_MAX,
- MDOC_JOIN & mdoc_macros[tok].flags);
+ mdoc_macro(tok)->flags & MDOC_JOIN);
+ if (ac == ARGS_ALLOC)
+ free(p);
continue;
}
+ if (ac == ARGS_ALLOC)
+ free(p);
if (n != NULL)
rew_last(mdoc, n);
mdoc->flags &= ~MDOC_NEWLINE;
- mdoc_macro(mdoc, ntok, line, lastarg, pos, buf);
+ (*mdoc_macro(ntok)->fp)(mdoc, ntok, line, lastarg, pos, buf);
break;
}
@@ -828,12 +847,14 @@ in_line(MACRO_PROT_ARGS)
} else if ( ! nc && ! cnt) {
mdoc_argv_free(arg);
mandoc_msg(MANDOCERR_MACRO_EMPTY,
- mdoc->parse, line, ppos,
- roff_name[tok]);
+ line, ppos, "%s", roff_name[tok]);
}
- mdoc_macro(mdoc, ntok, line, la, pos, buf);
+ (*mdoc_macro(ntok)->fp)(mdoc, ntok,
+ line, la, pos, buf);
if (nl)
append_delims(mdoc, line, pos, buf);
+ if (ac == ARGS_ALLOC)
+ free(p);
return;
}
@@ -875,7 +896,10 @@ in_line(MACRO_PROT_ARGS)
}
dword(mdoc, line, la, p, d,
- mdoc_macros[tok].flags & MDOC_JOIN);
+ mdoc_macro(tok)->flags & MDOC_JOIN);
+
+ if (ac == ARGS_ALLOC)
+ free(p);
/*
* If the first argument is a closing delimiter,
@@ -914,8 +938,8 @@ in_line(MACRO_PROT_ARGS)
rew_last(mdoc, mdoc->last);
} else {
mdoc_argv_free(arg);
- mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
- line, ppos, roff_name[tok]);
+ mandoc_msg(MANDOCERR_MACRO_EMPTY,
+ line, ppos, "%s", roff_name[tok]);
}
}
if (nl)
@@ -927,24 +951,25 @@ in_line(MACRO_PROT_ARGS)
static void
blk_full(MACRO_PROT_ARGS)
{
- int la, nl, parsed;
struct mdoc_arg *arg;
struct roff_node *blk; /* Our own or a broken block. */
struct roff_node *head; /* Our own head. */
struct roff_node *body; /* Our own body. */
struct roff_node *n;
- enum margserr ac, lac;
char *p;
+ size_t iarg;
+ int done, la, nl, parsed;
+ enum margserr ac, lac;
nl = MDOC_NEWLINE & mdoc->flags;
if (buf[*pos] == '\0' && (tok == MDOC_Sh || tok == MDOC_Ss)) {
- mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
- line, ppos, roff_name[tok]);
+ mandoc_msg(MANDOCERR_MACRO_EMPTY,
+ line, ppos, "%s", roff_name[tok]);
return;
}
- if ( ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)) {
+ if ((mdoc_macro(tok)->flags & MDOC_EXPLICIT) == 0) {
/* Here, tok is one of Sh Ss Nm Nd It. */
@@ -960,21 +985,20 @@ blk_full(MACRO_PROT_ARGS)
if (tok == MDOC_It && n->tok == MDOC_Bl) {
if (blk != NULL) {
- mandoc_vmsg(MANDOCERR_BLK_BROKEN,
- mdoc->parse, line, ppos,
- "It breaks %s",
+ mandoc_msg(MANDOCERR_BLK_BROKEN,
+ line, ppos, "It breaks %s",
roff_name[blk->tok]);
rew_pending(mdoc, blk);
}
break;
}
- if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {
+ if (mdoc_macro(n->tok)->flags & MDOC_EXPLICIT) {
switch (tok) {
case MDOC_Sh:
case MDOC_Ss:
- mandoc_vmsg(MANDOCERR_BLK_BROKEN,
- mdoc->parse, line, ppos,
+ mandoc_msg(MANDOCERR_BLK_BROKEN,
+ line, ppos,
"%s breaks %s", roff_name[tok],
roff_name[n->tok]);
rew_pending(mdoc, n);
@@ -1000,8 +1024,7 @@ blk_full(MACRO_PROT_ARGS)
/* Item breaking an explicit block. */
if (blk != NULL) {
- mandoc_vmsg(MANDOCERR_BLK_BROKEN,
- mdoc->parse, line, ppos,
+ mandoc_msg(MANDOCERR_BLK_BROKEN, line, ppos,
"It breaks %s", roff_name[blk->tok]);
rew_pending(mdoc, blk);
blk = NULL;
@@ -1015,7 +1038,7 @@ blk_full(MACRO_PROT_ARGS)
/* Skip items outside lists. */
if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) {
- mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse,
+ mandoc_msg(MANDOCERR_IT_STRAY,
line, ppos, "It %s", buf + *pos);
roff_elem_alloc(mdoc, line, ppos, ROFF_br);
rew_elem(mdoc, ROFF_br);
@@ -1032,6 +1055,16 @@ blk_full(MACRO_PROT_ARGS)
* regular child nodes.
*/
+ switch (tok) {
+ case MDOC_Sh:
+ mdoc->flags &= ~ROFF_NOFILL;
+ break;
+ case MDOC_Ss:
+ mdoc->flags |= ROFF_NONOFILL;
+ break;
+ default:
+ break;
+ }
mdoc_argv(mdoc, line, tok, &arg, pos, buf);
blk = mdoc_block_alloc(mdoc, line, ppos, tok, arg);
head = body = NULL;
@@ -1093,14 +1126,17 @@ blk_full(MACRO_PROT_ARGS)
}
if (tok == MDOC_Bd || tok == MDOC_Bk) {
- mandoc_vmsg(MANDOCERR_ARG_EXCESS,
- mdoc->parse, line, la, "%s ... %s",
- roff_name[tok], buf + la);
+ mandoc_msg(MANDOCERR_ARG_EXCESS, line, la,
+ "%s ... %s", roff_name[tok], buf + la);
+ if (ac == ARGS_ALLOC)
+ free(p);
break;
}
if (tok == MDOC_Rs) {
- mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse,
+ mandoc_msg(MANDOCERR_ARG_SKIP,
line, la, "Rs %s", buf + la);
+ if (ac == ARGS_ALLOC)
+ free(p);
break;
}
if (ac == ARGS_PUNCT)
@@ -1115,6 +1151,8 @@ blk_full(MACRO_PROT_ARGS)
ac != ARGS_PHRASE &&
mdoc_isdelim(p) == DELIM_OPEN) {
dword(mdoc, line, la, p, DELIM_OPEN, 0);
+ if (ac == ARGS_ALLOC)
+ free(p);
continue;
}
@@ -1146,7 +1184,10 @@ blk_full(MACRO_PROT_ARGS)
continue;
}
- if (macro_or_word(mdoc, tok, line, la, pos, buf, parsed))
+ done = macro_or_word(mdoc, tok, line, la, pos, buf, p, parsed);
+ if (ac == ARGS_ALLOC)
+ free(p);
+ if (done)
break;
}
@@ -1165,6 +1206,33 @@ blk_full(MACRO_PROT_ARGS)
rew_last(mdoc, head);
body = roff_body_alloc(mdoc, line, ppos, tok);
+ if (tok == MDOC_Ss)
+ mdoc->flags &= ~ROFF_NONOFILL;
+
+ /*
+ * Set up fill mode for display blocks.
+ * This needs to be done here up front rather than during
+ * validation such that child nodes get the right flags.
+ */
+
+ if (tok == MDOC_Bd && arg != NULL) {
+ for (iarg = 0; iarg < arg->argc; iarg++) {
+ switch (arg->argv[iarg].arg) {
+ case MDOC_Unfilled:
+ case MDOC_Literal:
+ mdoc->flags |= ROFF_NOFILL;
+ break;
+ case MDOC_Filled:
+ case MDOC_Ragged:
+ case MDOC_Centred:
+ mdoc->flags &= ~ROFF_NOFILL;
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
out:
if (mdoc->flags & MDOC_FREECOL) {
rew_last(mdoc, body);
@@ -1176,7 +1244,7 @@ out:
static void
blk_part_imp(MACRO_PROT_ARGS)
{
- int la, nl;
+ int done, la, nl;
enum margserr ac;
char *p;
struct roff_node *blk; /* saved block context */
@@ -1211,13 +1279,18 @@ blk_part_imp(MACRO_PROT_ARGS)
if (body == NULL && mdoc_isdelim(p) == DELIM_OPEN) {
dword(mdoc, line, la, p, DELIM_OPEN, 0);
+ if (ac == ARGS_ALLOC)
+ free(p);
continue;
}
if (body == NULL)
body = roff_body_alloc(mdoc, line, ppos, tok);
- if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))
+ done = macro_or_word(mdoc, tok, line, la, pos, buf, p, 1);
+ if (ac == ARGS_ALLOC)
+ free(p);
+ if (done)
break;
}
if (body == NULL)
@@ -1236,13 +1309,13 @@ blk_part_imp(MACRO_PROT_ARGS)
for (n = body->child; n && n->next; n = n->next)
/* Do nothing. */ ;
if (n && n->tok == MDOC_Ns)
- mdoc_node_relink(mdoc, n);
+ roff_node_relink(mdoc, n);
}
static void
blk_part_exp(MACRO_PROT_ARGS)
{
- int la, nl;
+ int done, la, nl;
enum margserr ac;
struct roff_node *head; /* keep track of head */
char *p;
@@ -1267,6 +1340,8 @@ blk_part_exp(MACRO_PROT_ARGS)
if (head == NULL && mdoc_isdelim(p) == DELIM_OPEN) {
dword(mdoc, line, la, p, DELIM_OPEN, 0);
+ if (ac == ARGS_ALLOC)
+ free(p);
continue;
}
@@ -1276,11 +1351,17 @@ blk_part_exp(MACRO_PROT_ARGS)
dword(mdoc, line, la, p, DELIM_MAX, 0);
rew_last(mdoc, head);
roff_body_alloc(mdoc, line, ppos, tok);
- if (tok == MDOC_Eo)
+ if (tok == MDOC_Eo) {
+ if (ac == ARGS_ALLOC)
+ free(p);
continue;
+ }
}
- if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))
+ done = macro_or_word(mdoc, tok, line, la, pos, buf, p, 1);
+ if (ac == ARGS_ALLOC)
+ free(p);
+ if (done)
break;
}
@@ -1338,10 +1419,12 @@ in_line_argn(MACRO_PROT_ARGS)
la = *pos;
ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
- if (ac == ARGS_WORD && state == -1 &&
- ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) &&
+ if ((ac == ARGS_WORD || ac == ARGS_ALLOC) && state == -1 &&
+ (mdoc_macro(tok)->flags & MDOC_IGNDELIM) == 0 &&
mdoc_isdelim(p) == DELIM_OPEN) {
dword(mdoc, line, la, p, DELIM_OPEN, 0);
+ if (ac == ARGS_ALLOC)
+ free(p);
continue;
}
@@ -1353,8 +1436,8 @@ in_line_argn(MACRO_PROT_ARGS)
if (ac == ARGS_PUNCT || ac == ARGS_EOLN) {
if (abs(state) < 2 && tok == MDOC_Pf)
- mandoc_vmsg(MANDOCERR_PF_SKIP,
- mdoc->parse, line, ppos, "Pf %s",
+ mandoc_msg(MANDOCERR_PF_SKIP,
+ line, ppos, "Pf %s",
p == NULL ? "at eol" : p);
break;
}
@@ -1372,11 +1455,14 @@ in_line_argn(MACRO_PROT_ARGS)
rew_elem(mdoc, tok);
state = -2;
}
- mdoc_macro(mdoc, ntok, line, la, pos, buf);
+ (*mdoc_macro(ntok)->fp)(mdoc, ntok,
+ line, la, pos, buf);
+ if (ac == ARGS_ALLOC)
+ free(p);
break;
}
- if (mdoc_macros[tok].flags & MDOC_IGNDELIM ||
+ if (mdoc_macro(tok)->flags & MDOC_IGNDELIM ||
mdoc_isdelim(p) == DELIM_NONE) {
if (state == -1) {
mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
@@ -1389,12 +1475,15 @@ in_line_argn(MACRO_PROT_ARGS)
}
dword(mdoc, line, la, p, DELIM_MAX,
- mdoc_macros[tok].flags & MDOC_JOIN);
+ mdoc_macro(tok)->flags & MDOC_JOIN);
+ if (ac == ARGS_ALLOC)
+ free(p);
+ p = mdoc->last->string;
}
if (state == -1) {
- mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
- line, ppos, roff_name[tok]);
+ mandoc_msg(MANDOCERR_MACRO_EMPTY,
+ line, ppos, "%s", roff_name[tok]);
return;
}
@@ -1423,8 +1512,8 @@ in_line_eoln(MACRO_PROT_ARGS)
if (buf[*pos] == '\0' &&
(tok == MDOC_Fd || *roff_name[tok] == '%')) {
- mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
- line, ppos, roff_name[tok]);
+ mandoc_msg(MANDOCERR_MACRO_EMPTY,
+ line, ppos, "%s", roff_name[tok]);
return;
}
@@ -1444,13 +1533,19 @@ static int
parse_rest(struct roff_man *mdoc, enum roff_tok tok,
int line, int *pos, char *buf)
{
- int la;
+ char *p;
+ int done, la;
+ enum margserr ac;
for (;;) {
la = *pos;
- if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN)
+ ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
+ if (ac == ARGS_EOLN)
return 0;
- if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))
+ done = macro_or_word(mdoc, tok, line, la, pos, buf, p, 1);
+ if (ac == ARGS_ALLOC)
+ free(p);
+ if (done)
return 1;
}
}
@@ -1492,8 +1587,7 @@ phrase_ta(MACRO_PROT_ARGS)
}
if (n == NULL || n->norm->Bl.type != LIST_column) {
- mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse,
- line, ppos, "Ta");
+ mandoc_msg(MANDOCERR_TA_STRAY, line, ppos, "Ta");
return;
}
diff --git a/mdoc_man.c b/mdoc_man.c
index bcf9207f79cc..2e8f02ae56f2 100644
--- a/mdoc_man.c
+++ b/mdoc_man.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc_man.c,v 1.126 2018/04/11 17:11:13 schwarze Exp $ */
+/* $Id: mdoc_man.c,v 1.132 2019/01/04 03:17:36 schwarze Exp $ */
/*
- * Copyright (c) 2011-2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011-2019 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -36,7 +36,7 @@
typedef int (*int_fp)(DECL_ARGS);
typedef void (*void_fp)(DECL_ARGS);
-struct manact {
+struct mdoc_man_act {
int_fp cond; /* DON'T run actions */
int_fp pre; /* pre-node action */
void_fp post; /* post-node action */
@@ -75,6 +75,7 @@ static void post_pf(DECL_ARGS);
static void post_sect(DECL_ARGS);
static void post_vt(DECL_ARGS);
static int pre__t(DECL_ARGS);
+static int pre_abort(DECL_ARGS);
static int pre_an(DECL_ARGS);
static int pre_ap(DECL_ARGS);
static int pre_aq(DECL_ARGS);
@@ -103,6 +104,7 @@ static int pre_lk(DECL_ARGS);
static int pre_li(DECL_ARGS);
static int pre_nm(DECL_ARGS);
static int pre_no(DECL_ARGS);
+static void pre_noarg(DECL_ARGS);
static int pre_ns(DECL_ARGS);
static void pre_onearg(DECL_ARGS);
static int pre_pp(DECL_ARGS);
@@ -124,12 +126,14 @@ static void print_width(const struct mdoc_bl *,
static void print_count(int *);
static void print_node(DECL_ARGS);
-static const void_fp roff_manacts[ROFF_MAX] = {
+static const void_fp roff_man_acts[ROFF_MAX] = {
pre_br, /* br */
pre_onearg, /* ce */
+ pre_noarg, /* fi */
pre_ft, /* ft */
pre_onearg, /* ll */
pre_onearg, /* mc */
+ pre_noarg, /* nf */
pre_onearg, /* po */
pre_onearg, /* rj */
pre_sp, /* sp */
@@ -137,7 +141,7 @@ static const void_fp roff_manacts[ROFF_MAX] = {
pre_onearg, /* ti */
};
-static const struct manact __manacts[MDOC_MAX - MDOC_Dd] = {
+static const struct mdoc_man_act mdoc_man_acts[MDOC_MAX - MDOC_Dd] = {
{ NULL, NULL, NULL, NULL, NULL }, /* Dd */
{ NULL, NULL, NULL, NULL, NULL }, /* Dt */
{ NULL, NULL, NULL, NULL, NULL }, /* Os */
@@ -172,7 +176,7 @@ static const struct manact __manacts[MDOC_MAX - MDOC_Dd] = {
{ cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
{ NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
- { NULL, pre_Ft, post_font, NULL, NULL }, /* Ot */
+ { NULL, pre_abort, NULL, NULL, NULL }, /* Ot */
{ NULL, pre_em, post_font, NULL, NULL }, /* Pa */
{ NULL, pre_ex, NULL, NULL, NULL }, /* Rv */
{ NULL, NULL, NULL, NULL, NULL }, /* St */
@@ -245,7 +249,7 @@ static const struct manact __manacts[MDOC_MAX - MDOC_Dd] = {
{ NULL, pre_em, post_font, NULL, NULL }, /* Fr */
{ NULL, NULL, NULL, NULL, NULL }, /* Ud */
{ NULL, NULL, post_lb, NULL, NULL }, /* Lb */
- { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
+ { NULL, pre_abort, NULL, NULL, NULL }, /* Lp */
{ NULL, pre_lk, NULL, NULL, NULL }, /* Lk */
{ NULL, pre_em, post_font, NULL, NULL }, /* Mt */
{ cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */
@@ -259,7 +263,7 @@ static const struct manact __manacts[MDOC_MAX - MDOC_Dd] = {
{ NULL, NULL, post_percent, NULL, NULL }, /* %U */
{ NULL, NULL, NULL, NULL, NULL }, /* Ta */
};
-static const struct manact *const manacts = __manacts - MDOC_Dd;
+static const struct mdoc_man_act *mdoc_man_act(enum roff_tok);
static int outflags;
#define MMAN_spc (1 << 0) /* blank character before next word */
@@ -290,6 +294,13 @@ static struct {
} fontqueue;
+static const struct mdoc_man_act *
+mdoc_man_act(enum roff_tok tok)
+{
+ assert(tok >= MDOC_Dd && tok <= MDOC_MAX);
+ return mdoc_man_acts + (tok - MDOC_Dd);
+}
+
static int
man_strlen(const char *cp)
{
@@ -317,6 +328,7 @@ man_strlen(const char *cp)
case ESCAPE_UNICODE:
case ESCAPE_NUMBERED:
case ESCAPE_SPECIAL:
+ case ESCAPE_UNDEF:
case ESCAPE_OVERSTRIKE:
if (skip)
skip = 0;
@@ -593,20 +605,7 @@ print_count(int *count)
}
void
-man_man(void *arg, const struct roff_man *man)
-{
-
- /*
- * Dump the keep buffer.
- * We're guaranteed by now that this exists (is non-NULL).
- * Flush stdout afterward, just in case.
- */
- fputs(mparse_getkeep(man_mparse(man)), stdout);
- fflush(stdout);
-}
-
-void
-man_mdoc(void *arg, const struct roff_man *mdoc)
+man_mdoc(void *arg, const struct roff_meta *mdoc)
{
struct roff_node *n;
@@ -619,9 +618,8 @@ man_mdoc(void *arg, const struct roff_man *mdoc)
}
printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
- mdoc->meta.title,
- (mdoc->meta.msec == NULL ? "" : mdoc->meta.msec),
- mdoc->meta.date, mdoc->meta.os, mdoc->meta.vol);
+ mdoc->title, (mdoc->msec == NULL ? "" : mdoc->msec),
+ mdoc->date, mdoc->os, mdoc->vol);
/* Disable hyphenation and if nroff, disable justification. */
printf(".nh\n.if n .ad l");
@@ -633,16 +631,16 @@ man_mdoc(void *arg, const struct roff_man *mdoc)
*fontqueue.tail = 'R';
}
for (; n != NULL; n = n->next)
- print_node(&mdoc->meta, n);
+ print_node(mdoc, n);
putchar('\n');
}
static void
print_node(DECL_ARGS)
{
- const struct manact *act;
- struct roff_node *sub;
- int cond, do_sub;
+ const struct mdoc_man_act *act;
+ struct roff_node *sub;
+ int cond, do_sub;
if (n->flags & NODE_NOPRT)
return;
@@ -680,15 +678,14 @@ print_node(DECL_ARGS)
else if (outflags & MMAN_Sm)
outflags |= MMAN_spc;
} else if (n->tok < ROFF_MAX) {
- (*roff_manacts[n->tok])(meta, n);
+ (*roff_man_acts[n->tok])(meta, n);
return;
} else {
- assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
/*
* Conditionally run the pre-node action handler for a
* node.
*/
- act = manacts + n->tok;
+ act = mdoc_man_act(n->tok);
cond = act->cond == NULL || (*act->cond)(meta, n);
if (cond && act->pre != NULL &&
(n->end == ENDBODY_NOT || n->child != NULL))
@@ -732,11 +729,17 @@ cond_body(DECL_ARGS)
}
static int
+pre_abort(DECL_ARGS)
+{
+ abort();
+}
+
+static int
pre_enc(DECL_ARGS)
{
const char *prefix;
- prefix = manacts[n->tok].prefix;
+ prefix = mdoc_man_act(n->tok)->prefix;
if (NULL == prefix)
return 1;
print_word(prefix);
@@ -749,7 +752,7 @@ post_enc(DECL_ARGS)
{
const char *suffix;
- suffix = manacts[n->tok].suffix;
+ suffix = mdoc_man_act(n->tok)->suffix;
if (NULL == suffix)
return;
outflags &= ~(MMAN_spc | MMAN_nl);
@@ -774,7 +777,7 @@ static void
post_percent(DECL_ARGS)
{
- if (pre_em == manacts[n->tok].pre)
+ if (mdoc_man_act(n->tok)->pre == pre_em)
font_pop();
if (n->next) {
print_word(",");
@@ -820,7 +823,7 @@ pre_sect(DECL_ARGS)
if (n->type == ROFFT_HEAD) {
outflags |= MMAN_sp;
- print_block(manacts[n->tok].prefix, 0);
+ print_block(mdoc_man_act(n->tok)->prefix, 0);
print_word("");
putchar('\"');
outflags &= ~MMAN_spc;
@@ -936,7 +939,6 @@ post_aq(DECL_ARGS)
static int
pre_bd(DECL_ARGS)
{
-
outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br);
if (DISP_unfilled == n->norm->Bd.type ||
@@ -951,12 +953,27 @@ pre_bd(DECL_ARGS)
static void
post_bd(DECL_ARGS)
{
+ enum roff_tok bef, now;
/* Close out this display. */
print_line(".RE", MMAN_nl);
- if (DISP_unfilled == n->norm->Bd.type ||
- DISP_literal == n->norm->Bd.type)
- print_line(".fi", MMAN_nl);
+ bef = n->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi;
+ if (n->last == NULL)
+ now = n->norm->Bd.type == DISP_unfilled ||
+ n->norm->Bd.type == DISP_literal ? ROFF_nf : ROFF_fi;
+ else if (n->last->tok == ROFF_nf)
+ now = ROFF_nf;
+ else if (n->last->tok == ROFF_fi)
+ now = ROFF_fi;
+ else
+ now = n->last->flags & NODE_NOFILL ? ROFF_nf : ROFF_fi;
+ if (bef != now) {
+ outflags |= MMAN_nl;
+ print_word(".");
+ outflags &= ~MMAN_spc;
+ print_word(roff_name[bef]);
+ outflags |= MMAN_nl;
+ }
/* Maybe we are inside an enclosing list? */
if (NULL != n->parent->next)
@@ -1607,7 +1624,6 @@ pre_onearg(DECL_ARGS)
static int
pre_li(DECL_ARGS)
{
-
font_push('R');
return 1;
}
@@ -1640,7 +1656,6 @@ pre_nm(DECL_ARGS)
static void
post_nm(DECL_ARGS)
{
-
switch (n->type) {
case ROFFT_BLOCK:
outflags &= ~MMAN_Bk;
@@ -1658,15 +1673,23 @@ post_nm(DECL_ARGS)
static int
pre_no(DECL_ARGS)
{
-
outflags |= MMAN_spc_force;
return 1;
}
+static void
+pre_noarg(DECL_ARGS)
+{
+ outflags |= MMAN_nl;
+ print_word(".");
+ outflags &= ~MMAN_spc;
+ print_word(roff_name[n->tok]);
+ outflags |= MMAN_nl;
+}
+
static int
pre_ns(DECL_ARGS)
{
-
outflags &= ~MMAN_spc;
return 0;
}
diff --git a/mdoc_markdown.c b/mdoc_markdown.c
index e73440a4e5cd..e9a931218cc4 100644
--- a/mdoc_markdown.c
+++ b/mdoc_markdown.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc_markdown.c,v 1.24 2018/04/11 17:11:13 schwarze Exp $ */
+/* $Id: mdoc_markdown.c,v 1.30 2018/12/30 00:49:55 schwarze Exp $ */
/*
- * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2017, 2018 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
@@ -19,6 +19,7 @@
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include "mandoc_aux.h"
@@ -48,6 +49,7 @@ static void md_uri(const char *);
static int md_cond_head(struct roff_node *);
static int md_cond_body(struct roff_node *);
+static int md_pre_abort(struct roff_node *);
static int md_pre_raw(struct roff_node *);
static int md_pre_word(struct roff_node *);
static int md_pre_skip(struct roff_node *);
@@ -103,7 +105,7 @@ static void md_post_Pf(struct roff_node *);
static void md_post_Vt(struct roff_node *);
static void md_post__T(struct roff_node *);
-static const struct md_act __md_acts[MDOC_MAX - MDOC_Dd] = {
+static const struct md_act md_acts[MDOC_MAX - MDOC_Dd] = {
{ NULL, NULL, NULL, NULL, NULL }, /* Dd */
{ NULL, NULL, NULL, NULL, NULL }, /* Dt */
{ NULL, NULL, NULL, NULL, NULL }, /* Os */
@@ -138,7 +140,7 @@ static const struct md_act __md_acts[MDOC_MAX - MDOC_Dd] = {
{ md_cond_head, md_pre_Nd, NULL, NULL, NULL }, /* Nd */
{ NULL, md_pre_Nm, md_post_Nm, "**", "**" }, /* Nm */
{ md_cond_body, md_pre_word, md_post_word, "[", "]" }, /* Op */
- { NULL, md_pre_Fd, md_post_raw, "*", "*" }, /* Ot */
+ { NULL, md_pre_abort, NULL, NULL, NULL }, /* Ot */
{ NULL, md_pre_raw, md_post_raw, "*", "*" }, /* Pa */
{ NULL, NULL, NULL, NULL, NULL }, /* Rv */
{ NULL, NULL, NULL, NULL, NULL }, /* St */
@@ -211,7 +213,7 @@ static const struct md_act __md_acts[MDOC_MAX - MDOC_Dd] = {
{ NULL, md_pre_raw, md_post_raw, "*", "*" }, /* Fr */
{ NULL, NULL, NULL, NULL, NULL }, /* Ud */
{ NULL, NULL, md_post_Lb, NULL, NULL }, /* Lb */
- { NULL, md_pre_Pp, NULL, NULL, NULL }, /* Lp */
+ { NULL, md_pre_abort, NULL, NULL, NULL }, /* Lp */
{ NULL, md_pre_Lk, NULL, NULL, NULL }, /* Lk */
{ NULL, md_pre_Mt, NULL, NULL, NULL }, /* Mt */
{ md_cond_body, md_pre_word, md_post_word, "{", "}" }, /* Brq */
@@ -225,7 +227,7 @@ static const struct md_act __md_acts[MDOC_MAX - MDOC_Dd] = {
{ NULL, md_pre_Lk, md_post_pc, NULL, NULL }, /* %U */
{ NULL, NULL, NULL, NULL, NULL }, /* Ta */
};
-static const struct md_act *const md_acts = __md_acts - MDOC_Dd;
+static const struct md_act *md_act(enum roff_tok);
static int outflags;
#define MD_spc (1 << 0) /* Blank character before next word. */
@@ -250,22 +252,30 @@ static int escflags; /* Escape in generated markdown code: */
static int code_blocks, quote_blocks, list_blocks;
static int outcount;
+
+static const struct md_act *
+md_act(enum roff_tok tok)
+{
+ assert(tok >= MDOC_Dd && tok <= MDOC_MAX);
+ return md_acts + (tok - MDOC_Dd);
+}
+
void
-markdown_mdoc(void *arg, const struct roff_man *mdoc)
+markdown_mdoc(void *arg, const struct roff_meta *mdoc)
{
outflags = MD_Sm;
- md_word(mdoc->meta.title);
- if (mdoc->meta.msec != NULL) {
+ md_word(mdoc->title);
+ if (mdoc->msec != NULL) {
outflags &= ~MD_spc;
md_word("(");
- md_word(mdoc->meta.msec);
+ md_word(mdoc->msec);
md_word(")");
}
md_word("-");
- md_word(mdoc->meta.vol);
- if (mdoc->meta.arch != NULL) {
+ md_word(mdoc->vol);
+ if (mdoc->arch != NULL) {
md_word("(");
- md_word(mdoc->meta.arch);
+ md_word(mdoc->arch);
md_word(")");
}
outflags |= MD_sp;
@@ -273,9 +283,9 @@ markdown_mdoc(void *arg, const struct roff_man *mdoc)
md_nodelist(mdoc->first->child);
outflags |= MD_sp;
- md_word(mdoc->meta.os);
+ md_word(mdoc->os);
md_word("-");
- md_word(mdoc->meta.date);
+ md_word(mdoc->date);
putchar('\n');
}
@@ -330,8 +340,7 @@ md_node(struct roff_node *n)
break;
}
} else {
- assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
- act = md_acts + n->tok;
+ act = md_act(n->tok);
cond = act->cond == NULL || (*act->cond)(n);
if (cond && act->pre != NULL &&
(n->end == ENDBODY_NOT || n->child != NULL))
@@ -580,6 +589,12 @@ md_word(const char *s)
case ESCAPE_SPECIAL:
uc = mchars_spec2cp(seq, sz);
break;
+ case ESCAPE_UNDEF:
+ uc = *seq;
+ break;
+ case ESCAPE_DEVICE:
+ md_rawword("markdown");
+ continue;
case ESCAPE_FONTBOLD:
nextfont = "**";
break;
@@ -590,6 +605,7 @@ md_word(const char *s)
nextfont = "***";
break;
case ESCAPE_FONT:
+ case ESCAPE_FONTCW:
case ESCAPE_FONTROMAN:
nextfont = "";
break;
@@ -712,11 +728,17 @@ md_cond_body(struct roff_node *n)
}
static int
+md_pre_abort(struct roff_node *n)
+{
+ abort();
+}
+
+static int
md_pre_raw(struct roff_node *n)
{
const char *prefix;
- if ((prefix = md_acts[n->tok].prefix) != NULL) {
+ if ((prefix = md_act(n->tok)->prefix) != NULL) {
md_rawword(prefix);
outflags &= ~MD_spc;
if (*prefix == '`')
@@ -730,7 +752,7 @@ md_post_raw(struct roff_node *n)
{
const char *suffix;
- if ((suffix = md_acts[n->tok].suffix) != NULL) {
+ if ((suffix = md_act(n->tok)->suffix) != NULL) {
outflags &= ~(MD_spc | MD_nl);
md_rawword(suffix);
if (*suffix == '`')
@@ -743,7 +765,7 @@ md_pre_word(struct roff_node *n)
{
const char *prefix;
- if ((prefix = md_acts[n->tok].prefix) != NULL) {
+ if ((prefix = md_act(n->tok)->prefix) != NULL) {
md_word(prefix);
outflags &= ~MD_spc;
}
@@ -755,7 +777,7 @@ md_post_word(struct roff_node *n)
{
const char *suffix;
- if ((suffix = md_acts[n->tok].suffix) != NULL) {
+ if ((suffix = md_act(n->tok)->suffix) != NULL) {
outflags &= ~(MD_spc | MD_nl);
md_word(suffix);
}
diff --git a/mdoc_state.c b/mdoc_state.c
index 2d8563f5bf16..f9a585e73623 100644
--- a/mdoc_state.c
+++ b/mdoc_state.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_state.c,v 1.9 2017/11/29 20:05:33 schwarze Exp $ */
+/* $Id: mdoc_state.c,v 1.15 2019/01/01 07:42:04 schwarze Exp $ */
/*
* Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -17,6 +17,7 @@
#include <sys/types.h>
#include <assert.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -24,19 +25,18 @@
#include "roff.h"
#include "mdoc.h"
#include "libmandoc.h"
+#include "roff_int.h"
#include "libmdoc.h"
#define STATE_ARGS struct roff_man *mdoc, struct roff_node *n
typedef void (*state_handler)(STATE_ARGS);
-static void state_bd(STATE_ARGS);
static void state_bl(STATE_ARGS);
-static void state_dl(STATE_ARGS);
static void state_sh(STATE_ARGS);
static void state_sm(STATE_ARGS);
-static const state_handler __state_handlers[MDOC_MAX - MDOC_Dd] = {
+static const state_handler state_handlers[MDOC_MAX - MDOC_Dd] = {
NULL, /* Dd */
NULL, /* Dt */
NULL, /* Os */
@@ -44,8 +44,8 @@ static const state_handler __state_handlers[MDOC_MAX - MDOC_Dd] = {
NULL, /* Ss */
NULL, /* Pp */
NULL, /* D1 */
- state_dl, /* Dl */
- state_bd, /* Bd */
+ NULL, /* Dl */
+ NULL, /* Bd */
NULL, /* Ed */
state_bl, /* Bl */
NULL, /* El */
@@ -158,7 +158,6 @@ static const state_handler __state_handlers[MDOC_MAX - MDOC_Dd] = {
NULL, /* %U */
NULL, /* Ta */
};
-static const state_handler *const state_handlers = __state_handlers - MDOC_Dd;
void
@@ -170,41 +169,14 @@ mdoc_state(struct roff_man *mdoc, struct roff_node *n)
return;
assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
- if ( ! (mdoc_macros[n->tok].flags & MDOC_PROLOGUE))
+ if ((mdoc_macro(n->tok)->flags & MDOC_PROLOGUE) == 0)
mdoc->flags |= MDOC_PBODY;
- handler = state_handlers[n->tok];
+ handler = state_handlers[n->tok - MDOC_Dd];
if (*handler)
(*handler)(mdoc, n);
}
-void
-mdoc_state_reset(struct roff_man *mdoc)
-{
-
- roff_setreg(mdoc->roff, "nS", 0, '=');
- mdoc->flags = 0;
-}
-
-static void
-state_bd(STATE_ARGS)
-{
- enum mdocargt arg;
-
- if (n->type != ROFFT_HEAD &&
- (n->type != ROFFT_BODY || n->end != ENDBODY_NOT))
- return;
-
- if (n->parent->args == NULL)
- return;
-
- arg = n->parent->args->argv[0].arg;
- if (arg != MDOC_Literal && arg != MDOC_Unfilled)
- return;
-
- state_dl(mdoc, n);
-}
-
static void
state_bl(STATE_ARGS)
{
@@ -230,22 +202,6 @@ state_bl(STATE_ARGS)
}
static void
-state_dl(STATE_ARGS)
-{
-
- switch (n->type) {
- case ROFFT_HEAD:
- mdoc->flags |= MDOC_LITERAL;
- break;
- case ROFFT_BODY:
- mdoc->flags &= ~MDOC_LITERAL;
- break;
- default:
- break;
- }
-}
-
-static void
state_sh(STATE_ARGS)
{
struct roff_node *nch;
diff --git a/mdoc_term.c b/mdoc_term.c
index cf3e7ef3dd64..52ff27e17f11 100644
--- a/mdoc_term.c
+++ b/mdoc_term.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc_term.c,v 1.367 2018/04/11 17:11:13 schwarze Exp $ */
+/* $Id: mdoc_term.c,v 1.372 2019/01/04 03:39:01 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012-2019 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -29,7 +29,6 @@
#include <string.h>
#include "mandoc_aux.h"
-#include "mandoc.h"
#include "roff.h"
#include "mdoc.h"
#include "out.h"
@@ -47,7 +46,7 @@ struct termpair {
const struct roff_meta *meta, \
struct roff_node *n
-struct termact {
+struct mdoc_term_act {
int (*pre)(DECL_ARGS);
void (*post)(DECL_ARGS);
};
@@ -84,6 +83,7 @@ static void termp_xx_post(DECL_ARGS);
static int termp__a_pre(DECL_ARGS);
static int termp__t_pre(DECL_ARGS);
+static int termp_abort_pre(DECL_ARGS);
static int termp_an_pre(DECL_ARGS);
static int termp_ap_pre(DECL_ARGS);
static int termp_bd_pre(DECL_ARGS);
@@ -124,7 +124,7 @@ static int termp_vt_pre(DECL_ARGS);
static int termp_xr_pre(DECL_ARGS);
static int termp_xx_pre(DECL_ARGS);
-static const struct termact __termacts[MDOC_MAX - MDOC_Dd] = {
+static const struct mdoc_term_act mdoc_term_acts[MDOC_MAX - MDOC_Dd] = {
{ NULL, NULL }, /* Dd */
{ NULL, NULL }, /* Dt */
{ NULL, NULL }, /* Os */
@@ -159,7 +159,7 @@ static const struct termact __termacts[MDOC_MAX - MDOC_Dd] = {
{ termp_nd_pre, NULL }, /* Nd */
{ termp_nm_pre, termp_nm_post }, /* Nm */
{ termp_quote_pre, termp_quote_post }, /* Op */
- { termp_ft_pre, NULL }, /* Ot */
+ { termp_abort_pre, NULL }, /* Ot */
{ termp_under_pre, NULL }, /* Pa */
{ termp_ex_pre, NULL }, /* Rv */
{ NULL, NULL }, /* St */
@@ -232,7 +232,7 @@ static const struct termact __termacts[MDOC_MAX - MDOC_Dd] = {
{ termp_under_pre, NULL }, /* Fr */
{ NULL, NULL }, /* Ud */
{ NULL, termp_lb_post }, /* Lb */
- { termp_pp_pre, NULL }, /* Lp */
+ { termp_abort_pre, NULL }, /* Lp */
{ termp_lk_pre, NULL }, /* Lk */
{ termp_under_pre, NULL }, /* Mt */
{ termp_quote_pre, termp_quote_post }, /* Brq */
@@ -246,13 +246,12 @@ static const struct termact __termacts[MDOC_MAX - MDOC_Dd] = {
{ NULL, termp____post }, /* %U */
{ NULL, NULL }, /* Ta */
};
-static const struct termact *const termacts = __termacts - MDOC_Dd;
static int fn_prio;
void
-terminal_mdoc(void *arg, const struct roff_man *mdoc)
+terminal_mdoc(void *arg, const struct roff_meta *mdoc)
{
struct roff_node *n;
struct termp *p;
@@ -270,8 +269,7 @@ terminal_mdoc(void *arg, const struct roff_man *mdoc)
if (n->tok == MDOC_Sh && n->sec == SEC_SYNOPSIS) {
if (n->child->next->child != NULL)
print_mdoc_nodelist(p, NULL,
- &mdoc->meta,
- n->child->next->child);
+ mdoc, n->child->next->child);
term_newln(p);
break;
}
@@ -281,8 +279,7 @@ terminal_mdoc(void *arg, const struct roff_man *mdoc)
save_defindent = p->defindent;
if (p->defindent == 0)
p->defindent = 5;
- term_begin(p, print_mdoc_head, print_mdoc_foot,
- &mdoc->meta);
+ term_begin(p, print_mdoc_head, print_mdoc_foot, mdoc);
while (n != NULL &&
(n->type == ROFFT_COMMENT ||
n->flags & NODE_NOPRT))
@@ -290,7 +287,7 @@ terminal_mdoc(void *arg, const struct roff_man *mdoc)
if (n != NULL) {
if (n->tok != MDOC_Sh)
term_vspace(p);
- print_mdoc_nodelist(p, NULL, &mdoc->meta, n);
+ print_mdoc_nodelist(p, NULL, mdoc, n);
}
term_end(p);
p->defindent = save_defindent;
@@ -310,9 +307,23 @@ print_mdoc_nodelist(DECL_ARGS)
static void
print_mdoc_node(DECL_ARGS)
{
- int chld;
+ const struct mdoc_term_act *act;
struct termpair npair;
size_t offset, rmargin;
+ int chld;
+
+ /*
+ * In no-fill mode, break the output line at the beginning
+ * of new input lines except after \c, and nowhere else.
+ */
+
+ if (n->flags & NODE_NOFILL) {
+ if (n->flags & NODE_LINE &&
+ (p->flags & TERMP_NONEWLINE) == 0)
+ term_newln(p);
+ p->flags |= TERMP_BRNEVER;
+ } else
+ p->flags &= ~TERMP_BRNEVER;
if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
return;
@@ -343,9 +354,22 @@ print_mdoc_node(DECL_ARGS)
switch (n->type) {
case ROFFT_TEXT:
- if (*n->string == ' ' && n->flags & NODE_LINE &&
- (p->flags & TERMP_NONEWLINE) == 0)
- term_newln(p);
+ if (n->flags & NODE_LINE) {
+ switch (*n->string) {
+ case '\0':
+ if (p->flags & TERMP_NONEWLINE)
+ term_newln(p);
+ else
+ term_vspace(p);
+ return;
+ case ' ':
+ if ((p->flags & TERMP_NONEWLINE) == 0)
+ term_newln(p);
+ break;
+ default:
+ break;
+ }
+ }
if (NODE_DELIMC & n->flags)
p->flags |= TERMP_NOSPACE;
term_word(p, n->string);
@@ -370,10 +394,10 @@ print_mdoc_node(DECL_ARGS)
return;
}
assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
- if (termacts[n->tok].pre != NULL &&
+ act = mdoc_term_acts + (n->tok - MDOC_Dd);
+ if (act->pre != NULL &&
(n->end == ENDBODY_NOT || n->child != NULL))
- chld = (*termacts[n->tok].pre)
- (p, &npair, meta, n);
+ chld = (*act->pre)(p, &npair, meta, n);
break;
}
@@ -391,9 +415,9 @@ print_mdoc_node(DECL_ARGS)
case ROFFT_EQN:
break;
default:
- if (termacts[n->tok].post == NULL || n->flags & NODE_ENDED)
+ if (act->post == NULL || n->flags & NODE_ENDED)
break;
- (void)(*termacts[n->tok].post)(p, &npair, meta, n);
+ (void)(*act->post)(p, &npair, meta, n);
/*
* Explicit end tokens not only call the post
@@ -1420,8 +1444,6 @@ termp_fa_pre(DECL_ARGS)
static int
termp_bd_pre(DECL_ARGS)
{
- size_t lm, len;
- struct roff_node *nn;
int offset;
if (n->type == ROFFT_BLOCK) {
@@ -1447,66 +1469,19 @@ termp_bd_pre(DECL_ARGS)
p->tcol->offset += offset;
}
- /*
- * If -ragged or -filled are specified, the block does nothing
- * but change the indentation. If -unfilled or -literal are
- * specified, text is printed exactly as entered in the display:
- * for macro lines, a newline is appended to the line. Blank
- * lines are allowed.
- */
-
- if (n->norm->Bd.type != DISP_literal &&
- n->norm->Bd.type != DISP_unfilled &&
- n->norm->Bd.type != DISP_centered)
- return 1;
-
- if (n->norm->Bd.type == DISP_literal) {
+ switch (n->norm->Bd.type) {
+ case DISP_literal:
term_tab_set(p, NULL);
term_tab_set(p, "T");
term_tab_set(p, "8n");
+ break;
+ case DISP_centered:
+ p->flags |= TERMP_CENTER;
+ break;
+ default:
+ break;
}
-
- lm = p->tcol->offset;
- p->flags |= TERMP_BRNEVER;
- for (nn = n->child; nn != NULL; nn = nn->next) {
- if (n->norm->Bd.type == DISP_centered) {
- if (nn->type == ROFFT_TEXT) {
- len = term_strlen(p, nn->string);
- p->tcol->offset = len >= p->tcol->rmargin ?
- 0 : lm + len >= p->tcol->rmargin ?
- p->tcol->rmargin - len :
- (lm + p->tcol->rmargin - len) / 2;
- } else
- p->tcol->offset = lm;
- }
- print_mdoc_node(p, pair, meta, nn);
- /*
- * If the printed node flushes its own line, then we
- * needn't do it here as well. This is hacky, but the
- * notion of selective eoln whitespace is pretty dumb
- * anyway, so don't sweat it.
- */
- if (nn->tok < ROFF_MAX)
- continue;
- switch (nn->tok) {
- case MDOC_Sm:
- case MDOC_Bl:
- case MDOC_D1:
- case MDOC_Dl:
- case MDOC_Lp:
- case MDOC_Pp:
- continue;
- default:
- break;
- }
- if (p->flags & TERMP_NONEWLINE ||
- (nn->next && ! (nn->next->flags & NODE_LINE)))
- continue;
- term_flushln(p);
- p->flags |= TERMP_NOSPACE;
- }
- p->flags &= ~TERMP_BRNEVER;
- return 0;
+ return 1;
}
static void
@@ -1514,12 +1489,14 @@ termp_bd_post(DECL_ARGS)
{
if (n->type != ROFFT_BODY)
return;
- if (DISP_literal == n->norm->Bd.type ||
- DISP_unfilled == n->norm->Bd.type)
+ if (n->norm->Bd.type == DISP_unfilled ||
+ n->norm->Bd.type == DISP_literal)
p->flags |= TERMP_BRNEVER;
p->flags |= TERMP_NOSPACE;
term_newln(p);
p->flags &= ~TERMP_BRNEVER;
+ if (n->norm->Bd.type == DISP_centered)
+ p->flags &= ~TERMP_CENTER;
}
static int
@@ -2098,3 +2075,9 @@ termp_tag_pre(DECL_ARGS)
tag_put(n->child->string, 1, p->line);
return 1;
}
+
+static int
+termp_abort_pre(DECL_ARGS)
+{
+ abort();
+}
diff --git a/mdoc_validate.c b/mdoc_validate.c
index b36d3c0a926c..7d1575f2f0f1 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc_validate.c,v 1.360 2018/08/01 16:00:58 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.371 2019/03/04 13:01:57 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -64,6 +64,7 @@ static size_t macro2len(enum roff_tok);
static void rewrite_macro2len(struct roff_man *, char **);
static int similar(const char *, const char *);
+static void post_abort(POST_ARGS);
static void post_an(POST_ARGS);
static void post_an_norm(POST_ARGS);
static void post_at(POST_ARGS);
@@ -116,7 +117,7 @@ static void post_useless(POST_ARGS);
static void post_xr(POST_ARGS);
static void post_xx(POST_ARGS);
-static const v_post __mdoc_valids[MDOC_MAX - MDOC_Dd] = {
+static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = {
post_dd, /* Dd */
post_dt, /* Dt */
post_os, /* Os */
@@ -151,7 +152,7 @@ static const v_post __mdoc_valids[MDOC_MAX - MDOC_Dd] = {
post_nd, /* Nd */
post_nm, /* Nm */
post_delim_nb, /* Op */
- post_obsolete, /* Ot */
+ post_abort, /* Ot */
post_defaults, /* Pa */
post_rv, /* Rv */
post_st, /* St */
@@ -224,7 +225,7 @@ static const v_post __mdoc_valids[MDOC_MAX - MDOC_Dd] = {
post_obsolete, /* Fr */
post_eoln, /* Ud */
post_lb, /* Lb */
- post_par, /* Lp */
+ post_abort, /* Lp */
post_delim_nb, /* Lk */
post_defaults, /* Mt */
post_delim_nb, /* Brq */
@@ -238,7 +239,6 @@ static const v_post __mdoc_valids[MDOC_MAX - MDOC_Dd] = {
NULL, /* %U */
NULL, /* Ta */
};
-static const v_post *const mdoc_valids = __mdoc_valids - MDOC_Dd;
#define RSORD_MAX 14 /* Number of `Rs' blocks. */
@@ -286,22 +286,48 @@ static const char * const secnames[SEC__MAX] = {
};
+/* Validate the subtree rooted at mdoc->last. */
void
-mdoc_node_validate(struct roff_man *mdoc)
+mdoc_validate(struct roff_man *mdoc)
{
struct roff_node *n, *np;
const v_post *p;
+ /*
+ * Translate obsolete macros to modern macros first
+ * such that later code does not need to look
+ * for the obsolete versions.
+ */
+
n = mdoc->last;
+ switch (n->tok) {
+ case MDOC_Lp:
+ n->tok = MDOC_Pp;
+ break;
+ case MDOC_Ot:
+ post_obsolete(mdoc);
+ n->tok = MDOC_Ft;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Iterate over all children, recursing into each one
+ * in turn, depth-first.
+ */
+
mdoc->last = mdoc->last->child;
while (mdoc->last != NULL) {
- mdoc_node_validate(mdoc);
+ mdoc_validate(mdoc);
if (mdoc->last == n)
mdoc->last = mdoc->last->child;
else
mdoc->last = mdoc->last->next;
}
+ /* Finally validate the macro itself. */
+
mdoc->last = n;
mdoc->next = ROFF_NEXT_SIBLING;
switch (n->type) {
@@ -310,9 +336,7 @@ mdoc_node_validate(struct roff_man *mdoc)
if (n->sec != SEC_SYNOPSIS ||
(np->tok != MDOC_Cd && np->tok != MDOC_Fd))
check_text(mdoc, n->line, n->pos, n->string);
- if (np->tok != MDOC_Ql && np->tok != MDOC_Dl &&
- (np->tok != MDOC_Bd ||
- (mdoc->flags & MDOC_LITERAL) == 0) &&
+ if ((n->flags & NODE_NOFILL) == 0 &&
(np->tok != MDOC_It || np->type != ROFFT_HEAD ||
np->parent->parent->norm->Bl.type != LIST_diag))
check_text_em(mdoc, n->line, n->pos, n->string);
@@ -344,20 +368,12 @@ mdoc_node_validate(struct roff_man *mdoc)
/* Call the macro's postprocessor. */
if (n->tok < ROFF_MAX) {
- switch(n->tok) {
- case ROFF_br:
- case ROFF_sp:
- post_par(mdoc);
- break;
- default:
- roff_validate(mdoc);
- break;
- }
+ roff_validate(mdoc);
break;
}
assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
- p = mdoc_valids + n->tok;
+ p = mdoc_valids + (n->tok - MDOC_Dd);
if (*p)
(*p)(mdoc);
if (mdoc->last == n)
@@ -393,12 +409,11 @@ check_text(struct roff_man *mdoc, int ln, int pos, char *p)
{
char *cp;
- if (MDOC_LITERAL & mdoc->flags)
+ if (mdoc->last->flags & NODE_NOFILL)
return;
for (cp = p; NULL != (p = strchr(p, '\t')); p++)
- mandoc_msg(MANDOCERR_FI_TAB, mdoc->parse,
- ln, pos + (int)(p - cp), NULL);
+ mandoc_msg(MANDOCERR_FI_TAB, ln, pos + (int)(p - cp), NULL);
}
static void
@@ -445,7 +460,7 @@ check_text_em(struct roff_man *mdoc, int ln, int pos, char *p)
nn != NULL &&
nn->type == ROFFT_TEXT &&
isalpha((unsigned char)*nn->string))) {
- mandoc_msg(MANDOCERR_DASHDASH, mdoc->parse,
+ mandoc_msg(MANDOCERR_DASHDASH,
ln, pos + (int)(cp - p) - 1, NULL);
break;
}
@@ -461,17 +476,13 @@ check_toptext(struct roff_man *mdoc, int ln, int pos, const char *p)
return;
if ((cp = strstr(p, "OpenBSD")) != NULL)
- mandoc_msg(MANDOCERR_BX, mdoc->parse,
- ln, pos + (cp - p), "Ox");
+ mandoc_msg(MANDOCERR_BX, ln, pos + (int)(cp - p), "Ox");
if ((cp = strstr(p, "NetBSD")) != NULL)
- mandoc_msg(MANDOCERR_BX, mdoc->parse,
- ln, pos + (cp - p), "Nx");
+ mandoc_msg(MANDOCERR_BX, ln, pos + (int)(cp - p), "Nx");
if ((cp = strstr(p, "FreeBSD")) != NULL)
- mandoc_msg(MANDOCERR_BX, mdoc->parse,
- ln, pos + (cp - p), "Fx");
+ mandoc_msg(MANDOCERR_BX, ln, pos + (int)(cp - p), "Fx");
if ((cp = strstr(p, "DragonFly")) != NULL)
- mandoc_msg(MANDOCERR_BX, mdoc->parse,
- ln, pos + (cp - p), "Dx");
+ mandoc_msg(MANDOCERR_BX, ln, pos + (int)(cp - p), "Dx");
cp = p;
while ((cp = strstr(cp + 1, "()")) != NULL) {
@@ -480,14 +491,19 @@ check_toptext(struct roff_man *mdoc, int ln, int pos, const char *p)
break;
if ((cpr < p || *cpr == ' ') && cpr + 1 < cp) {
cpr++;
- mandoc_vmsg(MANDOCERR_FUNC, mdoc->parse,
- ln, pos + (cpr - p),
+ mandoc_msg(MANDOCERR_FUNC, ln, pos + (int)(cpr - p),
"%.*s()", (int)(cp - cpr), cpr);
}
}
}
static void
+post_abort(POST_ARGS)
+{
+ abort();
+}
+
+static void
post_delim(POST_ARGS)
{
const struct roff_node *nch;
@@ -509,9 +525,8 @@ post_delim(POST_ARGS)
tok == MDOC_Ss || tok == MDOC_Fo))
return;
- mandoc_vmsg(MANDOCERR_DELIM, mdoc->parse,
- nch->line, nch->pos + (lc - nch->string),
- "%s%s %s", roff_name[tok],
+ mandoc_msg(MANDOCERR_DELIM, nch->line,
+ nch->pos + (int)(lc - nch->string), "%s%s %s", roff_name[tok],
nch == mdoc->last->child ? "" : " ...", nch->string);
}
@@ -603,9 +618,8 @@ post_delim_nb(POST_ARGS)
}
}
- mandoc_vmsg(MANDOCERR_DELIM_NB, mdoc->parse,
- nch->line, nch->pos + (lc - nch->string),
- "%s%s %s", roff_name[tok],
+ mandoc_msg(MANDOCERR_DELIM_NB, nch->line,
+ nch->pos + (int)(lc - nch->string), "%s%s %s", roff_name[tok],
nch == mdoc->last->child ? "" : " ...", nch->string);
}
@@ -671,39 +685,34 @@ post_bl_norm(POST_ARGS)
case MDOC_Compact:
if (n->norm->Bl.comp)
mandoc_msg(MANDOCERR_ARG_REP,
- mdoc->parse, argv->line,
- argv->pos, "Bl -compact");
+ argv->line, argv->pos, "Bl -compact");
n->norm->Bl.comp = 1;
break;
case MDOC_Width:
wa = argv;
if (0 == argv->sz) {
mandoc_msg(MANDOCERR_ARG_EMPTY,
- mdoc->parse, argv->line,
- argv->pos, "Bl -width");
+ argv->line, argv->pos, "Bl -width");
n->norm->Bl.width = "0n";
break;
}
if (NULL != n->norm->Bl.width)
- mandoc_vmsg(MANDOCERR_ARG_REP,
- mdoc->parse, argv->line,
- argv->pos, "Bl -width %s",
- argv->value[0]);
+ mandoc_msg(MANDOCERR_ARG_REP,
+ argv->line, argv->pos,
+ "Bl -width %s", argv->value[0]);
rewrite_macro2len(mdoc, argv->value);
n->norm->Bl.width = argv->value[0];
break;
case MDOC_Offset:
if (0 == argv->sz) {
mandoc_msg(MANDOCERR_ARG_EMPTY,
- mdoc->parse, argv->line,
- argv->pos, "Bl -offset");
+ argv->line, argv->pos, "Bl -offset");
break;
}
if (NULL != n->norm->Bl.offs)
- mandoc_vmsg(MANDOCERR_ARG_REP,
- mdoc->parse, argv->line,
- argv->pos, "Bl -offset %s",
- argv->value[0]);
+ mandoc_msg(MANDOCERR_ARG_REP,
+ argv->line, argv->pos,
+ "Bl -offset %s", argv->value[0]);
rewrite_macro2len(mdoc, argv->value);
n->norm->Bl.offs = argv->value[0];
break;
@@ -717,8 +726,7 @@ post_bl_norm(POST_ARGS)
/* Check: multiple list types. */
if (LIST__NONE != n->norm->Bl.type) {
- mandoc_vmsg(MANDOCERR_BL_REP,
- mdoc->parse, n->line, n->pos,
+ mandoc_msg(MANDOCERR_BL_REP, n->line, n->pos,
"Bl -%s", mdoc_argnames[argv->arg]);
continue;
}
@@ -728,8 +736,8 @@ post_bl_norm(POST_ARGS)
if (n->norm->Bl.width ||
n->norm->Bl.offs ||
n->norm->Bl.comp)
- mandoc_vmsg(MANDOCERR_BL_LATETYPE,
- mdoc->parse, n->line, n->pos, "Bl -%s",
+ mandoc_msg(MANDOCERR_BL_LATETYPE,
+ n->line, n->pos, "Bl -%s",
mdoc_argnames[n->args->argv[0].arg]);
n->norm->Bl.type = lt;
@@ -742,8 +750,7 @@ post_bl_norm(POST_ARGS)
/* Allow lists to default to LIST_item. */
if (LIST__NONE == n->norm->Bl.type) {
- mandoc_msg(MANDOCERR_BL_NOTYPE, mdoc->parse,
- n->line, n->pos, "Bl");
+ mandoc_msg(MANDOCERR_BL_NOTYPE, n->line, n->pos, "Bl");
n->norm->Bl.type = LIST_item;
mdoclt = MDOC_Item;
}
@@ -758,7 +765,7 @@ post_bl_norm(POST_ARGS)
switch (n->norm->Bl.type) {
case LIST_tag:
if (n->norm->Bl.width == NULL)
- mandoc_msg(MANDOCERR_BL_NOWIDTH, mdoc->parse,
+ mandoc_msg(MANDOCERR_BL_NOWIDTH,
n->line, n->pos, "Bl -tag");
break;
case LIST_column:
@@ -767,9 +774,8 @@ post_bl_norm(POST_ARGS)
case LIST_inset:
case LIST_item:
if (n->norm->Bl.width != NULL)
- mandoc_vmsg(MANDOCERR_BL_SKIPW, mdoc->parse,
- wa->line, wa->pos, "Bl -%s",
- mdoc_argnames[mdoclt]);
+ mandoc_msg(MANDOCERR_BL_SKIPW, wa->line, wa->pos,
+ "Bl -%s", mdoc_argnames[mdoclt]);
n->norm->Bl.width = NULL;
break;
case LIST_bullet:
@@ -817,29 +823,25 @@ post_bd(POST_ARGS)
dt = DISP_literal;
break;
case MDOC_File:
- mandoc_msg(MANDOCERR_BD_FILE, mdoc->parse,
- n->line, n->pos, NULL);
+ mandoc_msg(MANDOCERR_BD_FILE, n->line, n->pos, NULL);
break;
case MDOC_Offset:
if (0 == argv->sz) {
mandoc_msg(MANDOCERR_ARG_EMPTY,
- mdoc->parse, argv->line,
- argv->pos, "Bd -offset");
+ argv->line, argv->pos, "Bd -offset");
break;
}
if (NULL != n->norm->Bd.offs)
- mandoc_vmsg(MANDOCERR_ARG_REP,
- mdoc->parse, argv->line,
- argv->pos, "Bd -offset %s",
- argv->value[0]);
+ mandoc_msg(MANDOCERR_ARG_REP,
+ argv->line, argv->pos,
+ "Bd -offset %s", argv->value[0]);
rewrite_macro2len(mdoc, argv->value);
n->norm->Bd.offs = argv->value[0];
break;
case MDOC_Compact:
if (n->norm->Bd.comp)
mandoc_msg(MANDOCERR_ARG_REP,
- mdoc->parse, argv->line,
- argv->pos, "Bd -compact");
+ argv->line, argv->pos, "Bd -compact");
n->norm->Bd.comp = 1;
break;
default:
@@ -851,14 +853,12 @@ post_bd(POST_ARGS)
if (DISP__NONE == n->norm->Bd.type)
n->norm->Bd.type = dt;
else
- mandoc_vmsg(MANDOCERR_BD_REP,
- mdoc->parse, n->line, n->pos,
+ mandoc_msg(MANDOCERR_BD_REP, n->line, n->pos,
"Bd -%s", mdoc_argnames[argv->arg]);
}
if (DISP__NONE == n->norm->Bd.type) {
- mandoc_msg(MANDOCERR_BD_NOTYPE, mdoc->parse,
- n->line, n->pos, "Bd");
+ mandoc_msg(MANDOCERR_BD_NOTYPE, n->line, n->pos, "Bd");
n->norm->Bd.type = DISP_ragged;
}
}
@@ -880,8 +880,7 @@ post_an_norm(POST_ARGS)
for (i = 1; i < n->args->argc; i++) {
argv = n->args->argv + i;
- mandoc_vmsg(MANDOCERR_AN_REP,
- mdoc->parse, argv->line, argv->pos,
+ mandoc_msg(MANDOCERR_AN_REP, argv->line, argv->pos,
"An -%s", mdoc_argnames[argv->arg]);
}
@@ -902,7 +901,7 @@ post_eoln(POST_ARGS)
post_useless(mdoc);
n = mdoc->last;
if (n->child != NULL)
- mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, n->line,
+ mandoc_msg(MANDOCERR_ARG_SKIP, n->line,
n->pos, "%s %s", roff_name[n->tok], n->child->string);
while (n->child != NULL)
@@ -924,7 +923,7 @@ build_list(struct roff_man *mdoc, int tok)
for (ic = 1;; ic++) {
roff_elem_alloc(mdoc, n->line, n->pos, tok);
mdoc->last->flags |= NODE_NOSRC;
- mdoc_node_relink(mdoc, n);
+ roff_node_relink(mdoc, n);
n = mdoc->last = mdoc->last->parent;
mdoc->next = ROFF_NEXT_SIBLING;
if (n->next == NULL)
@@ -965,8 +964,7 @@ post_ex(POST_ARGS)
mdoc->next = ROFF_NEXT_SIBLING;
ic = 1;
} else {
- mandoc_msg(MANDOCERR_EX_NONAME, mdoc->parse,
- n->line, n->pos, "Ex");
+ mandoc_msg(MANDOCERR_EX_NONAME, n->line, n->pos, "Ex");
ic = 0;
}
@@ -999,7 +997,7 @@ post_lb(POST_ARGS)
return;
}
- mandoc_vmsg(MANDOCERR_LB_BAD, mdoc->parse, n->child->line,
+ mandoc_msg(MANDOCERR_LB_BAD, n->child->line,
n->child->pos, "Lb %s", n->child->string);
roff_word_alloc(mdoc, n->line, n->pos, "library");
@@ -1063,8 +1061,8 @@ post_std(POST_ARGS)
if (n->args->argv[0].arg == MDOC_Std)
return;
- mandoc_msg(MANDOCERR_ARG_STD, mdoc->parse,
- n->line, n->pos, roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_ARG_STD, n->line, n->pos,
+ "%s", roff_name[n->tok]);
}
static void
@@ -1078,7 +1076,7 @@ post_st(POST_ARGS)
assert(nch->type == ROFFT_TEXT);
if ((p = mdoc_a2st(nch->string)) == NULL) {
- mandoc_vmsg(MANDOCERR_ST_BAD, mdoc->parse,
+ mandoc_msg(MANDOCERR_ST_BAD,
nch->line, nch->pos, "St %s", nch->string);
roff_node_delete(mdoc, n);
return;
@@ -1098,8 +1096,8 @@ post_obsolete(POST_ARGS)
n = mdoc->last;
if (n->type == ROFFT_ELEM || n->type == ROFFT_BLOCK)
- mandoc_msg(MANDOCERR_MACRO_OBS, mdoc->parse,
- n->line, n->pos, roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_MACRO_OBS, n->line, n->pos,
+ "%s", roff_name[n->tok]);
}
static void
@@ -1108,8 +1106,8 @@ post_useless(POST_ARGS)
struct roff_node *n;
n = mdoc->last;
- mandoc_msg(MANDOCERR_MACRO_USELESS, mdoc->parse,
- n->line, n->pos, roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_MACRO_USELESS, n->line, n->pos,
+ "%s", roff_name[n->tok]);
}
/*
@@ -1138,14 +1136,14 @@ post_bf(POST_ARGS)
nch = np->child;
if (np->parent->args == NULL) {
if (nch == NULL) {
- mandoc_msg(MANDOCERR_BF_NOFONT, mdoc->parse,
+ mandoc_msg(MANDOCERR_BF_NOFONT,
np->line, np->pos, "Bf");
return;
}
nch = nch->next;
}
if (nch != NULL)
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
+ mandoc_msg(MANDOCERR_ARG_EXCESS,
nch->line, nch->pos, "Bf ... %s", nch->string);
/* Extract argument into data. */
@@ -1176,9 +1174,8 @@ post_bf(POST_ARGS)
else if ( ! strcmp(np->child->string, "Sy"))
np->norm->Bf.font = FONT_Sy;
else
- mandoc_vmsg(MANDOCERR_BF_BADFONT, mdoc->parse,
- np->child->line, np->child->pos,
- "Bf %s", np->child->string);
+ mandoc_msg(MANDOCERR_BF_BADFONT, np->child->line,
+ np->child->pos, "Bf %s", np->child->string);
}
static void
@@ -1192,8 +1189,8 @@ post_fname(POST_ARGS)
pos = strcspn(n->string, "()");
cp = n->string + pos;
if ( ! (cp[0] == '\0' || (cp[0] == '(' && cp[1] == '*')))
- mandoc_msg(MANDOCERR_FN_PAREN, mdoc->parse,
- n->line, n->pos + pos, n->string);
+ mandoc_msg(MANDOCERR_FN_PAREN, n->line, n->pos + pos,
+ "%s", n->string);
}
static void
@@ -1215,12 +1212,11 @@ post_fo(POST_ARGS)
return;
if (n->child == NULL) {
- mandoc_msg(MANDOCERR_FO_NOHEAD, mdoc->parse,
- n->line, n->pos, "Fo");
+ mandoc_msg(MANDOCERR_FO_NOHEAD, n->line, n->pos, "Fo");
return;
}
if (n->child != n->last) {
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
+ mandoc_msg(MANDOCERR_ARG_EXCESS,
n->child->next->line, n->child->next->pos,
"Fo ... %s", n->child->next->string);
while (n->child != n->last)
@@ -1244,9 +1240,8 @@ post_fa(POST_ARGS)
break;
if (*cp != ',')
continue;
- mandoc_msg(MANDOCERR_FA_COMMA, mdoc->parse,
- n->line, n->pos + (cp - n->string),
- n->string);
+ mandoc_msg(MANDOCERR_FA_COMMA, n->line,
+ n->pos + (int)(cp - n->string), "%s", n->string);
break;
}
}
@@ -1264,18 +1259,15 @@ post_nm(POST_ARGS)
n->child->type == ROFFT_TEXT && mdoc->meta.msec != NULL)
mandoc_xr_add(mdoc->meta.msec, n->child->string, -1, -1);
- if (n->last != NULL &&
- (n->last->tok == MDOC_Pp ||
- n->last->tok == MDOC_Lp))
- mdoc_node_relink(mdoc, n->last);
+ if (n->last != NULL && n->last->tok == MDOC_Pp)
+ roff_node_relink(mdoc, n->last);
if (mdoc->meta.name == NULL)
deroff(&mdoc->meta.name, n);
if (mdoc->meta.name == NULL ||
(mdoc->lastsec == SEC_NAME && n->child == NULL))
- mandoc_msg(MANDOCERR_NM_NONAME, mdoc->parse,
- n->line, n->pos, "Nm");
+ mandoc_msg(MANDOCERR_NM_NONAME, n->line, n->pos, "Nm");
switch (n->type) {
case ROFFT_ELEM:
@@ -1309,12 +1301,10 @@ post_nd(POST_ARGS)
return;
if (n->sec != SEC_NAME)
- mandoc_msg(MANDOCERR_ND_LATE, mdoc->parse,
- n->line, n->pos, "Nd");
+ mandoc_msg(MANDOCERR_ND_LATE, n->line, n->pos, "Nd");
if (n->child == NULL)
- mandoc_msg(MANDOCERR_ND_EMPTY, mdoc->parse,
- n->line, n->pos, "Nd");
+ mandoc_msg(MANDOCERR_ND_EMPTY, n->line, n->pos, "Nd");
else
post_delim(mdoc);
@@ -1334,8 +1324,8 @@ post_display(POST_ARGS)
n->body->parent->args == NULL)
roff_node_delete(mdoc, n);
} else if (n->child == NULL)
- mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse,
- n->line, n->pos, roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_BLK_EMPTY, n->line, n->pos,
+ "%s", roff_name[n->tok]);
else if (n->tok == MDOC_D1)
post_hyph(mdoc);
break;
@@ -1343,10 +1333,10 @@ post_display(POST_ARGS)
if (n->tok == MDOC_Bd) {
if (n->args == NULL) {
mandoc_msg(MANDOCERR_BD_NOARG,
- mdoc->parse, n->line, n->pos, "Bd");
+ n->line, n->pos, "Bd");
mdoc->next = ROFF_NEXT_SIBLING;
while (n->body->child != NULL)
- mdoc_node_relink(mdoc,
+ roff_node_relink(mdoc,
n->body->child);
roff_node_delete(mdoc, n);
break;
@@ -1356,9 +1346,8 @@ post_display(POST_ARGS)
}
for (np = n->parent; np != NULL; np = np->parent) {
if (np->type == ROFFT_BLOCK && np->tok == MDOC_Bd) {
- mandoc_vmsg(MANDOCERR_BD_NEST,
- mdoc->parse, n->line, n->pos,
- "%s in Bd", roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_BD_NEST, n->line,
+ n->pos, "%s in Bd", roff_name[n->tok]);
break;
}
}
@@ -1422,7 +1411,7 @@ post_at(POST_ARGS)
att = NULL;
if (nch != NULL && ((att = mdoc_a2att(nch->string)) == NULL))
- mandoc_vmsg(MANDOCERR_AT_BAD, mdoc->parse,
+ mandoc_msg(MANDOCERR_AT_BAD,
nch->line, nch->pos, "At %s", nch->string);
mdoc->next = ROFF_NEXT_CHILD;
@@ -1446,12 +1435,12 @@ post_an(POST_ARGS)
nch = np->child;
if (np->norm->An.auth == AUTH__NONE) {
if (nch == NULL)
- mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
+ mandoc_msg(MANDOCERR_MACRO_EMPTY,
np->line, np->pos, "An");
else
post_delim_nb(mdoc);
} else if (nch != NULL)
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
+ mandoc_msg(MANDOCERR_ARG_EXCESS,
nch->line, nch->pos, "An ... %s", nch->string);
}
@@ -1547,9 +1536,8 @@ post_it(POST_ARGS)
case LIST_inset:
case LIST_diag:
if (nit->head->child == NULL)
- mandoc_vmsg(MANDOCERR_IT_NOHEAD,
- mdoc->parse, nit->line, nit->pos,
- "Bl -%s It",
+ mandoc_msg(MANDOCERR_IT_NOHEAD,
+ nit->line, nit->pos, "Bl -%s It",
mdoc_argnames[nbl->args->argv[0].arg]);
break;
case LIST_bullet:
@@ -1557,14 +1545,13 @@ post_it(POST_ARGS)
case LIST_enum:
case LIST_hyphen:
if (nit->body == NULL || nit->body->child == NULL)
- mandoc_vmsg(MANDOCERR_IT_NOBODY,
- mdoc->parse, nit->line, nit->pos,
- "Bl -%s It",
+ mandoc_msg(MANDOCERR_IT_NOBODY,
+ nit->line, nit->pos, "Bl -%s It",
mdoc_argnames[nbl->args->argv[0].arg]);
/* FALLTHROUGH */
case LIST_item:
if ((nch = nit->head->child) != NULL)
- mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse,
+ mandoc_msg(MANDOCERR_ARG_SKIP,
nit->line, nit->pos, "It %s",
nch->string == NULL ? roff_name[nch->tok] :
nch->string);
@@ -1576,7 +1563,7 @@ post_it(POST_ARGS)
if (nit->head->next->child == NULL &&
nit->head->next->next == NULL) {
- mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
+ mandoc_msg(MANDOCERR_MACRO_EMPTY,
nit->line, nit->pos, "It");
roff_node_delete(mdoc, nit);
break;
@@ -1587,16 +1574,15 @@ post_it(POST_ARGS)
if (nch->type != ROFFT_BODY)
continue;
if (i++ && nch->flags & NODE_LINE)
- mandoc_msg(MANDOCERR_TA_LINE, mdoc->parse,
+ mandoc_msg(MANDOCERR_TA_LINE,
nch->line, nch->pos, "Ta");
}
if (i < cols || i > cols + 1)
- mandoc_vmsg(MANDOCERR_BL_COL,
- mdoc->parse, nit->line, nit->pos,
+ mandoc_msg(MANDOCERR_BL_COL, nit->line, nit->pos,
"%d columns, %d cells", cols, i);
else if (nit->head->next->child != NULL &&
- nit->head->next->child->line > nit->line)
- mandoc_msg(MANDOCERR_IT_NOARG, mdoc->parse,
+ nit->head->next->child->flags & NODE_LINE)
+ mandoc_msg(MANDOCERR_IT_NOARG,
nit->line, nit->pos, "Bl -column It");
break;
default:
@@ -1619,7 +1605,6 @@ post_bl_block(POST_ARGS)
while (nc != NULL) {
switch (nc->tok) {
case MDOC_Pp:
- case MDOC_Lp:
case ROFF_br:
break;
default:
@@ -1627,14 +1612,13 @@ post_bl_block(POST_ARGS)
continue;
}
if (ni->next == NULL) {
- mandoc_msg(MANDOCERR_PAR_MOVE,
- mdoc->parse, nc->line, nc->pos,
- roff_name[nc->tok]);
- mdoc_node_relink(mdoc, nc);
+ mandoc_msg(MANDOCERR_PAR_MOVE, nc->line,
+ nc->pos, "%s", roff_name[nc->tok]);
+ roff_node_relink(mdoc, nc);
} else if (n->norm->Bl.comp == 0 &&
n->norm->Bl.type != LIST_column) {
- mandoc_vmsg(MANDOCERR_PAR_SKIP,
- mdoc->parse, nc->line, nc->pos,
+ mandoc_msg(MANDOCERR_PAR_SKIP,
+ nc->line, nc->pos,
"%s before It", roff_name[nc->tok]);
roff_node_delete(mdoc, nc);
} else
@@ -1680,7 +1664,7 @@ post_bl_head(POST_ARGS)
if (nh->norm->Bl.type != LIST_column) {
if ((nch = nh->child) == NULL)
return;
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
+ mandoc_msg(MANDOCERR_ARG_EXCESS,
nch->line, nch->pos, "Bl ... %s", nch->string);
while (nch != NULL) {
roff_node_delete(mdoc, nch);
@@ -1757,7 +1741,7 @@ post_bl(POST_ARGS)
nchild = nbody->child;
if (nchild == NULL) {
- mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse,
+ mandoc_msg(MANDOCERR_BLK_EMPTY,
nbody->line, nbody->pos, "Bl");
return;
}
@@ -1790,7 +1774,7 @@ post_bl(POST_ARGS)
roff_body_alloc(mdoc, nchild->line,
nchild->pos, MDOC_It);
while (nchild->tok != MDOC_It) {
- mdoc_node_relink(mdoc, nchild);
+ roff_node_relink(mdoc, nchild);
if ((nchild = nnext) == NULL)
break;
nnext = nchild->next;
@@ -1800,8 +1784,8 @@ post_bl(POST_ARGS)
continue;
}
- mandoc_msg(MANDOCERR_BL_MOVE, mdoc->parse,
- nchild->line, nchild->pos, roff_name[nchild->tok]);
+ mandoc_msg(MANDOCERR_BL_MOVE, nchild->line, nchild->pos,
+ "%s", roff_name[nchild->tok]);
/*
* Move the node out of the Bl block.
@@ -1856,13 +1840,13 @@ post_bl(POST_ARGS)
if (prev_Er != NULL) {
order = strcmp(prev_Er, nnext->string);
if (order > 0)
- mandoc_vmsg(MANDOCERR_ER_ORDER,
- mdoc->parse, nnext->line, nnext->pos,
+ mandoc_msg(MANDOCERR_ER_ORDER,
+ nnext->line, nnext->pos,
"Er %s %s (NetBSD)",
prev_Er, nnext->string);
else if (order == 0)
- mandoc_vmsg(MANDOCERR_ER_REP,
- mdoc->parse, nnext->line, nnext->pos,
+ mandoc_msg(MANDOCERR_ER_REP,
+ nnext->line, nnext->pos,
"Er %s (NetBSD)", prev_Er);
}
prev_Er = nnext->string;
@@ -1877,8 +1861,7 @@ post_bk(POST_ARGS)
n = mdoc->last;
if (n->type == ROFFT_BLOCK && n->body->child == NULL) {
- mandoc_msg(MANDOCERR_BLK_EMPTY,
- mdoc->parse, n->line, n->pos, "Bk");
+ mandoc_msg(MANDOCERR_BLK_EMPTY, n->line, n->pos, "Bk");
roff_node_delete(mdoc, n);
}
}
@@ -1906,39 +1889,16 @@ post_sm(POST_ARGS)
return;
}
- mandoc_vmsg(MANDOCERR_SM_BAD,
- mdoc->parse, nch->line, nch->pos,
+ mandoc_msg(MANDOCERR_SM_BAD, nch->line, nch->pos,
"%s %s", roff_name[mdoc->last->tok], nch->string);
- mdoc_node_relink(mdoc, nch);
+ roff_node_relink(mdoc, nch);
return;
}
static void
post_root(POST_ARGS)
{
- const char *openbsd_arch[] = {
- "alpha", "amd64", "arm64", "armv7", "hppa", "i386",
- "landisk", "loongson", "luna88k", "macppc", "mips64",
- "octeon", "sgi", "socppc", "sparc64", NULL
- };
- const char *netbsd_arch[] = {
- "acorn26", "acorn32", "algor", "alpha", "amiga",
- "arc", "atari",
- "bebox", "cats", "cesfic", "cobalt", "dreamcast",
- "emips", "evbarm", "evbmips", "evbppc", "evbsh3", "evbsh5",
- "hp300", "hpcarm", "hpcmips", "hpcsh", "hppa",
- "i386", "ibmnws", "luna68k",
- "mac68k", "macppc", "mipsco", "mmeye", "mvme68k", "mvmeppc",
- "netwinder", "news68k", "newsmips", "next68k",
- "pc532", "playstation2", "pmax", "pmppc", "prep",
- "sandpoint", "sbmips", "sgimips", "shark",
- "sparc", "sparc64", "sun2", "sun3",
- "vax", "walnut", "x68k", "x86", "x86_64", "xen", NULL
- };
- const char **arches[] = { NULL, netbsd_arch, openbsd_arch };
-
struct roff_node *n;
- const char **arch;
/* Add missing prologue data. */
@@ -1947,8 +1907,7 @@ post_root(POST_ARGS)
mandoc_normdate(mdoc, NULL, 0, 0);
if (mdoc->meta.title == NULL) {
- mandoc_msg(MANDOCERR_DT_NOTITLE,
- mdoc->parse, 0, 0, "EOF");
+ mandoc_msg(MANDOCERR_DT_NOTITLE, 0, 0, "EOF");
mdoc->meta.title = mandoc_strdup("UNTITLED");
}
@@ -1956,49 +1915,43 @@ post_root(POST_ARGS)
mdoc->meta.vol = mandoc_strdup("LOCAL");
if (mdoc->meta.os == NULL) {
- mandoc_msg(MANDOCERR_OS_MISSING,
- mdoc->parse, 0, 0, NULL);
+ mandoc_msg(MANDOCERR_OS_MISSING, 0, 0, NULL);
mdoc->meta.os = mandoc_strdup("");
} else if (mdoc->meta.os_e &&
(mdoc->meta.rcsids & (1 << mdoc->meta.os_e)) == 0)
- mandoc_msg(MANDOCERR_RCS_MISSING, mdoc->parse, 0, 0,
+ mandoc_msg(MANDOCERR_RCS_MISSING, 0, 0,
mdoc->meta.os_e == MANDOC_OS_OPENBSD ?
"(OpenBSD)" : "(NetBSD)");
if (mdoc->meta.arch != NULL &&
- (arch = arches[mdoc->meta.os_e]) != NULL) {
- while (*arch != NULL && strcmp(*arch, mdoc->meta.arch))
- arch++;
- if (*arch == NULL) {
- n = mdoc->first->child;
- while (n->tok != MDOC_Dt ||
- n->child == NULL ||
- n->child->next == NULL ||
- n->child->next->next == NULL)
- n = n->next;
- n = n->child->next->next;
- mandoc_vmsg(MANDOCERR_ARCH_BAD,
- mdoc->parse, n->line, n->pos,
- "Dt ... %s %s", mdoc->meta.arch,
- mdoc->meta.os_e == MANDOC_OS_OPENBSD ?
- "(OpenBSD)" : "(NetBSD)");
- }
+ arch_valid(mdoc->meta.arch, mdoc->meta.os_e) == 0) {
+ n = mdoc->meta.first->child;
+ while (n->tok != MDOC_Dt ||
+ n->child == NULL ||
+ n->child->next == NULL ||
+ n->child->next->next == NULL)
+ n = n->next;
+ n = n->child->next->next;
+ mandoc_msg(MANDOCERR_ARCH_BAD, n->line, n->pos,
+ "Dt ... %s %s", mdoc->meta.arch,
+ mdoc->meta.os_e == MANDOC_OS_OPENBSD ?
+ "(OpenBSD)" : "(NetBSD)");
}
/* Check that we begin with a proper `Sh'. */
- n = mdoc->first->child;
+ n = mdoc->meta.first->child;
while (n != NULL &&
(n->type == ROFFT_COMMENT ||
(n->tok >= MDOC_Dd &&
- mdoc_macros[n->tok].flags & MDOC_PROLOGUE)))
+ mdoc_macro(n->tok)->flags & MDOC_PROLOGUE)))
n = n->next;
if (n == NULL)
- mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL);
+ mandoc_msg(MANDOCERR_DOC_EMPTY, 0, 0, NULL);
else if (n->tok != MDOC_Sh)
- mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse,
- n->line, n->pos, roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_SEC_BEFORE, n->line, n->pos,
+ "%s", roff_name[n->tok]);
}
static void
@@ -2013,8 +1966,7 @@ post_rs(POST_ARGS)
return;
if (np->child == NULL) {
- mandoc_msg(MANDOCERR_RS_EMPTY, mdoc->parse,
- np->line, np->pos, "Rs");
+ mandoc_msg(MANDOCERR_RS_EMPTY, np->line, np->pos, "Rs");
return;
}
@@ -2032,8 +1984,8 @@ post_rs(POST_ARGS)
break;
if (i == RSORD_MAX) {
- mandoc_msg(MANDOCERR_RS_BAD, mdoc->parse,
- nch->line, nch->pos, roff_name[nch->tok]);
+ mandoc_msg(MANDOCERR_RS_BAD, nch->line, nch->pos,
+ "%s", roff_name[nch->tok]);
i = -1;
} else if (nch->tok == MDOC__J || nch->tok == MDOC__B)
np->norm->Rs.quote_T++;
@@ -2122,8 +2074,7 @@ post_ns(POST_ARGS)
n = mdoc->last;
if (n->flags & NODE_LINE ||
(n->next != NULL && n->next->flags & NODE_DELIMC))
- mandoc_msg(MANDOCERR_NS_SKIP, mdoc->parse,
- n->line, n->pos, NULL);
+ mandoc_msg(MANDOCERR_NS_SKIP, n->line, n->pos, NULL);
}
static void
@@ -2175,8 +2126,8 @@ post_sh_name(POST_ARGS)
switch (n->tok) {
case MDOC_Nm:
if (hasnm && n->child != NULL)
- mandoc_vmsg(MANDOCERR_NAMESEC_PUNCT,
- mdoc->parse, n->line, n->pos,
+ mandoc_msg(MANDOCERR_NAMESEC_PUNCT,
+ n->line, n->pos,
"Nm %s", n->child->string);
hasnm = 1;
continue;
@@ -2184,7 +2135,7 @@ post_sh_name(POST_ARGS)
hasnd = 1;
if (n->next != NULL)
mandoc_msg(MANDOCERR_NAMESEC_ND,
- mdoc->parse, n->line, n->pos, NULL);
+ n->line, n->pos, NULL);
break;
case TOKEN_NONE:
if (n->type == ROFFT_TEXT &&
@@ -2195,18 +2146,18 @@ post_sh_name(POST_ARGS)
}
/* FALLTHROUGH */
default:
- mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
- n->line, n->pos, roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_NAMESEC_BAD,
+ n->line, n->pos, "%s", roff_name[n->tok]);
continue;
}
break;
}
if ( ! hasnm)
- mandoc_msg(MANDOCERR_NAMESEC_NONM, mdoc->parse,
+ mandoc_msg(MANDOCERR_NAMESEC_NONM,
mdoc->last->line, mdoc->last->pos, NULL);
if ( ! hasnd)
- mandoc_msg(MANDOCERR_NAMESEC_NOND, mdoc->parse,
+ mandoc_msg(MANDOCERR_NAMESEC_NOND,
mdoc->last->line, mdoc->last->pos, NULL);
}
@@ -2232,21 +2183,18 @@ post_sh_see_also(POST_ARGS)
sec = n->child->next->string;
if (lastsec != NULL) {
if (lastpunct[0] != ',' || lastpunct[1] != '\0')
- mandoc_vmsg(MANDOCERR_XR_PUNCT,
- mdoc->parse, n->line, n->pos,
- "%s before %s(%s)", lastpunct,
- name, sec);
+ mandoc_msg(MANDOCERR_XR_PUNCT, n->line,
+ n->pos, "%s before %s(%s)",
+ lastpunct, name, sec);
cmp = strcmp(lastsec, sec);
if (cmp > 0)
- mandoc_vmsg(MANDOCERR_XR_ORDER,
- mdoc->parse, n->line, n->pos,
- "%s(%s) after %s(%s)", name,
- sec, lastname, lastsec);
+ mandoc_msg(MANDOCERR_XR_ORDER, n->line,
+ n->pos, "%s(%s) after %s(%s)",
+ name, sec, lastname, lastsec);
else if (cmp == 0 &&
strcasecmp(lastname, name) > 0)
- mandoc_vmsg(MANDOCERR_XR_ORDER,
- mdoc->parse, n->line, n->pos,
- "%s after %s", name, lastname);
+ mandoc_msg(MANDOCERR_XR_ORDER, n->line,
+ n->pos, "%s after %s", name, lastname);
}
lastname = name;
lastsec = sec;
@@ -2267,8 +2215,8 @@ post_sh_see_also(POST_ARGS)
return;
lastpunct = n->string;
if (n->next == NULL || n->next->tok == MDOC_Rs)
- mandoc_vmsg(MANDOCERR_XR_PUNCT, mdoc->parse,
- n->line, n->pos, "%s after %s(%s)",
+ mandoc_msg(MANDOCERR_XR_PUNCT, n->line,
+ n->pos, "%s after %s(%s)",
lastpunct, lastname, lastsec);
n = n->next;
}
@@ -2289,7 +2237,7 @@ post_sh_authors(POST_ARGS)
{
if ( ! child_an(mdoc->last))
- mandoc_msg(MANDOCERR_AN_MISSING, mdoc->parse,
+ mandoc_msg(MANDOCERR_AN_MISSING,
mdoc->last->line, mdoc->last->pos, NULL);
}
@@ -2355,7 +2303,7 @@ post_sh_head(POST_ARGS)
/* The NAME should be first. */
if (sec != SEC_NAME && mdoc->lastnamed == SEC_NONE)
- mandoc_vmsg(MANDOCERR_NAMESEC_FIRST, mdoc->parse,
+ mandoc_msg(MANDOCERR_NAMESEC_FIRST,
mdoc->last->line, mdoc->last->pos, "Sh %s",
sec != SEC_CUSTOM ? secnames[sec] :
(nch = mdoc->last->child) == NULL ? "" :
@@ -2392,9 +2340,8 @@ post_sh_head(POST_ARGS)
}
}
if (goodsec != NULL)
- mandoc_vmsg(MANDOCERR_SEC_TYPO, mdoc->parse,
- nch->line, nch->pos, "Sh %s instead of %s",
- nch->string, goodsec);
+ mandoc_msg(MANDOCERR_SEC_TYPO, nch->line, nch->pos,
+ "Sh %s instead of %s", nch->string, goodsec);
return;
}
@@ -2404,14 +2351,12 @@ post_sh_head(POST_ARGS)
*/
if (sec == mdoc->lastnamed)
- mandoc_vmsg(MANDOCERR_SEC_REP, mdoc->parse,
- mdoc->last->line, mdoc->last->pos,
- "Sh %s", secnames[sec]);
+ mandoc_msg(MANDOCERR_SEC_REP, mdoc->last->line,
+ mdoc->last->pos, "Sh %s", secnames[sec]);
if (sec < mdoc->lastnamed)
- mandoc_vmsg(MANDOCERR_SEC_ORDER, mdoc->parse,
- mdoc->last->line, mdoc->last->pos,
- "Sh %s", secnames[sec]);
+ mandoc_msg(MANDOCERR_SEC_ORDER, mdoc->last->line,
+ mdoc->last->pos, "Sh %s", secnames[sec]);
/* Mark the last named section. */
@@ -2443,7 +2388,7 @@ post_sh_head(POST_ARGS)
break;
if (NULL == goodsec)
goodsec = "9";
- mandoc_vmsg(MANDOCERR_SEC_MSEC, mdoc->parse,
+ mandoc_msg(MANDOCERR_SEC_MSEC,
mdoc->last->line, mdoc->last->pos,
"Sh %s for %s only", secnames[sec], goodsec);
break;
@@ -2460,13 +2405,13 @@ post_xr(POST_ARGS)
n = mdoc->last;
nch = n->child;
if (nch->next == NULL) {
- mandoc_vmsg(MANDOCERR_XR_NOSEC, mdoc->parse,
+ mandoc_msg(MANDOCERR_XR_NOSEC,
n->line, n->pos, "Xr %s", nch->string);
} else {
assert(nch->next == n->last);
if(mandoc_xr_add(nch->next->string, nch->string,
nch->line, nch->pos))
- mandoc_vmsg(MANDOCERR_XR_SELF, mdoc->parse,
+ mandoc_msg(MANDOCERR_XR_SELF,
nch->line, nch->pos, "Xr %s %s",
nch->string, nch->next->string);
}
@@ -2493,19 +2438,18 @@ post_ignpar(POST_ARGS)
}
if ((np = mdoc->last->child) != NULL)
- if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) {
- mandoc_vmsg(MANDOCERR_PAR_SKIP,
- mdoc->parse, np->line, np->pos,
+ if (np->tok == MDOC_Pp ||
+ np->tok == ROFF_br || np->tok == ROFF_sp) {
+ mandoc_msg(MANDOCERR_PAR_SKIP, np->line, np->pos,
"%s after %s", roff_name[np->tok],
roff_name[mdoc->last->tok]);
roff_node_delete(mdoc, np);
}
if ((np = mdoc->last->last) != NULL)
- if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) {
- mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
- np->line, np->pos, "%s at the end of %s",
- roff_name[np->tok],
+ if (np->tok == MDOC_Pp || np->tok == ROFF_br) {
+ mandoc_msg(MANDOCERR_PAR_SKIP, np->line, np->pos,
+ "%s at the end of %s", roff_name[np->tok],
roff_name[mdoc->last->tok]);
roff_node_delete(mdoc, np);
}
@@ -2523,13 +2467,11 @@ post_prevpar(POST_ARGS)
return;
/*
- * Don't allow prior `Lp' or `Pp' prior to a paragraph-type
- * block: `Lp', `Pp', or non-compact `Bd' or `Bl'.
+ * Don't allow `Pp' prior to a paragraph-type
+ * block: `Pp' or non-compact `Bd' or `Bl'.
*/
- if (n->prev->tok != MDOC_Pp &&
- n->prev->tok != MDOC_Lp &&
- n->prev->tok != ROFF_br)
+ if (n->prev->tok != MDOC_Pp && n->prev->tok != ROFF_br)
return;
if (n->tok == MDOC_Bl && n->norm->Bl.comp)
return;
@@ -2538,9 +2480,8 @@ post_prevpar(POST_ARGS)
if (n->tok == MDOC_It && n->parent->norm->Bl.comp)
return;
- mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
- n->prev->line, n->prev->pos, "%s before %s",
- roff_name[n->prev->tok], roff_name[n->tok]);
+ mandoc_msg(MANDOCERR_PAR_SKIP, n->prev->line, n->prev->pos,
+ "%s before %s", roff_name[n->prev->tok], roff_name[n->tok]);
roff_node_delete(mdoc, n->prev);
}
@@ -2549,33 +2490,12 @@ post_par(POST_ARGS)
{
struct roff_node *np;
- np = mdoc->last;
- if (np->tok != ROFF_br && np->tok != ROFF_sp)
- post_prevpar(mdoc);
-
- if (np->tok == ROFF_sp) {
- if (np->child != NULL && np->child->next != NULL)
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
- np->child->next->line, np->child->next->pos,
- "sp ... %s", np->child->next->string);
- } else if (np->child != NULL)
- mandoc_vmsg(MANDOCERR_ARG_SKIP,
- mdoc->parse, np->line, np->pos, "%s %s",
- roff_name[np->tok], np->child->string);
-
- if ((np = mdoc->last->prev) == NULL) {
- np = mdoc->last->parent;
- if (np->tok != MDOC_Sh && np->tok != MDOC_Ss)
- return;
- } else if (np->tok != MDOC_Pp && np->tok != MDOC_Lp &&
- (mdoc->last->tok != ROFF_br ||
- (np->tok != ROFF_sp && np->tok != ROFF_br)))
- return;
+ post_prevpar(mdoc);
- mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
- mdoc->last->line, mdoc->last->pos, "%s after %s",
- roff_name[mdoc->last->tok], roff_name[np->tok]);
- roff_node_delete(mdoc, mdoc->last);
+ np = mdoc->last;
+ if (np->child != NULL)
+ mandoc_msg(MANDOCERR_ARG_SKIP, np->line, np->pos,
+ "%s %s", roff_name[np->tok], np->child->string);
}
static void
@@ -2588,17 +2508,15 @@ post_dd(POST_ARGS)
n->flags |= NODE_NOPRT;
if (mdoc->meta.date != NULL) {
- mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
- n->line, n->pos, "Dd");
+ mandoc_msg(MANDOCERR_PROLOG_REP, n->line, n->pos, "Dd");
free(mdoc->meta.date);
} else if (mdoc->flags & MDOC_PBODY)
- mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
- n->line, n->pos, "Dd");
+ mandoc_msg(MANDOCERR_PROLOG_LATE, n->line, n->pos, "Dd");
else if (mdoc->meta.title != NULL)
- mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
+ mandoc_msg(MANDOCERR_PROLOG_ORDER,
n->line, n->pos, "Dd after Dt");
else if (mdoc->meta.os != NULL)
- mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
+ mandoc_msg(MANDOCERR_PROLOG_ORDER,
n->line, n->pos, "Dd after Os");
if (n->child == NULL || n->child->string[0] == '\0') {
@@ -2629,16 +2547,14 @@ post_dt(POST_ARGS)
n->flags |= NODE_NOPRT;
if (mdoc->flags & MDOC_PBODY) {
- mandoc_msg(MANDOCERR_DT_LATE, mdoc->parse,
- n->line, n->pos, "Dt");
+ mandoc_msg(MANDOCERR_DT_LATE, n->line, n->pos, "Dt");
return;
}
if (mdoc->meta.title != NULL)
- mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
- n->line, n->pos, "Dt");
+ mandoc_msg(MANDOCERR_PROLOG_REP, n->line, n->pos, "Dt");
else if (mdoc->meta.os != NULL)
- mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse,
+ mandoc_msg(MANDOCERR_PROLOG_ORDER,
n->line, n->pos, "Dt after Os");
free(mdoc->meta.title);
@@ -2655,8 +2571,7 @@ post_dt(POST_ARGS)
nn = n->child;
if (nn == NULL || *nn->string == '\0') {
- mandoc_msg(MANDOCERR_DT_NOTITLE,
- mdoc->parse, n->line, n->pos, "Dt");
+ mandoc_msg(MANDOCERR_DT_NOTITLE, n->line, n->pos, "Dt");
mdoc->meta.title = mandoc_strdup("UNTITLED");
} else {
mdoc->meta.title = mandoc_strdup(nn->string);
@@ -2665,9 +2580,8 @@ post_dt(POST_ARGS)
for (p = nn->string; *p != '\0'; p++)
if (islower((unsigned char)*p)) {
- mandoc_vmsg(MANDOCERR_TITLE_CASE,
- mdoc->parse, nn->line,
- nn->pos + (p - nn->string),
+ mandoc_msg(MANDOCERR_TITLE_CASE, nn->line,
+ nn->pos + (int)(p - nn->string),
"Dt %s", nn->string);
break;
}
@@ -2679,8 +2593,7 @@ post_dt(POST_ARGS)
nn = nn->next;
if (nn == NULL) {
- mandoc_vmsg(MANDOCERR_MSEC_MISSING,
- mdoc->parse, n->line, n->pos,
+ mandoc_msg(MANDOCERR_MSEC_MISSING, n->line, n->pos,
"Dt %s", mdoc->meta.title);
mdoc->meta.vol = mandoc_strdup("LOCAL");
return; /* msec and arch remain NULL. */
@@ -2692,7 +2605,7 @@ post_dt(POST_ARGS)
cp = mandoc_a2msec(nn->string);
if (cp == NULL) {
- mandoc_vmsg(MANDOCERR_MSEC_BAD, mdoc->parse,
+ mandoc_msg(MANDOCERR_MSEC_BAD,
nn->line, nn->pos, "Dt ... %s", nn->string);
mdoc->meta.vol = mandoc_strdup(nn->string);
} else
@@ -2710,7 +2623,7 @@ post_dt(POST_ARGS)
/* Ignore fourth and later arguments. */
if ((nn = nn->next) != NULL)
- mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
+ mandoc_msg(MANDOCERR_ARG_EXCESS,
nn->line, nn->pos, "Dt ... %s", nn->string);
}
@@ -2731,8 +2644,8 @@ post_bx(POST_ARGS)
!strcmp(nch->string, "Free") ? "Fx" :
!strcmp(nch->string, "DragonFly") ? "Dx" : NULL;
if (macro != NULL)
- mandoc_msg(MANDOCERR_BX, mdoc->parse,
- n->line, n->pos, macro);
+ mandoc_msg(MANDOCERR_BX,
+ n->line, n->pos, "%s", macro);
mdoc->last = nch;
nch = nch->next;
mdoc->next = ROFF_NEXT_SIBLING;
@@ -2780,11 +2693,9 @@ post_os(POST_ARGS)
n->flags |= NODE_NOPRT;
if (mdoc->meta.os != NULL)
- mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse,
- n->line, n->pos, "Os");
+ mandoc_msg(MANDOCERR_PROLOG_REP, n->line, n->pos, "Os");
else if (mdoc->flags & MDOC_PBODY)
- mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse,
- n->line, n->pos, "Os");
+ mandoc_msg(MANDOCERR_PROLOG_LATE, n->line, n->pos, "Os");
post_delim(mdoc);
@@ -2813,8 +2724,7 @@ post_os(POST_ARGS)
#else /*!OSNAME */
if (defbuf == NULL) {
if (uname(&utsname) == -1) {
- mandoc_msg(MANDOCERR_OS_UNAME, mdoc->parse,
- n->line, n->pos, "Os");
+ mandoc_msg(MANDOCERR_OS_UNAME, n->line, n->pos, "Os");
defbuf = mandoc_strdup("UNKNOWN");
} else
mandoc_asprintf(&defbuf, "%s %s",
@@ -2838,8 +2748,7 @@ out:
*/
if (n->child != NULL)
- mandoc_vmsg(MANDOCERR_OS_ARG, mdoc->parse,
- n->child->line, n->child->pos,
+ mandoc_msg(MANDOCERR_OS_ARG, n->child->line, n->child->pos,
"Os %s (%s)", n->child->string,
mdoc->meta.os_e == MANDOC_OS_OPENBSD ?
"OpenBSD" : "NetBSD");
@@ -2851,14 +2760,12 @@ out:
return;
if (strncmp(n->string, "$" "Mdocdate", 9)) {
if (mdoc->meta.os_e == MANDOC_OS_OPENBSD)
- mandoc_vmsg(MANDOCERR_MDOCDATE_MISSING,
- mdoc->parse, n->line, n->pos,
- "Dd %s (OpenBSD)", n->string);
+ mandoc_msg(MANDOCERR_MDOCDATE_MISSING, n->line,
+ n->pos, "Dd %s (OpenBSD)", n->string);
} else {
if (mdoc->meta.os_e == MANDOC_OS_NETBSD)
- mandoc_vmsg(MANDOCERR_MDOCDATE,
- mdoc->parse, n->line, n->pos,
- "Dd %s (NetBSD)", n->string);
+ mandoc_msg(MANDOCERR_MDOCDATE, n->line,
+ n->pos, "Dd %s (NetBSD)", n->string);
}
}
diff --git a/msec.c b/msec.c
index 9d41511696d0..9a52213d95e6 100644
--- a/msec.c
+++ b/msec.c
@@ -1,4 +1,4 @@
-/* $Id: msec.c,v 1.15 2015/10/06 18:32:19 schwarze Exp $ */
+/* $Id: msec.c,v 1.16 2018/12/14 01:18:26 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -18,6 +18,7 @@
#include <sys/types.h>
+#include <stdio.h>
#include <string.h>
#include "mandoc.h"
diff --git a/out.c b/out.c
index b2b643787ec1..363d04cf979d 100644
--- a/out.c
+++ b/out.c
@@ -1,7 +1,7 @@
-/* $Id: out.c,v 1.70 2017/06/27 18:25:02 schwarze Exp $ */
+/* $Id: out.c,v 1.77 2018/12/13 11:55:47 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011,2014,2015,2017,2018 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
@@ -20,21 +20,29 @@
#include <sys/types.h>
#include <assert.h>
+#include <ctype.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "mandoc_aux.h"
-#include "mandoc.h"
+#include "tbl.h"
#include "out.h"
-static void tblcalc_data(struct rofftbl *, struct roffcol *,
+struct tbl_colgroup {
+ struct tbl_colgroup *next;
+ size_t wanted;
+ int startcol;
+ int endcol;
+};
+
+static size_t tblcalc_data(struct rofftbl *, struct roffcol *,
const struct tbl_opts *, const struct tbl_dat *,
size_t);
-static void tblcalc_literal(struct rofftbl *, struct roffcol *,
+static size_t tblcalc_literal(struct rofftbl *, struct roffcol *,
const struct tbl_dat *, size_t);
-static void tblcalc_number(struct rofftbl *, struct roffcol *,
+static size_t tblcalc_number(struct rofftbl *, struct roffcol *,
const struct tbl_opts *, const struct tbl_dat *);
@@ -103,16 +111,18 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
* used for the actual width calculations.
*/
void
-tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
+tblcalc(struct rofftbl *tbl, const struct tbl_span *sp_first,
size_t offset, size_t rmargin)
{
struct roffsu su;
const struct tbl_opts *opts;
+ const struct tbl_span *sp;
const struct tbl_dat *dp;
struct roffcol *col;
- size_t ewidth, xwidth;
- int spans;
- int icol, maxcol, necol, nxcol, quirkcol;
+ struct tbl_colgroup *first_group, **gp, *g;
+ size_t *colwidth;
+ size_t ewidth, min1, min2, wanted, width, xwidth;
+ int done, icol, maxcol, necol, nxcol, quirkcol;
/*
* Allocate the master column specifiers. These will hold the
@@ -120,33 +130,34 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
* must be freed and nullified by the caller.
*/
- assert(NULL == tbl->cols);
- tbl->cols = mandoc_calloc((size_t)sp->opts->cols,
+ assert(tbl->cols == NULL);
+ tbl->cols = mandoc_calloc((size_t)sp_first->opts->cols,
sizeof(struct roffcol));
- opts = sp->opts;
+ opts = sp_first->opts;
- for (maxcol = -1; sp; sp = sp->next) {
- if (TBL_SPAN_DATA != sp->pos)
+ maxcol = -1;
+ first_group = NULL;
+ for (sp = sp_first; sp != NULL; sp = sp->next) {
+ if (sp->pos != TBL_SPAN_DATA)
continue;
- spans = 1;
+
/*
* Account for the data cells in the layout, matching it
* to data cells in the data section.
*/
- for (dp = sp->first; dp; dp = dp->next) {
- /* Do not used spanned cells in the calculation. */
- if (0 < --spans)
- continue;
- spans = dp->spans;
- if (1 < spans)
- continue;
+
+ gp = &first_group;
+ for (dp = sp->first; dp != NULL; dp = dp->next) {
icol = dp->layout->col;
- while (maxcol < icol)
+ while (icol > maxcol)
tbl->cols[++maxcol].spacing = SIZE_MAX;
col = tbl->cols + icol;
col->flags |= dp->layout->flags;
if (dp->layout->flags & TBL_CELL_WIGN)
continue;
+
+ /* Handle explicit width specifications. */
+
if (dp->layout->wstr != NULL &&
dp->layout->width == 0 &&
a2roffsu(dp->layout->wstr, &su, SCALE_EN)
@@ -159,15 +170,165 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
(col->spacing == SIZE_MAX ||
col->spacing < dp->layout->spacing))
col->spacing = dp->layout->spacing;
- tblcalc_data(tbl, col, opts, dp,
+
+ /*
+ * Calculate an automatic width.
+ * Except for spanning cells, apply it.
+ */
+
+ width = tblcalc_data(tbl,
+ dp->hspans == 0 ? col : NULL,
+ opts, dp,
dp->block == 0 ? 0 :
dp->layout->width ? dp->layout->width :
rmargin ? (rmargin + sp->opts->cols / 2)
/ (sp->opts->cols + 1) : 0);
+ if (dp->hspans == 0)
+ continue;
+
+ /*
+ * Build an ordered, singly linked list
+ * of all groups of columns joined by spans,
+ * recording the minimum width for each group.
+ */
+
+ while (*gp != NULL && ((*gp)->startcol < icol ||
+ (*gp)->endcol < icol + dp->hspans))
+ gp = &(*gp)->next;
+ if (*gp == NULL || (*gp)->startcol > icol ||
+ (*gp)->endcol > icol + dp->hspans) {
+ g = mandoc_malloc(sizeof(*g));
+ g->next = *gp;
+ g->wanted = width;
+ g->startcol = icol;
+ g->endcol = icol + dp->hspans;
+ *gp = g;
+ } else if ((*gp)->wanted < width)
+ (*gp)->wanted = width;
+ }
+ }
+
+ /*
+ * Column spacings are needed for span width calculations,
+ * so set the default values now.
+ */
+
+ for (icol = 0; icol <= maxcol; icol++)
+ if (tbl->cols[icol].spacing == SIZE_MAX || icol == maxcol)
+ tbl->cols[icol].spacing = 3;
+
+ /*
+ * Replace the minimum widths with the missing widths,
+ * and dismiss groups that are already wide enough.
+ */
+
+ gp = &first_group;
+ while ((g = *gp) != NULL) {
+ done = 0;
+ for (icol = g->startcol; icol <= g->endcol; icol++) {
+ width = tbl->cols[icol].width;
+ if (icol < g->endcol)
+ width += tbl->cols[icol].spacing;
+ if (g->wanted <= width) {
+ done = 1;
+ break;
+ } else
+ (*gp)->wanted -= width;
+ }
+ if (done) {
+ *gp = g->next;
+ free(g);
+ } else
+ gp = &(*gp)->next;
+ }
+
+ colwidth = mandoc_reallocarray(NULL, maxcol + 1, sizeof(*colwidth));
+ while (first_group != NULL) {
+
+ /*
+ * Rebuild the array of the widths of all columns
+ * participating in spans that require expansion.
+ */
+
+ for (icol = 0; icol <= maxcol; icol++)
+ colwidth[icol] = SIZE_MAX;
+ for (g = first_group; g != NULL; g = g->next)
+ for (icol = g->startcol; icol <= g->endcol; icol++)
+ colwidth[icol] = tbl->cols[icol].width;
+
+ /*
+ * Find the smallest and second smallest column width
+ * among the columns which may need expamsion.
+ */
+
+ min1 = min2 = SIZE_MAX;
+ for (icol = 0; icol <= maxcol; icol++) {
+ if (min1 > colwidth[icol]) {
+ min2 = min1;
+ min1 = colwidth[icol];
+ } else if (min1 < colwidth[icol] &&
+ min2 > colwidth[icol])
+ min2 = colwidth[icol];
+ }
+
+ /*
+ * Find the minimum wanted width
+ * for any one of the narrowest columns,
+ * and mark the columns wanting that width.
+ */
+
+ wanted = min2;
+ for (g = first_group; g != NULL; g = g->next) {
+ necol = 0;
+ for (icol = g->startcol; icol <= g->endcol; icol++)
+ if (tbl->cols[icol].width == min1)
+ necol++;
+ if (necol == 0)
+ continue;
+ width = min1 + (g->wanted - 1) / necol + 1;
+ if (width > min2)
+ width = min2;
+ if (wanted > width)
+ wanted = width;
+ for (icol = g->startcol; icol <= g->endcol; icol++)
+ if (colwidth[icol] == min1 ||
+ (colwidth[icol] < min2 &&
+ colwidth[icol] > width))
+ colwidth[icol] = width;
+ }
+
+ /* Record the effect of the widening on the group list. */
+
+ gp = &first_group;
+ while ((g = *gp) != NULL) {
+ done = 0;
+ for (icol = g->startcol; icol <= g->endcol; icol++) {
+ if (colwidth[icol] != wanted ||
+ tbl->cols[icol].width == wanted)
+ continue;
+ if (g->wanted <= wanted - min1) {
+ done = 1;
+ break;
+ }
+ g->wanted -= wanted - min1;
+ }
+ if (done) {
+ *gp = g->next;
+ free(g);
+ } else
+ gp = &(*gp)->next;
}
+
+ /* Record the effect of the widening on the columns. */
+
+ for (icol = 0; icol <= maxcol; icol++)
+ if (colwidth[icol] == wanted)
+ tbl->cols[icol].width = wanted;
}
+ free(colwidth);
/*
+ * Align numbers with text.
* Count columns to equalize and columns to maximize.
* Find maximum width of the columns to equalize.
* Find total width of the columns *not* to maximize.
@@ -177,8 +338,10 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
ewidth = xwidth = 0;
for (icol = 0; icol <= maxcol; icol++) {
col = tbl->cols + icol;
- if (col->spacing == SIZE_MAX || icol == maxcol)
- col->spacing = 3;
+ if (col->width > col->nwidth)
+ col->decimal += (col->width - col->nwidth) / 2;
+ else
+ col->width = col->nwidth;
if (col->flags & TBL_CELL_EQUAL) {
necol++;
if (ewidth < col->width)
@@ -251,7 +414,7 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
}
}
-static void
+static size_t
tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
const struct tbl_opts *opts, const struct tbl_dat *dp, size_t mw)
{
@@ -263,26 +426,24 @@ tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
case TBL_CELL_HORIZ:
case TBL_CELL_DHORIZ:
sz = (*tbl->len)(1, tbl->arg);
- if (col->width < sz)
+ if (col != NULL && col->width < sz)
col->width = sz;
- break;
+ return sz;
case TBL_CELL_LONG:
case TBL_CELL_CENTRE:
case TBL_CELL_LEFT:
case TBL_CELL_RIGHT:
- tblcalc_literal(tbl, col, dp, mw);
- break;
+ return tblcalc_literal(tbl, col, dp, mw);
case TBL_CELL_NUMBER:
- tblcalc_number(tbl, col, opts, dp);
- break;
+ return tblcalc_number(tbl, col, opts, dp);
case TBL_CELL_DOWN:
- break;
+ return 0;
default:
abort();
}
}
-static void
+static size_t
tblcalc_literal(struct rofftbl *tbl, struct roffcol *col,
const struct tbl_dat *dp, size_t mw)
{
@@ -291,11 +452,12 @@ tblcalc_literal(struct rofftbl *tbl, struct roffcol *col,
char *end; /* End of the current line. */
size_t lsz; /* Length of the current line. */
size_t wsz; /* Length of the current word. */
+ size_t msz; /* Length of the longest line. */
if (dp->string == NULL || *dp->string == '\0')
- return;
+ return 0;
str = mw ? mandoc_strdup(dp->string) : dp->string;
- lsz = 0;
+ msz = lsz = 0;
for (beg = str; beg != NULL && *beg != '\0'; beg = end) {
end = mw ? strchr(beg, ' ') : NULL;
if (end != NULL) {
@@ -308,62 +470,84 @@ tblcalc_literal(struct rofftbl *tbl, struct roffcol *col,
lsz += 1 + wsz;
else
lsz = wsz;
- if (col->width < lsz)
- col->width = lsz;
+ if (msz < lsz)
+ msz = lsz;
}
if (mw)
free((void *)str);
+ if (col != NULL && col->width < msz)
+ col->width = msz;
+ return msz;
}
-static void
+static size_t
tblcalc_number(struct rofftbl *tbl, struct roffcol *col,
const struct tbl_opts *opts, const struct tbl_dat *dp)
{
- int i;
- size_t sz, psz, ssz, d;
- const char *str;
- char *cp;
+ const char *cp, *lastdigit, *lastpoint;
+ size_t intsz, totsz;
char buf[2];
+ if (dp->string == NULL || *dp->string == '\0')
+ return 0;
+
+ totsz = (*tbl->slen)(dp->string, tbl->arg);
+ if (col == NULL)
+ return totsz;
+
/*
- * First calculate number width and decimal place (last + 1 for
- * non-decimal numbers). If the stored decimal is subsequent to
- * ours, make our size longer by that difference
- * (right-"shifting"); similarly, if ours is subsequent the
- * stored, then extend the stored size by the difference.
- * Finally, re-assign the stored values.
+ * Find the last digit and
+ * the last decimal point that is adjacent to a digit.
+ * The alignment indicator "\&" overrides everything.
*/
- str = dp->string ? dp->string : "";
- sz = (*tbl->slen)(str, tbl->arg);
+ lastdigit = lastpoint = NULL;
+ for (cp = dp->string; cp[0] != '\0'; cp++) {
+ if (cp[0] == '\\' && cp[1] == '&') {
+ lastdigit = lastpoint = cp;
+ break;
+ } else if (cp[0] == opts->decimal &&
+ (isdigit((unsigned char)cp[1]) ||
+ (cp > dp->string && isdigit((unsigned char)cp[-1]))))
+ lastpoint = cp;
+ else if (isdigit((unsigned char)cp[0]))
+ lastdigit = cp;
+ }
- /* FIXME: TBL_DATA_HORIZ et al.? */
+ /* Not a number, treat as a literal string. */
- buf[0] = opts->decimal;
- buf[1] = '\0';
+ if (lastdigit == NULL) {
+ if (col != NULL && col->width < totsz)
+ col->width = totsz;
+ return totsz;
+ }
- psz = (*tbl->slen)(buf, tbl->arg);
+ /* Measure the width of the integer part. */
- if (NULL != (cp = strrchr(str, opts->decimal))) {
- buf[1] = '\0';
- for (ssz = 0, i = 0; cp != &str[i]; i++) {
- buf[0] = str[i];
- ssz += (*tbl->slen)(buf, tbl->arg);
- }
- d = ssz + psz;
- } else
- d = sz + psz;
+ if (lastpoint == NULL)
+ lastpoint = lastdigit + 1;
+ intsz = 0;
+ buf[1] = '\0';
+ for (cp = dp->string; cp < lastpoint; cp++) {
+ buf[0] = cp[0];
+ intsz += (*tbl->slen)(buf, tbl->arg);
+ }
- /* Adjust the settings for this column. */
+ /*
+ * If this number has more integer digits than all numbers
+ * seen on earlier lines, shift them all to the right.
+ * If it has fewer, shift this number to the right.
+ */
- if (col->decimal > d) {
- sz += col->decimal - d;
- d = col->decimal;
+ if (intsz > col->decimal) {
+ col->nwidth += intsz - col->decimal;
+ col->decimal = intsz;
} else
- col->width += d - col->decimal;
+ totsz += col->decimal - intsz;
+
+ /* Update the maximum total width seen so far. */
- if (sz > col->width)
- col->width = sz;
- if (d > col->decimal)
- col->decimal = d;
+ if (totsz > col->nwidth)
+ col->nwidth = totsz;
+ return totsz;
}
diff --git a/out.h b/out.h
index 9f0a541d5dfd..dec6a8f87324 100644
--- a/out.h
+++ b/out.h
@@ -1,7 +1,7 @@
-/* $Id: out.h,v 1.32 2018/06/25 16:54:59 schwarze Exp $ */
+/* $Id: out.h,v 1.33 2018/08/18 20:18:14 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2017, 2018 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
@@ -32,6 +32,7 @@ enum roffscale {
struct roffcol {
size_t width; /* width of cell */
+ size_t nwidth; /* max. width of number in cell */
size_t decimal; /* decimal position in cell */
size_t spacing; /* spacing after the column */
int flags; /* layout flags, see tbl_cell */
diff --git a/preconv.c b/preconv.c
index 08f8df86a61b..9ed627d4467d 100644
--- a/preconv.c
+++ b/preconv.c
@@ -1,4 +1,4 @@
-/* $Id: preconv.c,v 1.16 2017/02/18 13:43:52 schwarze Exp $ */
+/* $Id: preconv.c,v 1.17 2018/12/13 11:55:47 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -22,7 +22,10 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>
+
#include "mandoc.h"
+#include "roff.h"
+#include "mandoc_parse.h"
#include "libmandoc.h"
int
diff --git a/read.c b/read.c
index 0a583445f2cd..a3a1f982c01c 100644
--- a/read.c
+++ b/read.c
@@ -1,7 +1,7 @@
-/* $Id: read.c,v 1.196 2018/07/28 18:34:15 schwarze Exp $ */
+/* $Id: read.c,v 1.211 2019/01/11 17:04:44 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -38,21 +38,19 @@
#include "roff.h"
#include "mdoc.h"
#include "man.h"
+#include "mandoc_parse.h"
#include "libmandoc.h"
+#include "roff_int.h"
#define REPARSE_LIMIT 1000
struct mparse {
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 */
- struct buf *secondary; /* preprocessed copy of input */
+ struct buf *secondary; /* copy of top level input */
+ struct buf *loop; /* open .while request line */
const char *os_s; /* default operating system */
- mandocmsg mmsg; /* warning/error message handler */
- enum mandoclevel file_status; /* status of current parse */
- enum mandocerr mmin; /* ignore messages below this */
int options; /* parser options */
int gzip; /* current input file is gzipped */
int filenc; /* encoding of the current file */
@@ -61,220 +59,11 @@ struct mparse {
};
static void choose_parser(struct mparse *);
+static void free_buf_list(struct buf *);
static void resize_buf(struct buf *, size_t);
static int mparse_buf_r(struct mparse *, struct buf, size_t, int);
-static int read_whole_file(struct mparse *, const char *, int,
- struct buf *, int *);
+static int read_whole_file(struct mparse *, int, struct buf *, int *);
static void mparse_end(struct mparse *);
-static void mparse_parse_buffer(struct mparse *, struct buf,
- const char *);
-
-static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
- MANDOCERR_OK,
- MANDOCERR_OK,
- MANDOCERR_WARNING,
- MANDOCERR_ERROR,
- MANDOCERR_UNSUPP,
- MANDOCERR_MAX,
- MANDOCERR_MAX
-};
-
-static const char * const mandocerrs[MANDOCERR_MAX] = {
- "ok",
-
- "base system convention",
-
- "Mdocdate found",
- "Mdocdate missing",
- "unknown architecture",
- "operating system explicitly specified",
- "RCS id missing",
- "referenced manual not found",
-
- "generic style suggestion",
-
- "legacy man(7) date format",
- "normalizing date format to",
- "lower case character in document title",
- "duplicate RCS id",
- "possible typo in section name",
- "unterminated quoted argument",
- "useless macro",
- "consider using OS macro",
- "errnos out of order",
- "duplicate errno",
- "trailing delimiter",
- "no blank before trailing delimiter",
- "fill mode already enabled, skipping",
- "fill mode already disabled, skipping",
- "verbatim \"--\", maybe consider using \\(em",
- "function name without markup",
- "whitespace at end of input line",
- "bad comment style",
-
- "generic warning",
-
- /* related to the prologue */
- "missing manual title, using UNTITLED",
- "missing manual title, using \"\"",
- "missing manual section, using \"\"",
- "unknown manual section",
- "missing date, using today's date",
- "cannot parse date, using it verbatim",
- "date in the future, using it anyway",
- "missing Os macro, using \"\"",
- "late prologue macro",
- "prologue macros out of order",
-
- /* related to document structure */
- ".so is fragile, better use ln(1)",
- "no document body",
- "content before first section header",
- "first section is not \"NAME\"",
- "NAME section without Nm before Nd",
- "NAME section without description",
- "description not at the end of NAME",
- "bad NAME section content",
- "missing comma before name",
- "missing description line, using \"\"",
- "description line outside NAME section",
- "sections out of conventional order",
- "duplicate section title",
- "unexpected section",
- "cross reference to self",
- "unusual Xr order",
- "unusual Xr punctuation",
- "AUTHORS section without An macro",
-
- /* related to macros and nesting */
- "obsolete macro",
- "macro neither callable nor escaped",
- "skipping paragraph macro",
- "moving paragraph macro out of list",
- "skipping no-space macro",
- "blocks badly nested",
- "nested displays are not portable",
- "moving content out of list",
- "first macro on line",
- "line scope broken",
- "skipping blank line in line scope",
-
- /* related to missing macro arguments */
- "skipping empty request",
- "conditional request controls empty scope",
- "skipping empty macro",
- "empty block",
- "empty argument, using 0n",
- "missing display type, using -ragged",
- "list type is not the first argument",
- "missing -width in -tag list, using 6n",
- "missing utility name, using \"\"",
- "missing function name, using \"\"",
- "empty head in list item",
- "empty list item",
- "missing argument, using next line",
- "missing font type, using \\fR",
- "unknown font type, using \\fR",
- "nothing follows prefix",
- "empty reference block",
- "missing section argument",
- "missing -std argument, adding it",
- "missing option string, using \"\"",
- "missing resource identifier, using \"\"",
- "missing eqn box, using \"\"",
-
- /* related to bad macro arguments */
- "duplicate argument",
- "skipping duplicate argument",
- "skipping duplicate display type",
- "skipping duplicate list type",
- "skipping -width argument",
- "wrong number of cells",
- "unknown AT&T UNIX version",
- "comma in function argument",
- "parenthesis in function name",
- "unknown library name",
- "invalid content in Rs block",
- "invalid Boolean argument",
- "unknown font, skipping request",
- "odd number of characters in request",
-
- /* related to plain text */
- "blank line in fill mode, using .sp",
- "tab in filled text",
- "new sentence, new line",
- "invalid escape sequence",
- "undefined string, using \"\"",
-
- /* related to tables */
- "tbl line starts with span",
- "tbl column starts with span",
- "skipping vertical bar in tbl layout",
-
- "generic error",
-
- /* related to tables */
- "non-alphabetic character in tbl options",
- "skipping unknown tbl option",
- "missing tbl option argument",
- "wrong tbl option argument size",
- "empty tbl layout",
- "invalid character in tbl layout",
- "unmatched parenthesis in tbl layout",
- "tbl without any data cells",
- "ignoring data in spanned tbl cell",
- "ignoring extra tbl data cells",
- "data block open at end of tbl",
-
- /* related to document structure and macros */
- NULL,
- "duplicate prologue macro",
- "skipping late title macro",
- "input stack limit exceeded, infinite loop?",
- "skipping bad character",
- "skipping unknown macro",
- "skipping insecure request",
- "skipping item outside list",
- "skipping column outside column list",
- "skipping end of block that is not open",
- "fewer RS blocks open, skipping",
- "inserting missing end of block",
- "appending missing end of block",
-
- /* related to request and macro arguments */
- "escaped character not allowed in a name",
- "NOT IMPLEMENTED: Bd -file",
- "skipping display without arguments",
- "missing list type, using -item",
- "argument is not numeric, using 1",
- "missing manual name, using \"\"",
- "uname(3) system call failed, using UNKNOWN",
- "unknown standard specifier",
- "skipping request without numeric argument",
- "NOT IMPLEMENTED: .so with absolute path or \"..\"",
- ".so request failed",
- "skipping all arguments",
- "skipping excess arguments",
- "divide by zero",
-
- "unsupported feature",
- "input too large",
- "unsupported control character",
- "unsupported roff request",
- "eqn delim option in tbl",
- "unsupported tbl layout modifier",
- "ignoring macro in table",
-};
-
-static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
- "SUCCESS",
- "STYLE",
- "WARNING",
- "ERROR",
- "UNSUPP",
- "BADARG",
- "SYSERR"
-};
static void
@@ -286,6 +75,19 @@ resize_buf(struct buf *buf, size_t initial)
}
static void
+free_buf_list(struct buf *buf)
+{
+ struct buf *tmp;
+
+ while (buf != NULL) {
+ tmp = buf;
+ buf = tmp->next;
+ free(tmp->buf);
+ free(tmp);
+ }
+}
+
+static void
choose_parser(struct mparse *curp)
{
char *cp, *ep;
@@ -320,15 +122,15 @@ choose_parser(struct mparse *curp)
}
if (format == MPARSE_MDOC) {
- curp->man->macroset = MACROSET_MDOC;
+ curp->man->meta.macroset = MACROSET_MDOC;
if (curp->man->mdocmac == NULL)
curp->man->mdocmac = roffhash_alloc(MDOC_Dd, MDOC_MAX);
} else {
- curp->man->macroset = MACROSET_MAN;
+ curp->man->meta.macroset = MACROSET_MAN;
if (curp->man->manmac == NULL)
curp->man->manmac = roffhash_alloc(MAN_TH, MAN_MAX);
}
- curp->man->first->tok = TOKEN_NONE;
+ curp->man->meta.first->tok = TOKEN_NONE;
}
/*
@@ -342,24 +144,26 @@ static int
mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
{
struct buf ln;
- const char *save_file;
+ struct buf *firstln, *lastln, *thisln, *loop;
char *cp;
size_t pos; /* byte number in the ln buffer */
- enum rofferr rr;
+ int line_result, result;
int of;
int lnn; /* line number in the real file */
int fd;
+ int inloop; /* Saw .while on this level. */
unsigned char c;
- memset(&ln, 0, sizeof(ln));
-
+ ln.sz = 256;
+ ln.buf = mandoc_malloc(ln.sz);
+ ln.next = NULL;
+ firstln = loop = NULL;
lnn = curp->line;
pos = 0;
+ inloop = 0;
+ result = ROFF_CONT;
- while (i < blk.sz) {
- if (0 == pos && '\0' == blk.buf[i])
- break;
-
+ while (i < blk.sz && (blk.buf[i] != '\0' || pos != 0)) {
if (start) {
curp->line = lnn;
curp->reparse_count = 0;
@@ -389,10 +193,10 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
/*
* Make sure we have space for the worst
- * case of 11 bytes: "\\[u10ffff]\0"
+ * case of 12 bytes: "\\[u10ffff]\n\0"
*/
- if (pos + 11 > ln.sz)
+ if (pos + 12 > ln.sz)
resize_buf(&ln, 256);
/*
@@ -403,7 +207,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
if (c & 0x80) {
if ( ! (curp->filenc && preconv_encode(
&blk, &i, &ln, &pos, &curp->filenc))) {
- mandoc_vmsg(MANDOCERR_CHAR_BAD, curp,
+ mandoc_msg(MANDOCERR_CHAR_BAD,
curp->line, pos, "0x%x", c);
ln.buf[pos++] = '?';
i++;
@@ -416,10 +220,10 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
*/
if (c == 0x7f || (c < 0x20 && c != 0x09)) {
- mandoc_vmsg(c == 0x00 || c == 0x04 ||
+ mandoc_msg(c == 0x00 || c == 0x04 ||
c > 0x0a ? MANDOCERR_CHAR_BAD :
MANDOCERR_CHAR_UNSUPP,
- curp, curp->line, pos, "0x%x", c);
+ curp->line, pos, "0x%x", c);
i++;
if (c != '\r')
ln.buf[pos++] = '?';
@@ -428,13 +232,32 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
ln.buf[pos++] = blk.buf[i++];
}
+ ln.buf[pos] = '\0';
- if (pos + 1 >= ln.sz)
- resize_buf(&ln, 256);
+ /*
+ * Maintain a lookaside buffer of all lines.
+ * parsed from this input source.
+ */
+
+ thisln = mandoc_malloc(sizeof(*thisln));
+ thisln->buf = mandoc_strdup(ln.buf);
+ thisln->sz = strlen(ln.buf) + 1;
+ thisln->next = NULL;
+ if (firstln == NULL) {
+ firstln = lastln = thisln;
+ if (curp->secondary == NULL)
+ curp->secondary = firstln;
+ } else {
+ lastln->next = thisln;
+ lastln = thisln;
+ }
- if (i == blk.sz || blk.buf[i] == '\0')
+ /* XXX Ugly hack to mark the end of the input. */
+
+ if (i == blk.sz || blk.buf[i] == '\0') {
ln.buf[pos++] = '\n';
- ln.buf[pos] = '\0';
+ ln.buf[pos] = '\0';
+ }
/*
* A significant amount of complexity is contained by
@@ -446,74 +269,112 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
*/
of = 0;
+rerun:
+ line_result = roff_parseln(curp->roff, curp->line, &ln, &of);
- /*
- * Maintain a lookaside buffer of all parsed lines. We
- * only do this if mparse_keep() has been invoked (the
- * buffer may be accessed with mparse_getkeep()).
- */
+ /* Process options. */
+
+ if (line_result & ROFF_APPEND)
+ assert(line_result == (ROFF_IGN | ROFF_APPEND));
- if (curp->secondary) {
- curp->secondary->buf = mandoc_realloc(
- curp->secondary->buf,
- curp->secondary->sz + pos + 2);
- memcpy(curp->secondary->buf +
- curp->secondary->sz,
- ln.buf, pos);
- curp->secondary->sz += pos;
- curp->secondary->buf
- [curp->secondary->sz] = '\n';
- curp->secondary->sz++;
- curp->secondary->buf
- [curp->secondary->sz] = '\0';
+ if (line_result & ROFF_USERCALL)
+ assert((line_result & ROFF_MASK) == ROFF_REPARSE);
+
+ if (line_result & ROFF_USERRET) {
+ assert(line_result == (ROFF_IGN | ROFF_USERRET));
+ if (start == 0) {
+ /* Return from the current macro. */
+ result = ROFF_USERRET;
+ goto out;
+ }
}
-rerun:
- rr = roff_parseln(curp->roff, curp->line, &ln, &of);
- switch (rr) {
- case ROFF_REPARSE:
- if (++curp->reparse_count > REPARSE_LIMIT)
- mandoc_msg(MANDOCERR_ROFFLOOP, curp,
+ switch (line_result & ROFF_LOOPMASK) {
+ case ROFF_IGN:
+ break;
+ case ROFF_WHILE:
+ if (curp->loop != NULL) {
+ if (loop == curp->loop)
+ break;
+ mandoc_msg(MANDOCERR_WHILE_NEST,
curp->line, pos, NULL);
- else if (mparse_buf_r(curp, ln, of, 0) == 1 ||
- start == 1) {
- pos = 0;
- continue;
}
- free(ln.buf);
- return 0;
- case ROFF_APPEND:
- pos = strlen(ln.buf);
- continue;
+ curp->loop = thisln;
+ loop = NULL;
+ inloop = 1;
+ break;
+ case ROFF_LOOPCONT:
+ case ROFF_LOOPEXIT:
+ if (curp->loop == NULL) {
+ mandoc_msg(MANDOCERR_WHILE_FAIL,
+ curp->line, pos, NULL);
+ break;
+ }
+ if (inloop == 0) {
+ mandoc_msg(MANDOCERR_WHILE_INTO,
+ curp->line, pos, NULL);
+ curp->loop = loop = NULL;
+ break;
+ }
+ if (line_result & ROFF_LOOPCONT)
+ loop = curp->loop;
+ else {
+ curp->loop = loop = NULL;
+ inloop = 0;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ /* Process the main instruction from the roff parser. */
+
+ switch (line_result & ROFF_MASK) {
+ case ROFF_IGN:
+ break;
+ case ROFF_CONT:
+ if (curp->man->meta.macroset == MACROSET_NONE)
+ choose_parser(curp);
+ if ((curp->man->meta.macroset == MACROSET_MDOC ?
+ mdoc_parseln(curp->man, curp->line, ln.buf, of) :
+ man_parseln(curp->man, curp->line, ln.buf, of)
+ ) == 2)
+ goto out;
+ break;
case ROFF_RERUN:
goto rerun;
- case ROFF_IGN:
- pos = 0;
- continue;
+ case ROFF_REPARSE:
+ if (++curp->reparse_count > REPARSE_LIMIT) {
+ /* Abort and return to the top level. */
+ result = ROFF_IGN;
+ mandoc_msg(MANDOCERR_ROFFLOOP,
+ curp->line, pos, NULL);
+ goto out;
+ }
+ result = mparse_buf_r(curp, ln, of, 0);
+ if (line_result & ROFF_USERCALL) {
+ roff_userret(curp->roff);
+ /* Continue normally. */
+ if (result & ROFF_USERRET)
+ result = ROFF_CONT;
+ }
+ if (start == 0 && result != ROFF_CONT)
+ goto out;
+ break;
case ROFF_SO:
if ( ! (curp->options & MPARSE_SO) &&
(i >= blk.sz || blk.buf[i] == '\0')) {
- curp->sodest = mandoc_strdup(ln.buf + of);
- free(ln.buf);
- return 1;
+ curp->man->meta.sodest =
+ mandoc_strdup(ln.buf + of);
+ goto out;
}
- /*
- * We remove `so' clauses from our lookaside
- * buffer because we're going to descend into
- * the file recursively.
- */
- if (curp->secondary)
- curp->secondary->sz -= pos + 1;
- save_file = curp->file;
if ((fd = mparse_open(curp, ln.buf + of)) != -1) {
mparse_readfd(curp, fd, ln.buf + of);
close(fd);
- curp->file = save_file;
} else {
- curp->file = save_file;
- mandoc_vmsg(MANDOCERR_SO_FAIL,
- curp, curp->line, pos,
- ".so %s", ln.buf + of);
+ mandoc_msg(MANDOCERR_SO_FAIL,
+ curp->line, of, ".so %s: %s",
+ ln.buf + of, strerror(errno));
ln.sz = mandoc_asprintf(&cp,
".sp\nSee the file %s.\n.sp",
ln.buf + of);
@@ -522,37 +383,44 @@ rerun:
of = 0;
mparse_buf_r(curp, ln, of, 0);
}
- pos = 0;
- continue;
- default:
break;
+ default:
+ abort();
}
- if (curp->man->macroset == MACROSET_NONE)
- choose_parser(curp);
-
- if ((curp->man->macroset == MACROSET_MDOC ?
- mdoc_parseln(curp->man, curp->line, ln.buf, of) :
- man_parseln(curp->man, curp->line, ln.buf, of)) == 2)
- break;
-
- /* Temporary buffers typically are not full. */
-
- if (0 == start && '\0' == blk.buf[i])
- break;
-
/* Start the next input line. */
- pos = 0;
- }
+ if (loop != NULL &&
+ (line_result & ROFF_LOOPMASK) == ROFF_IGN)
+ loop = loop->next;
+
+ if (loop != NULL) {
+ if ((line_result & ROFF_APPEND) == 0)
+ *ln.buf = '\0';
+ if (ln.sz < loop->sz)
+ resize_buf(&ln, loop->sz);
+ (void)strlcat(ln.buf, loop->buf, ln.sz);
+ of = 0;
+ goto rerun;
+ }
+ pos = (line_result & ROFF_APPEND) ? strlen(ln.buf) : 0;
+ }
+out:
+ if (inloop) {
+ if (result != ROFF_USERRET)
+ mandoc_msg(MANDOCERR_WHILE_OUTOF,
+ curp->line, pos, NULL);
+ curp->loop = NULL;
+ }
free(ln.buf);
- return 1;
+ if (firstln != curp->secondary)
+ free_buf_list(firstln);
+ return result;
}
static int
-read_whole_file(struct mparse *curp, const char *file, int fd,
- struct buf *fb, int *with_mmap)
+read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
{
struct stat st;
gzFile gz;
@@ -561,7 +429,7 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
int gzerrnum, retval;
if (fstat(fd, &st) == -1) {
- mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
+ mandoc_msg(MANDOCERR_FILE, 0, 0,
"fstat: %s", strerror(errno));
return 0;
}
@@ -575,7 +443,7 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
if (curp->gzip == 0 && S_ISREG(st.st_mode)) {
if (st.st_size > 0x7fffffff) {
- mandoc_msg(MANDOCERR_TOOLARGE, curp, 0, 0, NULL);
+ mandoc_msg(MANDOCERR_TOOLARGE, 0, 0, NULL);
return 0;
}
*with_mmap = 1;
@@ -594,12 +462,12 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
* which this function must not do.
*/
if ((fd = dup(fd)) == -1) {
- mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
+ mandoc_msg(MANDOCERR_FILE, 0, 0,
"dup: %s", strerror(errno));
return 0;
}
if ((gz = gzdopen(fd, "rb")) == NULL) {
- mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
+ mandoc_msg(MANDOCERR_FILE, 0, 0,
"gzdopen: %s", strerror(errno));
close(fd);
return 0;
@@ -620,8 +488,7 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
for (;;) {
if (off == fb->sz) {
if (fb->sz == (1U << 31)) {
- mandoc_msg(MANDOCERR_TOOLARGE, curp,
- 0, 0, NULL);
+ mandoc_msg(MANDOCERR_TOOLARGE, 0, 0, NULL);
break;
}
resize_buf(fb, 65536);
@@ -637,7 +504,7 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
if (ssz == -1) {
if (curp->gzip)
(void)gzerror(gz, &gzerrnum);
- mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, "read: %s",
+ mandoc_msg(MANDOCERR_FILE, 0, 0, "read: %s",
curp->gzip && gzerrnum != Z_ERRNO ?
zError(gzerrnum) : strerror(errno));
break;
@@ -646,7 +513,7 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
}
if (curp->gzip && (gzerrnum = gzclose(gz)) != Z_OK)
- mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, "gzclose: %s",
+ mandoc_msg(MANDOCERR_FILE, 0, 0, "gzclose: %s",
gzerrnum == Z_ERRNO ? strerror(errno) :
zError(gzerrnum));
if (retval == 0) {
@@ -659,35 +526,51 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
static void
mparse_end(struct mparse *curp)
{
- if (curp->man->macroset == MACROSET_NONE)
- curp->man->macroset = MACROSET_MAN;
- if (curp->man->macroset == MACROSET_MDOC)
+ if (curp->man->meta.macroset == MACROSET_NONE)
+ curp->man->meta.macroset = MACROSET_MAN;
+ if (curp->man->meta.macroset == MACROSET_MDOC)
mdoc_endparse(curp->man);
else
man_endparse(curp->man);
roff_endparse(curp->roff);
}
-static void
-mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
+/*
+ * Read the whole file into memory and call the parsers.
+ * Called recursively when an .so request is encountered.
+ */
+void
+mparse_readfd(struct mparse *curp, int fd, const char *filename)
{
- struct buf *svprimary;
- const char *svfile;
- size_t offset;
static int recursion_depth;
- if (64 < recursion_depth) {
- mandoc_msg(MANDOCERR_ROFFLOOP, curp, curp->line, 0, NULL);
+ struct buf blk;
+ struct buf *save_primary;
+ const char *save_filename;
+ size_t offset;
+ int save_filenc, save_lineno;
+ int with_mmap;
+
+ if (recursion_depth > 64) {
+ mandoc_msg(MANDOCERR_ROFFLOOP, curp->line, 0, NULL);
return;
}
+ if (read_whole_file(curp, fd, &blk, &with_mmap) == 0)
+ return;
+
+ /*
+ * Save some properties of the parent file.
+ */
+
+ save_primary = curp->primary;
+ save_filenc = curp->filenc;
+ save_lineno = curp->line;
+ save_filename = mandoc_msg_getinfilename();
- /* Line number is per-file. */
- svfile = curp->file;
- curp->file = file;
- svprimary = curp->primary;
curp->primary = &blk;
+ curp->filenc = curp->options & (MPARSE_UTF8 | MPARSE_LATIN1);
curp->line = 1;
- recursion_depth++;
+ mandoc_msg_setinfilename(filename);
/* Skip an UTF-8 byte order mark. */
if (curp->filenc & MPARSE_UTF8 && blk.sz > 2 &&
@@ -699,60 +582,33 @@ mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
} else
offset = 0;
+ recursion_depth++;
mparse_buf_r(curp, blk, offset, 1);
-
if (--recursion_depth == 0)
mparse_end(curp);
- curp->primary = svprimary;
- curp->file = svfile;
-}
-
-enum mandoclevel
-mparse_readmem(struct mparse *curp, void *buf, size_t len,
- const char *file)
-{
- struct buf blk;
-
- blk.buf = buf;
- blk.sz = len;
+ /*
+ * Clean up and restore saved parent properties.
+ */
- mparse_parse_buffer(curp, blk, file);
- return curp->file_status;
-}
+ if (with_mmap)
+ munmap(blk.buf, blk.sz);
+ else
+ free(blk.buf);
-/*
- * Read the whole file into memory and call the parsers.
- * Called recursively when an .so request is encountered.
- */
-enum mandoclevel
-mparse_readfd(struct mparse *curp, int fd, const char *file)
-{
- struct buf blk;
- int with_mmap;
- int save_filenc;<